<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[174477] trunk/Websites/perf.webkit.org</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/174477">174477</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2014-10-08 13:40:18 -0700 (Wed, 08 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add v2 UI for the perf dashboard
https://bugs.webkit.org/show_bug.cgi?id=137537

Rubber-stamped by Andreas Kling.

* public/v2: Added.
* public/v2/app.css: Added.
* public/v2/app.js: Added.
* public/v2/chart-pane.css: Added.
* public/v2/data.js: Added.
* public/v2/index.html: Added.
* public/v2/js: Added.
* public/v2/js/d3: Added.
* public/v2/js/d3/LICENSE: Added.
* public/v2/js/d3/d3.js: Added.
* public/v2/js/d3/d3.min.js: Added.
* public/v2/js/ember-data.js: Added.
* public/v2/js/ember.js: Added.
* public/v2/js/handlebars.js: Added.
* public/v2/js/jquery.min.js: Added.
* public/v2/js/statistics.js: Added.
* public/v2/manifest.js: Added.
* public/v2/popup.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgChangeLog">trunk/Websites/perf.webkit.org/ChangeLog</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/Websites/perf.webkit.org/public/v2/</li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2appcss">trunk/Websites/perf.webkit.org/public/v2/app.css</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2appjs">trunk/Websites/perf.webkit.org/public/v2/app.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2chartpanecss">trunk/Websites/perf.webkit.org/public/v2/chart-pane.css</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2datajs">trunk/Websites/perf.webkit.org/public/v2/data.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2indexhtml">trunk/Websites/perf.webkit.org/public/v2/index.html</a></li>
<li>trunk/Websites/perf.webkit.org/public/v2/js/</li>
<li>trunk/Websites/perf.webkit.org/public/v2/js/d3/</li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsd3LICENSE">trunk/Websites/perf.webkit.org/public/v2/js/d3/LICENSE</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsd3d3js">trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsd3d3minjs">trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.min.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsemberdatajs">trunk/Websites/perf.webkit.org/public/v2/js/ember-data.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsemberjs">trunk/Websites/perf.webkit.org/public/v2/js/ember.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jshandlebarsjs">trunk/Websites/perf.webkit.org/public/v2/js/handlebars.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsjqueryminjs">trunk/Websites/perf.webkit.org/public/v2/js/jquery.min.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2jsstatisticsjs">trunk/Websites/perf.webkit.org/public/v2/js/statistics.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2manifestjs">trunk/Websites/perf.webkit.org/public/v2/manifest.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgpublicv2popupjs">trunk/Websites/perf.webkit.org/public/v2/popup.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebsitesperfwebkitorgChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/ChangeLog (174476 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ChangeLog        2014-10-08 20:30:04 UTC (rev 174476)
+++ trunk/Websites/perf.webkit.org/ChangeLog        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -1,5 +1,31 @@
</span><span class="cx"> 2014-10-08  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        Add v2 UI for the perf dashboard
+        https://bugs.webkit.org/show_bug.cgi?id=137537
+
+        Rubber-stamped by Andreas Kling.
+
+        * public/v2: Added.
+        * public/v2/app.css: Added.
+        * public/v2/app.js: Added.
+        * public/v2/chart-pane.css: Added.
+        * public/v2/data.js: Added.
+        * public/v2/index.html: Added.
+        * public/v2/js: Added.
+        * public/v2/js/d3: Added.
+        * public/v2/js/d3/LICENSE: Added.
+        * public/v2/js/d3/d3.js: Added.
+        * public/v2/js/d3/d3.min.js: Added.
+        * public/v2/js/ember-data.js: Added.
+        * public/v2/js/ember.js: Added.
+        * public/v2/js/handlebars.js: Added.
+        * public/v2/js/jquery.min.js: Added.
+        * public/v2/js/statistics.js: Added.
+        * public/v2/manifest.js: Added.
+        * public/v2/popup.js: Added.
+
+2014-10-08  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
</ins><span class="cx">         Remove superfluously duplicated code in public/api/report-commits.php.
</span><span class="cx"> 
</span><span class="cx"> 2014-10-08  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgpublicv2appcss"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/app.css (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/app.css                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/app.css        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,410 @@
</span><ins>+html {
+    margin: 0;
+    padding: 0;
+}
+body {
+    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    padding: 0;
+    margin: 0 1rem;
+    min-width: 60rem;
+}
+
+
+.popup {
+    margin: 0;
+    position: relative;
+    display: inline-block;
+}
+
+.popup h1 {
+    display: inline-block;
+    margin: 0;
+    padding: 0;
+}
+
+.popup .popup-button,
+.control-button,
+.start-time-slider {
+    display: inline-block;
+    margin: 0;
+    padding: 0;
+    font-weight: normal;
+    color: #666;
+    text-decoration: none;
+    cursor: pointer;
+
+    border: solid 1px #999;
+    border-radius: 0.3rem;
+    padding: 0.2rem 0.5rem;
+}
+
+#header ul.controls li:not(:first-child) .control-button {
+    border-left: none;
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+}
+#header ul.controls li:not(:last-child) .control-button {
+    border-top-right-radius: 0;
+    border-bottom-right-radius: 0;
+}
+
+.popup .popup-button:after {
+    content: &quot; \25BE&quot;;
+}
+
+.popup .popup {
+    display: block;
+    margin: 0;
+}
+
+.popup .popup .popup-button:after {
+    content: &quot; \25B8&quot;;
+}
+
+.popup ul {
+    display: block;
+    position: absolute;
+    left: 0rem;
+    top: 0rem;
+    z-index: 999;
+    background: #fff;
+    box-shadow: rgba(0, 0, 0, 0.03) 1px 1px 10px 3px;
+/*    box-shadow: rgba(0, 0, 0, 0.03) 1px 1px 0px 0px;*/
+    margin: 0.2rem 0;
+    padding: 0.5rem 0;
+    list-style: none;
+    border: solid 1px #999;
+    border-radius: 0.3rem;
+    white-space: nowrap;
+    text-align: left;
+}
+
+.popup .popup ul {
+    top: 0rem;
+    margin: 0;
+    margin-top: -0.5rem;
+    margin-left: -0.7rem;
+}
+
+.popup li .label {
+    display: block;
+    max-width: 15rem;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+.popup .popup a {
+    display: block;
+    width: auto;
+    padding: 0.2rem 0.5rem;
+    border: none;
+}
+
+.popup a {
+    color: #333;
+    text-decoration: none;
+}
+
+.popup a:active,
+.popup a:focus {
+    background: #eef;
+}
+
+.popup li:hover {
+    background: #eee;
+}
+
+
+.close-button {
+    width: 1rem;
+    height: 1rem;
+}
+.close-button g {
+    stroke: #ccc;
+}
+.close-button:hover g {
+    stroke: #666;
+}
+
+
+#header {
+    margin: 0 0 1rem 0;
+    border: 1px solid #999;
+    border-radius: 0.3rem;
+    background: #fff;
+    box-shadow: rgba(0, 0, 0, 0.05) 0px 1px 3px 0px;
+    border-top: none;
+    border-top-left-radius: 0;
+    border-top-right-radius: 0;
+    color: #888;
+    position: relative;
+}
+
+#navigation {
+    display: inline-block;
+}
+
+#navigation h1,
+#navigation ul,
+#navigation li,
+#header ul.controls {
+    margin: 0;
+    padding: 0;
+    font-weight: normal;
+    line-height: 3rem;
+}
+#navigation a {
+    text-decoration: none;
+    color: inherit;
+}
+#navigation h1 {
+    font-size: 1.3rem;
+    margin-left: 0.5rem;
+    display: inline;
+    color: #c93;
+}
+#navigation ul,
+#header ul.controls {
+    display: inline-block;
+    list-style: none;
+}
+#navigation ul {
+    vertical-align: bottom;
+    margin-left: 4rem;
+    margin-right: 2.5rem;
+}
+#header ul.controls {
+    margin: 0 1.5rem;
+    vertical-align: top;
+    padding-top: 0.95rem;
+    font-size: 0.8rem;
+    line-height: 1rem;
+}
+#navigation li,
+#header ul.controls &gt; li {
+    display: block;
+    float: left;
+    margin: 0;
+    padding: 0;
+}
+#navigation li a {
+    display: block;
+    border: solid 1px #999;
+    border-bottom: 0px;
+    border-radius: 0.3rem;
+    border-bottom-left-radius: 0;
+    border-bottom-right-radius: 0;
+    padding: 0.5rem;
+    margin: 0;
+    line-height: 1rem;
+}
+#navigation li:not(:last-child) a {
+    border-top-right-radius: 0;
+    border-bottom-right-radius: 0;
+    border-right: 0;
+}
+#navigation li:not(:first-child) a {
+    border-top-left-radius: 0;
+    border-bottom-left-radius: 0;
+}
+#navigation li.active a,
+#header ul.controls li.active .control-button {
+    border-color: inherit;
+    color: #000;
+}
+
+#navigation li:not(.active) a:hover,
+#navigation li:not(.active) a:active,
+#header ul.controls &gt; li:not(.active) &gt; a:hover,
+#header ul.controls &gt; li:not(.active) &gt; a:active {
+    background-color: rgba(204, 153, 51, 0.1);
+}
+
+
+
+.start-time-slider {
+    line-height: 1em;
+}
+
+.start-time-slider label {
+    display: block;
+}
+
+.start-time-slider input {
+    vertical-align: middle;
+    height: 0.8rem;
+}
+
+.start-time-slider .numberOfDays {
+    display: inline-block;
+    text-align: right;
+    width: 1.5rem;
+}
+
+
+
+
+.spinner {
+    width: 2rem;
+    height: 2rem;
+    -webkit-transform: translateZ(0);
+}
+.spinner line {
+    animation: spinner-animation 1.6s linear infinite;
+    -webkit-animation: spinner-animation 1.6s linear infinite;
+    opacity: 0.1;
+}
+.spinner line:nth-child(0) {
+    -webkit-animation-delay: 0.0s;
+    animation-delay: 0.0s;
+}
+.spinner line:nth-child(1) {
+    -webkit-animation-delay: 0.2s;
+    animation-delay: 0.2s;
+}
+.spinner line:nth-child(2) {
+    -webkit-animation-delay: 0.4s;
+    animation-delay: 0.4s;
+}
+.spinner line:nth-child(3) {
+    -webkit-animation-delay: 0.6s;
+    animation-delay: 0.6s;
+}
+.spinner line:nth-child(4) {
+    -webkit-animation-delay: 0.8s;
+    animation-delay: 0.8s;
+}
+.spinner line:nth-child(5) {
+    -webkit-animation-delay: 1s;
+    animation-delay: 1s;
+}
+.spinner line:nth-child(6) {
+    -webkit-animation-delay: 1.2s;
+    animation-delay: 1.2s;
+}
+.spinner line:nth-child(7) {
+    -webkit-animation-delay: 1.4s;
+    animation-delay: 1.4s;
+}
+.spinner line:nth-child(8) {
+    -webkit-animation-delay: 1.6s;
+    animation-delay: 1.6s;
+}
+@-webkit-keyframes spinner-animation {
+    0% { opacity: 0.9; }
+    50% { opacity: 0.1; }
+    100% { opacity: 0.1; }
+}
+
+
+table.dashboard {
+    border-collapse: collapse;
+    table-layout: fixed;
+    color: #999;
+    width: 100%;
+}
+
+table.dashboard th,
+table.dashboard td {
+    border: solid 0px #d9d9d9;
+    padding: 0.2rem 0.5rem;
+    text-align: center;
+    position: relative;
+}
+
+table.dashboard thead th,
+table.dashboard thead td {
+    padding: 0.5rem;
+}
+/*
+table.dashboard thead th:nth-child(odd),
+table.dashboard tbody td:nth-child(even) {
+}
+*/
+table.dashboard input {
+    font-size: 1rem;
+    width: 12rem;
+    height: 1rem;
+    text-align: center;
+    margin: 0.5rem 0.3rem;
+}
+
+table.dashboard th {
+    font-weight: normal;
+    font-size: 1rem;
+    white-space: nowrap;
+    color: #f96;
+}
+
+table.dashboard thead th {
+    height: 1rem;
+}
+
+table.dashboard.readonly thead td,
+table.dashboard.readonly tbody th {
+    width: 1rem;
+    padding: 0.2rem 0.5rem;
+}
+
+table.dashboard tbody th {
+    height: 12rem;
+}
+
+table.dashboard.readonly tbody th .label {
+    position: absolute;
+    left: 0;
+    right: 0;
+    display: block;
+    width: 12.4rem;
+    height: 2rem;
+    line-height: 2rem;
+    vertical-align: middle;
+    -webkit-transform: rotate(-90deg) translate(-50%, 0);
+    -webkit-transform-origin: 0 0;
+    transform: rotate(-90deg) translate(-50%, 0);
+    transform-origin: 0 0;
+}
+
+table.dashboard.editMode a {
+    text-decoration: none;
+    vertical-align: middle;
+}
+
+table.dashboard.editMode tbody th a {
+    margin-left: 0.3rem;
+}
+
+table.dashboard.editMode input {
+    box-shadow: inset 1px 1px 0px rgba(0, 0, 0, 0.05);
+    border: solid 1px #999;
+    padding: 0.2rem;
+    border-radius: 0.2rem;
+}
+
+table.dashboard tbody td a.reset {
+    position: absolute;
+    top: 0.5rem;
+    left: 0.5rem;
+}
+table.dashboard.editMode tbody td {
+    padding-left: 2rem;
+}
+table.dashboard tbody td a.reset svg {
+    background: white;
+}
+
+table.dashboard tbody td .chart {
+    border: solid 1px #ddd;
+    border-radius: 0.5rem;
+    margin: 0.5rem 0.5rem;
+}
+
+table.dashboard tbody td .chart,
+table.dashboard tbody td .failure,
+table.dashboard tbody td .progress {
+    display: inline-block;
+    width: 100%;
+    height: 12rem;
+    line-height: 12rem;
+    vertical-align: center;
+}
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/app.css
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2appjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/app.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/app.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/app.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,1429 @@
</span><ins>+window.App = Ember.Application.create();
+
+App.Router.map(function () {
+    this.resource('charts', {path: 'charts'});
+});
+
+App.DashboardRow = Ember.Object.extend({
+    header: null,
+    cells: [],
+
+    init: function ()
+    {
+        this._super();
+
+        var cellsInfo = this.get('cellsInfo') || [];
+        var columnCount = this.get('columnCount');
+        while (cellsInfo.length &lt; columnCount)
+            cellsInfo.push([]);
+
+        this.set('cells', cellsInfo.map(this._createPane.bind(this)));
+    },
+    addPane: function (paneInfo)
+    {
+        var pane = this._createPane(paneInfo);
+        this.get('cells').pushObject(pane);
+        this.set('columnCount', this.get('columnCount') + 1);
+    },
+    _createPane: function (paneInfo)
+    {
+        if (!paneInfo || !paneInfo.length || (!paneInfo[0] &amp;&amp; !paneInfo[1]))
+            paneInfo = null;
+
+        var pane = App.Pane.create({
+            platformId: paneInfo ? paneInfo[0] : null,
+            metricId: paneInfo ? paneInfo[1] : null,
+        });
+
+        return App.DashboardPaneProxyForPicker.create({content: pane});
+    },
+});
+
+App.DashboardPaneProxyForPicker = Ember.ObjectProxy.extend({
+    _platformOrMetricIdChanged: function ()
+    {
+        var self = this;
+        App.BuildPopup('choosePane', this)
+            .then(function (platforms) { self.set('pickerData', platforms); });
+    }.observes('platformId', 'metricId').on('init'),
+    paneList: function () {
+        return App.encodePrettifiedJSON([[this.get('platformId'), this.get('metricId'), null, null, false]]);
+    }.property('platformId', 'metricId'),
+});
+
+App.IndexController = Ember.Controller.extend({
+    queryParams: ['grid', 'numberOfDays'],
+    _previousGrid: {},
+    defaultTable: [],
+    headerColumns: [],
+    rows: [],
+    numberOfDays: 30,
+    editMode: false,
+
+    gridChanged: function ()
+    {
+        var grid = this.get('grid');
+        if (grid === this._previousGrid)
+            return;
+
+        var table = null;
+        try {
+            if (grid)
+                table = JSON.parse(grid);
+        } catch (error) {
+            console.log(&quot;Failed to parse the grid:&quot;, error, grid);
+        }
+
+        if (!table || !table.length) // FIXME: We should fetch this from the manifest.
+            table = this.get('defaultTable');
+
+        table = this._normalizeTable(table);
+        var columnCount = table[0].length;
+        this.set('columnCount', columnCount);
+
+        this.set('headerColumns', table[0].map(function (name, index) {
+            return {label:name, index: index};
+        }));
+
+        this.set('rows', table.slice(1).map(function (rowParam) {
+            return App.DashboardRow.create({
+                header: rowParam[0],
+                cellsInfo: rowParam.slice(1),
+                columnCount: columnCount,
+            })
+        }));
+
+        this.set('emptyRow', new Array(columnCount));
+    }.observes('grid').on('init'),
+
+    _normalizeTable: function (table)
+    {
+        var maxColumnCount = Math.max(table.map(function (column) { return column.length; }));
+        for (var i = 1; i &lt; table.length; i++) {
+            var row = table[i];
+            for (var j = 1; j &lt; row.length; j++) {
+                if (row[j] &amp;&amp; !(row[j] instanceof Array)) {
+                    console.log('Unrecognized (platform, metric) pair at column ' + i + ' row ' + j + ':' + row[j]);
+                    row[j] = [];
+                }
+            }
+        }
+        return table;
+    },
+
+    updateGrid: function()
+    {
+        var headers = this.get('headerColumns').map(function (header) { return header.label; });
+        var table = [headers].concat(this.get('rows').map(function (row) {
+            return [row.get('header')].concat(row.get('cells').map(function (pane) {
+                var platformAndMetric = [pane.get('platformId'), pane.get('metricId')];
+                return platformAndMetric[0] || platformAndMetric[1] ? platformAndMetric : [];
+            }));
+        }));
+        this._previousGrid = JSON.stringify(table);
+        this.set('grid', this._previousGrid);
+    },
+
+    _sharedDomainChanged: function ()
+    {
+        var numberOfDays = this.get('numberOfDays');
+        if (!numberOfDays)
+            return;
+
+        numberOfDays = parseInt(numberOfDays);
+        var present = Date.now();
+        var past = present - numberOfDays * 24 * 3600 * 1000;
+        this.set('sharedDomain', [past, present]);
+    }.observes('numberOfDays').on('init'),
+
+    actions: {
+        setNumberOfDays: function (numberOfDays)
+        {
+            this.set('numberOfDays', numberOfDays);
+        },
+        choosePane: function (param)
+        {
+            var pane = param.position;
+            pane.set('platformId', param.platform.get('id'));
+            pane.set('metricId', param.metric.get('id'));
+        },
+        addColumn: function ()
+        {
+            this.get('headerColumns').pushObject({
+                label: this.get('newColumnHeader'),
+                index: this.get('headerColumns').length,
+            });
+            this.get('rows').forEach(function (row) {
+                row.addPane();
+            });
+            this.set('newColumnHeader', null);
+        },
+        removeColumn: function (index)
+        {
+            this.get('headerColumns').removeAt(index);
+            this.get('rows').forEach(function (row) {
+                row.get('cells').removeAt(index);
+            });
+        },
+        addRow: function ()
+        {
+            this.get('rows').pushObject(App.DashboardRow.create({
+                header: this.get('newRowHeader'),
+                columnCount: this.get('columnCount'),
+            }));
+            this.set('newRowHeader', null);
+        },
+        removeRow: function (row)
+        {
+            this.get('rows').removeObject(row);
+        },
+        resetPane: function (pane)
+        {
+            pane.set('platformId', null);
+            pane.set('metricId', null);
+        },
+        toggleEditMode: function ()
+        {
+            this.toggleProperty('editMode');
+            if (!this.get('editMode'))
+                this.updateGrid();
+        },
+    },
+
+    init: function ()
+    {
+        this._super();
+        App.Manifest.fetch();
+    }
+});
+
+App.NumberOfDaysControlView = Ember.View.extend({
+    classNames: ['controls'],
+    templateName: 'number-of-days-controls',
+    didInsertElement: function ()
+    {
+        this._matchingElements(this._previousNumberOfDaysClass).addClass('active');
+    },
+    _numberOfDaysChanged: function ()
+    {
+        this._matchingElements(this._previousNumberOfDaysClass).removeClass('active');
+
+        var newNumberOfDaysClass = 'numberOfDaysIs' + this.get('numberOfDays');
+        this._matchingElements(this._previousNumberOfDaysClass).addClass('active');
+        this._previousNumberOfDaysClass = newNumberOfDaysClass;
+    }.observes('numberOfDays').on('init'),
+    _matchingElements: function (className)
+    {
+        var element = this.get('element');
+        if (!element)
+            return $([]);
+        return $(element.getElementsByClassName(className));
+    }
+});
+
+App.StartTimeSliderView = Ember.View.extend({
+    templateName: 'start-time-slider',
+    classNames: ['start-time-slider'],
+    startTime: Date.now() - 7 * 24 * 3600 * 1000,
+    oldestStartTime: null,
+    _numberOfDaysView: null,
+    _slider: null,
+    _startTimeInSlider: null,
+    _currentNumberOfDays: null,
+    _MILLISECONDS_PER_DAY: 24 * 3600 * 1000,
+
+    didInsertElement: function ()
+    {
+        this.oldestStartTime = Date.now() - 365 * 24 * 3600 * 1000;
+        this._slider = $(this.get('element')).find('input');
+        this._numberOfDaysView = $(this.get('element')).find('.numberOfDays');
+        this._sliderRangeChanged();
+        this._slider.change(this._sliderMoved.bind(this));
+    },
+    _sliderRangeChanged: function ()
+    {
+        var minimumNumberOfDays = 1;
+        var maximumNumberOfDays = this._timeInPastToNumberOfDays(this.get('oldestStartTime'));
+        var precision = 1000; // FIXME: Compute this from maximumNumberOfDays.
+        var slider = this._slider;
+        slider.attr('min', Math.floor(Math.log(Math.max(1, minimumNumberOfDays)) * precision) / precision);
+        slider.attr('max', Math.ceil(Math.log(maximumNumberOfDays) * precision) / precision);
+        slider.attr('step', 1 / precision);
+        this._startTimeChanged();
+    }.observes('oldestStartTime'),
+    _sliderMoved: function ()
+    {
+        this._currentNumberOfDays = Math.round(Math.exp(this._slider.val()));
+        this._numberOfDaysView.text(this._currentNumberOfDays);
+        this._startTimeInSlider = this._numberOfDaysToTimeInPast(this._currentNumberOfDays);
+        this.set('startTime', this._startTimeInSlider);
+    },
+    _startTimeChanged: function ()
+    {
+        var startTime = this.get('startTime');
+        if (startTime == this._startTimeSetBySlider)
+            return;
+        this._currentNumberOfDays = this._timeInPastToNumberOfDays(startTime);
+
+        if (this._slider) {
+            this._numberOfDaysView.text(this._currentNumberOfDays);
+            this._slider.val(Math.log(this._currentNumberOfDays));
+            this._startTimeInSlider = startTime;
+        }
+    }.observes('startTime').on('init'),
+    _timeInPastToNumberOfDays: function (timeInPast)
+    {
+        return Math.max(1, Math.round((Date.now() - timeInPast) / this._MILLISECONDS_PER_DAY));
+    },
+    _numberOfDaysToTimeInPast: function (numberOfDays)
+    {
+        return Date.now() - numberOfDays * this._MILLISECONDS_PER_DAY;
+    },
+});
+
+App.Pane = Ember.Object.extend({
+    platformId: null,
+    platform: null,
+    metricId: null,
+    metric: null,
+    selectedItem: null,
+    init: function ()
+    {
+        this._super();
+    },
+    _fetch: function () {
+        var platformId = this.get('platformId');
+        var metricId = this.get('metricId');
+        if (!platformId &amp;&amp; !metricId) {
+            this.set('empty', true);
+            return;
+        }
+        this.set('empty', false);
+        this.set('platform', null);
+        this.set('chartData', null);
+        this.set('metric', null);
+        this.set('failure', null);
+
+        if (!this._isValidId(platformId))
+            this.set('failure', platformId ? 'Invalid platform id:' + platformId : 'Platform id was not specified');
+        else if (!this._isValidId(metricId))
+            this.set('failure', metricId ? 'Invalid metric id:' + metricId : 'Metric id was not specified');
+        else {
+            var self = this;
+
+            var metric;
+            var manifestPromise = App.Manifest.fetch(this.store).then(function () {
+                return new Ember.RSVP.Promise(function (resolve, reject) {
+                    var platform = App.Manifest.platform(platformId);
+                    metric = App.Manifest.metric(metricId);
+                    if (!platform)
+                        reject('Could not find the platform &quot;' + platformId + '&quot;');
+                    else if (!metric)
+                        reject('Could not find the metric &quot;' + metricId + '&quot;');
+                    else {
+                        self.set('platform', platform);
+                        self.set('metric', metric);
+                        resolve(null);
+                    }
+                });
+            });
+
+            Ember.RSVP.all([
+                RunsData.fetchRuns(platformId, metricId),
+                manifestPromise,
+            ]).then(function (values) {
+                var runs = values[0];
+
+                // FIXME: Include this information in JSON and process it in RunsData.fetchRuns
+                var unit = {'Combined': '', // Assume smaller is better for now.
+                    'FrameRate': 'fps',
+                    'Runs': 'runs/s',
+                    'Time': 'ms',
+                    'Malloc': 'bytes',
+                    'JSHeap': 'bytes',
+                    'Allocations': 'bytes',
+                    'EndAllocations': 'bytes',
+                    'MaxAllocations': 'bytes',
+                    'MeanAllocations': 'bytes'}[metric.get('name')];
+                runs.unit = unit;
+
+                self.set('chartData', runs);
+            }, function (status) {
+                self.set('failure', 'Failed to fetch the JSON with an error: ' + status);
+            });
+        }
+    }.observes('platformId', 'metricId').on('init'),
+    _isValidId: function (id)
+    {
+        if (typeof(id) == &quot;number&quot;)
+            return true;
+        if (typeof(id) == &quot;string&quot;)
+            return !!id.match(/^[A-Za-z0-9_]+$/);
+        return false;
+    }
+});
+
+App.encodePrettifiedJSON = function (plain)
+{
+    function numberIfPossible(string) {
+        return string == parseInt(string) ? parseInt(string) : string;
+    }
+
+    function recursivelyConvertNumberIfPossible(input) {
+        if (input instanceof Array) {
+            return input.map(recursivelyConvertNumberIfPossible);
+        }
+        return numberIfPossible(input);
+    }
+
+    return JSON.stringify(recursivelyConvertNumberIfPossible(plain))
+        .replace(/\[/g, '(').replace(/\]/g, ')').replace(/\,/g, '-');
+}
+
+App.decodePrettifiedJSON = function (encoded)
+{
+    var parsed = encoded.replace(/\(/g, '[').replace(/\)/g, ']').replace(/\-/g, ',');
+    try {
+        return JSON.parse(parsed);
+    } catch (exception) {
+        return null;
+    }
+}
+
+App.ChartsController = Ember.Controller.extend({
+    queryParams: ['paneList', 'zoom', 'since'],
+    needs: ['pane'],
+    _currentEncodedPaneList: null,
+    panes: [],
+    platforms: null,
+    sharedZoom: null,
+    startTime: null,
+    defaultSince: Date.now() - 7 * 24 * 3600 * 1000,
+
+    addPane: function (pane)
+    {
+        this.panes.unshiftObject(pane);
+    },
+
+    removePane: function (pane)
+    {
+        this.panes.removeObject(pane);
+    },
+
+    refreshPanes: function()
+    {
+        var paneList = this.get('paneList');
+        if (paneList === this._currentEncodedPaneList)
+            return;
+
+        var panes = this._parsePaneList(paneList || '[]');
+        if (!panes) {
+            console.log('Failed to parse', jsonPaneList, exception);
+            return;
+        }
+        this.set('panes', panes);
+        this._currentEncodedPaneList = paneList;
+    }.observes('paneList').on('init'),
+
+    refreshZoom: function()
+    {
+        var zoom = this.get('zoom');
+        if (!zoom) {
+            this.set('sharedZoom', null);
+            return;
+        }
+
+        zoom = zoom.split('-');
+        var selection = new Array(2);
+        try {
+            selection[0] = new Date(parseFloat(zoom[0]));
+            selection[1] = new Date(parseFloat(zoom[1]));
+        } catch (error) {
+            console.log('Failed to parse the zoom', zoom);
+        }
+        this.set('sharedZoom', selection);
+
+        var startTime = this.get('startTime');
+        if (startTime &amp;&amp; startTime &gt; selection[0])
+            this.set('startTime', selection[0]);
+
+    }.observes('zoom').on('init'),
+
+    updateSharedDomain: function ()
+    {
+        var panes = this.get('panes');
+        if (!panes.length)
+            return;
+
+        var union = [undefined, undefined];
+        for (var i = 0; i &lt; panes.length; i++) {
+            var domain = panes[i].intrinsicDomain;
+            if (!domain)
+                continue;
+            if (!union[0] || domain[0] &lt; union[0])
+                union[0] = domain[0];
+            if (!union[1] || domain[1] &gt; union[1])
+                union[1] = domain[1];
+        }
+        if (union[0] === undefined)
+            return;
+
+        var startTime = this.get('startTime');
+        var zoom = this.get('sharedZoom');
+        if (startTime)
+            union[0] = zoom ? Math.min(zoom[0], startTime) : startTime;
+
+        this.set('sharedDomain', union);
+    }.observes('panes.@each'),
+
+    _startTimeChanged: function () {
+        this.updateSharedDomain();
+        this._scheduleQueryStringUpdate();
+    }.observes('startTime'),
+
+    _sinceChanged: function () {
+        var since = parseInt(this.get('since'));
+        if (isNaN(since))
+            since = this.defaultSince;
+        this.set('startTime', new Date(since));
+    }.observes('since').on('init'),
+
+    _parsePaneList: function (encodedPaneList)
+    {
+        var parsedPaneList = App.decodePrettifiedJSON(encodedPaneList);
+        if (!parsedPaneList)
+            return null;
+
+        // Don't re-create all panes.
+        var self = this;
+        return parsedPaneList.map(function (paneInfo) {
+            var timeRange = null;
+            if (paneInfo[3] &amp;&amp; paneInfo[3] instanceof Array) {
+                var timeRange = paneInfo[3];
+                try {
+                    timeRange = [new Date(timeRange[0]), new Date(timeRange[1])];
+                } catch (error) {
+                    console.log(&quot;Failed to parse the time range:&quot;, timeRange, error);
+                }
+            }
+            return App.Pane.create({
+                info: paneInfo,
+                platformId: paneInfo[0],
+                metricId: paneInfo[1],
+                selectedItem: paneInfo[2],
+                timeRange: timeRange,
+                timeRangeIsLocked: !!paneInfo[4],
+            });
+        });
+    },
+
+    _serializePaneList: function (panes)
+    {
+        if (!panes.length)
+            return undefined;
+        return App.encodePrettifiedJSON(panes.map(function (pane) {
+            return [
+                pane.get('platformId'),
+                pane.get('metricId'),
+                pane.get('selectedItem'),
+                pane.get('timeRange') ? pane.get('timeRange').map(function (date) { return date.getTime() }) : null,
+                !!pane.get('timeRangeIsLocked'),
+            ];
+        }));
+    },
+
+    _scheduleQueryStringUpdate: function ()
+    {
+        Ember.run.debounce(this, '_updateQueryString', 500);
+    }.observes('sharedZoom')
+        .observes('panes.@each.platform', 'panes.@each.metric', 'panes.@each.selectedItem',
+        'panes.@each.timeRange', 'panes.@each.timeRangeIsLocked'),
+
+    _updateQueryString: function ()
+    {
+        this._currentEncodedPaneList = this._serializePaneList(this.get('panes'));
+        this.set('paneList', this._currentEncodedPaneList);
+
+        var zoom = undefined;
+        var selection = this.get('sharedZoom');
+        if (selection)
+            zoom = (selection[0] - 0) + '-' + (selection[1] - 0);
+        this.set('zoom', zoom);
+
+        if (this.get('startTime') - this.defaultSince)
+            this.set('since', this.get('startTime') - 0);
+    },
+
+    actions: {
+        addPaneByMetricAndPlatform: function (param)
+        {
+            this.addPane(App.Pane.create({
+                platformId: param.platform.get('id'),
+                metricId: param.metric.get('id'),
+                showingDetails: false
+            }));
+        },
+    },
+
+    init: function ()
+    {
+        this._super();
+        var self = this;
+        App.BuildPopup('addPaneByMetricAndPlatform').then(function (platforms) {
+            self.set('platforms', platforms);
+        });
+    },
+});
+
+App.BuildPopup = function(action, position)
+{
+    return App.Manifest.fetch().then(function () {
+        return App.Manifest.get('platforms').map(function (platform) {
+            return App.PlatformProxyForPopup.create({content: platform,
+                action: action, position: position});
+        });
+    });
+}
+
+App.PlatformProxyForPopup = Ember.ObjectProxy.extend({
+    children: function ()
+    {
+        var platform = this.content;
+        var containsTest = this.content.containsTest.bind(this.content);
+        var action = this.get('action');
+        var position = this.get('position');
+        return App.Manifest.get('topLevelTests')
+            .filter(containsTest)
+            .map(function (test) {
+                return App.TestProxyForPopup.create({content: test, platform: platform, action: action, position: position});
+            });
+    }.property('App.Manifest.topLevelTests'),
+});
+
+App.TestProxyForPopup = Ember.ObjectProxy.extend({
+    platform: null,
+    children: function ()
+    {
+        var platform = this.get('platform');
+        var action = this.get('action');
+        var position = this.get('position');
+
+        var childTests = this.get('childTests')
+            .filter(function (test) { return platform.containsTest(test); })
+            .map(function (test) {
+                return App.TestProxyForPopup.create({content: test, platform: platform, action: action, position: position});
+            });
+
+        var metrics = this.get('metrics')
+            .filter(function (metric) { return platform.containsMetric(metric); })
+            .map(function (metric) {
+                var aggregator = metric.get('aggregator');
+                return {
+                    actionName: action,
+                    actionArgument: {platform: platform, metric: metric, position:position},
+                    label: metric.get('label')
+                };
+            });
+
+        if (childTests.length &amp;&amp; metrics.length)
+            metrics.push({isSeparator: true});
+
+        return metrics.concat(childTests);
+    }.property('childTests', 'metrics'),
+});
+
+App.PaneController = Ember.ObjectController.extend({
+    needs: ['charts'],
+    sharedTime: Ember.computed.alias('parentController.sharedTime'),
+    sharedSelection: Ember.computed.alias('parentController.sharedSelection'),
+    selection: null,
+    actions: {
+        toggleDetails: function()
+        {
+            this.toggleProperty('showingDetails');
+        },
+        close: function ()
+        {
+            this.parentController.removePane(this.get('model'));
+        },
+        zoomed: function (selection)
+        {
+            this.set('mainPlotDomain', selection ? selection : this.get('overviewDomain'));
+            Ember.run.debounce(this, 'propagateZoom', 100);
+        },
+        overviewDomainChanged: function (domain, intrinsicDomain)
+        {
+            this.set('overviewDomain', domain);
+            this.set('intrinsicDomain', intrinsicDomain);
+            this.get('parentController').updateSharedDomain();
+        },
+        rangeChanged: function (extent, startPoint, endPoint)
+        {
+            if (!startPoint || !endPoint) {
+                this._hasRange = false;
+                this.set('details', null);
+                this.set('timeRange', null);
+                return;
+            }
+            this._hasRange = true;
+            this._showDetails(startPoint.measurement, endPoint.measurement, false);
+            this.set('timeRange', extent);
+        },
+    },
+    _overviewSelectionChanged: function ()
+    {
+        var overviewSelection = this.get('overviewSelection');
+        this.set('mainPlotDomain', overviewSelection);
+        Ember.run.debounce(this, 'propagateZoom', 100);
+    }.observes('overviewSelection'),
+    _sharedDomainChanged: function ()
+    {
+        var newDomain = this.get('parentController').get('sharedDomain');
+        if (newDomain == this.get('overviewDomain'))
+            return;
+        this.set('overviewDomain', newDomain);
+        if (!this.get('overviewSelection'))
+            this.set('mainPlotDomain', newDomain);
+    }.observes('parentController.sharedDomain').on('init'),
+    propagateZoom: function ()
+    {
+        this.get('parentController').set('sharedZoom', this.get('mainPlotDomain'));
+    },
+    _sharedZoomChanged: function ()
+    {
+        var newSelection = this.get('parentController').get('sharedZoom');
+        if (newSelection == this.get('mainPlotDomain'))
+            return;
+        this.set('overviewSelection', newSelection);
+        this.set('mainPlotDomain', newSelection);
+    }.observes('parentController.sharedZoom').on('init'),
+    _currentItemChanged: function ()
+    {
+        if (this._hasRange)
+            return;
+        var point = this.get('currentItem');
+        if (!point || !point.measurement)
+            this.set('details', null);
+        else
+            this._showDetails(point.series.previousPoint(point).measurement, point.measurement, true);
+    }.observes('currentItem'),
+    _showDetails: function (oldMeasurement, currentMeasurement, isShowingEndPoint)
+    {
+        var revisions = [];
+
+        var formattedRevisions = currentMeasurement.formattedRevisions(oldMeasurement);
+        var repositoryNames = [];
+        for (var repositoryName in formattedRevisions)
+            repositoryNames.push(repositoryName);
+        var revisions = [];
+        repositoryNames.sort().forEach(function (repositoryName) {
+            var revision = formattedRevisions[repositoryName];
+            var repository = App.Manifest.repository(repositoryName);
+            revision['url'] = false;
+            if (repository) {
+                revision['url'] = revision.previousRevision
+                    ? repository.urlForRevisionRange(revision.previousRevision, revision.currentRevision)
+                    : repository.urlForRevision(revision.currentRevision);
+            }
+            revision['name'] = repositoryName;
+            revision['repository'] = repository;
+            revisions.push(Ember.Object.create(revision));            
+        });
+
+        var buildNumber = null;
+        var buildURL = null;
+        if (isShowingEndPoint) {
+            buildNumber = currentMeasurement.buildNumber();
+            var builder = App.Manifest.builder(currentMeasurement.builderId());
+            if (builder)
+                buildURL = builder.urlFromBuildNumber(buildNumber);
+        }
+        this.set('details', {
+            currentValue: currentMeasurement.mean().toFixed(2),
+            oldValue: oldMeasurement &amp;&amp; !isShowingEndPoint ? oldMeasurement.mean().toFixed(2) : null,
+            buildNumber: buildNumber,
+            buildURL: buildURL,
+            buildTime: currentMeasurement.formattedBuildTime(),
+            revisions: revisions,
+        });
+    }
+});
+
+App.InteractiveChartComponent = Ember.Component.extend({
+    chartData: null,
+    showXAxis: true,
+    showYAxis: true,
+    interactive: false,
+    enableSelection: true,
+    classNames: ['chart'],
+    init: function ()
+    {
+        this._super();
+        this._needsConstruction = true;
+        this._eventHandlers = [];
+        $(window).resize(this._updateDimensionsIfNeeded.bind(this));
+    },
+    chartDataDidChange: function ()
+    {
+        var chartData = this.get('chartData');
+        if (!chartData)
+            return;
+        this._needsConstruction = true;
+        this._constructGraphIfPossible(chartData);
+    }.observes('chartData').on('init'),
+    didInsertElement: function ()
+    {
+        var chartData = this.get('chartData');
+        if (chartData)
+            this._constructGraphIfPossible(chartData);
+    },
+    willClearRender: function ()
+    {
+        this._eventHandlers.forEach(function (item) {
+            $(item[0]).off(item[1], item[2]);
+        })
+    },
+    _attachEventListener: function(target, eventName, listener)
+    {
+        this._eventHandlers.push([target, eventName, listener]);
+        $(target).on(eventName, listener);
+    },
+    _constructGraphIfPossible: function (chartData)
+    {
+        if (!this._needsConstruction || !this.get('element'))
+            return;
+
+        var element = this.get('element');
+
+        this._x = d3.time.scale();
+        this._y = d3.scale.linear();
+
+        // FIXME: Tear down the old SVG element.
+        this._svgElement = d3.select(element).append(&quot;svg&quot;)
+                .attr(&quot;width&quot;, &quot;100%&quot;)
+                .attr(&quot;height&quot;, &quot;100%&quot;);
+
+        var svg = this._svg = this._svgElement.append(&quot;g&quot;);
+
+        var clipId = element.id + &quot;-clip&quot;;
+        this._clipPath = svg.append(&quot;defs&quot;).append(&quot;clipPath&quot;)
+            .attr(&quot;id&quot;, clipId)
+            .append(&quot;rect&quot;);
+
+        if (this.get('showXAxis')) {
+            this._xAxis = d3.svg.axis().scale(this._x).orient(&quot;bottom&quot;).ticks(6);
+            this._xAxisLabels = svg.append(&quot;g&quot;)
+                .attr(&quot;class&quot;, &quot;x axis&quot;);
+        }
+
+        if (this.get('showYAxis')) {
+            this._yAxis = d3.svg.axis().scale(this._y).orient(&quot;left&quot;).ticks(6).tickFormat(d3.format(&quot;s&quot;));
+            this._yAxisLabels = svg.append(&quot;g&quot;)
+                .attr(&quot;class&quot;, &quot;y axis&quot;);
+        }
+
+        this._clippedContainer = svg.append(&quot;g&quot;)
+            .attr(&quot;clip-path&quot;, &quot;url(#&quot; + clipId + &quot;)&quot;);
+
+        var xScale = this._x;
+        var yScale = this._y;
+        this._timeLine = d3.svg.line()
+            .x(function(point) { return xScale(point.time); })
+            .y(function(point) { return yScale(point.value); });
+
+        this._confidenceArea = d3.svg.area()
+//            .interpolate(&quot;cardinal&quot;)
+            .x(function(point) { return xScale(point.time); })
+            .y0(function(point) { return point.interval ? yScale(point.interval[0]) : null; })
+            .y1(function(point) { return point.interval ? yScale(point.interval[1]) : null; });
+
+        if (this._paths)
+            this._paths.forEach(function (path) { path.remove(); });
+        this._paths = [];
+        if (this._areas)
+            this._areas.forEach(function (area) { area.remove(); });
+        this._areas = [];
+        this._dots = [];
+
+        this._currentTimeSeries = chartData.current.timeSeriesByCommitTime();
+        this._currentTimeSeriesData = this._currentTimeSeries.series();
+        this._baselineTimeSeries = chartData.baseline ? chartData.baseline.timeSeriesByCommitTime() : null;
+        this._targetTimeSeries = chartData.target ? chartData.target.timeSeriesByCommitTime() : null;
+
+        this._yAxisUnit = chartData.unit;
+
+        var minMax = this._minMaxForAllTimeSeries();
+        var smallEnoughValue = minMax[0] - (minMax[1] - minMax[0]) * 10;
+        var largeEnoughValue = minMax[1] + (minMax[1] - minMax[0]) * 10;
+
+        // FIXME: Flip the sides based on smallerIsBetter-ness.
+        if (this._baselineTimeSeries) {
+            var data = this._baselineTimeSeries.series();
+            this._areas.push(this._clippedContainer
+                .append(&quot;path&quot;)
+                .datum(data.map(function (point) { return {time: point.time, value: point.value, interval: point.interval ? point.interval : [point.value, largeEnoughValue]}; }))
+                .attr(&quot;class&quot;, &quot;area baseline&quot;));
+        }
+        if (this._targetTimeSeries) {
+            var data = this._targetTimeSeries.series();
+            this._areas.push(this._clippedContainer
+                .append(&quot;path&quot;)
+                .datum(data.map(function (point) { return {time: point.time, value: point.value, interval: point.interval ? point.interval : [smallEnoughValue, point.value]}; }))
+                .attr(&quot;class&quot;, &quot;area target&quot;));
+        }
+
+        this._areas.push(this._clippedContainer
+            .append(&quot;path&quot;)
+            .datum(this._currentTimeSeriesData)
+            .attr(&quot;class&quot;, &quot;area&quot;));
+
+        this._paths.push(this._clippedContainer
+            .append(&quot;path&quot;)
+            .datum(this._currentTimeSeriesData)
+            .attr(&quot;class&quot;, &quot;commit-time-line&quot;));
+
+        this._dots.push(this._clippedContainer
+            .selectAll(&quot;.dot&quot;)
+                .data(this._currentTimeSeriesData)
+            .enter().append(&quot;circle&quot;)
+                .attr(&quot;class&quot;, &quot;dot&quot;)
+                .attr(&quot;r&quot;, this.get('interactive') ? 2 : 1));
+
+        if (this.get('interactive')) {
+            this._attachEventListener(element, &quot;mousemove&quot;, this._mouseMoved.bind(this));
+            this._attachEventListener(element, &quot;mouseleave&quot;, this._mouseLeft.bind(this));
+            this._attachEventListener(element, &quot;mousedown&quot;, this._mouseDown.bind(this));
+            this._attachEventListener($(element).parents(&quot;[tabindex]&quot;), &quot;keydown&quot;, this._keyPressed.bind(this));
+
+            this._currentItemLine = this._clippedContainer
+                .append(&quot;line&quot;)
+                .attr(&quot;class&quot;, &quot;current-item&quot;);
+
+            this._currentItemCircle = this._clippedContainer
+                .append(&quot;circle&quot;)
+                .attr(&quot;class&quot;, &quot;dot current-item&quot;)
+                .attr(&quot;r&quot;, 3);
+        }
+
+        this._brush = null;
+        if (this.get('enableSelection')) {
+            this._brush = d3.svg.brush()
+                .x(this._x)
+                .on(&quot;brush&quot;, this._brushChanged.bind(this));
+
+            this._brushRect = this._clippedContainer
+                .append(&quot;g&quot;)
+                .attr(&quot;class&quot;, &quot;x brush&quot;);
+        }
+
+        this._updateDomain();
+        this._updateDimensionsIfNeeded();
+
+        // Work around the fact the brush isn't set if we updated it synchronously here.
+        setTimeout(this._selectionChanged.bind(this), 0);
+
+        setTimeout(this._selectedItemChanged.bind(this), 0);
+
+        this._needsConstruction = false;
+    },
+    _updateDomain: function ()
+    {
+        var xDomain = this.get('domain');
+        var intrinsicXDomain = this._computeXAxisDomain(this._currentTimeSeriesData);
+        if (!xDomain)
+            xDomain = intrinsicXDomain;
+        var currentDomain = this._x.domain();
+        if (currentDomain &amp;&amp; this._xDomainsAreSame(currentDomain, xDomain))
+            return currentDomain;
+
+        var yDomain = this._computeYAxisDomain(xDomain[0], xDomain[1]);
+        this._x.domain(xDomain);
+        this._y.domain(yDomain);
+        this.sendAction('domainChanged', xDomain, intrinsicXDomain);
+        return xDomain;
+    },
+    _updateDimensionsIfNeeded: function (newSelection)
+    {
+        var element = $(this.get('element'));
+
+        var newTotalWidth = element.width();
+        var newTotalHeight = element.height();
+        if (this._totalWidth == newTotalWidth &amp;&amp; this._totalHeight == newTotalHeight)
+            return;
+
+        this._totalWidth = newTotalWidth;
+        this._totalHeight = newTotalHeight;
+
+        if (!this._rem)
+            this._rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
+        var rem = this._rem;
+
+        var padding = 0.5 * rem;
+        var margin = {top: padding, right: padding, bottom: padding, left: padding};
+        if (this._xAxis)
+            margin.bottom += rem;
+        if (this._yAxis)
+            margin.left += 3 * rem;
+
+        this._margin = margin;
+        this._contentWidth = this._totalWidth - margin.left - margin.right;
+        this._contentHeight = this._totalHeight - margin.top - margin.bottom;
+
+        this._svg.attr(&quot;transform&quot;, &quot;translate(&quot; + margin.left + &quot;,&quot; + margin.top + &quot;)&quot;);
+
+        this._clipPath
+            .attr(&quot;width&quot;, this._contentWidth)
+            .attr(&quot;height&quot;, this._contentHeight);
+
+        this._x.range([0, this._contentWidth]);
+        this._y.range([this._contentHeight, 0]);
+
+        if (this._xAxis) {
+            this._xAxis.tickSize(-this._contentHeight);
+            this._xAxisLabels.attr(&quot;transform&quot;, &quot;translate(0,&quot; + this._contentHeight + &quot;)&quot;);
+        }
+
+        if (this._yAxis)
+            this._yAxis.tickSize(-this._contentWidth);
+
+        if (this._currentItemLine) {
+            this._currentItemLine
+                .attr(&quot;y1&quot;, 0)
+                .attr(&quot;y2&quot;, margin.top + this._contentHeight);
+        }
+
+        this._relayoutDataAndAxes(this._currentSelection());
+    },
+    _updateBrush: function ()
+    {
+        this._brushRect
+            .call(this._brush)
+        .selectAll(&quot;rect&quot;)
+            .attr(&quot;y&quot;, 1)
+            .attr(&quot;height&quot;, this._contentHeight - 2);
+        this._updateSelectionToolbar();
+    },
+    _relayoutDataAndAxes: function (selection)
+    {
+        var timeline = this._timeLine;
+        this._paths.forEach(function (path) { path.attr(&quot;d&quot;, timeline); });
+
+        var confidenceArea = this._confidenceArea;
+        this._areas.forEach(function (path) { path.attr(&quot;d&quot;, confidenceArea); });
+
+        var xScale = this._x;
+        var yScale = this._y;
+        this._dots.forEach(function (dot) {
+            dot
+                .attr(&quot;cx&quot;, function(measurement) { return xScale(measurement.time); })
+                .attr(&quot;cy&quot;, function(measurement) { return yScale(measurement.value); });
+        });
+
+        if (this._brush) {
+            if (selection)
+                this._brush.extent(selection);
+            else
+                this._brush.clear();
+            this._updateBrush();
+        }
+
+        this._updateCurrentItemIndicators();
+
+        if (this._xAxis)
+            this._xAxisLabels.call(this._xAxis);
+        if (!this._yAxis)
+            return;
+
+        this._yAxisLabels.call(this._yAxis);
+        if (this._yAxisUnitContainer)
+            this._yAxisUnitContainer.remove();
+        this._yAxisUnitContainer = this._yAxisLabels.append(&quot;text&quot;)
+            .attr(&quot;x&quot;, 0.5 * this._rem)
+            .attr(&quot;y&quot;, this._rem)
+            .attr(&quot;dy&quot;, '0.8rem')
+            .style(&quot;text-anchor&quot;, &quot;start&quot;)
+            .style(&quot;z-index&quot;, &quot;100&quot;)
+            .text(this._yAxisUnit);
+    },
+    _computeXAxisDomain: function (timeSeries)
+    {
+        var extent = d3.extent(timeSeries, function(point) { return point.time; });
+        var margin = 3600 * 1000; // Use x.inverse to compute the right amount from a margin.
+        return [+extent[0] - margin, +extent[1] + margin];
+    },
+    _computeYAxisDomain: function (startTime, endTime)
+    {
+        var range = this._minMaxForAllTimeSeries(startTime, endTime);
+        var min = range[0];
+        var max = range[1];
+        if (max &lt; min)
+            min = max = 0;
+        var diff = max - min;
+        var margin = diff * 0.05;
+
+        yExtent = [min - margin, max + margin];
+//        if (yMin !== undefined)
+//            yExtent[0] = parseInt(yMin);
+        return yExtent;
+    },
+    _minMaxForAllTimeSeries: function (startTime, endTime)
+    {
+        var currentRange = this._currentTimeSeries.minMaxForTimeRange(startTime, endTime);
+        var baselineRange = this._baselineTimeSeries ? this._baselineTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
+        var targetRange = this._targetTimeSeries ? this._targetTimeSeries.minMaxForTimeRange(startTime, endTime) : [Number.MAX_VALUE, Number.MIN_VALUE];
+        return [
+            Math.min(currentRange[0], baselineRange[0], targetRange[0]),
+            Math.max(currentRange[1], baselineRange[1], targetRange[1]),
+        ];
+    },
+    _currentSelection: function ()
+    {
+        return this._brush &amp;&amp; !this._brush.empty() ? this._brush.extent() : null;
+    },
+    _domainChanged: function ()
+    {
+        var selection = this._currentSelection() || this.get('sharedSelection');
+        var newXDomain = this._updateDomain();
+
+        if (selection &amp;&amp; newXDomain &amp;&amp; selection[0] &lt;= newXDomain[0] &amp;&amp; newXDomain[1] &lt;= selection[1])
+            selection = null; // Otherwise the user has no way of clearing the selection.
+
+        this._relayoutDataAndAxes(selection);
+    }.observes('domain'),
+    _selectionChanged: function ()
+    {
+        this._updateSelection(this.get('selection'));
+    }.observes('selection'),
+    _sharedSelectionChanged: function ()
+    {
+        if (this.get('selectionIsLocked'))
+            return;
+        this._updateSelection(this.get('sharedSelection'));
+    }.observes('sharedSelection'),
+    _updateSelection: function (newSelection)
+    {
+        if (!this._brush)
+            return;
+
+        var currentSelection = this._currentSelection();
+        if (newSelection &amp;&amp; currentSelection &amp;&amp; this._xDomainsAreSame(newSelection, currentSelection))
+            return;
+
+        var domain = this._x.domain();
+        if (!newSelection || this._xDomainsAreSame(domain, newSelection))
+            this._brush.clear();
+        else
+            this._brush.extent(newSelection);
+        this._updateBrush();
+
+        this._setCurrentSelection(newSelection);
+    },
+    _xDomainsAreSame: function (domain1, domain2)
+    {
+        return !(domain1[0] - domain2[0]) &amp;&amp; !(domain1[1] - domain2[1]);
+    },
+    _brushChanged: function ()
+    {
+        if (this._brush.empty()) {
+            if (!this._brushExtent)
+                return;
+
+            this.set('selectionIsLocked', false);
+            this._setCurrentSelection(undefined);
+
+            // Avoid locking the indicator in _mouseDown when the brush was cleared in the same mousedown event.
+            this._brushJustChanged = true;
+            var self = this;
+            setTimeout(function () {
+                self._brushJustChanged = false;
+            }, 0);
+
+            return;
+        }
+
+        this.set('selectionIsLocked', true);
+        this._setCurrentSelection(this._brush.extent());
+    },
+    _keyPressed: function (event)
+    {
+        if (!this._currentItemIndex || this._currentSelection())
+            return;
+
+        var newIndex;
+        switch (event.keyCode) {
+        case 37: // Left
+            newIndex = this._currentItemIndex - 1;
+            break;
+        case 39: // Right
+            newIndex = this._currentItemIndex + 1;
+            break;
+        case 38: // Up
+        case 40: // Down
+        default:
+            return;
+        }
+
+        // Unlike mousemove, keydown shouldn't move off the edge.
+        if (this._currentTimeSeriesData[newIndex])
+            this._setCurrentItem(newIndex);
+    },
+    _mouseMoved: function (event)
+    {
+        if (!this._margin || this._currentSelection() || this._currentItemLocked)
+            return;
+
+        var point = this._mousePointInGraph(event);
+
+        this._selectClosestPointToMouseAsCurrentItem(point);
+    },
+    _mouseLeft: function (event)
+    {
+        if (!this._margin || this._currentItemLocked)
+            return;
+
+        this._selectClosestPointToMouseAsCurrentItem(null);
+    },
+    _mouseDown: function (event)
+    {
+        if (!this._margin || this._currentSelection() || this._brushJustChanged)
+            return;
+
+        var point = this._mousePointInGraph(event);
+        if (!point)
+            return;
+
+        if (this._currentItemLocked) {
+            this._currentItemLocked = false;
+            this.set('selectedItem', null);
+            return;
+        }
+
+        this._currentItemLocked = true;
+        this._selectClosestPointToMouseAsCurrentItem(point);
+    },
+    _mousePointInGraph: function (event)
+    {
+        var offset = $(this.get('element')).offset();
+        if (!offset)
+            return null;
+
+        var point = {
+            x: event.pageX - offset.left - this._margin.left,
+            y: event.pageY - offset.top - this._margin.top
+        };
+
+        var xScale = this._x;
+        var yScale = this._y;
+        var xDomain = xScale.domain();
+        var yDomain = yScale.domain();
+        if (point.x &gt;= xScale(xDomain[0]) &amp;&amp; point.x &lt;= xScale(xDomain[1])
+            &amp;&amp; point.y &lt;= yScale(yDomain[0]) &amp;&amp; point.y &gt;= yScale(yDomain[1]))
+            return point;
+
+        return null;
+    },
+    _selectClosestPointToMouseAsCurrentItem: function (point)
+    {
+        var xScale = this._x;
+        var yScale = this._y;
+        var distanceHeuristics = function (m) {
+            var mX = xScale(m.time);
+            var mY = yScale(m.value);
+            var xDiff = mX - point.x;
+            var yDiff = mY - point.y;
+            return xDiff * xDiff + yDiff * yDiff / 16; // Favor horizontal affinity.
+        };
+        distanceHeuristics = function (m) {
+            return Math.abs(xScale(m.time) - point.x);
+        }
+
+        var newItemIndex;
+        if (point &amp;&amp; !this._currentSelection()) {
+            var distances = this._currentTimeSeriesData.map(distanceHeuristics);
+            var minDistance = Number.MAX_VALUE;
+            for (var i = 0; i &lt; distances.length; i++) {
+                if (distances[i] &lt; minDistance) {
+                    newItemIndex = i;
+                    minDistance = distances[i];
+                }
+            }
+        }
+
+        this._setCurrentItem(newItemIndex);
+        this._updateSelectionToolbar();
+    },
+    _currentTimeChanged: function ()
+    {
+        if (!this._margin || this._currentSelection() || this._currentItemLocked)
+            return
+
+        var currentTime = this.get('currentTime');
+        if (currentTime) {
+            for (var i = 0; i &lt; this._currentTimeSeriesData.length; i++) {
+                var point = this._currentTimeSeriesData[i];
+                if (point.time &gt;= currentTime) {
+                    this._setCurrentItem(i, /* doNotNotify */ true);
+                    return;
+                }
+            }
+        }
+        this._setCurrentItem(undefined, /* doNotNotify */ true);
+    }.observes('currentTime'),
+    _setCurrentItem: function (newItemIndex, doNotNotify)
+    {
+        if (newItemIndex === this._currentItemIndex) {
+            if (this._currentItemLocked)
+                this.set('selectedItem', this.get('currentItem') ? this.get('currentItem').measurement.id() : null);
+            return;
+        }
+
+        var newItem = this._currentTimeSeriesData[newItemIndex];
+        this._brushExtent = undefined;
+        this._currentItemIndex = newItemIndex;
+
+        if (!newItem) {
+            this._currentItemLocked = false;
+            this.set('selectedItem', null);
+        }
+
+        this._updateCurrentItemIndicators();
+
+        if (!doNotNotify)
+            this.set('currentTime', newItem ? newItem.time : undefined);
+
+        this.set('currentItem', newItem);
+        if (this._currentItemLocked)
+            this.set('selectedItem', newItem ? newItem.measurement.id() : null);
+    },
+    _selectedItemChanged: function ()
+    {
+        if (!this._margin)
+            return;
+
+        var selectedId = this.get('selectedItem');
+        var currentItem = this.get('currentItem');
+        if (currentItem &amp;&amp; currentItem.measurement.id() == selectedId)
+            return;
+
+        var series = this._currentTimeSeriesData;
+        var selectedItemIndex = undefined;
+        for (var i = 0; i &lt; series.length; i++) {
+            if (series[i].measurement.id() == selectedId) {
+                this._updateSelection(null);
+                this._currentItemLocked = true;
+                this._setCurrentItem(i);
+                this._updateSelectionToolbar();
+                return;
+            }
+        }
+    }.observes('selectedItem').on('init'),
+    _updateCurrentItemIndicators: function ()
+    {
+        if (!this._currentItemLine)
+            return;
+
+        var item = this._currentTimeSeriesData[this._currentItemIndex];
+        if (!item) {
+            this._currentItemLine.attr(&quot;x1&quot;, -1000).attr(&quot;x2&quot;, -1000);
+            this._currentItemCircle.attr(&quot;cx&quot;, -1000);
+            return;
+        }
+
+        var x = this._x(item.time);
+        var y = this._y(item.value);
+
+        this._currentItemLine
+            .attr(&quot;x1&quot;, x)
+            .attr(&quot;x2&quot;, x);
+
+        this._currentItemCircle
+            .attr(&quot;cx&quot;, x)
+            .attr(&quot;cy&quot;, y);
+    },
+    _setCurrentSelection: function (newSelection)
+    {
+        if (this._brushExtent === newSelection)
+            return;
+
+        if (newSelection) {
+            var startPoint;
+            var endPoint;
+            for (var i = 0; i &lt; this._currentTimeSeriesData.length; i++) {
+                var point = this._currentTimeSeriesData[i];
+                if (!startPoint) {
+                    if (point.time &gt;= newSelection[0]) {
+                        if (point.time &gt; newSelection[1])
+                            break;
+                        startPoint = point;
+                    }
+                } else if (point.time &gt; newSelection[1])
+                    break;
+                if (point.time &gt;= newSelection[0] &amp;&amp; point.time &lt;= newSelection[1])
+                    endPoint = point;
+            }
+        }
+
+        this._brushExtent = newSelection;
+        this._setCurrentItem(undefined);
+        this._updateSelectionToolbar();
+
+        this.set('sharedSelection', newSelection);
+        this.sendAction('selectionChanged', newSelection, startPoint, endPoint);
+    },
+    _updateSelectionToolbar: function ()
+    {
+        if (!this.get('interactive'))
+            return;
+
+        var selection = this._currentSelection();
+        var selectionToolbar = $(this.get('element')).children('.selection-toolbar');
+        if (selection) {
+            var left = this._x(selection[0]);
+            var right = this._x(selection[1]);
+            selectionToolbar
+                .css({left: this._margin.left + right, top: this._margin.top + this._contentHeight})
+                .show();
+        } else
+            selectionToolbar.hide();
+    },
+    actions: {
+        zoom: function ()
+        {
+            this.sendAction('zoom', this._currentSelection());
+            this.set('selection', null);
+        },
+    },
+});
+
+
+
+App.CommitsViewerComponent = Ember.Component.extend({
+    repository: null,
+    revisionInfo: null,
+    commits: null,
+    commitsChanged: function ()
+    {
+        var revisionInfo = this.get('revisionInfo');
+
+        var to = revisionInfo.get('currentRevision');
+        var from = revisionInfo.get('previousRevision') || to;
+        var repository = this.get('repository');
+        if (!from || !repository)
+            return;
+
+        var self = this;
+        FetchCommitsForTimeRange(repository, from, to).then(function (commits) {
+            self.set('commits', commits.map(function (commit) {
+                return Ember.Object.create({
+                    repository: repository,
+                    revision: commit.revision,
+                    url: repository.urlForRevision(commit.revision),
+                    author: commit.author.name || commit.author.email,
+                    message: commit.message ? commit.message.substr(0, 75) : null,
+                });
+            }));
+        }, function () {
+            self.set('commits', []);
+        })
+    }.observes('repository').observes('revisionInfo').on('init'),
+});
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/app.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2chartpanecss"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/chart-pane.css (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/chart-pane.css                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/chart-pane.css        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,236 @@
</span><ins>+.chart-pane {
+    border: 1px solid #bbb;
+    border-radius: 0.5rem;
+    box-shadow: rgba(0, 0, 0, 0.03) 1px 1px 0px 0px;
+    padding: 0;
+    margin-bottom: 1rem;
+    outline: none;
+}
+.chart-pane header {
+    background: #fff;
+    margin: 0;
+    padding: 0.5rem;
+    color: #000;
+    border-bottom: 1px solid #bbb;
+    border-top-left-radius: 0.5rem;
+    border-top-right-radius: 0.5rem;
+    position: relative;
+}
+.chart-pane h1 {
+    color: #333;
+    font-size: 1rem;
+    font-weight: normal;
+    line-height: 1rem;
+    margin: 0 0 0 1.5rem;
+    padding: 0;
+}
+.chart-pane:focus header {
+    background-color: rgba(204, 153, 51, 0.1);
+    color: #333;
+}
+
+.chart-pane .progress {
+    height: 100%;
+    position: relative;
+}
+
+.chart-pane .progress .spinner {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    margin-left: -1rem;
+    margin-top: -1rem;
+}
+
+.chart-pane a.close-button {
+    display: inline-block;
+    position: absolute;
+    left: 0.55rem;
+    top: 0.55rem;
+}
+
+.chart-pane .body {
+    position: relative;
+    width: 100%;
+    height: 18rem;
+}
+.chart-pane .svg-container {
+    width: auto;
+    height: 100%;
+}
+.chart-pane .svg-container {
+    margin-right: 25rem;
+}
+
+.selection-toolbar {
+    display: inline-block;
+    background: white;
+    border: solid 1px #d9d9d9;
+    border-radius: 0.3rem;
+    z-index: 10;
+    position: absolute;
+    margin-top: -2rem;
+    margin-left: 0.5rem;
+    white-space: nowrap;
+}
+
+.selection-toolbar .button {
+    display: block;
+    float: left;
+    width: 1rem;
+    height: 1rem;
+    padding: 0.2rem;
+    margin: 0;
+    border-left: solid 1px #bbb;
+}
+
+.selection-toolbar .button:first-child {
+    border-left: none;
+}
+
+.selection-toolbar .button svg {
+    stroke: #666;
+    fill: #666;
+}
+
+.chart-pane .details {
+    position: absolute;
+    right: 0;
+    top: 0;
+    width: 25rem;
+    height: 100%;
+    border-left: solid 1px #bbb;
+}
+
+.chart-pane .overview {
+    height: 5rem;
+    border-bottom: solid 0px #eee;
+}
+
+.chart-pane .details-table-container {
+    position: absolute;
+    top: 5rem;
+    width: 100%;
+    height: 13rem;
+    overflow: scroll;
+}
+
+.chart-pane .details-table {
+    font-size: 0.8rem;
+    width: 100%;
+    table-layout: fixed;
+    border-collapse: collapse;
+}
+
+.chart-pane .details-table td:last-child {
+    padding-right: 1px;
+}
+
+.chart-pane .details-table td table {
+    border-collapse: collapse;
+}
+
+.chart-pane .details-table td table td {
+    word-break: break-word;
+    border-top: solid 1px #ccc;
+    padding: 0.2rem;
+}
+
+.chart-pane .details-table td table td a {
+    text-decoration: none;
+}
+
+.chart-pane .details-table th {
+    width: 4rem;
+    text-align: right;
+    font-weight: normal;
+    padding: 0;
+}
+
+.chart-pane .details-table th:after {
+    content: &quot; : &quot;;
+}
+
+.chart-pane .chart {
+    height: 100%;
+}
+
+.chart-pane .chart svg {
+    height: 100%;
+}
+
+.chart {
+    position: relative;
+    overflow: hidden;
+}
+
+.chart svg {
+    stroke: #666;
+    fill: #000;
+    color: #000;
+    font-size: 0.7rem;
+}
+
+.chart path {
+    fill: none;
+    stroke-width: 1.5px;
+}
+
+.chart .commit-time-line {
+    stroke: #999;
+}
+
+.chart .dot {
+    fill: #666;
+    stroke: none;
+}
+
+.chart path.area {
+    stroke: none;
+    fill: #ccc;
+    opacity: 0.8;
+}
+
+.chart path.area.baseline {
+    stroke: #f66;
+    fill: #fdd;
+    opacity: 0.4;
+}
+
+.chart path.area.target {
+    stroke: #66f;
+    fill: #ddf;
+    opacity: 0.4;
+}
+
+.chart .axis,
+.chart .domain {
+  fill: none;
+  stroke-width: 1px;
+  stroke: #ddd;
+  color: #000;
+  shape-rendering: crispEdges;
+}
+
+.chart .domain {
+    stroke: none;
+}
+
+.chart .current-item {
+    stroke: #f93;
+    stroke-width: 2px;
+    fill: #f93;
+}
+
+.chart .extent {
+    stroke: #9c6;
+    stroke-width: 1px;
+    fill: #9c6;
+    fill-opacity: .125;
+    shape-rendering: crispEdges;
+}
+
+.chart .axis text {
+    fill: #333;
+    stroke: none;
+}
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/chart-pane.css
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2datajs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/data.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/data.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/data.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,268 @@
</span><ins>+// We don't use DS.Model for these object types because we can't afford to process millions of them.
+
+FetchCommitsForTimeRange = function (repository, from, to)
+{
+    var url = '../api/commits/' + repository.get('id') + '/' + from + '-' + to;
+    console.log('Fetching ' + url)
+    return new Ember.RSVP.Promise(function (resolve, reject) {
+        $.getJSON(url, function (data) {
+            if (data.status != 'OK') {
+                reject(data.status);
+                return;
+            }
+            resolve(data.commits);
+        }).fail(function (xhr, status, error) {
+            reject(xhr.status + (error ? ', ' + error : ''));
+        })
+    });
+}
+
+function Measurement(rawData)
+{
+    this._raw = rawData;
+
+    var latestTime = -1;
+    var revisions = this._raw['revisions'];
+    // FIXME: Fix this in the server side.
+    if (Array.isArray(revisions))
+        revisions = {};
+    this._raw['revisions'] = revisions;
+
+    for (var repositoryName in revisions) {
+        var commitTimeOrUndefined = revisions[repositoryName][1]; // e.g. [&quot;162190&quot;, 1389945046000]
+        if (latestTime &lt; commitTimeOrUndefined)
+            latestTime = commitTimeOrUndefined;
+    }
+    this._latestCommitTime = latestTime !== -1 ? new Date(latestTime) : null;
+    this._buildTime = new Date(this._raw['buildTime']);
+    this._confidenceInterval = undefined;
+    this._formattedRevisions = undefined;
+}
+
+Measurement.prototype.formattedRevisions = function (previousMeasurement)
+{
+    var revisions = this._raw['revisions'];
+    var previousRevisions = previousMeasurement ? previousMeasurement._raw['revisions'] : null;
+    var formattedRevisions = {};
+    for (var repositoryName in revisions) {
+        var currentRevision = revisions[repositoryName][0];
+        var commitTimeInPOSIX = revisions[repositoryName][1];
+
+        var previousRevision = previousRevisions ? previousRevisions[repositoryName][0] : null;
+
+        var formatttedRevision = this._formatRevisionRange(previousRevision, currentRevision);
+        if (commitTimeInPOSIX)
+            formatttedRevision['commitTime'] = new Date(commitTimeInPOSIX);
+        formattedRevisions[repositoryName] = formatttedRevision;
+    }
+
+    return formattedRevisions;
+}
+
+Measurement.prototype._formatRevisionRange = function (previousRevision, currentRevision)
+{
+    var revisionChanged = false;
+    if (previousRevision == currentRevision)
+        previousRevision = null;
+    else
+        revisionChanged = true;
+
+    var revisionPrefix = '';
+    var revisionDelimiter = '-';
+    var label = '';
+    if (parseInt(currentRevision) == currentRevision) { // e.g. r12345.
+        currentRevision = parseInt(currentRevision);
+        revisionPrefix = 'r';
+        if (previousRevision)
+            previousRevision = (parseInt(previousRevision) + 1);
+    } else if (currentRevision.indexOf(' ') &gt;= 0) // e.g. 10.9 13C64.
+        revisionDelimiter = ' - ';
+    else if (currentRevision.length == 40) { // e.g. git hash
+        formattedCurrentHash = currentRevision.substring(0, 8);
+        if (previousRevision)
+            label = previousRevision.substring(0, 8) + '..' + formattedCurrentHash;
+        else
+            label = 'At ' + formattedCurrentHash;
+    }
+
+    if (!label) {
+        if (previousRevision)
+            label = revisionPrefix + previousRevision + revisionDelimiter + revisionPrefix + currentRevision;
+        else
+            label = 'At ' + revisionPrefix + currentRevision;
+    }
+
+    return {
+        label: label,
+        previousRevision: previousRevision,
+        currentRevision: currentRevision,
+        revisionChanged: revisionChanged
+    };
+}
+
+Measurement.prototype.id = function ()
+{
+    return this._raw['id'];
+}
+
+Measurement.prototype.mean = function()
+{
+    return this._raw['mean'];
+}
+
+Measurement.prototype.confidenceInterval = function()
+{
+    if (this._confidenceInterval === undefined) {
+        var delta = Statistics.confidenceIntervalDelta(0.95, this._raw[&quot;iterationCount&quot;], this._raw[&quot;sum&quot;], this._raw[&quot;squareSum&quot;]);
+        var mean = this.mean();
+        this._confidenceInterval = isNaN(delta) ? null : [mean - delta, mean + delta];
+    }
+    return this._confidenceInterval;
+}
+
+Measurement.prototype.latestCommitTime = function()
+{
+    return this._latestCommitTime || this._buildTime;
+}
+
+Measurement.prototype.buildNumber = function ()
+{
+    return this._raw['buildNumber'];
+}
+
+Measurement.prototype.builderId = function ()
+{
+    return this._raw['builder'];
+}
+
+Measurement.prototype.buildTime = function()
+{
+    return this._buildTime;
+}
+
+Measurement.prototype.formattedBuildTime = function ()
+{
+    return Measurement._formatDate(this.buildTime());
+}
+
+Measurement._formatDate = function (date)
+{
+    return date.toISOString().replace('T', ' ').replace(/\.\d+Z$/, '');
+}
+
+function RunsData(rawData)
+{
+    this._measurements = rawData.map(function (run) { return new Measurement(run); });
+}
+
+RunsData.prototype.count = function ()
+{
+    return this._measurements.length;
+}
+
+RunsData.prototype.timeSeriesByCommitTime = function ()
+{
+    return new TimeSeries(this._measurements.map(function (measurement) {
+        var confidenceInterval = measurement.confidenceInterval();
+        return {
+            measurement: measurement,
+            time: measurement.latestCommitTime(),
+            value: measurement.mean(),
+            interval: measurement.confidenceInterval(),
+        };
+    }));
+}
+
+RunsData.prototype.timeSeriesByBuildTime = function ()
+{
+    return new TimeSeries(this._measurements.map(function (measurement) {
+        return {
+            measurement: measurement,
+            time: measurement.buildTime(),
+            value: measurement.mean(),
+            interval: measurement.confidenceInterval(),
+        };
+    }));
+}
+
+// FIXME: We need to devise a way to fetch runs in multiple chunks so that
+// we don't have to fetch the entire time series to just show the last 3 days.
+RunsData.fetchRuns = function (platformId, metricId)
+{
+    var filename = platformId + '-' + metricId + '.json';
+
+    return new Ember.RSVP.Promise(function (resolve, reject) {
+        $.getJSON('../api/runs/' + filename, function (data) {
+            if (data.status != 'OK') {
+                reject(data.status);
+                return;
+            }
+            delete data.status;
+
+            for (var config in data)
+                data[config] = new RunsData(data[config]);
+
+            resolve(data);
+        }).fail(function (xhr, status, error) {
+            reject(xhr.status + (error ? ', ' + error : ''));
+        })
+    });
+}
+
+function TimeSeries(series)
+{
+    this._series = series.sort(function (a, b) { return a.time - b.time; });
+    var self = this;
+    var min = undefined;
+    var max = undefined;
+    this._series.forEach(function (point, index) {
+        point.series = self;
+        point.seriesIndex = index;
+        if (min === undefined || min &gt; point.value)
+            min = point.value;
+        if (max === undefined || max &lt; point.value)
+            max = point.value;
+    });
+    this._min = min;
+    this._max = max;
+}
+
+TimeSeries.prototype.minMaxForTimeRange = function (startTime, endTime)
+{
+    var data = this._series;
+    var i = 0;
+    if (startTime !== undefined) {
+        for (i = 0; i &lt; data.length; i++) {
+            var point = data[i];
+            if (point.time &gt;= startTime)
+                break;
+        }
+        if (i)
+            i--;
+    }
+    var min = Number.MAX_VALUE;
+    var max = Number.MIN_VALUE;
+    for (; i &lt; data.length; i++) {
+        var point = data[i];
+        var currentMin = point.interval ? point.interval[0] : point.value;
+        var currentMax = point.interval ? point.interval[1] : point.value;
+
+        if (currentMin &lt; min)
+            min = currentMin;
+        if (currentMax &gt; max)
+            max = currentMax;
+
+        if (point.time &gt;= endTime)
+            break;
+    }
+    return [min, max];
+}
+
+TimeSeries.prototype.series = function () { return this._series; }
+
+TimeSeries.prototype.previousPoint = function (point)
+{
+    if (!point.seriesIndex)
+        return null;
+    return this._series[point.seriesIndex - 1];
+}
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/data.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2indexhtml"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/index.html (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/index.html                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/index.html        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,348 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;meta charset=&quot;utf-8&quot;&gt;
+    &lt;title&gt;WebKit Performance Monitor (Beta)&lt;/title&gt;
+    &lt;script src=&quot;js/jquery.min.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;js/handlebars.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;js/ember.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;js/ember-data.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;js/d3/d3.min.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;js/statistics.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;data.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;app.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;manifest.js&quot; defer&gt;&lt;/script&gt;
+    &lt;script src=&quot;popup.js&quot; defer&gt;&lt;/script&gt;
+    &lt;link rel=&quot;stylesheet&quot; href=&quot;app.css&quot;&gt;
+    &lt;link rel=&quot;stylesheet&quot; href=&quot;chart-pane.css&quot;&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;index&quot;&gt;
+        &lt;header id=&quot;header&quot;&gt;
+            {{partial &quot;navbar&quot;}}
+            {{view App.NumberOfDaysControlView tagName=&quot;ul&quot; numberOfDays=numberOfDays}}
+            &lt;ul class=&quot;controls&quot;&gt;
+                &lt;li&gt;
+                    &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action toggleEditMode}}&gt;
+                        {{#if controller.editMode}}
+                            Finish editing
+                        {{else}}
+                            Edit
+                        {{/if}}
+                    &lt;/a&gt;
+                &lt;/li&gt;
+            &lt;/ul&gt;
+        &lt;/header&gt;
+
+        &lt;table {{bind-attr class=&quot;:dashboard editMode:editMode:readonly&quot;}}&gt;
+        &lt;thead&gt;
+            &lt;tr&gt;
+                &lt;td&gt;&lt;/td&gt;
+                {{#each headerColumns}}
+                    {{#if controller.editMode}}
+                        &lt;th&gt;
+                            &lt;a href=&quot;#&quot; title=&quot;Remove column&quot; {{action &quot;removeColumn&quot; index}}&gt;
+                                {{partial &quot;close-button&quot;}}
+                            &lt;/a&gt;
+                            {{input value=label}}
+                        &lt;/th&gt;
+                    {{else}}
+                        &lt;th&gt;{{label}}&lt;/th&gt;
+                    {{/if}}
+                {{/each}}
+                {{#if controller.editMode}}
+                    &lt;td&gt;{{input value=newColumnHeader action=&quot;addColumn&quot; placeholder=&quot;Add a column&quot;}}&lt;/td&gt;
+                {{/if}}
+            &lt;/tr&gt;
+        &lt;/thead&gt;
+        &lt;tbody&gt;
+            {{#each rows}}
+                &lt;tr&gt;
+                    {{#if controller.editMode}}
+                        &lt;th&gt;
+                            &lt;a href=&quot;#&quot; title=&quot;Remove row&quot; {{action &quot;removeRow&quot; this}}&gt;
+                                {{partial &quot;close-button&quot;}}
+                            &lt;/a&gt;
+                            {{input value=header}}
+                        &lt;/th&gt;
+                    {{else}}
+                        &lt;th&gt;&lt;span class=&quot;label&quot;&gt;{{header}}&lt;/span&gt;&lt;/th&gt;
+                    {{/if}}
+                    {{#each cells}}
+                        &lt;td&gt;
+                            {{#if empty}}
+                                {{#if controller.editMode}}
+                                    {{view App.PopupView list=pickerData label='Choose'}}
+                                {{/if}}
+                            {{else}}
+                                {{#if chartData}}
+                                    {{#link-to 'charts' (query-params paneList=paneList)}}
+                                    {{interactive-chart
+                                        chartData=chartData
+                                        domain=controller.sharedDomain
+                                        enableSelection=false}}
+                                    {{/link-to}}
+                                {{else}}
+                                    {{#if failure}}
+                                        &lt;div class=&quot;failure&quot;&gt;{{failure}}&lt;/div&gt;
+                                    {{else}}
+                                        &lt;div class=&quot;progress&quot;&gt;{{partial &quot;spinner&quot;}}&lt;/div&gt;
+                                    {{/if}}
+                                {{/if}}
+                                {{#if controller.editMode}}
+                                    &lt;a href=&quot;#&quot; title=&quot;Reset pane&quot; class=&quot;reset&quot; {{action &quot;resetPane&quot; this}}&gt;
+                                        {{partial &quot;close-button&quot;}}
+                                    &lt;/a&gt;
+                                {{/if}}
+                            {{/if}}
+                        &lt;/td&gt;
+                    {{/each}}
+                    {{#if controller.editMode}}
+                        &lt;td&gt;&lt;/td&gt;
+                    {{/if}}
+                &lt;/tr&gt;
+            {{/each}}
+            {{#if controller.editMode}}
+                &lt;tr&gt;
+                    &lt;td&gt;{{input value=newRowHeader action=&quot;addRow&quot; placeholder=&quot;Add a row&quot;}}&lt;/td&gt;
+                    {{#each emptyRow}}
+                        &lt;td&gt;&lt;/td&gt;
+                    {{/each}}
+                    &lt;td&gt;&lt;/td&gt;
+                &lt;/tr&gt;
+            {{/if}}
+        &lt;/tbody&gt;
+        &lt;/table&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;charts&quot;&gt;
+        &lt;header id=&quot;header&quot;&gt;
+            {{partial &quot;navbar&quot;}}
+            &lt;ul class=&quot;controls&quot;&gt;
+                &lt;li&gt;{{view App.PopupView list=platforms label='Add pane'}}&lt;/li&gt;
+            &lt;/ul&gt;
+            &lt;ul class=&quot;controls&quot;&gt;
+                &lt;li&gt;{{view App.StartTimeSliderView startTime=startTime oldestStartTime=oldestStartTime}}&lt;/li&gt;
+            &lt;/ul&gt;
+        &lt;/header&gt;
+
+        {{#each panes itemController=&quot;pane&quot;}}
+            &lt;section class=&quot;chart-pane&quot; tabindex=&quot;0&quot;&gt;
+                &lt;header&gt;
+                    &lt;h1 {{action &quot;toggleDetails&quot;}}&gt;
+                    {{#each metric.path}}
+                        {{this}} &amp;ni;
+                    {{/each}}
+                    {{metric.label}}
+                    - {{ platform.name}}&lt;/h2&gt;
+                    &lt;a href=&quot;#&quot; title=&quot;Close&quot; class=&quot;close-button&quot; {{action &quot;close&quot;}}&gt;{{partial &quot;close-button&quot;}}&lt;/a&gt;
+                &lt;/header&gt;
+
+                &lt;div {{bind-attr class=&quot;:body showingDetails&quot;}}&gt;
+                    &lt;div class=&quot;svg-container&quot;&gt;
+                    {{#if chartData}}
+                        {{interactive-chart
+                            chartData=chartData
+                            domain=mainPlotDomain
+                            interactive=true
+                            currentItem=currentItem
+                            currentTime=sharedTime
+                            selectedItem=selectedItem
+                            selection=timeRange
+                            sharedSelection=sharedSelection
+                            selectionChanged=&quot;rangeChanged&quot;
+                            selectionIsLocked=timeRangeIsLocked
+                            zoom=&quot;zoomed&quot;}}
+                    {{else}}
+                        {{#if failure}}
+                            &lt;div class=&quot;failure&quot;&gt;{{failure}}&lt;/div&gt;
+                        {{else}}
+                            &lt;div class=&quot;progress&quot;&gt;{{partial &quot;spinner&quot;}}&lt;/div&gt;
+                        {{/if}}
+                    {{/if}}
+                    &lt;/div&gt;
+                    &lt;div class=&quot;details&quot;&gt;
+                        &lt;div class=&quot;overview&quot;&gt;
+                        {{#if chartData}}
+                            {{interactive-chart
+                                chartData=chartData
+                                showYAxis=false
+                                domain=overviewDomain
+                                domainChanged=&quot;overviewDomainChanged&quot;
+                                selection=mainPlotDomain
+                                selectionChanged=&quot;zoomed&quot;}}
+                        {{/if}}
+                        &lt;/div&gt;
+                        {{#if details}}
+                            {{partial &quot;chart-details&quot;}}
+                        {{/if}}
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/section&gt;
+        {{/each}}
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;components/interactive-chart&quot;&gt;
+        {{#if interactive}}
+            &lt;div class=&quot;selection-toolbar&quot; style=&quot;display: none;&quot;&gt;
+                &lt;a href=&quot;#&quot; class=&quot;button&quot; {{action &quot;zoom&quot;}}&gt;
+                    &lt;svg class=&quot;zoom&quot; viewBox=&quot;0 0 100 100&quot;&gt;
+                        &lt;g stroke-width=&quot;0&quot; stroke=&quot;none&quot;&gt;
+                            &lt;polygon points=&quot;25,25 5,50 25,75&quot;/&gt;
+                            &lt;polygon points=&quot;75,25 95,50 75,75&quot;/&gt;
+                        &lt;/g&gt;
+                        &lt;line x1=&quot;20&quot; y1=&quot;50&quot; x2=&quot;80&quot; y2=&quot;50&quot; stroke-width=&quot;10&quot;&gt;&lt;/line&gt;
+                    &lt;/svg&gt;
+                &lt;/a&gt;
+            &lt;/div&gt;
+        {{/if}}
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;chart-details&quot;&gt;
+    &lt;div class=&quot;details-table-container&quot;&gt;
+        &lt;table class=&quot;details-table&quot;&gt;
+            &lt;tr&gt;&lt;th&gt;Current&lt;/th&gt;&lt;td&gt;{{details.currentValue}} {{chartData.unit}}
+            {{#if details.oldValue}}
+                (from {{details.oldValue}})
+            {{/if}}&lt;/td&gt;&lt;/tr&gt;
+            {{#if details.buildNumber}}
+                &lt;tr&gt;
+                    &lt;th&gt;Build&lt;/th&gt;
+                    &lt;td&gt;
+                        {{#if details.buildURL}}
+                            &lt;a {{bind-attr href=details.buildURL}} target=&quot;_blank&quot;&gt;{{details.buildNumber}}&lt;/a&gt;
+                        {{else}}
+                            {{details.buildNumber}}
+                        {{/if}}
+                        ({{details.buildTime}})
+                    &lt;/td&gt;
+                &lt;/tr&gt;
+            {{/if}}
+            {{#each details.revisions}}
+                &lt;tr&gt;
+                    &lt;th&gt;{{name}}&lt;/th&gt;
+                    &lt;td&gt;
+                        {{#if url}}
+                            &lt;a {{bind-attr href=url}} target=&quot;_blank&quot;&gt;{{label}}&lt;/a&gt;
+                        {{else}}
+                            {{label}}
+                        {{/if}}
+                    &lt;/td&gt;
+                &lt;/tr&gt;
+                &lt;tr&gt;
+                    &lt;td colspan=&quot;2&quot;&gt;{{commits-viewer repository=repository revisionInfo=this}}&lt;/td&gt;
+                &lt;/tr&gt;
+            {{/each}}
+        &lt;/table&gt;
+    &lt;/div&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;components/commits-viewer&quot;&gt;
+    {{#if commits}}
+        &lt;table&gt;
+            &lt;tbody&gt;
+                {{#each commits}}
+                    &lt;tr&gt;
+                        &lt;td&gt;
+                            {{#if url}}
+                                &lt;a {{bind-attr href=url}} target=&quot;_blank&quot;&gt;{{author}}&lt;/a&gt;
+                            {{else}}
+                                {{author}}
+                            {{/if}}
+                        &lt;/td&gt;
+                        &lt;td&gt;{{message}}&lt;/td&gt;
+                    &lt;/tr&gt;
+                {{/each}}
+            &lt;/tbody&gt;
+        &lt;/table&gt;
+    {{/if}}
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;close-button&quot;&gt;
+        &lt;svg class=&quot;close-button&quot; viewBox=&quot;0 0 100 100&quot;&gt;
+            &lt;g stroke=&quot;black&quot; stroke-width=&quot;10&quot;&gt;
+                &lt;circle cx=&quot;50&quot; cy=&quot;50&quot; r=&quot;45&quot; fill=&quot;transparent&quot;/&gt;
+                &lt;polygon points=&quot;30,30 70,70&quot; /&gt;
+                &lt;polygon points=&quot;30,70 70,30&quot; /&gt;
+            &lt;/g&gt;
+        &lt;/svg&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;spinner&quot;&gt;
+        &lt;svg class=&quot;spinner&quot; viewBox=&quot;0 0 100 100&quot;&gt;
+            &lt;line x1=&quot;10&quot; y1=&quot;50&quot; x2=&quot;30&quot; y2=&quot;50&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;21.72&quot; y1=&quot;21.72&quot; x2=&quot;35.86&quot; y2=&quot;35.86&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;50&quot; y1=&quot;10&quot; x2=&quot;50&quot; y2=&quot;30&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;78.28&quot; y1=&quot;21.72&quot; x2=&quot;64.14&quot; y2=&quot;35.86&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;70&quot; y1=&quot;50&quot; x2=&quot;90&quot; y2=&quot;50&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;65.86&quot; y1=&quot;65.86&quot; x2=&quot;78.28&quot; y2=&quot;78.28&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;50&quot; y1=&quot;70&quot; x2=&quot;50&quot; y2=&quot;90&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+            &lt;line x1=&quot;21.72&quot; y1=&quot;78.28&quot; x2=&quot;35.86&quot; y2=&quot;65.86&quot; stroke=&quot;black&quot; stroke-width=&quot;10&quot; stroke-linecap=&quot;round&quot;/&gt;
+        &lt;/svg&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;navbar&quot;&gt;
+        &lt;nav id=&quot;navigation&quot; role=&quot;navigation&quot;&gt;
+            &lt;h1&gt;&lt;a href=&quot;#&quot;&gt;WebKit Perf Monitor&lt;/a&gt;&lt;/h1&gt;
+            &lt;ul&gt;
+                {{#link-to 'index' tagName='li'}}
+                    {{#link-to 'index'}}Dashboard{{/link-to}}
+                {{/link-to}}
+                {{#link-to 'charts' tagName='li'}}
+                    {{#link-to 'charts'}}Charts{{/link-to}}
+                {{/link-to}}
+            &lt;/ul&gt;
+        &lt;/nav&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;number-of-days-controls&quot;&gt;
+        &lt;li class=&quot;numberOfDaysIs1&quot;&gt;
+            &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action &quot;setNumberOfDays&quot; 1}}&gt;1D&lt;/a&gt;
+        &lt;/li&gt;
+        &lt;li class=&quot;numberOfDaysIs7&quot;&gt;
+            &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action &quot;setNumberOfDays&quot; 7}}&gt;1W&lt;/a&gt;
+        &lt;/li&gt;
+        &lt;li class=&quot;numberOfDaysIs30&quot;&gt;
+            &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action &quot;setNumberOfDays&quot; 30}}&gt;1M&lt;/a&gt;
+        &lt;/li&gt;
+        &lt;li class=&quot;numberOfDaysIs90&quot;&gt;
+            &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action &quot;setNumberOfDays&quot; 90}}&gt;3M&lt;/a&gt;
+        &lt;/li&gt;
+        &lt;li class=&quot;numberOfDaysIs183&quot;&gt;
+            &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action &quot;setNumberOfDays&quot; 183}}&gt;6M&lt;/a&gt;
+        &lt;/li&gt;
+        &lt;li class=&quot;numberOfDaysIs365&quot;&gt;
+            &lt;a href=&quot;#&quot; class=&quot;control-button&quot; {{action &quot;setNumberOfDays&quot; 365}}&gt;1Y&lt;/a&gt;
+        &lt;/li&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;start-time-slider&quot;&gt;
+        &lt;label&gt;&lt;input type=&quot;range&quot;&gt; &lt;span class=&quot;numberOfDays&quot;&gt;X&lt;/span&gt; days&lt;/label&gt;
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;popup&quot;&gt;
+        &lt;span class=&quot;label&quot;&gt;{{view App.PopupButtonView tagName=&quot;a&quot; label=view.label }}&lt;/span&gt;
+        {{view view.popupListContainerView viewName=&quot;popupListContainerViewInstance&quot;}}
+    &lt;/script&gt;
+
+    &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;popup-list&quot;&gt;
+        {{#each view.list}}
+            {{#if isSeparator}}
+                &lt;li&gt;&lt;hr&gt;&lt;/li&gt;
+            {{else }} {{#if children}}
+                &lt;li&gt;{{view App.PopupView list=children label=label}}&lt;/li&gt;
+            {{else}}
+                &lt;li&gt;
+                    {{#if actionName}}
+                        &lt;a href=&quot;#&quot; class=&quot;label&quot; {{action actionName actionArgument}}&gt;{{label}}&lt;/a&gt;
+                    {{else}}
+                        &lt;a class=&quot;label&quot;&gt;{{label}}&lt;/a&gt;
+                    {{/if}}
+                &lt;/li&gt;
+            {{/if}} {{/if}}
+        {{/each}}
+    &lt;/script&gt;
+
+&lt;/head&gt;
+&lt;body&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/index.html
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsd3LICENSE"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/d3/LICENSE (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/d3/LICENSE                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/d3/LICENSE        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+Copyright (c) 2010-2014, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/d3/LICENSE
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsd3d3js"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,9233 @@
</span><ins>+!function() {
+  var d3 = {
+    version: &quot;3.4.11&quot;
+  };
+  if (!Date.now) Date.now = function() {
+    return +new Date();
+  };
+  var d3_arraySlice = [].slice, d3_array = function(list) {
+    return d3_arraySlice.call(list);
+  };
+  var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window;
+  try {
+    d3_array(d3_documentElement.childNodes)[0].nodeType;
+  } catch (e) {
+    d3_array = function(list) {
+      var i = list.length, array = new Array(i);
+      while (i--) array[i] = list[i];
+      return array;
+    };
+  }
+  try {
+    d3_document.createElement(&quot;div&quot;).style.setProperty(&quot;opacity&quot;, 0, &quot;&quot;);
+  } catch (error) {
+    var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
+    d3_element_prototype.setAttribute = function(name, value) {
+      d3_element_setAttribute.call(this, name, value + &quot;&quot;);
+    };
+    d3_element_prototype.setAttributeNS = function(space, local, value) {
+      d3_element_setAttributeNS.call(this, space, local, value + &quot;&quot;);
+    };
+    d3_style_prototype.setProperty = function(name, value, priority) {
+      d3_style_setProperty.call(this, name, value + &quot;&quot;, priority);
+    };
+  }
+  d3.ascending = d3_ascending;
+  function d3_ascending(a, b) {
+    return a &lt; b ? -1 : a &gt; b ? 1 : a &gt;= b ? 0 : NaN;
+  }
+  d3.descending = function(a, b) {
+    return b &lt; a ? -1 : b &gt; a ? 1 : b &gt;= a ? 0 : NaN;
+  };
+  d3.min = function(array, f) {
+    var i = -1, n = array.length, a, b;
+    if (arguments.length === 1) {
+      while (++i &lt; n &amp;&amp; !((a = array[i]) != null &amp;&amp; a &lt;= a)) a = undefined;
+      while (++i &lt; n) if ((b = array[i]) != null &amp;&amp; a &gt; b) a = b;
+    } else {
+      while (++i &lt; n &amp;&amp; !((a = f.call(array, array[i], i)) != null &amp;&amp; a &lt;= a)) a = undefined;
+      while (++i &lt; n) if ((b = f.call(array, array[i], i)) != null &amp;&amp; a &gt; b) a = b;
+    }
+    return a;
+  };
+  d3.max = function(array, f) {
+    var i = -1, n = array.length, a, b;
+    if (arguments.length === 1) {
+      while (++i &lt; n &amp;&amp; !((a = array[i]) != null &amp;&amp; a &lt;= a)) a = undefined;
+      while (++i &lt; n) if ((b = array[i]) != null &amp;&amp; b &gt; a) a = b;
+    } else {
+      while (++i &lt; n &amp;&amp; !((a = f.call(array, array[i], i)) != null &amp;&amp; a &lt;= a)) a = undefined;
+      while (++i &lt; n) if ((b = f.call(array, array[i], i)) != null &amp;&amp; b &gt; a) a = b;
+    }
+    return a;
+  };
+  d3.extent = function(array, f) {
+    var i = -1, n = array.length, a, b, c;
+    if (arguments.length === 1) {
+      while (++i &lt; n &amp;&amp; !((a = c = array[i]) != null &amp;&amp; a &lt;= a)) a = c = undefined;
+      while (++i &lt; n) if ((b = array[i]) != null) {
+        if (a &gt; b) a = b;
+        if (c &lt; b) c = b;
+      }
+    } else {
+      while (++i &lt; n &amp;&amp; !((a = c = f.call(array, array[i], i)) != null &amp;&amp; a &lt;= a)) a = undefined;
+      while (++i &lt; n) if ((b = f.call(array, array[i], i)) != null) {
+        if (a &gt; b) a = b;
+        if (c &lt; b) c = b;
+      }
+    }
+    return [ a, c ];
+  };
+  d3.sum = function(array, f) {
+    var s = 0, n = array.length, a, i = -1;
+    if (arguments.length === 1) {
+      while (++i &lt; n) if (!isNaN(a = +array[i])) s += a;
+    } else {
+      while (++i &lt; n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
+    }
+    return s;
+  };
+  function d3_number(x) {
+    return x != null &amp;&amp; !isNaN(x);
+  }
+  d3.mean = function(array, f) {
+    var s = 0, n = array.length, a, i = -1, j = n;
+    if (arguments.length === 1) {
+      while (++i &lt; n) if (d3_number(a = array[i])) s += a; else --j;
+    } else {
+      while (++i &lt; n) if (d3_number(a = f.call(array, array[i], i))) s += a; else --j;
+    }
+    return j ? s / j : undefined;
+  };
+  d3.quantile = function(values, p) {
+    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
+    return e ? v + e * (values[h] - v) : v;
+  };
+  d3.median = function(array, f) {
+    if (arguments.length &gt; 1) array = array.map(f);
+    array = array.filter(d3_number);
+    return array.length ? d3.quantile(array.sort(d3_ascending), .5) : undefined;
+  };
+  function d3_bisector(compare) {
+    return {
+      left: function(a, x, lo, hi) {
+        if (arguments.length &lt; 3) lo = 0;
+        if (arguments.length &lt; 4) hi = a.length;
+        while (lo &lt; hi) {
+          var mid = lo + hi &gt;&gt;&gt; 1;
+          if (compare(a[mid], x) &lt; 0) lo = mid + 1; else hi = mid;
+        }
+        return lo;
+      },
+      right: function(a, x, lo, hi) {
+        if (arguments.length &lt; 3) lo = 0;
+        if (arguments.length &lt; 4) hi = a.length;
+        while (lo &lt; hi) {
+          var mid = lo + hi &gt;&gt;&gt; 1;
+          if (compare(a[mid], x) &gt; 0) hi = mid; else lo = mid + 1;
+        }
+        return lo;
+      }
+    };
+  }
+  var d3_bisect = d3_bisector(d3_ascending);
+  d3.bisectLeft = d3_bisect.left;
+  d3.bisect = d3.bisectRight = d3_bisect.right;
+  d3.bisector = function(f) {
+    return d3_bisector(f.length === 1 ? function(d, x) {
+      return d3_ascending(f(d), x);
+    } : f);
+  };
+  d3.shuffle = function(array) {
+    var m = array.length, t, i;
+    while (m) {
+      i = Math.random() * m-- | 0;
+      t = array[m], array[m] = array[i], array[i] = t;
+    }
+    return array;
+  };
+  d3.permute = function(array, indexes) {
+    var i = indexes.length, permutes = new Array(i);
+    while (i--) permutes[i] = array[indexes[i]];
+    return permutes;
+  };
+  d3.pairs = function(array) {
+    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n &lt; 0 ? 0 : n);
+    while (i &lt; n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
+    return pairs;
+  };
+  d3.zip = function() {
+    if (!(n = arguments.length)) return [];
+    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i &lt; m; ) {
+      for (var j = -1, n, zip = zips[i] = new Array(n); ++j &lt; n; ) {
+        zip[j] = arguments[j][i];
+      }
+    }
+    return zips;
+  };
+  function d3_zipLength(d) {
+    return d.length;
+  }
+  d3.transpose = function(matrix) {
+    return d3.zip.apply(d3, matrix);
+  };
+  d3.keys = function(map) {
+    var keys = [];
+    for (var key in map) keys.push(key);
+    return keys;
+  };
+  d3.values = function(map) {
+    var values = [];
+    for (var key in map) values.push(map[key]);
+    return values;
+  };
+  d3.entries = function(map) {
+    var entries = [];
+    for (var key in map) entries.push({
+      key: key,
+      value: map[key]
+    });
+    return entries;
+  };
+  d3.merge = function(arrays) {
+    var n = arrays.length, m, i = -1, j = 0, merged, array;
+    while (++i &lt; n) j += arrays[i].length;
+    merged = new Array(j);
+    while (--n &gt;= 0) {
+      array = arrays[n];
+      m = array.length;
+      while (--m &gt;= 0) {
+        merged[--j] = array[m];
+      }
+    }
+    return merged;
+  };
+  var abs = Math.abs;
+  d3.range = function(start, stop, step) {
+    if (arguments.length &lt; 3) {
+      step = 1;
+      if (arguments.length &lt; 2) {
+        stop = start;
+        start = 0;
+      }
+    }
+    if ((stop - start) / step === Infinity) throw new Error(&quot;infinite range&quot;);
+    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
+    start *= k, stop *= k, step *= k;
+    if (step &lt; 0) while ((j = start + step * ++i) &gt; stop) range.push(j / k); else while ((j = start + step * ++i) &lt; stop) range.push(j / k);
+    return range;
+  };
+  function d3_range_integerScale(x) {
+    var k = 1;
+    while (x * k % 1) k *= 10;
+    return k;
+  }
+  function d3_class(ctor, properties) {
+    try {
+      for (var key in properties) {
+        Object.defineProperty(ctor.prototype, key, {
+          value: properties[key],
+          enumerable: false
+        });
+      }
+    } catch (e) {
+      ctor.prototype = properties;
+    }
+  }
+  d3.map = function(object) {
+    var map = new d3_Map();
+    if (object instanceof d3_Map) object.forEach(function(key, value) {
+      map.set(key, value);
+    }); else for (var key in object) map.set(key, object[key]);
+    return map;
+  };
+  function d3_Map() {}
+  d3_class(d3_Map, {
+    has: d3_map_has,
+    get: function(key) {
+      return this[d3_map_prefix + key];
+    },
+    set: function(key, value) {
+      return this[d3_map_prefix + key] = value;
+    },
+    remove: d3_map_remove,
+    keys: d3_map_keys,
+    values: function() {
+      var values = [];
+      this.forEach(function(key, value) {
+        values.push(value);
+      });
+      return values;
+    },
+    entries: function() {
+      var entries = [];
+      this.forEach(function(key, value) {
+        entries.push({
+          key: key,
+          value: value
+        });
+      });
+      return entries;
+    },
+    size: d3_map_size,
+    empty: d3_map_empty,
+    forEach: function(f) {
+      for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) f.call(this, key.substring(1), this[key]);
+    }
+  });
+  var d3_map_prefix = &quot;\x00&quot;, d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
+  function d3_map_has(key) {
+    return d3_map_prefix + key in this;
+  }
+  function d3_map_remove(key) {
+    key = d3_map_prefix + key;
+    return key in this &amp;&amp; delete this[key];
+  }
+  function d3_map_keys() {
+    var keys = [];
+    this.forEach(function(key) {
+      keys.push(key);
+    });
+    return keys;
+  }
+  function d3_map_size() {
+    var size = 0;
+    for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) ++size;
+    return size;
+  }
+  function d3_map_empty() {
+    for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) return false;
+    return true;
+  }
+  d3.nest = function() {
+    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
+    function map(mapType, array, depth) {
+      if (depth &gt;= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
+      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
+      while (++i &lt; n) {
+        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
+          values.push(object);
+        } else {
+          valuesByKey.set(keyValue, [ object ]);
+        }
+      }
+      if (mapType) {
+        object = mapType();
+        setter = function(keyValue, values) {
+          object.set(keyValue, map(mapType, values, depth));
+        };
+      } else {
+        object = {};
+        setter = function(keyValue, values) {
+          object[keyValue] = map(mapType, values, depth);
+        };
+      }
+      valuesByKey.forEach(setter);
+      return object;
+    }
+    function entries(map, depth) {
+      if (depth &gt;= keys.length) return map;
+      var array = [], sortKey = sortKeys[depth++];
+      map.forEach(function(key, keyMap) {
+        array.push({
+          key: key,
+          values: entries(keyMap, depth)
+        });
+      });
+      return sortKey ? array.sort(function(a, b) {
+        return sortKey(a.key, b.key);
+      }) : array;
+    }
+    nest.map = function(array, mapType) {
+      return map(mapType, array, 0);
+    };
+    nest.entries = function(array) {
+      return entries(map(d3.map, array, 0), 0);
+    };
+    nest.key = function(d) {
+      keys.push(d);
+      return nest;
+    };
+    nest.sortKeys = function(order) {
+      sortKeys[keys.length - 1] = order;
+      return nest;
+    };
+    nest.sortValues = function(order) {
+      sortValues = order;
+      return nest;
+    };
+    nest.rollup = function(f) {
+      rollup = f;
+      return nest;
+    };
+    return nest;
+  };
+  d3.set = function(array) {
+    var set = new d3_Set();
+    if (array) for (var i = 0, n = array.length; i &lt; n; ++i) set.add(array[i]);
+    return set;
+  };
+  function d3_Set() {}
+  d3_class(d3_Set, {
+    has: d3_map_has,
+    add: function(value) {
+      this[d3_map_prefix + value] = true;
+      return value;
+    },
+    remove: function(value) {
+      value = d3_map_prefix + value;
+      return value in this &amp;&amp; delete this[value];
+    },
+    values: d3_map_keys,
+    size: d3_map_size,
+    empty: d3_map_empty,
+    forEach: function(f) {
+      for (var value in this) if (value.charCodeAt(0) === d3_map_prefixCode) f.call(this, value.substring(1));
+    }
+  });
+  d3.behavior = {};
+  d3.rebind = function(target, source) {
+    var i = 1, n = arguments.length, method;
+    while (++i &lt; n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
+    return target;
+  };
+  function d3_rebind(target, source, method) {
+    return function() {
+      var value = method.apply(source, arguments);
+      return value === source ? target : value;
+    };
+  }
+  function d3_vendorSymbol(object, name) {
+    if (name in object) return name;
+    name = name.charAt(0).toUpperCase() + name.substring(1);
+    for (var i = 0, n = d3_vendorPrefixes.length; i &lt; n; ++i) {
+      var prefixName = d3_vendorPrefixes[i] + name;
+      if (prefixName in object) return prefixName;
+    }
+  }
+  var d3_vendorPrefixes = [ &quot;webkit&quot;, &quot;ms&quot;, &quot;moz&quot;, &quot;Moz&quot;, &quot;o&quot;, &quot;O&quot; ];
+  function d3_noop() {}
+  d3.dispatch = function() {
+    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
+    while (++i &lt; n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+    return dispatch;
+  };
+  function d3_dispatch() {}
+  d3_dispatch.prototype.on = function(type, listener) {
+    var i = type.indexOf(&quot;.&quot;), name = &quot;&quot;;
+    if (i &gt;= 0) {
+      name = type.substring(i + 1);
+      type = type.substring(0, i);
+    }
+    if (type) return arguments.length &lt; 2 ? this[type].on(name) : this[type].on(name, listener);
+    if (arguments.length === 2) {
+      if (listener == null) for (type in this) {
+        if (this.hasOwnProperty(type)) this[type].on(name, null);
+      }
+      return this;
+    }
+  };
+  function d3_dispatch_event(dispatch) {
+    var listeners = [], listenerByName = new d3_Map();
+    function event() {
+      var z = listeners, i = -1, n = z.length, l;
+      while (++i &lt; n) if (l = z[i].on) l.apply(this, arguments);
+      return dispatch;
+    }
+    event.on = function(name, listener) {
+      var l = listenerByName.get(name), i;
+      if (arguments.length &lt; 2) return l &amp;&amp; l.on;
+      if (l) {
+        l.on = null;
+        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
+        listenerByName.remove(name);
+      }
+      if (listener) listeners.push(listenerByName.set(name, {
+        on: listener
+      }));
+      return dispatch;
+    };
+    return event;
+  }
+  d3.event = null;
+  function d3_eventPreventDefault() {
+    d3.event.preventDefault();
+  }
+  function d3_eventSource() {
+    var e = d3.event, s;
+    while (s = e.sourceEvent) e = s;
+    return e;
+  }
+  function d3_eventDispatch(target) {
+    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
+    while (++i &lt; n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+    dispatch.of = function(thiz, argumentz) {
+      return function(e1) {
+        try {
+          var e0 = e1.sourceEvent = d3.event;
+          e1.target = target;
+          d3.event = e1;
+          dispatch[e1.type].apply(thiz, argumentz);
+        } finally {
+          d3.event = e0;
+        }
+      };
+    };
+    return dispatch;
+  }
+  d3.requote = function(s) {
+    return s.replace(d3_requote_re, &quot;\\$&amp;&quot;);
+  };
+  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+  var d3_subclass = {}.__proto__ ? function(object, prototype) {
+    object.__proto__ = prototype;
+  } : function(object, prototype) {
+    for (var property in prototype) object[property] = prototype[property];
+  };
+  function d3_selection(groups) {
+    d3_subclass(groups, d3_selectionPrototype);
+    return groups;
+  }
+  var d3_select = function(s, n) {
+    return n.querySelector(s);
+  }, d3_selectAll = function(s, n) {
+    return n.querySelectorAll(s);
+  }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, &quot;matchesSelector&quot;)], d3_selectMatches = function(n, s) {
+    return d3_selectMatcher.call(n, s);
+  };
+  if (typeof Sizzle === &quot;function&quot;) {
+    d3_select = function(s, n) {
+      return Sizzle(s, n)[0] || null;
+    };
+    d3_selectAll = Sizzle;
+    d3_selectMatches = Sizzle.matchesSelector;
+  }
+  d3.selection = function() {
+    return d3_selectionRoot;
+  };
+  var d3_selectionPrototype = d3.selection.prototype = [];
+  d3_selectionPrototype.select = function(selector) {
+    var subgroups = [], subgroup, subnode, group, node;
+    selector = d3_selection_selector(selector);
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = (group = this[j]).parentNode;
+      for (var i = -1, n = group.length; ++i &lt; n; ) {
+        if (node = group[i]) {
+          subgroup.push(subnode = selector.call(node, node.__data__, i, j));
+          if (subnode &amp;&amp; &quot;__data__&quot; in node) subnode.__data__ = node.__data__;
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_selector(selector) {
+    return typeof selector === &quot;function&quot; ? selector : function() {
+      return d3_select(selector, this);
+    };
+  }
+  d3_selectionPrototype.selectAll = function(selector) {
+    var subgroups = [], subgroup, node;
+    selector = d3_selection_selectorAll(selector);
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      for (var group = this[j], i = -1, n = group.length; ++i &lt; n; ) {
+        if (node = group[i]) {
+          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
+          subgroup.parentNode = node;
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_selectorAll(selector) {
+    return typeof selector === &quot;function&quot; ? selector : function() {
+      return d3_selectAll(selector, this);
+    };
+  }
+  var d3_nsPrefix = {
+    svg: &quot;http://www.w3.org/2000/svg&quot;,
+    xhtml: &quot;http://www.w3.org/1999/xhtml&quot;,
+    xlink: &quot;http://www.w3.org/1999/xlink&quot;,
+    xml: &quot;http://www.w3.org/XML/1998/namespace&quot;,
+    xmlns: &quot;http://www.w3.org/2000/xmlns/&quot;
+  };
+  d3.ns = {
+    prefix: d3_nsPrefix,
+    qualify: function(name) {
+      var i = name.indexOf(&quot;:&quot;), prefix = name;
+      if (i &gt;= 0) {
+        prefix = name.substring(0, i);
+        name = name.substring(i + 1);
+      }
+      return d3_nsPrefix.hasOwnProperty(prefix) ? {
+        space: d3_nsPrefix[prefix],
+        local: name
+      } : name;
+    }
+  };
+  d3_selectionPrototype.attr = function(name, value) {
+    if (arguments.length &lt; 2) {
+      if (typeof name === &quot;string&quot;) {
+        var node = this.node();
+        name = d3.ns.qualify(name);
+        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
+      }
+      for (value in name) this.each(d3_selection_attr(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_attr(name, value));
+  };
+  function d3_selection_attr(name, value) {
+    name = d3.ns.qualify(name);
+    function attrNull() {
+      this.removeAttribute(name);
+    }
+    function attrNullNS() {
+      this.removeAttributeNS(name.space, name.local);
+    }
+    function attrConstant() {
+      this.setAttribute(name, value);
+    }
+    function attrConstantNS() {
+      this.setAttributeNS(name.space, name.local, value);
+    }
+    function attrFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
+    }
+    function attrFunctionNS() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
+    }
+    return value == null ? name.local ? attrNullNS : attrNull : typeof value === &quot;function&quot; ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
+  }
+  function d3_collapse(s) {
+    return s.trim().replace(/\s+/g, &quot; &quot;);
+  }
+  d3_selectionPrototype.classed = function(name, value) {
+    if (arguments.length &lt; 2) {
+      if (typeof name === &quot;string&quot;) {
+        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
+        if (value = node.classList) {
+          while (++i &lt; n) if (!value.contains(name[i])) return false;
+        } else {
+          value = node.getAttribute(&quot;class&quot;);
+          while (++i &lt; n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
+        }
+        return true;
+      }
+      for (value in name) this.each(d3_selection_classed(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_classed(name, value));
+  };
+  function d3_selection_classedRe(name) {
+    return new RegExp(&quot;(?:^|\\s+)&quot; + d3.requote(name) + &quot;(?:\\s+|$)&quot;, &quot;g&quot;);
+  }
+  function d3_selection_classes(name) {
+    return (name + &quot;&quot;).trim().split(/^|\s+/);
+  }
+  function d3_selection_classed(name, value) {
+    name = d3_selection_classes(name).map(d3_selection_classedName);
+    var n = name.length;
+    function classedConstant() {
+      var i = -1;
+      while (++i &lt; n) name[i](this, value);
+    }
+    function classedFunction() {
+      var i = -1, x = value.apply(this, arguments);
+      while (++i &lt; n) name[i](this, x);
+    }
+    return typeof value === &quot;function&quot; ? classedFunction : classedConstant;
+  }
+  function d3_selection_classedName(name) {
+    var re = d3_selection_classedRe(name);
+    return function(node, value) {
+      if (c = node.classList) return value ? c.add(name) : c.remove(name);
+      var c = node.getAttribute(&quot;class&quot;) || &quot;&quot;;
+      if (value) {
+        re.lastIndex = 0;
+        if (!re.test(c)) node.setAttribute(&quot;class&quot;, d3_collapse(c + &quot; &quot; + name));
+      } else {
+        node.setAttribute(&quot;class&quot;, d3_collapse(c.replace(re, &quot; &quot;)));
+      }
+    };
+  }
+  d3_selectionPrototype.style = function(name, value, priority) {
+    var n = arguments.length;
+    if (n &lt; 3) {
+      if (typeof name !== &quot;string&quot;) {
+        if (n &lt; 2) value = &quot;&quot;;
+        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
+        return this;
+      }
+      if (n &lt; 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
+      priority = &quot;&quot;;
+    }
+    return this.each(d3_selection_style(name, value, priority));
+  };
+  function d3_selection_style(name, value, priority) {
+    function styleNull() {
+      this.style.removeProperty(name);
+    }
+    function styleConstant() {
+      this.style.setProperty(name, value, priority);
+    }
+    function styleFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
+    }
+    return value == null ? styleNull : typeof value === &quot;function&quot; ? styleFunction : styleConstant;
+  }
+  d3_selectionPrototype.property = function(name, value) {
+    if (arguments.length &lt; 2) {
+      if (typeof name === &quot;string&quot;) return this.node()[name];
+      for (value in name) this.each(d3_selection_property(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_property(name, value));
+  };
+  function d3_selection_property(name, value) {
+    function propertyNull() {
+      delete this[name];
+    }
+    function propertyConstant() {
+      this[name] = value;
+    }
+    function propertyFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) delete this[name]; else this[name] = x;
+    }
+    return value == null ? propertyNull : typeof value === &quot;function&quot; ? propertyFunction : propertyConstant;
+  }
+  d3_selectionPrototype.text = function(value) {
+    return arguments.length ? this.each(typeof value === &quot;function&quot; ? function() {
+      var v = value.apply(this, arguments);
+      this.textContent = v == null ? &quot;&quot; : v;
+    } : value == null ? function() {
+      this.textContent = &quot;&quot;;
+    } : function() {
+      this.textContent = value;
+    }) : this.node().textContent;
+  };
+  d3_selectionPrototype.html = function(value) {
+    return arguments.length ? this.each(typeof value === &quot;function&quot; ? function() {
+      var v = value.apply(this, arguments);
+      this.innerHTML = v == null ? &quot;&quot; : v;
+    } : value == null ? function() {
+      this.innerHTML = &quot;&quot;;
+    } : function() {
+      this.innerHTML = value;
+    }) : this.node().innerHTML;
+  };
+  d3_selectionPrototype.append = function(name) {
+    name = d3_selection_creator(name);
+    return this.select(function() {
+      return this.appendChild(name.apply(this, arguments));
+    });
+  };
+  function d3_selection_creator(name) {
+    return typeof name === &quot;function&quot; ? name : (name = d3.ns.qualify(name)).local ? function() {
+      return this.ownerDocument.createElementNS(name.space, name.local);
+    } : function() {
+      return this.ownerDocument.createElementNS(this.namespaceURI, name);
+    };
+  }
+  d3_selectionPrototype.insert = function(name, before) {
+    name = d3_selection_creator(name);
+    before = d3_selection_selector(before);
+    return this.select(function() {
+      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
+    });
+  };
+  d3_selectionPrototype.remove = function() {
+    return this.each(function() {
+      var parent = this.parentNode;
+      if (parent) parent.removeChild(this);
+    });
+  };
+  d3_selectionPrototype.data = function(value, key) {
+    var i = -1, n = this.length, group, node;
+    if (!arguments.length) {
+      value = new Array(n = (group = this[0]).length);
+      while (++i &lt; n) {
+        if (node = group[i]) {
+          value[i] = node.__data__;
+        }
+      }
+      return value;
+    }
+    function bind(group, groupData) {
+      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
+      if (key) {
+        var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
+        for (i = -1; ++i &lt; n; ) {
+          keyValue = key.call(node = group[i], node.__data__, i);
+          if (nodeByKeyValue.has(keyValue)) {
+            exitNodes[i] = node;
+          } else {
+            nodeByKeyValue.set(keyValue, node);
+          }
+          keyValues.push(keyValue);
+        }
+        for (i = -1; ++i &lt; m; ) {
+          keyValue = key.call(groupData, nodeData = groupData[i], i);
+          if (node = nodeByKeyValue.get(keyValue)) {
+            updateNodes[i] = node;
+            node.__data__ = nodeData;
+          } else if (!dataByKeyValue.has(keyValue)) {
+            enterNodes[i] = d3_selection_dataNode(nodeData);
+          }
+          dataByKeyValue.set(keyValue, nodeData);
+          nodeByKeyValue.remove(keyValue);
+        }
+        for (i = -1; ++i &lt; n; ) {
+          if (nodeByKeyValue.has(keyValues[i])) {
+            exitNodes[i] = group[i];
+          }
+        }
+      } else {
+        for (i = -1; ++i &lt; n0; ) {
+          node = group[i];
+          nodeData = groupData[i];
+          if (node) {
+            node.__data__ = nodeData;
+            updateNodes[i] = node;
+          } else {
+            enterNodes[i] = d3_selection_dataNode(nodeData);
+          }
+        }
+        for (;i &lt; m; ++i) {
+          enterNodes[i] = d3_selection_dataNode(groupData[i]);
+        }
+        for (;i &lt; n; ++i) {
+          exitNodes[i] = group[i];
+        }
+      }
+      enterNodes.update = updateNodes;
+      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
+      enter.push(enterNodes);
+      update.push(updateNodes);
+      exit.push(exitNodes);
+    }
+    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
+    if (typeof value === &quot;function&quot;) {
+      while (++i &lt; n) {
+        bind(group = this[i], value.call(group, group.parentNode.__data__, i));
+      }
+    } else {
+      while (++i &lt; n) {
+        bind(group = this[i], value);
+      }
+    }
+    update.enter = function() {
+      return enter;
+    };
+    update.exit = function() {
+      return exit;
+    };
+    return update;
+  };
+  function d3_selection_dataNode(data) {
+    return {
+      __data__: data
+    };
+  }
+  d3_selectionPrototype.datum = function(value) {
+    return arguments.length ? this.property(&quot;__data__&quot;, value) : this.property(&quot;__data__&quot;);
+  };
+  d3_selectionPrototype.filter = function(filter) {
+    var subgroups = [], subgroup, group, node;
+    if (typeof filter !== &quot;function&quot;) filter = d3_selection_filter(filter);
+    for (var j = 0, m = this.length; j &lt; m; j++) {
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = (group = this[j]).parentNode;
+      for (var i = 0, n = group.length; i &lt; n; i++) {
+        if ((node = group[i]) &amp;&amp; filter.call(node, node.__data__, i, j)) {
+          subgroup.push(node);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_filter(selector) {
+    return function() {
+      return d3_selectMatches(this, selector);
+    };
+  }
+  d3_selectionPrototype.order = function() {
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      for (var group = this[j], i = group.length - 1, next = group[i], node; --i &gt;= 0; ) {
+        if (node = group[i]) {
+          if (next &amp;&amp; next !== node.nextSibling) next.parentNode.insertBefore(node, next);
+          next = node;
+        }
+      }
+    }
+    return this;
+  };
+  d3_selectionPrototype.sort = function(comparator) {
+    comparator = d3_selection_sortComparator.apply(this, arguments);
+    for (var j = -1, m = this.length; ++j &lt; m; ) this[j].sort(comparator);
+    return this.order();
+  };
+  function d3_selection_sortComparator(comparator) {
+    if (!arguments.length) comparator = d3_ascending;
+    return function(a, b) {
+      return a &amp;&amp; b ? comparator(a.__data__, b.__data__) : !a - !b;
+    };
+  }
+  d3_selectionPrototype.each = function(callback) {
+    return d3_selection_each(this, function(node, i, j) {
+      callback.call(node, node.__data__, i, j);
+    });
+  };
+  function d3_selection_each(groups, callback) {
+    for (var j = 0, m = groups.length; j &lt; m; j++) {
+      for (var group = groups[j], i = 0, n = group.length, node; i &lt; n; i++) {
+        if (node = group[i]) callback(node, i, j);
+      }
+    }
+    return groups;
+  }
+  d3_selectionPrototype.call = function(callback) {
+    var args = d3_array(arguments);
+    callback.apply(args[0] = this, args);
+    return this;
+  };
+  d3_selectionPrototype.empty = function() {
+    return !this.node();
+  };
+  d3_selectionPrototype.node = function() {
+    for (var j = 0, m = this.length; j &lt; m; j++) {
+      for (var group = this[j], i = 0, n = group.length; i &lt; n; i++) {
+        var node = group[i];
+        if (node) return node;
+      }
+    }
+    return null;
+  };
+  d3_selectionPrototype.size = function() {
+    var n = 0;
+    this.each(function() {
+      ++n;
+    });
+    return n;
+  };
+  function d3_selection_enter(selection) {
+    d3_subclass(selection, d3_selection_enterPrototype);
+    return selection;
+  }
+  var d3_selection_enterPrototype = [];
+  d3.selection.enter = d3_selection_enter;
+  d3.selection.enter.prototype = d3_selection_enterPrototype;
+  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
+  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
+  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
+  d3_selection_enterPrototype.call = d3_selectionPrototype.call;
+  d3_selection_enterPrototype.size = d3_selectionPrototype.size;
+  d3_selection_enterPrototype.select = function(selector) {
+    var subgroups = [], subgroup, subnode, upgroup, group, node;
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      upgroup = (group = this[j]).update;
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = group.parentNode;
+      for (var i = -1, n = group.length; ++i &lt; n; ) {
+        if (node = group[i]) {
+          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
+          subnode.__data__ = node.__data__;
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  d3_selection_enterPrototype.insert = function(name, before) {
+    if (arguments.length &lt; 2) before = d3_selection_enterInsertBefore(this);
+    return d3_selectionPrototype.insert.call(this, name, before);
+  };
+  function d3_selection_enterInsertBefore(enter) {
+    var i0, j0;
+    return function(d, i, j) {
+      var group = enter[j].update, n = group.length, node;
+      if (j != j0) j0 = j, i0 = 0;
+      if (i &gt;= i0) i0 = i + 1;
+      while (!(node = group[i0]) &amp;&amp; ++i0 &lt; n) ;
+      return node;
+    };
+  }
+  d3_selectionPrototype.transition = function() {
+    var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || {
+      time: Date.now(),
+      ease: d3_ease_cubicInOut,
+      delay: 0,
+      duration: 250
+    };
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = -1, n = group.length; ++i &lt; n; ) {
+        if (node = group[i]) d3_transitionNode(node, i, id, transition);
+        subgroup.push(node);
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_selectionPrototype.interrupt = function() {
+    return this.each(d3_selection_interrupt);
+  };
+  function d3_selection_interrupt() {
+    var lock = this.__transition__;
+    if (lock) ++lock.active;
+  }
+  d3.select = function(node) {
+    var group = [ typeof node === &quot;string&quot; ? d3_select(node, d3_document) : node ];
+    group.parentNode = d3_documentElement;
+    return d3_selection([ group ]);
+  };
+  d3.selectAll = function(nodes) {
+    var group = d3_array(typeof nodes === &quot;string&quot; ? d3_selectAll(nodes, d3_document) : nodes);
+    group.parentNode = d3_documentElement;
+    return d3_selection([ group ]);
+  };
+  var d3_selectionRoot = d3.select(d3_documentElement);
+  d3_selectionPrototype.on = function(type, listener, capture) {
+    var n = arguments.length;
+    if (n &lt; 3) {
+      if (typeof type !== &quot;string&quot;) {
+        if (n &lt; 2) listener = false;
+        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
+        return this;
+      }
+      if (n &lt; 2) return (n = this.node()[&quot;__on&quot; + type]) &amp;&amp; n._;
+      capture = false;
+    }
+    return this.each(d3_selection_on(type, listener, capture));
+  };
+  function d3_selection_on(type, listener, capture) {
+    var name = &quot;__on&quot; + type, i = type.indexOf(&quot;.&quot;), wrap = d3_selection_onListener;
+    if (i &gt; 0) type = type.substring(0, i);
+    var filter = d3_selection_onFilters.get(type);
+    if (filter) type = filter, wrap = d3_selection_onFilter;
+    function onRemove() {
+      var l = this[name];
+      if (l) {
+        this.removeEventListener(type, l, l.$);
+        delete this[name];
+      }
+    }
+    function onAdd() {
+      var l = wrap(listener, d3_array(arguments));
+      onRemove.call(this);
+      this.addEventListener(type, this[name] = l, l.$ = capture);
+      l._ = listener;
+    }
+    function removeAll() {
+      var re = new RegExp(&quot;^__on([^.]+)&quot; + d3.requote(type) + &quot;$&quot;), match;
+      for (var name in this) {
+        if (match = name.match(re)) {
+          var l = this[name];
+          this.removeEventListener(match[1], l, l.$);
+          delete this[name];
+        }
+      }
+    }
+    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
+  }
+  var d3_selection_onFilters = d3.map({
+    mouseenter: &quot;mouseover&quot;,
+    mouseleave: &quot;mouseout&quot;
+  });
+  d3_selection_onFilters.forEach(function(k) {
+    if (&quot;on&quot; + k in d3_document) d3_selection_onFilters.remove(k);
+  });
+  function d3_selection_onListener(listener, argumentz) {
+    return function(e) {
+      var o = d3.event;
+      d3.event = e;
+      argumentz[0] = this.__data__;
+      try {
+        listener.apply(this, argumentz);
+      } finally {
+        d3.event = o;
+      }
+    };
+  }
+  function d3_selection_onFilter(listener, argumentz) {
+    var l = d3_selection_onListener(listener, argumentz);
+    return function(e) {
+      var target = this, related = e.relatedTarget;
+      if (!related || related !== target &amp;&amp; !(related.compareDocumentPosition(target) &amp; 8)) {
+        l.call(target, e);
+      }
+    };
+  }
+  var d3_event_dragSelect = &quot;onselectstart&quot; in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, &quot;userSelect&quot;), d3_event_dragId = 0;
+  function d3_event_dragSuppress() {
+    var name = &quot;.dragsuppress-&quot; + ++d3_event_dragId, click = &quot;click&quot; + name, w = d3.select(d3_window).on(&quot;touchmove&quot; + name, d3_eventPreventDefault).on(&quot;dragstart&quot; + name, d3_eventPreventDefault).on(&quot;selectstart&quot; + name, d3_eventPreventDefault);
+    if (d3_event_dragSelect) {
+      var style = d3_documentElement.style, select = style[d3_event_dragSelect];
+      style[d3_event_dragSelect] = &quot;none&quot;;
+    }
+    return function(suppressClick) {
+      w.on(name, null);
+      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
+      if (suppressClick) {
+        function off() {
+          w.on(click, null);
+        }
+        w.on(click, function() {
+          d3_eventPreventDefault();
+          off();
+        }, true);
+        setTimeout(off, 0);
+      }
+    };
+  }
+  d3.mouse = function(container) {
+    return d3_mousePoint(container, d3_eventSource());
+  };
+  var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
+  function d3_mousePoint(container, e) {
+    if (e.changedTouches) e = e.changedTouches[0];
+    var svg = container.ownerSVGElement || container;
+    if (svg.createSVGPoint) {
+      var point = svg.createSVGPoint();
+      if (d3_mouse_bug44083 &lt; 0 &amp;&amp; (d3_window.scrollX || d3_window.scrollY)) {
+        svg = d3.select(&quot;body&quot;).append(&quot;svg&quot;).style({
+          position: &quot;absolute&quot;,
+          top: 0,
+          left: 0,
+          margin: 0,
+          padding: 0,
+          border: &quot;none&quot;
+        }, &quot;important&quot;);
+        var ctm = svg[0][0].getScreenCTM();
+        d3_mouse_bug44083 = !(ctm.f || ctm.e);
+        svg.remove();
+      }
+      if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, 
+      point.y = e.clientY;
+      point = point.matrixTransform(container.getScreenCTM().inverse());
+      return [ point.x, point.y ];
+    }
+    var rect = container.getBoundingClientRect();
+    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
+  }
+  d3.touches = function(container, touches) {
+    if (arguments.length &lt; 2) touches = d3_eventSource().touches;
+    return touches ? d3_array(touches).map(function(touch) {
+      var point = d3_mousePoint(container, touch);
+      point.identifier = touch.identifier;
+      return point;
+    }) : [];
+  };
+  d3.behavior.drag = function() {
+    var event = d3_eventDispatch(drag, &quot;drag&quot;, &quot;dragstart&quot;, &quot;dragend&quot;), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, &quot;mousemove&quot;, &quot;mouseup&quot;), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, &quot;touchmove&quot;, &quot;touchend&quot;);
+    function drag() {
+      this.on(&quot;mousedown.drag&quot;, mousedown).on(&quot;touchstart.drag&quot;, touchstart);
+    }
+    function dragstart(id, position, subject, move, end) {
+      return function() {
+        var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = &quot;.drag&quot; + (dragId == null ? &quot;&quot; : &quot;-&quot; + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId);
+        if (origin) {
+          dragOffset = origin.apply(that, arguments);
+          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
+        } else {
+          dragOffset = [ 0, 0 ];
+        }
+        dispatch({
+          type: &quot;dragstart&quot;
+        });
+        function moved() {
+          var position1 = position(parent, dragId), dx, dy;
+          if (!position1) return;
+          dx = position1[0] - position0[0];
+          dy = position1[1] - position0[1];
+          dragged |= dx | dy;
+          position0 = position1;
+          dispatch({
+            type: &quot;drag&quot;,
+            x: position1[0] + dragOffset[0],
+            y: position1[1] + dragOffset[1],
+            dx: dx,
+            dy: dy
+          });
+        }
+        function ended() {
+          if (!position(parent, dragId)) return;
+          dragSubject.on(move + dragName, null).on(end + dragName, null);
+          dragRestore(dragged &amp;&amp; d3.event.target === target);
+          dispatch({
+            type: &quot;dragend&quot;
+          });
+        }
+      };
+    }
+    drag.origin = function(x) {
+      if (!arguments.length) return origin;
+      origin = x;
+      return drag;
+    };
+    return d3.rebind(drag, event, &quot;on&quot;);
+  };
+  function d3_behavior_dragTouchId() {
+    return d3.event.changedTouches[0].identifier;
+  }
+  function d3_behavior_dragTouchSubject() {
+    return d3.event.target;
+  }
+  function d3_behavior_dragMouseSubject() {
+    return d3_window;
+  }
+  var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π;
+  function d3_sgn(x) {
+    return x &gt; 0 ? 1 : x &lt; 0 ? -1 : 0;
+  }
+  function d3_cross2d(a, b, c) {
+    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
+  }
+  function d3_acos(x) {
+    return x &gt; 1 ? 0 : x &lt; -1 ? π : Math.acos(x);
+  }
+  function d3_asin(x) {
+    return x &gt; 1 ? halfπ : x &lt; -1 ? -halfπ : Math.asin(x);
+  }
+  function d3_sinh(x) {
+    return ((x = Math.exp(x)) - 1 / x) / 2;
+  }
+  function d3_cosh(x) {
+    return ((x = Math.exp(x)) + 1 / x) / 2;
+  }
+  function d3_tanh(x) {
+    return ((x = Math.exp(2 * x)) - 1) / (x + 1);
+  }
+  function d3_haversin(x) {
+    return (x = Math.sin(x / 2)) * x;
+  }
+  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
+  d3.interpolateZoom = function(p0, p1) {
+    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
+    var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
+    function interpolate(t) {
+      var s = t * S;
+      if (dr) {
+        var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
+        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
+      }
+      return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
+    }
+    interpolate.duration = S * 1e3;
+    return interpolate;
+  };
+  d3.behavior.zoom = function() {
+    var view = {
+      x: 0,
+      y: 0,
+      k: 1
+    }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = &quot;mousedown.zoom&quot;, mousemove = &quot;mousemove.zoom&quot;, mouseup = &quot;mouseup.zoom&quot;, mousewheelTimer, touchstart = &quot;touchstart.zoom&quot;, touchtime, event = d3_eventDispatch(zoom, &quot;zoomstart&quot;, &quot;zoom&quot;, &quot;zoomend&quot;), x0, x1, y0, y1;
+    function zoom(g) {
+      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + &quot;.zoom&quot;, mousewheeled).on(&quot;dblclick.zoom&quot;, dblclicked).on(touchstart, touchstarted);
+    }
+    zoom.event = function(g) {
+      g.each(function() {
+        var dispatch = event.of(this, arguments), view1 = view;
+        if (d3_transitionInheritId) {
+          d3.select(this).transition().each(&quot;start.zoom&quot;, function() {
+            view = this.__chart__ || {
+              x: 0,
+              y: 0,
+              k: 1
+            };
+            zoomstarted(dispatch);
+          }).tween(&quot;zoom:zoom&quot;, function() {
+            var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
+            return function(t) {
+              var l = i(t), k = dx / l[2];
+              this.__chart__ = view = {
+                x: cx - l[0] * k,
+                y: cy - l[1] * k,
+                k: k
+              };
+              zoomed(dispatch);
+            };
+          }).each(&quot;end.zoom&quot;, function() {
+            zoomended(dispatch);
+          });
+        } else {
+          this.__chart__ = view;
+          zoomstarted(dispatch);
+          zoomed(dispatch);
+          zoomended(dispatch);
+        }
+      });
+    };
+    zoom.translate = function(_) {
+      if (!arguments.length) return [ view.x, view.y ];
+      view = {
+        x: +_[0],
+        y: +_[1],
+        k: view.k
+      };
+      rescale();
+      return zoom;
+    };
+    zoom.scale = function(_) {
+      if (!arguments.length) return view.k;
+      view = {
+        x: view.x,
+        y: view.y,
+        k: +_
+      };
+      rescale();
+      return zoom;
+    };
+    zoom.scaleExtent = function(_) {
+      if (!arguments.length) return scaleExtent;
+      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.center = function(_) {
+      if (!arguments.length) return center;
+      center = _ &amp;&amp; [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.size = function(_) {
+      if (!arguments.length) return size;
+      size = _ &amp;&amp; [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.x = function(z) {
+      if (!arguments.length) return x1;
+      x1 = z;
+      x0 = z.copy();
+      view = {
+        x: 0,
+        y: 0,
+        k: 1
+      };
+      return zoom;
+    };
+    zoom.y = function(z) {
+      if (!arguments.length) return y1;
+      y1 = z;
+      y0 = z.copy();
+      view = {
+        x: 0,
+        y: 0,
+        k: 1
+      };
+      return zoom;
+    };
+    function location(p) {
+      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
+    }
+    function point(l) {
+      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
+    }
+    function scaleTo(s) {
+      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+    }
+    function translateTo(p, l) {
+      l = point(l);
+      view.x += p[0] - l[0];
+      view.y += p[1] - l[1];
+    }
+    function rescale() {
+      if (x1) x1.domain(x0.range().map(function(x) {
+        return (x - view.x) / view.k;
+      }).map(x0.invert));
+      if (y1) y1.domain(y0.range().map(function(y) {
+        return (y - view.y) / view.k;
+      }).map(y0.invert));
+    }
+    function zoomstarted(dispatch) {
+      dispatch({
+        type: &quot;zoomstart&quot;
+      });
+    }
+    function zoomed(dispatch) {
+      rescale();
+      dispatch({
+        type: &quot;zoom&quot;,
+        scale: view.k,
+        translate: [ view.x, view.y ]
+      });
+    }
+    function zoomended(dispatch) {
+      dispatch({
+        type: &quot;zoomend&quot;
+      });
+    }
+    function mousedowned() {
+      var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      zoomstarted(dispatch);
+      function moved() {
+        dragged = 1;
+        translateTo(d3.mouse(that), location0);
+        zoomed(dispatch);
+      }
+      function ended() {
+        subject.on(mousemove, null).on(mouseup, null);
+        dragRestore(dragged &amp;&amp; d3.event.target === target);
+        zoomended(dispatch);
+      }
+    }
+    function touchstarted() {
+      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = &quot;.zoom-&quot; + d3.event.changedTouches[0].identifier, touchmove = &quot;touchmove&quot; + zoomName, touchend = &quot;touchend&quot; + zoomName, targets = [], subject = d3.select(that).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      started();
+      zoomstarted(dispatch);
+      function relocate() {
+        var touches = d3.touches(that);
+        scale0 = view.k;
+        touches.forEach(function(t) {
+          if (t.identifier in locations0) locations0[t.identifier] = location(t);
+        });
+        return touches;
+      }
+      function started() {
+        var target = d3.event.target;
+        d3.select(target).on(touchmove, moved).on(touchend, ended);
+        targets.push(target);
+        var changed = d3.event.changedTouches;
+        for (var i = 0, n = changed.length; i &lt; n; ++i) {
+          locations0[changed[i].identifier] = null;
+        }
+        var touches = relocate(), now = Date.now();
+        if (touches.length === 1) {
+          if (now - touchtime &lt; 500) {
+            var p = touches[0], l = locations0[p.identifier];
+            scaleTo(view.k * 2);
+            translateTo(p, l);
+            d3_eventPreventDefault();
+            zoomed(dispatch);
+          }
+          touchtime = now;
+        } else if (touches.length &gt; 1) {
+          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
+          distance0 = dx * dx + dy * dy;
+        }
+      }
+      function moved() {
+        var touches = d3.touches(that), p0, l0, p1, l1;
+        for (var i = 0, n = touches.length; i &lt; n; ++i, l1 = null) {
+          p1 = touches[i];
+          if (l1 = locations0[p1.identifier]) {
+            if (l0) break;
+            p0 = p1, l0 = l1;
+          }
+        }
+        if (l1) {
+          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 &amp;&amp; Math.sqrt(distance1 / distance0);
+          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
+          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
+          scaleTo(scale1 * scale0);
+        }
+        touchtime = null;
+        translateTo(p0, l0);
+        zoomed(dispatch);
+      }
+      function ended() {
+        if (d3.event.touches.length) {
+          var changed = d3.event.changedTouches;
+          for (var i = 0, n = changed.length; i &lt; n; ++i) {
+            delete locations0[changed[i].identifier];
+          }
+          for (var identifier in locations0) {
+            return void relocate();
+          }
+        }
+        d3.selectAll(targets).on(zoomName, null);
+        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
+        dragRestore();
+        zoomended(dispatch);
+      }
+    }
+    function mousewheeled() {
+      var dispatch = event.of(this, arguments);
+      if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), 
+      d3_selection_interrupt.call(this), zoomstarted(dispatch);
+      mousewheelTimer = setTimeout(function() {
+        mousewheelTimer = null;
+        zoomended(dispatch);
+      }, 50);
+      d3_eventPreventDefault();
+      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
+      translateTo(center0, translate0);
+      zoomed(dispatch);
+    }
+    function dblclicked() {
+      var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;
+      zoomstarted(dispatch);
+      scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
+      translateTo(p, l);
+      zoomed(dispatch);
+      zoomended(dispatch);
+    }
+    return d3.rebind(zoom, event, &quot;on&quot;);
+  };
+  var d3_behavior_zoomInfinity = [ 0, Infinity ];
+  var d3_behavior_zoomDelta, d3_behavior_zoomWheel = &quot;onwheel&quot; in d3_document ? (d3_behavior_zoomDelta = function() {
+    return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
+  }, &quot;wheel&quot;) : &quot;onmousewheel&quot; in d3_document ? (d3_behavior_zoomDelta = function() {
+    return d3.event.wheelDelta;
+  }, &quot;mousewheel&quot;) : (d3_behavior_zoomDelta = function() {
+    return -d3.event.detail;
+  }, &quot;MozMousePixelScroll&quot;);
+  d3.color = d3_color;
+  function d3_color() {}
+  d3_color.prototype.toString = function() {
+    return this.rgb() + &quot;&quot;;
+  };
+  d3.hsl = d3_hsl;
+  function d3_hsl(h, s, l) {
+    return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length &lt; 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse(&quot;&quot; + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
+  }
+  var d3_hslPrototype = d3_hsl.prototype = new d3_color();
+  d3_hslPrototype.brighter = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return new d3_hsl(this.h, this.s, this.l / k);
+  };
+  d3_hslPrototype.darker = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return new d3_hsl(this.h, this.s, k * this.l);
+  };
+  d3_hslPrototype.rgb = function() {
+    return d3_hsl_rgb(this.h, this.s, this.l);
+  };
+  function d3_hsl_rgb(h, s, l) {
+    var m1, m2;
+    h = isNaN(h) ? 0 : (h %= 360) &lt; 0 ? h + 360 : h;
+    s = isNaN(s) ? 0 : s &lt; 0 ? 0 : s &gt; 1 ? 1 : s;
+    l = l &lt; 0 ? 0 : l &gt; 1 ? 1 : l;
+    m2 = l &lt;= .5 ? l * (1 + s) : l + s - l * s;
+    m1 = 2 * l - m2;
+    function v(h) {
+      if (h &gt; 360) h -= 360; else if (h &lt; 0) h += 360;
+      if (h &lt; 60) return m1 + (m2 - m1) * h / 60;
+      if (h &lt; 180) return m2;
+      if (h &lt; 240) return m1 + (m2 - m1) * (240 - h) / 60;
+      return m1;
+    }
+    function vv(h) {
+      return Math.round(v(h) * 255);
+    }
+    return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+  }
+  d3.hcl = d3_hcl;
+  function d3_hcl(h, c, l) {
+    return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length &lt; 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
+  }
+  var d3_hclPrototype = d3_hcl.prototype = new d3_color();
+  d3_hclPrototype.brighter = function(k) {
+    return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+  };
+  d3_hclPrototype.darker = function(k) {
+    return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
+  };
+  d3_hclPrototype.rgb = function() {
+    return d3_hcl_lab(this.h, this.c, this.l).rgb();
+  };
+  function d3_hcl_lab(h, c, l) {
+    if (isNaN(h)) h = 0;
+    if (isNaN(c)) c = 0;
+    return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+  }
+  d3.lab = d3_lab;
+  function d3_lab(l, a, b) {
+    return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length &lt; 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
+  }
+  var d3_lab_K = 18;
+  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
+  var d3_labPrototype = d3_lab.prototype = new d3_color();
+  d3_labPrototype.brighter = function(k) {
+    return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+  };
+  d3_labPrototype.darker = function(k) {
+    return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+  };
+  d3_labPrototype.rgb = function() {
+    return d3_lab_rgb(this.l, this.a, this.b);
+  };
+  function d3_lab_rgb(l, a, b) {
+    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
+    x = d3_lab_xyz(x) * d3_lab_X;
+    y = d3_lab_xyz(y) * d3_lab_Y;
+    z = d3_lab_xyz(z) * d3_lab_Z;
+    return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
+  }
+  function d3_lab_hcl(l, a, b) {
+    return l &gt; 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
+  }
+  function d3_lab_xyz(x) {
+    return x &gt; .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
+  }
+  function d3_xyz_lab(x) {
+    return x &gt; .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
+  }
+  function d3_xyz_rgb(r) {
+    return Math.round(255 * (r &lt;= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
+  }
+  d3.rgb = d3_rgb;
+  function d3_rgb(r, g, b) {
+    return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length &lt; 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse(&quot;&quot; + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
+  }
+  function d3_rgbNumber(value) {
+    return new d3_rgb(value &gt;&gt; 16, value &gt;&gt; 8 &amp; 255, value &amp; 255);
+  }
+  function d3_rgbString(value) {
+    return d3_rgbNumber(value) + &quot;&quot;;
+  }
+  var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
+  d3_rgbPrototype.brighter = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    var r = this.r, g = this.g, b = this.b, i = 30;
+    if (!r &amp;&amp; !g &amp;&amp; !b) return new d3_rgb(i, i, i);
+    if (r &amp;&amp; r &lt; i) r = i;
+    if (g &amp;&amp; g &lt; i) g = i;
+    if (b &amp;&amp; b &lt; i) b = i;
+    return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
+  };
+  d3_rgbPrototype.darker = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return new d3_rgb(k * this.r, k * this.g, k * this.b);
+  };
+  d3_rgbPrototype.hsl = function() {
+    return d3_rgb_hsl(this.r, this.g, this.b);
+  };
+  d3_rgbPrototype.toString = function() {
+    return &quot;#&quot; + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
+  };
+  function d3_rgb_hex(v) {
+    return v &lt; 16 ? &quot;0&quot; + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
+  }
+  function d3_rgb_parse(format, rgb, hsl) {
+    var r = 0, g = 0, b = 0, m1, m2, color;
+    m1 = /([a-z]+)\((.*)\)/i.exec(format);
+    if (m1) {
+      m2 = m1[2].split(&quot;,&quot;);
+      switch (m1[1]) {
+       case &quot;hsl&quot;:
+        {
+          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
+        }
+
+       case &quot;rgb&quot;:
+        {
+          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
+        }
+      }
+    }
+    if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b);
+    if (format != null &amp;&amp; format.charAt(0) === &quot;#&quot; &amp;&amp; !isNaN(color = parseInt(format.substring(1), 16))) {
+      if (format.length === 4) {
+        r = (color &amp; 3840) &gt;&gt; 4;
+        r = r &gt;&gt; 4 | r;
+        g = color &amp; 240;
+        g = g &gt;&gt; 4 | g;
+        b = color &amp; 15;
+        b = b &lt;&lt; 4 | b;
+      } else if (format.length === 7) {
+        r = (color &amp; 16711680) &gt;&gt; 16;
+        g = (color &amp; 65280) &gt;&gt; 8;
+        b = color &amp; 255;
+      }
+    }
+    return rgb(r, g, b);
+  }
+  function d3_rgb_hsl(r, g, b) {
+    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
+    if (d) {
+      s = l &lt; .5 ? d / (max + min) : d / (2 - max - min);
+      if (r == max) h = (g - b) / d + (g &lt; b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
+      h *= 60;
+    } else {
+      h = NaN;
+      s = l &gt; 0 &amp;&amp; l &lt; 1 ? 0 : h;
+    }
+    return new d3_hsl(h, s, l);
+  }
+  function d3_rgb_lab(r, g, b) {
+    r = d3_rgb_xyz(r);
+    g = d3_rgb_xyz(g);
+    b = d3_rgb_xyz(b);
+    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
+    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
+  }
+  function d3_rgb_xyz(r) {
+    return (r /= 255) &lt;= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
+  }
+  function d3_rgb_parseNumber(c) {
+    var f = parseFloat(c);
+    return c.charAt(c.length - 1) === &quot;%&quot; ? Math.round(f * 2.55) : f;
+  }
+  var d3_rgb_names = d3.map({
+    aliceblue: 15792383,
+    antiquewhite: 16444375,
+    aqua: 65535,
+    aquamarine: 8388564,
+    azure: 15794175,
+    beige: 16119260,
+    bisque: 16770244,
+    black: 0,
+    blanchedalmond: 16772045,
+    blue: 255,
+    blueviolet: 9055202,
+    brown: 10824234,
+    burlywood: 14596231,
+    cadetblue: 6266528,
+    chartreuse: 8388352,
+    chocolate: 13789470,
+    coral: 16744272,
+    cornflowerblue: 6591981,
+    cornsilk: 16775388,
+    crimson: 14423100,
+    cyan: 65535,
+    darkblue: 139,
+    darkcyan: 35723,
+    darkgoldenrod: 12092939,
+    darkgray: 11119017,
+    darkgreen: 25600,
+    darkgrey: 11119017,
+    darkkhaki: 12433259,
+    darkmagenta: 9109643,
+    darkolivegreen: 5597999,
+    darkorange: 16747520,
+    darkorchid: 10040012,
+    darkred: 9109504,
+    darksalmon: 15308410,
+    darkseagreen: 9419919,
+    darkslateblue: 4734347,
+    darkslategray: 3100495,
+    darkslategrey: 3100495,
+    darkturquoise: 52945,
+    darkviolet: 9699539,
+    deeppink: 16716947,
+    deepskyblue: 49151,
+    dimgray: 6908265,
+    dimgrey: 6908265,
+    dodgerblue: 2003199,
+    firebrick: 11674146,
+    floralwhite: 16775920,
+    forestgreen: 2263842,
+    fuchsia: 16711935,
+    gainsboro: 14474460,
+    ghostwhite: 16316671,
+    gold: 16766720,
+    goldenrod: 14329120,
+    gray: 8421504,
+    green: 32768,
+    greenyellow: 11403055,
+    grey: 8421504,
+    honeydew: 15794160,
+    hotpink: 16738740,
+    indianred: 13458524,
+    indigo: 4915330,
+    ivory: 16777200,
+    khaki: 15787660,
+    lavender: 15132410,
+    lavenderblush: 16773365,
+    lawngreen: 8190976,
+    lemonchiffon: 16775885,
+    lightblue: 11393254,
+    lightcoral: 15761536,
+    lightcyan: 14745599,
+    lightgoldenrodyellow: 16448210,
+    lightgray: 13882323,
+    lightgreen: 9498256,
+    lightgrey: 13882323,
+    lightpink: 16758465,
+    lightsalmon: 16752762,
+    lightseagreen: 2142890,
+    lightskyblue: 8900346,
+    lightslategray: 7833753,
+    lightslategrey: 7833753,
+    lightsteelblue: 11584734,
+    lightyellow: 16777184,
+    lime: 65280,
+    limegreen: 3329330,
+    linen: 16445670,
+    magenta: 16711935,
+    maroon: 8388608,
+    mediumaquamarine: 6737322,
+    mediumblue: 205,
+    mediumorchid: 12211667,
+    mediumpurple: 9662683,
+    mediumseagreen: 3978097,
+    mediumslateblue: 8087790,
+    mediumspringgreen: 64154,
+    mediumturquoise: 4772300,
+    mediumvioletred: 13047173,
+    midnightblue: 1644912,
+    mintcream: 16121850,
+    mistyrose: 16770273,
+    moccasin: 16770229,
+    navajowhite: 16768685,
+    navy: 128,
+    oldlace: 16643558,
+    olive: 8421376,
+    olivedrab: 7048739,
+    orange: 16753920,
+    orangered: 16729344,
+    orchid: 14315734,
+    palegoldenrod: 15657130,
+    palegreen: 10025880,
+    paleturquoise: 11529966,
+    palevioletred: 14381203,
+    papayawhip: 16773077,
+    peachpuff: 16767673,
+    peru: 13468991,
+    pink: 16761035,
+    plum: 14524637,
+    powderblue: 11591910,
+    purple: 8388736,
+    red: 16711680,
+    rosybrown: 12357519,
+    royalblue: 4286945,
+    saddlebrown: 9127187,
+    salmon: 16416882,
+    sandybrown: 16032864,
+    seagreen: 3050327,
+    seashell: 16774638,
+    sienna: 10506797,
+    silver: 12632256,
+    skyblue: 8900331,
+    slateblue: 6970061,
+    slategray: 7372944,
+    slategrey: 7372944,
+    snow: 16775930,
+    springgreen: 65407,
+    steelblue: 4620980,
+    tan: 13808780,
+    teal: 32896,
+    thistle: 14204888,
+    tomato: 16737095,
+    turquoise: 4251856,
+    violet: 15631086,
+    wheat: 16113331,
+    white: 16777215,
+    whitesmoke: 16119285,
+    yellow: 16776960,
+    yellowgreen: 10145074
+  });
+  d3_rgb_names.forEach(function(key, value) {
+    d3_rgb_names.set(key, d3_rgbNumber(value));
+  });
+  function d3_functor(v) {
+    return typeof v === &quot;function&quot; ? v : function() {
+      return v;
+    };
+  }
+  d3.functor = d3_functor;
+  function d3_identity(d) {
+    return d;
+  }
+  d3.xhr = d3_xhrType(d3_identity);
+  function d3_xhrType(response) {
+    return function(url, mimeType, callback) {
+      if (arguments.length === 2 &amp;&amp; typeof mimeType === &quot;function&quot;) callback = mimeType, 
+      mimeType = null;
+      return d3_xhr(url, mimeType, response, callback);
+    };
+  }
+  function d3_xhr(url, mimeType, response, callback) {
+    var xhr = {}, dispatch = d3.dispatch(&quot;beforesend&quot;, &quot;progress&quot;, &quot;load&quot;, &quot;error&quot;), headers = {}, request = new XMLHttpRequest(), responseType = null;
+    if (d3_window.XDomainRequest &amp;&amp; !(&quot;withCredentials&quot; in request) &amp;&amp; /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
+    &quot;onload&quot; in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
+      request.readyState &gt; 3 &amp;&amp; respond();
+    };
+    function respond() {
+      var status = request.status, result;
+      if (!status &amp;&amp; request.responseText || status &gt;= 200 &amp;&amp; status &lt; 300 || status === 304) {
+        try {
+          result = response.call(xhr, request);
+        } catch (e) {
+          dispatch.error.call(xhr, e);
+          return;
+        }
+        dispatch.load.call(xhr, result);
+      } else {
+        dispatch.error.call(xhr, request);
+      }
+    }
+    request.onprogress = function(event) {
+      var o = d3.event;
+      d3.event = event;
+      try {
+        dispatch.progress.call(xhr, request);
+      } finally {
+        d3.event = o;
+      }
+    };
+    xhr.header = function(name, value) {
+      name = (name + &quot;&quot;).toLowerCase();
+      if (arguments.length &lt; 2) return headers[name];
+      if (value == null) delete headers[name]; else headers[name] = value + &quot;&quot;;
+      return xhr;
+    };
+    xhr.mimeType = function(value) {
+      if (!arguments.length) return mimeType;
+      mimeType = value == null ? null : value + &quot;&quot;;
+      return xhr;
+    };
+    xhr.responseType = function(value) {
+      if (!arguments.length) return responseType;
+      responseType = value;
+      return xhr;
+    };
+    xhr.response = function(value) {
+      response = value;
+      return xhr;
+    };
+    [ &quot;get&quot;, &quot;post&quot; ].forEach(function(method) {
+      xhr[method] = function() {
+        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
+      };
+    });
+    xhr.send = function(method, data, callback) {
+      if (arguments.length === 2 &amp;&amp; typeof data === &quot;function&quot;) callback = data, data = null;
+      request.open(method, url, true);
+      if (mimeType != null &amp;&amp; !(&quot;accept&quot; in headers)) headers[&quot;accept&quot;] = mimeType + &quot;,*/*&quot;;
+      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
+      if (mimeType != null &amp;&amp; request.overrideMimeType) request.overrideMimeType(mimeType);
+      if (responseType != null) request.responseType = responseType;
+      if (callback != null) xhr.on(&quot;error&quot;, callback).on(&quot;load&quot;, function(request) {
+        callback(null, request);
+      });
+      dispatch.beforesend.call(xhr, request);
+      request.send(data == null ? null : data);
+      return xhr;
+    };
+    xhr.abort = function() {
+      request.abort();
+      return xhr;
+    };
+    d3.rebind(xhr, dispatch, &quot;on&quot;);
+    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
+  }
+  function d3_xhr_fixCallback(callback) {
+    return callback.length === 1 ? function(error, request) {
+      callback(error == null ? request : null);
+    } : callback;
+  }
+  d3.dsv = function(delimiter, mimeType) {
+    var reFormat = new RegExp('[&quot;' + delimiter + &quot;\n]&quot;), delimiterCode = delimiter.charCodeAt(0);
+    function dsv(url, row, callback) {
+      if (arguments.length &lt; 3) callback = row, row = null;
+      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
+      xhr.row = function(_) {
+        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
+      };
+      return xhr;
+    }
+    function response(request) {
+      return dsv.parse(request.responseText);
+    }
+    function typedResponse(f) {
+      return function(request) {
+        return dsv.parse(request.responseText, f);
+      };
+    }
+    dsv.parse = function(text, f) {
+      var o;
+      return dsv.parseRows(text, function(row, i) {
+        if (o) return o(row, i - 1);
+        var a = new Function(&quot;d&quot;, &quot;return {&quot; + row.map(function(name, i) {
+          return JSON.stringify(name) + &quot;: d[&quot; + i + &quot;]&quot;;
+        }).join(&quot;,&quot;) + &quot;}&quot;);
+        o = f ? function(row, i) {
+          return f(a(row), i);
+        } : a;
+      });
+    };
+    dsv.parseRows = function(text, f) {
+      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
+      function token() {
+        if (I &gt;= N) return EOF;
+        if (eol) return eol = false, EOL;
+        var j = I;
+        if (text.charCodeAt(j) === 34) {
+          var i = j;
+          while (i++ &lt; N) {
+            if (text.charCodeAt(i) === 34) {
+              if (text.charCodeAt(i + 1) !== 34) break;
+              ++i;
+            }
+          }
+          I = i + 2;
+          var c = text.charCodeAt(i + 1);
+          if (c === 13) {
+            eol = true;
+            if (text.charCodeAt(i + 2) === 10) ++I;
+          } else if (c === 10) {
+            eol = true;
+          }
+          return text.substring(j + 1, i).replace(/&quot;&quot;/g, '&quot;');
+        }
+        while (I &lt; N) {
+          var c = text.charCodeAt(I++), k = 1;
+          if (c === 10) eol = true; else if (c === 13) {
+            eol = true;
+            if (text.charCodeAt(I) === 10) ++I, ++k;
+          } else if (c !== delimiterCode) continue;
+          return text.substring(j, I - k);
+        }
+        return text.substring(j);
+      }
+      while ((t = token()) !== EOF) {
+        var a = [];
+        while (t !== EOL &amp;&amp; t !== EOF) {
+          a.push(t);
+          t = token();
+        }
+        if (f &amp;&amp; !(a = f(a, n++))) continue;
+        rows.push(a);
+      }
+      return rows;
+    };
+    dsv.format = function(rows) {
+      if (Array.isArray(rows[0])) return dsv.formatRows(rows);
+      var fieldSet = new d3_Set(), fields = [];
+      rows.forEach(function(row) {
+        for (var field in row) {
+          if (!fieldSet.has(field)) {
+            fields.push(fieldSet.add(field));
+          }
+        }
+      });
+      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
+        return fields.map(function(field) {
+          return formatValue(row[field]);
+        }).join(delimiter);
+      })).join(&quot;\n&quot;);
+    };
+    dsv.formatRows = function(rows) {
+      return rows.map(formatRow).join(&quot;\n&quot;);
+    };
+    function formatRow(row) {
+      return row.map(formatValue).join(delimiter);
+    }
+    function formatValue(text) {
+      return reFormat.test(text) ? '&quot;' + text.replace(/\&quot;/g, '&quot;&quot;') + '&quot;' : text;
+    }
+    return dsv;
+  };
+  d3.csv = d3.dsv(&quot;,&quot;, &quot;text/csv&quot;);
+  d3.tsv = d3.dsv(&quot;    &quot;, &quot;text/tab-separated-values&quot;);
+  d3.touch = function(container, touches, identifier) {
+    if (arguments.length &lt; 3) identifier = touches, touches = d3_eventSource().changedTouches;
+    if (touches) for (var i = 0, n = touches.length, touch; i &lt; n; ++i) {
+      if ((touch = touches[i]).identifier === identifier) {
+        return d3_mousePoint(container, touch);
+      }
+    }
+  };
+  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, &quot;requestAnimationFrame&quot;)] || function(callback) {
+    setTimeout(callback, 17);
+  };
+  d3.timer = function(callback, delay, then) {
+    var n = arguments.length;
+    if (n &lt; 2) delay = 0;
+    if (n &lt; 3) then = Date.now();
+    var time = then + delay, timer = {
+      c: callback,
+      t: time,
+      f: false,
+      n: null
+    };
+    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
+    d3_timer_queueTail = timer;
+    if (!d3_timer_interval) {
+      d3_timer_timeout = clearTimeout(d3_timer_timeout);
+      d3_timer_interval = 1;
+      d3_timer_frame(d3_timer_step);
+    }
+  };
+  function d3_timer_step() {
+    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
+    if (delay &gt; 24) {
+      if (isFinite(delay)) {
+        clearTimeout(d3_timer_timeout);
+        d3_timer_timeout = setTimeout(d3_timer_step, delay);
+      }
+      d3_timer_interval = 0;
+    } else {
+      d3_timer_interval = 1;
+      d3_timer_frame(d3_timer_step);
+    }
+  }
+  d3.timer.flush = function() {
+    d3_timer_mark();
+    d3_timer_sweep();
+  };
+  function d3_timer_mark() {
+    var now = Date.now();
+    d3_timer_active = d3_timer_queueHead;
+    while (d3_timer_active) {
+      if (now &gt;= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
+      d3_timer_active = d3_timer_active.n;
+    }
+    return now;
+  }
+  function d3_timer_sweep() {
+    var t0, t1 = d3_timer_queueHead, time = Infinity;
+    while (t1) {
+      if (t1.f) {
+        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
+      } else {
+        if (t1.t &lt; time) time = t1.t;
+        t1 = (t0 = t1).n;
+      }
+    }
+    d3_timer_queueTail = t0;
+    return time;
+  }
+  function d3_format_precision(x, p) {
+    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
+  }
+  d3.round = function(x, n) {
+    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+  };
+  var d3_formatPrefixes = [ &quot;y&quot;, &quot;z&quot;, &quot;a&quot;, &quot;f&quot;, &quot;p&quot;, &quot;n&quot;, &quot;µ&quot;, &quot;m&quot;, &quot;&quot;, &quot;k&quot;, &quot;M&quot;, &quot;G&quot;, &quot;T&quot;, &quot;P&quot;, &quot;E&quot;, &quot;Z&quot;, &quot;Y&quot; ].map(d3_formatPrefix);
+  d3.formatPrefix = function(value, precision) {
+    var i = 0;
+    if (value) {
+      if (value &lt; 0) value *= -1;
+      if (precision) value = d3.round(value, d3_format_precision(value, precision));
+      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
+      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
+    }
+    return d3_formatPrefixes[8 + i / 3];
+  };
+  function d3_formatPrefix(d, i) {
+    var k = Math.pow(10, abs(8 - i) * 3);
+    return {
+      scale: i &gt; 8 ? function(d) {
+        return d / k;
+      } : function(d) {
+        return d * k;
+      },
+      symbol: d
+    };
+  }
+  function d3_locale_numberFormat(locale) {
+    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping ? function(value) {
+      var i = value.length, t = [], j = 0, g = locale_grouping[0];
+      while (i &gt; 0 &amp;&amp; g &gt; 0) {
+        t.push(value.substring(i -= g, i + g));
+        g = locale_grouping[j = (j + 1) % locale_grouping.length];
+      }
+      return t.reverse().join(locale_thousands);
+    } : d3_identity;
+    return function(specifier) {
+      var match = d3_format_re.exec(specifier), fill = match[1] || &quot; &quot;, align = match[2] || &quot;&gt;&quot;, sign = match[3] || &quot;&quot;, symbol = match[4] || &quot;&quot;, zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = &quot;&quot;, suffix = &quot;&quot;, integer = false;
+      if (precision) precision = +precision.substring(1);
+      if (zfill || fill === &quot;0&quot; &amp;&amp; align === &quot;=&quot;) {
+        zfill = fill = &quot;0&quot;;
+        align = &quot;=&quot;;
+        if (comma) width -= Math.floor((width - 1) / 4);
+      }
+      switch (type) {
+       case &quot;n&quot;:
+        comma = true;
+        type = &quot;g&quot;;
+        break;
+
+       case &quot;%&quot;:
+        scale = 100;
+        suffix = &quot;%&quot;;
+        type = &quot;f&quot;;
+        break;
+
+       case &quot;p&quot;:
+        scale = 100;
+        suffix = &quot;%&quot;;
+        type = &quot;r&quot;;
+        break;
+
+       case &quot;b&quot;:
+       case &quot;o&quot;:
+       case &quot;x&quot;:
+       case &quot;X&quot;:
+        if (symbol === &quot;#&quot;) prefix = &quot;0&quot; + type.toLowerCase();
+
+       case &quot;c&quot;:
+       case &quot;d&quot;:
+        integer = true;
+        precision = 0;
+        break;
+
+       case &quot;s&quot;:
+        scale = -1;
+        type = &quot;r&quot;;
+        break;
+      }
+      if (symbol === &quot;$&quot;) prefix = locale_currency[0], suffix = locale_currency[1];
+      if (type == &quot;r&quot; &amp;&amp; !precision) type = &quot;g&quot;;
+      if (precision != null) {
+        if (type == &quot;g&quot;) precision = Math.max(1, Math.min(21, precision)); else if (type == &quot;e&quot; || type == &quot;f&quot;) precision = Math.max(0, Math.min(20, precision));
+      }
+      type = d3_format_types.get(type) || d3_format_typeDefault;
+      var zcomma = zfill &amp;&amp; comma;
+      return function(value) {
+        var fullSuffix = suffix;
+        if (integer &amp;&amp; value % 1) return &quot;&quot;;
+        var negative = value &lt; 0 || value === 0 &amp;&amp; 1 / value &lt; 0 ? (value = -value, &quot;-&quot;) : sign;
+        if (scale &lt; 0) {
+          var unit = d3.formatPrefix(value, precision);
+          value = unit.scale(value);
+          fullSuffix = unit.symbol + suffix;
+        } else {
+          value *= scale;
+        }
+        value = type(value, precision);
+        var i = value.lastIndexOf(&quot;.&quot;), before = i &lt; 0 ? value : value.substring(0, i), after = i &lt; 0 ? &quot;&quot; : locale_decimal + value.substring(i + 1);
+        if (!zfill &amp;&amp; comma) before = formatGroup(before);
+        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length &lt; width ? new Array(length = width - length + 1).join(fill) : &quot;&quot;;
+        if (zcomma) before = formatGroup(padding + before);
+        negative += prefix;
+        value = before + after;
+        return (align === &quot;&lt;&quot; ? negative + value + padding : align === &quot;&gt;&quot; ? padding + negative + value : align === &quot;^&quot; ? padding.substring(0, length &gt;&gt;= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
+      };
+    };
+  }
+  var d3_format_re = /(?:([^{])?([&lt;&gt;=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
+  var d3_format_types = d3.map({
+    b: function(x) {
+      return x.toString(2);
+    },
+    c: function(x) {
+      return String.fromCharCode(x);
+    },
+    o: function(x) {
+      return x.toString(8);
+    },
+    x: function(x) {
+      return x.toString(16);
+    },
+    X: function(x) {
+      return x.toString(16).toUpperCase();
+    },
+    g: function(x, p) {
+      return x.toPrecision(p);
+    },
+    e: function(x, p) {
+      return x.toExponential(p);
+    },
+    f: function(x, p) {
+      return x.toFixed(p);
+    },
+    r: function(x, p) {
+      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
+    }
+  });
+  function d3_format_typeDefault(x) {
+    return x + &quot;&quot;;
+  }
+  var d3_time = d3.time = {}, d3_date = Date;
+  function d3_date_utc() {
+    this._ = new Date(arguments.length &gt; 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
+  }
+  d3_date_utc.prototype = {
+    getDate: function() {
+      return this._.getUTCDate();
+    },
+    getDay: function() {
+      return this._.getUTCDay();
+    },
+    getFullYear: function() {
+      return this._.getUTCFullYear();
+    },
+    getHours: function() {
+      return this._.getUTCHours();
+    },
+    getMilliseconds: function() {
+      return this._.getUTCMilliseconds();
+    },
+    getMinutes: function() {
+      return this._.getUTCMinutes();
+    },
+    getMonth: function() {
+      return this._.getUTCMonth();
+    },
+    getSeconds: function() {
+      return this._.getUTCSeconds();
+    },
+    getTime: function() {
+      return this._.getTime();
+    },
+    getTimezoneOffset: function() {
+      return 0;
+    },
+    valueOf: function() {
+      return this._.valueOf();
+    },
+    setDate: function() {
+      d3_time_prototype.setUTCDate.apply(this._, arguments);
+    },
+    setDay: function() {
+      d3_time_prototype.setUTCDay.apply(this._, arguments);
+    },
+    setFullYear: function() {
+      d3_time_prototype.setUTCFullYear.apply(this._, arguments);
+    },
+    setHours: function() {
+      d3_time_prototype.setUTCHours.apply(this._, arguments);
+    },
+    setMilliseconds: function() {
+      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
+    },
+    setMinutes: function() {
+      d3_time_prototype.setUTCMinutes.apply(this._, arguments);
+    },
+    setMonth: function() {
+      d3_time_prototype.setUTCMonth.apply(this._, arguments);
+    },
+    setSeconds: function() {
+      d3_time_prototype.setUTCSeconds.apply(this._, arguments);
+    },
+    setTime: function() {
+      d3_time_prototype.setTime.apply(this._, arguments);
+    }
+  };
+  var d3_time_prototype = Date.prototype;
+  function d3_time_interval(local, step, number) {
+    function round(date) {
+      var d0 = local(date), d1 = offset(d0, 1);
+      return date - d0 &lt; d1 - date ? d0 : d1;
+    }
+    function ceil(date) {
+      step(date = local(new d3_date(date - 1)), 1);
+      return date;
+    }
+    function offset(date, k) {
+      step(date = new d3_date(+date), k);
+      return date;
+    }
+    function range(t0, t1, dt) {
+      var time = ceil(t0), times = [];
+      if (dt &gt; 1) {
+        while (time &lt; t1) {
+          if (!(number(time) % dt)) times.push(new Date(+time));
+          step(time, 1);
+        }
+      } else {
+        while (time &lt; t1) times.push(new Date(+time)), step(time, 1);
+      }
+      return times;
+    }
+    function range_utc(t0, t1, dt) {
+      try {
+        d3_date = d3_date_utc;
+        var utc = new d3_date_utc();
+        utc._ = t0;
+        return range(utc, t1, dt);
+      } finally {
+        d3_date = Date;
+      }
+    }
+    local.floor = local;
+    local.round = round;
+    local.ceil = ceil;
+    local.offset = offset;
+    local.range = range;
+    var utc = local.utc = d3_time_interval_utc(local);
+    utc.floor = utc;
+    utc.round = d3_time_interval_utc(round);
+    utc.ceil = d3_time_interval_utc(ceil);
+    utc.offset = d3_time_interval_utc(offset);
+    utc.range = range_utc;
+    return local;
+  }
+  function d3_time_interval_utc(method) {
+    return function(date, k) {
+      try {
+        d3_date = d3_date_utc;
+        var utc = new d3_date_utc();
+        utc._ = date;
+        return method(utc, k)._;
+      } finally {
+        d3_date = Date;
+      }
+    };
+  }
+  d3_time.year = d3_time_interval(function(date) {
+    date = d3_time.day(date);
+    date.setMonth(0, 1);
+    return date;
+  }, function(date, offset) {
+    date.setFullYear(date.getFullYear() + offset);
+  }, function(date) {
+    return date.getFullYear();
+  });
+  d3_time.years = d3_time.year.range;
+  d3_time.years.utc = d3_time.year.utc.range;
+  d3_time.day = d3_time_interval(function(date) {
+    var day = new d3_date(2e3, 0);
+    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+    return day;
+  }, function(date, offset) {
+    date.setDate(date.getDate() + offset);
+  }, function(date) {
+    return date.getDate() - 1;
+  });
+  d3_time.days = d3_time.day.range;
+  d3_time.days.utc = d3_time.day.utc.range;
+  d3_time.dayOfYear = function(date) {
+    var year = d3_time.year(date);
+    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
+  };
+  [ &quot;sunday&quot;, &quot;monday&quot;, &quot;tuesday&quot;, &quot;wednesday&quot;, &quot;thursday&quot;, &quot;friday&quot;, &quot;saturday&quot; ].forEach(function(day, i) {
+    i = 7 - i;
+    var interval = d3_time[day] = d3_time_interval(function(date) {
+      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
+      return date;
+    }, function(date, offset) {
+      date.setDate(date.getDate() + Math.floor(offset) * 7);
+    }, function(date) {
+      var day = d3_time.year(date).getDay();
+      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
+    });
+    d3_time[day + &quot;s&quot;] = interval.range;
+    d3_time[day + &quot;s&quot;].utc = interval.utc.range;
+    d3_time[day + &quot;OfYear&quot;] = function(date) {
+      var day = d3_time.year(date).getDay();
+      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
+    };
+  });
+  d3_time.week = d3_time.sunday;
+  d3_time.weeks = d3_time.sunday.range;
+  d3_time.weeks.utc = d3_time.sunday.utc.range;
+  d3_time.weekOfYear = d3_time.sundayOfYear;
+  function d3_locale_timeFormat(locale) {
+    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
+    function d3_time_format(template) {
+      var n = template.length;
+      function format(date) {
+        var string = [], i = -1, j = 0, c, p, f;
+        while (++i &lt; n) {
+          if (template.charCodeAt(i) === 37) {
+            string.push(template.substring(j, i));
+            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
+            if (f = d3_time_formats[c]) c = f(date, p == null ? c === &quot;e&quot; ? &quot; &quot; : &quot;0&quot; : p);
+            string.push(c);
+            j = i + 1;
+          }
+        }
+        string.push(template.substring(j, i));
+        return string.join(&quot;&quot;);
+      }
+      format.parse = function(string) {
+        var d = {
+          y: 1900,
+          m: 0,
+          d: 1,
+          H: 0,
+          M: 0,
+          S: 0,
+          L: 0,
+          Z: null
+        }, i = d3_time_parse(d, template, string, 0);
+        if (i != string.length) return null;
+        if (&quot;p&quot; in d) d.H = d.H % 12 + d.p * 12;
+        var localZ = d.Z != null &amp;&amp; d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
+        if (&quot;j&quot; in d) date.setFullYear(d.y, 0, d.j); else if (&quot;w&quot; in d &amp;&amp; (&quot;W&quot; in d || &quot;U&quot; in d)) {
+          date.setFullYear(d.y, 0, 1);
+          date.setFullYear(d.y, 0, &quot;W&quot; in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
+        } else date.setFullYear(d.y, d.m, d.d);
+        date.setHours(d.H + Math.floor(d.Z / 100), d.M + d.Z % 100, d.S, d.L);
+        return localZ ? date._ : date;
+      };
+      format.toString = function() {
+        return template;
+      };
+      return format;
+    }
+    function d3_time_parse(date, template, string, j) {
+      var c, p, t, i = 0, n = template.length, m = string.length;
+      while (i &lt; n) {
+        if (j &gt;= m) return -1;
+        c = template.charCodeAt(i++);
+        if (c === 37) {
+          t = template.charAt(i++);
+          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
+          if (!p || (j = p(date, string, j)) &lt; 0) return -1;
+        } else if (c != string.charCodeAt(j++)) {
+          return -1;
+        }
+      }
+      return j;
+    }
+    d3_time_format.utc = function(template) {
+      var local = d3_time_format(template);
+      function format(date) {
+        try {
+          d3_date = d3_date_utc;
+          var utc = new d3_date();
+          utc._ = date;
+          return local(utc);
+        } finally {
+          d3_date = Date;
+        }
+      }
+      format.parse = function(string) {
+        try {
+          d3_date = d3_date_utc;
+          var date = local.parse(string);
+          return date &amp;&amp; date._;
+        } finally {
+          d3_date = Date;
+        }
+      };
+      format.toString = local.toString;
+      return format;
+    };
+    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
+    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
+    locale_periods.forEach(function(p, i) {
+      d3_time_periodLookup.set(p.toLowerCase(), i);
+    });
+    var d3_time_formats = {
+      a: function(d) {
+        return locale_shortDays[d.getDay()];
+      },
+      A: function(d) {
+        return locale_days[d.getDay()];
+      },
+      b: function(d) {
+        return locale_shortMonths[d.getMonth()];
+      },
+      B: function(d) {
+        return locale_months[d.getMonth()];
+      },
+      c: d3_time_format(locale_dateTime),
+      d: function(d, p) {
+        return d3_time_formatPad(d.getDate(), p, 2);
+      },
+      e: function(d, p) {
+        return d3_time_formatPad(d.getDate(), p, 2);
+      },
+      H: function(d, p) {
+        return d3_time_formatPad(d.getHours(), p, 2);
+      },
+      I: function(d, p) {
+        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
+      },
+      j: function(d, p) {
+        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
+      },
+      L: function(d, p) {
+        return d3_time_formatPad(d.getMilliseconds(), p, 3);
+      },
+      m: function(d, p) {
+        return d3_time_formatPad(d.getMonth() + 1, p, 2);
+      },
+      M: function(d, p) {
+        return d3_time_formatPad(d.getMinutes(), p, 2);
+      },
+      p: function(d) {
+        return locale_periods[+(d.getHours() &gt;= 12)];
+      },
+      S: function(d, p) {
+        return d3_time_formatPad(d.getSeconds(), p, 2);
+      },
+      U: function(d, p) {
+        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
+      },
+      w: function(d) {
+        return d.getDay();
+      },
+      W: function(d, p) {
+        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
+      },
+      x: d3_time_format(locale_date),
+      X: d3_time_format(locale_time),
+      y: function(d, p) {
+        return d3_time_formatPad(d.getFullYear() % 100, p, 2);
+      },
+      Y: function(d, p) {
+        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
+      },
+      Z: d3_time_zone,
+      &quot;%&quot;: function() {
+        return &quot;%&quot;;
+      }
+    };
+    var d3_time_parsers = {
+      a: d3_time_parseWeekdayAbbrev,
+      A: d3_time_parseWeekday,
+      b: d3_time_parseMonthAbbrev,
+      B: d3_time_parseMonth,
+      c: d3_time_parseLocaleFull,
+      d: d3_time_parseDay,
+      e: d3_time_parseDay,
+      H: d3_time_parseHour24,
+      I: d3_time_parseHour24,
+      j: d3_time_parseDayOfYear,
+      L: d3_time_parseMilliseconds,
+      m: d3_time_parseMonthNumber,
+      M: d3_time_parseMinutes,
+      p: d3_time_parseAmPm,
+      S: d3_time_parseSeconds,
+      U: d3_time_parseWeekNumberSunday,
+      w: d3_time_parseWeekdayNumber,
+      W: d3_time_parseWeekNumberMonday,
+      x: d3_time_parseLocaleDate,
+      X: d3_time_parseLocaleTime,
+      y: d3_time_parseYear,
+      Y: d3_time_parseFullYear,
+      Z: d3_time_parseZone,
+      &quot;%&quot;: d3_time_parseLiteralPercent
+    };
+    function d3_time_parseWeekdayAbbrev(date, string, i) {
+      d3_time_dayAbbrevRe.lastIndex = 0;
+      var n = d3_time_dayAbbrevRe.exec(string.substring(i));
+      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseWeekday(date, string, i) {
+      d3_time_dayRe.lastIndex = 0;
+      var n = d3_time_dayRe.exec(string.substring(i));
+      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseMonthAbbrev(date, string, i) {
+      d3_time_monthAbbrevRe.lastIndex = 0;
+      var n = d3_time_monthAbbrevRe.exec(string.substring(i));
+      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseMonth(date, string, i) {
+      d3_time_monthRe.lastIndex = 0;
+      var n = d3_time_monthRe.exec(string.substring(i));
+      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseLocaleFull(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
+    }
+    function d3_time_parseLocaleDate(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
+    }
+    function d3_time_parseLocaleTime(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
+    }
+    function d3_time_parseAmPm(date, string, i) {
+      var n = d3_time_periodLookup.get(string.substring(i, i += 2).toLowerCase());
+      return n == null ? -1 : (date.p = n, i);
+    }
+    return d3_time_format;
+  }
+  var d3_time_formatPads = {
+    &quot;-&quot;: &quot;&quot;,
+    _: &quot; &quot;,
+    &quot;0&quot;: &quot;0&quot;
+  }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
+  function d3_time_formatPad(value, fill, width) {
+    var sign = value &lt; 0 ? &quot;-&quot; : &quot;&quot;, string = (sign ? -value : value) + &quot;&quot;, length = string.length;
+    return sign + (length &lt; width ? new Array(width - length + 1).join(fill) + string : string);
+  }
+  function d3_time_formatRe(names) {
+    return new RegExp(&quot;^(?:&quot; + names.map(d3.requote).join(&quot;|&quot;) + &quot;)&quot;, &quot;i&quot;);
+  }
+  function d3_time_formatLookup(names) {
+    var map = new d3_Map(), i = -1, n = names.length;
+    while (++i &lt; n) map.set(names[i].toLowerCase(), i);
+    return map;
+  }
+  function d3_time_parseWeekdayNumber(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 1));
+    return n ? (date.w = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseWeekNumberSunday(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i));
+    return n ? (date.U = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseWeekNumberMonday(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i));
+    return n ? (date.W = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseFullYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 4));
+    return n ? (date.y = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
+  }
+  function d3_time_parseZone(date, string, i) {
+    return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = -string, 
+    i + 5) : -1;
+  }
+  function d3_time_expandYear(d) {
+    return d + (d &gt; 68 ? 1900 : 2e3);
+  }
+  function d3_time_parseMonthNumber(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
+  }
+  function d3_time_parseDay(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.d = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseDayOfYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+    return n ? (date.j = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseHour24(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.H = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseMinutes(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.M = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseSeconds(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.S = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseMilliseconds(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+    return n ? (date.L = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_zone(d) {
+    var z = d.getTimezoneOffset(), zs = z &gt; 0 ? &quot;-&quot; : &quot;+&quot;, zh = ~~(abs(z) / 60), zm = abs(z) % 60;
+    return zs + d3_time_formatPad(zh, &quot;0&quot;, 2) + d3_time_formatPad(zm, &quot;0&quot;, 2);
+  }
+  function d3_time_parseLiteralPercent(date, string, i) {
+    d3_time_percentRe.lastIndex = 0;
+    var n = d3_time_percentRe.exec(string.substring(i, i + 1));
+    return n ? i + n[0].length : -1;
+  }
+  function d3_time_formatMulti(formats) {
+    var n = formats.length, i = -1;
+    while (++i &lt; n) formats[i][0] = this(formats[i][0]);
+    return function(date) {
+      var i = 0, f = formats[i];
+      while (!f[1](date)) f = formats[++i];
+      return f[0](date);
+    };
+  }
+  d3.locale = function(locale) {
+    return {
+      numberFormat: d3_locale_numberFormat(locale),
+      timeFormat: d3_locale_timeFormat(locale)
+    };
+  };
+  var d3_locale_enUS = d3.locale({
+    decimal: &quot;.&quot;,
+    thousands: &quot;,&quot;,
+    grouping: [ 3 ],
+    currency: [ &quot;$&quot;, &quot;&quot; ],
+    dateTime: &quot;%a %b %e %X %Y&quot;,
+    date: &quot;%m/%d/%Y&quot;,
+    time: &quot;%H:%M:%S&quot;,
+    periods: [ &quot;AM&quot;, &quot;PM&quot; ],
+    days: [ &quot;Sunday&quot;, &quot;Monday&quot;, &quot;Tuesday&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot; ],
+    shortDays: [ &quot;Sun&quot;, &quot;Mon&quot;, &quot;Tue&quot;, &quot;Wed&quot;, &quot;Thu&quot;, &quot;Fri&quot;, &quot;Sat&quot; ],
+    months: [ &quot;January&quot;, &quot;February&quot;, &quot;March&quot;, &quot;April&quot;, &quot;May&quot;, &quot;June&quot;, &quot;July&quot;, &quot;August&quot;, &quot;September&quot;, &quot;October&quot;, &quot;November&quot;, &quot;December&quot; ],
+    shortMonths: [ &quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, &quot;Apr&quot;, &quot;May&quot;, &quot;Jun&quot;, &quot;Jul&quot;, &quot;Aug&quot;, &quot;Sep&quot;, &quot;Oct&quot;, &quot;Nov&quot;, &quot;Dec&quot; ]
+  });
+  d3.format = d3_locale_enUS.numberFormat;
+  d3.geo = {};
+  function d3_adder() {}
+  d3_adder.prototype = {
+    s: 0,
+    t: 0,
+    add: function(y) {
+      d3_adderSum(y, this.t, d3_adderTemp);
+      d3_adderSum(d3_adderTemp.s, this.s, this);
+      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
+    },
+    reset: function() {
+      this.s = this.t = 0;
+    },
+    valueOf: function() {
+      return this.s;
+    }
+  };
+  var d3_adderTemp = new d3_adder();
+  function d3_adderSum(a, b, o) {
+    var x = o.s = a + b, bv = x - a, av = x - bv;
+    o.t = a - av + (b - bv);
+  }
+  d3.geo.stream = function(object, listener) {
+    if (object &amp;&amp; d3_geo_streamObjectType.hasOwnProperty(object.type)) {
+      d3_geo_streamObjectType[object.type](object, listener);
+    } else {
+      d3_geo_streamGeometry(object, listener);
+    }
+  };
+  function d3_geo_streamGeometry(geometry, listener) {
+    if (geometry &amp;&amp; d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
+      d3_geo_streamGeometryType[geometry.type](geometry, listener);
+    }
+  }
+  var d3_geo_streamObjectType = {
+    Feature: function(feature, listener) {
+      d3_geo_streamGeometry(feature.geometry, listener);
+    },
+    FeatureCollection: function(object, listener) {
+      var features = object.features, i = -1, n = features.length;
+      while (++i &lt; n) d3_geo_streamGeometry(features[i].geometry, listener);
+    }
+  };
+  var d3_geo_streamGeometryType = {
+    Sphere: function(object, listener) {
+      listener.sphere();
+    },
+    Point: function(object, listener) {
+      object = object.coordinates;
+      listener.point(object[0], object[1], object[2]);
+    },
+    MultiPoint: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i &lt; n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
+    },
+    LineString: function(object, listener) {
+      d3_geo_streamLine(object.coordinates, listener, 0);
+    },
+    MultiLineString: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i &lt; n) d3_geo_streamLine(coordinates[i], listener, 0);
+    },
+    Polygon: function(object, listener) {
+      d3_geo_streamPolygon(object.coordinates, listener);
+    },
+    MultiPolygon: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i &lt; n) d3_geo_streamPolygon(coordinates[i], listener);
+    },
+    GeometryCollection: function(object, listener) {
+      var geometries = object.geometries, i = -1, n = geometries.length;
+      while (++i &lt; n) d3_geo_streamGeometry(geometries[i], listener);
+    }
+  };
+  function d3_geo_streamLine(coordinates, listener, closed) {
+    var i = -1, n = coordinates.length - closed, coordinate;
+    listener.lineStart();
+    while (++i &lt; n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
+    listener.lineEnd();
+  }
+  function d3_geo_streamPolygon(coordinates, listener) {
+    var i = -1, n = coordinates.length;
+    listener.polygonStart();
+    while (++i &lt; n) d3_geo_streamLine(coordinates[i], listener, 1);
+    listener.polygonEnd();
+  }
+  d3.geo.area = function(object) {
+    d3_geo_areaSum = 0;
+    d3.geo.stream(object, d3_geo_area);
+    return d3_geo_areaSum;
+  };
+  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
+  var d3_geo_area = {
+    sphere: function() {
+      d3_geo_areaSum += 4 * π;
+    },
+    point: d3_noop,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: function() {
+      d3_geo_areaRingSum.reset();
+      d3_geo_area.lineStart = d3_geo_areaRingStart;
+    },
+    polygonEnd: function() {
+      var area = 2 * d3_geo_areaRingSum;
+      d3_geo_areaSum += area &lt; 0 ? 4 * π + area : area;
+      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
+    }
+  };
+  function d3_geo_areaRingStart() {
+    var λ00, φ00, λ0, cosφ0, sinφ0;
+    d3_geo_area.point = function(λ, φ) {
+      d3_geo_area.point = nextPoint;
+      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
+      sinφ0 = Math.sin(φ);
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      φ = φ * d3_radians / 2 + π / 4;
+      var dλ = λ - λ0, sdλ = dλ &gt;= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
+      d3_geo_areaRingSum.add(Math.atan2(v, u));
+      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
+    }
+    d3_geo_area.lineEnd = function() {
+      nextPoint(λ00, φ00);
+    };
+  }
+  function d3_geo_cartesian(spherical) {
+    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
+    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
+  }
+  function d3_geo_cartesianDot(a, b) {
+    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+  }
+  function d3_geo_cartesianCross(a, b) {
+    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
+  }
+  function d3_geo_cartesianAdd(a, b) {
+    a[0] += b[0];
+    a[1] += b[1];
+    a[2] += b[2];
+  }
+  function d3_geo_cartesianScale(vector, k) {
+    return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+  }
+  function d3_geo_cartesianNormalize(d) {
+    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+    d[0] /= l;
+    d[1] /= l;
+    d[2] /= l;
+  }
+  function d3_geo_spherical(cartesian) {
+    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
+  }
+  function d3_geo_sphericalEqual(a, b) {
+    return abs(a[0] - b[0]) &lt; ε &amp;&amp; abs(a[1] - b[1]) &lt; ε;
+  }
+  d3.geo.bounds = function() {
+    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
+    var bound = {
+      point: point,
+      lineStart: lineStart,
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        bound.point = ringPoint;
+        bound.lineStart = ringStart;
+        bound.lineEnd = ringEnd;
+        dλSum = 0;
+        d3_geo_area.polygonStart();
+      },
+      polygonEnd: function() {
+        d3_geo_area.polygonEnd();
+        bound.point = point;
+        bound.lineStart = lineStart;
+        bound.lineEnd = lineEnd;
+        if (d3_geo_areaRingSum &lt; 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum &gt; ε) φ1 = 90; else if (dλSum &lt; -ε) φ0 = -90;
+        range[0] = λ0, range[1] = λ1;
+      }
+    };
+    function point(λ, φ) {
+      ranges.push(range = [ λ0 = λ, λ1 = λ ]);
+      if (φ &lt; φ0) φ0 = φ;
+      if (φ &gt; φ1) φ1 = φ;
+    }
+    function linePoint(λ, φ) {
+      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
+      if (p0) {
+        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
+        d3_geo_cartesianNormalize(inflection);
+        inflection = d3_geo_spherical(inflection);
+        var dλ = λ - λ_, s = dλ &gt; 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) &gt; 180;
+        if (antimeridian ^ (s * λ_ &lt; λi &amp;&amp; λi &lt; s * λ)) {
+          var φi = inflection[1] * d3_degrees;
+          if (φi &gt; φ1) φ1 = φi;
+        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ &lt; λi &amp;&amp; λi &lt; s * λ)) {
+          var φi = -inflection[1] * d3_degrees;
+          if (φi &lt; φ0) φ0 = φi;
+        } else {
+          if (φ &lt; φ0) φ0 = φ;
+          if (φ &gt; φ1) φ1 = φ;
+        }
+        if (antimeridian) {
+          if (λ &lt; λ_) {
+            if (angle(λ0, λ) &gt; angle(λ0, λ1)) λ1 = λ;
+          } else {
+            if (angle(λ, λ1) &gt; angle(λ0, λ1)) λ0 = λ;
+          }
+        } else {
+          if (λ1 &gt;= λ0) {
+            if (λ &lt; λ0) λ0 = λ;
+            if (λ &gt; λ1) λ1 = λ;
+          } else {
+            if (λ &gt; λ_) {
+              if (angle(λ0, λ) &gt; angle(λ0, λ1)) λ1 = λ;
+            } else {
+              if (angle(λ, λ1) &gt; angle(λ0, λ1)) λ0 = λ;
+            }
+          }
+        }
+      } else {
+        point(λ, φ);
+      }
+      p0 = p, λ_ = λ;
+    }
+    function lineStart() {
+      bound.point = linePoint;
+    }
+    function lineEnd() {
+      range[0] = λ0, range[1] = λ1;
+      bound.point = point;
+      p0 = null;
+    }
+    function ringPoint(λ, φ) {
+      if (p0) {
+        var dλ = λ - λ_;
+        dλSum += abs(dλ) &gt; 180 ? dλ + (dλ &gt; 0 ? 360 : -360) : dλ;
+      } else λ__ = λ, φ__ = φ;
+      d3_geo_area.point(λ, φ);
+      linePoint(λ, φ);
+    }
+    function ringStart() {
+      d3_geo_area.lineStart();
+    }
+    function ringEnd() {
+      ringPoint(λ__, φ__);
+      d3_geo_area.lineEnd();
+      if (abs(dλSum) &gt; ε) λ0 = -(λ1 = 180);
+      range[0] = λ0, range[1] = λ1;
+      p0 = null;
+    }
+    function angle(λ0, λ1) {
+      return (λ1 -= λ0) &lt; 0 ? λ1 + 360 : λ1;
+    }
+    function compareRanges(a, b) {
+      return a[0] - b[0];
+    }
+    function withinRange(x, range) {
+      return range[0] &lt;= range[1] ? range[0] &lt;= x &amp;&amp; x &lt;= range[1] : x &lt; range[0] || range[1] &lt; x;
+    }
+    return function(feature) {
+      φ1 = λ1 = -(λ0 = φ0 = Infinity);
+      ranges = [];
+      d3.geo.stream(feature, bound);
+      var n = ranges.length;
+      if (n) {
+        ranges.sort(compareRanges);
+        for (var i = 1, a = ranges[0], b, merged = [ a ]; i &lt; n; ++i) {
+          b = ranges[i];
+          if (withinRange(b[0], a) || withinRange(b[1], a)) {
+            if (angle(a[0], b[1]) &gt; angle(a[0], a[1])) a[1] = b[1];
+            if (angle(b[0], a[1]) &gt; angle(a[0], a[1])) a[0] = b[0];
+          } else {
+            merged.push(a = b);
+          }
+        }
+        var best = -Infinity, dλ;
+        for (var n = merged.length - 1, i = 0, a = merged[n], b; i &lt;= n; a = b, ++i) {
+          b = merged[i];
+          if ((dλ = angle(a[1], b[0])) &gt; best) best = dλ, λ0 = b[0], λ1 = a[1];
+        }
+      }
+      ranges = range = null;
+      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
+    };
+  }();
+  d3.geo.centroid = function(object) {
+    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+    d3.geo.stream(object, d3_geo_centroid);
+    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
+    if (m &lt; ε2) {
+      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
+      if (d3_geo_centroidW1 &lt; ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
+      m = x * x + y * y + z * z;
+      if (m &lt; ε2) return [ NaN, NaN ];
+    }
+    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
+  };
+  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
+  var d3_geo_centroid = {
+    sphere: d3_noop,
+    point: d3_geo_centroidPoint,
+    lineStart: d3_geo_centroidLineStart,
+    lineEnd: d3_geo_centroidLineEnd,
+    polygonStart: function() {
+      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
+    }
+  };
+  function d3_geo_centroidPoint(λ, φ) {
+    λ *= d3_radians;
+    var cosφ = Math.cos(φ *= d3_radians);
+    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
+  }
+  function d3_geo_centroidPointXYZ(x, y, z) {
+    ++d3_geo_centroidW0;
+    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
+    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
+    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
+  }
+  function d3_geo_centroidLineStart() {
+    var x0, y0, z0;
+    d3_geo_centroid.point = function(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians);
+      x0 = cosφ * Math.cos(λ);
+      y0 = cosφ * Math.sin(λ);
+      z0 = Math.sin(φ);
+      d3_geo_centroid.point = nextPoint;
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
+      d3_geo_centroidW1 += w;
+      d3_geo_centroidX1 += w * (x0 + (x0 = x));
+      d3_geo_centroidY1 += w * (y0 + (y0 = y));
+      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    }
+  }
+  function d3_geo_centroidLineEnd() {
+    d3_geo_centroid.point = d3_geo_centroidPoint;
+  }
+  function d3_geo_centroidRingStart() {
+    var λ00, φ00, x0, y0, z0;
+    d3_geo_centroid.point = function(λ, φ) {
+      λ00 = λ, φ00 = φ;
+      d3_geo_centroid.point = nextPoint;
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians);
+      x0 = cosφ * Math.cos(λ);
+      y0 = cosφ * Math.sin(λ);
+      z0 = Math.sin(φ);
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    };
+    d3_geo_centroid.lineEnd = function() {
+      nextPoint(λ00, φ00);
+      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
+      d3_geo_centroid.point = d3_geo_centroidPoint;
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m &amp;&amp; -d3_acos(u) / m, w = Math.atan2(m, u);
+      d3_geo_centroidX2 += v * cx;
+      d3_geo_centroidY2 += v * cy;
+      d3_geo_centroidZ2 += v * cz;
+      d3_geo_centroidW1 += w;
+      d3_geo_centroidX1 += w * (x0 + (x0 = x));
+      d3_geo_centroidY1 += w * (y0 + (y0 = y));
+      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    }
+  }
+  function d3_true() {
+    return true;
+  }
+  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
+    var subject = [], clip = [];
+    segments.forEach(function(segment) {
+      if ((n = segment.length - 1) &lt;= 0) return;
+      var n, p0 = segment[0], p1 = segment[n];
+      if (d3_geo_sphericalEqual(p0, p1)) {
+        listener.lineStart();
+        for (var i = 0; i &lt; n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
+        listener.lineEnd();
+        return;
+      }
+      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
+      a.o = b;
+      subject.push(a);
+      clip.push(b);
+      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
+      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
+      a.o = b;
+      subject.push(a);
+      clip.push(b);
+    });
+    clip.sort(compare);
+    d3_geo_clipPolygonLinkCircular(subject);
+    d3_geo_clipPolygonLinkCircular(clip);
+    if (!subject.length) return;
+    for (var i = 0, entry = clipStartInside, n = clip.length; i &lt; n; ++i) {
+      clip[i].e = entry = !entry;
+    }
+    var start = subject[0], points, point;
+    while (1) {
+      var current = start, isSubject = true;
+      while (current.v) if ((current = current.n) === start) return;
+      points = current.z;
+      listener.lineStart();
+      do {
+        current.v = current.o.v = true;
+        if (current.e) {
+          if (isSubject) {
+            for (var i = 0, n = points.length; i &lt; n; ++i) listener.point((point = points[i])[0], point[1]);
+          } else {
+            interpolate(current.x, current.n.x, 1, listener);
+          }
+          current = current.n;
+        } else {
+          if (isSubject) {
+            points = current.p.z;
+            for (var i = points.length - 1; i &gt;= 0; --i) listener.point((point = points[i])[0], point[1]);
+          } else {
+            interpolate(current.x, current.p.x, -1, listener);
+          }
+          current = current.p;
+        }
+        current = current.o;
+        points = current.z;
+        isSubject = !isSubject;
+      } while (!current.v);
+      listener.lineEnd();
+    }
+  }
+  function d3_geo_clipPolygonLinkCircular(array) {
+    if (!(n = array.length)) return;
+    var n, i = 0, a = array[0], b;
+    while (++i &lt; n) {
+      a.n = b = array[i];
+      b.p = a;
+      a = b;
+    }
+    a.n = b = array[0];
+    b.p = a;
+  }
+  function d3_geo_clipPolygonIntersection(point, points, other, entry) {
+    this.x = point;
+    this.z = points;
+    this.o = other;
+    this.e = entry;
+    this.v = false;
+    this.n = this.p = null;
+  }
+  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
+    return function(rotate, listener) {
+      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
+      var clip = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          clip.point = pointRing;
+          clip.lineStart = ringStart;
+          clip.lineEnd = ringEnd;
+          segments = [];
+          polygon = [];
+        },
+        polygonEnd: function() {
+          clip.point = point;
+          clip.lineStart = lineStart;
+          clip.lineEnd = lineEnd;
+          segments = d3.merge(segments);
+          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
+          if (segments.length) {
+            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
+          } else if (clipStartInside) {
+            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+            listener.lineStart();
+            interpolate(null, null, 1, listener);
+            listener.lineEnd();
+          }
+          if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
+          segments = polygon = null;
+        },
+        sphere: function() {
+          listener.polygonStart();
+          listener.lineStart();
+          interpolate(null, null, 1, listener);
+          listener.lineEnd();
+          listener.polygonEnd();
+        }
+      };
+      function point(λ, φ) {
+        var point = rotate(λ, φ);
+        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
+      }
+      function pointLine(λ, φ) {
+        var point = rotate(λ, φ);
+        line.point(point[0], point[1]);
+      }
+      function lineStart() {
+        clip.point = pointLine;
+        line.lineStart();
+      }
+      function lineEnd() {
+        clip.point = point;
+        line.lineEnd();
+      }
+      var segments;
+      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
+      function pointRing(λ, φ) {
+        ring.push([ λ, φ ]);
+        var point = rotate(λ, φ);
+        ringListener.point(point[0], point[1]);
+      }
+      function ringStart() {
+        ringListener.lineStart();
+        ring = [];
+      }
+      function ringEnd() {
+        pointRing(ring[0][0], ring[0][1]);
+        ringListener.lineEnd();
+        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
+        ring.pop();
+        polygon.push(ring);
+        ring = null;
+        if (!n) return;
+        if (clean &amp; 1) {
+          segment = ringSegments[0];
+          var n = segment.length - 1, i = -1, point;
+          if (n &gt; 0) {
+            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+            listener.lineStart();
+            while (++i &lt; n) listener.point((point = segment[i])[0], point[1]);
+            listener.lineEnd();
+          }
+          return;
+        }
+        if (n &gt; 1 &amp;&amp; clean &amp; 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
+        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+      }
+      return clip;
+    };
+  }
+  function d3_geo_clipSegmentLength1(segment) {
+    return segment.length &gt; 1;
+  }
+  function d3_geo_clipBufferListener() {
+    var lines = [], line;
+    return {
+      lineStart: function() {
+        lines.push(line = []);
+      },
+      point: function(λ, φ) {
+        line.push([ λ, φ ]);
+      },
+      lineEnd: d3_noop,
+      buffer: function() {
+        var buffer = lines;
+        lines = [];
+        line = null;
+        return buffer;
+      },
+      rejoin: function() {
+        if (lines.length &gt; 1) lines.push(lines.pop().concat(lines.shift()));
+      }
+    };
+  }
+  function d3_geo_clipSort(a, b) {
+    return ((a = a.x)[0] &lt; 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] &lt; 0 ? b[1] - halfπ - ε : halfπ - b[1]);
+  }
+  function d3_geo_pointInPolygon(point, polygon) {
+    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
+    d3_geo_areaRingSum.reset();
+    for (var i = 0, n = polygon.length; i &lt; n; ++i) {
+      var ring = polygon[i], m = ring.length;
+      if (!m) continue;
+      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
+      while (true) {
+        if (j === m) j = 0;
+        point = ring[j];
+        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ &gt;= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ &gt; π, k = sinφ0 * sinφ;
+        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
+        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
+        if (antimeridian ^ λ0 &gt;= meridian ^ λ &gt;= meridian) {
+          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
+          d3_geo_cartesianNormalize(arc);
+          var intersection = d3_geo_cartesianCross(meridianNormal, arc);
+          d3_geo_cartesianNormalize(intersection);
+          var φarc = (antimeridian ^ dλ &gt;= 0 ? -1 : 1) * d3_asin(intersection[2]);
+          if (parallel &gt; φarc || parallel === φarc &amp;&amp; (arc[0] || arc[1])) {
+            winding += antimeridian ^ dλ &gt;= 0 ? 1 : -1;
+          }
+        }
+        if (!j++) break;
+        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
+      }
+    }
+    return (polarAngle &lt; -ε || polarAngle &lt; ε &amp;&amp; d3_geo_areaRingSum &lt; 0) ^ winding &amp; 1;
+  }
+  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
+  function d3_geo_clipAntimeridianLine(listener) {
+    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
+    return {
+      lineStart: function() {
+        listener.lineStart();
+        clean = 1;
+      },
+      point: function(λ1, φ1) {
+        var sλ1 = λ1 &gt; 0 ? π : -π, dλ = abs(λ1 - λ0);
+        if (abs(dλ - π) &lt; ε) {
+          listener.point(λ0, φ0 = (φ0 + φ1) / 2 &gt; 0 ? halfπ : -halfπ);
+          listener.point(sλ0, φ0);
+          listener.lineEnd();
+          listener.lineStart();
+          listener.point(sλ1, φ0);
+          listener.point(λ1, φ0);
+          clean = 0;
+        } else if (sλ0 !== sλ1 &amp;&amp; dλ &gt;= π) {
+          if (abs(λ0 - sλ0) &lt; ε) λ0 -= sλ0 * ε;
+          if (abs(λ1 - sλ1) &lt; ε) λ1 -= sλ1 * ε;
+          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
+          listener.point(sλ0, φ0);
+          listener.lineEnd();
+          listener.lineStart();
+          listener.point(sλ1, φ0);
+          clean = 0;
+        }
+        listener.point(λ0 = λ1, φ0 = φ1);
+        sλ0 = sλ1;
+      },
+      lineEnd: function() {
+        listener.lineEnd();
+        λ0 = φ0 = NaN;
+      },
+      clean: function() {
+        return 2 - clean;
+      }
+    };
+  }
+  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
+    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
+    return abs(sinλ0_λ1) &gt; ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
+  }
+  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
+    var φ;
+    if (from == null) {
+      φ = direction * halfπ;
+      listener.point(-π, φ);
+      listener.point(0, φ);
+      listener.point(π, φ);
+      listener.point(π, 0);
+      listener.point(π, -φ);
+      listener.point(0, -φ);
+      listener.point(-π, -φ);
+      listener.point(-π, 0);
+      listener.point(-π, φ);
+    } else if (abs(from[0] - to[0]) &gt; ε) {
+      var s = from[0] &lt; to[0] ? π : -π;
+      φ = direction * s / 2;
+      listener.point(-s, φ);
+      listener.point(0, φ);
+      listener.point(s, φ);
+    } else {
+      listener.point(to[0], to[1]);
+    }
+  }
+  function d3_geo_clipCircle(radius) {
+    var cr = Math.cos(radius), smallRadius = cr &gt; 0, notHemisphere = abs(cr) &gt; ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
+    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
+    function visible(λ, φ) {
+      return Math.cos(λ) * Math.cos(φ) &gt; cr;
+    }
+    function clipLine(listener) {
+      var point0, c0, v0, v00, clean;
+      return {
+        lineStart: function() {
+          v00 = v0 = false;
+          clean = 1;
+        },
+        point: function(λ, φ) {
+          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ &lt; 0 ? π : -π), φ) : 0;
+          if (!point0 &amp;&amp; (v00 = v0 = v)) listener.lineStart();
+          if (v !== v0) {
+            point2 = intersect(point0, point1);
+            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
+              point1[0] += ε;
+              point1[1] += ε;
+              v = visible(point1[0], point1[1]);
+            }
+          }
+          if (v !== v0) {
+            clean = 0;
+            if (v) {
+              listener.lineStart();
+              point2 = intersect(point1, point0);
+              listener.point(point2[0], point2[1]);
+            } else {
+              point2 = intersect(point0, point1);
+              listener.point(point2[0], point2[1]);
+              listener.lineEnd();
+            }
+            point0 = point2;
+          } else if (notHemisphere &amp;&amp; point0 &amp;&amp; smallRadius ^ v) {
+            var t;
+            if (!(c &amp; c0) &amp;&amp; (t = intersect(point1, point0, true))) {
+              clean = 0;
+              if (smallRadius) {
+                listener.lineStart();
+                listener.point(t[0][0], t[0][1]);
+                listener.point(t[1][0], t[1][1]);
+                listener.lineEnd();
+              } else {
+                listener.point(t[1][0], t[1][1]);
+                listener.lineEnd();
+                listener.lineStart();
+                listener.point(t[0][0], t[0][1]);
+              }
+            }
+          }
+          if (v &amp;&amp; (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
+            listener.point(point1[0], point1[1]);
+          }
+          point0 = point1, v0 = v, c0 = c;
+        },
+        lineEnd: function() {
+          if (v0) listener.lineEnd();
+          point0 = null;
+        },
+        clean: function() {
+          return clean | (v00 &amp;&amp; v0) &lt;&lt; 1;
+        }
+      };
+    }
+    function intersect(a, b, two) {
+      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
+      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
+      if (!determinant) return !two &amp;&amp; a;
+      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
+      d3_geo_cartesianAdd(A, B);
+      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
+      if (t2 &lt; 0) return;
+      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
+      d3_geo_cartesianAdd(q, A);
+      q = d3_geo_spherical(q);
+      if (!two) return q;
+      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
+      if (λ1 &lt; λ0) z = λ0, λ0 = λ1, λ1 = z;
+      var δλ = λ1 - λ0, polar = abs(δλ - π) &lt; ε, meridian = polar || δλ &lt; ε;
+      if (!polar &amp;&amp; φ1 &lt; φ0) z = φ0, φ0 = φ1, φ1 = z;
+      if (meridian ? polar ? φ0 + φ1 &gt; 0 ^ q[1] &lt; (abs(q[0] - λ0) &lt; ε ? φ0 : φ1) : φ0 &lt;= q[1] &amp;&amp; q[1] &lt;= φ1 : δλ &gt; π ^ (λ0 &lt;= q[0] &amp;&amp; q[0] &lt;= λ1)) {
+        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
+        d3_geo_cartesianAdd(q1, A);
+        return [ q, d3_geo_spherical(q1) ];
+      }
+    }
+    function code(λ, φ) {
+      var r = smallRadius ? radius : π - radius, code = 0;
+      if (λ &lt; -r) code |= 1; else if (λ &gt; r) code |= 2;
+      if (φ &lt; -r) code |= 4; else if (φ &gt; r) code |= 8;
+      return code;
+    }
+  }
+  function d3_geom_clipLine(x0, y0, x1, y1) {
+    return function(line) {
+      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
+      r = x0 - ax;
+      if (!dx &amp;&amp; r &gt; 0) return;
+      r /= dx;
+      if (dx &lt; 0) {
+        if (r &lt; t0) return;
+        if (r &lt; t1) t1 = r;
+      } else if (dx &gt; 0) {
+        if (r &gt; t1) return;
+        if (r &gt; t0) t0 = r;
+      }
+      r = x1 - ax;
+      if (!dx &amp;&amp; r &lt; 0) return;
+      r /= dx;
+      if (dx &lt; 0) {
+        if (r &gt; t1) return;
+        if (r &gt; t0) t0 = r;
+      } else if (dx &gt; 0) {
+        if (r &lt; t0) return;
+        if (r &lt; t1) t1 = r;
+      }
+      r = y0 - ay;
+      if (!dy &amp;&amp; r &gt; 0) return;
+      r /= dy;
+      if (dy &lt; 0) {
+        if (r &lt; t0) return;
+        if (r &lt; t1) t1 = r;
+      } else if (dy &gt; 0) {
+        if (r &gt; t1) return;
+        if (r &gt; t0) t0 = r;
+      }
+      r = y1 - ay;
+      if (!dy &amp;&amp; r &lt; 0) return;
+      r /= dy;
+      if (dy &lt; 0) {
+        if (r &gt; t1) return;
+        if (r &gt; t0) t0 = r;
+      } else if (dy &gt; 0) {
+        if (r &lt; t0) return;
+        if (r &lt; t1) t1 = r;
+      }
+      if (t0 &gt; 0) line.a = {
+        x: ax + t0 * dx,
+        y: ay + t0 * dy
+      };
+      if (t1 &lt; 1) line.b = {
+        x: ax + t1 * dx,
+        y: ay + t1 * dy
+      };
+      return line;
+    };
+  }
+  var d3_geo_clipExtentMAX = 1e9;
+  d3.geo.clipExtent = function() {
+    var x0, y0, x1, y1, stream, clip, clipExtent = {
+      stream: function(output) {
+        if (stream) stream.valid = false;
+        stream = clip(output);
+        stream.valid = true;
+        return stream;
+      },
+      extent: function(_) {
+        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
+        if (stream) stream.valid = false, stream = null;
+        return clipExtent;
+      }
+    };
+    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
+  };
+  function d3_geo_clipExtent(x0, y0, x1, y1) {
+    return function(listener) {
+      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
+      var clip = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          listener = bufferListener;
+          segments = [];
+          polygon = [];
+          clean = true;
+        },
+        polygonEnd: function() {
+          listener = listener_;
+          segments = d3.merge(segments);
+          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean &amp;&amp; clipStartInside, visible = segments.length;
+          if (inside || visible) {
+            listener.polygonStart();
+            if (inside) {
+              listener.lineStart();
+              interpolate(null, null, 1, listener);
+              listener.lineEnd();
+            }
+            if (visible) {
+              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
+            }
+            listener.polygonEnd();
+          }
+          segments = polygon = ring = null;
+        }
+      };
+      function insidePolygon(p) {
+        var wn = 0, n = polygon.length, y = p[1];
+        for (var i = 0; i &lt; n; ++i) {
+          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j &lt; m; ++j) {
+            b = v[j];
+            if (a[1] &lt;= y) {
+              if (b[1] &gt; y &amp;&amp; d3_cross2d(a, b, p) &gt; 0) ++wn;
+            } else {
+              if (b[1] &lt;= y &amp;&amp; d3_cross2d(a, b, p) &lt; 0) --wn;
+            }
+            a = b;
+          }
+        }
+        return wn !== 0;
+      }
+      function interpolate(from, to, direction, listener) {
+        var a = 0, a1 = 0;
+        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) &lt; 0 ^ direction &gt; 0) {
+          do {
+            listener.point(a === 0 || a === 3 ? x0 : x1, a &gt; 1 ? y1 : y0);
+          } while ((a = (a + direction + 4) % 4) !== a1);
+        } else {
+          listener.point(to[0], to[1]);
+        }
+      }
+      function pointVisible(x, y) {
+        return x0 &lt;= x &amp;&amp; x &lt;= x1 &amp;&amp; y0 &lt;= y &amp;&amp; y &lt;= y1;
+      }
+      function point(x, y) {
+        if (pointVisible(x, y)) listener.point(x, y);
+      }
+      var x__, y__, v__, x_, y_, v_, first, clean;
+      function lineStart() {
+        clip.point = linePoint;
+        if (polygon) polygon.push(ring = []);
+        first = true;
+        v_ = false;
+        x_ = y_ = NaN;
+      }
+      function lineEnd() {
+        if (segments) {
+          linePoint(x__, y__);
+          if (v__ &amp;&amp; v_) bufferListener.rejoin();
+          segments.push(bufferListener.buffer());
+        }
+        clip.point = point;
+        if (v_) listener.lineEnd();
+      }
+      function linePoint(x, y) {
+        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
+        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
+        var v = pointVisible(x, y);
+        if (polygon) ring.push([ x, y ]);
+        if (first) {
+          x__ = x, y__ = y, v__ = v;
+          first = false;
+          if (v) {
+            listener.lineStart();
+            listener.point(x, y);
+          }
+        } else {
+          if (v &amp;&amp; v_) listener.point(x, y); else {
+            var l = {
+              a: {
+                x: x_,
+                y: y_
+              },
+              b: {
+                x: x,
+                y: y
+              }
+            };
+            if (clipLine(l)) {
+              if (!v_) {
+                listener.lineStart();
+                listener.point(l.a.x, l.a.y);
+              }
+              listener.point(l.b.x, l.b.y);
+              if (!v) listener.lineEnd();
+              clean = false;
+            } else if (v) {
+              listener.lineStart();
+              listener.point(x, y);
+              clean = false;
+            }
+          }
+        }
+        x_ = x, y_ = y, v_ = v;
+      }
+      return clip;
+    };
+    function corner(p, direction) {
+      return abs(p[0] - x0) &lt; ε ? direction &gt; 0 ? 0 : 3 : abs(p[0] - x1) &lt; ε ? direction &gt; 0 ? 2 : 1 : abs(p[1] - y0) &lt; ε ? direction &gt; 0 ? 1 : 0 : direction &gt; 0 ? 3 : 2;
+    }
+    function compare(a, b) {
+      return comparePoints(a.x, b.x);
+    }
+    function comparePoints(a, b) {
+      var ca = corner(a, 1), cb = corner(b, 1);
+      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
+    }
+  }
+  function d3_geo_compose(a, b) {
+    function compose(x, y) {
+      return x = a(x, y), b(x[0], x[1]);
+    }
+    if (a.invert &amp;&amp; b.invert) compose.invert = function(x, y) {
+      return x = b.invert(x, y), x &amp;&amp; a.invert(x[0], x[1]);
+    };
+    return compose;
+  }
+  function d3_geo_conic(projectAt) {
+    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
+    p.parallels = function(_) {
+      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
+      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
+    };
+    return p;
+  }
+  function d3_geo_conicEqualArea(φ0, φ1) {
+    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
+    function forward(λ, φ) {
+      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
+      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = ρ0 - y;
+      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
+    };
+    return forward;
+  }
+  (d3.geo.conicEqualArea = function() {
+    return d3_geo_conic(d3_geo_conicEqualArea);
+  }).raw = d3_geo_conicEqualArea;
+  d3.geo.albers = function() {
+    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
+  };
+  d3.geo.albersUsa = function() {
+    var lower48 = d3.geo.albers();
+    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
+    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
+    var point, pointStream = {
+      point: function(x, y) {
+        point = [ x, y ];
+      }
+    }, lower48Point, alaskaPoint, hawaiiPoint;
+    function albersUsa(coordinates) {
+      var x = coordinates[0], y = coordinates[1];
+      point = null;
+      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
+      return point;
+    }
+    albersUsa.invert = function(coordinates) {
+      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
+      return (y &gt;= .12 &amp;&amp; y &lt; .234 &amp;&amp; x &gt;= -.425 &amp;&amp; x &lt; -.214 ? alaska : y &gt;= .166 &amp;&amp; y &lt; .234 &amp;&amp; x &gt;= -.214 &amp;&amp; x &lt; -.115 ? hawaii : lower48).invert(coordinates);
+    };
+    albersUsa.stream = function(stream) {
+      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
+      return {
+        point: function(x, y) {
+          lower48Stream.point(x, y);
+          alaskaStream.point(x, y);
+          hawaiiStream.point(x, y);
+        },
+        sphere: function() {
+          lower48Stream.sphere();
+          alaskaStream.sphere();
+          hawaiiStream.sphere();
+        },
+        lineStart: function() {
+          lower48Stream.lineStart();
+          alaskaStream.lineStart();
+          hawaiiStream.lineStart();
+        },
+        lineEnd: function() {
+          lower48Stream.lineEnd();
+          alaskaStream.lineEnd();
+          hawaiiStream.lineEnd();
+        },
+        polygonStart: function() {
+          lower48Stream.polygonStart();
+          alaskaStream.polygonStart();
+          hawaiiStream.polygonStart();
+        },
+        polygonEnd: function() {
+          lower48Stream.polygonEnd();
+          alaskaStream.polygonEnd();
+          hawaiiStream.polygonEnd();
+        }
+      };
+    };
+    albersUsa.precision = function(_) {
+      if (!arguments.length) return lower48.precision();
+      lower48.precision(_);
+      alaska.precision(_);
+      hawaii.precision(_);
+      return albersUsa;
+    };
+    albersUsa.scale = function(_) {
+      if (!arguments.length) return lower48.scale();
+      lower48.scale(_);
+      alaska.scale(_ * .35);
+      hawaii.scale(_);
+      return albersUsa.translate(lower48.translate());
+    };
+    albersUsa.translate = function(_) {
+      if (!arguments.length) return lower48.translate();
+      var k = lower48.scale(), x = +_[0], y = +_[1];
+      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
+      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+      return albersUsa;
+    };
+    return albersUsa.scale(1070);
+  };
+  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
+    point: d3_noop,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: function() {
+      d3_geo_pathAreaPolygon = 0;
+      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
+      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
+    }
+  };
+  function d3_geo_pathAreaRingStart() {
+    var x00, y00, x0, y0;
+    d3_geo_pathArea.point = function(x, y) {
+      d3_geo_pathArea.point = nextPoint;
+      x00 = x0 = x, y00 = y0 = y;
+    };
+    function nextPoint(x, y) {
+      d3_geo_pathAreaPolygon += y0 * x - x0 * y;
+      x0 = x, y0 = y;
+    }
+    d3_geo_pathArea.lineEnd = function() {
+      nextPoint(x00, y00);
+    };
+  }
+  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
+  var d3_geo_pathBounds = {
+    point: d3_geo_pathBoundsPoint,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: d3_noop,
+    polygonEnd: d3_noop
+  };
+  function d3_geo_pathBoundsPoint(x, y) {
+    if (x &lt; d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
+    if (x &gt; d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
+    if (y &lt; d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
+    if (y &gt; d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
+  }
+  function d3_geo_pathBuffer() {
+    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
+    var stream = {
+      point: point,
+      lineStart: function() {
+        stream.point = pointLineStart;
+      },
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        stream.lineEnd = lineEndPolygon;
+      },
+      polygonEnd: function() {
+        stream.lineEnd = lineEnd;
+        stream.point = point;
+      },
+      pointRadius: function(_) {
+        pointCircle = d3_geo_pathBufferCircle(_);
+        return stream;
+      },
+      result: function() {
+        if (buffer.length) {
+          var result = buffer.join(&quot;&quot;);
+          buffer = [];
+          return result;
+        }
+      }
+    };
+    function point(x, y) {
+      buffer.push(&quot;M&quot;, x, &quot;,&quot;, y, pointCircle);
+    }
+    function pointLineStart(x, y) {
+      buffer.push(&quot;M&quot;, x, &quot;,&quot;, y);
+      stream.point = pointLine;
+    }
+    function pointLine(x, y) {
+      buffer.push(&quot;L&quot;, x, &quot;,&quot;, y);
+    }
+    function lineEnd() {
+      stream.point = point;
+    }
+    function lineEndPolygon() {
+      buffer.push(&quot;Z&quot;);
+    }
+    return stream;
+  }
+  function d3_geo_pathBufferCircle(radius) {
+    return &quot;m0,&quot; + radius + &quot;a&quot; + radius + &quot;,&quot; + radius + &quot; 0 1,1 0,&quot; + -2 * radius + &quot;a&quot; + radius + &quot;,&quot; + radius + &quot; 0 1,1 0,&quot; + 2 * radius + &quot;z&quot;;
+  }
+  var d3_geo_pathCentroid = {
+    point: d3_geo_pathCentroidPoint,
+    lineStart: d3_geo_pathCentroidLineStart,
+    lineEnd: d3_geo_pathCentroidLineEnd,
+    polygonStart: function() {
+      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
+      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
+    }
+  };
+  function d3_geo_pathCentroidPoint(x, y) {
+    d3_geo_centroidX0 += x;
+    d3_geo_centroidY0 += y;
+    ++d3_geo_centroidZ0;
+  }
+  function d3_geo_pathCentroidLineStart() {
+    var x0, y0;
+    d3_geo_pathCentroid.point = function(x, y) {
+      d3_geo_pathCentroid.point = nextPoint;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    };
+    function nextPoint(x, y) {
+      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+      d3_geo_centroidX1 += z * (x0 + x) / 2;
+      d3_geo_centroidY1 += z * (y0 + y) / 2;
+      d3_geo_centroidZ1 += z;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    }
+  }
+  function d3_geo_pathCentroidLineEnd() {
+    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+  }
+  function d3_geo_pathCentroidRingStart() {
+    var x00, y00, x0, y0;
+    d3_geo_pathCentroid.point = function(x, y) {
+      d3_geo_pathCentroid.point = nextPoint;
+      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
+    };
+    function nextPoint(x, y) {
+      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+      d3_geo_centroidX1 += z * (x0 + x) / 2;
+      d3_geo_centroidY1 += z * (y0 + y) / 2;
+      d3_geo_centroidZ1 += z;
+      z = y0 * x - x0 * y;
+      d3_geo_centroidX2 += z * (x0 + x);
+      d3_geo_centroidY2 += z * (y0 + y);
+      d3_geo_centroidZ2 += z * 3;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    }
+    d3_geo_pathCentroid.lineEnd = function() {
+      nextPoint(x00, y00);
+    };
+  }
+  function d3_geo_pathContext(context) {
+    var pointRadius = 4.5;
+    var stream = {
+      point: point,
+      lineStart: function() {
+        stream.point = pointLineStart;
+      },
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        stream.lineEnd = lineEndPolygon;
+      },
+      polygonEnd: function() {
+        stream.lineEnd = lineEnd;
+        stream.point = point;
+      },
+      pointRadius: function(_) {
+        pointRadius = _;
+        return stream;
+      },
+      result: d3_noop
+    };
+    function point(x, y) {
+      context.moveTo(x, y);
+      context.arc(x, y, pointRadius, 0, τ);
+    }
+    function pointLineStart(x, y) {
+      context.moveTo(x, y);
+      stream.point = pointLine;
+    }
+    function pointLine(x, y) {
+      context.lineTo(x, y);
+    }
+    function lineEnd() {
+      stream.point = point;
+    }
+    function lineEndPolygon() {
+      context.closePath();
+    }
+    return stream;
+  }
+  function d3_geo_resample(project) {
+    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
+    function resample(stream) {
+      return (maxDepth ? resampleRecursive : resampleNone)(stream);
+    }
+    function resampleNone(stream) {
+      return d3_geo_transformPoint(stream, function(x, y) {
+        x = project(x, y);
+        stream.point(x[0], x[1]);
+      });
+    }
+    function resampleRecursive(stream) {
+      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
+      var resample = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          stream.polygonStart();
+          resample.lineStart = ringStart;
+        },
+        polygonEnd: function() {
+          stream.polygonEnd();
+          resample.lineStart = lineStart;
+        }
+      };
+      function point(x, y) {
+        x = project(x, y);
+        stream.point(x[0], x[1]);
+      }
+      function lineStart() {
+        x0 = NaN;
+        resample.point = linePoint;
+        stream.lineStart();
+      }
+      function linePoint(λ, φ) {
+        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
+        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
+        stream.point(x0, y0);
+      }
+      function lineEnd() {
+        resample.point = point;
+        stream.lineEnd();
+      }
+      function ringStart() {
+        lineStart();
+        resample.point = ringPoint;
+        resample.lineEnd = ringEnd;
+      }
+      function ringPoint(λ, φ) {
+        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
+        resample.point = linePoint;
+      }
+      function ringEnd() {
+        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
+        resample.lineEnd = lineEnd;
+        lineEnd();
+      }
+      return resample;
+    }
+    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
+      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
+      if (d2 &gt; 4 * δ2 &amp;&amp; depth--) {
+        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) &lt; ε || abs(λ0 - λ1) &lt; ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
+        if (dz * dz / d2 &gt; δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) &gt; .3 || a0 * a1 + b0 * b1 + c0 * c1 &lt; cosMinDistance) {
+          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
+          stream.point(x2, y2);
+          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
+        }
+      }
+    }
+    resample.precision = function(_) {
+      if (!arguments.length) return Math.sqrt(δ2);
+      maxDepth = (δ2 = _ * _) &gt; 0 &amp;&amp; 16;
+      return resample;
+    };
+    return resample;
+  }
+  d3.geo.path = function() {
+    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
+    function path(object) {
+      if (object) {
+        if (typeof pointRadius === &quot;function&quot;) contextStream.pointRadius(+pointRadius.apply(this, arguments));
+        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
+        d3.geo.stream(object, cacheStream);
+      }
+      return contextStream.result();
+    }
+    path.area = function(object) {
+      d3_geo_pathAreaSum = 0;
+      d3.geo.stream(object, projectStream(d3_geo_pathArea));
+      return d3_geo_pathAreaSum;
+    };
+    path.centroid = function(object) {
+      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
+      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
+    };
+    path.bounds = function(object) {
+      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
+      d3.geo.stream(object, projectStream(d3_geo_pathBounds));
+      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
+    };
+    path.projection = function(_) {
+      if (!arguments.length) return projection;
+      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
+      return reset();
+    };
+    path.context = function(_) {
+      if (!arguments.length) return context;
+      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
+      if (typeof pointRadius !== &quot;function&quot;) contextStream.pointRadius(pointRadius);
+      return reset();
+    };
+    path.pointRadius = function(_) {
+      if (!arguments.length) return pointRadius;
+      pointRadius = typeof _ === &quot;function&quot; ? _ : (contextStream.pointRadius(+_), +_);
+      return path;
+    };
+    function reset() {
+      cacheStream = null;
+      return path;
+    }
+    return path.projection(d3.geo.albersUsa()).context(null);
+  };
+  function d3_geo_pathProjectStream(project) {
+    var resample = d3_geo_resample(function(x, y) {
+      return project([ x * d3_degrees, y * d3_degrees ]);
+    });
+    return function(stream) {
+      return d3_geo_projectionRadians(resample(stream));
+    };
+  }
+  d3.geo.transform = function(methods) {
+    return {
+      stream: function(stream) {
+        var transform = new d3_geo_transform(stream);
+        for (var k in methods) transform[k] = methods[k];
+        return transform;
+      }
+    };
+  };
+  function d3_geo_transform(stream) {
+    this.stream = stream;
+  }
+  d3_geo_transform.prototype = {
+    point: function(x, y) {
+      this.stream.point(x, y);
+    },
+    sphere: function() {
+      this.stream.sphere();
+    },
+    lineStart: function() {
+      this.stream.lineStart();
+    },
+    lineEnd: function() {
+      this.stream.lineEnd();
+    },
+    polygonStart: function() {
+      this.stream.polygonStart();
+    },
+    polygonEnd: function() {
+      this.stream.polygonEnd();
+    }
+  };
+  function d3_geo_transformPoint(stream, point) {
+    return {
+      point: point,
+      sphere: function() {
+        stream.sphere();
+      },
+      lineStart: function() {
+        stream.lineStart();
+      },
+      lineEnd: function() {
+        stream.lineEnd();
+      },
+      polygonStart: function() {
+        stream.polygonStart();
+      },
+      polygonEnd: function() {
+        stream.polygonEnd();
+      }
+    };
+  }
+  d3.geo.projection = d3_geo_projection;
+  d3.geo.projectionMutator = d3_geo_projectionMutator;
+  function d3_geo_projection(project) {
+    return d3_geo_projectionMutator(function() {
+      return project;
+    })();
+  }
+  function d3_geo_projectionMutator(projectAt) {
+    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
+      x = project(x, y);
+      return [ x[0] * k + δx, δy - x[1] * k ];
+    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
+    function projection(point) {
+      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
+      return [ point[0] * k + δx, δy - point[1] * k ];
+    }
+    function invert(point) {
+      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
+      return point &amp;&amp; [ point[0] * d3_degrees, point[1] * d3_degrees ];
+    }
+    projection.stream = function(output) {
+      if (stream) stream.valid = false;
+      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
+      stream.valid = true;
+      return stream;
+    };
+    projection.clipAngle = function(_) {
+      if (!arguments.length) return clipAngle;
+      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
+      return invalidate();
+    };
+    projection.clipExtent = function(_) {
+      if (!arguments.length) return clipExtent;
+      clipExtent = _;
+      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
+      return invalidate();
+    };
+    projection.scale = function(_) {
+      if (!arguments.length) return k;
+      k = +_;
+      return reset();
+    };
+    projection.translate = function(_) {
+      if (!arguments.length) return [ x, y ];
+      x = +_[0];
+      y = +_[1];
+      return reset();
+    };
+    projection.center = function(_) {
+      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
+      λ = _[0] % 360 * d3_radians;
+      φ = _[1] % 360 * d3_radians;
+      return reset();
+    };
+    projection.rotate = function(_) {
+      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
+      δλ = _[0] % 360 * d3_radians;
+      δφ = _[1] % 360 * d3_radians;
+      δγ = _.length &gt; 2 ? _[2] % 360 * d3_radians : 0;
+      return reset();
+    };
+    d3.rebind(projection, projectResample, &quot;precision&quot;);
+    function reset() {
+      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
+      var center = project(λ, φ);
+      δx = x - center[0] * k;
+      δy = y + center[1] * k;
+      return invalidate();
+    }
+    function invalidate() {
+      if (stream) stream.valid = false, stream = null;
+      return projection;
+    }
+    return function() {
+      project = projectAt.apply(this, arguments);
+      projection.invert = project.invert &amp;&amp; invert;
+      return reset();
+    };
+  }
+  function d3_geo_projectionRadians(stream) {
+    return d3_geo_transformPoint(stream, function(x, y) {
+      stream.point(x * d3_radians, y * d3_radians);
+    });
+  }
+  function d3_geo_equirectangular(λ, φ) {
+    return [ λ, φ ];
+  }
+  (d3.geo.equirectangular = function() {
+    return d3_geo_projection(d3_geo_equirectangular);
+  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
+  d3.geo.rotation = function(rotate) {
+    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length &gt; 2 ? rotate[2] * d3_radians : 0);
+    function forward(coordinates) {
+      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+    }
+    forward.invert = function(coordinates) {
+      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+    };
+    return forward;
+  };
+  function d3_geo_identityRotation(λ, φ) {
+    return [ λ &gt; π ? λ - τ : λ &lt; -π ? λ + τ : λ, φ ];
+  }
+  d3_geo_identityRotation.invert = d3_geo_equirectangular;
+  function d3_geo_rotation(δλ, δφ, δγ) {
+    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
+  }
+  function d3_geo_forwardRotationλ(δλ) {
+    return function(λ, φ) {
+      return λ += δλ, [ λ &gt; π ? λ - τ : λ &lt; -π ? λ + τ : λ, φ ];
+    };
+  }
+  function d3_geo_rotationλ(δλ) {
+    var rotation = d3_geo_forwardRotationλ(δλ);
+    rotation.invert = d3_geo_forwardRotationλ(-δλ);
+    return rotation;
+  }
+  function d3_geo_rotationφγ(δφ, δγ) {
+    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
+    function rotation(λ, φ) {
+      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
+      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
+    }
+    rotation.invert = function(λ, φ) {
+      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
+      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
+    };
+    return rotation;
+  }
+  d3.geo.circle = function() {
+    var origin = [ 0, 0 ], angle, precision = 6, interpolate;
+    function circle() {
+      var center = typeof origin === &quot;function&quot; ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
+      interpolate(null, null, 1, {
+        point: function(x, y) {
+          ring.push(x = rotate(x, y));
+          x[0] *= d3_degrees, x[1] *= d3_degrees;
+        }
+      });
+      return {
+        type: &quot;Polygon&quot;,
+        coordinates: [ ring ]
+      };
+    }
+    circle.origin = function(x) {
+      if (!arguments.length) return origin;
+      origin = x;
+      return circle;
+    };
+    circle.angle = function(x) {
+      if (!arguments.length) return angle;
+      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
+      return circle;
+    };
+    circle.precision = function(_) {
+      if (!arguments.length) return precision;
+      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
+      return circle;
+    };
+    return circle.angle(90);
+  };
+  function d3_geo_circleInterpolate(radius, precision) {
+    var cr = Math.cos(radius), sr = Math.sin(radius);
+    return function(from, to, direction, listener) {
+      var step = direction * precision;
+      if (from != null) {
+        from = d3_geo_circleAngle(cr, from);
+        to = d3_geo_circleAngle(cr, to);
+        if (direction &gt; 0 ? from &lt; to : from &gt; to) from += direction * τ;
+      } else {
+        from = radius + direction * τ;
+        to = radius - .5 * step;
+      }
+      for (var point, t = from; direction &gt; 0 ? t &gt; to : t &lt; to; t -= step) {
+        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
+      }
+    };
+  }
+  function d3_geo_circleAngle(cr, point) {
+    var a = d3_geo_cartesian(point);
+    a[0] -= cr;
+    d3_geo_cartesianNormalize(a);
+    var angle = d3_acos(-a[1]);
+    return ((-a[2] &lt; 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+  }
+  d3.geo.distance = function(a, b) {
+    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
+    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
+  };
+  d3.geo.graticule = function() {
+    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
+    function graticule() {
+      return {
+        type: &quot;MultiLineString&quot;,
+        coordinates: lines()
+      };
+    }
+    function lines() {
+      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
+        return abs(x % DX) &gt; ε;
+      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
+        return abs(y % DY) &gt; ε;
+      }).map(y));
+    }
+    graticule.lines = function() {
+      return lines().map(function(coordinates) {
+        return {
+          type: &quot;LineString&quot;,
+          coordinates: coordinates
+        };
+      });
+    };
+    graticule.outline = function() {
+      return {
+        type: &quot;Polygon&quot;,
+        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
+      };
+    };
+    graticule.extent = function(_) {
+      if (!arguments.length) return graticule.minorExtent();
+      return graticule.majorExtent(_).minorExtent(_);
+    };
+    graticule.majorExtent = function(_) {
+      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
+      X0 = +_[0][0], X1 = +_[1][0];
+      Y0 = +_[0][1], Y1 = +_[1][1];
+      if (X0 &gt; X1) _ = X0, X0 = X1, X1 = _;
+      if (Y0 &gt; Y1) _ = Y0, Y0 = Y1, Y1 = _;
+      return graticule.precision(precision);
+    };
+    graticule.minorExtent = function(_) {
+      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+      x0 = +_[0][0], x1 = +_[1][0];
+      y0 = +_[0][1], y1 = +_[1][1];
+      if (x0 &gt; x1) _ = x0, x0 = x1, x1 = _;
+      if (y0 &gt; y1) _ = y0, y0 = y1, y1 = _;
+      return graticule.precision(precision);
+    };
+    graticule.step = function(_) {
+      if (!arguments.length) return graticule.minorStep();
+      return graticule.majorStep(_).minorStep(_);
+    };
+    graticule.majorStep = function(_) {
+      if (!arguments.length) return [ DX, DY ];
+      DX = +_[0], DY = +_[1];
+      return graticule;
+    };
+    graticule.minorStep = function(_) {
+      if (!arguments.length) return [ dx, dy ];
+      dx = +_[0], dy = +_[1];
+      return graticule;
+    };
+    graticule.precision = function(_) {
+      if (!arguments.length) return precision;
+      precision = +_;
+      x = d3_geo_graticuleX(y0, y1, 90);
+      y = d3_geo_graticuleY(x0, x1, precision);
+      X = d3_geo_graticuleX(Y0, Y1, 90);
+      Y = d3_geo_graticuleY(X0, X1, precision);
+      return graticule;
+    };
+    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
+  };
+  function d3_geo_graticuleX(y0, y1, dy) {
+    var y = d3.range(y0, y1 - ε, dy).concat(y1);
+    return function(x) {
+      return y.map(function(y) {
+        return [ x, y ];
+      });
+    };
+  }
+  function d3_geo_graticuleY(x0, x1, dx) {
+    var x = d3.range(x0, x1 - ε, dx).concat(x1);
+    return function(y) {
+      return x.map(function(x) {
+        return [ x, y ];
+      });
+    };
+  }
+  function d3_source(d) {
+    return d.source;
+  }
+  function d3_target(d) {
+    return d.target;
+  }
+  d3.geo.greatArc = function() {
+    var source = d3_source, source_, target = d3_target, target_;
+    function greatArc() {
+      return {
+        type: &quot;LineString&quot;,
+        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
+      };
+    }
+    greatArc.distance = function() {
+      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
+    };
+    greatArc.source = function(_) {
+      if (!arguments.length) return source;
+      source = _, source_ = typeof _ === &quot;function&quot; ? null : _;
+      return greatArc;
+    };
+    greatArc.target = function(_) {
+      if (!arguments.length) return target;
+      target = _, target_ = typeof _ === &quot;function&quot; ? null : _;
+      return greatArc;
+    };
+    greatArc.precision = function() {
+      return arguments.length ? greatArc : 0;
+    };
+    return greatArc;
+  };
+  d3.geo.interpolate = function(source, target) {
+    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
+  };
+  function d3_geo_interpolate(x0, y0, x1, y1) {
+    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
+    var interpolate = d ? function(t) {
+      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
+      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
+    } : function() {
+      return [ x0 * d3_degrees, y0 * d3_degrees ];
+    };
+    interpolate.distance = d;
+    return interpolate;
+  }
+  d3.geo.length = function(object) {
+    d3_geo_lengthSum = 0;
+    d3.geo.stream(object, d3_geo_length);
+    return d3_geo_lengthSum;
+  };
+  var d3_geo_lengthSum;
+  var d3_geo_length = {
+    sphere: d3_noop,
+    point: d3_noop,
+    lineStart: d3_geo_lengthLineStart,
+    lineEnd: d3_noop,
+    polygonStart: d3_noop,
+    polygonEnd: d3_noop
+  };
+  function d3_geo_lengthLineStart() {
+    var λ0, sinφ0, cosφ0;
+    d3_geo_length.point = function(λ, φ) {
+      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
+      d3_geo_length.point = nextPoint;
+    };
+    d3_geo_length.lineEnd = function() {
+      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
+    };
+    function nextPoint(λ, φ) {
+      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
+      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
+      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
+    }
+  }
+  function d3_geo_azimuthal(scale, angle) {
+    function azimuthal(λ, φ) {
+      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
+      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
+    }
+    azimuthal.invert = function(x, y) {
+      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
+      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ &amp;&amp; y * sinc / ρ) ];
+    };
+    return azimuthal;
+  }
+  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
+    return Math.sqrt(2 / (1 + cosλcosφ));
+  }, function(ρ) {
+    return 2 * Math.asin(ρ / 2);
+  });
+  (d3.geo.azimuthalEqualArea = function() {
+    return d3_geo_projection(d3_geo_azimuthalEqualArea);
+  }).raw = d3_geo_azimuthalEqualArea;
+  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
+    var c = Math.acos(cosλcosφ);
+    return c &amp;&amp; c / Math.sin(c);
+  }, d3_identity);
+  (d3.geo.azimuthalEquidistant = function() {
+    return d3_geo_projection(d3_geo_azimuthalEquidistant);
+  }).raw = d3_geo_azimuthalEquidistant;
+  function d3_geo_conicConformal(φ0, φ1) {
+    var cosφ0 = Math.cos(φ0), t = function(φ) {
+      return Math.tan(π / 4 + φ / 2);
+    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
+    if (!n) return d3_geo_mercator;
+    function forward(λ, φ) {
+      if (F &gt; 0) {
+        if (φ &lt; -halfπ + ε) φ = -halfπ + ε;
+      } else {
+        if (φ &gt; halfπ - ε) φ = halfπ - ε;
+      }
+      var ρ = F / Math.pow(t(φ), n);
+      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
+      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
+    };
+    return forward;
+  }
+  (d3.geo.conicConformal = function() {
+    return d3_geo_conic(d3_geo_conicConformal);
+  }).raw = d3_geo_conicConformal;
+  function d3_geo_conicEquidistant(φ0, φ1) {
+    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
+    if (abs(n) &lt; ε) return d3_geo_equirectangular;
+    function forward(λ, φ) {
+      var ρ = G - φ;
+      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = G - y;
+      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
+    };
+    return forward;
+  }
+  (d3.geo.conicEquidistant = function() {
+    return d3_geo_conic(d3_geo_conicEquidistant);
+  }).raw = d3_geo_conicEquidistant;
+  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
+    return 1 / cosλcosφ;
+  }, Math.atan);
+  (d3.geo.gnomonic = function() {
+    return d3_geo_projection(d3_geo_gnomonic);
+  }).raw = d3_geo_gnomonic;
+  function d3_geo_mercator(λ, φ) {
+    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
+  }
+  d3_geo_mercator.invert = function(x, y) {
+    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
+  };
+  function d3_geo_mercatorProjection(project) {
+    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
+    m.scale = function() {
+      var v = scale.apply(m, arguments);
+      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+    };
+    m.translate = function() {
+      var v = translate.apply(m, arguments);
+      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+    };
+    m.clipExtent = function(_) {
+      var v = clipExtent.apply(m, arguments);
+      if (v === m) {
+        if (clipAuto = _ == null) {
+          var k = π * scale(), t = translate();
+          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
+        }
+      } else if (clipAuto) {
+        v = null;
+      }
+      return v;
+    };
+    return m.clipExtent(null);
+  }
+  (d3.geo.mercator = function() {
+    return d3_geo_mercatorProjection(d3_geo_mercator);
+  }).raw = d3_geo_mercator;
+  var d3_geo_orthographic = d3_geo_azimuthal(function() {
+    return 1;
+  }, Math.asin);
+  (d3.geo.orthographic = function() {
+    return d3_geo_projection(d3_geo_orthographic);
+  }).raw = d3_geo_orthographic;
+  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
+    return 1 / (1 + cosλcosφ);
+  }, function(ρ) {
+    return 2 * Math.atan(ρ);
+  });
+  (d3.geo.stereographic = function() {
+    return d3_geo_projection(d3_geo_stereographic);
+  }).raw = d3_geo_stereographic;
+  function d3_geo_transverseMercator(λ, φ) {
+    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
+  }
+  d3_geo_transverseMercator.invert = function(x, y) {
+    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
+  };
+  (d3.geo.transverseMercator = function() {
+    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
+    projection.center = function(_) {
+      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
+    };
+    projection.rotate = function(_) {
+      return _ ? rotate([ _[0], _[1], _.length &gt; 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
+      [ _[0], _[1], _[2] - 90 ]);
+    };
+    return rotate([ 0, 0, 90 ]);
+  }).raw = d3_geo_transverseMercator;
+  d3.geom = {};
+  function d3_geom_pointX(d) {
+    return d[0];
+  }
+  function d3_geom_pointY(d) {
+    return d[1];
+  }
+  d3.geom.hull = function(vertices) {
+    var x = d3_geom_pointX, y = d3_geom_pointY;
+    if (arguments.length) return hull(vertices);
+    function hull(data) {
+      if (data.length &lt; 3) return [];
+      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
+      for (i = 0; i &lt; n; i++) {
+        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
+      }
+      points.sort(d3_geom_hullOrder);
+      for (i = 0; i &lt; n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
+      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
+      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
+      for (i = upper.length - 1; i &gt;= 0; --i) polygon.push(data[points[upper[i]][2]]);
+      for (i = +skipLeft; i &lt; lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
+      return polygon;
+    }
+    hull.x = function(_) {
+      return arguments.length ? (x = _, hull) : x;
+    };
+    hull.y = function(_) {
+      return arguments.length ? (y = _, hull) : y;
+    };
+    return hull;
+  };
+  function d3_geom_hullUpper(points) {
+    var n = points.length, hull = [ 0, 1 ], hs = 2;
+    for (var i = 2; i &lt; n; i++) {
+      while (hs &gt; 1 &amp;&amp; d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) &lt;= 0) --hs;
+      hull[hs++] = i;
+    }
+    return hull.slice(0, hs);
+  }
+  function d3_geom_hullOrder(a, b) {
+    return a[0] - b[0] || a[1] - b[1];
+  }
+  d3.geom.polygon = function(coordinates) {
+    d3_subclass(coordinates, d3_geom_polygonPrototype);
+    return coordinates;
+  };
+  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
+  d3_geom_polygonPrototype.area = function() {
+    var i = -1, n = this.length, a, b = this[n - 1], area = 0;
+    while (++i &lt; n) {
+      a = b;
+      b = this[i];
+      area += a[1] * b[0] - a[0] * b[1];
+    }
+    return area * .5;
+  };
+  d3_geom_polygonPrototype.centroid = function(k) {
+    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
+    if (!arguments.length) k = -1 / (6 * this.area());
+    while (++i &lt; n) {
+      a = b;
+      b = this[i];
+      c = a[0] * b[1] - b[0] * a[1];
+      x += (a[0] + b[0]) * c;
+      y += (a[1] + b[1]) * c;
+    }
+    return [ x * k, y * k ];
+  };
+  d3_geom_polygonPrototype.clip = function(subject) {
+    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
+    while (++i &lt; n) {
+      input = subject.slice();
+      subject.length = 0;
+      b = this[i];
+      c = input[(m = input.length - closed) - 1];
+      j = -1;
+      while (++j &lt; m) {
+        d = input[j];
+        if (d3_geom_polygonInside(d, a, b)) {
+          if (!d3_geom_polygonInside(c, a, b)) {
+            subject.push(d3_geom_polygonIntersect(c, d, a, b));
+          }
+          subject.push(d);
+        } else if (d3_geom_polygonInside(c, a, b)) {
+          subject.push(d3_geom_polygonIntersect(c, d, a, b));
+        }
+        c = d;
+      }
+      if (closed) subject.push(subject[0]);
+      a = b;
+    }
+    return subject;
+  };
+  function d3_geom_polygonInside(p, a, b) {
+    return (b[0] - a[0]) * (p[1] - a[1]) &lt; (b[1] - a[1]) * (p[0] - a[0]);
+  }
+  function d3_geom_polygonIntersect(c, d, a, b) {
+    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
+    return [ x1 + ua * x21, y1 + ua * y21 ];
+  }
+  function d3_geom_polygonClosed(coordinates) {
+    var a = coordinates[0], b = coordinates[coordinates.length - 1];
+    return !(a[0] - b[0] || a[1] - b[1]);
+  }
+  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
+  function d3_geom_voronoiBeach() {
+    d3_geom_voronoiRedBlackNode(this);
+    this.edge = this.site = this.circle = null;
+  }
+  function d3_geom_voronoiCreateBeach(site) {
+    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
+    beach.site = site;
+    return beach;
+  }
+  function d3_geom_voronoiDetachBeach(beach) {
+    d3_geom_voronoiDetachCircle(beach);
+    d3_geom_voronoiBeaches.remove(beach);
+    d3_geom_voronoiBeachPool.push(beach);
+    d3_geom_voronoiRedBlackNode(beach);
+  }
+  function d3_geom_voronoiRemoveBeach(beach) {
+    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
+      x: x,
+      y: y
+    }, previous = beach.P, next = beach.N, disappearing = [ beach ];
+    d3_geom_voronoiDetachBeach(beach);
+    var lArc = previous;
+    while (lArc.circle &amp;&amp; abs(x - lArc.circle.x) &lt; ε &amp;&amp; abs(y - lArc.circle.cy) &lt; ε) {
+      previous = lArc.P;
+      disappearing.unshift(lArc);
+      d3_geom_voronoiDetachBeach(lArc);
+      lArc = previous;
+    }
+    disappearing.unshift(lArc);
+    d3_geom_voronoiDetachCircle(lArc);
+    var rArc = next;
+    while (rArc.circle &amp;&amp; abs(x - rArc.circle.x) &lt; ε &amp;&amp; abs(y - rArc.circle.cy) &lt; ε) {
+      next = rArc.N;
+      disappearing.push(rArc);
+      d3_geom_voronoiDetachBeach(rArc);
+      rArc = next;
+    }
+    disappearing.push(rArc);
+    d3_geom_voronoiDetachCircle(rArc);
+    var nArcs = disappearing.length, iArc;
+    for (iArc = 1; iArc &lt; nArcs; ++iArc) {
+      rArc = disappearing[iArc];
+      lArc = disappearing[iArc - 1];
+      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
+    }
+    lArc = disappearing[0];
+    rArc = disappearing[nArcs - 1];
+    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
+    d3_geom_voronoiAttachCircle(lArc);
+    d3_geom_voronoiAttachCircle(rArc);
+  }
+  function d3_geom_voronoiAddBeach(site) {
+    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
+    while (node) {
+      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
+      if (dxl &gt; ε) node = node.L; else {
+        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
+        if (dxr &gt; ε) {
+          if (!node.R) {
+            lArc = node;
+            break;
+          }
+          node = node.R;
+        } else {
+          if (dxl &gt; -ε) {
+            lArc = node.P;
+            rArc = node;
+          } else if (dxr &gt; -ε) {
+            lArc = node;
+            rArc = node.N;
+          } else {
+            lArc = rArc = node;
+          }
+          break;
+        }
+      }
+    }
+    var newArc = d3_geom_voronoiCreateBeach(site);
+    d3_geom_voronoiBeaches.insert(lArc, newArc);
+    if (!lArc &amp;&amp; !rArc) return;
+    if (lArc === rArc) {
+      d3_geom_voronoiDetachCircle(lArc);
+      rArc = d3_geom_voronoiCreateBeach(lArc.site);
+      d3_geom_voronoiBeaches.insert(newArc, rArc);
+      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+      d3_geom_voronoiAttachCircle(lArc);
+      d3_geom_voronoiAttachCircle(rArc);
+      return;
+    }
+    if (!rArc) {
+      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+      return;
+    }
+    d3_geom_voronoiDetachCircle(lArc);
+    d3_geom_voronoiDetachCircle(rArc);
+    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
+      x: (cy * hb - by * hc) / d + ax,
+      y: (bx * hc - cx * hb) / d + ay
+    };
+    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
+    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
+    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
+    d3_geom_voronoiAttachCircle(lArc);
+    d3_geom_voronoiAttachCircle(rArc);
+  }
+  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
+    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
+    if (!pby2) return rfocx;
+    var lArc = arc.P;
+    if (!lArc) return -Infinity;
+    site = lArc.site;
+    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
+    if (!plby2) return lfocx;
+    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
+    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
+    return (rfocx + lfocx) / 2;
+  }
+  function d3_geom_voronoiRightBreakPoint(arc, directrix) {
+    var rArc = arc.N;
+    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
+    var site = arc.site;
+    return site.y === directrix ? site.x : Infinity;
+  }
+  function d3_geom_voronoiCell(site) {
+    this.site = site;
+    this.edges = [];
+  }
+  d3_geom_voronoiCell.prototype.prepare = function() {
+    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
+    while (iHalfEdge--) {
+      edge = halfEdges[iHalfEdge].edge;
+      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
+    }
+    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
+    return halfEdges.length;
+  };
+  function d3_geom_voronoiCloseCells(extent) {
+    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
+    while (iCell--) {
+      cell = cells[iCell];
+      if (!cell || !cell.prepare()) continue;
+      halfEdges = cell.edges;
+      nHalfEdges = halfEdges.length;
+      iHalfEdge = 0;
+      while (iHalfEdge &lt; nHalfEdges) {
+        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
+        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
+        if (abs(x3 - x2) &gt; ε || abs(y3 - y2) &gt; ε) {
+          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) &lt; ε &amp;&amp; y1 - y3 &gt; ε ? {
+            x: x0,
+            y: abs(x2 - x0) &lt; ε ? y2 : y1
+          } : abs(y3 - y1) &lt; ε &amp;&amp; x1 - x3 &gt; ε ? {
+            x: abs(y2 - y1) &lt; ε ? x2 : x1,
+            y: y1
+          } : abs(x3 - x1) &lt; ε &amp;&amp; y3 - y0 &gt; ε ? {
+            x: x1,
+            y: abs(x2 - x1) &lt; ε ? y2 : y0
+          } : abs(y3 - y0) &lt; ε &amp;&amp; x3 - x0 &gt; ε ? {
+            x: abs(y2 - y0) &lt; ε ? x2 : x0,
+            y: y0
+          } : null), cell.site, null));
+          ++nHalfEdges;
+        }
+      }
+    }
+  }
+  function d3_geom_voronoiHalfEdgeOrder(a, b) {
+    return b.angle - a.angle;
+  }
+  function d3_geom_voronoiCircle() {
+    d3_geom_voronoiRedBlackNode(this);
+    this.x = this.y = this.arc = this.site = this.cy = null;
+  }
+  function d3_geom_voronoiAttachCircle(arc) {
+    var lArc = arc.P, rArc = arc.N;
+    if (!lArc || !rArc) return;
+    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
+    if (lSite === rSite) return;
+    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
+    var d = 2 * (ax * cy - ay * cx);
+    if (d &gt;= -ε2) return;
+    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
+    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
+    circle.arc = arc;
+    circle.site = cSite;
+    circle.x = x + bx;
+    circle.y = cy + Math.sqrt(x * x + y * y);
+    circle.cy = cy;
+    arc.circle = circle;
+    var before = null, node = d3_geom_voronoiCircles._;
+    while (node) {
+      if (circle.y &lt; node.y || circle.y === node.y &amp;&amp; circle.x &lt;= node.x) {
+        if (node.L) node = node.L; else {
+          before = node.P;
+          break;
+        }
+      } else {
+        if (node.R) node = node.R; else {
+          before = node;
+          break;
+        }
+      }
+    }
+    d3_geom_voronoiCircles.insert(before, circle);
+    if (!before) d3_geom_voronoiFirstCircle = circle;
+  }
+  function d3_geom_voronoiDetachCircle(arc) {
+    var circle = arc.circle;
+    if (circle) {
+      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
+      d3_geom_voronoiCircles.remove(circle);
+      d3_geom_voronoiCirclePool.push(circle);
+      d3_geom_voronoiRedBlackNode(circle);
+      arc.circle = null;
+    }
+  }
+  function d3_geom_voronoiClipEdges(extent) {
+    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
+    while (i--) {
+      e = edges[i];
+      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) &lt; ε &amp;&amp; abs(e.a.y - e.b.y) &lt; ε) {
+        e.a = e.b = null;
+        edges.splice(i, 1);
+      }
+    }
+  }
+  function d3_geom_voronoiConnectEdge(edge, extent) {
+    var vb = edge.b;
+    if (vb) return true;
+    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
+    if (ry === ly) {
+      if (fx &lt; x0 || fx &gt;= x1) return;
+      if (lx &gt; rx) {
+        if (!va) va = {
+          x: fx,
+          y: y0
+        }; else if (va.y &gt;= y1) return;
+        vb = {
+          x: fx,
+          y: y1
+        };
+      } else {
+        if (!va) va = {
+          x: fx,
+          y: y1
+        }; else if (va.y &lt; y0) return;
+        vb = {
+          x: fx,
+          y: y0
+        };
+      }
+    } else {
+      fm = (lx - rx) / (ry - ly);
+      fb = fy - fm * fx;
+      if (fm &lt; -1 || fm &gt; 1) {
+        if (lx &gt; rx) {
+          if (!va) va = {
+            x: (y0 - fb) / fm,
+            y: y0
+          }; else if (va.y &gt;= y1) return;
+          vb = {
+            x: (y1 - fb) / fm,
+            y: y1
+          };
+        } else {
+          if (!va) va = {
+            x: (y1 - fb) / fm,
+            y: y1
+          }; else if (va.y &lt; y0) return;
+          vb = {
+            x: (y0 - fb) / fm,
+            y: y0
+          };
+        }
+      } else {
+        if (ly &lt; ry) {
+          if (!va) va = {
+            x: x0,
+            y: fm * x0 + fb
+          }; else if (va.x &gt;= x1) return;
+          vb = {
+            x: x1,
+            y: fm * x1 + fb
+          };
+        } else {
+          if (!va) va = {
+            x: x1,
+            y: fm * x1 + fb
+          }; else if (va.x &lt; x0) return;
+          vb = {
+            x: x0,
+            y: fm * x0 + fb
+          };
+        }
+      }
+    }
+    edge.a = va;
+    edge.b = vb;
+    return true;
+  }
+  function d3_geom_voronoiEdge(lSite, rSite) {
+    this.l = lSite;
+    this.r = rSite;
+    this.a = this.b = null;
+  }
+  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
+    var edge = new d3_geom_voronoiEdge(lSite, rSite);
+    d3_geom_voronoiEdges.push(edge);
+    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
+    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
+    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
+    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
+    return edge;
+  }
+  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
+    var edge = new d3_geom_voronoiEdge(lSite, null);
+    edge.a = va;
+    edge.b = vb;
+    d3_geom_voronoiEdges.push(edge);
+    return edge;
+  }
+  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
+    if (!edge.a &amp;&amp; !edge.b) {
+      edge.a = vertex;
+      edge.l = lSite;
+      edge.r = rSite;
+    } else if (edge.l === rSite) {
+      edge.b = vertex;
+    } else {
+      edge.a = vertex;
+    }
+  }
+  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
+    var va = edge.a, vb = edge.b;
+    this.edge = edge;
+    this.site = lSite;
+    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
+  }
+  d3_geom_voronoiHalfEdge.prototype = {
+    start: function() {
+      return this.edge.l === this.site ? this.edge.a : this.edge.b;
+    },
+    end: function() {
+      return this.edge.l === this.site ? this.edge.b : this.edge.a;
+    }
+  };
+  function d3_geom_voronoiRedBlackTree() {
+    this._ = null;
+  }
+  function d3_geom_voronoiRedBlackNode(node) {
+    node.U = node.C = node.L = node.R = node.P = node.N = null;
+  }
+  d3_geom_voronoiRedBlackTree.prototype = {
+    insert: function(after, node) {
+      var parent, grandpa, uncle;
+      if (after) {
+        node.P = after;
+        node.N = after.N;
+        if (after.N) after.N.P = node;
+        after.N = node;
+        if (after.R) {
+          after = after.R;
+          while (after.L) after = after.L;
+          after.L = node;
+        } else {
+          after.R = node;
+        }
+        parent = after;
+      } else if (this._) {
+        after = d3_geom_voronoiRedBlackFirst(this._);
+        node.P = null;
+        node.N = after;
+        after.P = after.L = node;
+        parent = after;
+      } else {
+        node.P = node.N = null;
+        this._ = node;
+        parent = null;
+      }
+      node.L = node.R = null;
+      node.U = parent;
+      node.C = true;
+      after = node;
+      while (parent &amp;&amp; parent.C) {
+        grandpa = parent.U;
+        if (parent === grandpa.L) {
+          uncle = grandpa.R;
+          if (uncle &amp;&amp; uncle.C) {
+            parent.C = uncle.C = false;
+            grandpa.C = true;
+            after = grandpa;
+          } else {
+            if (after === parent.R) {
+              d3_geom_voronoiRedBlackRotateLeft(this, parent);
+              after = parent;
+              parent = after.U;
+            }
+            parent.C = false;
+            grandpa.C = true;
+            d3_geom_voronoiRedBlackRotateRight(this, grandpa);
+          }
+        } else {
+          uncle = grandpa.L;
+          if (uncle &amp;&amp; uncle.C) {
+            parent.C = uncle.C = false;
+            grandpa.C = true;
+            after = grandpa;
+          } else {
+            if (after === parent.L) {
+              d3_geom_voronoiRedBlackRotateRight(this, parent);
+              after = parent;
+              parent = after.U;
+            }
+            parent.C = false;
+            grandpa.C = true;
+            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
+          }
+        }
+        parent = after.U;
+      }
+      this._.C = false;
+    },
+    remove: function(node) {
+      if (node.N) node.N.P = node.P;
+      if (node.P) node.P.N = node.N;
+      node.N = node.P = null;
+      var parent = node.U, sibling, left = node.L, right = node.R, next, red;
+      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
+      if (parent) {
+        if (parent.L === node) parent.L = next; else parent.R = next;
+      } else {
+        this._ = next;
+      }
+      if (left &amp;&amp; right) {
+        red = next.C;
+        next.C = node.C;
+        next.L = left;
+        left.U = next;
+        if (next !== right) {
+          parent = next.U;
+          next.U = node.U;
+          node = next.R;
+          parent.L = node;
+          next.R = right;
+          right.U = next;
+        } else {
+          next.U = parent;
+          parent = next;
+          node = next.R;
+        }
+      } else {
+        red = node.C;
+        node = next;
+      }
+      if (node) node.U = parent;
+      if (red) return;
+      if (node &amp;&amp; node.C) {
+        node.C = false;
+        return;
+      }
+      do {
+        if (node === this._) break;
+        if (node === parent.L) {
+          sibling = parent.R;
+          if (sibling.C) {
+            sibling.C = false;
+            parent.C = true;
+            d3_geom_voronoiRedBlackRotateLeft(this, parent);
+            sibling = parent.R;
+          }
+          if (sibling.L &amp;&amp; sibling.L.C || sibling.R &amp;&amp; sibling.R.C) {
+            if (!sibling.R || !sibling.R.C) {
+              sibling.L.C = false;
+              sibling.C = true;
+              d3_geom_voronoiRedBlackRotateRight(this, sibling);
+              sibling = parent.R;
+            }
+            sibling.C = parent.C;
+            parent.C = sibling.R.C = false;
+            d3_geom_voronoiRedBlackRotateLeft(this, parent);
+            node = this._;
+            break;
+          }
+        } else {
+          sibling = parent.L;
+          if (sibling.C) {
+            sibling.C = false;
+            parent.C = true;
+            d3_geom_voronoiRedBlackRotateRight(this, parent);
+            sibling = parent.L;
+          }
+          if (sibling.L &amp;&amp; sibling.L.C || sibling.R &amp;&amp; sibling.R.C) {
+            if (!sibling.L || !sibling.L.C) {
+              sibling.R.C = false;
+              sibling.C = true;
+              d3_geom_voronoiRedBlackRotateLeft(this, sibling);
+              sibling = parent.L;
+            }
+            sibling.C = parent.C;
+            parent.C = sibling.L.C = false;
+            d3_geom_voronoiRedBlackRotateRight(this, parent);
+            node = this._;
+            break;
+          }
+        }
+        sibling.C = true;
+        node = parent;
+        parent = parent.U;
+      } while (!node.C);
+      if (node) node.C = false;
+    }
+  };
+  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
+    var p = node, q = node.R, parent = p.U;
+    if (parent) {
+      if (parent.L === p) parent.L = q; else parent.R = q;
+    } else {
+      tree._ = q;
+    }
+    q.U = parent;
+    p.U = q;
+    p.R = q.L;
+    if (p.R) p.R.U = p;
+    q.L = p;
+  }
+  function d3_geom_voronoiRedBlackRotateRight(tree, node) {
+    var p = node, q = node.L, parent = p.U;
+    if (parent) {
+      if (parent.L === p) parent.L = q; else parent.R = q;
+    } else {
+      tree._ = q;
+    }
+    q.U = parent;
+    p.U = q;
+    p.L = q.R;
+    if (p.L) p.L.U = p;
+    q.R = p;
+  }
+  function d3_geom_voronoiRedBlackFirst(node) {
+    while (node.L) node = node.L;
+    return node;
+  }
+  function d3_geom_voronoi(sites, bbox) {
+    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
+    d3_geom_voronoiEdges = [];
+    d3_geom_voronoiCells = new Array(sites.length);
+    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
+    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
+    while (true) {
+      circle = d3_geom_voronoiFirstCircle;
+      if (site &amp;&amp; (!circle || site.y &lt; circle.y || site.y === circle.y &amp;&amp; site.x &lt; circle.x)) {
+        if (site.x !== x0 || site.y !== y0) {
+          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
+          d3_geom_voronoiAddBeach(site);
+          x0 = site.x, y0 = site.y;
+        }
+        site = sites.pop();
+      } else if (circle) {
+        d3_geom_voronoiRemoveBeach(circle.arc);
+      } else {
+        break;
+      }
+    }
+    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
+    var diagram = {
+      cells: d3_geom_voronoiCells,
+      edges: d3_geom_voronoiEdges
+    };
+    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
+    return diagram;
+  }
+  function d3_geom_voronoiVertexOrder(a, b) {
+    return b.y - a.y || b.x - a.x;
+  }
+  d3.geom.voronoi = function(points) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
+    if (points) return voronoi(points);
+    function voronoi(data) {
+      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
+      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
+        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
+          var s = e.start();
+          return [ s.x, s.y ];
+        }) : site.x &gt;= x0 &amp;&amp; site.x &lt;= x1 &amp;&amp; site.y &gt;= y0 &amp;&amp; site.y &lt;= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
+        polygon.point = data[i];
+      });
+      return polygons;
+    }
+    function sites(data) {
+      return data.map(function(d, i) {
+        return {
+          x: Math.round(fx(d, i) / ε) * ε,
+          y: Math.round(fy(d, i) / ε) * ε,
+          i: i
+        };
+      });
+    }
+    voronoi.links = function(data) {
+      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
+        return edge.l &amp;&amp; edge.r;
+      }).map(function(edge) {
+        return {
+          source: data[edge.l.i],
+          target: data[edge.r.i]
+        };
+      });
+    };
+    voronoi.triangles = function(data) {
+      var triangles = [];
+      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
+        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
+        while (++j &lt; m) {
+          e0 = e1;
+          s0 = s1;
+          e1 = edges[j].edge;
+          s1 = e1.l === site ? e1.r : e1.l;
+          if (i &lt; s0.i &amp;&amp; i &lt; s1.i &amp;&amp; d3_geom_voronoiTriangleArea(site, s0, s1) &lt; 0) {
+            triangles.push([ data[i], data[s0.i], data[s1.i] ]);
+          }
+        }
+      });
+      return triangles;
+    };
+    voronoi.x = function(_) {
+      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
+    };
+    voronoi.y = function(_) {
+      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
+    };
+    voronoi.clipExtent = function(_) {
+      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
+      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
+      return voronoi;
+    };
+    voronoi.size = function(_) {
+      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent &amp;&amp; clipExtent[1];
+      return voronoi.clipExtent(_ &amp;&amp; [ [ 0, 0 ], _ ]);
+    };
+    return voronoi;
+  };
+  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
+  function d3_geom_voronoiTriangleArea(a, b, c) {
+    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
+  }
+  d3.geom.delaunay = function(vertices) {
+    return d3.geom.voronoi().triangles(vertices);
+  };
+  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, compat;
+    if (compat = arguments.length) {
+      x = d3_geom_quadtreeCompatX;
+      y = d3_geom_quadtreeCompatY;
+      if (compat === 3) {
+        y2 = y1;
+        x2 = x1;
+        y1 = x1 = 0;
+      }
+      return quadtree(points);
+    }
+    function quadtree(data) {
+      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
+      if (x1 != null) {
+        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
+      } else {
+        x2_ = y2_ = -(x1_ = y1_ = Infinity);
+        xs = [], ys = [];
+        n = data.length;
+        if (compat) for (i = 0; i &lt; n; ++i) {
+          d = data[i];
+          if (d.x &lt; x1_) x1_ = d.x;
+          if (d.y &lt; y1_) y1_ = d.y;
+          if (d.x &gt; x2_) x2_ = d.x;
+          if (d.y &gt; y2_) y2_ = d.y;
+          xs.push(d.x);
+          ys.push(d.y);
+        } else for (i = 0; i &lt; n; ++i) {
+          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
+          if (x_ &lt; x1_) x1_ = x_;
+          if (y_ &lt; y1_) y1_ = y_;
+          if (x_ &gt; x2_) x2_ = x_;
+          if (y_ &gt; y2_) y2_ = y_;
+          xs.push(x_);
+          ys.push(y_);
+        }
+      }
+      var dx = x2_ - x1_, dy = y2_ - y1_;
+      if (dx &gt; dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
+      function insert(n, d, x, y, x1, y1, x2, y2) {
+        if (isNaN(x) || isNaN(y)) return;
+        if (n.leaf) {
+          var nx = n.x, ny = n.y;
+          if (nx != null) {
+            if (abs(nx - x) + abs(ny - y) &lt; .01) {
+              insertChild(n, d, x, y, x1, y1, x2, y2);
+            } else {
+              var nPoint = n.point;
+              n.x = n.y = n.point = null;
+              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
+              insertChild(n, d, x, y, x1, y1, x2, y2);
+            }
+          } else {
+            n.x = x, n.y = y, n.point = d;
+          }
+        } else {
+          insertChild(n, d, x, y, x1, y1, x2, y2);
+        }
+      }
+      function insertChild(n, d, x, y, x1, y1, x2, y2) {
+        var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x &gt;= sx, bottom = y &gt;= sy, i = (bottom &lt;&lt; 1) + right;
+        n.leaf = false;
+        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
+        if (right) x1 = sx; else x2 = sx;
+        if (bottom) y1 = sy; else y2 = sy;
+        insert(n, d, x, y, x1, y1, x2, y2);
+      }
+      var root = d3_geom_quadtreeNode();
+      root.add = function(d) {
+        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
+      };
+      root.visit = function(f) {
+        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
+      };
+      i = -1;
+      if (x1 == null) {
+        while (++i &lt; n) {
+          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
+        }
+        --i;
+      } else data.forEach(root.add);
+      xs = ys = data = d = null;
+      return root;
+    }
+    quadtree.x = function(_) {
+      return arguments.length ? (x = _, quadtree) : x;
+    };
+    quadtree.y = function(_) {
+      return arguments.length ? (y = _, quadtree) : y;
+    };
+    quadtree.extent = function(_) {
+      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
+      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 
+      y2 = +_[1][1];
+      return quadtree;
+    };
+    quadtree.size = function(_) {
+      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
+      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
+      return quadtree;
+    };
+    return quadtree;
+  };
+  function d3_geom_quadtreeCompatX(d) {
+    return d.x;
+  }
+  function d3_geom_quadtreeCompatY(d) {
+    return d.y;
+  }
+  function d3_geom_quadtreeNode() {
+    return {
+      leaf: true,
+      nodes: [],
+      point: null,
+      x: null,
+      y: null
+    };
+  }
+  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
+    if (!f(node, x1, y1, x2, y2)) {
+      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
+      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
+      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
+      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
+      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
+    }
+  }
+  d3.interpolateRgb = d3_interpolateRgb;
+  function d3_interpolateRgb(a, b) {
+    a = d3.rgb(a);
+    b = d3.rgb(b);
+    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
+    return function(t) {
+      return &quot;#&quot; + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
+    };
+  }
+  d3.interpolateObject = d3_interpolateObject;
+  function d3_interpolateObject(a, b) {
+    var i = {}, c = {}, k;
+    for (k in a) {
+      if (k in b) {
+        i[k] = d3_interpolate(a[k], b[k]);
+      } else {
+        c[k] = a[k];
+      }
+    }
+    for (k in b) {
+      if (!(k in a)) {
+        c[k] = b[k];
+      }
+    }
+    return function(t) {
+      for (k in i) c[k] = i[k](t);
+      return c;
+    };
+  }
+  d3.interpolateNumber = d3_interpolateNumber;
+  function d3_interpolateNumber(a, b) {
+    b -= a = +a;
+    return function(t) {
+      return a + b * t;
+    };
+  }
+  d3.interpolateString = d3_interpolateString;
+  function d3_interpolateString(a, b) {
+    var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
+    a = a + &quot;&quot;, b = b + &quot;&quot;;
+    while ((am = d3_interpolate_numberA.exec(a)) &amp;&amp; (bm = d3_interpolate_numberB.exec(b))) {
+      if ((bs = bm.index) &gt; bi) {
+        bs = b.substring(bi, bs);
+        if (s[i]) s[i] += bs; else s[++i] = bs;
+      }
+      if ((am = am[0]) === (bm = bm[0])) {
+        if (s[i]) s[i] += bm; else s[++i] = bm;
+      } else {
+        s[++i] = null;
+        q.push({
+          i: i,
+          x: d3_interpolateNumber(am, bm)
+        });
+      }
+      bi = d3_interpolate_numberB.lastIndex;
+    }
+    if (bi &lt; b.length) {
+      bs = b.substring(bi);
+      if (s[i]) s[i] += bs; else s[++i] = bs;
+    }
+    return s.length &lt; 2 ? q[0] ? (b = q[0].x, function(t) {
+      return b(t) + &quot;&quot;;
+    }) : function() {
+      return b;
+    } : (b = q.length, function(t) {
+      for (var i = 0, o; i &lt; b; ++i) s[(o = q[i]).i] = o.x(t);
+      return s.join(&quot;&quot;);
+    });
+  }
+  var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, &quot;g&quot;);
+  d3.interpolate = d3_interpolate;
+  function d3_interpolate(a, b) {
+    var i = d3.interpolators.length, f;
+    while (--i &gt;= 0 &amp;&amp; !(f = d3.interpolators[i](a, b))) ;
+    return f;
+  }
+  d3.interpolators = [ function(a, b) {
+    var t = typeof b;
+    return (t === &quot;string&quot; ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === &quot;object&quot; &amp;&amp; isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
+  } ];
+  d3.interpolateArray = d3_interpolateArray;
+  function d3_interpolateArray(a, b) {
+    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
+    for (i = 0; i &lt; n0; ++i) x.push(d3_interpolate(a[i], b[i]));
+    for (;i &lt; na; ++i) c[i] = a[i];
+    for (;i &lt; nb; ++i) c[i] = b[i];
+    return function(t) {
+      for (i = 0; i &lt; n0; ++i) c[i] = x[i](t);
+      return c;
+    };
+  }
+  var d3_ease_default = function() {
+    return d3_identity;
+  };
+  var d3_ease = d3.map({
+    linear: d3_ease_default,
+    poly: d3_ease_poly,
+    quad: function() {
+      return d3_ease_quad;
+    },
+    cubic: function() {
+      return d3_ease_cubic;
+    },
+    sin: function() {
+      return d3_ease_sin;
+    },
+    exp: function() {
+      return d3_ease_exp;
+    },
+    circle: function() {
+      return d3_ease_circle;
+    },
+    elastic: d3_ease_elastic,
+    back: d3_ease_back,
+    bounce: function() {
+      return d3_ease_bounce;
+    }
+  });
+  var d3_ease_mode = d3.map({
+    &quot;in&quot;: d3_identity,
+    out: d3_ease_reverse,
+    &quot;in-out&quot;: d3_ease_reflect,
+    &quot;out-in&quot;: function(f) {
+      return d3_ease_reflect(d3_ease_reverse(f));
+    }
+  });
+  d3.ease = function(name) {
+    var i = name.indexOf(&quot;-&quot;), t = i &gt;= 0 ? name.substring(0, i) : name, m = i &gt;= 0 ? name.substring(i + 1) : &quot;in&quot;;
+    t = d3_ease.get(t) || d3_ease_default;
+    m = d3_ease_mode.get(m) || d3_identity;
+    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
+  };
+  function d3_ease_clamp(f) {
+    return function(t) {
+      return t &lt;= 0 ? 0 : t &gt;= 1 ? 1 : f(t);
+    };
+  }
+  function d3_ease_reverse(f) {
+    return function(t) {
+      return 1 - f(1 - t);
+    };
+  }
+  function d3_ease_reflect(f) {
+    return function(t) {
+      return .5 * (t &lt; .5 ? f(2 * t) : 2 - f(2 - 2 * t));
+    };
+  }
+  function d3_ease_quad(t) {
+    return t * t;
+  }
+  function d3_ease_cubic(t) {
+    return t * t * t;
+  }
+  function d3_ease_cubicInOut(t) {
+    if (t &lt;= 0) return 0;
+    if (t &gt;= 1) return 1;
+    var t2 = t * t, t3 = t2 * t;
+    return 4 * (t &lt; .5 ? t3 : 3 * (t - t2) + t3 - .75);
+  }
+  function d3_ease_poly(e) {
+    return function(t) {
+      return Math.pow(t, e);
+    };
+  }
+  function d3_ease_sin(t) {
+    return 1 - Math.cos(t * halfπ);
+  }
+  function d3_ease_exp(t) {
+    return Math.pow(2, 10 * (t - 1));
+  }
+  function d3_ease_circle(t) {
+    return 1 - Math.sqrt(1 - t * t);
+  }
+  function d3_ease_elastic(a, p) {
+    var s;
+    if (arguments.length &lt; 2) p = .45;
+    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
+    return function(t) {
+      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
+    };
+  }
+  function d3_ease_back(s) {
+    if (!s) s = 1.70158;
+    return function(t) {
+      return t * t * ((s + 1) * t - s);
+    };
+  }
+  function d3_ease_bounce(t) {
+    return t &lt; 1 / 2.75 ? 7.5625 * t * t : t &lt; 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t &lt; 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
+  }
+  d3.interpolateHcl = d3_interpolateHcl;
+  function d3_interpolateHcl(a, b) {
+    a = d3.hcl(a);
+    b = d3.hcl(b);
+    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
+    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
+    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh &gt; 180) bh -= 360; else if (bh &lt; -180) bh += 360;
+    return function(t) {
+      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + &quot;&quot;;
+    };
+  }
+  d3.interpolateHsl = d3_interpolateHsl;
+  function d3_interpolateHsl(a, b) {
+    a = d3.hsl(a);
+    b = d3.hsl(b);
+    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
+    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
+    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh &gt; 180) bh -= 360; else if (bh &lt; -180) bh += 360;
+    return function(t) {
+      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + &quot;&quot;;
+    };
+  }
+  d3.interpolateLab = d3_interpolateLab;
+  function d3_interpolateLab(a, b) {
+    a = d3.lab(a);
+    b = d3.lab(b);
+    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
+    return function(t) {
+      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + &quot;&quot;;
+    };
+  }
+  d3.interpolateRound = d3_interpolateRound;
+  function d3_interpolateRound(a, b) {
+    b -= a;
+    return function(t) {
+      return Math.round(a + b * t);
+    };
+  }
+  d3.transform = function(string) {
+    var g = d3_document.createElementNS(d3.ns.prefix.svg, &quot;g&quot;);
+    return (d3.transform = function(string) {
+      if (string != null) {
+        g.setAttribute(&quot;transform&quot;, string);
+        var t = g.transform.baseVal.consolidate();
+      }
+      return new d3_transform(t ? t.matrix : d3_transformIdentity);
+    })(string);
+  };
+  function d3_transform(m) {
+    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
+    if (r0[0] * r1[1] &lt; r1[0] * r0[1]) {
+      r0[0] *= -1;
+      r0[1] *= -1;
+      kx *= -1;
+      kz *= -1;
+    }
+    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
+    this.translate = [ m.e, m.f ];
+    this.scale = [ kx, ky ];
+    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
+  }
+  d3_transform.prototype.toString = function() {
+    return &quot;translate(&quot; + this.translate + &quot;)rotate(&quot; + this.rotate + &quot;)skewX(&quot; + this.skew + &quot;)scale(&quot; + this.scale + &quot;)&quot;;
+  };
+  function d3_transformDot(a, b) {
+    return a[0] * b[0] + a[1] * b[1];
+  }
+  function d3_transformNormalize(a) {
+    var k = Math.sqrt(d3_transformDot(a, a));
+    if (k) {
+      a[0] /= k;
+      a[1] /= k;
+    }
+    return k;
+  }
+  function d3_transformCombine(a, b, k) {
+    a[0] += k * b[0];
+    a[1] += k * b[1];
+    return a;
+  }
+  var d3_transformIdentity = {
+    a: 1,
+    b: 0,
+    c: 0,
+    d: 1,
+    e: 0,
+    f: 0
+  };
+  d3.interpolateTransform = d3_interpolateTransform;
+  function d3_interpolateTransform(a, b) {
+    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
+    if (ta[0] != tb[0] || ta[1] != tb[1]) {
+      s.push(&quot;translate(&quot;, null, &quot;,&quot;, null, &quot;)&quot;);
+      q.push({
+        i: 1,
+        x: d3_interpolateNumber(ta[0], tb[0])
+      }, {
+        i: 3,
+        x: d3_interpolateNumber(ta[1], tb[1])
+      });
+    } else if (tb[0] || tb[1]) {
+      s.push(&quot;translate(&quot; + tb + &quot;)&quot;);
+    } else {
+      s.push(&quot;&quot;);
+    }
+    if (ra != rb) {
+      if (ra - rb &gt; 180) rb += 360; else if (rb - ra &gt; 180) ra += 360;
+      q.push({
+        i: s.push(s.pop() + &quot;rotate(&quot;, null, &quot;)&quot;) - 2,
+        x: d3_interpolateNumber(ra, rb)
+      });
+    } else if (rb) {
+      s.push(s.pop() + &quot;rotate(&quot; + rb + &quot;)&quot;);
+    }
+    if (wa != wb) {
+      q.push({
+        i: s.push(s.pop() + &quot;skewX(&quot;, null, &quot;)&quot;) - 2,
+        x: d3_interpolateNumber(wa, wb)
+      });
+    } else if (wb) {
+      s.push(s.pop() + &quot;skewX(&quot; + wb + &quot;)&quot;);
+    }
+    if (ka[0] != kb[0] || ka[1] != kb[1]) {
+      n = s.push(s.pop() + &quot;scale(&quot;, null, &quot;,&quot;, null, &quot;)&quot;);
+      q.push({
+        i: n - 4,
+        x: d3_interpolateNumber(ka[0], kb[0])
+      }, {
+        i: n - 2,
+        x: d3_interpolateNumber(ka[1], kb[1])
+      });
+    } else if (kb[0] != 1 || kb[1] != 1) {
+      s.push(s.pop() + &quot;scale(&quot; + kb + &quot;)&quot;);
+    }
+    n = q.length;
+    return function(t) {
+      var i = -1, o;
+      while (++i &lt; n) s[(o = q[i]).i] = o.x(t);
+      return s.join(&quot;&quot;);
+    };
+  }
+  function d3_uninterpolateNumber(a, b) {
+    b = b - (a = +a) ? 1 / (b - a) : 0;
+    return function(x) {
+      return (x - a) * b;
+    };
+  }
+  function d3_uninterpolateClamp(a, b) {
+    b = b - (a = +a) ? 1 / (b - a) : 0;
+    return function(x) {
+      return Math.max(0, Math.min(1, (x - a) * b));
+    };
+  }
+  d3.layout = {};
+  d3.layout.bundle = function() {
+    return function(links) {
+      var paths = [], i = -1, n = links.length;
+      while (++i &lt; n) paths.push(d3_layout_bundlePath(links[i]));
+      return paths;
+    };
+  };
+  function d3_layout_bundlePath(link) {
+    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
+    while (start !== lca) {
+      start = start.parent;
+      points.push(start);
+    }
+    var k = points.length;
+    while (end !== lca) {
+      points.splice(k, 0, end);
+      end = end.parent;
+    }
+    return points;
+  }
+  function d3_layout_bundleAncestors(node) {
+    var ancestors = [], parent = node.parent;
+    while (parent != null) {
+      ancestors.push(node);
+      node = parent;
+      parent = parent.parent;
+    }
+    ancestors.push(node);
+    return ancestors;
+  }
+  function d3_layout_bundleLeastCommonAncestor(a, b) {
+    if (a === b) return a;
+    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
+    while (aNode === bNode) {
+      sharedNode = aNode;
+      aNode = aNodes.pop();
+      bNode = bNodes.pop();
+    }
+    return sharedNode;
+  }
+  d3.layout.chord = function() {
+    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
+    function relayout() {
+      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
+      chords = [];
+      groups = [];
+      k = 0, i = -1;
+      while (++i &lt; n) {
+        x = 0, j = -1;
+        while (++j &lt; n) {
+          x += matrix[i][j];
+        }
+        groupSums.push(x);
+        subgroupIndex.push(d3.range(n));
+        k += x;
+      }
+      if (sortGroups) {
+        groupIndex.sort(function(a, b) {
+          return sortGroups(groupSums[a], groupSums[b]);
+        });
+      }
+      if (sortSubgroups) {
+        subgroupIndex.forEach(function(d, i) {
+          d.sort(function(a, b) {
+            return sortSubgroups(matrix[i][a], matrix[i][b]);
+          });
+        });
+      }
+      k = (τ - padding * n) / k;
+      x = 0, i = -1;
+      while (++i &lt; n) {
+        x0 = x, j = -1;
+        while (++j &lt; n) {
+          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
+          subgroups[di + &quot;-&quot; + dj] = {
+            index: di,
+            subindex: dj,
+            startAngle: a0,
+            endAngle: a1,
+            value: v
+          };
+        }
+        groups[di] = {
+          index: di,
+          startAngle: x0,
+          endAngle: x,
+          value: (x - x0) / k
+        };
+        x += padding;
+      }
+      i = -1;
+      while (++i &lt; n) {
+        j = i - 1;
+        while (++j &lt; n) {
+          var source = subgroups[i + &quot;-&quot; + j], target = subgroups[j + &quot;-&quot; + i];
+          if (source.value || target.value) {
+            chords.push(source.value &lt; target.value ? {
+              source: target,
+              target: source
+            } : {
+              source: source,
+              target: target
+            });
+          }
+        }
+      }
+      if (sortChords) resort();
+    }
+    function resort() {
+      chords.sort(function(a, b) {
+        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
+      });
+    }
+    chord.matrix = function(x) {
+      if (!arguments.length) return matrix;
+      n = (matrix = x) &amp;&amp; matrix.length;
+      chords = groups = null;
+      return chord;
+    };
+    chord.padding = function(x) {
+      if (!arguments.length) return padding;
+      padding = x;
+      chords = groups = null;
+      return chord;
+    };
+    chord.sortGroups = function(x) {
+      if (!arguments.length) return sortGroups;
+      sortGroups = x;
+      chords = groups = null;
+      return chord;
+    };
+    chord.sortSubgroups = function(x) {
+      if (!arguments.length) return sortSubgroups;
+      sortSubgroups = x;
+      chords = null;
+      return chord;
+    };
+    chord.sortChords = function(x) {
+      if (!arguments.length) return sortChords;
+      sortChords = x;
+      if (chords) resort();
+      return chord;
+    };
+    chord.chords = function() {
+      if (!chords) relayout();
+      return chords;
+    };
+    chord.groups = function() {
+      if (!groups) relayout();
+      return groups;
+    };
+    return chord;
+  };
+  d3.layout.force = function() {
+    var force = {}, event = d3.dispatch(&quot;start&quot;, &quot;tick&quot;, &quot;end&quot;), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
+    function repulse(node) {
+      return function(quad, x1, _, x2) {
+        if (quad.point !== node) {
+          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
+          if (dw * dw / theta2 &lt; dn) {
+            if (dn &lt; chargeDistance2) {
+              var k = quad.charge / dn;
+              node.px -= dx * k;
+              node.py -= dy * k;
+            }
+            return true;
+          }
+          if (quad.point &amp;&amp; dn &amp;&amp; dn &lt; chargeDistance2) {
+            var k = quad.pointCharge / dn;
+            node.px -= dx * k;
+            node.py -= dy * k;
+          }
+        }
+        return !quad.charge;
+      };
+    }
+    force.tick = function() {
+      if ((alpha *= .99) &lt; .005) {
+        event.end({
+          type: &quot;end&quot;,
+          alpha: alpha = 0
+        });
+        return true;
+      }
+      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
+      for (i = 0; i &lt; m; ++i) {
+        o = links[i];
+        s = o.source;
+        t = o.target;
+        x = t.x - s.x;
+        y = t.y - s.y;
+        if (l = x * x + y * y) {
+          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
+          x *= l;
+          y *= l;
+          t.x -= x * (k = s.weight / (t.weight + s.weight));
+          t.y -= y * k;
+          s.x += x * (k = 1 - k);
+          s.y += y * k;
+        }
+      }
+      if (k = alpha * gravity) {
+        x = size[0] / 2;
+        y = size[1] / 2;
+        i = -1;
+        if (k) while (++i &lt; n) {
+          o = nodes[i];
+          o.x += (x - o.x) * k;
+          o.y += (y - o.y) * k;
+        }
+      }
+      if (charge) {
+        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
+        i = -1;
+        while (++i &lt; n) {
+          if (!(o = nodes[i]).fixed) {
+            q.visit(repulse(o));
+          }
+        }
+      }
+      i = -1;
+      while (++i &lt; n) {
+        o = nodes[i];
+        if (o.fixed) {
+          o.x = o.px;
+          o.y = o.py;
+        } else {
+          o.x -= (o.px - (o.px = o.x)) * friction;
+          o.y -= (o.py - (o.py = o.y)) * friction;
+        }
+      }
+      event.tick({
+        type: &quot;tick&quot;,
+        alpha: alpha
+      });
+    };
+    force.nodes = function(x) {
+      if (!arguments.length) return nodes;
+      nodes = x;
+      return force;
+    };
+    force.links = function(x) {
+      if (!arguments.length) return links;
+      links = x;
+      return force;
+    };
+    force.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return force;
+    };
+    force.linkDistance = function(x) {
+      if (!arguments.length) return linkDistance;
+      linkDistance = typeof x === &quot;function&quot; ? x : +x;
+      return force;
+    };
+    force.distance = force.linkDistance;
+    force.linkStrength = function(x) {
+      if (!arguments.length) return linkStrength;
+      linkStrength = typeof x === &quot;function&quot; ? x : +x;
+      return force;
+    };
+    force.friction = function(x) {
+      if (!arguments.length) return friction;
+      friction = +x;
+      return force;
+    };
+    force.charge = function(x) {
+      if (!arguments.length) return charge;
+      charge = typeof x === &quot;function&quot; ? x : +x;
+      return force;
+    };
+    force.chargeDistance = function(x) {
+      if (!arguments.length) return Math.sqrt(chargeDistance2);
+      chargeDistance2 = x * x;
+      return force;
+    };
+    force.gravity = function(x) {
+      if (!arguments.length) return gravity;
+      gravity = +x;
+      return force;
+    };
+    force.theta = function(x) {
+      if (!arguments.length) return Math.sqrt(theta2);
+      theta2 = x * x;
+      return force;
+    };
+    force.alpha = function(x) {
+      if (!arguments.length) return alpha;
+      x = +x;
+      if (alpha) {
+        if (x &gt; 0) alpha = x; else alpha = 0;
+      } else if (x &gt; 0) {
+        event.start({
+          type: &quot;start&quot;,
+          alpha: alpha = x
+        });
+        d3.timer(force.tick);
+      }
+      return force;
+    };
+    force.start = function() {
+      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
+      for (i = 0; i &lt; n; ++i) {
+        (o = nodes[i]).index = i;
+        o.weight = 0;
+      }
+      for (i = 0; i &lt; m; ++i) {
+        o = links[i];
+        if (typeof o.source == &quot;number&quot;) o.source = nodes[o.source];
+        if (typeof o.target == &quot;number&quot;) o.target = nodes[o.target];
+        ++o.source.weight;
+        ++o.target.weight;
+      }
+      for (i = 0; i &lt; n; ++i) {
+        o = nodes[i];
+        if (isNaN(o.x)) o.x = position(&quot;x&quot;, w);
+        if (isNaN(o.y)) o.y = position(&quot;y&quot;, h);
+        if (isNaN(o.px)) o.px = o.x;
+        if (isNaN(o.py)) o.py = o.y;
+      }
+      distances = [];
+      if (typeof linkDistance === &quot;function&quot;) for (i = 0; i &lt; m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i &lt; m; ++i) distances[i] = linkDistance;
+      strengths = [];
+      if (typeof linkStrength === &quot;function&quot;) for (i = 0; i &lt; m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i &lt; m; ++i) strengths[i] = linkStrength;
+      charges = [];
+      if (typeof charge === &quot;function&quot;) for (i = 0; i &lt; n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i &lt; n; ++i) charges[i] = charge;
+      function position(dimension, size) {
+        if (!neighbors) {
+          neighbors = new Array(n);
+          for (j = 0; j &lt; n; ++j) {
+            neighbors[j] = [];
+          }
+          for (j = 0; j &lt; m; ++j) {
+            var o = links[j];
+            neighbors[o.source.index].push(o.target);
+            neighbors[o.target.index].push(o.source);
+          }
+        }
+        var candidates = neighbors[i], j = -1, m = candidates.length, x;
+        while (++j &lt; m) if (!isNaN(x = candidates[j][dimension])) return x;
+        return Math.random() * size;
+      }
+      return force.resume();
+    };
+    force.resume = function() {
+      return force.alpha(.1);
+    };
+    force.stop = function() {
+      return force.alpha(0);
+    };
+    force.drag = function() {
+      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on(&quot;dragstart.force&quot;, d3_layout_forceDragstart).on(&quot;drag.force&quot;, dragmove).on(&quot;dragend.force&quot;, d3_layout_forceDragend);
+      if (!arguments.length) return drag;
+      this.on(&quot;mouseover.force&quot;, d3_layout_forceMouseover).on(&quot;mouseout.force&quot;, d3_layout_forceMouseout).call(drag);
+    };
+    function dragmove(d) {
+      d.px = d3.event.x, d.py = d3.event.y;
+      force.resume();
+    }
+    return d3.rebind(force, event, &quot;on&quot;);
+  };
+  function d3_layout_forceDragstart(d) {
+    d.fixed |= 2;
+  }
+  function d3_layout_forceDragend(d) {
+    d.fixed &amp;= ~6;
+  }
+  function d3_layout_forceMouseover(d) {
+    d.fixed |= 4;
+    d.px = d.x, d.py = d.y;
+  }
+  function d3_layout_forceMouseout(d) {
+    d.fixed &amp;= ~4;
+  }
+  function d3_layout_forceAccumulate(quad, alpha, charges) {
+    var cx = 0, cy = 0;
+    quad.charge = 0;
+    if (!quad.leaf) {
+      var nodes = quad.nodes, n = nodes.length, i = -1, c;
+      while (++i &lt; n) {
+        c = nodes[i];
+        if (c == null) continue;
+        d3_layout_forceAccumulate(c, alpha, charges);
+        quad.charge += c.charge;
+        cx += c.charge * c.cx;
+        cy += c.charge * c.cy;
+      }
+    }
+    if (quad.point) {
+      if (!quad.leaf) {
+        quad.point.x += Math.random() - .5;
+        quad.point.y += Math.random() - .5;
+      }
+      var k = alpha * charges[quad.point.index];
+      quad.charge += quad.pointCharge = k;
+      cx += k * quad.point.x;
+      cy += k * quad.point.y;
+    }
+    quad.cx = cx / quad.charge;
+    quad.cy = cy / quad.charge;
+  }
+  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
+  d3.layout.hierarchy = function() {
+    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
+    function hierarchy(root) {
+      var stack = [ root ], nodes = [], node;
+      root.depth = 0;
+      while ((node = stack.pop()) != null) {
+        nodes.push(node);
+        if ((childs = children.call(hierarchy, node, node.depth)) &amp;&amp; (n = childs.length)) {
+          var n, childs, child;
+          while (--n &gt;= 0) {
+            stack.push(child = childs[n]);
+            child.parent = node;
+            child.depth = node.depth + 1;
+          }
+          if (value) node.value = 0;
+          node.children = childs;
+        } else {
+          if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
+          delete node.children;
+        }
+      }
+      d3_layout_hierarchyVisitAfter(root, function(node) {
+        var childs, parent;
+        if (sort &amp;&amp; (childs = node.children)) childs.sort(sort);
+        if (value &amp;&amp; (parent = node.parent)) parent.value += node.value;
+      });
+      return nodes;
+    }
+    hierarchy.sort = function(x) {
+      if (!arguments.length) return sort;
+      sort = x;
+      return hierarchy;
+    };
+    hierarchy.children = function(x) {
+      if (!arguments.length) return children;
+      children = x;
+      return hierarchy;
+    };
+    hierarchy.value = function(x) {
+      if (!arguments.length) return value;
+      value = x;
+      return hierarchy;
+    };
+    hierarchy.revalue = function(root) {
+      if (value) {
+        d3_layout_hierarchyVisitBefore(root, function(node) {
+          if (node.children) node.value = 0;
+        });
+        d3_layout_hierarchyVisitAfter(root, function(node) {
+          var parent;
+          if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
+          if (parent = node.parent) parent.value += node.value;
+        });
+      }
+      return root;
+    };
+    return hierarchy;
+  };
+  function d3_layout_hierarchyRebind(object, hierarchy) {
+    d3.rebind(object, hierarchy, &quot;sort&quot;, &quot;children&quot;, &quot;value&quot;);
+    object.nodes = object;
+    object.links = d3_layout_hierarchyLinks;
+    return object;
+  }
+  function d3_layout_hierarchyVisitBefore(node, callback) {
+    var nodes = [ node ];
+    while ((node = nodes.pop()) != null) {
+      callback(node);
+      if ((children = node.children) &amp;&amp; (n = children.length)) {
+        var n, children;
+        while (--n &gt;= 0) nodes.push(children[n]);
+      }
+    }
+  }
+  function d3_layout_hierarchyVisitAfter(node, callback) {
+    var nodes = [ node ], nodes2 = [];
+    while ((node = nodes.pop()) != null) {
+      nodes2.push(node);
+      if ((children = node.children) &amp;&amp; (n = children.length)) {
+        var i = -1, n, children;
+        while (++i &lt; n) nodes.push(children[i]);
+      }
+    }
+    while ((node = nodes2.pop()) != null) {
+      callback(node);
+    }
+  }
+  function d3_layout_hierarchyChildren(d) {
+    return d.children;
+  }
+  function d3_layout_hierarchyValue(d) {
+    return d.value;
+  }
+  function d3_layout_hierarchySort(a, b) {
+    return b.value - a.value;
+  }
+  function d3_layout_hierarchyLinks(nodes) {
+    return d3.merge(nodes.map(function(parent) {
+      return (parent.children || []).map(function(child) {
+        return {
+          source: parent,
+          target: child
+        };
+      });
+    }));
+  }
+  d3.layout.partition = function() {
+    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
+    function position(node, x, dx, dy) {
+      var children = node.children;
+      node.x = x;
+      node.y = node.depth * dy;
+      node.dx = dx;
+      node.dy = dy;
+      if (children &amp;&amp; (n = children.length)) {
+        var i = -1, n, c, d;
+        dx = node.value ? dx / node.value : 0;
+        while (++i &lt; n) {
+          position(c = children[i], x, d = c.value * dx, dy);
+          x += d;
+        }
+      }
+    }
+    function depth(node) {
+      var children = node.children, d = 0;
+      if (children &amp;&amp; (n = children.length)) {
+        var i = -1, n;
+        while (++i &lt; n) d = Math.max(d, depth(children[i]));
+      }
+      return 1 + d;
+    }
+    function partition(d, i) {
+      var nodes = hierarchy.call(this, d, i);
+      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
+      return nodes;
+    }
+    partition.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return partition;
+    };
+    return d3_layout_hierarchyRebind(partition, hierarchy);
+  };
+  d3.layout.pie = function() {
+    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ;
+    function pie(data) {
+      var values = data.map(function(d, i) {
+        return +value.call(pie, d, i);
+      });
+      var a = +(typeof startAngle === &quot;function&quot; ? startAngle.apply(this, arguments) : startAngle);
+      var k = ((typeof endAngle === &quot;function&quot; ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);
+      var index = d3.range(data.length);
+      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
+        return values[j] - values[i];
+      } : function(i, j) {
+        return sort(data[i], data[j]);
+      });
+      var arcs = [];
+      index.forEach(function(i) {
+        var d;
+        arcs[i] = {
+          data: data[i],
+          value: d = values[i],
+          startAngle: a,
+          endAngle: a += d * k
+        };
+      });
+      return arcs;
+    }
+    pie.value = function(x) {
+      if (!arguments.length) return value;
+      value = x;
+      return pie;
+    };
+    pie.sort = function(x) {
+      if (!arguments.length) return sort;
+      sort = x;
+      return pie;
+    };
+    pie.startAngle = function(x) {
+      if (!arguments.length) return startAngle;
+      startAngle = x;
+      return pie;
+    };
+    pie.endAngle = function(x) {
+      if (!arguments.length) return endAngle;
+      endAngle = x;
+      return pie;
+    };
+    return pie;
+  };
+  var d3_layout_pieSortByValue = {};
+  d3.layout.stack = function() {
+    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
+    function stack(data, index) {
+      var series = data.map(function(d, i) {
+        return values.call(stack, d, i);
+      });
+      var points = series.map(function(d) {
+        return d.map(function(v, i) {
+          return [ x.call(stack, v, i), y.call(stack, v, i) ];
+        });
+      });
+      var orders = order.call(stack, points, index);
+      series = d3.permute(series, orders);
+      points = d3.permute(points, orders);
+      var offsets = offset.call(stack, points, index);
+      var n = series.length, m = series[0].length, i, j, o;
+      for (j = 0; j &lt; m; ++j) {
+        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
+        for (i = 1; i &lt; n; ++i) {
+          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
+        }
+      }
+      return data;
+    }
+    stack.values = function(x) {
+      if (!arguments.length) return values;
+      values = x;
+      return stack;
+    };
+    stack.order = function(x) {
+      if (!arguments.length) return order;
+      order = typeof x === &quot;function&quot; ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
+      return stack;
+    };
+    stack.offset = function(x) {
+      if (!arguments.length) return offset;
+      offset = typeof x === &quot;function&quot; ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
+      return stack;
+    };
+    stack.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      return stack;
+    };
+    stack.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      return stack;
+    };
+    stack.out = function(z) {
+      if (!arguments.length) return out;
+      out = z;
+      return stack;
+    };
+    return stack;
+  };
+  function d3_layout_stackX(d) {
+    return d.x;
+  }
+  function d3_layout_stackY(d) {
+    return d.y;
+  }
+  function d3_layout_stackOut(d, y0, y) {
+    d.y0 = y0;
+    d.y = y;
+  }
+  var d3_layout_stackOrders = d3.map({
+    &quot;inside-out&quot;: function(data) {
+      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
+        return max[a] - max[b];
+      }), top = 0, bottom = 0, tops = [], bottoms = [];
+      for (i = 0; i &lt; n; ++i) {
+        j = index[i];
+        if (top &lt; bottom) {
+          top += sums[j];
+          tops.push(j);
+        } else {
+          bottom += sums[j];
+          bottoms.push(j);
+        }
+      }
+      return bottoms.reverse().concat(tops);
+    },
+    reverse: function(data) {
+      return d3.range(data.length).reverse();
+    },
+    &quot;default&quot;: d3_layout_stackOrderDefault
+  });
+  var d3_layout_stackOffsets = d3.map({
+    silhouette: function(data) {
+      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
+      for (j = 0; j &lt; m; ++j) {
+        for (i = 0, o = 0; i &lt; n; i++) o += data[i][j][1];
+        if (o &gt; max) max = o;
+        sums.push(o);
+      }
+      for (j = 0; j &lt; m; ++j) {
+        y0[j] = (max - sums[j]) / 2;
+      }
+      return y0;
+    },
+    wiggle: function(data) {
+      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
+      y0[0] = o = o0 = 0;
+      for (j = 1; j &lt; m; ++j) {
+        for (i = 0, s1 = 0; i &lt; n; ++i) s1 += data[i][j][1];
+        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i &lt; n; ++i) {
+          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k &lt; i; ++k) {
+            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
+          }
+          s2 += s3 * data[i][j][1];
+        }
+        y0[j] = o -= s1 ? s2 / s1 * dx : 0;
+        if (o &lt; o0) o0 = o;
+      }
+      for (j = 0; j &lt; m; ++j) y0[j] -= o0;
+      return y0;
+    },
+    expand: function(data) {
+      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
+      for (j = 0; j &lt; m; ++j) {
+        for (i = 0, o = 0; i &lt; n; i++) o += data[i][j][1];
+        if (o) for (i = 0; i &lt; n; i++) data[i][j][1] /= o; else for (i = 0; i &lt; n; i++) data[i][j][1] = k;
+      }
+      for (j = 0; j &lt; m; ++j) y0[j] = 0;
+      return y0;
+    },
+    zero: d3_layout_stackOffsetZero
+  });
+  function d3_layout_stackOrderDefault(data) {
+    return d3.range(data.length);
+  }
+  function d3_layout_stackOffsetZero(data) {
+    var j = -1, m = data[0].length, y0 = [];
+    while (++j &lt; m) y0[j] = 0;
+    return y0;
+  }
+  function d3_layout_stackMaxIndex(array) {
+    var i = 1, j = 0, v = array[0][1], k, n = array.length;
+    for (;i &lt; n; ++i) {
+      if ((k = array[i][1]) &gt; v) {
+        j = i;
+        v = k;
+      }
+    }
+    return j;
+  }
+  function d3_layout_stackReduceSum(d) {
+    return d.reduce(d3_layout_stackSum, 0);
+  }
+  function d3_layout_stackSum(p, d) {
+    return p + d[1];
+  }
+  d3.layout.histogram = function() {
+    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
+    function histogram(data, i) {
+      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
+      while (++i &lt; m) {
+        bin = bins[i] = [];
+        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
+        bin.y = 0;
+      }
+      if (m &gt; 0) {
+        i = -1;
+        while (++i &lt; n) {
+          x = values[i];
+          if (x &gt;= range[0] &amp;&amp; x &lt;= range[1]) {
+            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
+            bin.y += k;
+            bin.push(data[i]);
+          }
+        }
+      }
+      return bins;
+    }
+    histogram.value = function(x) {
+      if (!arguments.length) return valuer;
+      valuer = x;
+      return histogram;
+    };
+    histogram.range = function(x) {
+      if (!arguments.length) return ranger;
+      ranger = d3_functor(x);
+      return histogram;
+    };
+    histogram.bins = function(x) {
+      if (!arguments.length) return binner;
+      binner = typeof x === &quot;number&quot; ? function(range) {
+        return d3_layout_histogramBinFixed(range, x);
+      } : d3_functor(x);
+      return histogram;
+    };
+    histogram.frequency = function(x) {
+      if (!arguments.length) return frequency;
+      frequency = !!x;
+      return histogram;
+    };
+    return histogram;
+  };
+  function d3_layout_histogramBinSturges(range, values) {
+    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
+  }
+  function d3_layout_histogramBinFixed(range, n) {
+    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
+    while (++x &lt;= n) f[x] = m * x + b;
+    return f;
+  }
+  function d3_layout_histogramRange(values) {
+    return [ d3.min(values), d3.max(values) ];
+  }
+  d3.layout.pack = function() {
+    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
+    function pack(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === &quot;function&quot; ? radius : function() {
+        return radius;
+      };
+      root.x = root.y = 0;
+      d3_layout_hierarchyVisitAfter(root, function(d) {
+        d.r = +r(d.value);
+      });
+      d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
+      if (padding) {
+        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
+        d3_layout_hierarchyVisitAfter(root, function(d) {
+          d.r += dr;
+        });
+        d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
+        d3_layout_hierarchyVisitAfter(root, function(d) {
+          d.r -= dr;
+        });
+      }
+      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
+      return nodes;
+    }
+    pack.size = function(_) {
+      if (!arguments.length) return size;
+      size = _;
+      return pack;
+    };
+    pack.radius = function(_) {
+      if (!arguments.length) return radius;
+      radius = _ == null || typeof _ === &quot;function&quot; ? _ : +_;
+      return pack;
+    };
+    pack.padding = function(_) {
+      if (!arguments.length) return padding;
+      padding = +_;
+      return pack;
+    };
+    return d3_layout_hierarchyRebind(pack, hierarchy);
+  };
+  function d3_layout_packSort(a, b) {
+    return a.value - b.value;
+  }
+  function d3_layout_packInsert(a, b) {
+    var c = a._pack_next;
+    a._pack_next = b;
+    b._pack_prev = a;
+    b._pack_next = c;
+    c._pack_prev = b;
+  }
+  function d3_layout_packSplice(a, b) {
+    a._pack_next = b;
+    b._pack_prev = a;
+  }
+  function d3_layout_packIntersects(a, b) {
+    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
+    return .999 * dr * dr &gt; dx * dx + dy * dy;
+  }
+  function d3_layout_packSiblings(node) {
+    if (!(nodes = node.children) || !(n = nodes.length)) return;
+    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
+    function bound(node) {
+      xMin = Math.min(node.x - node.r, xMin);
+      xMax = Math.max(node.x + node.r, xMax);
+      yMin = Math.min(node.y - node.r, yMin);
+      yMax = Math.max(node.y + node.r, yMax);
+    }
+    nodes.forEach(d3_layout_packLink);
+    a = nodes[0];
+    a.x = -a.r;
+    a.y = 0;
+    bound(a);
+    if (n &gt; 1) {
+      b = nodes[1];
+      b.x = b.r;
+      b.y = 0;
+      bound(b);
+      if (n &gt; 2) {
+        c = nodes[2];
+        d3_layout_packPlace(a, b, c);
+        bound(c);
+        d3_layout_packInsert(a, c);
+        a._pack_prev = c;
+        d3_layout_packInsert(c, b);
+        b = a._pack_next;
+        for (i = 3; i &lt; n; i++) {
+          d3_layout_packPlace(a, b, c = nodes[i]);
+          var isect = 0, s1 = 1, s2 = 1;
+          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
+            if (d3_layout_packIntersects(j, c)) {
+              isect = 1;
+              break;
+            }
+          }
+          if (isect == 1) {
+            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
+              if (d3_layout_packIntersects(k, c)) {
+                break;
+              }
+            }
+          }
+          if (isect) {
+            if (s1 &lt; s2 || s1 == s2 &amp;&amp; b.r &lt; a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
+            i--;
+          } else {
+            d3_layout_packInsert(a, c);
+            b = c;
+            bound(c);
+          }
+        }
+      }
+    }
+    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
+    for (i = 0; i &lt; n; i++) {
+      c = nodes[i];
+      c.x -= cx;
+      c.y -= cy;
+      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
+    }
+    node.r = cr;
+    nodes.forEach(d3_layout_packUnlink);
+  }
+  function d3_layout_packLink(node) {
+    node._pack_next = node._pack_prev = node;
+  }
+  function d3_layout_packUnlink(node) {
+    delete node._pack_next;
+    delete node._pack_prev;
+  }
+  function d3_layout_packTransform(node, x, y, k) {
+    var children = node.children;
+    node.x = x += k * node.x;
+    node.y = y += k * node.y;
+    node.r *= k;
+    if (children) {
+      var i = -1, n = children.length;
+      while (++i &lt; n) d3_layout_packTransform(children[i], x, y, k);
+    }
+  }
+  function d3_layout_packPlace(a, b, c) {
+    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
+    if (db &amp;&amp; (dx || dy)) {
+      var da = b.r + c.r, dc = dx * dx + dy * dy;
+      da *= da;
+      db *= db;
+      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
+      c.x = a.x + x * dx + y * dy;
+      c.y = a.y + x * dy - y * dx;
+    } else {
+      c.x = a.x + db;
+      c.y = a.y;
+    }
+  }
+  d3.layout.tree = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
+    function tree(d, i) {
+      var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
+      d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
+      d3_layout_hierarchyVisitBefore(root1, secondWalk);
+      if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
+        var left = root0, right = root0, bottom = root0;
+        d3_layout_hierarchyVisitBefore(root0, function(node) {
+          if (node.x &lt; left.x) left = node;
+          if (node.x &gt; right.x) right = node;
+          if (node.depth &gt; bottom.depth) bottom = node;
+        });
+        var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
+        d3_layout_hierarchyVisitBefore(root0, function(node) {
+          node.x = (node.x + tx) * kx;
+          node.y = node.depth * ky;
+        });
+      }
+      return nodes;
+    }
+    function wrapTree(root0) {
+      var root1 = {
+        A: null,
+        children: [ root0 ]
+      }, queue = [ root1 ], node1;
+      while ((node1 = queue.pop()) != null) {
+        for (var children = node1.children, child, i = 0, n = children.length; i &lt; n; ++i) {
+          queue.push((children[i] = child = {
+            _: children[i],
+            parent: node1,
+            children: (child = children[i].children) &amp;&amp; child.slice() || [],
+            A: null,
+            a: null,
+            z: 0,
+            m: 0,
+            c: 0,
+            s: 0,
+            t: null,
+            i: i
+          }).a = child);
+        }
+      }
+      return root1.children[0];
+    }
+    function firstWalk(v) {
+      var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
+      if (children.length) {
+        d3_layout_treeShift(v);
+        var midpoint = (children[0].z + children[children.length - 1].z) / 2;
+        if (w) {
+          v.z = w.z + separation(v._, w._);
+          v.m = v.z - midpoint;
+        } else {
+          v.z = midpoint;
+        }
+      } else if (w) {
+        v.z = w.z + separation(v._, w._);
+      }
+      v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
+    }
+    function secondWalk(v) {
+      v._.x = v.z + v.parent.m;
+      v.m += v.parent.m;
+    }
+    function apportion(v, w, ancestor) {
+      if (w) {
+        var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
+        while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim &amp;&amp; vip) {
+          vom = d3_layout_treeLeft(vom);
+          vop = d3_layout_treeRight(vop);
+          vop.a = v;
+          shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
+          if (shift &gt; 0) {
+            d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
+            sip += shift;
+            sop += shift;
+          }
+          sim += vim.m;
+          sip += vip.m;
+          som += vom.m;
+          sop += vop.m;
+        }
+        if (vim &amp;&amp; !d3_layout_treeRight(vop)) {
+          vop.t = vim;
+          vop.m += sim - sop;
+        }
+        if (vip &amp;&amp; !d3_layout_treeLeft(vom)) {
+          vom.t = vip;
+          vom.m += sip - som;
+          ancestor = v;
+        }
+      }
+      return ancestor;
+    }
+    function sizeNode(node) {
+      node.x *= size[0];
+      node.y = node.depth * size[1];
+    }
+    tree.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return tree;
+    };
+    tree.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null ? sizeNode : null;
+      return tree;
+    };
+    tree.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) == null ? null : sizeNode;
+      return tree;
+    };
+    return d3_layout_hierarchyRebind(tree, hierarchy);
+  };
+  function d3_layout_treeSeparation(a, b) {
+    return a.parent == b.parent ? 1 : 2;
+  }
+  function d3_layout_treeLeft(v) {
+    var children = v.children;
+    return children.length ? children[0] : v.t;
+  }
+  function d3_layout_treeRight(v) {
+    var children = v.children, n;
+    return (n = children.length) ? children[n - 1] : v.t;
+  }
+  function d3_layout_treeMove(wm, wp, shift) {
+    var change = shift / (wp.i - wm.i);
+    wp.c -= change;
+    wp.s += shift;
+    wm.c += change;
+    wp.z += shift;
+    wp.m += shift;
+  }
+  function d3_layout_treeShift(v) {
+    var shift = 0, change = 0, children = v.children, i = children.length, w;
+    while (--i &gt;= 0) {
+      w = children[i];
+      w.z += shift;
+      w.m += shift;
+      shift += w.s + (change += w.c);
+    }
+  }
+  function d3_layout_treeAncestor(vim, v, ancestor) {
+    return vim.a.parent === v.parent ? vim.a : ancestor;
+  }
+  d3.layout.cluster = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
+    function cluster(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
+      d3_layout_hierarchyVisitAfter(root, function(node) {
+        var children = node.children;
+        if (children &amp;&amp; children.length) {
+          node.x = d3_layout_clusterX(children);
+          node.y = d3_layout_clusterY(children);
+        } else {
+          node.x = previousNode ? x += separation(node, previousNode) : 0;
+          node.y = 0;
+          previousNode = node;
+        }
+      });
+      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
+      d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
+        node.x = (node.x - root.x) * size[0];
+        node.y = (root.y - node.y) * size[1];
+      } : function(node) {
+        node.x = (node.x - x0) / (x1 - x0) * size[0];
+        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
+      });
+      return nodes;
+    }
+    cluster.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return cluster;
+    };
+    cluster.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null;
+      return cluster;
+    };
+    cluster.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) != null;
+      return cluster;
+    };
+    return d3_layout_hierarchyRebind(cluster, hierarchy);
+  };
+  function d3_layout_clusterY(children) {
+    return 1 + d3.max(children, function(child) {
+      return child.y;
+    });
+  }
+  function d3_layout_clusterX(children) {
+    return children.reduce(function(x, child) {
+      return x + child.x;
+    }, 0) / children.length;
+  }
+  function d3_layout_clusterLeft(node) {
+    var children = node.children;
+    return children &amp;&amp; children.length ? d3_layout_clusterLeft(children[0]) : node;
+  }
+  function d3_layout_clusterRight(node) {
+    var children = node.children, n;
+    return children &amp;&amp; (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
+  }
+  d3.layout.treemap = function() {
+    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = &quot;squarify&quot;, ratio = .5 * (1 + Math.sqrt(5));
+    function scale(children, k) {
+      var i = -1, n = children.length, child, area;
+      while (++i &lt; n) {
+        area = (child = children[i]).value * (k &lt; 0 ? 0 : k);
+        child.area = isNaN(area) || area &lt;= 0 ? 0 : area;
+      }
+    }
+    function squarify(node) {
+      var children = node.children;
+      if (children &amp;&amp; children.length) {
+        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === &quot;slice&quot; ? rect.dx : mode === &quot;dice&quot; ? rect.dy : mode === &quot;slice-dice&quot; ? node.depth &amp; 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
+        scale(remaining, rect.dx * rect.dy / node.value);
+        row.area = 0;
+        while ((n = remaining.length) &gt; 0) {
+          row.push(child = remaining[n - 1]);
+          row.area += child.area;
+          if (mode !== &quot;squarify&quot; || (score = worst(row, u)) &lt;= best) {
+            remaining.pop();
+            best = score;
+          } else {
+            row.area -= row.pop().area;
+            position(row, u, rect, false);
+            u = Math.min(rect.dx, rect.dy);
+            row.length = row.area = 0;
+            best = Infinity;
+          }
+        }
+        if (row.length) {
+          position(row, u, rect, true);
+          row.length = row.area = 0;
+        }
+        children.forEach(squarify);
+      }
+    }
+    function stickify(node) {
+      var children = node.children;
+      if (children &amp;&amp; children.length) {
+        var rect = pad(node), remaining = children.slice(), child, row = [];
+        scale(remaining, rect.dx * rect.dy / node.value);
+        row.area = 0;
+        while (child = remaining.pop()) {
+          row.push(child);
+          row.area += child.area;
+          if (child.z != null) {
+            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
+            row.length = row.area = 0;
+          }
+        }
+        children.forEach(stickify);
+      }
+    }
+    function worst(row, u) {
+      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
+      while (++i &lt; n) {
+        if (!(r = row[i].area)) continue;
+        if (r &lt; rmin) rmin = r;
+        if (r &gt; rmax) rmax = r;
+      }
+      s *= s;
+      u *= u;
+      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
+    }
+    function position(row, u, rect, flush) {
+      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
+      if (u == rect.dx) {
+        if (flush || v &gt; rect.dy) v = rect.dy;
+        while (++i &lt; n) {
+          o = row[i];
+          o.x = x;
+          o.y = y;
+          o.dy = v;
+          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
+        }
+        o.z = true;
+        o.dx += rect.x + rect.dx - x;
+        rect.y += v;
+        rect.dy -= v;
+      } else {
+        if (flush || v &gt; rect.dx) v = rect.dx;
+        while (++i &lt; n) {
+          o = row[i];
+          o.x = x;
+          o.y = y;
+          o.dx = v;
+          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
+        }
+        o.z = false;
+        o.dy += rect.y + rect.dy - y;
+        rect.x += v;
+        rect.dx -= v;
+      }
+    }
+    function treemap(d) {
+      var nodes = stickies || hierarchy(d), root = nodes[0];
+      root.x = 0;
+      root.y = 0;
+      root.dx = size[0];
+      root.dy = size[1];
+      if (stickies) hierarchy.revalue(root);
+      scale([ root ], root.dx * root.dy / root.value);
+      (stickies ? stickify : squarify)(root);
+      if (sticky) stickies = nodes;
+      return nodes;
+    }
+    treemap.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return treemap;
+    };
+    treemap.padding = function(x) {
+      if (!arguments.length) return padding;
+      function padFunction(node) {
+        var p = x.call(treemap, node, node.depth);
+        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === &quot;number&quot; ? [ p, p, p, p ] : p);
+      }
+      function padConstant(node) {
+        return d3_layout_treemapPad(node, x);
+      }
+      var type;
+      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === &quot;function&quot; ? padFunction : type === &quot;number&quot; ? (x = [ x, x, x, x ], 
+      padConstant) : padConstant;
+      return treemap;
+    };
+    treemap.round = function(x) {
+      if (!arguments.length) return round != Number;
+      round = x ? Math.round : Number;
+      return treemap;
+    };
+    treemap.sticky = function(x) {
+      if (!arguments.length) return sticky;
+      sticky = x;
+      stickies = null;
+      return treemap;
+    };
+    treemap.ratio = function(x) {
+      if (!arguments.length) return ratio;
+      ratio = x;
+      return treemap;
+    };
+    treemap.mode = function(x) {
+      if (!arguments.length) return mode;
+      mode = x + &quot;&quot;;
+      return treemap;
+    };
+    return d3_layout_hierarchyRebind(treemap, hierarchy);
+  };
+  function d3_layout_treemapPadNull(node) {
+    return {
+      x: node.x,
+      y: node.y,
+      dx: node.dx,
+      dy: node.dy
+    };
+  }
+  function d3_layout_treemapPad(node, padding) {
+    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
+    if (dx &lt; 0) {
+      x += dx / 2;
+      dx = 0;
+    }
+    if (dy &lt; 0) {
+      y += dy / 2;
+      dy = 0;
+    }
+    return {
+      x: x,
+      y: y,
+      dx: dx,
+      dy: dy
+    };
+  }
+  d3.random = {
+    normal: function(µ, σ) {
+      var n = arguments.length;
+      if (n &lt; 2) σ = 1;
+      if (n &lt; 1) µ = 0;
+      return function() {
+        var x, y, r;
+        do {
+          x = Math.random() * 2 - 1;
+          y = Math.random() * 2 - 1;
+          r = x * x + y * y;
+        } while (!r || r &gt; 1);
+        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
+      };
+    },
+    logNormal: function() {
+      var random = d3.random.normal.apply(d3, arguments);
+      return function() {
+        return Math.exp(random());
+      };
+    },
+    bates: function(m) {
+      var random = d3.random.irwinHall(m);
+      return function() {
+        return random() / m;
+      };
+    },
+    irwinHall: function(m) {
+      return function() {
+        for (var s = 0, j = 0; j &lt; m; j++) s += Math.random();
+        return s;
+      };
+    }
+  };
+  d3.scale = {};
+  function d3_scaleExtent(domain) {
+    var start = domain[0], stop = domain[domain.length - 1];
+    return start &lt; stop ? [ start, stop ] : [ stop, start ];
+  }
+  function d3_scaleRange(scale) {
+    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
+  }
+  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
+    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
+    return function(x) {
+      return i(u(x));
+    };
+  }
+  function d3_scale_nice(domain, nice) {
+    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
+    if (x1 &lt; x0) {
+      dx = i0, i0 = i1, i1 = dx;
+      dx = x0, x0 = x1, x1 = dx;
+    }
+    domain[i0] = nice.floor(x0);
+    domain[i1] = nice.ceil(x1);
+    return domain;
+  }
+  function d3_scale_niceStep(step) {
+    return step ? {
+      floor: function(x) {
+        return Math.floor(x / step) * step;
+      },
+      ceil: function(x) {
+        return Math.ceil(x / step) * step;
+      }
+    } : d3_scale_niceIdentity;
+  }
+  var d3_scale_niceIdentity = {
+    floor: d3_identity,
+    ceil: d3_identity
+  };
+  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
+    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
+    if (domain[k] &lt; domain[0]) {
+      domain = domain.slice().reverse();
+      range = range.slice().reverse();
+    }
+    while (++j &lt;= k) {
+      u.push(uninterpolate(domain[j - 1], domain[j]));
+      i.push(interpolate(range[j - 1], range[j]));
+    }
+    return function(x) {
+      var j = d3.bisect(domain, x, 1, k) - 1;
+      return i[j](u[j](x));
+    };
+  }
+  d3.scale.linear = function() {
+    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
+  };
+  function d3_scale_linear(domain, range, interpolate, clamp) {
+    var output, input;
+    function rescale() {
+      var linear = Math.min(domain.length, range.length) &gt; 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
+      output = linear(domain, range, uninterpolate, interpolate);
+      input = linear(range, domain, uninterpolate, d3_interpolate);
+      return scale;
+    }
+    function scale(x) {
+      return output(x);
+    }
+    scale.invert = function(y) {
+      return input(y);
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.map(Number);
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.rangeRound = function(x) {
+      return scale.range(x).interpolate(d3_interpolateRound);
+    };
+    scale.clamp = function(x) {
+      if (!arguments.length) return clamp;
+      clamp = x;
+      return rescale();
+    };
+    scale.interpolate = function(x) {
+      if (!arguments.length) return interpolate;
+      interpolate = x;
+      return rescale();
+    };
+    scale.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    scale.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    scale.nice = function(m) {
+      d3_scale_linearNice(domain, m);
+      return rescale();
+    };
+    scale.copy = function() {
+      return d3_scale_linear(domain, range, interpolate, clamp);
+    };
+    return rescale();
+  }
+  function d3_scale_linearRebind(scale, linear) {
+    return d3.rebind(scale, linear, &quot;range&quot;, &quot;rangeRound&quot;, &quot;interpolate&quot;, &quot;clamp&quot;);
+  }
+  function d3_scale_linearNice(domain, m) {
+    return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
+  }
+  function d3_scale_linearTickRange(domain, m) {
+    if (m == null) m = 10;
+    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
+    if (err &lt;= .15) step *= 10; else if (err &lt;= .35) step *= 5; else if (err &lt;= .75) step *= 2;
+    extent[0] = Math.ceil(extent[0] / step) * step;
+    extent[1] = Math.floor(extent[1] / step) * step + step * .5;
+    extent[2] = step;
+    return extent;
+  }
+  function d3_scale_linearTicks(domain, m) {
+    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
+  }
+  function d3_scale_linearTickFormat(domain, m, format) {
+    var range = d3_scale_linearTickRange(domain, m);
+    if (format) {
+      var match = d3_format_re.exec(format);
+      match.shift();
+      if (match[8] === &quot;s&quot;) {
+        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
+        if (!match[7]) match[7] = &quot;.&quot; + d3_scale_linearPrecision(prefix.scale(range[2]));
+        match[8] = &quot;f&quot;;
+        format = d3.format(match.join(&quot;&quot;));
+        return function(d) {
+          return format(prefix.scale(d)) + prefix.symbol;
+        };
+      }
+      if (!match[7]) match[7] = &quot;.&quot; + d3_scale_linearFormatPrecision(match[8], range);
+      format = match.join(&quot;&quot;);
+    } else {
+      format = &quot;,.&quot; + d3_scale_linearPrecision(range[2]) + &quot;f&quot;;
+    }
+    return d3.format(format);
+  }
+  var d3_scale_linearFormatSignificant = {
+    s: 1,
+    g: 1,
+    p: 1,
+    r: 1,
+    e: 1
+  };
+  function d3_scale_linearPrecision(value) {
+    return -Math.floor(Math.log(value) / Math.LN10 + .01);
+  }
+  function d3_scale_linearFormatPrecision(type, range) {
+    var p = d3_scale_linearPrecision(range[2]);
+    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== &quot;e&quot;) : p - (type === &quot;%&quot;) * 2;
+  }
+  d3.scale.log = function() {
+    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
+  };
+  function d3_scale_log(linear, base, positive, domain) {
+    function log(x) {
+      return (positive ? Math.log(x &lt; 0 ? 0 : x) : -Math.log(x &gt; 0 ? 0 : -x)) / Math.log(base);
+    }
+    function pow(x) {
+      return positive ? Math.pow(base, x) : -Math.pow(base, -x);
+    }
+    function scale(x) {
+      return linear(log(x));
+    }
+    scale.invert = function(x) {
+      return pow(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      positive = x[0] &gt;= 0;
+      linear.domain((domain = x.map(Number)).map(log));
+      return scale;
+    };
+    scale.base = function(_) {
+      if (!arguments.length) return base;
+      base = +_;
+      linear.domain(domain.map(log));
+      return scale;
+    };
+    scale.nice = function() {
+      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
+      linear.domain(niced);
+      domain = niced.map(pow);
+      return scale;
+    };
+    scale.ticks = function() {
+      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
+      if (isFinite(j - i)) {
+        if (positive) {
+          for (;i &lt; j; i++) for (var k = 1; k &lt; n; k++) ticks.push(pow(i) * k);
+          ticks.push(pow(i));
+        } else {
+          ticks.push(pow(i));
+          for (;i++ &lt; j; ) for (var k = n - 1; k &gt; 0; k--) ticks.push(pow(i) * k);
+        }
+        for (i = 0; ticks[i] &lt; u; i++) {}
+        for (j = ticks.length; ticks[j - 1] &gt; v; j--) {}
+        ticks = ticks.slice(i, j);
+      }
+      return ticks;
+    };
+    scale.tickFormat = function(n, format) {
+      if (!arguments.length) return d3_scale_logFormat;
+      if (arguments.length &lt; 2) format = d3_scale_logFormat; else if (typeof format !== &quot;function&quot;) format = d3.format(format);
+      var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, 
+      Math.floor), e;
+      return function(d) {
+        return d / pow(f(log(d) + e)) &lt;= k ? format(d) : &quot;&quot;;
+      };
+    };
+    scale.copy = function() {
+      return d3_scale_log(linear.copy(), base, positive, domain);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  var d3_scale_logFormat = d3.format(&quot;.0e&quot;), d3_scale_logNiceNegative = {
+    floor: function(x) {
+      return -Math.ceil(-x);
+    },
+    ceil: function(x) {
+      return -Math.floor(-x);
+    }
+  };
+  d3.scale.pow = function() {
+    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
+  };
+  function d3_scale_pow(linear, exponent, domain) {
+    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
+    function scale(x) {
+      return linear(powp(x));
+    }
+    scale.invert = function(x) {
+      return powb(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      linear.domain((domain = x.map(Number)).map(powp));
+      return scale;
+    };
+    scale.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    scale.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    scale.nice = function(m) {
+      return scale.domain(d3_scale_linearNice(domain, m));
+    };
+    scale.exponent = function(x) {
+      if (!arguments.length) return exponent;
+      powp = d3_scale_powPow(exponent = x);
+      powb = d3_scale_powPow(1 / exponent);
+      linear.domain(domain.map(powp));
+      return scale;
+    };
+    scale.copy = function() {
+      return d3_scale_pow(linear.copy(), exponent, domain);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  function d3_scale_powPow(e) {
+    return function(x) {
+      return x &lt; 0 ? -Math.pow(-x, e) : Math.pow(x, e);
+    };
+  }
+  d3.scale.sqrt = function() {
+    return d3.scale.pow().exponent(.5);
+  };
+  d3.scale.ordinal = function() {
+    return d3_scale_ordinal([], {
+      t: &quot;range&quot;,
+      a: [ [] ]
+    });
+  };
+  function d3_scale_ordinal(domain, ranger) {
+    var index, range, rangeBand;
+    function scale(x) {
+      return range[((index.get(x) || (ranger.t === &quot;range&quot; ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
+    }
+    function steps(start, step) {
+      return d3.range(domain.length).map(function(i) {
+        return start + step * i;
+      });
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = [];
+      index = new d3_Map();
+      var i = -1, n = x.length, xi;
+      while (++i &lt; n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
+      return scale[ranger.t].apply(scale, ranger.a);
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      rangeBand = 0;
+      ranger = {
+        t: &quot;range&quot;,
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangePoints = function(x, padding) {
+      if (arguments.length &lt; 2) padding = 0;
+      var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
+      range = steps(domain.length &lt; 2 ? (start + stop) / 2 : start + step * padding / 2, step);
+      rangeBand = 0;
+      ranger = {
+        t: &quot;rangePoints&quot;,
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeBands = function(x, padding, outerPadding) {
+      if (arguments.length &lt; 2) padding = 0;
+      if (arguments.length &lt; 3) outerPadding = padding;
+      var reverse = x[1] &lt; x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
+      range = steps(start + step * outerPadding, step);
+      if (reverse) range.reverse();
+      rangeBand = step * (1 - padding);
+      ranger = {
+        t: &quot;rangeBands&quot;,
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeRoundBands = function(x, padding, outerPadding) {
+      if (arguments.length &lt; 2) padding = 0;
+      if (arguments.length &lt; 3) outerPadding = padding;
+      var reverse = x[1] &lt; x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
+      range = steps(start + Math.round(error / 2), step);
+      if (reverse) range.reverse();
+      rangeBand = Math.round(step * (1 - padding));
+      ranger = {
+        t: &quot;rangeRoundBands&quot;,
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeBand = function() {
+      return rangeBand;
+    };
+    scale.rangeExtent = function() {
+      return d3_scaleExtent(ranger.a[0]);
+    };
+    scale.copy = function() {
+      return d3_scale_ordinal(domain, ranger);
+    };
+    return scale.domain(domain);
+  }
+  d3.scale.category10 = function() {
+    return d3.scale.ordinal().range(d3_category10);
+  };
+  d3.scale.category20 = function() {
+    return d3.scale.ordinal().range(d3_category20);
+  };
+  d3.scale.category20b = function() {
+    return d3.scale.ordinal().range(d3_category20b);
+  };
+  d3.scale.category20c = function() {
+    return d3.scale.ordinal().range(d3_category20c);
+  };
+  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
+  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
+  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
+  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
+  d3.scale.quantile = function() {
+    return d3_scale_quantile([], []);
+  };
+  function d3_scale_quantile(domain, range) {
+    var thresholds;
+    function rescale() {
+      var k = 0, q = range.length;
+      thresholds = [];
+      while (++k &lt; q) thresholds[k - 1] = d3.quantile(domain, k / q);
+      return scale;
+    }
+    function scale(x) {
+      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.filter(d3_number).sort(d3_ascending);
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.quantiles = function() {
+      return thresholds;
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      return y &lt; 0 ? [ NaN, NaN ] : [ y &gt; 0 ? thresholds[y - 1] : domain[0], y &lt; thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
+    };
+    scale.copy = function() {
+      return d3_scale_quantile(domain, range);
+    };
+    return rescale();
+  }
+  d3.scale.quantize = function() {
+    return d3_scale_quantize(0, 1, [ 0, 1 ]);
+  };
+  function d3_scale_quantize(x0, x1, range) {
+    var kx, i;
+    function scale(x) {
+      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
+    }
+    function rescale() {
+      kx = range.length / (x1 - x0);
+      i = range.length - 1;
+      return scale;
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return [ x0, x1 ];
+      x0 = +x[0];
+      x1 = +x[x.length - 1];
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      y = y &lt; 0 ? NaN : y / kx + x0;
+      return [ y, y + 1 / kx ];
+    };
+    scale.copy = function() {
+      return d3_scale_quantize(x0, x1, range);
+    };
+    return rescale();
+  }
+  d3.scale.threshold = function() {
+    return d3_scale_threshold([ .5 ], [ 0, 1 ]);
+  };
+  function d3_scale_threshold(domain, range) {
+    function scale(x) {
+      if (x &lt;= x) return range[d3.bisect(domain, x)];
+    }
+    scale.domain = function(_) {
+      if (!arguments.length) return domain;
+      domain = _;
+      return scale;
+    };
+    scale.range = function(_) {
+      if (!arguments.length) return range;
+      range = _;
+      return scale;
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      return [ domain[y - 1], domain[y] ];
+    };
+    scale.copy = function() {
+      return d3_scale_threshold(domain, range);
+    };
+    return scale;
+  }
+  d3.scale.identity = function() {
+    return d3_scale_identity([ 0, 1 ]);
+  };
+  function d3_scale_identity(domain) {
+    function identity(x) {
+      return +x;
+    }
+    identity.invert = identity;
+    identity.domain = identity.range = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.map(identity);
+      return identity;
+    };
+    identity.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    identity.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    identity.copy = function() {
+      return d3_scale_identity(domain);
+    };
+    return identity;
+  }
+  d3.svg = {};
+  d3.svg.arc = function() {
+    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+    function arc() {
+      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 &lt; a0 &amp;&amp; (da = a0, 
+      a0 = a1, a1 = da), a1 - a0), df = da &lt; π ? &quot;0&quot; : &quot;1&quot;, c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
+      return da &gt;= d3_svg_arcMax ? r0 ? &quot;M0,&quot; + r1 + &quot;A&quot; + r1 + &quot;,&quot; + r1 + &quot; 0 1,1 0,&quot; + -r1 + &quot;A&quot; + r1 + &quot;,&quot; + r1 + &quot; 0 1,1 0,&quot; + r1 + &quot;M0,&quot; + r0 + &quot;A&quot; + r0 + &quot;,&quot; + r0 + &quot; 0 1,0 0,&quot; + -r0 + &quot;A&quot; + r0 + &quot;,&quot; + r0 + &quot; 0 1,0 0,&quot; + r0 + &quot;Z&quot; : &quot;M0,&quot; + r1 + &quot;A&quot; + r1 + &quot;,&quot; + r1 + &quot; 0 1,1 0,&quot; + -r1 + &quot;A&quot; + r1 + &quot;,&quot; + r1 + &quot; 0 1,1 0,&quot; + r1 + &quot;Z&quot; : r0 ? &quot;M&quot; + r1 * c0 + &quot;,&quot; + r1 * s0 + &quot;A&quot; + r1 + &quot;,&quot; + r1 + &quot; 0 &quot; + df + &quot;,1 &quot; + r1 * c1 + &quot;,&quot; + r1 * s1 + &quot;L&quot; + r0 * c1 + &quot;,&quot; + r0 * s1 + &quot;A&quot; + r0 + &quot;,&quot; + r0 + &quot; 0 &quot; + df + &quot;,0 &quot; + r0 * c0 + &quot;,&quot; + r0 * s0 + &quot;Z&quot; : &quot;M&quot; + r1 * c0 + &quot;,&quot; + r1 * s0 + &quot;A&quot; + r1 + &quot;,&quot; + r1 + &quot; 0 &quot; + df + &quot;,1 &quot; + r1 * c1 + &quot;,&quot; + r1 * s1 + &quot;L0,0&quot; + &quot;Z&quot;;
+    }
+    arc.innerRadius = function(v) {
+      if (!arguments.length) return innerRadius;
+      innerRadius = d3_functor(v);
+      return arc;
+    };
+    arc.outerRadius = function(v) {
+      if (!arguments.length) return outerRadius;
+      outerRadius = d3_functor(v);
+      return arc;
+    };
+    arc.startAngle = function(v) {
+      if (!arguments.length) return startAngle;
+      startAngle = d3_functor(v);
+      return arc;
+    };
+    arc.endAngle = function(v) {
+      if (!arguments.length) return endAngle;
+      endAngle = d3_functor(v);
+      return arc;
+    };
+    arc.centroid = function() {
+      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
+      return [ Math.cos(a) * r, Math.sin(a) * r ];
+    };
+    return arc;
+  };
+  var d3_svg_arcOffset = -halfπ, d3_svg_arcMax = τ - ε;
+  function d3_svg_arcInnerRadius(d) {
+    return d.innerRadius;
+  }
+  function d3_svg_arcOuterRadius(d) {
+    return d.outerRadius;
+  }
+  function d3_svg_arcStartAngle(d) {
+    return d.startAngle;
+  }
+  function d3_svg_arcEndAngle(d) {
+    return d.endAngle;
+  }
+  function d3_svg_line(projection) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
+    function line(data) {
+      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
+      function segment() {
+        segments.push(&quot;M&quot;, interpolate(projection(points), tension));
+      }
+      while (++i &lt; n) {
+        if (defined.call(this, d = data[i], i)) {
+          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
+        } else if (points.length) {
+          segment();
+          points = [];
+        }
+      }
+      if (points.length) segment();
+      return segments.length ? segments.join(&quot;&quot;) : null;
+    }
+    line.x = function(_) {
+      if (!arguments.length) return x;
+      x = _;
+      return line;
+    };
+    line.y = function(_) {
+      if (!arguments.length) return y;
+      y = _;
+      return line;
+    };
+    line.defined = function(_) {
+      if (!arguments.length) return defined;
+      defined = _;
+      return line;
+    };
+    line.interpolate = function(_) {
+      if (!arguments.length) return interpolateKey;
+      if (typeof _ === &quot;function&quot;) interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+      return line;
+    };
+    line.tension = function(_) {
+      if (!arguments.length) return tension;
+      tension = _;
+      return line;
+    };
+    return line;
+  }
+  d3.svg.line = function() {
+    return d3_svg_line(d3_identity);
+  };
+  var d3_svg_lineInterpolators = d3.map({
+    linear: d3_svg_lineLinear,
+    &quot;linear-closed&quot;: d3_svg_lineLinearClosed,
+    step: d3_svg_lineStep,
+    &quot;step-before&quot;: d3_svg_lineStepBefore,
+    &quot;step-after&quot;: d3_svg_lineStepAfter,
+    basis: d3_svg_lineBasis,
+    &quot;basis-open&quot;: d3_svg_lineBasisOpen,
+    &quot;basis-closed&quot;: d3_svg_lineBasisClosed,
+    bundle: d3_svg_lineBundle,
+    cardinal: d3_svg_lineCardinal,
+    &quot;cardinal-open&quot;: d3_svg_lineCardinalOpen,
+    &quot;cardinal-closed&quot;: d3_svg_lineCardinalClosed,
+    monotone: d3_svg_lineMonotone
+  });
+  d3_svg_lineInterpolators.forEach(function(key, value) {
+    value.key = key;
+    value.closed = /-closed$/.test(key);
+  });
+  function d3_svg_lineLinear(points) {
+    return points.join(&quot;L&quot;);
+  }
+  function d3_svg_lineLinearClosed(points) {
+    return d3_svg_lineLinear(points) + &quot;Z&quot;;
+  }
+  function d3_svg_lineStep(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], &quot;,&quot;, p[1] ];
+    while (++i &lt; n) path.push(&quot;H&quot;, (p[0] + (p = points[i])[0]) / 2, &quot;V&quot;, p[1]);
+    if (n &gt; 1) path.push(&quot;H&quot;, p[0]);
+    return path.join(&quot;&quot;);
+  }
+  function d3_svg_lineStepBefore(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], &quot;,&quot;, p[1] ];
+    while (++i &lt; n) path.push(&quot;V&quot;, (p = points[i])[1], &quot;H&quot;, p[0]);
+    return path.join(&quot;&quot;);
+  }
+  function d3_svg_lineStepAfter(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], &quot;,&quot;, p[1] ];
+    while (++i &lt; n) path.push(&quot;H&quot;, (p = points[i])[0], &quot;V&quot;, p[1]);
+    return path.join(&quot;&quot;);
+  }
+  function d3_svg_lineCardinalOpen(points, tension) {
+    return points.length &lt; 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
+  }
+  function d3_svg_lineCardinalClosed(points, tension) {
+    return points.length &lt; 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
+    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
+  }
+  function d3_svg_lineCardinal(points, tension) {
+    return points.length &lt; 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
+  }
+  function d3_svg_lineHermite(points, tangents) {
+    if (tangents.length &lt; 1 || points.length != tangents.length &amp;&amp; points.length != tangents.length + 2) {
+      return d3_svg_lineLinear(points);
+    }
+    var quad = points.length != tangents.length, path = &quot;&quot;, p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
+    if (quad) {
+      path += &quot;Q&quot; + (p[0] - t0[0] * 2 / 3) + &quot;,&quot; + (p[1] - t0[1] * 2 / 3) + &quot;,&quot; + p[0] + &quot;,&quot; + p[1];
+      p0 = points[1];
+      pi = 2;
+    }
+    if (tangents.length &gt; 1) {
+      t = tangents[1];
+      p = points[pi];
+      pi++;
+      path += &quot;C&quot; + (p0[0] + t0[0]) + &quot;,&quot; + (p0[1] + t0[1]) + &quot;,&quot; + (p[0] - t[0]) + &quot;,&quot; + (p[1] - t[1]) + &quot;,&quot; + p[0] + &quot;,&quot; + p[1];
+      for (var i = 2; i &lt; tangents.length; i++, pi++) {
+        p = points[pi];
+        t = tangents[i];
+        path += &quot;S&quot; + (p[0] - t[0]) + &quot;,&quot; + (p[1] - t[1]) + &quot;,&quot; + p[0] + &quot;,&quot; + p[1];
+      }
+    }
+    if (quad) {
+      var lp = points[pi];
+      path += &quot;Q&quot; + (p[0] + t[0] * 2 / 3) + &quot;,&quot; + (p[1] + t[1] * 2 / 3) + &quot;,&quot; + lp[0] + &quot;,&quot; + lp[1];
+    }
+    return path;
+  }
+  function d3_svg_lineCardinalTangents(points, tension) {
+    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
+    while (++i &lt; n) {
+      p0 = p1;
+      p1 = p2;
+      p2 = points[i];
+      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
+    }
+    return tangents;
+  }
+  function d3_svg_lineBasis(points) {
+    if (points.length &lt; 3) return d3_svg_lineLinear(points);
+    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, &quot;,&quot;, y0, &quot;L&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+    points.push(points[n - 1]);
+    while (++i &lt;= n) {
+      pi = points[i];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    points.pop();
+    path.push(&quot;L&quot;, pi);
+    return path.join(&quot;&quot;);
+  }
+  function d3_svg_lineBasisOpen(points) {
+    if (points.length &lt; 4) return d3_svg_lineLinear(points);
+    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
+    while (++i &lt; 3) {
+      pi = points[i];
+      px.push(pi[0]);
+      py.push(pi[1]);
+    }
+    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + &quot;,&quot; + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
+    --i;
+    while (++i &lt; n) {
+      pi = points[i];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    return path.join(&quot;&quot;);
+  }
+  function d3_svg_lineBasisClosed(points) {
+    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
+    while (++i &lt; 4) {
+      pi = points[i % n];
+      px.push(pi[0]);
+      py.push(pi[1]);
+    }
+    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+    --i;
+    while (++i &lt; m) {
+      pi = points[i % n];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    return path.join(&quot;&quot;);
+  }
+  function d3_svg_lineBundle(points, tension) {
+    var n = points.length - 1;
+    if (n) {
+      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
+      while (++i &lt;= n) {
+        p = points[i];
+        t = i / n;
+        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
+        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
+      }
+    }
+    return d3_svg_lineBasis(points);
+  }
+  function d3_svg_lineDot4(a, b) {
+    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+  }
+  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
+  function d3_svg_lineBasisBezier(path, x, y) {
+    path.push(&quot;C&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), &quot;,&quot;, d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
+  }
+  function d3_svg_lineSlope(p0, p1) {
+    return (p1[1] - p0[1]) / (p1[0] - p0[0]);
+  }
+  function d3_svg_lineFiniteDifferences(points) {
+    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
+    while (++i &lt; j) {
+      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
+    }
+    m[i] = d;
+    return m;
+  }
+  function d3_svg_lineMonotoneTangents(points) {
+    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
+    while (++i &lt; j) {
+      d = d3_svg_lineSlope(points[i], points[i + 1]);
+      if (abs(d) &lt; ε) {
+        m[i] = m[i + 1] = 0;
+      } else {
+        a = m[i] / d;
+        b = m[i + 1] / d;
+        s = a * a + b * b;
+        if (s &gt; 9) {
+          s = d * 3 / Math.sqrt(s);
+          m[i] = s * a;
+          m[i + 1] = s * b;
+        }
+      }
+    }
+    i = -1;
+    while (++i &lt;= j) {
+      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
+      tangents.push([ s || 0, m[i] * s || 0 ]);
+    }
+    return tangents;
+  }
+  function d3_svg_lineMonotone(points) {
+    return points.length &lt; 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+  }
+  d3.svg.line.radial = function() {
+    var line = d3_svg_line(d3_svg_lineRadial);
+    line.radius = line.x, delete line.x;
+    line.angle = line.y, delete line.y;
+    return line;
+  };
+  function d3_svg_lineRadial(points) {
+    var point, i = -1, n = points.length, r, a;
+    while (++i &lt; n) {
+      point = points[i];
+      r = point[0];
+      a = point[1] + d3_svg_arcOffset;
+      point[0] = r * Math.cos(a);
+      point[1] = r * Math.sin(a);
+    }
+    return points;
+  }
+  function d3_svg_area(projection) {
+    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = &quot;L&quot;, tension = .7;
+    function area(data) {
+      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
+        return x;
+      } : d3_functor(x1), fy1 = y0 === y1 ? function() {
+        return y;
+      } : d3_functor(y1), x, y;
+      function segment() {
+        segments.push(&quot;M&quot;, interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), &quot;Z&quot;);
+      }
+      while (++i &lt; n) {
+        if (defined.call(this, d = data[i], i)) {
+          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
+          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
+        } else if (points0.length) {
+          segment();
+          points0 = [];
+          points1 = [];
+        }
+      }
+      if (points0.length) segment();
+      return segments.length ? segments.join(&quot;&quot;) : null;
+    }
+    area.x = function(_) {
+      if (!arguments.length) return x1;
+      x0 = x1 = _;
+      return area;
+    };
+    area.x0 = function(_) {
+      if (!arguments.length) return x0;
+      x0 = _;
+      return area;
+    };
+    area.x1 = function(_) {
+      if (!arguments.length) return x1;
+      x1 = _;
+      return area;
+    };
+    area.y = function(_) {
+      if (!arguments.length) return y1;
+      y0 = y1 = _;
+      return area;
+    };
+    area.y0 = function(_) {
+      if (!arguments.length) return y0;
+      y0 = _;
+      return area;
+    };
+    area.y1 = function(_) {
+      if (!arguments.length) return y1;
+      y1 = _;
+      return area;
+    };
+    area.defined = function(_) {
+      if (!arguments.length) return defined;
+      defined = _;
+      return area;
+    };
+    area.interpolate = function(_) {
+      if (!arguments.length) return interpolateKey;
+      if (typeof _ === &quot;function&quot;) interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+      interpolateReverse = interpolate.reverse || interpolate;
+      L = interpolate.closed ? &quot;M&quot; : &quot;L&quot;;
+      return area;
+    };
+    area.tension = function(_) {
+      if (!arguments.length) return tension;
+      tension = _;
+      return area;
+    };
+    return area;
+  }
+  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
+  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
+  d3.svg.area = function() {
+    return d3_svg_area(d3_identity);
+  };
+  d3.svg.area.radial = function() {
+    var area = d3_svg_area(d3_svg_lineRadial);
+    area.radius = area.x, delete area.x;
+    area.innerRadius = area.x0, delete area.x0;
+    area.outerRadius = area.x1, delete area.x1;
+    area.angle = area.y, delete area.y;
+    area.startAngle = area.y0, delete area.y0;
+    area.endAngle = area.y1, delete area.y1;
+    return area;
+  };
+  d3.svg.chord = function() {
+    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+    function chord(d, i) {
+      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
+      return &quot;M&quot; + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + &quot;Z&quot;;
+    }
+    function subgroup(self, f, d, i) {
+      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
+      return {
+        r: r,
+        a0: a0,
+        a1: a1,
+        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
+        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
+      };
+    }
+    function equals(a, b) {
+      return a.a0 == b.a0 &amp;&amp; a.a1 == b.a1;
+    }
+    function arc(r, p, a) {
+      return &quot;A&quot; + r + &quot;,&quot; + r + &quot; 0 &quot; + +(a &gt; π) + &quot;,1 &quot; + p;
+    }
+    function curve(r0, p0, r1, p1) {
+      return &quot;Q 0,0 &quot; + p1;
+    }
+    chord.radius = function(v) {
+      if (!arguments.length) return radius;
+      radius = d3_functor(v);
+      return chord;
+    };
+    chord.source = function(v) {
+      if (!arguments.length) return source;
+      source = d3_functor(v);
+      return chord;
+    };
+    chord.target = function(v) {
+      if (!arguments.length) return target;
+      target = d3_functor(v);
+      return chord;
+    };
+    chord.startAngle = function(v) {
+      if (!arguments.length) return startAngle;
+      startAngle = d3_functor(v);
+      return chord;
+    };
+    chord.endAngle = function(v) {
+      if (!arguments.length) return endAngle;
+      endAngle = d3_functor(v);
+      return chord;
+    };
+    return chord;
+  };
+  function d3_svg_chordRadius(d) {
+    return d.radius;
+  }
+  d3.svg.diagonal = function() {
+    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
+    function diagonal(d, i) {
+      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
+        x: p0.x,
+        y: m
+      }, {
+        x: p3.x,
+        y: m
+      }, p3 ];
+      p = p.map(projection);
+      return &quot;M&quot; + p[0] + &quot;C&quot; + p[1] + &quot; &quot; + p[2] + &quot; &quot; + p[3];
+    }
+    diagonal.source = function(x) {
+      if (!arguments.length) return source;
+      source = d3_functor(x);
+      return diagonal;
+    };
+    diagonal.target = function(x) {
+      if (!arguments.length) return target;
+      target = d3_functor(x);
+      return diagonal;
+    };
+    diagonal.projection = function(x) {
+      if (!arguments.length) return projection;
+      projection = x;
+      return diagonal;
+    };
+    return diagonal;
+  };
+  function d3_svg_diagonalProjection(d) {
+    return [ d.x, d.y ];
+  }
+  d3.svg.diagonal.radial = function() {
+    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
+    diagonal.projection = function(x) {
+      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
+    };
+    return diagonal;
+  };
+  function d3_svg_diagonalRadialProjection(projection) {
+    return function() {
+      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
+      return [ r * Math.cos(a), r * Math.sin(a) ];
+    };
+  }
+  d3.svg.symbol = function() {
+    var type = d3_svg_symbolType, size = d3_svg_symbolSize;
+    function symbol(d, i) {
+      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
+    }
+    symbol.type = function(x) {
+      if (!arguments.length) return type;
+      type = d3_functor(x);
+      return symbol;
+    };
+    symbol.size = function(x) {
+      if (!arguments.length) return size;
+      size = d3_functor(x);
+      return symbol;
+    };
+    return symbol;
+  };
+  function d3_svg_symbolSize() {
+    return 64;
+  }
+  function d3_svg_symbolType() {
+    return &quot;circle&quot;;
+  }
+  function d3_svg_symbolCircle(size) {
+    var r = Math.sqrt(size / π);
+    return &quot;M0,&quot; + r + &quot;A&quot; + r + &quot;,&quot; + r + &quot; 0 1,1 0,&quot; + -r + &quot;A&quot; + r + &quot;,&quot; + r + &quot; 0 1,1 0,&quot; + r + &quot;Z&quot;;
+  }
+  var d3_svg_symbols = d3.map({
+    circle: d3_svg_symbolCircle,
+    cross: function(size) {
+      var r = Math.sqrt(size / 5) / 2;
+      return &quot;M&quot; + -3 * r + &quot;,&quot; + -r + &quot;H&quot; + -r + &quot;V&quot; + -3 * r + &quot;H&quot; + r + &quot;V&quot; + -r + &quot;H&quot; + 3 * r + &quot;V&quot; + r + &quot;H&quot; + r + &quot;V&quot; + 3 * r + &quot;H&quot; + -r + &quot;V&quot; + r + &quot;H&quot; + -3 * r + &quot;Z&quot;;
+    },
+    diamond: function(size) {
+      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
+      return &quot;M0,&quot; + -ry + &quot;L&quot; + rx + &quot;,0&quot; + &quot; 0,&quot; + ry + &quot; &quot; + -rx + &quot;,0&quot; + &quot;Z&quot;;
+    },
+    square: function(size) {
+      var r = Math.sqrt(size) / 2;
+      return &quot;M&quot; + -r + &quot;,&quot; + -r + &quot;L&quot; + r + &quot;,&quot; + -r + &quot; &quot; + r + &quot;,&quot; + r + &quot; &quot; + -r + &quot;,&quot; + r + &quot;Z&quot;;
+    },
+    &quot;triangle-down&quot;: function(size) {
+      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+      return &quot;M0,&quot; + ry + &quot;L&quot; + rx + &quot;,&quot; + -ry + &quot; &quot; + -rx + &quot;,&quot; + -ry + &quot;Z&quot;;
+    },
+    &quot;triangle-up&quot;: function(size) {
+      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+      return &quot;M0,&quot; + -ry + &quot;L&quot; + rx + &quot;,&quot; + ry + &quot; &quot; + -rx + &quot;,&quot; + ry + &quot;Z&quot;;
+    }
+  });
+  d3.svg.symbolTypes = d3_svg_symbols.keys();
+  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
+  function d3_transition(groups, id) {
+    d3_subclass(groups, d3_transitionPrototype);
+    groups.id = id;
+    return groups;
+  }
+  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
+  d3_transitionPrototype.call = d3_selectionPrototype.call;
+  d3_transitionPrototype.empty = d3_selectionPrototype.empty;
+  d3_transitionPrototype.node = d3_selectionPrototype.node;
+  d3_transitionPrototype.size = d3_selectionPrototype.size;
+  d3.transition = function(selection) {
+    return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+  };
+  d3.transition.prototype = d3_transitionPrototype;
+  d3_transitionPrototype.select = function(selector) {
+    var id = this.id, subgroups = [], subgroup, subnode, node;
+    selector = d3_selection_selector(selector);
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = -1, n = group.length; ++i &lt; n; ) {
+        if ((node = group[i]) &amp;&amp; (subnode = selector.call(node, node.__data__, i, j))) {
+          if (&quot;__data__&quot; in node) subnode.__data__ = node.__data__;
+          d3_transitionNode(subnode, i, id, node.__transition__[id]);
+          subgroup.push(subnode);
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_transitionPrototype.selectAll = function(selector) {
+    var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
+    selector = d3_selection_selectorAll(selector);
+    for (var j = -1, m = this.length; ++j &lt; m; ) {
+      for (var group = this[j], i = -1, n = group.length; ++i &lt; n; ) {
+        if (node = group[i]) {
+          transition = node.__transition__[id];
+          subnodes = selector.call(node, node.__data__, i, j);
+          subgroups.push(subgroup = []);
+          for (var k = -1, o = subnodes.length; ++k &lt; o; ) {
+            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);
+            subgroup.push(subnode);
+          }
+        }
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_transitionPrototype.filter = function(filter) {
+    var subgroups = [], subgroup, group, node;
+    if (typeof filter !== &quot;function&quot;) filter = d3_selection_filter(filter);
+    for (var j = 0, m = this.length; j &lt; m; j++) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = 0, n = group.length; i &lt; n; i++) {
+        if ((node = group[i]) &amp;&amp; filter.call(node, node.__data__, i, j)) {
+          subgroup.push(node);
+        }
+      }
+    }
+    return d3_transition(subgroups, this.id);
+  };
+  d3_transitionPrototype.tween = function(name, tween) {
+    var id = this.id;
+    if (arguments.length &lt; 2) return this.node().__transition__[id].tween.get(name);
+    return d3_selection_each(this, tween == null ? function(node) {
+      node.__transition__[id].tween.remove(name);
+    } : function(node) {
+      node.__transition__[id].tween.set(name, tween);
+    });
+  };
+  function d3_transition_tween(groups, name, value, tween) {
+    var id = groups.id;
+    return d3_selection_each(groups, typeof value === &quot;function&quot; ? function(node, i, j) {
+      node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
+    } : (value = tween(value), function(node) {
+      node.__transition__[id].tween.set(name, value);
+    }));
+  }
+  d3_transitionPrototype.attr = function(nameNS, value) {
+    if (arguments.length &lt; 2) {
+      for (value in nameNS) this.attr(value, nameNS[value]);
+      return this;
+    }
+    var interpolate = nameNS == &quot;transform&quot; ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
+    function attrNull() {
+      this.removeAttribute(name);
+    }
+    function attrNullNS() {
+      this.removeAttributeNS(name.space, name.local);
+    }
+    function attrTween(b) {
+      return b == null ? attrNull : (b += &quot;&quot;, function() {
+        var a = this.getAttribute(name), i;
+        return a !== b &amp;&amp; (i = interpolate(a, b), function(t) {
+          this.setAttribute(name, i(t));
+        });
+      });
+    }
+    function attrTweenNS(b) {
+      return b == null ? attrNullNS : (b += &quot;&quot;, function() {
+        var a = this.getAttributeNS(name.space, name.local), i;
+        return a !== b &amp;&amp; (i = interpolate(a, b), function(t) {
+          this.setAttributeNS(name.space, name.local, i(t));
+        });
+      });
+    }
+    return d3_transition_tween(this, &quot;attr.&quot; + nameNS, value, name.local ? attrTweenNS : attrTween);
+  };
+  d3_transitionPrototype.attrTween = function(nameNS, tween) {
+    var name = d3.ns.qualify(nameNS);
+    function attrTween(d, i) {
+      var f = tween.call(this, d, i, this.getAttribute(name));
+      return f &amp;&amp; function(t) {
+        this.setAttribute(name, f(t));
+      };
+    }
+    function attrTweenNS(d, i) {
+      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
+      return f &amp;&amp; function(t) {
+        this.setAttributeNS(name.space, name.local, f(t));
+      };
+    }
+    return this.tween(&quot;attr.&quot; + nameNS, name.local ? attrTweenNS : attrTween);
+  };
+  d3_transitionPrototype.style = function(name, value, priority) {
+    var n = arguments.length;
+    if (n &lt; 3) {
+      if (typeof name !== &quot;string&quot;) {
+        if (n &lt; 2) value = &quot;&quot;;
+        for (priority in name) this.style(priority, name[priority], value);
+        return this;
+      }
+      priority = &quot;&quot;;
+    }
+    function styleNull() {
+      this.style.removeProperty(name);
+    }
+    function styleString(b) {
+      return b == null ? styleNull : (b += &quot;&quot;, function() {
+        var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
+        return a !== b &amp;&amp; (i = d3_interpolate(a, b), function(t) {
+          this.style.setProperty(name, i(t), priority);
+        });
+      });
+    }
+    return d3_transition_tween(this, &quot;style.&quot; + name, value, styleString);
+  };
+  d3_transitionPrototype.styleTween = function(name, tween, priority) {
+    if (arguments.length &lt; 3) priority = &quot;&quot;;
+    function styleTween(d, i) {
+      var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));
+      return f &amp;&amp; function(t) {
+        this.style.setProperty(name, f(t), priority);
+      };
+    }
+    return this.tween(&quot;style.&quot; + name, styleTween);
+  };
+  d3_transitionPrototype.text = function(value) {
+    return d3_transition_tween(this, &quot;text&quot;, value, d3_transition_text);
+  };
+  function d3_transition_text(b) {
+    if (b == null) b = &quot;&quot;;
+    return function() {
+      this.textContent = b;
+    };
+  }
+  d3_transitionPrototype.remove = function() {
+    return this.each(&quot;end.transition&quot;, function() {
+      var p;
+      if (this.__transition__.count &lt; 2 &amp;&amp; (p = this.parentNode)) p.removeChild(this);
+    });
+  };
+  d3_transitionPrototype.ease = function(value) {
+    var id = this.id;
+    if (arguments.length &lt; 1) return this.node().__transition__[id].ease;
+    if (typeof value !== &quot;function&quot;) value = d3.ease.apply(d3, arguments);
+    return d3_selection_each(this, function(node) {
+      node.__transition__[id].ease = value;
+    });
+  };
+  d3_transitionPrototype.delay = function(value) {
+    var id = this.id;
+    if (arguments.length &lt; 1) return this.node().__transition__[id].delay;
+    return d3_selection_each(this, typeof value === &quot;function&quot; ? function(node, i, j) {
+      node.__transition__[id].delay = +value.call(node, node.__data__, i, j);
+    } : (value = +value, function(node) {
+      node.__transition__[id].delay = value;
+    }));
+  };
+  d3_transitionPrototype.duration = function(value) {
+    var id = this.id;
+    if (arguments.length &lt; 1) return this.node().__transition__[id].duration;
+    return d3_selection_each(this, typeof value === &quot;function&quot; ? function(node, i, j) {
+      node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j));
+    } : (value = Math.max(1, value), function(node) {
+      node.__transition__[id].duration = value;
+    }));
+  };
+  d3_transitionPrototype.each = function(type, listener) {
+    var id = this.id;
+    if (arguments.length &lt; 2) {
+      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
+      d3_transitionInheritId = id;
+      d3_selection_each(this, function(node, i, j) {
+        d3_transitionInherit = node.__transition__[id];
+        type.call(node, node.__data__, i, j);
+      });
+      d3_transitionInherit = inherit;
+      d3_transitionInheritId = inheritId;
+    } else {
+      d3_selection_each(this, function(node) {
+        var transition = node.__transition__[id];
+        (transition.event || (transition.event = d3.dispatch(&quot;start&quot;, &quot;end&quot;))).on(type, listener);
+      });
+    }
+    return this;
+  };
+  d3_transitionPrototype.transition = function() {
+    var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;
+    for (var j = 0, m = this.length; j &lt; m; j++) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = 0, n = group.length; i &lt; n; i++) {
+        if (node = group[i]) {
+          transition = Object.create(node.__transition__[id0]);
+          transition.delay += transition.duration;
+          d3_transitionNode(node, i, id1, transition);
+        }
+        subgroup.push(node);
+      }
+    }
+    return d3_transition(subgroups, id1);
+  };
+  function d3_transitionNode(node, i, id, inherit) {
+    var lock = node.__transition__ || (node.__transition__ = {
+      active: 0,
+      count: 0
+    }), transition = lock[id];
+    if (!transition) {
+      var time = inherit.time;
+      transition = lock[id] = {
+        tween: new d3_Map(),
+        time: time,
+        ease: inherit.ease,
+        delay: inherit.delay,
+        duration: inherit.duration
+      };
+      ++lock.count;
+      d3.timer(function(elapsed) {
+        var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = [];
+        timer.t = delay + time;
+        if (delay &lt;= elapsed) return start(elapsed - delay);
+        timer.c = start;
+        function start(elapsed) {
+          if (lock.active &gt; id) return stop();
+          lock.active = id;
+          transition.event &amp;&amp; transition.event.start.call(node, d, i);
+          transition.tween.forEach(function(key, value) {
+            if (value = value.call(node, d, i)) {
+              tweened.push(value);
+            }
+          });
+          d3.timer(function() {
+            timer.c = tick(elapsed || 1) ? d3_true : tick;
+            return 1;
+          }, 0, time);
+        }
+        function tick(elapsed) {
+          if (lock.active !== id) return stop();
+          var t = elapsed / duration, e = ease(t), n = tweened.length;
+          while (n &gt; 0) {
+            tweened[--n].call(node, e);
+          }
+          if (t &gt;= 1) {
+            transition.event &amp;&amp; transition.event.end.call(node, d, i);
+            return stop();
+          }
+        }
+        function stop() {
+          if (--lock.count) delete lock[id]; else delete node.__transition__;
+          return 1;
+        }
+      }, 0, time);
+    }
+  }
+  d3.svg.axis = function() {
+    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
+    function axis(g) {
+      g.each(function() {
+        var g = d3.select(this);
+        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
+        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(&quot;.tick&quot;).data(ticks, scale1), tickEnter = tick.enter().insert(&quot;g&quot;, &quot;.domain&quot;).attr(&quot;class&quot;, &quot;tick&quot;).style(&quot;opacity&quot;, ε), tickExit = d3.transition(tick.exit()).style(&quot;opacity&quot;, ε).remove(), tickUpdate = d3.transition(tick.order()).style(&quot;opacity&quot;, 1), tickTransform;
+        var range = d3_scaleRange(scale1), path = g.selectAll(&quot;.domain&quot;).data([ 0 ]), pathUpdate = (path.enter().append(&quot;path&quot;).attr(&quot;class&quot;, &quot;domain&quot;), 
+        d3.transition(path));
+        tickEnter.append(&quot;line&quot;);
+        tickEnter.append(&quot;text&quot;);
+        var lineEnter = tickEnter.select(&quot;line&quot;), lineUpdate = tickUpdate.select(&quot;line&quot;), text = tick.select(&quot;text&quot;).text(tickFormat), textEnter = tickEnter.select(&quot;text&quot;), textUpdate = tickUpdate.select(&quot;text&quot;);
+        switch (orient) {
+         case &quot;bottom&quot;:
+          {
+            tickTransform = d3_svg_axisX;
+            lineEnter.attr(&quot;y2&quot;, innerTickSize);
+            textEnter.attr(&quot;y&quot;, Math.max(innerTickSize, 0) + tickPadding);
+            lineUpdate.attr(&quot;x2&quot;, 0).attr(&quot;y2&quot;, innerTickSize);
+            textUpdate.attr(&quot;x&quot;, 0).attr(&quot;y&quot;, Math.max(innerTickSize, 0) + tickPadding);
+            text.attr(&quot;dy&quot;, &quot;.71em&quot;).style(&quot;text-anchor&quot;, &quot;middle&quot;);
+            pathUpdate.attr(&quot;d&quot;, &quot;M&quot; + range[0] + &quot;,&quot; + outerTickSize + &quot;V0H&quot; + range[1] + &quot;V&quot; + outerTickSize);
+            break;
+          }
+
+         case &quot;top&quot;:
+          {
+            tickTransform = d3_svg_axisX;
+            lineEnter.attr(&quot;y2&quot;, -innerTickSize);
+            textEnter.attr(&quot;y&quot;, -(Math.max(innerTickSize, 0) + tickPadding));
+            lineUpdate.attr(&quot;x2&quot;, 0).attr(&quot;y2&quot;, -innerTickSize);
+            textUpdate.attr(&quot;x&quot;, 0).attr(&quot;y&quot;, -(Math.max(innerTickSize, 0) + tickPadding));
+            text.attr(&quot;dy&quot;, &quot;0em&quot;).style(&quot;text-anchor&quot;, &quot;middle&quot;);
+            pathUpdate.attr(&quot;d&quot;, &quot;M&quot; + range[0] + &quot;,&quot; + -outerTickSize + &quot;V0H&quot; + range[1] + &quot;V&quot; + -outerTickSize);
+            break;
+          }
+
+         case &quot;left&quot;:
+          {
+            tickTransform = d3_svg_axisY;
+            lineEnter.attr(&quot;x2&quot;, -innerTickSize);
+            textEnter.attr(&quot;x&quot;, -(Math.max(innerTickSize, 0) + tickPadding));
+            lineUpdate.attr(&quot;x2&quot;, -innerTickSize).attr(&quot;y2&quot;, 0);
+            textUpdate.attr(&quot;x&quot;, -(Math.max(innerTickSize, 0) + tickPadding)).attr(&quot;y&quot;, 0);
+            text.attr(&quot;dy&quot;, &quot;.32em&quot;).style(&quot;text-anchor&quot;, &quot;end&quot;);
+            pathUpdate.attr(&quot;d&quot;, &quot;M&quot; + -outerTickSize + &quot;,&quot; + range[0] + &quot;H0V&quot; + range[1] + &quot;H&quot; + -outerTickSize);
+            break;
+          }
+
+         case &quot;right&quot;:
+          {
+            tickTransform = d3_svg_axisY;
+            lineEnter.attr(&quot;x2&quot;, innerTickSize);
+            textEnter.attr(&quot;x&quot;, Math.max(innerTickSize, 0) + tickPadding);
+            lineUpdate.attr(&quot;x2&quot;, innerTickSize).attr(&quot;y2&quot;, 0);
+            textUpdate.attr(&quot;x&quot;, Math.max(innerTickSize, 0) + tickPadding).attr(&quot;y&quot;, 0);
+            text.attr(&quot;dy&quot;, &quot;.32em&quot;).style(&quot;text-anchor&quot;, &quot;start&quot;);
+            pathUpdate.attr(&quot;d&quot;, &quot;M&quot; + outerTickSize + &quot;,&quot; + range[0] + &quot;H0V&quot; + range[1] + &quot;H&quot; + outerTickSize);
+            break;
+          }
+        }
+        if (scale1.rangeBand) {
+          var x = scale1, dx = x.rangeBand() / 2;
+          scale0 = scale1 = function(d) {
+            return x(d) + dx;
+          };
+        } else if (scale0.rangeBand) {
+          scale0 = scale1;
+        } else {
+          tickExit.call(tickTransform, scale1);
+        }
+        tickEnter.call(tickTransform, scale0);
+        tickUpdate.call(tickTransform, scale1);
+      });
+    }
+    axis.scale = function(x) {
+      if (!arguments.length) return scale;
+      scale = x;
+      return axis;
+    };
+    axis.orient = function(x) {
+      if (!arguments.length) return orient;
+      orient = x in d3_svg_axisOrients ? x + &quot;&quot; : d3_svg_axisDefaultOrient;
+      return axis;
+    };
+    axis.ticks = function() {
+      if (!arguments.length) return tickArguments_;
+      tickArguments_ = arguments;
+      return axis;
+    };
+    axis.tickValues = function(x) {
+      if (!arguments.length) return tickValues;
+      tickValues = x;
+      return axis;
+    };
+    axis.tickFormat = function(x) {
+      if (!arguments.length) return tickFormat_;
+      tickFormat_ = x;
+      return axis;
+    };
+    axis.tickSize = function(x) {
+      var n = arguments.length;
+      if (!n) return innerTickSize;
+      innerTickSize = +x;
+      outerTickSize = +arguments[n - 1];
+      return axis;
+    };
+    axis.innerTickSize = function(x) {
+      if (!arguments.length) return innerTickSize;
+      innerTickSize = +x;
+      return axis;
+    };
+    axis.outerTickSize = function(x) {
+      if (!arguments.length) return outerTickSize;
+      outerTickSize = +x;
+      return axis;
+    };
+    axis.tickPadding = function(x) {
+      if (!arguments.length) return tickPadding;
+      tickPadding = +x;
+      return axis;
+    };
+    axis.tickSubdivide = function() {
+      return arguments.length &amp;&amp; axis;
+    };
+    return axis;
+  };
+  var d3_svg_axisDefaultOrient = &quot;bottom&quot;, d3_svg_axisOrients = {
+    top: 1,
+    right: 1,
+    bottom: 1,
+    left: 1
+  };
+  function d3_svg_axisX(selection, x) {
+    selection.attr(&quot;transform&quot;, function(d) {
+      return &quot;translate(&quot; + x(d) + &quot;,0)&quot;;
+    });
+  }
+  function d3_svg_axisY(selection, y) {
+    selection.attr(&quot;transform&quot;, function(d) {
+      return &quot;translate(0,&quot; + y(d) + &quot;)&quot;;
+    });
+  }
+  d3.svg.brush = function() {
+    var event = d3_eventDispatch(brush, &quot;brushstart&quot;, &quot;brush&quot;, &quot;brushend&quot;), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
+    function brush(g) {
+      g.each(function() {
+        var g = d3.select(this).style(&quot;pointer-events&quot;, &quot;all&quot;).style(&quot;-webkit-tap-highlight-color&quot;, &quot;rgba(0,0,0,0)&quot;).on(&quot;mousedown.brush&quot;, brushstart).on(&quot;touchstart.brush&quot;, brushstart);
+        var background = g.selectAll(&quot;.background&quot;).data([ 0 ]);
+        background.enter().append(&quot;rect&quot;).attr(&quot;class&quot;, &quot;background&quot;).style(&quot;visibility&quot;, &quot;hidden&quot;).style(&quot;cursor&quot;, &quot;crosshair&quot;);
+        g.selectAll(&quot;.extent&quot;).data([ 0 ]).enter().append(&quot;rect&quot;).attr(&quot;class&quot;, &quot;extent&quot;).style(&quot;cursor&quot;, &quot;move&quot;);
+        var resize = g.selectAll(&quot;.resize&quot;).data(resizes, d3_identity);
+        resize.exit().remove();
+        resize.enter().append(&quot;g&quot;).attr(&quot;class&quot;, function(d) {
+          return &quot;resize &quot; + d;
+        }).style(&quot;cursor&quot;, function(d) {
+          return d3_svg_brushCursor[d];
+        }).append(&quot;rect&quot;).attr(&quot;x&quot;, function(d) {
+          return /[ew]$/.test(d) ? -3 : null;
+        }).attr(&quot;y&quot;, function(d) {
+          return /^[ns]/.test(d) ? -3 : null;
+        }).attr(&quot;width&quot;, 6).attr(&quot;height&quot;, 6).style(&quot;visibility&quot;, &quot;hidden&quot;);
+        resize.style(&quot;display&quot;, brush.empty() ? &quot;none&quot; : null);
+        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
+        if (x) {
+          range = d3_scaleRange(x);
+          backgroundUpdate.attr(&quot;x&quot;, range[0]).attr(&quot;width&quot;, range[1] - range[0]);
+          redrawX(gUpdate);
+        }
+        if (y) {
+          range = d3_scaleRange(y);
+          backgroundUpdate.attr(&quot;y&quot;, range[0]).attr(&quot;height&quot;, range[1] - range[0]);
+          redrawY(gUpdate);
+        }
+        redraw(gUpdate);
+      });
+    }
+    brush.event = function(g) {
+      g.each(function() {
+        var event_ = event.of(this, arguments), extent1 = {
+          x: xExtent,
+          y: yExtent,
+          i: xExtentDomain,
+          j: yExtentDomain
+        }, extent0 = this.__chart__ || extent1;
+        this.__chart__ = extent1;
+        if (d3_transitionInheritId) {
+          d3.select(this).transition().each(&quot;start.brush&quot;, function() {
+            xExtentDomain = extent0.i;
+            yExtentDomain = extent0.j;
+            xExtent = extent0.x;
+            yExtent = extent0.y;
+            event_({
+              type: &quot;brushstart&quot;
+            });
+          }).tween(&quot;brush:brush&quot;, function() {
+            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
+            xExtentDomain = yExtentDomain = null;
+            return function(t) {
+              xExtent = extent1.x = xi(t);
+              yExtent = extent1.y = yi(t);
+              event_({
+                type: &quot;brush&quot;,
+                mode: &quot;resize&quot;
+              });
+            };
+          }).each(&quot;end.brush&quot;, function() {
+            xExtentDomain = extent1.i;
+            yExtentDomain = extent1.j;
+            event_({
+              type: &quot;brush&quot;,
+              mode: &quot;resize&quot;
+            });
+            event_({
+              type: &quot;brushend&quot;
+            });
+          });
+        } else {
+          event_({
+            type: &quot;brushstart&quot;
+          });
+          event_({
+            type: &quot;brush&quot;,
+            mode: &quot;resize&quot;
+          });
+          event_({
+            type: &quot;brushend&quot;
+          });
+        }
+      });
+    };
+    function redraw(g) {
+      g.selectAll(&quot;.resize&quot;).attr(&quot;transform&quot;, function(d) {
+        return &quot;translate(&quot; + xExtent[+/e$/.test(d)] + &quot;,&quot; + yExtent[+/^s/.test(d)] + &quot;)&quot;;
+      });
+    }
+    function redrawX(g) {
+      g.select(&quot;.extent&quot;).attr(&quot;x&quot;, xExtent[0]);
+      g.selectAll(&quot;.extent,.n&gt;rect,.s&gt;rect&quot;).attr(&quot;width&quot;, xExtent[1] - xExtent[0]);
+    }
+    function redrawY(g) {
+      g.select(&quot;.extent&quot;).attr(&quot;y&quot;, yExtent[0]);
+      g.selectAll(&quot;.extent,.e&gt;rect,.w&gt;rect&quot;).attr(&quot;height&quot;, yExtent[1] - yExtent[0]);
+    }
+    function brushstart() {
+      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) &amp;&amp; x, resizingY = !/^(e|w)$/.test(resizing) &amp;&amp; y, dragging = eventTarget.classed(&quot;extent&quot;), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset;
+      var w = d3.select(d3_window).on(&quot;keydown.brush&quot;, keydown).on(&quot;keyup.brush&quot;, keyup);
+      if (d3.event.changedTouches) {
+        w.on(&quot;touchmove.brush&quot;, brushmove).on(&quot;touchend.brush&quot;, brushend);
+      } else {
+        w.on(&quot;mousemove.brush&quot;, brushmove).on(&quot;mouseup.brush&quot;, brushend);
+      }
+      g.interrupt().selectAll(&quot;*&quot;).interrupt();
+      if (dragging) {
+        origin[0] = xExtent[0] - origin[0];
+        origin[1] = yExtent[0] - origin[1];
+      } else if (resizing) {
+        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
+        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
+        origin[0] = xExtent[ex];
+        origin[1] = yExtent[ey];
+      } else if (d3.event.altKey) center = origin.slice();
+      g.style(&quot;pointer-events&quot;, &quot;none&quot;).selectAll(&quot;.resize&quot;).style(&quot;display&quot;, null);
+      d3.select(&quot;body&quot;).style(&quot;cursor&quot;, eventTarget.style(&quot;cursor&quot;));
+      event_({
+        type: &quot;brushstart&quot;
+      });
+      brushmove();
+      function keydown() {
+        if (d3.event.keyCode == 32) {
+          if (!dragging) {
+            center = null;
+            origin[0] -= xExtent[1];
+            origin[1] -= yExtent[1];
+            dragging = 2;
+          }
+          d3_eventPreventDefault();
+        }
+      }
+      function keyup() {
+        if (d3.event.keyCode == 32 &amp;&amp; dragging == 2) {
+          origin[0] += xExtent[1];
+          origin[1] += yExtent[1];
+          dragging = 0;
+          d3_eventPreventDefault();
+        }
+      }
+      function brushmove() {
+        var point = d3.mouse(target), moved = false;
+        if (offset) {
+          point[0] += offset[0];
+          point[1] += offset[1];
+        }
+        if (!dragging) {
+          if (d3.event.altKey) {
+            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
+            origin[0] = xExtent[+(point[0] &lt; center[0])];
+            origin[1] = yExtent[+(point[1] &lt; center[1])];
+          } else center = null;
+        }
+        if (resizingX &amp;&amp; move1(point, x, 0)) {
+          redrawX(g);
+          moved = true;
+        }
+        if (resizingY &amp;&amp; move1(point, y, 1)) {
+          redrawY(g);
+          moved = true;
+        }
+        if (moved) {
+          redraw(g);
+          event_({
+            type: &quot;brush&quot;,
+            mode: dragging ? &quot;move&quot; : &quot;resize&quot;
+          });
+        }
+      }
+      function move1(point, scale, i) {
+        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
+        if (dragging) {
+          r0 -= position;
+          r1 -= size + position;
+        }
+        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
+        if (dragging) {
+          max = (min += position) + size;
+        } else {
+          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
+          if (position &lt; min) {
+            max = min;
+            min = position;
+          } else {
+            max = position;
+          }
+        }
+        if (extent[0] != min || extent[1] != max) {
+          if (i) yExtentDomain = null; else xExtentDomain = null;
+          extent[0] = min;
+          extent[1] = max;
+          return true;
+        }
+      }
+      function brushend() {
+        brushmove();
+        g.style(&quot;pointer-events&quot;, &quot;all&quot;).selectAll(&quot;.resize&quot;).style(&quot;display&quot;, brush.empty() ? &quot;none&quot; : null);
+        d3.select(&quot;body&quot;).style(&quot;cursor&quot;, null);
+        w.on(&quot;mousemove.brush&quot;, null).on(&quot;mouseup.brush&quot;, null).on(&quot;touchmove.brush&quot;, null).on(&quot;touchend.brush&quot;, null).on(&quot;keydown.brush&quot;, null).on(&quot;keyup.brush&quot;, null);
+        dragRestore();
+        event_({
+          type: &quot;brushend&quot;
+        });
+      }
+    }
+    brush.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      resizes = d3_svg_brushResizes[!x &lt;&lt; 1 | !y];
+      return brush;
+    };
+    brush.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      resizes = d3_svg_brushResizes[!x &lt;&lt; 1 | !y];
+      return brush;
+    };
+    brush.clamp = function(z) {
+      if (!arguments.length) return x &amp;&amp; y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
+      if (x &amp;&amp; y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
+      return brush;
+    };
+    brush.extent = function(z) {
+      var x0, x1, y0, y1, t;
+      if (!arguments.length) {
+        if (x) {
+          if (xExtentDomain) {
+            x0 = xExtentDomain[0], x1 = xExtentDomain[1];
+          } else {
+            x0 = xExtent[0], x1 = xExtent[1];
+            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
+            if (x1 &lt; x0) t = x0, x0 = x1, x1 = t;
+          }
+        }
+        if (y) {
+          if (yExtentDomain) {
+            y0 = yExtentDomain[0], y1 = yExtentDomain[1];
+          } else {
+            y0 = yExtent[0], y1 = yExtent[1];
+            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
+            if (y1 &lt; y0) t = y0, y0 = y1, y1 = t;
+          }
+        }
+        return x &amp;&amp; y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y &amp;&amp; [ y0, y1 ];
+      }
+      if (x) {
+        x0 = z[0], x1 = z[1];
+        if (y) x0 = x0[0], x1 = x1[0];
+        xExtentDomain = [ x0, x1 ];
+        if (x.invert) x0 = x(x0), x1 = x(x1);
+        if (x1 &lt; x0) t = x0, x0 = x1, x1 = t;
+        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
+      }
+      if (y) {
+        y0 = z[0], y1 = z[1];
+        if (x) y0 = y0[1], y1 = y1[1];
+        yExtentDomain = [ y0, y1 ];
+        if (y.invert) y0 = y(y0), y1 = y(y1);
+        if (y1 &lt; y0) t = y0, y0 = y1, y1 = t;
+        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
+      }
+      return brush;
+    };
+    brush.clear = function() {
+      if (!brush.empty()) {
+        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
+        xExtentDomain = yExtentDomain = null;
+      }
+      return brush;
+    };
+    brush.empty = function() {
+      return !!x &amp;&amp; xExtent[0] == xExtent[1] || !!y &amp;&amp; yExtent[0] == yExtent[1];
+    };
+    return d3.rebind(brush, event, &quot;on&quot;);
+  };
+  var d3_svg_brushCursor = {
+    n: &quot;ns-resize&quot;,
+    e: &quot;ew-resize&quot;,
+    s: &quot;ns-resize&quot;,
+    w: &quot;ew-resize&quot;,
+    nw: &quot;nwse-resize&quot;,
+    ne: &quot;nesw-resize&quot;,
+    se: &quot;nwse-resize&quot;,
+    sw: &quot;nesw-resize&quot;
+  };
+  var d3_svg_brushResizes = [ [ &quot;n&quot;, &quot;e&quot;, &quot;s&quot;, &quot;w&quot;, &quot;nw&quot;, &quot;ne&quot;, &quot;se&quot;, &quot;sw&quot; ], [ &quot;e&quot;, &quot;w&quot; ], [ &quot;n&quot;, &quot;s&quot; ], [] ];
+  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
+  var d3_time_formatUtc = d3_time_format.utc;
+  var d3_time_formatIso = d3_time_formatUtc(&quot;%Y-%m-%dT%H:%M:%S.%LZ&quot;);
+  d3_time_format.iso = Date.prototype.toISOString &amp;&amp; +new Date(&quot;2000-01-01T00:00:00.000Z&quot;) ? d3_time_formatIsoNative : d3_time_formatIso;
+  function d3_time_formatIsoNative(date) {
+    return date.toISOString();
+  }
+  d3_time_formatIsoNative.parse = function(string) {
+    var date = new Date(string);
+    return isNaN(date) ? null : date;
+  };
+  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
+  d3_time.second = d3_time_interval(function(date) {
+    return new d3_date(Math.floor(date / 1e3) * 1e3);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 1e3);
+  }, function(date) {
+    return date.getSeconds();
+  });
+  d3_time.seconds = d3_time.second.range;
+  d3_time.seconds.utc = d3_time.second.utc.range;
+  d3_time.minute = d3_time_interval(function(date) {
+    return new d3_date(Math.floor(date / 6e4) * 6e4);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 6e4);
+  }, function(date) {
+    return date.getMinutes();
+  });
+  d3_time.minutes = d3_time.minute.range;
+  d3_time.minutes.utc = d3_time.minute.utc.range;
+  d3_time.hour = d3_time_interval(function(date) {
+    var timezone = date.getTimezoneOffset() / 60;
+    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 36e5);
+  }, function(date) {
+    return date.getHours();
+  });
+  d3_time.hours = d3_time.hour.range;
+  d3_time.hours.utc = d3_time.hour.utc.range;
+  d3_time.month = d3_time_interval(function(date) {
+    date = d3_time.day(date);
+    date.setDate(1);
+    return date;
+  }, function(date, offset) {
+    date.setMonth(date.getMonth() + offset);
+  }, function(date) {
+    return date.getMonth();
+  });
+  d3_time.months = d3_time.month.range;
+  d3_time.months.utc = d3_time.month.utc.range;
+  function d3_time_scale(linear, methods, format) {
+    function scale(x) {
+      return linear(x);
+    }
+    scale.invert = function(x) {
+      return d3_time_scaleDate(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
+      linear.domain(x);
+      return scale;
+    };
+    function tickMethod(extent, count) {
+      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
+      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
+        return d / 31536e6;
+      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] &lt; d3_time_scaleSteps[i] / target ? i - 1 : i];
+    }
+    scale.nice = function(interval, skip) {
+      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === &quot;number&quot; &amp;&amp; tickMethod(extent, interval);
+      if (method) interval = method[0], skip = method[1];
+      function skipped(date) {
+        return !isNaN(date) &amp;&amp; !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
+      }
+      return scale.domain(d3_scale_nice(domain, skip &gt; 1 ? {
+        floor: function(date) {
+          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
+          return date;
+        },
+        ceil: function(date) {
+          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
+          return date;
+        }
+      } : interval));
+    };
+    scale.ticks = function(interval, skip) {
+      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === &quot;number&quot; ? tickMethod(extent, interval) : !interval.range &amp;&amp; [ {
+        range: interval
+      }, skip ];
+      if (method) interval = method[0], skip = method[1];
+      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip &lt; 1 ? 1 : skip);
+    };
+    scale.tickFormat = function() {
+      return format;
+    };
+    scale.copy = function() {
+      return d3_time_scale(linear.copy(), methods, format);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  function d3_time_scaleDate(t) {
+    return new Date(t);
+  }
+  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
+  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
+  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ &quot;.%L&quot;, function(d) {
+    return d.getMilliseconds();
+  } ], [ &quot;:%S&quot;, function(d) {
+    return d.getSeconds();
+  } ], [ &quot;%I:%M&quot;, function(d) {
+    return d.getMinutes();
+  } ], [ &quot;%I %p&quot;, function(d) {
+    return d.getHours();
+  } ], [ &quot;%a %d&quot;, function(d) {
+    return d.getDay() &amp;&amp; d.getDate() != 1;
+  } ], [ &quot;%b %d&quot;, function(d) {
+    return d.getDate() != 1;
+  } ], [ &quot;%B&quot;, function(d) {
+    return d.getMonth();
+  } ], [ &quot;%Y&quot;, d3_true ] ]);
+  var d3_time_scaleMilliseconds = {
+    range: function(start, stop, step) {
+      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
+    },
+    floor: d3_identity,
+    ceil: d3_identity
+  };
+  d3_time_scaleLocalMethods.year = d3_time.year;
+  d3_time.scale = function() {
+    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
+  };
+  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
+    return [ m[0].utc, m[1] ];
+  });
+  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ &quot;.%L&quot;, function(d) {
+    return d.getUTCMilliseconds();
+  } ], [ &quot;:%S&quot;, function(d) {
+    return d.getUTCSeconds();
+  } ], [ &quot;%I:%M&quot;, function(d) {
+    return d.getUTCMinutes();
+  } ], [ &quot;%I %p&quot;, function(d) {
+    return d.getUTCHours();
+  } ], [ &quot;%a %d&quot;, function(d) {
+    return d.getUTCDay() &amp;&amp; d.getUTCDate() != 1;
+  } ], [ &quot;%b %d&quot;, function(d) {
+    return d.getUTCDate() != 1;
+  } ], [ &quot;%B&quot;, function(d) {
+    return d.getUTCMonth();
+  } ], [ &quot;%Y&quot;, d3_true ] ]);
+  d3_time_scaleUtcMethods.year = d3_time.year.utc;
+  d3_time.scale.utc = function() {
+    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
+  };
+  d3.text = d3_xhrType(function(request) {
+    return request.responseText;
+  });
+  d3.json = function(url, callback) {
+    return d3_xhr(url, &quot;application/json&quot;, d3_json, callback);
+  };
+  function d3_json(request) {
+    return JSON.parse(request.responseText);
+  }
+  d3.html = function(url, callback) {
+    return d3_xhr(url, &quot;text/html&quot;, d3_html, callback);
+  };
+  function d3_html(request) {
+    var range = d3_document.createRange();
+    range.selectNode(d3_document.body);
+    return range.createContextualFragment(request.responseText);
+  }
+  d3.xml = d3_xhrType(function(request) {
+    return request.responseXML;
+  });
+  if (typeof define === &quot;function&quot; &amp;&amp; define.amd) define(d3); else if (typeof module === &quot;object&quot; &amp;&amp; module.exports) module.exports = d3;
+  this.d3 = d3;
+}();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsd3d3minjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.min.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.min.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.min.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+!function(){function n(n,t){return t&gt;n?-1:n&gt;t?1:n&gt;=t?0:0/0}function t(n){return null!=n&amp;&amp;!isNaN(n)}function e(n){return{left:function(t,e,r,u){for(arguments.length&lt;3&amp;&amp;(r=0),arguments.length&lt;4&amp;&amp;(u=t.length);u&gt;r;){var i=r+u&gt;&gt;&gt;1;n(t[i],e)&lt;0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length&lt;3&amp;&amp;(r=0),arguments.length&lt;4&amp;&amp;(u=t.length);u&gt;r;){var i=r+u&gt;&gt;&gt;1;n(t[i],e)&gt;0?u=i:r=i+1}return r}}}function r(n){return n.length}function u(n){for(var t=1;n*t%1;)t*=10;return t}function i(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function o(){}function a(n){return ia+n in this}function c(n){return n=ia+n,n in this&amp;&amp;delete this[n]}function s(){var n=[];return this.forEach(function(t){n.push(t)}),n}function l(){var n=0;for(var t in this)t.charCodeAt(0)===oa&amp;&amp;++n;return n}function f(){for(var n in this)if(n.charCodeAt(0)===oa)return!1;return!0}function h(){}function g(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function p(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=aa.length;r&gt;e;++e){var u=aa[e]+t;if(u in n)return u}}function v(){}function d(){}function m(n){function t(){for(var t,r=e,u=-1,i=r.length;++u&lt;i;)(t=r[u].on)&amp;&amp;t.apply(this,arguments);return n}var e=[],r=new o;return t.on=function(t,u){var i,o=r.get(t);return arguments.length&lt;2?o&amp;&amp;o.on:(o&amp;&amp;(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&amp;&amp;e.push(r.set(t,{on:u})),n)},t}function y(){Zo.event.preventDefault()}function x(){for(var n,t=Zo.event;n=t.sourceEvent;)t=n;return t}function M(n){for(var t=new d,e=0,r=arguments.length;++e&lt;r;)t[arguments[e]]=m(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Zo.event;u.target=n,Zo.event=u,t[u.type].apply(e,r)}finally{Zo.event=i}}},t}function _(n){return sa(n,pa),n}function b(n){return&quot;function&quot;==typeof n?n:function(){return la(n,this)}}function w(n){return&quot;function&quot;==typeof n?n:function(){return fa(n,this)}}function S(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Zo.ns.qualify(n),null==t?n.local?r:e:&quot;function&quot;==typeof t?n.local?a:o:n.local?i:u}function k(n){return n.trim().replace(/\s+/g,&quot; &quot;)}function E(n){return new RegExp(&quot;(?:^|\\s+)&quot;+Zo.requote(n)+&quot;(?:\\s+|$)&quot;,&quot;g&quot;)}function A(n){return(n+&quot;&quot;).trim().split(/^|\s+/)}function C(n,t){function e(){for(var e=-1;++e&lt;u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e&lt;u;)n[e](this,r)}n=A(n).map(N);var u=n.length;return&quot;function&quot;==typeof t?r:e}function N(n){var t=E(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute(&quot;class&quot;)||&quot;&quot;;r?(t.lastIndex=0,t.test(u)||e.setAttribute(&quot;class&quot;,k(u+&quot; &quot;+n))):e.setAttribute(&quot;class&quot;,k(u.replace(t,&quot; &quot;)))}}function z(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:&quot;function&quot;==typeof t?i:u}function L(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:&quot;function&quot;==typeof t?u:r}function T(n){return&quot;function&quot;==typeof n?n:(n=Zo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function q(n){return{__data__:n}}function R(n){return function(){return ga(this,n)}}function D(t){return arguments.length||(t=n),function(n,e){return n&amp;&amp;e?t(n.__data__,e.__data__):!n-!e}}function P(n,t){for(var e=0,r=n.length;r&gt;e;e++)for(var u,i=n[e],o=0,a=i.length;a&gt;o;o++)(u=i[o])&amp;&amp;t(u,o,e);return n}function U(n){return sa(n,da),n}function j(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&amp;&amp;(e=i,t=0),u&gt;=t&amp;&amp;(t=u+1);!(o=a[t])&amp;&amp;++t&lt;c;);return o}}function H(){var n=this.__transition__;n&amp;&amp;++n.active}function F(n,t,e){function r(){var t=this[o];t&amp;&amp;(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Xo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp(&quot;^__on([^.]+)&quot;+Zo.requote(n)+&quot;$&quot;);for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o=&quot;__on&quot;+n,a=n.indexOf(&quot;.&quot;),c=O;a&gt;0&amp;&amp;(n=n.substring(0,a));var s=ya.get(n);return s&amp;&amp;(n=s,c=Y),a?t?u:r:t?v:i}function O(n,t){return function(e){var r=Zo.event;Zo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Zo.event=r}}}function Y(n,t){var e=O(n,t);return function(n){var t=this,r=n.relatedTarget;r&amp;&amp;(r===t||8&amp;r.compareDocumentPosition(t))||e.call(t,n)}}function I(){var n=&quot;.dragsuppress-&quot;+ ++Ma,t=&quot;click&quot;+n,e=Zo.select(Wo).on(&quot;touchmove&quot;+n,y).on(&quot;dragstart&quot;+n,y).on(&quot;selectstart&quot;+n,y);if(xa){var r=Bo.style,u=r[xa];r[xa]=&quot;none&quot;}return function(i){function o(){e.on(t,null)}e.on(n,null),xa&amp;&amp;(r[xa]=u),i&amp;&amp;(e.on(t,function(){y(),o()},!0),setTimeout(o,0))}}function Z(n,t){t.changedTouches&amp;&amp;(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0&gt;_a&amp;&amp;(Wo.scrollX||Wo.scrollY)){e=Zo.select(&quot;body&quot;).append(&quot;svg&quot;).style({position:&quot;absolute&quot;,top:0,left:0,margin:0,padding:0,border:&quot;none&quot;},&quot;important&quot;);var u=e[0][0].getScreenCTM();_a=!(u.f||u.e),e.remove()}return _a?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function V(){return Zo.event.changedTouches[0].identifier}function X(){return Zo.event.target}function $(){return Wo}function B(n){return n&gt;0?1:0&gt;n?-1:0}function W(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function J(n){return n&gt;1?0:-1&gt;n?ba:Math.acos(n)}function G(n){return n&gt;1?Sa:-1&gt;n?-Sa:Math.asin(n)}function K(n){return((n=Math.exp(n))-1/n)/2}function Q(n){return((n=Math.exp(n))+1/n)/2}function nt(n){return((n=Math.exp(2*n))-1)/(n+1)}function tt(n){return(n=Math.sin(n/2))*n}function et(){}function rt(n,t,e){return this instanceof rt?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length&lt;2?n instanceof rt?new rt(n.h,n.s,n.l):mt(&quot;&quot;+n,yt,rt):new rt(n,t,e)}function ut(n,t,e){function r(n){return n&gt;360?n-=360:0&gt;n&amp;&amp;(n+=360),60&gt;n?i+(o-i)*n/60:180&gt;n?o:240&gt;n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)&lt;0?n+360:n,t=isNaN(t)?0:0&gt;t?0:t&gt;1?1:t,e=0&gt;e?0:e&gt;1?1:e,o=.5&gt;=e?e*(1+t):e+t-e*t,i=2*e-o,new gt(u(n+120),u(n),u(n-120))}function it(n,t,e){return this instanceof it?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length&lt;2?n instanceof it?new it(n.h,n.c,n.l):n instanceof at?st(n.l,n.a,n.b):st((n=xt((n=Zo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new it(n,t,e)}function ot(n,t,e){return isNaN(n)&amp;&amp;(n=0),isNaN(t)&amp;&amp;(t=0),new at(e,Math.cos(n*=Aa)*t,Math.sin(n)*t)}function at(n,t,e){return this instanceof at?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length&lt;2?n instanceof at?new at(n.l,n.a,n.b):n instanceof it?ot(n.l,n.c,n.h):xt((n=gt(n)).r,n.g,n.b):new at(n,t,e)}function ct(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=lt(u)*ja,r=lt(r)*Ha,i=lt(i)*Fa,new gt(ht(3.2404542*u-1.5371385*r-.4985314*i),ht(-.969266*u+1.8760108*r+.041556*i),ht(.0556434*u-.2040259*r+1.0572252*i))}function st(n,t,e){return n&gt;0?new it(Math.atan2(e,t)*Ca,Math.sqrt(t*t+e*e),n):new it(0/0,0/0,n)}function lt(n){return n&gt;.206893034?n*n*n:(n-4/29)/7.787037}function ft(n){return n&gt;.008856?Math.pow(n,1/3):7.787037*n+4/29}function ht(n){return Math.round(255*(.00304&gt;=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function gt(n,t,e){return this instanceof gt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length&lt;2?n instanceof gt?new gt(n.r,n.g,n.b):mt(&quot;&quot;+n,gt,ut):new gt(n,t,e)}function pt(n){return new gt(n&gt;&gt;16,255&amp;n&gt;&gt;8,255&amp;n)}function vt(n){return pt(n)+&quot;&quot;}function dt(n){return 16&gt;n?&quot;0&quot;+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function mt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(&quot;,&quot;),r[1]){case&quot;hsl&quot;:return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case&quot;rgb&quot;:return t(_t(u[0]),_t(u[1]),_t(u[2]))}return(i=Ia.get(n))?t(i.r,i.g,i.b):(null==n||&quot;#&quot;!==n.charAt(0)||isNaN(i=parseInt(n.substring(1),16))||(4===n.length?(o=(3840&amp;i)&gt;&gt;4,o=o&gt;&gt;4|o,a=240&amp;i,a=a&gt;&gt;4|a,c=15&amp;i,c=c&lt;&lt;4|c):7===n.length&amp;&amp;(o=(16711680&amp;i)&gt;&gt;16,a=(65280&amp;i)&gt;&gt;8,c=255&amp;i)),t(o,a,c))}function yt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5&gt;c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e&gt;t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c&gt;0&amp;&amp;1&gt;c?0:r),new rt(r,u,c)}function xt(n,t,e){n=Mt(n),t=Mt(t),e=Mt(e);var r=ft((.4124564*n+.3575761*t+.1804375*e)/ja),u=ft((.2126729*n+.7151522*t+.072175*e)/Ha),i=ft((.0193339*n+.119192*t+.9503041*e)/Fa);return at(116*u-16,500*(r-u),200*(u-i))}function Mt(n){return(n/=255)&lt;=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function _t(n){var t=parseFloat(n);return&quot;%&quot;===n.charAt(n.length-1)?Math.round(2.55*t):t}function bt(n){return&quot;function&quot;==typeof n?n:function(){return n}}function wt(n){return n}function St(n){return function(t,e,r){return 2===arguments.length&amp;&amp;&quot;function&quot;==typeof e&amp;&amp;(r=e,e=null),kt(t,e,n,r)}}function kt(n,t,e,r){function u(){var n,t=c.status;if(!t&amp;&amp;c.responseText||t&gt;=200&amp;&amp;300&gt;t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Zo.dispatch(&quot;beforesend&quot;,&quot;progress&quot;,&quot;load&quot;,&quot;error&quot;),a={},c=new XMLHttpRequest,s=null;return!Wo.XDomainRequest||&quot;withCredentials&quot;in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),&quot;onload&quot;in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState&gt;3&amp;&amp;u()},c.onprogress=function(n){var t=Zo.event;Zo.event=n;try{o.progress.call(i,c)}finally{Zo.event=t}},i.header=function(n,t){return n=(n+&quot;&quot;).toLowerCase(),arguments.length&lt;2?a[n]:(null==t?delete a[n]:a[n]=t+&quot;&quot;,i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+&quot;&quot;,i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},[&quot;get&quot;,&quot;post&quot;].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Xo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&amp;&amp;&quot;function&quot;==typeof r&amp;&amp;(u=r,r=null),c.open(e,n,!0),null==t||&quot;accept&quot;in a||(a.accept=t+&quot;,*/*&quot;),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&amp;&amp;c.overrideMimeType&amp;&amp;c.overrideMimeType(t),null!=s&amp;&amp;(c.responseType=s),null!=u&amp;&amp;i.on(&quot;error&quot;,u).on(&quot;load&quot;,function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Zo.rebind(i,o,&quot;on&quot;),null==r?i:i.get(Et(r))}function Et(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function At(){var n=Ct(),t=Nt()-n;t&gt;24?(isFinite(t)&amp;&amp;(clearTimeout($a),$a=setTimeout(At,t)),Xa=0):(Xa=1,Wa(At))}function Ct(){var n=Date.now();for(Ba=Za;Ba;)n&gt;=Ba.t&amp;&amp;(Ba.f=Ba.c(n-Ba.t)),Ba=Ba.n;return n}function Nt(){for(var n,t=Za,e=1/0;t;)t.f?t=n?n.n=t.n:Za=t.n:(t.t&lt;e&amp;&amp;(e=t.t),t=(n=t).n);return Va=n,e}function zt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*ua(8-t));return{scale:t&gt;8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t&gt;0&amp;&amp;o&gt;0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:wt;return function(n){var e=Ga.exec(n),r=e[1]||&quot; &quot;,o=e[2]||&quot;&gt;&quot;,a=e[3]||&quot;&quot;,c=e[4]||&quot;&quot;,s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v=&quot;&quot;,d=&quot;&quot;,m=!1;switch(h&amp;&amp;(h=+h.substring(1)),(s||&quot;0&quot;===r&amp;&amp;&quot;=&quot;===o)&amp;&amp;(s=r=&quot;0&quot;,o=&quot;=&quot;,f&amp;&amp;(l-=Math.floor((l-1)/4))),g){case&quot;n&quot;:f=!0,g=&quot;g&quot;;break;case&quot;%&quot;:p=100,d=&quot;%&quot;,g=&quot;f&quot;;break;case&quot;p&quot;:p=100,d=&quot;%&quot;,g=&quot;r&quot;;break;case&quot;b&quot;:case&quot;o&quot;:case&quot;x&quot;:case&quot;X&quot;:&quot;#&quot;===c&amp;&amp;(v=&quot;0&quot;+g.toLowerCase());case&quot;c&quot;:case&quot;d&quot;:m=!0,h=0;break;case&quot;s&quot;:p=-1,g=&quot;r&quot;}&quot;$&quot;===c&amp;&amp;(v=u[0],d=u[1]),&quot;r&quot;!=g||h||(g=&quot;g&quot;),null!=h&amp;&amp;(&quot;g&quot;==g?h=Math.max(1,Math.min(21,h)):(&quot;e&quot;==g||&quot;f&quot;==g)&amp;&amp;(h=Math.max(0,Math.min(20,h)))),g=Ka.get(g)||qt;var y=s&amp;&amp;f;return function(n){var e=d;if(m&amp;&amp;n%1)return&quot;&quot;;var u=0&gt;n||0===n&amp;&amp;0&gt;1/n?(n=-n,&quot;-&quot;):a;if(0&gt;p){var c=Zo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf(&quot;.&quot;),M=0&gt;x?n:n.substring(0,x),_=0&gt;x?&quot;&quot;:t+n.substring(x+1);!s&amp;&amp;f&amp;&amp;(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l&gt;b?new Array(b=l-b+1).join(r):&quot;&quot;;return y&amp;&amp;(M=i(w+M)),u+=v,n=M+_,(&quot;&lt;&quot;===o?u+n+w:&quot;&gt;&quot;===o?w+u+n:&quot;^&quot;===o?w.substring(0,b&gt;&gt;=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+&quot;&quot;}function Rt(){this._=new Date(arguments.length&gt;1?Date.UTC.apply(this,arguments):arguments[0])}function Dt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t&gt;t-e?e:r}function u(e){return t(e=n(new nc(e-1)),1),e}function i(n,e){return t(n=new nc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i&gt;1)for(;r&gt;o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r&gt;o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{nc=Rt;var r=new Rt;return r._=n,o(r,t,e)}finally{nc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Pt(n);return c.floor=c,c.round=Pt(r),c.ceil=Pt(u),c.offset=Pt(i),c.range=a,n}function Pt(n){return function(t,e){try{nc=Rt;var r=new Rt;return r._=t,n(r,e)._}finally{nc=Date}}}function Ut(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a&lt;r;)37===n.charCodeAt(a)&amp;&amp;(o.push(n.substring(c,a)),null!=(u=ec[e=n.charAt(++a)])&amp;&amp;(e=n.charAt(++a)),(i=C[e])&amp;&amp;(e=i(t,null==u?&quot;e&quot;===e?&quot; &quot;:&quot;0&quot;:u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join(&quot;&quot;)}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;&quot;p&quot;in r&amp;&amp;(r.H=r.H%12+12*r.p);var i=null!=r.Z&amp;&amp;nc!==Rt,o=new(i?Rt:nc);return&quot;j&quot;in r?o.setFullYear(r.y,0,r.j):&quot;w&quot;in r&amp;&amp;(&quot;W&quot;in r||&quot;U&quot;in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,&quot;W&quot;in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c&gt;a;){if(r&gt;=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in ec?t.charAt(a++):o],!i||(r=i(n,e,r))&lt;0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{nc=Rt;var t=new nc;return t._=n,r(t)}finally{nc=Date}}var r=t(n);return e.parse=function(n){try{nc=Rt;var t=r.parse(n);return t&amp;&amp;t._}finally{nc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=re;var x=Zo.map(),M=Ht(v),_=Ft(v),b=Ht(d),w=Ft(d),S=Ht(m),k=Ft(m),E=Ht(y),A=Ft(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return jt(n.getDate(),t,2)},e:function(n,t){return jt(n.getDate(),t,2)},H:function(n,t){return jt(n.getHours(),t,2)},I:function(n,t){return jt(n.getHours()%12||12,t,2)},j:function(n,t){return jt(1+Qa.dayOfYear(n),t,3)},L:function(n,t){return jt(n.getMilliseconds(),t,3)},m:function(n,t){return jt(n.getMonth()+1,t,2)},M:function(n,t){return jt(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()&gt;=12)]},S:function(n,t){return jt(n.getSeconds(),t,2)},U:function(n,t){return jt(Qa.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return jt(Qa.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return jt(n.getFullYear()%100,t,2)},Y:function(n,t){return jt(n.getFullYear()%1e4,t,4)},Z:te,&quot;%&quot;:function(){return&quot;%&quot;}},N={a:r,A:u,b:i,B:o,c:a,d:Wt,e:Wt,H:Gt,I:Gt,j:Jt,L:ne,m:Bt,M:Kt,p:l,S:Qt,U:Yt,w:Ot,W:It,x:c,X:s,y:Vt,Y:Zt,Z:Xt,&quot;%&quot;:ee};return t}function jt(n,t,e){var r=0&gt;n?&quot;-&quot;:&quot;&quot;,u=(r?-n:n)+&quot;&quot;,i=u.length;return r+(e&gt;i?new Array(e-i+1).join(t)+u:u)}function Ht(n){return new RegExp(&quot;^(?:&quot;+n.map(Zo.requote).join(&quot;|&quot;)+&quot;)&quot;,&quot;i&quot;)}function Ft(n){for(var t=new o,e=-1,r=n.length;++e&lt;r;)t.set(n[e].toLowerCase(),e);return t}function Ot(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Yt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function It(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function Zt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Vt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.y=$t(+r[0]),e+r[0].length):-1}function Xt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=-t,e+5):-1}function $t(n){return n+(n&gt;68?1900:2e3)}function Bt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Wt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Jt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Gt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Kt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Qt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ne(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function te(n){var t=n.getTimezoneOffset(),e=t&gt;0?&quot;-&quot;:&quot;+&quot;,r=~~(ua(t)/60),u=ua(t)%60;return e+jt(r,&quot;0&quot;,2)+jt(u,&quot;0&quot;,2)}function ee(n,t,e){uc.lastIndex=0;var r=uc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function re(n){for(var t=n.length,e=-1;++e&lt;t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ue(){}function ie(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function oe(n,t){n&amp;&amp;cc.hasOwnProperty(n.type)&amp;&amp;cc[n.type](n,t)}function ae(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u&lt;i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ce(n,t){var e=-1,r=n.length;for(t.polygonStart();++e&lt;r;)ae(n[e],t,1);t.polygonEnd()}function se(){function n(n,t){n*=Aa,t=t*Aa/2+ba/4;var e=n-r,o=e&gt;=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);lc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;fc.point=function(o,a){fc.point=n,r=(t=o)*Aa,u=Math.cos(a=(e=a)*Aa/2+ba/4),i=Math.sin(a)},fc.lineEnd=function(){n(t,e)}}function le(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function fe(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function he(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function ge(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function pe(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function ve(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function de(n){return[Math.atan2(n[1],n[0]),G(n[2])]}function me(n,t){return ua(n[0]-t[0])&lt;ka&amp;&amp;ua(n[1]-t[1])&lt;ka}function ye(n,t){n*=Aa;var e=Math.cos(t*=Aa);xe(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function xe(n,t,e){++hc,pc+=(n-pc)/hc,vc+=(t-vc)/hc,dc+=(e-dc)/hc}function Me(){function n(n,u){n*=Aa;var i=Math.cos(u*=Aa),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);gc+=s,mc+=s*(t+(t=o)),yc+=s*(e+(e=a)),xc+=s*(r+(r=c)),xe(t,e,r)}var t,e,r;wc.point=function(u,i){u*=Aa;var o=Math.cos(i*=Aa);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),wc.point=n,xe(t,e,r)}}function _e(){wc.point=ye}function be(){function n(n,t){n*=Aa;var e=Math.cos(t*=Aa),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&amp;&amp;-J(g)/h,v=Math.atan2(h,g);Mc+=p*s,_c+=p*l,bc+=p*f,gc+=v,mc+=v*(r+(r=o)),yc+=v*(u+(u=a)),xc+=v*(i+(i=c)),xe(r,u,i)}var t,e,r,u,i;wc.point=function(o,a){t=o,e=a,wc.point=n,o*=Aa;var c=Math.cos(a*=Aa);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),xe(r,u,i)},wc.lineEnd=function(){n(t,e),wc.lineEnd=_e,wc.point=ye}}function we(){return!0}function Se(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)&lt;=0)){var t,e=n[0],r=n[t];if(me(e,r)){u.lineStart();for(var a=0;t&gt;a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new Ee(e,n,null,!0),s=new Ee(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new Ee(r,n,null,!1),s=new Ee(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),ke(i),ke(o),i.length){for(var a=0,c=e,s=o.length;s&gt;a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s&gt;a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a&gt;=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ke(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r&lt;t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function Ee(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ae(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&amp;&amp;i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r)if(1&amp;t){n=e[0];var u,r=n.length-1,o=-1;if(r&gt;0){for(_||(i.polygonStart(),_=!0),i.lineStart();++o&lt;r;)i.point((u=n[o])[0],u[1]);i.lineEnd()}}else r&gt;1&amp;&amp;2&amp;t&amp;&amp;e.push(e.pop().concat(e.shift())),g.push(e.filter(Ce))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Zo.merge(g);var n=Le(m,p);g.length?(_||(i.polygonStart(),_=!0),Se(g,ze,n,e,i)):n&amp;&amp;(_||(i.polygonStart(),_=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),_&amp;&amp;(i.polygonEnd(),_=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ne(),M=t(x),_=!1;return y}}function Ce(n){return n.length&gt;1}function Ne(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:v,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length&gt;1&amp;&amp;t.push(t.pop().concat(t.shift()))}}}function ze(n,t){return((n=n.x)[0]&lt;0?n[1]-Sa-ka:Sa-n[1])-((t=t.x)[0]&lt;0?t[1]-Sa-ka:Sa-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;lc.reset();for(var a=0,c=t.length;c&gt;a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+ba/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&amp;&amp;(d=0),n=s[d];var m=n[0],y=n[1]/2+ba/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_&gt;=0?1:-1,w=b*_,S=w&gt;ba,k=p*x;if(lc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*wa:_,S^h&gt;=e^m&gt;=e){var E=he(le(f),le(n));ve(E);var A=he(u,E);ve(A);var C=(S^_&gt;=0?-1:1)*G(A[2]);(r&gt;C||r===C&amp;&amp;(E[0]||E[1]))&amp;&amp;(o+=S^_&gt;=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-ka&gt;i||ka&gt;i&amp;&amp;0&gt;lc)^1&amp;o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i&gt;0?ba:-ba,c=ua(i-e);ua(c-ba)&lt;ka?(n.point(e,r=(r+o)/2&gt;0?Sa:-Sa),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&amp;&amp;c&gt;=ba&amp;&amp;(ua(e-u)&lt;ka&amp;&amp;(e-=u*ka),ua(i-a)&lt;ka&amp;&amp;(i-=a*ka),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return ua(o)&gt;ka?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Re(n,t,e,r){var u;if(null==n)u=e*Sa,r.point(-ba,u),r.point(0,u),r.point(ba,u),r.point(ba,0),r.point(ba,-u),r.point(0,-u),r.point(-ba,-u),r.point(-ba,0),r.point(-ba,u);else if(ua(n[0]-t[0])&gt;ka){var i=n[0]&lt;t[0]?ba:-ba;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function De(n){function t(n,t){return Math.cos(n)*Math.cos(t)&gt;i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0&gt;f?ba:-ba),h):0;if(!e&amp;&amp;(s=c=v)&amp;&amp;n.lineStart(),v!==c&amp;&amp;(g=r(e,p),(me(e,g)||me(p,g))&amp;&amp;(p[0]+=ka,p[1]+=ka,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&amp;&amp;e&amp;&amp;o^v){var m;d&amp;i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&amp;&amp;me(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&amp;&amp;n.lineEnd(),e=null},clean:function(){return l|(s&amp;&amp;c)&lt;&lt;1}}}function r(n,t,e){var r=le(n),u=le(t),o=[1,0,0],a=he(r,u),c=fe(a,a),s=a[0],l=c-s*s;if(!l)return!e&amp;&amp;n;var f=i*c/l,h=-i*s/l,g=he(o,a),p=pe(o,f),v=pe(a,h);ge(p,v);var d=g,m=fe(p,d),y=fe(d,d),x=m*m-y*(fe(p,p)-1);if(!(0&gt;x)){var M=Math.sqrt(x),_=pe(d,(-m-M)/y);if(ge(_,p),_=de(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w&gt;S&amp;&amp;(b=w,w=S,S=b);var A=S-w,C=ua(A-ba)&lt;ka,N=C||ka&gt;A;if(!C&amp;&amp;k&gt;E&amp;&amp;(b=k,k=E,E=b),N?C?k+E&gt;0^_[1]&lt;(ua(_[0]-w)&lt;ka?k:E):k&lt;=_[1]&amp;&amp;_[1]&lt;=E:A&gt;ba^(w&lt;=_[0]&amp;&amp;_[0]&lt;=S)){var z=pe(d,(-m+M)/y);return ge(z,p),[_,de(z)]}}}function u(t,e){var r=o?n:ba-n,u=0;return-r&gt;t?u|=1:t&gt;r&amp;&amp;(u|=2),-r&gt;e?u|=4:e&gt;r&amp;&amp;(u|=8),u}var i=Math.cos(n),o=i&gt;0,a=ua(i)&gt;ka,c=sr(n,6*Aa);return Ae(t,e,c,o?[0,-n]:[-ba,n-ba])}function Pe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i&gt;0)){if(i/=p,0&gt;p){if(h&gt;i)return;g&gt;i&amp;&amp;(g=i)}else if(p&gt;0){if(i&gt;g)return;i&gt;h&amp;&amp;(h=i)}if(i=e-c,p||!(0&gt;i)){if(i/=p,0&gt;p){if(i&gt;g)return;i&gt;h&amp;&amp;(h=i)}else if(p&gt;0){if(h&gt;i)return;g&gt;i&amp;&amp;(g=i)}if(i=t-s,v||!(i&gt;0)){if(i/=v,0&gt;v){if(h&gt;i)return;g&gt;i&amp;&amp;(g=i)}else if(v&gt;0){if(i&gt;g)return;i&gt;h&amp;&amp;(h=i)}if(i=r-s,v||!(0&gt;i)){if(i/=v,0&gt;v){if(i&gt;g)return;i&gt;h&amp;&amp;(h=i)}else if(v&gt;0){if(h&gt;i)return;g&gt;i&amp;&amp;(g=i)}return h&gt;0&amp;&amp;(u.a={x:c+h*p,y:s+h*v}),1&gt;g&amp;&amp;(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Ue(n,t,e,r){function u(r,u){return ua(r[0]-n)&lt;ka?u&gt;0?0:3:ua(r[0]-e)&lt;ka?u&gt;0?2:1:ua(r[1]-t)&lt;ka?u&gt;0?1:0:u&gt;0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e&gt;u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c&gt;o;++o)i=a[o],s[1]&lt;=r?i[1]&gt;r&amp;&amp;W(s,i,n)&gt;0&amp;&amp;++t:i[1]&lt;=r&amp;&amp;W(s,i,n)&lt;0&amp;&amp;--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)&lt;0^c&gt;0){do s.point(0===l||3===l?n:e,l&gt;1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u&gt;=n&amp;&amp;e&gt;=u&amp;&amp;i&gt;=t&amp;&amp;r&gt;=i}function f(n,t){l(n,t)&amp;&amp;a.point(n,t)}function h(){N.point=p,d&amp;&amp;d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&amp;&amp;(p(y,x),M&amp;&amp;w&amp;&amp;A.rejoin(),v.push(A.buffer())),N.point=f,w&amp;&amp;a.lineEnd()}function p(n,t){n=Math.max(-kc,Math.min(kc,n)),t=Math.max(-kc,Math.min(kc,t));var e=l(n,t);if(d&amp;&amp;m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&amp;&amp;(a.lineStart(),a.point(n,t));else if(e&amp;&amp;w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&amp;&amp;(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ne(),C=Pe(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Zo.merge(v);var t=c([n,r]),e=k&amp;&amp;t,u=v.length;(e||u)&amp;&amp;(a.polygonStart(),e&amp;&amp;(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&amp;&amp;Se(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function je(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&amp;&amp;t.invert&amp;&amp;(e.invert=function(e,r){return e=t.invert(e,r),e&amp;&amp;n.invert(e[0],e[1])}),e}function He(n){var t=0,e=ba/3,r=tr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ba/180,e=n[1]*ba/180):[180*(t/ba),180*(e/ba)]},u}function Fe(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,G((i-(n*n+e*e)*u*u)/(2*u))]},e}function Oe(){function n(n,t){Ac+=u*n-r*t,r=n,u=t}var t,e,r,u;Tc.point=function(i,o){Tc.point=n,t=r=i,e=u=o},Tc.lineEnd=function(){n(t,e)}}function Ye(n,t){Cc&gt;n&amp;&amp;(Cc=n),n&gt;zc&amp;&amp;(zc=n),Nc&gt;t&amp;&amp;(Nc=t),t&gt;Lc&amp;&amp;(Lc=t)}function Ie(){function n(n,t){o.push(&quot;M&quot;,n,&quot;,&quot;,t,i)}function t(n,t){o.push(&quot;M&quot;,n,&quot;,&quot;,t),a.point=e}function e(n,t){o.push(&quot;L&quot;,n,&quot;,&quot;,t)}function r(){a.point=n}function u(){o.push(&quot;Z&quot;)}var i=Ze(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ze(n),a},result:function(){if(o.length){var n=o.join(&quot;&quot;);return o=[],n}}};return a}function Ze(n){return&quot;m0,&quot;+n+&quot;a&quot;+n+&quot;,&quot;+n+&quot; 0 1,1 0,&quot;+-2*n+&quot;a&quot;+n+&quot;,&quot;+n+&quot; 0 1,1 0,&quot;+2*n+&quot;z&quot;}function Ve(n,t){pc+=n,vc+=t,++dc}function Xe(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);mc+=o*(t+n)/2,yc+=o*(e+r)/2,xc+=o,Ve(t=n,e=r)}var t,e;Rc.point=function(r,u){Rc.point=n,Ve(t=r,e=u)}}function $e(){Rc.point=Ve}function Be(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);mc+=o*(r+n)/2,yc+=o*(u+t)/2,xc+=o,o=u*n-r*t,Mc+=o*(r+n),_c+=o*(u+t),bc+=3*o,Ve(r=n,u=t)}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,Ve(t=r=i,e=u=o)},Rc.lineEnd=function(){n(t,e)}}function We(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,wa)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:v};return a}function Je(n){function t(n){return(a?r:e)(n)}function e(t){return Qe(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=le([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M&gt;4*i&amp;&amp;d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=ua(ua(w)-1)&lt;ka||ua(r-h)&lt;ka?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],z=C-t,L=N-e,T=x*z-y*L;(T*T/M&gt;i||ua((y*z+x*L)/M-.5)&gt;.3||o&gt;a*g+c*p+s*v)&amp;&amp;(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Aa),a=16;
+return t.precision=function(n){return arguments.length?(a=(i=n*n)&gt;0&amp;&amp;16,t):Math.sqrt(i)},t}function Ge(n){var t=Je(function(t,e){return n([t*Ca,e*Ca])});return function(n){return er(t(n))}}function Ke(n){this.stream=n}function Qe(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function nr(n){return tr(function(){return n})()}function tr(n){function t(n){return n=a(n[0]*Aa,n[1]*Aa),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&amp;&amp;[n[0]*Ca,n[1]*Ca]}function r(){a=je(o=ir(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&amp;&amp;(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=Je(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Sc,_=wt,b=null,w=null;return t.stream=function(n){return l&amp;&amp;(l.valid=!1),l=er(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Sc):De((b=+n)*Aa),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Ue(n[0][0],n[0][1],n[1][0],n[1][1]):wt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Aa,d=n[1]%360*Aa,r()):[v*Ca,d*Ca]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Aa,y=n[1]%360*Aa,x=n.length&gt;2?n[2]%360*Aa:0,r()):[m*Ca,y*Ca,x*Ca]},Zo.rebind(t,f,&quot;precision&quot;),function(){return i=n.apply(this,arguments),t.invert=i.invert&amp;&amp;e,r()}}function er(n){return Qe(n,function(t,e){n.point(t*Aa,e*Aa)})}function rr(n,t){return[n,t]}function ur(n,t){return[n&gt;ba?n-wa:-ba&gt;n?n+wa:n,t]}function ir(n,t,e){return n?t||e?je(ar(n),cr(t,e)):ar(n):t||e?cr(t,e):ur}function or(n){return function(t,e){return t+=n,[t&gt;ba?t-wa:-ba&gt;t?t+wa:t,e]}}function ar(n){var t=or(n);return t.invert=or(-n),t}function cr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),G(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),G(l*r-a*u)]},e}function sr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=lr(e,u),i=lr(e,i),(o&gt;0?i&gt;u:u&gt;i)&amp;&amp;(u+=o*wa)):(u=n+o*wa,i=n-.5*c);for(var s,l=u;o&gt;0?l&gt;i:i&gt;l;l-=c)a.point((s=de([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function lr(n,t){var e=le(t);e[0]-=n,ve(e);var r=J(-e[1]);return((-e[2]&lt;0?-r:r)+2*Math.PI-ka)%(2*Math.PI)}function fr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function hr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function gr(n){return n.source}function pr(n){return n.target}function vr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(tt(r-t)+u*o*tt(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Ca,Math.atan2(o,Math.sqrt(r*r+u*u))*Ca]}:function(){return[n*Ca,t*Ca]};return p.distance=h,p}function dr(){function n(n,u){var i=Math.sin(u*=Aa),o=Math.cos(u),a=ua((n*=Aa)-t),c=Math.cos(a);Dc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Pc.point=function(u,i){t=u*Aa,e=Math.sin(i*=Aa),r=Math.cos(i),Pc.point=n},Pc.lineEnd=function(){Pc.point=Pc.lineEnd=v}}function mr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&amp;&amp;e*i/r)]},e}function yr(n,t){function e(n,t){o&gt;0?-Sa+ka&gt;t&amp;&amp;(t=-Sa+ka):t&gt;Sa-ka&amp;&amp;(t=Sa-ka);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ba/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=B(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Sa]},e):Mr}function xr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ua(u)&lt;ka?rr:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-B(u)*Math.sqrt(n*n+e*e)]},e)}function Mr(n,t){return[n,Math.log(Math.tan(ba/4+t/2))]}function _r(n){var t,e=nr(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=ba*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&amp;&amp;(o=null);return o},e.clipExtent(null)}function br(n,t){return[Math.log(Math.tan(ba/4+t/2)),-n]}function wr(n){return n[0]}function Sr(n){return n[1]}function kr(n){for(var t=n.length,e=[0,1],r=2,u=2;t&gt;u;u++){for(;r&gt;1&amp;&amp;W(n[e[r-2]],n[e[r-1]],n[u])&lt;=0;)--r;e[r++]=u}return e.slice(0,r)}function Er(n,t){return n[0]-t[0]||n[1]-t[1]}function Ar(n,t,e){return(e[0]-t[0])*(n[1]-t[1])&lt;(e[1]-t[1])*(n[0]-t[0])}function Cr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Nr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function zr(){Gr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Bc.pop()||new zr;return t.site=n,t}function Tr(n){Yr(n),Vc.remove(n),Bc.push(n),Gr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&amp;&amp;ua(e-c.circle.x)&lt;ka&amp;&amp;ua(r-c.circle.cy)&lt;ka;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Yr(c);for(var s=o;s.circle&amp;&amp;ua(e-s.circle.x)&lt;ka&amp;&amp;ua(r-s.circle.cy)&lt;ka;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Yr(s);var l,f=a.length;for(l=1;f&gt;l;++l)s=a[l],c=a[l-1],Br(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Xr(c.site,s.site,null,u),Or(c),Or(s)}function Rr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Vc._;a;)if(r=Dr(a,o)-i,r&gt;ka)a=a.L;else{if(u=i-Pr(a,o),!(u&gt;ka)){r&gt;-ka?(t=a.P,e=a):u&gt;-ka?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if(Vc.insert(t,c),t||e){if(t===e)return Yr(t),e=Lr(t.site),Vc.insert(c,e),c.edge=e.edge=Xr(t.site,c.site),Or(t),Or(e),void 0;if(!e)return c.edge=Xr(t.site,c.site),void 0;Yr(t),Yr(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};Br(e.edge,s,p,M),c.edge=Xr(s,n,null,M),e.edge=Xr(n,p,null,M),Or(t),Or(e)}}function Dr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Pr(n,t){var e=n.N;if(e)return Dr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ur(n){this.site=n,this.edges=[]}function jr(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Zc,d=v.length;d--;)if(i=v[d],i&amp;&amp;i.prepare())for(a=i.edges,c=a.length,o=0;c&gt;o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(ua(r-t)&gt;ka||ua(u-e)&gt;ka)&amp;&amp;(a.splice(o,0,new Wr($r(i.site,l,ua(r-f)&lt;ka&amp;&amp;p-u&gt;ka?{x:f,y:ua(t-f)&lt;ka?e:p}:ua(u-p)&lt;ka&amp;&amp;h-r&gt;ka?{x:ua(e-p)&lt;ka?t:h,y:p}:ua(r-h)&lt;ka&amp;&amp;u-g&gt;ka?{x:h,y:ua(t-h)&lt;ka?e:g}:ua(u-g)&lt;ka&amp;&amp;r-f&gt;ka?{x:ua(e-g)&lt;ka?t:f,y:g}:null),i.site,null)),++c)}function Hr(n,t){return t.angle-n.angle}function Fr(){Gr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Or(n){var t=n.P,e=n.N;if(t&amp;&amp;e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h&gt;=-Ea)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Wc.pop()||new Fr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=$c._;x;)if(m.y&lt;x.y||m.y===x.y&amp;&amp;m.x&lt;=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}$c.insert(y,m),y||(Xc=m)}}}}function Yr(n){var t=n.circle;t&amp;&amp;(t.P||(Xc=t.N),$c.remove(t),Wc.push(t),Gr(t),n.circle=null)}function Ir(n){for(var t,e=Ic,r=Pe(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Zr(t,n)||!r(t)||ua(t.a.x-t.b.x)&lt;ka&amp;&amp;ua(t.a.y-t.b.y)&lt;ka)&amp;&amp;(t.a=t.b=null,e.splice(u,1))}function Zr(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o&gt;d||d&gt;=a)return;if(h&gt;p){if(i){if(i.y&gt;=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y&lt;c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1&gt;r||r&gt;1)if(h&gt;p){if(i){if(i.y&gt;=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y&lt;c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v&gt;g){if(i){if(i.x&gt;=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x&lt;o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Vr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Xr(n,t,e,r){var u=new Vr(n,t);return Ic.push(u),e&amp;&amp;Br(u,n,t,e),r&amp;&amp;Br(u,t,n,r),Zc[n.i].edges.push(new Wr(u,n,t)),Zc[t.i].edges.push(new Wr(u,t,n)),u}function $r(n,t,e){var r=new Vr(n,null);return r.a=t,r.b=e,Ic.push(r),r}function Br(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Wr(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Jr(){this._=null}function Gr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Kr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&amp;&amp;(e.R.U=e),r.L=e}function Qr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&amp;&amp;(e.L.U=e),r.R=e}function nu(n){for(;n.L;)n=n.L;return n}function tu(n,t){var e,r,u,i=n.sort(eu).pop();for(Ic=[],Zc=new Array(n.length),Vc=new Jr,$c=new Jr;;)if(u=Xc,i&amp;&amp;(!u||i.y&lt;u.y||i.y===u.y&amp;&amp;i.x&lt;u.x))(i.x!==e||i.y!==r)&amp;&amp;(Zc[i.i]=new Ur(i),Rr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&amp;&amp;(Ir(t),jr(t));var o={cells:Zc,edges:Ic};return Vc=$c=Ic=Zc=null,o}function eu(n,t){return t.y-n.y||t.x-n.x}function ru(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function uu(n){return n.x}function iu(n){return n.y}function ou(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function au(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&amp;&amp;au(n,c[0],e,r,o,a),c[1]&amp;&amp;au(n,c[1],o,r,u,a),c[2]&amp;&amp;au(n,c[2],e,a,o,i),c[3]&amp;&amp;au(n,c[3],o,a,u,i)}}function cu(n,t){n=Zo.rgb(n),t=Zo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return&quot;#&quot;+dt(Math.round(e+i*n))+dt(Math.round(r+o*n))+dt(Math.round(u+a*n))}}function su(n,t){var e,r={},u={};for(e in n)e in t?r[e]=hu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function lu(n,t){return t-=n=+n,function(e){return n+t*e}}function fu(n,t){var e,r,u,i=Gc.lastIndex=Kc.lastIndex=0,o=-1,a=[],c=[];for(n+=&quot;&quot;,t+=&quot;&quot;;(e=Gc.exec(n))&amp;&amp;(r=Kc.exec(t));)(u=r.index)&gt;i&amp;&amp;(u=t.substring(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:lu(e,r)})),i=Kc.lastIndex;return i&lt;t.length&amp;&amp;(u=t.substring(i),a[o]?a[o]+=u:a[++o]=u),a.length&lt;2?c[0]?(t=c[0].x,function(n){return t(n)+&quot;&quot;}):function(){return t}:(t=c.length,function(n){for(var e,r=0;t&gt;r;++r)a[(e=c[r]).i]=e.x(n);return a.join(&quot;&quot;)})}function hu(n,t){for(var e,r=Zo.interpolators.length;--r&gt;=0&amp;&amp;!(e=Zo.interpolators[r](n,t)););return e}function gu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a&gt;e;++e)r.push(hu(n[e],t[e]));for(;i&gt;e;++e)u[e]=n[e];for(;o&gt;e;++e)u[e]=t[e];return function(n){for(e=0;a&gt;e;++e)u[e]=r[e](n);return u}}function pu(n){return function(t){return 0&gt;=t?0:t&gt;=1?1:n(t)}}function vu(n){return function(t){return 1-n(1-t)}}function du(n){return function(t){return.5*(.5&gt;t?n(2*t):2-n(2-2*t))}}function mu(n){return n*n}function yu(n){return n*n*n}function xu(n){if(0&gt;=n)return 0;if(n&gt;=1)return 1;var t=n*n,e=t*n;return 4*(.5&gt;n?e:3*(n-t)+e-.75)}function Mu(n){return function(t){return Math.pow(t,n)}}function _u(n){return 1-Math.cos(n*Sa)}function bu(n){return Math.pow(2,10*(n-1))}function wu(n){return 1-Math.sqrt(1-n*n)}function Su(n,t){var e;return arguments.length&lt;2&amp;&amp;(t=.45),arguments.length?e=t/wa*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*wa/t)}}function ku(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Eu(n){return 1/2.75&gt;n?7.5625*n*n:2/2.75&gt;n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75&gt;n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Au(n,t){n=Zo.hcl(n),t=Zo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&amp;&amp;(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i&gt;180?i-=360:-180&gt;i&amp;&amp;(i+=360),function(n){return ot(e+i*n,r+o*n,u+a*n)+&quot;&quot;}}function Cu(n,t){n=Zo.hsl(n),t=Zo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&amp;&amp;(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i&gt;180?i-=360:-180&gt;i&amp;&amp;(i+=360),function(n){return ut(e+i*n,r+o*n,u+a*n)+&quot;&quot;}}function Nu(n,t){n=Zo.lab(n),t=Zo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ct(e+i*n,r+o*n,u+a*n)+&quot;&quot;}}function zu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(Ru(e,t,-u))||0;t[0]*e[1]&lt;e[0]*t[1]&amp;&amp;(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Ca,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Ca:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&amp;&amp;(n[0]/=t,n[1]/=t),t}function Ru(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Du(n,t){var e,r=[],u=[],i=Zo.transform(n),o=Zo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push(&quot;translate(&quot;,null,&quot;,&quot;,null,&quot;)&quot;),u.push({i:1,x:lu(a[0],c[0])},{i:3,x:lu(a[1],c[1])})):c[0]||c[1]?r.push(&quot;translate(&quot;+c+&quot;)&quot;):r.push(&quot;&quot;),s!=l?(s-l&gt;180?l+=360:l-s&gt;180&amp;&amp;(s+=360),u.push({i:r.push(r.pop()+&quot;rotate(&quot;,null,&quot;)&quot;)-2,x:lu(s,l)})):l&amp;&amp;r.push(r.pop()+&quot;rotate(&quot;+l+&quot;)&quot;),f!=h?u.push({i:r.push(r.pop()+&quot;skewX(&quot;,null,&quot;)&quot;)-2,x:lu(f,h)}):h&amp;&amp;r.push(r.pop()+&quot;skewX(&quot;+h+&quot;)&quot;),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+&quot;scale(&quot;,null,&quot;,&quot;,null,&quot;)&quot;),u.push({i:e-4,x:lu(g[0],p[0])},{i:e-2,x:lu(g[1],p[1])})):(1!=p[0]||1!=p[1])&amp;&amp;r.push(r.pop()+&quot;scale(&quot;+p+&quot;)&quot;),e=u.length,function(n){for(var t,i=-1;++i&lt;e;)r[(t=u[i]).i]=t.x(n);return r.join(&quot;&quot;)}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Uu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function ju(n){for(var t=n.source,e=n.target,r=Fu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Hu(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Fu(n,t){if(n===t)return n;for(var e=Hu(n),r=Hu(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Ou(n){n.fixed|=2}function Yu(n){n.fixed&amp;=-7}function Iu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Zu(n){n.fixed&amp;=-5}function Vu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c&lt;a;)i=o[c],null!=i&amp;&amp;(Vu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Xu(n,t){return Zo.rebind(n,t,&quot;sort&quot;,&quot;children&quot;,&quot;value&quot;),n.nodes=n,n.links=Ku,n}function $u(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(u=n.children)&amp;&amp;(r=u.length))for(var r,u;--r&gt;=0;)e.push(u[r])}function Bu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&amp;&amp;(u=i.length))for(var u,i,o=-1;++o&lt;u;)e.push(i[o]);for(;null!=(n=r.pop());)t(n)}function Wu(n){return n.children}function Ju(n){return n.value}function Gu(n,t){return t.value-n.value}function Ku(n){return Zo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Qu(n){return n.x}function ni(n){return n.y}function ti(n,t,e){n.y0=t,n.y=e}function ei(n){return Zo.range(n.length)}function ri(n){for(var t=-1,e=n[0].length,r=[];++t&lt;e;)r[t]=0;return r}function ui(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i&gt;e;++e)(t=n[e][1])&gt;u&amp;&amp;(r=e,u=t);return r}function ii(n){return n.reduce(oi,0)}function oi(n,t){return n+t[1]}function ai(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e&lt;=t;)i[e]=u*e+r;return i}function si(n){return[Zo.min(n),Zo.max(n)]}function li(n,t){return n.value-t.value}function fi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function hi(n,t){n._pack_next=t,t._pack_prev=n}function gi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u&gt;e*e+r*r}function pi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&amp;&amp;(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(vi),r=e[0],r.x=-r.r,r.y=0,t(r),s&gt;1&amp;&amp;(u=e[1],u.x=u.r,u.y=0,t(u),s&gt;2))for(i=e[2],yi(r,u,i),t(i),fi(r,i),r._pack_prev=i,fi(i,u),u=r._pack_next,o=3;s&gt;o;o++){yi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(gi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&amp;&amp;!gi(c,i);c=c._pack_prev,d++);p?(d&gt;v||v==d&amp;&amp;u.r&lt;r.r?hi(r,u=a):hi(r=c,u),o--):(fi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s&gt;o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(di)}}function vi(n){n._pack_next=n._pack_prev=n}function di(n){delete n._pack_next,delete n._pack_prev}function mi(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i&lt;o;)mi(u[i],t,e,r)}function yi(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&amp;&amp;(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function xi(n,t){return n.parent==t.parent?1:2}function Mi(n){var t=n.children;return t.length?t[0]:n.t}function _i(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function bi(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function wi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i&gt;=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Si(n,t,e){return n.a.parent===t.parent?n.a:e}function ki(n){return 1+Zo.max(n,function(n){return n.y})}function Ei(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ai(n){var t=n.children;return t&amp;&amp;t.length?Ai(t[0]):n}function Ci(n){var t,e=n.children;return e&amp;&amp;(t=e.length)?Ci(e[t-1]):n}function Ni(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function zi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0&gt;u&amp;&amp;(e+=u/2,u=0),0&gt;i&amp;&amp;(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Li(n){var t=n[0],e=n[n.length-1];return e&gt;t?[t,e]:[e,t]}function Ti(n){return n.rangeExtent?n.rangeExtent():Li(n.range())}function qi(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ri(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i&gt;o&amp;&amp;(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Di(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ss}function Pi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]&lt;n[0]&amp;&amp;(n=n.slice().reverse(),t=t.slice().reverse());++o&lt;=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Zo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Ui(n,t,e,r){function u(){var u=Math.min(n.length,t.length)&gt;2?Pi:qi,c=r?Uu:Pu;return o=u(n,t,c,e),a=u(t,n,c,hu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(zu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Oi(n,t)},i.tickFormat=function(t,e){return Yi(n,t,e)},i.nice=function(t){return Hi(n,t),u()},i.copy=function(){return Ui(n,t,e,r)},u()}function ji(n,t){return Zo.rebind(n,t,&quot;range&quot;,&quot;rangeRound&quot;,&quot;interpolate&quot;,&quot;clamp&quot;)}function Hi(n,t){return Ri(n,Di(Fi(n,t)[2]))}function Fi(n,t){null==t&amp;&amp;(t=10);var e=Li(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15&gt;=i?u*=10:.35&gt;=i?u*=5:.75&gt;=i&amp;&amp;(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Oi(n,t){return Zo.range.apply(Zo,Fi(n,t))}function Yi(n,t,e){var r=Fi(n,t);if(e){var u=Ga.exec(e);if(u.shift(),&quot;s&quot;===u[8]){var i=Zo.formatPrefix(Math.max(ua(r[0]),ua(r[1])));return u[7]||(u[7]=&quot;.&quot;+Ii(i.scale(r[2]))),u[8]=&quot;f&quot;,e=Zo.format(u.join(&quot;&quot;)),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]=&quot;.&quot;+Zi(u[8],r)),e=u.join(&quot;&quot;)}else e=&quot;,.&quot;+Ii(r[2])+&quot;f&quot;;return Zo.format(e)}function Ii(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Zi(n,t){var e=Ii(t[2]);return n in ls?Math.abs(e-Ii(Math.max(ua(t[0]),ua(t[1]))))+ +(&quot;e&quot;!==n):e-2*(&quot;%&quot;===n)}function Vi(n,t,e,r){function u(n){return(e?Math.log(0&gt;n?0:n):-Math.log(n&gt;0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]&gt;=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ri(r.map(u),e?Math:hs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Li(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l&gt;s;s++)for(var h=1;f&gt;h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++&lt;l;)for(var h=f-1;h&gt;0;h--)o.push(i(s)*h);for(s=0;o[s]&lt;a;s++);for(l=o.length;o[l-1]&gt;c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return fs;arguments.length&lt;2?t=fs:&quot;function&quot;!=typeof t&amp;&amp;(t=Zo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))&lt;=a?t(n):&quot;&quot;}},o.copy=function(){return Vi(n.copy(),t,e,r)},ji(o,n)}function Xi(n,t,e){function r(t){return n(u(t))}var u=$i(t),i=$i(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Oi(e,n)},r.tickFormat=function(n,t){return Yi(e,n,t)},r.nice=function(n){return r.domain(Hi(e,n))},r.exponent=function(o){return arguments.length?(u=$i(t=o),i=$i(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Xi(n.copy(),t,e)},ji(r,n)}function $i(n){return function(t){return 0&gt;t?-Math.pow(-t,n):Math.pow(t,n)}}function Bi(n,t){function e(e){return i[((u.get(e)||(&quot;range&quot;===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return Zo.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new o;for(var i,a=-1,c=r.length;++a&lt;c;)u.has(i=r[a])||u.set(i,n.push(i));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(i=n,a=0,t={t:&quot;range&quot;,a:arguments},e):i},e.rangePoints=function(u,o){arguments.length&lt;2&amp;&amp;(o=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+o);return i=r(n.length&lt;2?(c+s)/2:c+l*o/2,l),a=0,t={t:&quot;rangePoints&quot;,a:arguments},e},e.rangeBands=function(u,o,c){arguments.length&lt;2&amp;&amp;(o=0),arguments.length&lt;3&amp;&amp;(c=o);var s=u[1]&lt;u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-o+2*c);return i=r(l+h*c,h),s&amp;&amp;i.reverse(),a=h*(1-o),t={t:&quot;rangeBands&quot;,a:arguments},e},e.rangeRoundBands=function(u,o,c){arguments.length&lt;2&amp;&amp;(o=0),arguments.length&lt;3&amp;&amp;(c=o);var s=u[1]&lt;u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-o+2*c)),g=f-l-(n.length-o)*h;return i=r(l+Math.round(g/2),h),s&amp;&amp;i.reverse(),a=Math.round(h*(1-o)),t={t:&quot;rangeRoundBands&quot;,a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return Li(t.a[0])},e.copy=function(){return Bi(n,t)},e.domain(n)}function Wi(e,r){function u(){var n=0,t=r.length;for(o=[];++n&lt;t;)o[n-1]=Zo.quantile(e,n/t);return i}function i(n){return isNaN(n=+n)?void 0:r[Zo.bisect(o,n)]}var o;return i.domain=function(r){return arguments.length?(e=r.filter(t).sort(n),u()):e},i.range=function(n){return arguments.length?(r=n,u()):r},i.quantiles=function(){return o},i.invertExtent=function(n){return n=r.indexOf(n),0&gt;n?[0/0,0/0]:[n&gt;0?o[n-1]:e[0],n&lt;o.length?o[n]:e[e.length-1]]},i.copy=function(){return Wi(e,r)},u()}function Ji(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0&gt;t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ji(n,t,e)},u()}function Gi(n,t){function e(e){return e&gt;=e?t[Zo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Gi(n,t)},e}function Ki(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Oi(n,t)},t.tickFormat=function(t,e){return Yi(n,t,e)},t.copy=function(){return Ki(n)},t}function Qi(n){return n.innerRadius}function no(n){return n.outerRadius}function to(n){return n.startAngle}function eo(n){return n.endAngle}function ro(n){function t(t){function o(){s.push(&quot;M&quot;,i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=bt(e),p=bt(r);++f&lt;h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&amp;&amp;(o(),l=[]);return l.length&amp;&amp;o(),s.length?s.join(&quot;&quot;):null}var e=wr,r=Sr,u=we,i=uo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o=&quot;function&quot;==typeof n?i=n:(i=xs.get(n)||uo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function uo(n){return n.join(&quot;L&quot;)}function io(n){return uo(n)+&quot;Z&quot;}function oo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],&quot;,&quot;,r[1]];++t&lt;e;)u.push(&quot;H&quot;,(r[0]+(r=n[t])[0])/2,&quot;V&quot;,r[1]);return e&gt;1&amp;&amp;u.push(&quot;H&quot;,r[0]),u.join(&quot;&quot;)}function ao(n){for(var t=0,e=n.length,r=n[0],u=[r[0],&quot;,&quot;,r[1]];++t&lt;e;)u.push(&quot;V&quot;,(r=n[t])[1],&quot;H&quot;,r[0]);return u.join(&quot;&quot;)}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],&quot;,&quot;,r[1]];++t&lt;e;)u.push(&quot;H&quot;,(r=n[t])[0],&quot;V&quot;,r[1]);return u.join(&quot;&quot;)}function so(n,t){return n.length&lt;4?uo(n):n[1]+ho(n.slice(1,n.length-1),go(n,t))}function lo(n,t){return n.length&lt;3?uo(n):n[0]+ho((n.push(n[0]),n),go([n[n.length-2]].concat(n,[n[1]]),t))}function fo(n,t){return n.length&lt;3?uo(n):n[0]+ho(n,go(n,t))}function ho(n,t){if(t.length&lt;1||n.length!=t.length&amp;&amp;n.length!=t.length+2)return uo(n);var e=n.length!=t.length,r=&quot;&quot;,u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&amp;&amp;(r+=&quot;Q&quot;+(i[0]-2*o[0]/3)+&quot;,&quot;+(i[1]-2*o[1]/3)+&quot;,&quot;+i[0]+&quot;,&quot;+i[1],u=n[1],c=2),t.length&gt;1){a=t[1],i=n[c],c++,r+=&quot;C&quot;+(u[0]+o[0])+&quot;,&quot;+(u[1]+o[1])+&quot;,&quot;+(i[0]-a[0])+&quot;,&quot;+(i[1]-a[1])+&quot;,&quot;+i[0]+&quot;,&quot;+i[1];for(var s=2;s&lt;t.length;s++,c++)i=n[c],a=t[s],r+=&quot;S&quot;+(i[0]-a[0])+&quot;,&quot;+(i[1]-a[1])+&quot;,&quot;+i[0]+&quot;,&quot;+i[1]}if(e){var l=n[c];r+=&quot;Q&quot;+(i[0]+2*a[0]/3)+&quot;,&quot;+(i[1]+2*a[1]/3)+&quot;,&quot;+l[0]+&quot;,&quot;+l[1]}return r}function go(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a&lt;c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function po(n){if(n.length&lt;3)return uo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,&quot;,&quot;,i,&quot;L&quot;,xo(bs,o),&quot;,&quot;,xo(bs,a)];for(n.push(n[e-1]);++t&lt;=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Mo(c,o,a);return n.pop(),c.push(&quot;L&quot;,r),c.join(&quot;&quot;)}function vo(n){if(n.length&lt;4)return uo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r&lt;3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(xo(bs,i)+&quot;,&quot;+xo(bs,o)),--r;++r&lt;u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),Mo(e,i,o);return e.join(&quot;&quot;)}function mo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r&lt;4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[xo(bs,o),&quot;,&quot;,xo(bs,a)],--r;++r&lt;i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Mo(t,o,a);return t.join(&quot;&quot;)}function yo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s&lt;=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return po(n)}function xo(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Mo(n,t,e){n.push(&quot;C&quot;,xo(Ms,t),&quot;,&quot;,xo(Ms,e),&quot;,&quot;,xo(_s,t),&quot;,&quot;,xo(_s,e),&quot;,&quot;,xo(bs,t),&quot;,&quot;,xo(bs,e))}function _o(n,t){return(t[1]-n[1])/(t[0]-n[0])}function bo(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=_o(u,i);++t&lt;e;)r[t]=(o+(o=_o(u=i,i=n[t+1])))/2;return r[t]=o,r}function wo(n){for(var t,e,r,u,i=[],o=bo(n),a=-1,c=n.length-1;++a&lt;c;)t=_o(n[a],n[a+1]),ua(t)&lt;ka?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u&gt;9&amp;&amp;(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a&lt;=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function So(n){return n.length&lt;3?uo(n):n[0]+ho(n,wo(n))}function ko(n){for(var t,e,r,u=-1,i=n.length;++u&lt;i;)t=n[u],e=t[0],r=t[1]+ms,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Eo(n){function t(t){function c(){v.push(&quot;M&quot;,a(n(m),f),l,s(n(d.reverse()),f),&quot;Z&quot;)}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=bt(e),_=bt(u),b=e===r?function(){return g}:bt(r),w=u===i?function(){return p}:bt(i);++y&lt;x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&amp;&amp;(c(),d=[],m=[]);return d.length&amp;&amp;c(),v.length?v.join(&quot;&quot;):null}var e=wr,r=wr,u=0,i=Sr,o=we,a=uo,c=a.key,s=a,l=&quot;L&quot;,f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c=&quot;function&quot;==typeof n?a=n:(a=xs.get(n)||uo).key,s=a.reverse||a,l=a.closed?&quot;M&quot;:&quot;L&quot;,t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Ao(n){return n.radius}function Co(n){return[n.x,n.y]}function No(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ms;return[e*Math.cos(r),e*Math.sin(r)]}}function zo(){return 64}function Lo(){return&quot;circle&quot;}function To(n){var t=Math.sqrt(n/ba);return&quot;M0,&quot;+t+&quot;A&quot;+t+&quot;,&quot;+t+&quot; 0 1,1 0,&quot;+-t+&quot;A&quot;+t+&quot;,&quot;+t+&quot; 0 1,1 0,&quot;+t+&quot;Z&quot;}function qo(n,t){return sa(n,Cs),n.id=t,n}function Ro(n,t,e,r){var u=n.id;return P(n,&quot;function&quot;==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Do(n){return null==n&amp;&amp;(n=&quot;&quot;),function(){this.textContent=n}}function Po(n,t,e,r){var u=n.__transition__||(n.__transition__={active:0,count:0}),i=u[e];if(!i){var a=r.time;i=u[e]={tween:new o,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,Zo.timer(function(r){function o(r){return u.active&gt;e?s():(u.active=e,i.event&amp;&amp;i.event.start.call(n,l,t),i.tween.forEach(function(e,r){(r=r.call(n,l,t))&amp;&amp;v.push(r)}),Zo.timer(function(){return p.c=c(r||1)?we:c,1},0,a),void 0)}function c(r){if(u.active!==e)return s();for(var o=r/g,a=f(o),c=v.length;c&gt;0;)v[--c].call(n,a);
+return o&gt;=1?(i.event&amp;&amp;i.event.end.call(n,l,t),s()):void 0}function s(){return--u.count?delete u[e]:delete n.__transition__,1}var l=n.__data__,f=i.ease,h=i.delay,g=i.duration,p=Ba,v=[];return p.t=h+a,r&gt;=h?o(r-h):(p.c=o,void 0)},0,a)}}function Uo(n,t){n.attr(&quot;transform&quot;,function(n){return&quot;translate(&quot;+t(n)+&quot;,0)&quot;})}function jo(n,t){n.attr(&quot;transform&quot;,function(n){return&quot;translate(0,&quot;+t(n)+&quot;)&quot;})}function Ho(n){return n.toISOString()}function Fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Zo.bisect(Us,u);return i==Us.length?[t.year,Fi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Us[i-1]&lt;Us[i]/u?i-1:i]:[Fs,Fi(n,e)[2]]}return r.invert=function(t){return Oo(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Oo)},r.nice=function(n,t){function e(e){return!isNaN(e)&amp;&amp;!n.range(e,Oo(+e+1),t).length}var i=r.domain(),o=Li(i),a=null==n?u(o,10):&quot;number&quot;==typeof n&amp;&amp;u(o,n);return a&amp;&amp;(n=a[0],t=a[1]),r.domain(Ri(i,t&gt;1?{floor:function(t){for(;e(t=n.floor(t));)t=Oo(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Oo(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Li(r.domain()),i=null==n?u(e,10):&quot;number&quot;==typeof n?u(e,n):!n.range&amp;&amp;[{range:n},t];return i&amp;&amp;(n=i[0],t=i[1]),n.range(e[0],Oo(+e[1]+1),1&gt;t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Fo(n.copy(),t,e)},ji(r,n)}function Oo(n){return new Date(n)}function Yo(n){return JSON.parse(n.responseText)}function Io(n){var t=$o.createRange();return t.selectNode($o.body),t.createContextualFragment(n.responseText)}var Zo={version:&quot;3.4.11&quot;};Date.now||(Date.now=function(){return+new Date});var Vo=[].slice,Xo=function(n){return Vo.call(n)},$o=document,Bo=$o.documentElement,Wo=window;try{Xo(Bo.childNodes)[0].nodeType}catch(Jo){Xo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{$o.createElement(&quot;div&quot;).style.setProperty(&quot;opacity&quot;,0,&quot;&quot;)}catch(Go){var Ko=Wo.Element.prototype,Qo=Ko.setAttribute,na=Ko.setAttributeNS,ta=Wo.CSSStyleDeclaration.prototype,ea=ta.setProperty;Ko.setAttribute=function(n,t){Qo.call(this,n,t+&quot;&quot;)},Ko.setAttributeNS=function(n,t,e){na.call(this,n,t,e+&quot;&quot;)},ta.setProperty=function(n,t,e){ea.call(this,n,t+&quot;&quot;,e)}}Zo.ascending=n,Zo.descending=function(n,t){return n&gt;t?-1:t&gt;n?1:t&gt;=n?0:0/0},Zo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u&lt;i&amp;&amp;!(null!=(e=n[u])&amp;&amp;e&gt;=e);)e=void 0;for(;++u&lt;i;)null!=(r=n[u])&amp;&amp;e&gt;r&amp;&amp;(e=r)}else{for(;++u&lt;i&amp;&amp;!(null!=(e=t.call(n,n[u],u))&amp;&amp;e&gt;=e);)e=void 0;for(;++u&lt;i;)null!=(r=t.call(n,n[u],u))&amp;&amp;e&gt;r&amp;&amp;(e=r)}return e},Zo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u&lt;i&amp;&amp;!(null!=(e=n[u])&amp;&amp;e&gt;=e);)e=void 0;for(;++u&lt;i;)null!=(r=n[u])&amp;&amp;r&gt;e&amp;&amp;(e=r)}else{for(;++u&lt;i&amp;&amp;!(null!=(e=t.call(n,n[u],u))&amp;&amp;e&gt;=e);)e=void 0;for(;++u&lt;i;)null!=(r=t.call(n,n[u],u))&amp;&amp;r&gt;e&amp;&amp;(e=r)}return e},Zo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i&lt;o&amp;&amp;!(null!=(e=u=n[i])&amp;&amp;e&gt;=e);)e=u=void 0;for(;++i&lt;o;)null!=(r=n[i])&amp;&amp;(e&gt;r&amp;&amp;(e=r),r&gt;u&amp;&amp;(u=r))}else{for(;++i&lt;o&amp;&amp;!(null!=(e=u=t.call(n,n[i],i))&amp;&amp;e&gt;=e);)e=void 0;for(;++i&lt;o;)null!=(r=t.call(n,n[i],i))&amp;&amp;(e&gt;r&amp;&amp;(e=r),r&gt;u&amp;&amp;(u=r))}return[e,u]},Zo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i&lt;u;)isNaN(e=+n[i])||(r+=e);else for(;++i&lt;u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Zo.mean=function(n,e){var r,u=0,i=n.length,o=-1,a=i;if(1===arguments.length)for(;++o&lt;i;)t(r=n[o])?u+=r:--a;else for(;++o&lt;i;)t(r=e.call(n,n[o],o))?u+=r:--a;return a?u/a:void 0},Zo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Zo.median=function(e,r){return arguments.length&gt;1&amp;&amp;(e=e.map(r)),e=e.filter(t),e.length?Zo.quantile(e.sort(n),.5):void 0};var ra=e(n);Zo.bisectLeft=ra.left,Zo.bisect=Zo.bisectRight=ra.right,Zo.bisector=function(t){return e(1===t.length?function(e,r){return n(t(e),r)}:t)},Zo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Zo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Zo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0&gt;r?0:r);r&gt;e;)i[e]=[t=u,u=n[++e]];return i},Zo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,t=Zo.min(arguments,r),e=new Array(t);++n&lt;t;)for(var u,i=-1,o=e[n]=new Array(u);++i&lt;u;)o[i]=arguments[i][n];return e},Zo.transpose=function(n){return Zo.zip.apply(Zo,n)},Zo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Zo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Zo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Zo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i&lt;u;)o+=n[i].length;for(e=new Array(o);--u&gt;=0;)for(r=n[u],t=r.length;--t&gt;=0;)e[--o]=r[t];return e};var ua=Math.abs;Zo.range=function(n,t,e){if(arguments.length&lt;3&amp;&amp;(e=1,arguments.length&lt;2&amp;&amp;(t=n,n=0)),1/0===(t-n)/e)throw new Error(&quot;infinite range&quot;);var r,i=[],o=u(ua(e)),a=-1;if(n*=o,t*=o,e*=o,0&gt;e)for(;(r=n+e*++a)&gt;t;)i.push(r/o);else for(;(r=n+e*++a)&lt;t;)i.push(r/o);return i},Zo.map=function(n){var t=new o;if(n instanceof o)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},i(o,{has:a,get:function(n){return this[ia+n]},set:function(n,t){return this[ia+n]=t},remove:c,keys:s,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&amp;&amp;n.call(this,t.substring(1),this[t])}});var ia=&quot;\x00&quot;,oa=ia.charCodeAt(0);Zo.nest=function(){function n(t,a,c){if(c&gt;=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=i[c++],d=new o;++g&lt;p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e&gt;=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(Zo.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},Zo.set=function(n){var t=new h;if(n)for(var e=0,r=n.length;r&gt;e;++e)t.add(n[e]);return t},i(h,{has:a,add:function(n){return this[ia+n]=!0,n},remove:function(n){return n=ia+n,n in this&amp;&amp;delete this[n]},values:s,size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&amp;&amp;n.call(this,t.substring(1))}}),Zo.behavior={},Zo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r&lt;u;)n[e=arguments[r]]=g(n,t,t[e]);return n};var aa=[&quot;webkit&quot;,&quot;ms&quot;,&quot;moz&quot;,&quot;Moz&quot;,&quot;o&quot;,&quot;O&quot;];Zo.dispatch=function(){for(var n=new d,t=-1,e=arguments.length;++t&lt;e;)n[arguments[t]]=m(n);return n},d.prototype.on=function(n,t){var e=n.indexOf(&quot;.&quot;),r=&quot;&quot;;if(e&gt;=0&amp;&amp;(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length&lt;2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&amp;&amp;this[n].on(r,null);return this}},Zo.event=null,Zo.requote=function(n){return n.replace(ca,&quot;\\$&amp;&quot;)};var ca=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},la=function(n,t){return t.querySelector(n)},fa=function(n,t){return t.querySelectorAll(n)},ha=Bo.matches||Bo[p(Bo,&quot;matchesSelector&quot;)],ga=function(n,t){return ha.call(n,t)};&quot;function&quot;==typeof Sizzle&amp;&amp;(la=function(n,t){return Sizzle(n,t)[0]||null},fa=Sizzle,ga=Sizzle.matchesSelector),Zo.selection=function(){return ma};var pa=Zo.selection.prototype=[];pa.select=function(n){var t,e,r,u,i=[];n=b(n);for(var o=-1,a=this.length;++o&lt;a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c&lt;s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&amp;&amp;&quot;__data__&quot;in u&amp;&amp;(e.__data__=u.__data__)):t.push(null)}return _(i)},pa.selectAll=function(n){var t,e,r=[];n=w(n);for(var u=-1,i=this.length;++u&lt;i;)for(var o=this[u],a=-1,c=o.length;++a&lt;c;)(e=o[a])&amp;&amp;(r.push(t=Xo(n.call(e,e.__data__,a,u))),t.parentNode=e);return _(r)};var va={svg:&quot;http://www.w3.org/2000/svg&quot;,xhtml:&quot;http://www.w3.org/1999/xhtml&quot;,xlink:&quot;http://www.w3.org/1999/xlink&quot;,xml:&quot;http://www.w3.org/XML/1998/namespace&quot;,xmlns:&quot;http://www.w3.org/2000/xmlns/&quot;};Zo.ns={prefix:va,qualify:function(n){var t=n.indexOf(&quot;:&quot;),e=n;return t&gt;=0&amp;&amp;(e=n.substring(0,t),n=n.substring(t+1)),va.hasOwnProperty(e)?{space:va[e],local:n}:n}},pa.attr=function(n,t){if(arguments.length&lt;2){if(&quot;string&quot;==typeof n){var e=this.node();return n=Zo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(S(t,n[t]));return this}return this.each(S(n,t))},pa.classed=function(n,t){if(arguments.length&lt;2){if(&quot;string&quot;==typeof n){var e=this.node(),r=(n=A(n)).length,u=-1;if(t=e.classList){for(;++u&lt;r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute(&quot;class&quot;);++u&lt;r;)if(!E(n[u]).test(t))return!1;return!0}for(t in n)this.each(C(t,n[t]));return this}return this.each(C(n,t))},pa.style=function(n,t,e){var r=arguments.length;if(3&gt;r){if(&quot;string&quot;!=typeof n){2&gt;r&amp;&amp;(t=&quot;&quot;);for(e in n)this.each(z(e,n[e],t));return this}if(2&gt;r)return Wo.getComputedStyle(this.node(),null).getPropertyValue(n);e=&quot;&quot;}return this.each(z(n,t,e))},pa.property=function(n,t){if(arguments.length&lt;2){if(&quot;string&quot;==typeof n)return this.node()[n];for(t in n)this.each(L(t,n[t]));return this}return this.each(L(n,t))},pa.text=function(n){return arguments.length?this.each(&quot;function&quot;==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?&quot;&quot;:t}:null==n?function(){this.textContent=&quot;&quot;}:function(){this.textContent=n}):this.node().textContent},pa.html=function(n){return arguments.length?this.each(&quot;function&quot;==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?&quot;&quot;:t}:null==n?function(){this.innerHTML=&quot;&quot;}:function(){this.innerHTML=n}):this.node().innerHTML},pa.append=function(n){return n=T(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},pa.insert=function(n,t){return n=T(n),t=b(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},pa.remove=function(){return this.each(function(){var n=this.parentNode;n&amp;&amp;n.removeChild(this)})},pa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new o,y=new o,x=[];for(r=-1;++r&lt;a;)d=t.call(u=n[r],u.__data__,r),m.has(d)?v[r]=u:m.set(d,u),x.push(d);for(r=-1;++r&lt;f;)d=t.call(e,i=e[r],r),(u=m.get(d))?(g[r]=u,u.__data__=i):y.has(d)||(p[r]=q(i)),y.set(d,i),m.remove(d);for(r=-1;++r&lt;a;)m.has(x[r])&amp;&amp;(v[r]=n[r])}else{for(r=-1;++r&lt;h;)u=n[r],i=e[r],u?(u.__data__=i,g[r]=u):p[r]=q(i);for(;f&gt;r;++r)p[r]=q(e[r]);for(;a&gt;r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++i&lt;a;)(u=r[i])&amp;&amp;(n[i]=u.__data__);return n}var c=U([]),s=_([]),l=_([]);if(&quot;function&quot;==typeof n)for(;++i&lt;a;)e(r=this[i],n.call(r,r.parentNode.__data__,i));else for(;++i&lt;a;)e(r=this[i],n);return s.enter=function(){return c},s.exit=function(){return l},s},pa.datum=function(n){return arguments.length?this.property(&quot;__data__&quot;,n):this.property(&quot;__data__&quot;)},pa.filter=function(n){var t,e,r,u=[];&quot;function&quot;!=typeof n&amp;&amp;(n=R(n));for(var i=0,o=this.length;o&gt;i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c&gt;a;a++)(r=e[a])&amp;&amp;n.call(r,r.__data__,a,i)&amp;&amp;t.push(r)}return _(u)},pa.order=function(){for(var n=-1,t=this.length;++n&lt;t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u&gt;=0;)(e=r[u])&amp;&amp;(i&amp;&amp;i!==e.nextSibling&amp;&amp;i.parentNode.insertBefore(e,i),i=e);return this},pa.sort=function(n){n=D.apply(this,arguments);for(var t=-1,e=this.length;++t&lt;e;)this[t].sort(n);return this.order()},pa.each=function(n){return P(this,function(t,e,r){n.call(t,t.__data__,e,r)})},pa.call=function(n){var t=Xo(arguments);return n.apply(t[0]=this,t),this},pa.empty=function(){return!this.node()},pa.node=function(){for(var n=0,t=this.length;t&gt;n;n++)for(var e=this[n],r=0,u=e.length;u&gt;r;r++){var i=e[r];if(i)return i}return null},pa.size=function(){var n=0;return this.each(function(){++n}),n};var da=[];Zo.selection.enter=U,Zo.selection.enter.prototype=da,da.append=pa.append,da.empty=pa.empty,da.node=pa.node,da.call=pa.call,da.size=pa.size,da.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a&lt;c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s&lt;l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return _(o)},da.insert=function(n,t){return arguments.length&lt;2&amp;&amp;(t=j(this)),pa.insert.call(this,n,t)},pa.transition=function(){for(var n,t,e=Ss||++Ns,r=[],u=ks||{time:Date.now(),ease:xu,delay:0,duration:250},i=-1,o=this.length;++i&lt;o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c&lt;s;)(t=a[c])&amp;&amp;Po(t,c,e,u),n.push(t)}return qo(r,e)},pa.interrupt=function(){return this.each(H)},Zo.select=function(n){var t=[&quot;string&quot;==typeof n?la(n,$o):n];return t.parentNode=Bo,_([t])},Zo.selectAll=function(n){var t=Xo(&quot;string&quot;==typeof n?fa(n,$o):n);return t.parentNode=Bo,_([t])};var ma=Zo.select(Bo);pa.on=function(n,t,e){var r=arguments.length;if(3&gt;r){if(&quot;string&quot;!=typeof n){2&gt;r&amp;&amp;(t=!1);for(e in n)this.each(F(e,n[e],t));return this}if(2&gt;r)return(r=this.node()[&quot;__on&quot;+n])&amp;&amp;r._;e=!1}return this.each(F(n,t,e))};var ya=Zo.map({mouseenter:&quot;mouseover&quot;,mouseleave:&quot;mouseout&quot;});ya.forEach(function(n){&quot;on&quot;+n in $o&amp;&amp;ya.remove(n)});var xa=&quot;onselectstart&quot;in $o?null:p(Bo.style,&quot;userSelect&quot;),Ma=0;Zo.mouse=function(n){return Z(n,x())};var _a=/WebKit/.test(Wo.navigator.userAgent)?-1:0;Zo.touches=function(n,t){return arguments.length&lt;2&amp;&amp;(t=x().touches),t?Xo(t).map(function(t){var e=Z(n,t);return e.identifier=t.identifier,e}):[]},Zo.behavior.drag=function(){function n(){this.on(&quot;mousedown.drag&quot;,u).on(&quot;touchstart.drag&quot;,i)}function t(n,t,u,i,o){return function(){function a(){var n,e,r=t(h,v);r&amp;&amp;(n=r[0]-x[0],e=r[1]-x[1],p|=n|e,x=r,g({type:&quot;drag&quot;,x:r[0]+s[0],y:r[1]+s[1],dx:n,dy:e}))}function c(){t(h,v)&amp;&amp;(m.on(i+d,null).on(o+d,null),y(p&amp;&amp;Zo.event.target===f),g({type:&quot;dragend&quot;}))}var s,l=this,f=Zo.event.target,h=l.parentNode,g=e.of(l,arguments),p=0,v=n(),d=&quot;.drag&quot;+(null==v?&quot;&quot;:&quot;-&quot;+v),m=Zo.select(u()).on(i+d,a).on(o+d,c),y=I(),x=t(h,v);r?(s=r.apply(l,arguments),s=[s.x-x[0],s.y-x[1]]):s=[0,0],g({type:&quot;dragstart&quot;})}}var e=M(n,&quot;drag&quot;,&quot;dragstart&quot;,&quot;dragend&quot;),r=null,u=t(v,Zo.mouse,$,&quot;mousemove&quot;,&quot;mouseup&quot;),i=t(V,Zo.touch,X,&quot;touchmove&quot;,&quot;touchend&quot;);return n.origin=function(t){return arguments.length?(r=t,n):r},Zo.rebind(n,e,&quot;on&quot;)};var ba=Math.PI,wa=2*ba,Sa=ba/2,ka=1e-6,Ea=ka*ka,Aa=ba/180,Ca=180/ba,Na=Math.SQRT2,za=2,La=4;Zo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Q(v),o=i/(za*h)*(e*nt(Na*t+v)-K(v));return[r+o*s,u+o*l,i*e/Q(Na*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Na*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+La*f)/(2*i*za*h),p=(c*c-i*i-La*f)/(2*c*za*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Na;return e.duration=1e3*y,e},Zo.behavior.zoom=function(){function n(n){n.on(A,s).on(Ra+&quot;.zoom&quot;,f).on(&quot;dblclick.zoom&quot;,h).on(z,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&amp;&amp;_.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&amp;&amp;w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:&quot;zoomstart&quot;})}function a(n){i(),n({type:&quot;zoom&quot;,scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:&quot;zoomend&quot;})}function s(){function n(){l=1,u(Zo.mouse(r),h),a(s)}function e(){f.on(C,null).on(N,null),g(l&amp;&amp;Zo.event.target===i),c(s)}var r=this,i=Zo.event.target,s=L.of(r,arguments),l=0,f=Zo.select(Wo).on(C,n).on(N,e),h=t(Zo.mouse(r)),g=I();H.call(r),o(s)}function l(){function n(){var n=Zo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&amp;&amp;(v[n.identifier]=t(n))}),n}function e(){var t=Zo.event.target;Zo.select(t).on(M,i).on(_,f),b.push(t);for(var e=Zo.event.changedTouches,o=0,c=e.length;c&gt;o;++o)v[e[o].identifier]=null;var s=n(),l=Date.now();if(1===s.length){if(500&gt;l-m){var h=s[0],g=v[h.identifier];r(2*S.k),u(h,g),y(),a(p)}m=l}else if(s.length&gt;1){var h=s[0],x=s[1],w=h[0]-x[0],k=h[1]-x[1];d=w*w+k*k}}function i(){for(var n,t,e,i,o=Zo.touches(g),c=0,s=o.length;s&gt;c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=d&amp;&amp;Math.sqrt(l/d);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}m=null,u(n,t),a(p)}function f(){if(Zo.event.touches.length){for(var t=Zo.event.changedTouches,e=0,r=t.length;r&gt;e;++e)delete v[t[e].identifier];for(var u in v)return void n()}Zo.selectAll(b).on(x,null),w.on(A,s).on(z,l),k(),c(p)}var h,g=this,p=L.of(g,arguments),v={},d=0,x=&quot;.zoom-&quot;+Zo.event.changedTouches[0].identifier,M=&quot;touchmove&quot;+x,_=&quot;touchend&quot;+x,b=[],w=Zo.select(g).on(A,null).on(z,e),k=I();H.call(g),e(),o(p)}function f(){var n=L.of(this,arguments);d?clearTimeout(d):(g=t(p=v||Zo.mouse(this)),H.call(this),o(n)),d=setTimeout(function(){d=null,c(n)},50),y(),r(Math.pow(2,.002*Ta())*S.k),u(p,g),a(n)}function h(){var n=L.of(this,arguments),e=Zo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Zo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var g,p,v,d,m,x,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=qa,A=&quot;mousedown.zoom&quot;,C=&quot;mousemove.zoom&quot;,N=&quot;mouseup.zoom&quot;,z=&quot;touchstart.zoom&quot;,L=M(n,&quot;zoomstart&quot;,&quot;zoom&quot;,&quot;zoomend&quot;);return n.event=function(n){n.each(function(){var n=L.of(this,arguments),t=S;Ss?Zo.select(this).transition().each(&quot;start.zoom&quot;,function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween(&quot;zoom:zoom&quot;,function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Zo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each(&quot;end.zoom&quot;,function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?qa:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&amp;&amp;[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&amp;&amp;[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,x=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Zo.rebind(n,L,&quot;on&quot;)};var Ta,qa=[0,1/0],Ra=&quot;onwheel&quot;in $o?(Ta=function(){return-Zo.event.deltaY*(Zo.event.deltaMode?120:1)},&quot;wheel&quot;):&quot;onmousewheel&quot;in $o?(Ta=function(){return Zo.event.wheelDelta},&quot;mousewheel&quot;):(Ta=function(){return-Zo.event.detail},&quot;MozMousePixelScroll&quot;);Zo.color=et,et.prototype.toString=function(){return this.rgb()+&quot;&quot;},Zo.hsl=rt;var Da=rt.prototype=new et;Da.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,this.l/n)},Da.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,n*this.l)},Da.rgb=function(){return ut(this.h,this.s,this.l)},Zo.hcl=it;var Pa=it.prototype=new et;Pa.brighter=function(n){return new it(this.h,this.c,Math.min(100,this.l+Ua*(arguments.length?n:1)))},Pa.darker=function(n){return new it(this.h,this.c,Math.max(0,this.l-Ua*(arguments.length?n:1)))},Pa.rgb=function(){return ot(this.h,this.c,this.l).rgb()},Zo.lab=at;var Ua=18,ja=.95047,Ha=1,Fa=1.08883,Oa=at.prototype=new et;Oa.brighter=function(n){return new at(Math.min(100,this.l+Ua*(arguments.length?n:1)),this.a,this.b)},Oa.darker=function(n){return new at(Math.max(0,this.l-Ua*(arguments.length?n:1)),this.a,this.b)},Oa.rgb=function(){return ct(this.l,this.a,this.b)},Zo.rgb=gt;var Ya=gt.prototype=new et;Ya.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&amp;&amp;u&gt;t&amp;&amp;(t=u),e&amp;&amp;u&gt;e&amp;&amp;(e=u),r&amp;&amp;u&gt;r&amp;&amp;(r=u),new gt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new gt(u,u,u)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new gt(n*this.r,n*this.g,n*this.b)},Ya.hsl=function(){return yt(this.r,this.g,this.b)},Ya.toString=function(){return&quot;#&quot;+dt(this.r)+dt(this.g)+dt(this.b)};var Ia=Zo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ia.forEach(function(n,t){Ia.set(n,pt(t))}),Zo.functor=bt,Zo.xhr=St(wt),Zo.dsv=function(n,t){function e(n,e,i){arguments.length&lt;3&amp;&amp;(i=e,e=null);var o=kt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'&quot;'+n.replace(/\&quot;/g,'&quot;&quot;')+'&quot;':n}var a=new RegExp('[&quot;'+n+&quot;\n]&quot;),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function(&quot;d&quot;,&quot;return {&quot;+n.map(function(n,t){return JSON.stringify(n)+&quot;: d[&quot;+t+&quot;]&quot;}).join(&quot;,&quot;)+&quot;}&quot;);r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l&gt;=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++&lt;s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&amp;&amp;++l):10===r&amp;&amp;(u=!0),n.substring(t+1,e).replace(/&quot;&quot;/g,'&quot;')}for(;s&gt;l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&amp;&amp;(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&amp;&amp;r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&amp;&amp;a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new h,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join(&quot;\n&quot;)},e.formatRows=function(n){return n.map(i).join(&quot;\n&quot;)},e},Zo.csv=Zo.dsv(&quot;,&quot;,&quot;text/csv&quot;),Zo.tsv=Zo.dsv(&quot;    &quot;,&quot;text/tab-separated-values&quot;),Zo.touch=function(n,t,e){if(arguments.length&lt;3&amp;&amp;(e=t,t=x().changedTouches),t)for(var r,u=0,i=t.length;i&gt;u;++u)if((r=t[u]).identifier===e)return Z(n,r)};var Za,Va,Xa,$a,Ba,Wa=Wo[p(Wo,&quot;requestAnimationFrame&quot;)]||function(n){setTimeout(n,17)};Zo.timer=function(n,t,e){var r=arguments.length;2&gt;r&amp;&amp;(t=0),3&gt;r&amp;&amp;(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Va?Va.n=i:Za=i,Va=i,Xa||($a=clearTimeout($a),Xa=1,Wa(At))},Zo.timer.flush=function(){Ct(),Nt()},Zo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ja=[&quot;y&quot;,&quot;z&quot;,&quot;a&quot;,&quot;f&quot;,&quot;p&quot;,&quot;n&quot;,&quot;\xb5&quot;,&quot;m&quot;,&quot;&quot;,&quot;k&quot;,&quot;M&quot;,&quot;G&quot;,&quot;T&quot;,&quot;P&quot;,&quot;E&quot;,&quot;Z&quot;,&quot;Y&quot;].map(Lt);Zo.formatPrefix=function(n,t){var e=0;return n&amp;&amp;(0&gt;n&amp;&amp;(n*=-1),t&amp;&amp;(n=Zo.round(n,zt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),Ja[8+e/3]};var Ga=/(?:([^{])?([&lt;&gt;=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Ka=Zo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Zo.round(n,zt(n,t))).toFixed(Math.max(0,Math.min(20,zt(n*(1+1e-15),t))))}}),Qa=Zo.time={},nc=Date;Rt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){tc.setUTCDate.apply(this._,arguments)},setDay:function(){tc.setUTCDay.apply(this._,arguments)},setFullYear:function(){tc.setUTCFullYear.apply(this._,arguments)},setHours:function(){tc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){tc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){tc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){tc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){tc.setUTCSeconds.apply(this._,arguments)},setTime:function(){tc.setTime.apply(this._,arguments)}};var tc=Date.prototype;Qa.year=Dt(function(n){return n=Qa.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Qa.years=Qa.year.range,Qa.years.utc=Qa.year.utc.range,Qa.day=Dt(function(n){var t=new nc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Qa.days=Qa.day.range,Qa.days.utc=Qa.day.utc.range,Qa.dayOfYear=function(n){var t=Qa.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},[&quot;sunday&quot;,&quot;monday&quot;,&quot;tuesday&quot;,&quot;wednesday&quot;,&quot;thursday&quot;,&quot;friday&quot;,&quot;saturday&quot;].forEach(function(n,t){t=7-t;var e=Qa[n]=Dt(function(n){return(n=Qa.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Qa[n+&quot;s&quot;]=e.range,Qa[n+&quot;s&quot;].utc=e.utc.range,Qa[n+&quot;OfYear&quot;]=function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)}}),Qa.week=Qa.sunday,Qa.weeks=Qa.sunday.range,Qa.weeks.utc=Qa.sunday.utc.range,Qa.weekOfYear=Qa.sundayOfYear;var ec={&quot;-&quot;:&quot;&quot;,_:&quot; &quot;,0:&quot;0&quot;},rc=/^\s*\d+/,uc=/^%/;Zo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Ut(n)}};var ic=Zo.locale({decimal:&quot;.&quot;,thousands:&quot;,&quot;,grouping:[3],currency:[&quot;$&quot;,&quot;&quot;],dateTime:&quot;%a %b %e %X %Y&quot;,date:&quot;%m/%d/%Y&quot;,time:&quot;%H:%M:%S&quot;,periods:[&quot;AM&quot;,&quot;PM&quot;],days:[&quot;Sunday&quot;,&quot;Monday&quot;,&quot;Tuesday&quot;,&quot;Wednesday&quot;,&quot;Thursday&quot;,&quot;Friday&quot;,&quot;Saturday&quot;],shortDays:[&quot;Sun&quot;,&quot;Mon&quot;,&quot;Tue&quot;,&quot;Wed&quot;,&quot;Thu&quot;,&quot;Fri&quot;,&quot;Sat&quot;],months:[&quot;January&quot;,&quot;February&quot;,&quot;March&quot;,&quot;April&quot;,&quot;May&quot;,&quot;June&quot;,&quot;July&quot;,&quot;August&quot;,&quot;September&quot;,&quot;October&quot;,&quot;November&quot;,&quot;December&quot;],shortMonths:[&quot;Jan&quot;,&quot;Feb&quot;,&quot;Mar&quot;,&quot;Apr&quot;,&quot;May&quot;,&quot;Jun&quot;,&quot;Jul&quot;,&quot;Aug&quot;,&quot;Sep&quot;,&quot;Oct&quot;,&quot;Nov&quot;,&quot;Dec&quot;]});Zo.format=ic.numberFormat,Zo.geo={},ue.prototype={s:0,t:0,add:function(n){ie(n,this.t,oc),ie(oc.s,this.s,this),this.s?this.t+=oc.t:this.s=oc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var oc=new ue;Zo.geo.stream=function(n,t){n&amp;&amp;ac.hasOwnProperty(n.type)?ac[n.type](n,t):oe(n,t)};var ac={Feature:function(n,t){oe(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r&lt;u;)oe(e[r].geometry,t)}},cc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r&lt;u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){ae(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r&lt;u;)ae(e[r],t,0)},Polygon:function(n,t){ce(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r&lt;u;)ce(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r&lt;u;)oe(e[r],t)}};Zo.geo.area=function(n){return sc=0,Zo.geo.stream(n,fc),sc};var sc,lc=new ue,fc={sphere:function(){sc+=4*ba},point:v,lineStart:v,lineEnd:v,polygonStart:function(){lc.reset(),fc.lineStart=se},polygonEnd:function(){var n=2*lc;sc+=0&gt;n?4*ba+n:n,fc.lineStart=fc.lineEnd=fc.point=v}};Zo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f&gt;t&amp;&amp;(f=t),t&gt;g&amp;&amp;(g=t)}function t(t,e){var r=le([t*Aa,e*Aa]);if(m){var u=he(m,r),i=[u[1],-u[0],0],o=he(i,u);ve(o),o=de(o);var c=t-p,s=c&gt;0?1:-1,v=o[0]*Ca*s,d=ua(c)&gt;180;if(d^(v&gt;s*p&amp;&amp;s*t&gt;v)){var y=o[1]*Ca;y&gt;g&amp;&amp;(g=y)}else if(v=(v+360)%360-180,d^(v&gt;s*p&amp;&amp;s*t&gt;v)){var y=-o[1]*Ca;f&gt;y&amp;&amp;(f=y)}else f&gt;e&amp;&amp;(f=e),e&gt;g&amp;&amp;(g=e);d?p&gt;t?a(l,t)&gt;a(l,h)&amp;&amp;(h=t):a(t,h)&gt;a(l,h)&amp;&amp;(l=t):h&gt;=l?(l&gt;t&amp;&amp;(l=t),t&gt;h&amp;&amp;(h=t)):t&gt;p?a(l,t)&gt;a(l,h)&amp;&amp;(h=t):a(t,h)&gt;a(l,h)&amp;&amp;(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ua(r)&gt;180?r+(r&gt;0?360:-360):r}else v=n,d=e;fc.point(n,e),t(n,e)}function i(){fc.lineStart()}function o(){u(v,d),fc.lineEnd(),ua(y)&gt;ka&amp;&amp;(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)&lt;0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]&lt;=t[1]?t[0]&lt;=n&amp;&amp;n&lt;=t[1]:n&lt;t[0]||t[1]&lt;n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,fc.polygonStart()},polygonEnd:function(){fc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0&gt;lc?(l=-(h=180),f=-(g=90)):y&gt;ka?g=90:-ka&gt;y&amp;&amp;(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Zo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t&gt;r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])&gt;a(u[0],u[1])&amp;&amp;(u[1]=e[1]),a(e[0],u[1])&gt;a(u[0],u[1])&amp;&amp;(u[0]=e[0])):i.push(u=e);
+for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t&gt;=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))&gt;p&amp;&amp;(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Zo.geo.centroid=function(n){hc=gc=pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,wc);var t=Mc,e=_c,r=bc,u=t*t+e*e+r*r;return Ea&gt;u&amp;&amp;(t=mc,e=yc,r=xc,ka&gt;gc&amp;&amp;(t=pc,e=vc,r=dc),u=t*t+e*e+r*r,Ea&gt;u)?[0/0,0/0]:[Math.atan2(e,t)*Ca,G(r/Math.sqrt(u))*Ca]};var hc,gc,pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc={sphere:v,point:ye,lineStart:Me,lineEnd:_e,polygonStart:function(){wc.lineStart=be},polygonEnd:function(){wc.lineStart=Me}},Sc=Ae(we,Te,Re,[-ba,-ba/2]),kc=1e9;Zo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&amp;&amp;(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ue(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&amp;&amp;(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Zo.geo.conicEqualArea=function(){return He(Fe)}).raw=Fe,Zo.geo.albers=function(){return Zo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Zo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Zo.geo.albers(),o=Zo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Zo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u&gt;=.12&amp;&amp;.234&gt;u&amp;&amp;r&gt;=-.425&amp;&amp;-.214&gt;r?o:u&gt;=.166&amp;&amp;.234&gt;u&amp;&amp;r&gt;=-.214&amp;&amp;-.115&gt;r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+ka,f+.12*s+ka],[l-.214*s-ka,f+.234*s-ka]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+ka,f+.166*s+ka],[l-.115*s-ka,f+.234*s-ka]]).stream(c).point,n},n.scale(1070)};var Ec,Ac,Cc,Nc,zc,Lc,Tc={point:v,lineStart:v,lineEnd:v,polygonStart:function(){Ac=0,Tc.lineStart=Oe},polygonEnd:function(){Tc.lineStart=Tc.lineEnd=Tc.point=v,Ec+=ua(Ac/2)}},qc={point:Ye,lineStart:v,lineEnd:v,polygonStart:v,polygonEnd:v},Rc={point:Ve,lineStart:Xe,lineEnd:$e,polygonStart:function(){Rc.lineStart=Be},polygonEnd:function(){Rc.point=Ve,Rc.lineStart=Xe,Rc.lineEnd=$e}};Zo.geo.path=function(){function n(n){return n&amp;&amp;(&quot;function&quot;==typeof a&amp;&amp;i.pointRadius(+a.apply(this,arguments)),o&amp;&amp;o.valid||(o=u(i)),Zo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ec=0,Zo.geo.stream(n,u(Tc)),Ec},n.centroid=function(n){return pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,u(Rc)),bc?[Mc/bc,_c/bc]:xc?[mc/xc,yc/xc]:dc?[pc/dc,vc/dc]:[0/0,0/0]},n.bounds=function(n){return zc=Lc=-(Cc=Nc=1/0),Zo.geo.stream(n,u(qc)),[[Cc,Nc],[zc,Lc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Ge(n):wt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ie:new We(n),&quot;function&quot;!=typeof a&amp;&amp;i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a=&quot;function&quot;==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Zo.geo.albersUsa()).context(null)},Zo.geo.transform=function(n){return{stream:function(t){var e=new Ke(t);for(var r in n)e[r]=n[r];return e}}},Ke.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Zo.geo.projection=nr,Zo.geo.projectionMutator=tr,(Zo.geo.equirectangular=function(){return nr(rr)}).raw=rr.invert=rr,Zo.geo.rotation=function(n){function t(t){return t=n(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t}return n=ir(n[0]%360*Aa,n[1]*Aa,n.length&gt;2?n[2]*Aa:0),t.invert=function(t){return t=n.invert(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t},t},ur.invert=rr,Zo.geo.circle=function(){function n(){var n=&quot;function&quot;==typeof r?r.apply(this,arguments):r,t=ir(-n[0]*Aa,-n[1]*Aa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ca,n[1]*=Ca}}),{type:&quot;Polygon&quot;,coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=sr((t=+r)*Aa,u*Aa),n):t},n.precision=function(r){return arguments.length?(e=sr(t*Aa,(u=+r)*Aa),n):u},n.angle(90)},Zo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Aa,u=n[1]*Aa,i=t[1]*Aa,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Zo.geo.graticule=function(){function n(){return{type:&quot;MultiLineString&quot;,coordinates:t()}}function t(){return Zo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Zo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Zo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ua(n%d)&gt;ka}).map(l)).concat(Zo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ua(n%m)&gt;ka}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:&quot;LineString&quot;,coordinates:n}})},n.outline=function(){return{type:&quot;Polygon&quot;,coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i&gt;u&amp;&amp;(t=i,i=u,u=t),s&gt;c&amp;&amp;(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r&gt;e&amp;&amp;(t=r,r=e,e=t),a&gt;o&amp;&amp;(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=fr(a,o,90),f=hr(r,e,y),h=fr(s,c,90),g=hr(i,u,y),n):y},n.majorExtent([[-180,-90+ka],[180,90-ka]]).minorExtent([[-180,-80-ka],[180,80+ka]])},Zo.geo.greatArc=function(){function n(){return{type:&quot;LineString&quot;,coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=gr,u=pr;return n.distance=function(){return Zo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t=&quot;function&quot;==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e=&quot;function&quot;==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Zo.geo.interpolate=function(n,t){return vr(n[0]*Aa,n[1]*Aa,t[0]*Aa,t[1]*Aa)},Zo.geo.length=function(n){return Dc=0,Zo.geo.stream(n,Pc),Dc};var Dc,Pc={sphere:v,point:v,lineStart:dr,lineEnd:v,polygonStart:v,polygonEnd:v},Uc=mr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Zo.geo.azimuthalEqualArea=function(){return nr(Uc)}).raw=Uc;var jc=mr(function(n){var t=Math.acos(n);return t&amp;&amp;t/Math.sin(t)},wt);(Zo.geo.azimuthalEquidistant=function(){return nr(jc)}).raw=jc,(Zo.geo.conicConformal=function(){return He(yr)}).raw=yr,(Zo.geo.conicEquidistant=function(){return He(xr)}).raw=xr;var Hc=mr(function(n){return 1/n},Math.atan);(Zo.geo.gnomonic=function(){return nr(Hc)}).raw=Hc,Mr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Sa]},(Zo.geo.mercator=function(){return _r(Mr)}).raw=Mr;var Fc=mr(function(){return 1},Math.asin);(Zo.geo.orthographic=function(){return nr(Fc)}).raw=Fc;var Oc=mr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Zo.geo.stereographic=function(){return nr(Oc)}).raw=Oc,br.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Sa]},(Zo.geo.transverseMercator=function(){var n=_r(br),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length&gt;2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=br,Zo.geom={},Zo.geom.hull=function(n){function t(n){if(n.length&lt;3)return[];var t,u=bt(e),i=bt(r),o=n.length,a=[],c=[];for(t=0;o&gt;t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(Er),t=0;o&gt;t;t++)c.push([a[t][0],-a[t][1]]);var s=kr(a),l=kr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t&gt;=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t&lt;l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=wr,r=Sr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Zo.geom.polygon=function(n){return sa(n,Yc),n};var Yc=Zo.geom.polygon.prototype=[];Yc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t&lt;e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Yc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r&lt;u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Yc.clip=function(n){for(var t,e,r,u,i,o,a=Nr(n),c=-1,s=this.length-Nr(this),l=this[s-1];++c&lt;s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e&lt;r;)o=t[e],Ar(o,l,u)?(Ar(i,l,u)||n.push(Cr(i,o,l,u)),n.push(o)):Ar(i,l,u)&amp;&amp;n.push(Cr(i,o,l,u)),i=o;a&amp;&amp;n.push(n[0]),l=u}return n};var Ic,Zc,Vc,Xc,$c,Bc=[],Wc=[];Ur.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&amp;&amp;n.a||t.splice(e,1);return t.sort(Hr),t.length},Wr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Jr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&amp;&amp;(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=nu(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&amp;&amp;e.C;)r=e.U,e===r.L?(u=r.R,u&amp;&amp;u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&amp;&amp;(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Qr(this,r))):(u=r.L,u&amp;&amp;u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&amp;&amp;(Qr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&amp;&amp;(n.N.P=n.P),n.P&amp;&amp;(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?nu(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&amp;&amp;o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&amp;&amp;(n.U=u),!r){if(n&amp;&amp;n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&amp;&amp;(t.C=!1,u.C=!0,Kr(this,u),t=u.R),t.L&amp;&amp;t.L.C||t.R&amp;&amp;t.R.C){t.R&amp;&amp;t.R.C||(t.L.C=!1,t.C=!0,Qr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Kr(this,u),n=this._;break}}else if(t=u.L,t.C&amp;&amp;(t.C=!1,u.C=!0,Qr(this,u),t=u.L),t.L&amp;&amp;t.L.C||t.R&amp;&amp;t.R.C){t.L&amp;&amp;t.L.C||(t.R.C=!1,t.C=!0,Kr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Qr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&amp;&amp;(n.C=!1)}}},Zo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return tu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x&gt;=r&amp;&amp;s.x&lt;=i&amp;&amp;s.y&gt;=u&amp;&amp;s.y&lt;=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/ka)*ka,y:Math.round(o(n,t)/ka)*ka,i:t}})}var r=wr,u=Sr,i=r,o=u,a=Jc;return n?t(n):(t.links=function(n){return tu(e(n)).edges.filter(function(n){return n.l&amp;&amp;n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return tu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Hr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c&lt;s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r&lt;i.i&amp;&amp;r&lt;f.i&amp;&amp;ru(o,i,f)&lt;0&amp;&amp;t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=bt(r=n),t):r},t.y=function(n){return arguments.length?(o=bt(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Jc:n,t):a===Jc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&amp;&amp;[[0,0],n]):a===Jc?null:a&amp;&amp;a[1]},t)};var Jc=[[-1e6,-1e6],[1e6,1e6]];Zo.geom.delaunay=function(n){return Zo.geom.voronoi().triangles(n)},Zo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&amp;&amp;!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(ua(c-e)+ua(l-r)&lt;.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e&gt;=s,h=r&gt;=l,g=(h&lt;&lt;1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=ou()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=bt(a),M=bt(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p&gt;g;++g)l=n[g],l.x&lt;v&amp;&amp;(v=l.x),l.y&lt;d&amp;&amp;(d=l.y),l.x&gt;m&amp;&amp;(m=l.x),l.y&gt;y&amp;&amp;(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p&gt;g;++g){var _=+x(l=n[g],g),b=+M(l,g);v&gt;_&amp;&amp;(v=_),d&gt;b&amp;&amp;(d=b),_&gt;m&amp;&amp;(m=_),b&gt;y&amp;&amp;(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w&gt;S?y=d+w:m=v+S;var k=ou();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){au(n,k,v,d,m,y)},g=-1,null==t){for(;++g&lt;p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=wr,c=Sr;return(o=arguments.length)?(a=uu,c=iu,3===o&amp;&amp;(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Zo.interpolateRgb=cu,Zo.interpolateObject=su,Zo.interpolateNumber=lu,Zo.interpolateString=fu;var Gc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Kc=new RegExp(Gc.source,&quot;g&quot;);Zo.interpolate=hu,Zo.interpolators=[function(n,t){var e=typeof t;return(&quot;string&quot;===e?Ia.has(t)||/^(#|rgb\(|hsl\()/.test(t)?cu:fu:t instanceof et?cu:Array.isArray(t)?gu:&quot;object&quot;===e&amp;&amp;isNaN(t)?su:lu)(n,t)}],Zo.interpolateArray=gu;var Qc=function(){return wt},ns=Zo.map({linear:Qc,poly:Mu,quad:function(){return mu},cubic:function(){return yu},sin:function(){return _u},exp:function(){return bu},circle:function(){return wu},elastic:Su,back:ku,bounce:function(){return Eu}}),ts=Zo.map({&quot;in&quot;:wt,out:vu,&quot;in-out&quot;:du,&quot;out-in&quot;:function(n){return du(vu(n))}});Zo.ease=function(n){var t=n.indexOf(&quot;-&quot;),e=t&gt;=0?n.substring(0,t):n,r=t&gt;=0?n.substring(t+1):&quot;in&quot;;return e=ns.get(e)||Qc,r=ts.get(r)||wt,pu(r(e.apply(null,Vo.call(arguments,1))))},Zo.interpolateHcl=Au,Zo.interpolateHsl=Cu,Zo.interpolateLab=Nu,Zo.interpolateRound=zu,Zo.transform=function(n){var t=$o.createElementNS(Zo.ns.prefix.svg,&quot;g&quot;);return(Zo.transform=function(n){if(null!=n){t.setAttribute(&quot;transform&quot;,n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:es)})(n)},Lu.prototype.toString=function(){return&quot;translate(&quot;+this.translate+&quot;)rotate(&quot;+this.rotate+&quot;)skewX(&quot;+this.skew+&quot;)scale(&quot;+this.scale+&quot;)&quot;};var es={a:1,b:0,c:0,d:1,e:0,f:0};Zo.interpolateTransform=Du,Zo.layout={},Zo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e&lt;r;)t.push(ju(n[e]));return t}},Zo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Zo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h&lt;i;){for(s=0,g=-1;++g&lt;i;)s+=u[h][g];v.push(s),m.push(Zo.range(i)),n+=s}for(o&amp;&amp;d.sort(function(n,t){return o(v[n],v[t])}),a&amp;&amp;m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(wa-l*i)/n,s=0,h=-1;++h&lt;i;){for(f=s,g=-1;++g&lt;i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+&quot;-&quot;+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h&lt;i;)for(g=h-1;++g&lt;i;){var w=p[h+&quot;-&quot;+g],S=p[g+&quot;-&quot;+h];(w.value||S.value)&amp;&amp;e.push(w.value&lt;S.value?{source:S,target:w}:{source:w,target:S})}c&amp;&amp;t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&amp;&amp;u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&amp;&amp;t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Zo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c&gt;a*a/d){if(p&gt;c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&amp;&amp;c&amp;&amp;p&gt;c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Zo.event.x,n.py=Zo.event.y,a.resume()}var e,r,u,i,o,a={},c=Zo.dispatch(&quot;start&quot;,&quot;tick&quot;,&quot;end&quot;),s=[1,1],l=.9,f=rs,h=us,g=-30,p=is,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)&lt;.005)return c.end({type:&quot;end&quot;,alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b&gt;e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&amp;&amp;(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&amp;&amp;(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e&lt;_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Vu(t=Zo.geom.quadtree(m),r,o),e=-1;++e&lt;_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e&lt;_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:&quot;tick&quot;,alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f=&quot;function&quot;==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h=&quot;function&quot;==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g=&quot;function&quot;==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n&gt;0?n:0:n&gt;0&amp;&amp;(c.start({type:&quot;start&quot;,alpha:r=n}),Zo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c&gt;a;++a)e[a]=[];for(a=0;s&gt;a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a&lt;s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c&gt;t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l&gt;t;++t)r=y[t],&quot;number&quot;==typeof r.source&amp;&amp;(r.source=m[r.source]),&quot;number&quot;==typeof r.target&amp;&amp;(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c&gt;t;++t)r=m[t],isNaN(r.x)&amp;&amp;(r.x=n(&quot;x&quot;,p)),isNaN(r.y)&amp;&amp;(r.y=n(&quot;y&quot;,v)),isNaN(r.px)&amp;&amp;(r.px=r.x),isNaN(r.py)&amp;&amp;(r.py=r.y);if(u=[],&quot;function&quot;==typeof f)for(t=0;l&gt;t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l&gt;t;++t)u[t]=f;if(i=[],&quot;function&quot;==typeof h)for(t=0;l&gt;t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l&gt;t;++t)i[t]=h;if(o=[],&quot;function&quot;==typeof g)for(t=0;c&gt;t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c&gt;t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Zo.behavior.drag().origin(wt).on(&quot;dragstart.force&quot;,Ou).on(&quot;drag.force&quot;,t).on(&quot;dragend.force&quot;,Yu)),arguments.length?(this.on(&quot;mouseover.force&quot;,Iu).on(&quot;mouseout.force&quot;,Zu).call(e),void 0):e},Zo.rebind(a,c,&quot;on&quot;)};var rs=20,us=1,is=1/0;Zo.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(s=e.call(n,i,i.depth))&amp;&amp;(c=s.length)){for(var c,s,l;--c&gt;=0;)o.push(l=s[c]),l.parent=i,l.depth=i.depth+1;r&amp;&amp;(i.value=0),i.children=s}else r&amp;&amp;(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Bu(u,function(n){var e,u;t&amp;&amp;(e=n.children)&amp;&amp;e.sort(t),r&amp;&amp;(u=n.parent)&amp;&amp;(u.value+=n.value)}),a}var t=Gu,e=Wu,r=Ju;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&amp;&amp;($u(t,function(n){n.children&amp;&amp;(n.value=0)}),Bu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&amp;&amp;(e.value+=t.value)})),t},n},Zo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&amp;&amp;(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s&lt;o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&amp;&amp;(u=e.length))for(var u,i=-1;++i&lt;u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Zo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Xu(e,r)},Zo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+(&quot;function&quot;==typeof r?r.apply(this,arguments):r),c=((&quot;function&quot;==typeof u?u.apply(this,arguments):u)-a)/Zo.sum(o),s=Zo.range(i.length);null!=e&amp;&amp;s.sort(e===os?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=os,r=0,u=wa;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var os={};Zo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Zo.permute(s,f),l=Zo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m&gt;g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d&gt;h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=wt,e=ei,r=ri,u=ti,i=Qu,o=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e=&quot;function&quot;==typeof t?t:as.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r=&quot;function&quot;==typeof t?t:cs.get(t)||ri,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var as=Zo.map({&quot;inside-out&quot;:function(n){var t,e,r=n.length,u=n.map(ui),i=n.map(ii),o=Zo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r&gt;t;++t)e=o[t],c&gt;a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Zo.range(n.length).reverse()},&quot;default&quot;:ei}),cs=Zo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i&gt;e;++e){for(t=0,r=0;u&gt;t;t++)r+=n[t][e][1];r&gt;a&amp;&amp;(a=r),o.push(r)}for(e=0;i&gt;e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h&gt;e;++e){for(t=0,u=0;l&gt;t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l&gt;t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t&gt;r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s&gt;c&amp;&amp;(s=c)}for(e=0;h&gt;e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i&gt;e;++e){for(t=0,r=0;u&gt;t;t++)r+=n[t][e][1];if(r)for(t=0;u&gt;t;t++)n[t][e][1]/=r;else for(t=0;u&gt;t;t++)n[t][e][1]=o}for(e=0;i&gt;e;++e)a[e]=0;return a},zero:ri});Zo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i&lt;g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g&gt;0)for(i=-1;++i&lt;h;)a=s[i],a&gt;=l[0]&amp;&amp;a&lt;=l[1]&amp;&amp;(o=c[Zo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=si,u=ai;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=bt(t),n):r},n.bins=function(t){return arguments.length?(u=&quot;number&quot;==typeof t?function(n){return ci(n,t)}:bt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Zo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:&quot;function&quot;==typeof t?t:function(){return t};if(a.x=a.y=0,Bu(a,function(n){n.r=+l(n.value)}),Bu(a,pi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;Bu(a,function(n){n.r+=f}),Bu(a,pi),Bu(a,function(n){n.r-=f})}return mi(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Zo.layout.hierarchy().sort(li),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||&quot;function&quot;==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Xu(n,e)},Zo.layout.tree=function(){function n(n,u){var l=o.call(this,n,u),f=l[0],h=t(f);if(Bu(h,e),h.parent.m=-h.z,$u(h,r),s)$u(f,i);else{var g=f,p=f,v=f;$u(f,function(n){n.x&lt;g.x&amp;&amp;(g=n),n.x&gt;p.x&amp;&amp;(p=n),n.depth&gt;v.depth&amp;&amp;(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);$u(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return l}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a&gt;o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&amp;&amp;u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){wi(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&amp;&amp;(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],s=u.m,l=i.m,f=o.m,h=c.m;o=_i(o),u=Mi(u),o&amp;&amp;u;)c=Mi(c),i=_i(i),i.a=n,r=o.z+f-u.z-s+a(o._,u._),r&gt;0&amp;&amp;(bi(Si(o,n,e),n,r),s+=r,l+=r),f+=o.m,s+=u.m,h+=c.m,l+=i.m;o&amp;&amp;!_i(i)&amp;&amp;(i.t=o,i.m+=f-l),u&amp;&amp;!Mi(c)&amp;&amp;(c.t=u,c.m+=s-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=Zo.layout.hierarchy().sort(null).value(null),a=xi,c=[1,1],s=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(s=null==(c=t)?i:null,n):s?null:c},n.nodeSize=function(t){return arguments.length?(s=null==(c=t)?null:i,n):s?c:null},Xu(n,o)},Zo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;Bu(c,function(n){var t=n.children;t&amp;&amp;t.length?(n.x=Ei(t),n.y=ki(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ai(c),f=Ci(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return Bu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Zo.layout.hierarchy().sort(null).value(null),e=xi,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Xu(n,t)},Zo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u&lt;i;)r=(e=n[u]).value*(0&gt;t?0:t),e.area=isNaN(r)||0&gt;=r?0:r}function t(e){var i=e.children;if(i&amp;&amp;i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v=&quot;slice&quot;===g?s.dx:&quot;dice&quot;===g?s.dy:&quot;slice-dice&quot;===g?1&amp;e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)&gt;0;)l.push(o=h[c-1]),l.area+=o.area,&quot;squarify&quot;!==g||(a=r(l,v))&lt;=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&amp;&amp;(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&amp;&amp;r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&amp;&amp;(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o&lt;a;)(e=n[o].area)&amp;&amp;(i&gt;e&amp;&amp;(i=e),e&gt;u&amp;&amp;(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l&gt;e.dy)&amp;&amp;(l=e.dy);++i&lt;o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l&gt;e.dx)&amp;&amp;(l=e.dx);++i&lt;o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&amp;&amp;a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&amp;&amp;(o=u),u}var o,a=Zo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ni,h=!1,g=&quot;squarify&quot;,p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ni(t):zi(t,&quot;number&quot;==typeof e?[e,e,e,e]:e)}function e(t){return zi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ni:&quot;function&quot;==(r=typeof n)?t:&quot;number&quot;===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+&quot;&quot;,i):g},Xu(i,a)},Zo.random={normal:function(n,t){var e=arguments.length;return 2&gt;e&amp;&amp;(t=1),1&gt;e&amp;&amp;(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u&gt;1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Zo.random.normal.apply(Zo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Zo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n&gt;e;e++)t+=Math.random();return t}}},Zo.scale={};var ss={floor:wt,ceil:wt};Zo.scale.linear=function(){return Ui([0,1],[0,1],hu,!1)};var ls={s:1,g:1,p:1,r:1,e:1};Zo.scale.log=function(){return Vi(Zo.scale.linear().domain([0,1]),10,!0,[1,10])};var fs=Zo.format(&quot;.0e&quot;),hs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Zo.scale.pow=function(){return Xi(Zo.scale.linear(),1,[0,1])},Zo.scale.sqrt=function(){return Zo.scale.pow().exponent(.5)},Zo.scale.ordinal=function(){return Bi([],{t:&quot;range&quot;,a:[[]]})},Zo.scale.category10=function(){return Zo.scale.ordinal().range(gs)},Zo.scale.category20=function(){return Zo.scale.ordinal().range(ps)},Zo.scale.category20b=function(){return Zo.scale.ordinal().range(vs)},Zo.scale.category20c=function(){return Zo.scale.ordinal().range(ds)};var gs=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(vt),ps=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(vt),vs=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(vt),ds=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(vt);Zo.scale.quantile=function(){return Wi([],[])},Zo.scale.quantize=function(){return Ji(0,1,[0,1])},Zo.scale.threshold=function(){return Gi([.5],[0,1])},Zo.scale.identity=function(){return Ki([0,1])},Zo.svg={},Zo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ms,a=u.apply(this,arguments)+ms,c=(o&gt;a&amp;&amp;(c=o,o=a,a=c),a-o),s=ba&gt;c?&quot;0&quot;:&quot;1&quot;,l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);
+return c&gt;=ys?n?&quot;M0,&quot;+i+&quot;A&quot;+i+&quot;,&quot;+i+&quot; 0 1,1 0,&quot;+-i+&quot;A&quot;+i+&quot;,&quot;+i+&quot; 0 1,1 0,&quot;+i+&quot;M0,&quot;+n+&quot;A&quot;+n+&quot;,&quot;+n+&quot; 0 1,0 0,&quot;+-n+&quot;A&quot;+n+&quot;,&quot;+n+&quot; 0 1,0 0,&quot;+n+&quot;Z&quot;:&quot;M0,&quot;+i+&quot;A&quot;+i+&quot;,&quot;+i+&quot; 0 1,1 0,&quot;+-i+&quot;A&quot;+i+&quot;,&quot;+i+&quot; 0 1,1 0,&quot;+i+&quot;Z&quot;:n?&quot;M&quot;+i*l+&quot;,&quot;+i*f+&quot;A&quot;+i+&quot;,&quot;+i+&quot; 0 &quot;+s+&quot;,1 &quot;+i*h+&quot;,&quot;+i*g+&quot;L&quot;+n*h+&quot;,&quot;+n*g+&quot;A&quot;+n+&quot;,&quot;+n+&quot; 0 &quot;+s+&quot;,0 &quot;+n*l+&quot;,&quot;+n*f+&quot;Z&quot;:&quot;M&quot;+i*l+&quot;,&quot;+i*f+&quot;A&quot;+i+&quot;,&quot;+i+&quot; 0 &quot;+s+&quot;,1 &quot;+i*h+&quot;,&quot;+i*g+&quot;L0,0&quot;+&quot;Z&quot;}var t=Qi,e=no,r=to,u=eo;return n.innerRadius=function(e){return arguments.length?(t=bt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=bt(t),n):e},n.startAngle=function(t){return arguments.length?(r=bt(t),n):r},n.endAngle=function(t){return arguments.length?(u=bt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ms;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ms=-Sa,ys=wa-ka;Zo.svg.line=function(){return ro(wt)};var xs=Zo.map({linear:uo,&quot;linear-closed&quot;:io,step:oo,&quot;step-before&quot;:ao,&quot;step-after&quot;:co,basis:po,&quot;basis-open&quot;:vo,&quot;basis-closed&quot;:mo,bundle:yo,cardinal:fo,&quot;cardinal-open&quot;:so,&quot;cardinal-closed&quot;:lo,monotone:So});xs.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Ms=[0,2/3,1/3,0],_s=[0,1/3,2/3,0],bs=[0,1/6,2/3,1/6];Zo.svg.line.radial=function(){var n=ro(ko);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},ao.reverse=co,co.reverse=ao,Zo.svg.area=function(){return Eo(wt)},Zo.svg.area.radial=function(){var n=Eo(ko);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Zo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return&quot;M&quot;+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+&quot;Z&quot;}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ms,l=s.call(n,u,r)+ms;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&amp;&amp;n.a1==t.a1}function r(n,t,e){return&quot;A&quot;+n+&quot;,&quot;+n+&quot; 0 &quot;+ +(e&gt;ba)+&quot;,1 &quot;+t}function u(n,t,e,r){return&quot;Q 0,0 &quot;+r}var i=gr,o=pr,a=Ao,c=to,s=eo;return n.radius=function(t){return arguments.length?(a=bt(t),n):a},n.source=function(t){return arguments.length?(i=bt(t),n):i},n.target=function(t){return arguments.length?(o=bt(t),n):o},n.startAngle=function(t){return arguments.length?(c=bt(t),n):c},n.endAngle=function(t){return arguments.length?(s=bt(t),n):s},n},Zo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),&quot;M&quot;+c[0]+&quot;C&quot;+c[1]+&quot; &quot;+c[2]+&quot; &quot;+c[3]}var t=gr,e=pr,r=Co;return n.source=function(e){return arguments.length?(t=bt(e),n):t},n.target=function(t){return arguments.length?(e=bt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Zo.svg.diagonal.radial=function(){var n=Zo.svg.diagonal(),t=Co,e=n.projection;return n.projection=function(n){return arguments.length?e(No(t=n)):t},n},Zo.svg.symbol=function(){function n(n,r){return(ws.get(t.call(this,n,r))||To)(e.call(this,n,r))}var t=Lo,e=zo;return n.type=function(e){return arguments.length?(t=bt(e),n):t},n.size=function(t){return arguments.length?(e=bt(t),n):e},n};var ws=Zo.map({circle:To,cross:function(n){var t=Math.sqrt(n/5)/2;return&quot;M&quot;+-3*t+&quot;,&quot;+-t+&quot;H&quot;+-t+&quot;V&quot;+-3*t+&quot;H&quot;+t+&quot;V&quot;+-t+&quot;H&quot;+3*t+&quot;V&quot;+t+&quot;H&quot;+t+&quot;V&quot;+3*t+&quot;H&quot;+-t+&quot;V&quot;+t+&quot;H&quot;+-3*t+&quot;Z&quot;},diamond:function(n){var t=Math.sqrt(n/(2*As)),e=t*As;return&quot;M0,&quot;+-t+&quot;L&quot;+e+&quot;,0&quot;+&quot; 0,&quot;+t+&quot; &quot;+-e+&quot;,0&quot;+&quot;Z&quot;},square:function(n){var t=Math.sqrt(n)/2;return&quot;M&quot;+-t+&quot;,&quot;+-t+&quot;L&quot;+t+&quot;,&quot;+-t+&quot; &quot;+t+&quot;,&quot;+t+&quot; &quot;+-t+&quot;,&quot;+t+&quot;Z&quot;},&quot;triangle-down&quot;:function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return&quot;M0,&quot;+e+&quot;L&quot;+t+&quot;,&quot;+-e+&quot; &quot;+-t+&quot;,&quot;+-e+&quot;Z&quot;},&quot;triangle-up&quot;:function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return&quot;M0,&quot;+-e+&quot;L&quot;+t+&quot;,&quot;+e+&quot; &quot;+-t+&quot;,&quot;+e+&quot;Z&quot;}});Zo.svg.symbolTypes=ws.keys();var Ss,ks,Es=Math.sqrt(3),As=Math.tan(30*Aa),Cs=[],Ns=0;Cs.call=pa.call,Cs.empty=pa.empty,Cs.node=pa.node,Cs.size=pa.size,Zo.transition=function(n){return arguments.length?Ss?n.transition():n:ma.transition()},Zo.transition.prototype=Cs,Cs.select=function(n){var t,e,r,u=this.id,i=[];n=b(n);for(var o=-1,a=this.length;++o&lt;a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s&lt;l;)(r=c[s])&amp;&amp;(e=n.call(r,r.__data__,s,o))?(&quot;__data__&quot;in r&amp;&amp;(e.__data__=r.__data__),Po(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return qo(i,u)},Cs.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=w(n);for(var c=-1,s=this.length;++c&lt;s;)for(var l=this[c],f=-1,h=l.length;++f&lt;h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g&lt;p;)(u=e[g])&amp;&amp;Po(u,g,o,i),t.push(u)}return qo(a,o)},Cs.filter=function(n){var t,e,r,u=[];&quot;function&quot;!=typeof n&amp;&amp;(n=R(n));for(var i=0,o=this.length;o&gt;i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c&gt;a;a++)(r=e[a])&amp;&amp;n.call(r,r.__data__,a,i)&amp;&amp;t.push(r)}return qo(u,this.id)},Cs.tween=function(n,t){var e=this.id;return arguments.length&lt;2?this.node().__transition__[e].tween.get(n):P(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Cs.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+=&quot;&quot;,function(){var t,e=this.getAttribute(a);return e!==n&amp;&amp;(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+=&quot;&quot;,function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&amp;&amp;(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length&lt;2){for(t in n)this.attr(t,n[t]);return this}var o=&quot;transform&quot;==n?Du:hu,a=Zo.ns.qualify(n);return Ro(this,&quot;attr.&quot;+n,t,a.local?i:u)},Cs.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&amp;&amp;function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&amp;&amp;function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Zo.ns.qualify(n);return this.tween(&quot;attr.&quot;+n,u.local?r:e)},Cs.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+=&quot;&quot;,function(){var r,u=Wo.getComputedStyle(this,null).getPropertyValue(n);return u!==t&amp;&amp;(r=hu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3&gt;i){if(&quot;string&quot;!=typeof n){2&gt;i&amp;&amp;(t=&quot;&quot;);for(e in n)this.style(e,n[e],t);return this}e=&quot;&quot;}return Ro(this,&quot;style.&quot;+n,t,u)},Cs.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Wo.getComputedStyle(this,null).getPropertyValue(n));return i&amp;&amp;function(t){this.style.setProperty(n,i(t),e)}}return arguments.length&lt;3&amp;&amp;(e=&quot;&quot;),this.tween(&quot;style.&quot;+n,r)},Cs.text=function(n){return Ro(this,&quot;text&quot;,n,Do)},Cs.remove=function(){return this.each(&quot;end.transition&quot;,function(){var n;this.__transition__.count&lt;2&amp;&amp;(n=this.parentNode)&amp;&amp;n.removeChild(this)})},Cs.ease=function(n){var t=this.id;return arguments.length&lt;1?this.node().__transition__[t].ease:(&quot;function&quot;!=typeof n&amp;&amp;(n=Zo.ease.apply(Zo,arguments)),P(this,function(e){e.__transition__[t].ease=n}))},Cs.delay=function(n){var t=this.id;return arguments.length&lt;1?this.node().__transition__[t].delay:P(this,&quot;function&quot;==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Cs.duration=function(n){var t=this.id;return arguments.length&lt;1?this.node().__transition__[t].duration:P(this,&quot;function&quot;==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Cs.each=function(n,t){var e=this.id;if(arguments.length&lt;2){var r=ks,u=Ss;Ss=e,P(this,function(t,r,u){ks=t.__transition__[e],n.call(t,t.__data__,r,u)}),ks=r,Ss=u}else P(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Zo.dispatch(&quot;start&quot;,&quot;end&quot;))).on(n,t)});return this},Cs.transition=function(){for(var n,t,e,r,u=this.id,i=++Ns,o=[],a=0,c=this.length;c&gt;a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l&gt;s;s++)(e=t[s])&amp;&amp;(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Po(e,s,i,r)),n.push(e)}return qo(o,i)},Zo.svg.axis=function(){function n(n){n.each(function(){var n,s=Zo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):wt:t,p=s.selectAll(&quot;.tick&quot;).data(h,f),v=p.enter().insert(&quot;g&quot;,&quot;.domain&quot;).attr(&quot;class&quot;,&quot;tick&quot;).style(&quot;opacity&quot;,ka),d=Zo.transition(p.exit()).style(&quot;opacity&quot;,ka).remove(),m=Zo.transition(p.order()).style(&quot;opacity&quot;,1),y=Ti(f),x=s.selectAll(&quot;.domain&quot;).data([0]),M=(x.enter().append(&quot;path&quot;).attr(&quot;class&quot;,&quot;domain&quot;),Zo.transition(x));v.append(&quot;line&quot;),v.append(&quot;text&quot;);var _=v.select(&quot;line&quot;),b=m.select(&quot;line&quot;),w=p.select(&quot;text&quot;).text(g),S=v.select(&quot;text&quot;),k=m.select(&quot;text&quot;);switch(r){case&quot;bottom&quot;:n=Uo,_.attr(&quot;y2&quot;,u),S.attr(&quot;y&quot;,Math.max(u,0)+o),b.attr(&quot;x2&quot;,0).attr(&quot;y2&quot;,u),k.attr(&quot;x&quot;,0).attr(&quot;y&quot;,Math.max(u,0)+o),w.attr(&quot;dy&quot;,&quot;.71em&quot;).style(&quot;text-anchor&quot;,&quot;middle&quot;),M.attr(&quot;d&quot;,&quot;M&quot;+y[0]+&quot;,&quot;+i+&quot;V0H&quot;+y[1]+&quot;V&quot;+i);break;case&quot;top&quot;:n=Uo,_.attr(&quot;y2&quot;,-u),S.attr(&quot;y&quot;,-(Math.max(u,0)+o)),b.attr(&quot;x2&quot;,0).attr(&quot;y2&quot;,-u),k.attr(&quot;x&quot;,0).attr(&quot;y&quot;,-(Math.max(u,0)+o)),w.attr(&quot;dy&quot;,&quot;0em&quot;).style(&quot;text-anchor&quot;,&quot;middle&quot;),M.attr(&quot;d&quot;,&quot;M&quot;+y[0]+&quot;,&quot;+-i+&quot;V0H&quot;+y[1]+&quot;V&quot;+-i);break;case&quot;left&quot;:n=jo,_.attr(&quot;x2&quot;,-u),S.attr(&quot;x&quot;,-(Math.max(u,0)+o)),b.attr(&quot;x2&quot;,-u).attr(&quot;y2&quot;,0),k.attr(&quot;x&quot;,-(Math.max(u,0)+o)).attr(&quot;y&quot;,0),w.attr(&quot;dy&quot;,&quot;.32em&quot;).style(&quot;text-anchor&quot;,&quot;end&quot;),M.attr(&quot;d&quot;,&quot;M&quot;+-i+&quot;,&quot;+y[0]+&quot;H0V&quot;+y[1]+&quot;H&quot;+-i);break;case&quot;right&quot;:n=jo,_.attr(&quot;x2&quot;,u),S.attr(&quot;x&quot;,Math.max(u,0)+o),b.attr(&quot;x2&quot;,u).attr(&quot;y2&quot;,0),k.attr(&quot;x&quot;,Math.max(u,0)+o).attr(&quot;y&quot;,0),w.attr(&quot;dy&quot;,&quot;.32em&quot;).style(&quot;text-anchor&quot;,&quot;start&quot;),M.attr(&quot;d&quot;,&quot;M&quot;+i+&quot;,&quot;+y[0]+&quot;H0V&quot;+y[1]+&quot;H&quot;+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Zo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Ls?t+&quot;&quot;:zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&amp;&amp;n},n};var zs=&quot;bottom&quot;,Ls={top:1,right:1,bottom:1,left:1};Zo.svg.brush=function(){function n(i){i.each(function(){var i=Zo.select(this).style(&quot;pointer-events&quot;,&quot;all&quot;).style(&quot;-webkit-tap-highlight-color&quot;,&quot;rgba(0,0,0,0)&quot;).on(&quot;mousedown.brush&quot;,u).on(&quot;touchstart.brush&quot;,u),o=i.selectAll(&quot;.background&quot;).data([0]);o.enter().append(&quot;rect&quot;).attr(&quot;class&quot;,&quot;background&quot;).style(&quot;visibility&quot;,&quot;hidden&quot;).style(&quot;cursor&quot;,&quot;crosshair&quot;),i.selectAll(&quot;.extent&quot;).data([0]).enter().append(&quot;rect&quot;).attr(&quot;class&quot;,&quot;extent&quot;).style(&quot;cursor&quot;,&quot;move&quot;);var a=i.selectAll(&quot;.resize&quot;).data(p,wt);a.exit().remove(),a.enter().append(&quot;g&quot;).attr(&quot;class&quot;,function(n){return&quot;resize &quot;+n}).style(&quot;cursor&quot;,function(n){return Ts[n]}).append(&quot;rect&quot;).attr(&quot;x&quot;,function(n){return/[ew]$/.test(n)?-3:null}).attr(&quot;y&quot;,function(n){return/^[ns]/.test(n)?-3:null}).attr(&quot;width&quot;,6).attr(&quot;height&quot;,6).style(&quot;visibility&quot;,&quot;hidden&quot;),a.style(&quot;display&quot;,n.empty()?&quot;none&quot;:null);var l,f=Zo.transition(i),h=Zo.transition(o);c&amp;&amp;(l=Ti(c),h.attr(&quot;x&quot;,l[0]).attr(&quot;width&quot;,l[1]-l[0]),e(f)),s&amp;&amp;(l=Ti(s),h.attr(&quot;y&quot;,l[0]).attr(&quot;height&quot;,l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(&quot;.resize&quot;).attr(&quot;transform&quot;,function(n){return&quot;translate(&quot;+l[+/e$/.test(n)]+&quot;,&quot;+f[+/^s/.test(n)]+&quot;)&quot;})}function e(n){n.select(&quot;.extent&quot;).attr(&quot;x&quot;,l[0]),n.selectAll(&quot;.extent,.n&gt;rect,.s&gt;rect&quot;).attr(&quot;width&quot;,l[1]-l[0])}function r(n){n.select(&quot;.extent&quot;).attr(&quot;y&quot;,f[0]),n.selectAll(&quot;.extent,.e&gt;rect,.w&gt;rect&quot;).attr(&quot;height&quot;,f[1]-f[0])}function u(){function u(){32==Zo.event.keyCode&amp;&amp;(C||(x=null,z[0]-=l[1],z[1]-=f[1],C=2),y())}function p(){32==Zo.event.keyCode&amp;&amp;2==C&amp;&amp;(z[0]+=l[1],z[1]+=f[1],C=0,y())}function v(){var n=Zo.mouse(_),u=!1;M&amp;&amp;(n[0]+=M[0],n[1]+=M[1]),C||(Zo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),z[0]=l[+(n[0]&lt;x[0])],z[1]=f[+(n[1]&lt;x[1])]):x=null),E&amp;&amp;d(n,c,0)&amp;&amp;(e(S),u=!0),A&amp;&amp;d(n,s,1)&amp;&amp;(r(S),u=!0),u&amp;&amp;(t(S),w({type:&quot;brush&quot;,mode:C?&quot;move&quot;:&quot;resize&quot;}))}function d(n,t,e){var r,u,a=Ti(t),c=a[0],s=a[1],p=z[e],v=e?f:l,d=v[1]-v[0];return C&amp;&amp;(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&amp;&amp;(p=Math.max(c,Math.min(s,2*x[e]-r))),r&gt;p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function m(){v(),S.style(&quot;pointer-events&quot;,&quot;all&quot;).selectAll(&quot;.resize&quot;).style(&quot;display&quot;,n.empty()?&quot;none&quot;:null),Zo.select(&quot;body&quot;).style(&quot;cursor&quot;,null),L.on(&quot;mousemove.brush&quot;,null).on(&quot;mouseup.brush&quot;,null).on(&quot;touchmove.brush&quot;,null).on(&quot;touchend.brush&quot;,null).on(&quot;keydown.brush&quot;,null).on(&quot;keyup.brush&quot;,null),N(),w({type:&quot;brushend&quot;})}var x,M,_=this,b=Zo.select(Zo.event.target),w=a.of(_,arguments),S=Zo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&amp;&amp;c,A=!/^(e|w)$/.test(k)&amp;&amp;s,C=b.classed(&quot;extent&quot;),N=I(),z=Zo.mouse(_),L=Zo.select(Wo).on(&quot;keydown.brush&quot;,u).on(&quot;keyup.brush&quot;,p);if(Zo.event.changedTouches?L.on(&quot;touchmove.brush&quot;,v).on(&quot;touchend.brush&quot;,m):L.on(&quot;mousemove.brush&quot;,v).on(&quot;mouseup.brush&quot;,m),S.interrupt().selectAll(&quot;*&quot;).interrupt(),C)z[0]=l[0]-z[0],z[1]=f[0]-z[1];else if(k){var T=+/w$/.test(k),q=+/^n/.test(k);M=[l[1-T]-z[0],f[1-q]-z[1]],z[0]=l[T],z[1]=f[q]}else Zo.event.altKey&amp;&amp;(x=z.slice());S.style(&quot;pointer-events&quot;,&quot;none&quot;).selectAll(&quot;.resize&quot;).style(&quot;display&quot;,null),Zo.select(&quot;body&quot;).style(&quot;cursor&quot;,b.style(&quot;cursor&quot;)),w({type:&quot;brushstart&quot;}),v()}var i,o,a=M(n,&quot;brushstart&quot;,&quot;brush&quot;,&quot;brushend&quot;),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=qs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Ss?Zo.select(this).transition().each(&quot;start.brush&quot;,function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:&quot;brushstart&quot;})}).tween(&quot;brush:brush&quot;,function(){var e=gu(l,t.x),r=gu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:&quot;brush&quot;,mode:&quot;resize&quot;})}}).each(&quot;end.brush&quot;,function(){i=t.i,o=t.j,n({type:&quot;brush&quot;,mode:&quot;resize&quot;}),n({type:&quot;brushend&quot;})}):(n({type:&quot;brushstart&quot;}),n({type:&quot;brush&quot;,mode:&quot;resize&quot;}),n({type:&quot;brushend&quot;}))})},n.x=function(t){return arguments.length?(c=t,p=qs[!c&lt;&lt;1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=qs[!c&lt;&lt;1|!s],n):s},n.clamp=function(t){return arguments.length?(c&amp;&amp;s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&amp;&amp;(g=!!t),n):c&amp;&amp;s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&amp;&amp;(e=t[0],r=t[1],s&amp;&amp;(e=e[0],r=r[0]),i=[e,r],c.invert&amp;&amp;(e=c(e),r=c(r)),e&gt;r&amp;&amp;(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&amp;&amp;(l=[e,r])),s&amp;&amp;(u=t[0],a=t[1],c&amp;&amp;(u=u[1],a=a[1]),o=[u,a],s.invert&amp;&amp;(u=s(u),a=s(a)),u&gt;a&amp;&amp;(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&amp;&amp;(f=[u,a])),n):(c&amp;&amp;(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&amp;&amp;(e=c.invert(e),r=c.invert(r)),e&gt;r&amp;&amp;(h=e,e=r,r=h))),s&amp;&amp;(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&amp;&amp;(u=s.invert(u),a=s.invert(a)),u&gt;a&amp;&amp;(h=u,u=a,a=h))),c&amp;&amp;s?[[e,u],[r,a]]:c?[e,r]:s&amp;&amp;[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&amp;&amp;l[0]==l[1]||!!s&amp;&amp;f[0]==f[1]},Zo.rebind(n,a,&quot;on&quot;)};var Ts={n:&quot;ns-resize&quot;,e:&quot;ew-resize&quot;,s:&quot;ns-resize&quot;,w:&quot;ew-resize&quot;,nw:&quot;nwse-resize&quot;,ne:&quot;nesw-resize&quot;,se:&quot;nwse-resize&quot;,sw:&quot;nesw-resize&quot;},qs=[[&quot;n&quot;,&quot;e&quot;,&quot;s&quot;,&quot;w&quot;,&quot;nw&quot;,&quot;ne&quot;,&quot;se&quot;,&quot;sw&quot;],[&quot;e&quot;,&quot;w&quot;],[&quot;n&quot;,&quot;s&quot;],[]],Rs=Qa.format=ic.timeFormat,Ds=Rs.utc,Ps=Ds(&quot;%Y-%m-%dT%H:%M:%S.%LZ&quot;);Rs.iso=Date.prototype.toISOString&amp;&amp;+new Date(&quot;2000-01-01T00:00:00.000Z&quot;)?Ho:Ps,Ho.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Ho.toString=Ps.toString,Qa.second=Dt(function(n){return new nc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Qa.seconds=Qa.second.range,Qa.seconds.utc=Qa.second.utc.range,Qa.minute=Dt(function(n){return new nc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Qa.minutes=Qa.minute.range,Qa.minutes.utc=Qa.minute.utc.range,Qa.hour=Dt(function(n){var t=n.getTimezoneOffset()/60;return new nc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Qa.hours=Qa.hour.range,Qa.hours.utc=Qa.hour.utc.range,Qa.month=Dt(function(n){return n=Qa.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Qa.months=Qa.month.range,Qa.months.utc=Qa.month.utc.range;var Us=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],js=[[Qa.second,1],[Qa.second,5],[Qa.second,15],[Qa.second,30],[Qa.minute,1],[Qa.minute,5],[Qa.minute,15],[Qa.minute,30],[Qa.hour,1],[Qa.hour,3],[Qa.hour,6],[Qa.hour,12],[Qa.day,1],[Qa.day,2],[Qa.week,1],[Qa.month,1],[Qa.month,3],[Qa.year,1]],Hs=Rs.multi([[&quot;.%L&quot;,function(n){return n.getMilliseconds()}],[&quot;:%S&quot;,function(n){return n.getSeconds()}],[&quot;%I:%M&quot;,function(n){return n.getMinutes()}],[&quot;%I %p&quot;,function(n){return n.getHours()}],[&quot;%a %d&quot;,function(n){return n.getDay()&amp;&amp;1!=n.getDate()}],[&quot;%b %d&quot;,function(n){return 1!=n.getDate()}],[&quot;%B&quot;,function(n){return n.getMonth()}],[&quot;%Y&quot;,we]]),Fs={range:function(n,t,e){return Zo.range(Math.ceil(n/e)*e,+t,e).map(Oo)},floor:wt,ceil:wt};js.year=Qa.year,Qa.scale=function(){return Fo(Zo.scale.linear(),js,Hs)};var Os=js.map(function(n){return[n[0].utc,n[1]]}),Ys=Ds.multi([[&quot;.%L&quot;,function(n){return n.getUTCMilliseconds()}],[&quot;:%S&quot;,function(n){return n.getUTCSeconds()}],[&quot;%I:%M&quot;,function(n){return n.getUTCMinutes()}],[&quot;%I %p&quot;,function(n){return n.getUTCHours()}],[&quot;%a %d&quot;,function(n){return n.getUTCDay()&amp;&amp;1!=n.getUTCDate()}],[&quot;%b %d&quot;,function(n){return 1!=n.getUTCDate()}],[&quot;%B&quot;,function(n){return n.getUTCMonth()}],[&quot;%Y&quot;,we]]);Os.year=Qa.year.utc,Qa.scale.utc=function(){return Fo(Zo.scale.linear(),Os,Ys)},Zo.text=St(function(n){return n.responseText}),Zo.json=function(n,t){return kt(n,&quot;application/json&quot;,Yo,t)},Zo.html=function(n,t){return kt(n,&quot;text/html&quot;,Io,t)},Zo.xml=St(function(n){return n.responseXML}),&quot;function&quot;==typeof define&amp;&amp;define.amd?define(Zo):&quot;object&quot;==typeof module&amp;&amp;module.exports&amp;&amp;(module.exports=Zo),this.d3=Zo}();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/d3/d3.min.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsemberdatajs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/ember-data.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/ember-data.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/ember-data.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,12053 @@
</span><ins>+/*!
+ * @overview  Ember Data
+ * @copyright Copyright 2011-2014 Tilde Inc. and contributors.
+ *            Portions Copyright 2011 LivingSocial Inc.
+ * @license   Licensed under MIT license (see license.js)
+ * @version   1.0.0-beta.8.2a68c63a
+ */
+(function(global) {
+var define, requireModule, require, requirejs;
+
+(function() {
+  var registry = {}, seen = {};
+
+  define = function(name, deps, callback) {
+    registry[name] = { deps: deps, callback: callback };
+  };
+
+  requirejs = require = requireModule = function(name) {
+  requirejs._eak_seen = registry;
+
+    if (seen[name]) { return seen[name]; }
+    seen[name] = {};
+
+    if (!registry[name]) {
+      throw new Error(&quot;Could not find module &quot; + name);
+    }
+
+    var mod = registry[name],
+        deps = mod.deps,
+        callback = mod.callback,
+        reified = [],
+        exports;
+
+    for (var i=0, l=deps.length; i&lt;l; i++) {
+      if (deps[i] === 'exports') {
+        reified.push(exports = {});
+      } else {
+        reified.push(requireModule(resolve(deps[i])));
+      }
+    }
+
+    var value = callback.apply(this, reified);
+    return seen[name] = exports || value;
+
+    function resolve(child) {
+      if (child.charAt(0) !== '.') { return child; }
+      var parts = child.split(&quot;/&quot;);
+      var parentBase = name.split(&quot;/&quot;).slice(0, -1);
+
+      for (var i=0, l=parts.length; i&lt;l; i++) {
+        var part = parts[i];
+
+        if (part === '..') { parentBase.pop(); }
+        else if (part === '.') { continue; }
+        else { parentBase.push(part); }
+      }
+
+      return parentBase.join(&quot;/&quot;);
+    }
+  };
+})();
+
+define(&quot;activemodel-adapter/lib/main&quot;, 
+  [&quot;./system&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var ActiveModelAdapter = __dependency1__.ActiveModelAdapter;
+    var ActiveModelSerializer = __dependency1__.ActiveModelSerializer;
+    var EmbeddedRecordsMixin = __dependency1__.EmbeddedRecordsMixin;
+
+    __exports__.ActiveModelAdapter = ActiveModelAdapter;
+    __exports__.ActiveModelSerializer = ActiveModelSerializer;
+    __exports__.EmbeddedRecordsMixin = EmbeddedRecordsMixin;
+  });
+define(&quot;activemodel-adapter/lib/setup-container&quot;, 
+  [&quot;../../ember-data/lib/system/container_proxy&quot;,&quot;./system/active_model_serializer&quot;,&quot;./system/active_model_adapter&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+    &quot;use strict&quot;;
+    var ContainerProxy = __dependency1__[&quot;default&quot;];
+    var ActiveModelSerializer = __dependency2__[&quot;default&quot;];
+    var ActiveModelAdapter = __dependency3__[&quot;default&quot;];
+
+    __exports__[&quot;default&quot;] = function setupActiveModelAdapter(container, application){
+      var proxy = new ContainerProxy(container);
+      proxy.registerDeprecations([
+        {deprecated: 'serializer:_ams',  valid: 'serializer:-active-model'},
+        {deprecated: 'adapter:_ams',     valid: 'adapter:-active-model'}
+      ]);
+
+      container.register('serializer:-active-model', ActiveModelSerializer);
+      container.register('adapter:-active-model', ActiveModelAdapter);
+    };
+  });
+define(&quot;activemodel-adapter/lib/system&quot;, 
+  [&quot;./system/embedded_records_mixin&quot;,&quot;./system/active_model_adapter&quot;,&quot;./system/active_model_serializer&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+    &quot;use strict&quot;;
+    var EmbeddedRecordsMixin = __dependency1__[&quot;default&quot;];
+    var ActiveModelAdapter = __dependency2__[&quot;default&quot;];
+    var ActiveModelSerializer = __dependency3__[&quot;default&quot;];
+
+    __exports__.EmbeddedRecordsMixin = EmbeddedRecordsMixin;
+    __exports__.ActiveModelAdapter = ActiveModelAdapter;
+    __exports__.ActiveModelSerializer = ActiveModelSerializer;
+  });
+define(&quot;activemodel-adapter/lib/system/active_model_adapter&quot;, 
+  [&quot;../../../ember-data/lib/adapters&quot;,&quot;../../../ember-data/lib/system/adapter&quot;,&quot;../../../ember-inflector/lib/main&quot;,&quot;./active_model_serializer&quot;,&quot;./embedded_records_mixin&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+    &quot;use strict&quot;;
+    var RESTAdapter = __dependency1__.RESTAdapter;
+    var InvalidError = __dependency2__.InvalidError;
+    var pluralize = __dependency3__.pluralize;
+    var ActiveModelSerializer = __dependency4__[&quot;default&quot;];
+    var EmbeddedRecordsMixin = __dependency5__[&quot;default&quot;];
+
+    /**
+      @module ember-data
+    */
+
+    var forEach = Ember.EnumerableUtils.forEach;
+    var decamelize = Ember.String.decamelize,
+        underscore = Ember.String.underscore;
+
+    /**
+      The ActiveModelAdapter is a subclass of the RESTAdapter designed to integrate
+      with a JSON API that uses an underscored naming convention instead of camelCasing.
+      It has been designed to work out of the box with the
+      [active_model_serializers](http://github.com/rails-api/active_model_serializers)
+      Ruby gem. This Adapter expects specific settings using ActiveModel::Serializers,
+      `embed :ids, include: true` which sideloads the records.
+
+      This adapter extends the DS.RESTAdapter by making consistent use of the camelization,
+      decamelization and pluralization methods to normalize the serialized JSON into a
+      format that is compatible with a conventional Rails backend and Ember Data.
+
+      ## JSON Structure
+
+      The ActiveModelAdapter expects the JSON returned from your server to follow
+      the REST adapter conventions substituting underscored keys for camelcased ones.
+
+      ### Conventional Names
+
+      Attribute names in your JSON payload should be the underscored versions of
+      the attributes in your Ember.js models.
+
+      For example, if you have a `Person` model:
+
+      ```js
+      App.FamousPerson = DS.Model.extend({
+        firstName: DS.attr('string'),
+        lastName: DS.attr('string'),
+        occupation: DS.attr('string')
+      });
+      ```
+
+      The JSON returned should look like this:
+
+      ```js
+      {
+        &quot;famous_person&quot;: {
+          &quot;first_name&quot;: &quot;Barack&quot;,
+          &quot;last_name&quot;: &quot;Obama&quot;,
+          &quot;occupation&quot;: &quot;President&quot;
+        }
+      }
+      ```
+
+      @class ActiveModelAdapter
+      @constructor
+      @namespace DS
+      @extends DS.RESTAdapter
+    **/
+
+    var ActiveModelAdapter = RESTAdapter.extend({
+      defaultSerializer: '-active-model',
+      /**
+        The ActiveModelAdapter overrides the `pathForType` method to build
+        underscored URLs by decamelizing and pluralizing the object type name.
+
+        ```js
+          this.pathForType(&quot;famousPerson&quot;);
+          //=&gt; &quot;famous_people&quot;
+        ```
+
+        @method pathForType
+        @param {String} type
+        @return String
+      */
+      pathForType: function(type) {
+        var decamelized = decamelize(type);
+        var underscored = underscore(decamelized);
+        return pluralize(underscored);
+      },
+
+      /**
+        The ActiveModelAdapter overrides the `ajaxError` method
+        to return a DS.InvalidError for all 422 Unprocessable Entity
+        responses.
+
+        A 422 HTTP response from the server generally implies that the request
+        was well formed but the API was unable to process it because the
+        content was not semantically correct or meaningful per the API.
+
+        For more information on 422 HTTP Error code see 11.2 WebDAV RFC 4918
+        https://tools.ietf.org/html/rfc4918#section-11.2
+
+        @method ajaxError
+        @param jqXHR
+        @return error
+      */
+      ajaxError: function(jqXHR) {
+        var error = this._super(jqXHR);
+
+        if (jqXHR &amp;&amp; jqXHR.status === 422) {
+          var response = Ember.$.parseJSON(jqXHR.responseText),
+              errors = {};
+
+          if (response.errors !== undefined) {
+            var jsonErrors = response.errors;
+
+            forEach(Ember.keys(jsonErrors), function(key) {
+              errors[Ember.String.camelize(key)] = jsonErrors[key];
+            });
+          }
+
+          return new InvalidError(errors);
+        } else {
+          return error;
+        }
+      }
+    });
+
+    __exports__[&quot;default&quot;] = ActiveModelAdapter;
+  });
+define(&quot;activemodel-adapter/lib/system/active_model_serializer&quot;, 
+  [&quot;../../../ember-inflector/lib/main&quot;,&quot;../../../ember-data/lib/serializers/rest_serializer&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    var singularize = __dependency1__.singularize;
+    var RESTSerializer = __dependency2__[&quot;default&quot;];
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get,
+        forEach = Ember.EnumerableUtils.forEach,
+        camelize =   Ember.String.camelize,
+        capitalize = Ember.String.capitalize,
+        decamelize = Ember.String.decamelize,
+        underscore = Ember.String.underscore;
+    /**
+      The ActiveModelSerializer is a subclass of the RESTSerializer designed to integrate
+      with a JSON API that uses an underscored naming convention instead of camelCasing.
+      It has been designed to work out of the box with the
+      [active_model_serializers](http://github.com/rails-api/active_model_serializers)
+      Ruby gem. This Serializer expects specific settings using ActiveModel::Serializers,
+      `embed :ids, include: true` which sideloads the records.
+
+      This serializer extends the DS.RESTSerializer by making consistent
+      use of the camelization, decamelization and pluralization methods to
+      normalize the serialized JSON into a format that is compatible with
+      a conventional Rails backend and Ember Data.
+
+      ## JSON Structure
+
+      The ActiveModelSerializer expects the JSON returned from your server
+      to follow the REST adapter conventions substituting underscored keys
+      for camelcased ones.
+
+      ### Conventional Names
+
+      Attribute names in your JSON payload should be the underscored versions of
+      the attributes in your Ember.js models.
+
+      For example, if you have a `Person` model:
+
+      ```js
+      App.FamousPerson = DS.Model.extend({
+        firstName: DS.attr('string'),
+        lastName: DS.attr('string'),
+        occupation: DS.attr('string')
+      });
+      ```
+
+      The JSON returned should look like this:
+
+      ```js
+      {
+        &quot;famous_person&quot;: {
+          &quot;first_name&quot;: &quot;Barack&quot;,
+          &quot;last_name&quot;: &quot;Obama&quot;,
+          &quot;occupation&quot;: &quot;President&quot;
+        }
+      }
+      ```
+
+      @class ActiveModelSerializer
+      @namespace DS
+      @extends DS.RESTSerializer
+    */
+    var ActiveModelSerializer = RESTSerializer.extend({
+      // SERIALIZE
+
+      /**
+        Converts camelCased attributes to underscored when serializing.
+
+        @method keyForAttribute
+        @param {String} attribute
+        @return String
+      */
+      keyForAttribute: function(attr) {
+        return decamelize(attr);
+      },
+
+      /**
+        Underscores relationship names and appends &quot;_id&quot; or &quot;_ids&quot; when serializing
+        relationship keys.
+
+        @method keyForRelationship
+        @param {String} key
+        @param {String} kind
+        @return String
+      */
+      keyForRelationship: function(key, kind) {
+        key = decamelize(key);
+        if (kind === &quot;belongsTo&quot;) {
+          return key + &quot;_id&quot;;
+        } else if (kind === &quot;hasMany&quot;) {
+          return singularize(key) + &quot;_ids&quot;;
+        } else {
+          return key;
+        }
+      },
+
+      /*
+        Does not serialize hasMany relationships by default.
+      */
+      serializeHasMany: Ember.K,
+
+      /**
+        Underscores the JSON root keys when serializing.
+
+        @method serializeIntoHash
+        @param {Object} hash
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @param {Object} options
+      */
+      serializeIntoHash: function(data, type, record, options) {
+        var root = underscore(decamelize(type.typeKey));
+        data[root] = this.serialize(record, options);
+      },
+
+      /**
+        Serializes a polymorphic type as a fully capitalized model name.
+
+        @method serializePolymorphicType
+        @param {DS.Model} record
+        @param {Object} json
+        @param relationship
+      */
+      serializePolymorphicType: function(record, json, relationship) {
+        var key = relationship.key,
+            belongsTo = get(record, key);
+
+        if (belongsTo) {
+          key = this.keyForAttribute(key);
+          json[key + &quot;_type&quot;] = capitalize(belongsTo.constructor.typeKey);
+        }
+      },
+
+      // EXTRACT
+
+      /**
+        Add extra step to `DS.RESTSerializer.normalize` so links are normalized.
+
+        If your payload looks like:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: 1,
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;links&quot;: { &quot;flagged_comments&quot;: &quot;api/comments/flagged&quot; }
+          }
+        }
+        ```
+
+        The normalized version would look like this
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: 1,
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;links&quot;: { &quot;flaggedComments&quot;: &quot;api/comments/flagged&quot; }
+          }
+        }
+        ```
+
+        @method normalize
+        @param {subclass of DS.Model} type
+        @param {Object} hash
+        @param {String} prop
+        @return Object
+      */
+
+      normalize: function(type, hash, prop) {
+        this.normalizeLinks(hash);
+
+        return this._super(type, hash, prop);
+      },
+
+      /**
+        Convert `snake_cased` links  to `camelCase`
+
+        @method normalizeLinks
+        @param {Object} data
+      */
+
+      normalizeLinks: function(data){
+        if (data.links) {
+          var links = data.links;
+
+          for (var link in links) {
+            var camelizedLink = camelize(link);
+
+            if (camelizedLink !== link) {
+              links[camelizedLink] = links[link];
+              delete links[link];
+            }
+          }
+        }
+      },
+
+      /**
+        Normalize the polymorphic type from the JSON.
+
+        Normalize:
+        ```js
+          {
+            id: &quot;1&quot;
+            minion: { type: &quot;evil_minion&quot;, id: &quot;12&quot;}
+          }
+        ```
+
+        To:
+        ```js
+          {
+            id: &quot;1&quot;
+            minion: { type: &quot;evilMinion&quot;, id: &quot;12&quot;}
+          }
+        ```
+
+        @method normalizeRelationships
+        @private
+      */
+      normalizeRelationships: function(type, hash) {
+        var payloadKey, payload;
+
+        if (this.keyForRelationship) {
+          type.eachRelationship(function(key, relationship) {
+            if (relationship.options.polymorphic) {
+              payloadKey = this.keyForAttribute(key);
+              payload = hash[payloadKey];
+              if (payload &amp;&amp; payload.type) {
+                payload.type = this.typeForRoot(payload.type);
+              } else if (payload &amp;&amp; relationship.kind === &quot;hasMany&quot;) {
+                var self = this;
+                forEach(payload, function(single) {
+                  single.type = self.typeForRoot(single.type);
+                });
+              }
+            } else {
+              payloadKey = this.keyForRelationship(key, relationship.kind);
+              payload = hash[payloadKey];
+            }
+
+            hash[key] = payload;
+
+            if (key !== payloadKey) {
+              delete hash[payloadKey];
+            }
+          }, this);
+        }
+      }
+    });
+
+    __exports__[&quot;default&quot;] = ActiveModelSerializer;
+  });
+define(&quot;activemodel-adapter/lib/system/embedded_records_mixin&quot;, 
+  [&quot;../../../ember-inflector/lib/main&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var get = Ember.get;
+    var forEach = Ember.EnumerableUtils.forEach;
+    var camelize = Ember.String.camelize;
+
+    var pluralize = __dependency1__.pluralize;
+
+    /**
+      ## Using Embedded Records
+
+      `DS.EmbeddedRecordsMixin` supports serializing embedded records.
+
+      To set up embedded records, include the mixin when extending a serializer
+      then define and configure embedded (model) relationships.
+
+      Below is an example of a per-type serializer ('post' type).
+
+      ```js
+      App.PostSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
+        attrs: {
+          author: {embedded: 'always'},
+          comments: {serialize: 'ids'}
+        }
+      })
+      ```
+
+      The `attrs` option for a resource `{embedded: 'always'}` is shorthand for:
+
+      ```js
+      {serialize: 'records', deserialize: 'records'}
+      ```
+
+      ### Configuring Attrs
+
+      A resource's `attrs` option may be set to use `ids`, `records` or `no` for the
+      `serialize`  and `deserialize` settings.
+
+      The `attrs` property can be set on the ApplicationSerializer or a per-type
+      serializer.
+
+      In the case where embedded JSON is expected while extracting a payoad (reading)
+      the setting is `deserialize: 'records'`, there is no need to use `ids` when
+      extracting as that is the default behavior without this mixin if you are using
+      the vanilla ActiveModelAdapter. Likewise, to embed JSON in the payload while
+      serializing `serialize: 'records'` is the setting to use. There is an option of
+      not embedding JSON in the serialized payload by using `serialize: 'ids'`. If you
+      do not want the relationship sent at all, you can use `serialize: 'no'`.
+
+
+      ### ActiveModelSerializer defaults
+      If you do not overwrite `attrs` for a specific relationship, the `ActiveModelSerializer`
+      will behave in the following way:
+
+      BelongsTo: `{serialize:'id', deserialize:'id'}`
+      HasMany:   `{serialize:no,  deserialize:'ids'}`
+
+      ### Model Relationships
+
+      Embedded records must have a model defined to be extracted and serialized.
+
+      To successfully extract and serialize embedded records the model relationships
+      must be setup correcty See the
+      [defining relationships](/guides/models/defining-models/#toc_defining-relationships)
+      section of the **Defining Models** guide page.
+
+      Records without an `id` property are not considered embedded records, model
+      instances must have an `id` property to be used with Ember Data.
+
+      ### Example JSON payloads, Models and Serializers
+
+      **When customizing a serializer it is imporant to grok what the cusomizations
+      are, please read the docs for the methods this mixin provides, in case you need
+      to modify to fit your specific needs.**
+
+      For example review the docs for each method of this mixin:
+
+      * [extractArray](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_extractArray)
+      * [extractSingle](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_extractSingle)
+      * [serializeBelongsTo](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_serializeBelongsTo)
+      * [serializeHasMany](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_serializeHasMany)
+
+      @class EmbeddedRecordsMixin
+      @namespace DS
+    */
+    var EmbeddedRecordsMixin = Ember.Mixin.create({
+
+      /**
+        Serialize `belongsTo` relationship when it is configured as an embedded object.
+
+        This example of an author model belongs to a post model:
+
+        ```js
+        Post = DS.Model.extend({
+          title:    DS.attr('string'),
+          body:     DS.attr('string'),
+          author:   DS.belongsTo('author')
+        });
+
+        Author = DS.Model.extend({
+          name:     DS.attr('string'),
+          post:     DS.belongsTo('post')
+        });
+        ```
+
+        Use a custom (type) serializer for the post model to configure embedded author
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
+          attrs: {
+            author: {embedded: 'always'}
+          }
+        })
+        ```
+
+        A payload with an attribute configured for embedded records can serialize
+        the records together under the root attribute's payload:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: &quot;1&quot;
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;author&quot;: {
+              &quot;id&quot;: &quot;2&quot;
+              &quot;name&quot;: &quot;dhh&quot;
+            }
+          }
+        }
+        ```
+
+        @method serializeBelongsTo
+        @param {DS.Model} record
+        @param {Object} json
+        @param {Object} relationship
+      */
+      serializeBelongsTo: function(record, json, relationship) {
+        var attr = relationship.key;
+        var attrs = this.get('attrs');
+        if (noSerializeOptionSpecified(attrs, attr)) {
+          this._super(record, json, relationship);
+          return;
+        }
+        var includeIds = hasSerializeIdsOption(attrs, attr);
+        var includeRecords = hasSerializeRecordsOption(attrs, attr);
+        var embeddedRecord = record.get(attr);
+        if (includeIds) {
+          key = this.keyForRelationship(attr, relationship.kind);
+          if (!embeddedRecord) {
+            json[key] = null;
+          } else {
+            json[key] = get(embeddedRecord, 'id');
+          }
+        } else if (includeRecords) {
+          var key = this.keyForRelationship(attr);
+          if (!embeddedRecord) {
+            json[key] = null;
+          } else {
+            json[key] = embeddedRecord.serialize({includeId: true});
+            this.removeEmbeddedForeignKey(record, embeddedRecord, relationship, json[key]);
+          }
+        }
+      },
+
+      /**
+        Serialize `hasMany` relationship when it is configured as embedded objects.
+
+        This example of a post model has many comments:
+
+        ```js
+        Post = DS.Model.extend({
+          title:    DS.attr('string'),
+          body:     DS.attr('string'),
+          comments: DS.hasMany('comment')
+        });
+
+        Comment = DS.Model.extend({
+          body:     DS.attr('string'),
+          post:     DS.belongsTo('post')
+        });
+        ```
+
+        Use a custom (type) serializer for the post model to configure embedded comments
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
+          attrs: {
+            comments: {embedded: 'always'}
+          }
+        })
+        ```
+
+        A payload with an attribute configured for embedded records can serialize
+        the records together under the root attribute's payload:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: &quot;1&quot;
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;body&quot;: &quot;I want this for my ORM, I want that for my template language...&quot;
+            &quot;comments&quot;: [{
+              &quot;id&quot;: &quot;1&quot;,
+              &quot;body&quot;: &quot;Rails is unagi&quot;
+            }, {
+              &quot;id&quot;: &quot;2&quot;,
+              &quot;body&quot;: &quot;Omakase O_o&quot;
+            }]
+          }
+        }
+        ```
+
+        The attrs options object can use more specific instruction for extracting and
+        serializing. When serializing, an option to embed `ids` or `records` can be set.
+        When extracting the only option is `records`.
+
+        So `{embedded: 'always'}` is shorthand for:
+        `{serialize: 'records', deserialize: 'records'}`
+
+        To embed the `ids` for a related object (using a hasMany relationship):
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
+          attrs: {
+            comments: {serialize: 'ids', deserialize: 'records'}
+          }
+        })
+        ```
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: &quot;1&quot;
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;body&quot;: &quot;I want this for my ORM, I want that for my template language...&quot;
+            &quot;comments&quot;: [&quot;1&quot;, &quot;2&quot;]
+          }
+        }
+        ```
+
+        @method serializeHasMany
+        @param {DS.Model} record
+        @param {Object} json
+        @param {Object} relationship
+      */
+      serializeHasMany: function(record, json, relationship) {
+        var attr = relationship.key;
+        var attrs = this.get('attrs');
+        if (noSerializeOptionSpecified(attrs, attr)) {
+          this._super(record, json, relationship);
+          return;
+        }
+        var includeIds = hasSerializeIdsOption(attrs, attr);
+        var includeRecords = hasSerializeRecordsOption(attrs, attr);
+        var key;
+        if (includeIds) {
+          key = this.keyForRelationship(attr, relationship.kind);
+          json[key] = get(record, attr).mapBy('id');
+        } else if (includeRecords) {
+          key = this.keyForAttribute(attr);
+          json[key] = get(record, attr).map(function(embeddedRecord) {
+            var serializedEmbeddedRecord = embeddedRecord.serialize({includeId: true});
+            this.removeEmbeddedForeignKey(record, embeddedRecord, relationship, serializedEmbeddedRecord);
+            return serializedEmbeddedRecord;
+          }, this);
+        }
+      },
+
+      /**
+        When serializing an embedded record, modify the property (in the json payload)
+        that refers to the parent record (foreign key for relationship).
+
+        Serializing a `belongsTo` relationship removes the property that refers to the
+        parent record
+
+        Serializing a `hasMany` relationship does not remove the property that refers to
+        the parent record.
+
+        @method removeEmbeddedForeignKey
+        @param {DS.Model} record
+        @param {DS.Model} embeddedRecord
+        @param {Object} relationship
+        @param {Object} json
+      */
+      removeEmbeddedForeignKey: function (record, embeddedRecord, relationship, json) {
+        if (relationship.kind === 'hasMany') {
+          return;
+        } else if (relationship.kind === 'belongsTo') {
+          var parentRecord = record.constructor.inverseFor(relationship.key);
+          if (parentRecord) {
+            var name = parentRecord.name;
+            var embeddedSerializer = this.store.serializerFor(embeddedRecord.constructor);
+            var parentKey = embeddedSerializer.keyForRelationship(name, parentRecord.kind);
+            if (parentKey) {
+              delete json[parentKey];
+            }
+          }
+        }
+      },
+
+      /**
+        Extract an embedded object from the payload for a single object
+        and add the object in the compound document (side-loaded) format instead.
+
+        A payload with an attribute configured for embedded records needs to be extracted:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: 1
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;author&quot;: {
+              &quot;id&quot;: 2
+              &quot;name&quot;: &quot;dhh&quot;
+            }
+            &quot;comments&quot;: []
+          }
+        }
+        ```
+
+        Ember Data is expecting a payload with a compound document (side-loaded) like:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: &quot;1&quot;
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;author&quot;: &quot;2&quot;
+            &quot;comments&quot;: []
+          },
+          &quot;authors&quot;: [{
+            &quot;id&quot;: &quot;2&quot;
+            &quot;post&quot;: &quot;1&quot;
+            &quot;name&quot;: &quot;dhh&quot;
+          }]
+          &quot;comments&quot;: []
+        }
+        ```
+
+        The payload's `author` attribute represents an object with a `belongsTo` relationship.
+        The `post` attribute under `author` is the foreign key with the id for the post
+
+        @method extractSingle
+        @param {DS.Store} store
+        @param {subclass of DS.Model} primaryType
+        @param {Object} payload
+        @param {String} recordId
+        @return Object the primary response to the original request
+      */
+      extractSingle: function(store, primaryType, payload, recordId) {
+        var root = this.keyForAttribute(primaryType.typeKey),
+            partial = payload[root];
+
+        updatePayloadWithEmbedded(this, store, primaryType, payload, partial);
+
+        return this._super(store, primaryType, payload, recordId);
+      },
+
+      /**
+        Extract embedded objects in an array when an attr is configured for embedded,
+        and add them as side-loaded objects instead.
+
+        A payload with an attr configured for embedded records needs to be extracted:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: &quot;1&quot;
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;comments&quot;: [{
+              &quot;id&quot;: &quot;1&quot;,
+              &quot;body&quot;: &quot;Rails is unagi&quot;
+            }, {
+              &quot;id&quot;: &quot;2&quot;,
+              &quot;body&quot;: &quot;Omakase O_o&quot;
+            }]
+          }
+        }
+        ```
+
+        Ember Data is expecting a payload with compound document (side-loaded) like:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: &quot;1&quot;
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;comments&quot;: [&quot;1&quot;, &quot;2&quot;]
+          },
+          &quot;comments&quot;: [{
+            &quot;id&quot;: &quot;1&quot;,
+            &quot;body&quot;: &quot;Rails is unagi&quot;
+          }, {
+            &quot;id&quot;: &quot;2&quot;,
+            &quot;body&quot;: &quot;Omakase O_o&quot;
+          }]
+        }
+        ```
+
+        The payload's `comments` attribute represents records in a `hasMany` relationship
+
+        @method extractArray
+        @param {DS.Store} store
+        @param {subclass of DS.Model} primaryType
+        @param {Object} payload
+        @return {Array&lt;Object&gt;} The primary array that was returned in response
+          to the original query.
+      */
+      extractArray: function(store, primaryType, payload) {
+        var root = this.keyForAttribute(primaryType.typeKey),
+            partials = payload[pluralize(root)];
+
+        forEach(partials, function(partial) {
+          updatePayloadWithEmbedded(this, store, primaryType, payload, partial);
+        }, this);
+
+        return this._super(store, primaryType, payload);
+      }
+    });
+
+    // checks config for attrs option to embedded (always) - serialize and deserialize
+    function hasEmbeddedAlwaysOption(attrs, attr) {
+      var option = attrsOption(attrs, attr);
+      return option &amp;&amp; option.embedded === 'always';
+    }
+
+    // checks config for attrs option to serialize ids
+    function hasSerializeRecordsOption(attrs, attr) {
+      var alwaysEmbed = hasEmbeddedAlwaysOption(attrs, attr);
+      var option = attrsOption(attrs, attr);
+      return alwaysEmbed || (option &amp;&amp; (option.serialize === 'records'));
+    }
+
+    // checks config for attrs option to serialize records
+    function hasSerializeIdsOption(attrs, attr) {
+      var option = attrsOption(attrs, attr);
+      return option &amp;&amp; (option.serialize === 'ids' || option.serialize === 'id');
+    }
+
+    // checks config for attrs option to serialize records
+    function noSerializeOptionSpecified(attrs, attr) {
+      var option = attrsOption(attrs, attr);
+      var serializeRecords = hasSerializeRecordsOption(attrs, attr);
+      var serializeIds = hasSerializeIdsOption(attrs, attr);
+      return !(option &amp;&amp; (option.serialize || option.embedded));
+    }
+
+    // checks config for attrs option to deserialize records
+    // a defined option object for a resource is treated the same as
+    // `deserialize: 'records'`
+    function hasDeserializeRecordsOption(attrs, attr) {
+      var alwaysEmbed = hasEmbeddedAlwaysOption(attrs, attr);
+      var option = attrsOption(attrs, attr);
+      var hasSerializingOption = option &amp;&amp; (option.deserialize || option.serialize);
+      return alwaysEmbed || hasSerializingOption /* option.deserialize === 'records' */;
+    }
+
+    function attrsOption(attrs, attr) {
+      return attrs &amp;&amp; (attrs[Ember.String.camelize(attr)] || attrs[attr]);
+    }
+
+    // chooses a relationship kind to branch which function is used to update payload
+    // does not change payload if attr is not embedded
+    function updatePayloadWithEmbedded(serializer, store, type, payload, partial) {
+      var attrs = get(serializer, 'attrs');
+
+      if (!attrs) {
+        return;
+      }
+      type.eachRelationship(function(key, relationship) {
+        if (hasDeserializeRecordsOption(attrs, key)) {
+          if (relationship.kind === &quot;hasMany&quot;) {
+            updatePayloadWithEmbeddedHasMany(serializer, store, key, relationship, payload, partial);
+          }
+          if (relationship.kind === &quot;belongsTo&quot;) {
+            updatePayloadWithEmbeddedBelongsTo(serializer, store, key, relationship, payload, partial);
+          }
+        }
+      });
+    }
+
+    // handles embedding for `hasMany` relationship
+    function updatePayloadWithEmbeddedHasMany(serializer, store, primaryType, relationship, payload, partial) {
+      var embeddedSerializer = store.serializerFor(relationship.type.typeKey);
+      var primaryKey = get(serializer, 'primaryKey');
+      var attr = relationship.type.typeKey;
+      // underscore forces the embedded records to be side loaded.
+      // it is needed when main type === relationship.type
+      var embeddedTypeKey = '_' + serializer.typeForRoot(relationship.type.typeKey);
+      var expandedKey = serializer.keyForRelationship(primaryType, relationship.kind);
+      var attribute  = serializer.keyForAttribute(primaryType);
+      var ids = [];
+
+      if (!partial[attribute]) {
+        return;
+      }
+
+      payload[embeddedTypeKey] = payload[embeddedTypeKey] || [];
+
+      forEach(partial[attribute], function(data) {
+        var embeddedType = store.modelFor(attr);
+        updatePayloadWithEmbedded(embeddedSerializer, store, embeddedType, payload, data);
+        ids.push(data[primaryKey]);
+        payload[embeddedTypeKey].push(data);
+      });
+
+      partial[expandedKey] = ids;
+      delete partial[attribute];
+    }
+
+    // handles embedding for `belongsTo` relationship
+    function updatePayloadWithEmbeddedBelongsTo(serializer, store, primaryType, relationship, payload, partial) {
+      var attrs = serializer.get('attrs');
+
+      if (!attrs ||
+        !(hasDeserializeRecordsOption(attrs, Ember.String.camelize(primaryType)) ||
+          hasDeserializeRecordsOption(attrs, primaryType))) {
+        return;
+      }
+      var attr = relationship.type.typeKey;
+      var _serializer = store.serializerFor(relationship.type.typeKey);
+      var primaryKey = get(_serializer, 'primaryKey');
+      var embeddedTypeKey = Ember.String.pluralize(attr); // TODO don't use pluralize
+      var expandedKey = _serializer.keyForRelationship(primaryType, relationship.kind);
+      var attribute = _serializer.keyForAttribute(primaryType);
+
+      if (!partial[attribute]) {
+        return;
+      }
+      payload[embeddedTypeKey] = payload[embeddedTypeKey] || [];
+      var embeddedType = store.modelFor(relationship.type.typeKey);
+      // Recursive call for nested record
+      updatePayloadWithEmbedded(_serializer, store, embeddedType, payload, partial[attribute]);
+      partial[expandedKey] = partial[attribute].id;
+      // Need to move an embedded `belongsTo` object into a pluralized collection
+      payload[embeddedTypeKey].push(partial[attribute]);
+      // Need a reference to the parent so relationship works between both `belongsTo` records
+      partial[attribute][relationship.parentType.typeKey + '_id'] = partial.id;
+      delete partial[attribute];
+    }
+
+    __exports__[&quot;default&quot;] = EmbeddedRecordsMixin;
+  });
+define(&quot;ember-data/lib/adapters&quot;, 
+  [&quot;./adapters/fixture_adapter&quot;,&quot;./adapters/rest_adapter&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var FixtureAdapter = __dependency1__[&quot;default&quot;];
+    var RESTAdapter = __dependency2__[&quot;default&quot;];
+
+    __exports__.RESTAdapter = RESTAdapter;
+    __exports__.FixtureAdapter = FixtureAdapter;
+  });
+define(&quot;ember-data/lib/adapters/fixture_adapter&quot;, 
+  [&quot;../system/adapter&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get, fmt = Ember.String.fmt,
+        indexOf = Ember.EnumerableUtils.indexOf;
+
+    var counter = 0;
+
+    var Adapter = __dependency1__[&quot;default&quot;];
+
+    /**
+      `DS.FixtureAdapter` is an adapter that loads records from memory.
+      It's primarily used for development and testing. You can also use
+      `DS.FixtureAdapter` while working on the API but are not ready to
+      integrate yet. It is a fully functioning adapter. All CRUD methods
+      are implemented. You can also implement query logic that a remote
+      system would do. It's possible to develop your entire application
+      with `DS.FixtureAdapter`.
+
+      For information on how to use the `FixtureAdapter` in your
+      application please see the [FixtureAdapter
+      guide](/guides/models/the-fixture-adapter/).
+
+      @class FixtureAdapter
+      @namespace DS
+      @extends DS.Adapter
+    */
+    var FixtureAdapter = Adapter.extend({
+      // by default, fixtures are already in normalized form
+      serializer: null,
+
+      /**
+        If `simulateRemoteResponse` is `true` the `FixtureAdapter` will
+        wait a number of milliseconds before resolving promises with the
+        fixture values. The wait time can be configured via the `latency`
+        property.
+
+        @property simulateRemoteResponse
+        @type {Boolean}
+        @default true
+      */
+      simulateRemoteResponse: true,
+
+      /**
+        By default the `FixtureAdapter` will simulate a wait of the
+        `latency` milliseconds before resolving promises with the fixture
+        values. This behavior can be turned off via the
+        `simulateRemoteResponse` property.
+
+        @property latency
+        @type {Number}
+        @default 50
+      */
+      latency: 50,
+
+      /**
+        Implement this method in order to provide data associated with a type
+
+        @method fixturesForType
+        @param {Subclass of DS.Model} type
+        @return {Array}
+      */
+      fixturesForType: function(type) {
+        if (type.FIXTURES) {
+          var fixtures = Ember.A(type.FIXTURES);
+          return fixtures.map(function(fixture){
+            var fixtureIdType = typeof fixture.id;
+            if(fixtureIdType !== &quot;number&quot; &amp;&amp; fixtureIdType !== &quot;string&quot;){
+              throw new Error(fmt('the id property must be defined as a number or string for fixture %@', [fixture]));
+            }
+            fixture.id = fixture.id + '';
+            return fixture;
+          });
+        }
+        return null;
+      },
+
+      /**
+        Implement this method in order to query fixtures data
+
+        @method queryFixtures
+        @param {Array} fixture
+        @param {Object} query
+        @param {Subclass of DS.Model} type
+        @return {Promise|Array}
+      */
+      queryFixtures: function(fixtures, query, type) {
+        Ember.assert('Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.');
+      },
+
+      /**
+        @method updateFixtures
+        @param {Subclass of DS.Model} type
+        @param {Array} fixture
+      */
+      updateFixtures: function(type, fixture) {
+        if(!type.FIXTURES) {
+          type.FIXTURES = [];
+        }
+
+        var fixtures = type.FIXTURES;
+
+        this.deleteLoadedFixture(type, fixture);
+
+        fixtures.push(fixture);
+      },
+
+      /**
+        Implement this method in order to provide json for CRUD methods
+
+        @method mockJSON
+        @param {Subclass of DS.Model} type
+        @param {DS.Model} record
+      */
+      mockJSON: function(store, type, record) {
+        return store.serializerFor(type).serialize(record, { includeId: true });
+      },
+
+      /**
+        @method generateIdForRecord
+        @param {DS.Store} store
+        @param {DS.Model} record
+        @return {String} id
+      */
+      generateIdForRecord: function(store) {
+        return &quot;fixture-&quot; + counter++;
+      },
+
+      /**
+        @method find
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {String} id
+        @return {Promise} promise
+      */
+      find: function(store, type, id) {
+        var fixtures = this.fixturesForType(type),
+            fixture;
+
+        Ember.assert(&quot;Unable to find fixtures for model type &quot;+type.toString(), fixtures);
+
+        if (fixtures) {
+          fixture = Ember.A(fixtures).findProperty('id', id);
+        }
+
+        if (fixture) {
+          return this.simulateRemoteCall(function() {
+            return fixture;
+          }, this);
+        }
+      },
+
+      /**
+        @method findMany
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Array} ids
+        @return {Promise} promise
+      */
+      findMany: function(store, type, ids) {
+        var fixtures = this.fixturesForType(type);
+
+        Ember.assert(&quot;Unable to find fixtures for model type &quot;+type.toString(), fixtures);
+
+        if (fixtures) {
+          fixtures = fixtures.filter(function(item) {
+            return indexOf(ids, item.id) !== -1;
+          });
+        }
+
+        if (fixtures) {
+          return this.simulateRemoteCall(function() {
+            return fixtures;
+          }, this);
+        }
+      },
+
+      /**
+        @private
+        @method findAll
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {String} sinceToken
+        @return {Promise} promise
+      */
+      findAll: function(store, type) {
+        var fixtures = this.fixturesForType(type);
+
+        Ember.assert(&quot;Unable to find fixtures for model type &quot;+type.toString(), fixtures);
+
+        return this.simulateRemoteCall(function() {
+          return fixtures;
+        }, this);
+      },
+
+      /**
+        @private
+        @method findQuery
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} query
+        @param {DS.AdapterPopulatedRecordArray} recordArray
+        @return {Promise} promise
+      */
+      findQuery: function(store, type, query, array) {
+        var fixtures = this.fixturesForType(type);
+
+        Ember.assert(&quot;Unable to find fixtures for model type &quot; + type.toString(), fixtures);
+
+        fixtures = this.queryFixtures(fixtures, query, type);
+
+        if (fixtures) {
+          return this.simulateRemoteCall(function() {
+            return fixtures;
+          }, this);
+        }
+      },
+
+      /**
+        @method createRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      createRecord: function(store, type, record) {
+        var fixture = this.mockJSON(store, type, record);
+
+        this.updateFixtures(type, fixture);
+
+        return this.simulateRemoteCall(function() {
+          return fixture;
+        }, this);
+      },
+
+      /**
+        @method updateRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      updateRecord: function(store, type, record) {
+        var fixture = this.mockJSON(store, type, record);
+
+        this.updateFixtures(type, fixture);
+
+        return this.simulateRemoteCall(function() {
+          return fixture;
+        }, this);
+      },
+
+      /**
+        @method deleteRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      deleteRecord: function(store, type, record) {
+        var fixture = this.mockJSON(store, type, record);
+
+        this.deleteLoadedFixture(type, fixture);
+
+        return this.simulateRemoteCall(function() {
+          // no payload in a deletion
+          return null;
+        });
+      },
+
+      /*
+        @method deleteLoadedFixture
+        @private
+        @param type
+        @param record
+      */
+      deleteLoadedFixture: function(type, record) {
+        var existingFixture = this.findExistingFixture(type, record);
+
+        if(existingFixture) {
+          var index = indexOf(type.FIXTURES, existingFixture);
+          type.FIXTURES.splice(index, 1);
+          return true;
+        }
+      },
+
+      /*
+        @method findExistingFixture
+        @private
+        @param type
+        @param record
+      */
+      findExistingFixture: function(type, record) {
+        var fixtures = this.fixturesForType(type);
+        var id = get(record, 'id');
+
+        return this.findFixtureById(fixtures, id);
+      },
+
+      /*
+        @method findFixtureById
+        @private
+        @param fixtures
+        @param id
+      */
+      findFixtureById: function(fixtures, id) {
+        return Ember.A(fixtures).find(function(r) {
+          if(''+get(r, 'id') === ''+id) {
+            return true;
+          } else {
+            return false;
+          }
+        });
+      },
+
+      /*
+        @method simulateRemoteCall
+        @private
+        @param callback
+        @param context
+      */
+      simulateRemoteCall: function(callback, context) {
+        var adapter = this;
+
+        return new Ember.RSVP.Promise(function(resolve) {
+          if (get(adapter, 'simulateRemoteResponse')) {
+            // Schedule with setTimeout
+            Ember.run.later(function() {
+              resolve(callback.call(context));
+            }, get(adapter, 'latency'));
+          } else {
+            // Asynchronous, but at the of the runloop with zero latency
+            Ember.run.schedule('actions', null, function() {
+              resolve(callback.call(context));
+            });
+          }
+        }, &quot;DS: FixtureAdapter#simulateRemoteCall&quot;);
+      }
+    });
+
+    __exports__[&quot;default&quot;] = FixtureAdapter;
+  });
+define(&quot;ember-data/lib/adapters/rest_adapter&quot;, 
+  [&quot;../system/adapter&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var Adapter = __dependency1__[&quot;default&quot;];
+    var get = Ember.get, set = Ember.set;
+    var forEach = Ember.ArrayPolyfills.forEach;
+
+    /**
+      The REST adapter allows your store to communicate with an HTTP server by
+      transmitting JSON via XHR. Most Ember.js apps that consume a JSON API
+      should use the REST adapter.
+
+      This adapter is designed around the idea that the JSON exchanged with
+      the server should be conventional.
+
+      ## JSON Structure
+
+      The REST adapter expects the JSON returned from your server to follow
+      these conventions.
+
+      ### Object Root
+
+      The JSON payload should be an object that contains the record inside a
+      root property. For example, in response to a `GET` request for
+      `/posts/1`, the JSON should look like this:
+
+      ```js
+      {
+        &quot;post&quot;: {
+          &quot;title&quot;: &quot;I'm Running to Reform the W3C's Tag&quot;,
+          &quot;author&quot;: &quot;Yehuda Katz&quot;
+        }
+      }
+      ```
+
+      ### Conventional Names
+
+      Attribute names in your JSON payload should be the camelCased versions of
+      the attributes in your Ember.js models.
+
+      For example, if you have a `Person` model:
+
+      ```js
+      App.Person = DS.Model.extend({
+        firstName: DS.attr('string'),
+        lastName: DS.attr('string'),
+        occupation: DS.attr('string')
+      });
+      ```
+
+      The JSON returned should look like this:
+
+      ```js
+      {
+        &quot;person&quot;: {
+          &quot;firstName&quot;: &quot;Barack&quot;,
+          &quot;lastName&quot;: &quot;Obama&quot;,
+          &quot;occupation&quot;: &quot;President&quot;
+        }
+      }
+      ```
+
+      ## Customization
+
+      ### Endpoint path customization
+
+      Endpoint paths can be prefixed with a `namespace` by setting the namespace
+      property on the adapter:
+
+      ```js
+      DS.RESTAdapter.reopen({
+        namespace: 'api/1'
+      });
+      ```
+      Requests for `App.Person` would now target `/api/1/people/1`.
+
+      ### Host customization
+
+      An adapter can target other hosts by setting the `host` property.
+
+      ```js
+      DS.RESTAdapter.reopen({
+        host: 'https://api.example.com'
+      });
+      ```
+
+      ### Headers customization
+
+      Some APIs require HTTP headers, e.g. to provide an API key. Arbitrary
+      headers can be set as key/value pairs on the `RESTAdapter`'s `headers`
+      object and Ember Data will send them along with each ajax request.
+
+
+      ```js
+      App.ApplicationAdapter = DS.RESTAdapter.extend({
+        headers: {
+          &quot;API_KEY&quot;: &quot;secret key&quot;,
+          &quot;ANOTHER_HEADER&quot;: &quot;Some header value&quot;
+        }
+      });
+      ```
+
+      `headers` can also be used as a computed property to support dynamic
+      headers. In the example below, the `session` object has been
+      injected into an adapter by Ember's container.
+
+      ```js
+      App.ApplicationAdapter = DS.RESTAdapter.extend({
+        headers: function() {
+          return {
+            &quot;API_KEY&quot;: this.get(&quot;session.authToken&quot;),
+            &quot;ANOTHER_HEADER&quot;: &quot;Some header value&quot;
+          };
+        }.property(&quot;session.authToken&quot;)
+      });
+      ```
+
+      In some cases, your dynamic headers may require data from some
+      object outside of Ember's observer system (for example
+      `document.cookie`). You can use the
+      [volatile](/api/classes/Ember.ComputedProperty.html#method_volatile)
+      function to set the property into a non-chached mode causing the headers to
+      be recomputed with every request.
+
+      ```js
+      App.ApplicationAdapter = DS.RESTAdapter.extend({
+        headers: function() {
+          return {
+            &quot;API_KEY&quot;: Ember.get(document.cookie.match(/apiKey\=([^;]*)/), &quot;1&quot;),
+            &quot;ANOTHER_HEADER&quot;: &quot;Some header value&quot;
+          };
+        }.property().volatile();
+      });
+      ```
+
+      @class RESTAdapter
+      @constructor
+      @namespace DS
+      @extends DS.Adapter
+    */
+    var RESTAdapter = Adapter.extend({
+      defaultSerializer: '-rest',
+      /**
+        Endpoint paths can be prefixed with a `namespace` by setting the namespace
+        property on the adapter:
+
+        ```javascript
+        DS.RESTAdapter.reopen({
+          namespace: 'api/1'
+        });
+        ```
+
+        Requests for `App.Post` would now target `/api/1/post/`.
+
+        @property namespace
+        @type {String}
+      */
+
+      /**
+        An adapter can target other hosts by setting the `host` property.
+
+        ```javascript
+        DS.RESTAdapter.reopen({
+          host: 'https://api.example.com'
+        });
+        ```
+
+        Requests for `App.Post` would now target `https://api.example.com/post/`.
+
+        @property host
+        @type {String}
+      */
+
+      /**
+        Some APIs require HTTP headers, e.g. to provide an API
+        key. Arbitrary headers can be set as key/value pairs on the
+        `RESTAdapter`'s `headers` object and Ember Data will send them
+        along with each ajax request. For dynamic headers see [headers
+        customization](/api/data/classes/DS.RESTAdapter.html#toc_headers-customization).
+
+        ```javascript
+        App.ApplicationAdapter = DS.RESTAdapter.extend({
+          headers: {
+            &quot;API_KEY&quot;: &quot;secret key&quot;,
+            &quot;ANOTHER_HEADER&quot;: &quot;Some header value&quot;
+          }
+        });
+        ```
+
+        @property headers
+        @type {Object}
+      */
+
+      /**
+        Called by the store in order to fetch the JSON for a given
+        type and ID.
+
+        The `find` method makes an Ajax request to a URL computed by `buildURL`, and returns a
+        promise for the resulting payload.
+
+        This method performs an HTTP `GET` request with the id provided as part of the query string.
+
+        @method find
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {String} id
+        @return {Promise} promise
+      */
+      find: function(store, type, id) {
+        return this.ajax(this.buildURL(type.typeKey, id), 'GET');
+      },
+
+      /**
+        Called by the store in order to fetch a JSON array for all
+        of the records for a given type.
+
+        The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
+        promise for the resulting payload.
+
+        @private
+        @method findAll
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {String} sinceToken
+        @return {Promise} promise
+      */
+      findAll: function(store, type, sinceToken) {
+        var query;
+
+        if (sinceToken) {
+          query = { since: sinceToken };
+        }
+
+        return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
+      },
+
+      /**
+        Called by the store in order to fetch a JSON array for
+        the records that match a particular query.
+
+        The `findQuery` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
+        promise for the resulting payload.
+
+        The `query` argument is a simple JavaScript object that will be passed directly
+        to the server as parameters.
+
+        @private
+        @method findQuery
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} query
+        @return {Promise} promise
+      */
+      findQuery: function(store, type, query) {
+        return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
+      },
+
+      /**
+        Called by the store in order to fetch a JSON array for
+        the unloaded records in a has-many relationship that were originally
+        specified as IDs.
+
+        For example, if the original payload looks like:
+
+        ```js
+        {
+          &quot;id&quot;: 1,
+          &quot;title&quot;: &quot;Rails is omakase&quot;,
+          &quot;comments&quot;: [ 1, 2, 3 ]
+        }
+        ```
+
+        The IDs will be passed as a URL-encoded Array of IDs, in this form:
+
+        ```
+        ids[]=1&amp;ids[]=2&amp;ids[]=3
+        ```
+
+        Many servers, such as Rails and PHP, will automatically convert this URL-encoded array
+        into an Array for you on the server-side. If you want to encode the
+        IDs, differently, just override this (one-line) method.
+
+        The `findMany` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
+        promise for the resulting payload.
+
+        @method findMany
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Array} ids
+        @return {Promise} promise
+      */
+      findMany: function(store, type, ids) {
+        return this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });
+      },
+
+      /**
+        Called by the store in order to fetch a JSON array for
+        the unloaded records in a has-many relationship that were originally
+        specified as a URL (inside of `links`).
+
+        For example, if your original payload looks like this:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: 1,
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;links&quot;: { &quot;comments&quot;: &quot;/posts/1/comments&quot; }
+          }
+        }
+        ```
+
+        This method will be called with the parent record and `/posts/1/comments`.
+
+        The `findHasMany` method will make an Ajax (HTTP GET) request to the originally specified URL.
+        If the URL is host-relative (starting with a single slash), the
+        request will use the host specified on the adapter (if any).
+
+        @method findHasMany
+        @param {DS.Store} store
+        @param {DS.Model} record
+        @param {String} url
+        @return {Promise} promise
+      */
+      findHasMany: function(store, record, url) {
+        var host = get(this, 'host'),
+            id   = get(record, 'id'),
+            type = record.constructor.typeKey;
+
+        if (host &amp;&amp; url.charAt(0) === '/' &amp;&amp; url.charAt(1) !== '/') {
+          url = host + url;
+        }
+
+        return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
+      },
+
+      /**
+        Called by the store in order to fetch a JSON array for
+        the unloaded records in a belongs-to relationship that were originally
+        specified as a URL (inside of `links`).
+
+        For example, if your original payload looks like this:
+
+        ```js
+        {
+          &quot;person&quot;: {
+            &quot;id&quot;: 1,
+            &quot;name&quot;: &quot;Tom Dale&quot;,
+            &quot;links&quot;: { &quot;group&quot;: &quot;/people/1/group&quot; }
+          }
+        }
+        ```
+
+        This method will be called with the parent record and `/people/1/group`.
+
+        The `findBelongsTo` method will make an Ajax (HTTP GET) request to the originally specified URL.
+
+        @method findBelongsTo
+        @param {DS.Store} store
+        @param {DS.Model} record
+        @param {String} url
+        @return {Promise} promise
+      */
+      findBelongsTo: function(store, record, url) {
+        var id   = get(record, 'id'),
+            type = record.constructor.typeKey;
+
+        return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
+      },
+
+      /**
+        Called by the store when a newly created record is
+        saved via the `save` method on a model record instance.
+
+        The `createRecord` method serializes the record and makes an Ajax (HTTP POST) request
+        to a URL computed by `buildURL`.
+
+        See `serialize` for information on how to customize the serialized form
+        of a record.
+
+        @method createRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      createRecord: function(store, type, record) {
+        var data = {};
+        var serializer = store.serializerFor(type.typeKey);
+
+        serializer.serializeIntoHash(data, type, record, { includeId: true });
+
+        return this.ajax(this.buildURL(type.typeKey), &quot;POST&quot;, { data: data });
+      },
+
+      /**
+        Called by the store when an existing record is saved
+        via the `save` method on a model record instance.
+
+        The `updateRecord` method serializes the record and makes an Ajax (HTTP PUT) request
+        to a URL computed by `buildURL`.
+
+        See `serialize` for information on how to customize the serialized form
+        of a record.
+
+        @method updateRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      updateRecord: function(store, type, record) {
+        var data = {};
+        var serializer = store.serializerFor(type.typeKey);
+
+        serializer.serializeIntoHash(data, type, record);
+
+        var id = get(record, 'id');
+
+        return this.ajax(this.buildURL(type.typeKey, id), &quot;PUT&quot;, { data: data });
+      },
+
+      /**
+        Called by the store when a record is deleted.
+
+        The `deleteRecord` method  makes an Ajax (HTTP DELETE) request to a URL computed by `buildURL`.
+
+        @method deleteRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      deleteRecord: function(store, type, record) {
+        var id = get(record, 'id');
+
+        return this.ajax(this.buildURL(type.typeKey, id), &quot;DELETE&quot;);
+      },
+
+      /**
+        Builds a URL for a given type and optional ID.
+
+        By default, it pluralizes the type's name (for example, 'post'
+        becomes 'posts' and 'person' becomes 'people'). To override the
+        pluralization see [pathForType](#method_pathForType).
+
+        If an ID is specified, it adds the ID to the path generated
+        for the type, separated by a `/`.
+
+        @method buildURL
+        @param {String} type
+        @param {String} id
+        @return {String} url
+      */
+      buildURL: function(type, id) {
+        var url = [],
+            host = get(this, 'host'),
+            prefix = this.urlPrefix();
+
+        if (type) { url.push(this.pathForType(type)); }
+        if (id) { url.push(id); }
+
+        if (prefix) { url.unshift(prefix); }
+
+        url = url.join('/');
+        if (!host &amp;&amp; url) { url = '/' + url; }
+
+        return url;
+      },
+
+      /**
+        @method urlPrefix
+        @private
+        @param {String} path
+        @param {String} parentUrl
+        @return {String} urlPrefix
+      */
+      urlPrefix: function(path, parentURL) {
+        var host = get(this, 'host'),
+            namespace = get(this, 'namespace'),
+            url = [];
+
+        if (path) {
+          // Absolute path
+          if (path.charAt(0) === '/') {
+            if (host) {
+              path = path.slice(1);
+              url.push(host);
+            }
+          // Relative path
+          } else if (!/^http(s)?:\/\//.test(path)) {
+            url.push(parentURL);
+          }
+        } else {
+          if (host) { url.push(host); }
+          if (namespace) { url.push(namespace); }
+        }
+
+        if (path) {
+          url.push(path);
+        }
+
+        return url.join('/');
+      },
+
+      /**
+        Determines the pathname for a given type.
+
+        By default, it pluralizes the type's name (for example,
+        'post' becomes 'posts' and 'person' becomes 'people').
+
+        ### Pathname customization
+
+        For example if you have an object LineItem with an
+        endpoint of &quot;/line_items/&quot;.
+
+        ```js
+        App.ApplicationAdapter = DS.RESTAdapter.extend({
+          pathForType: function(type) {
+            var decamelized = Ember.String.decamelize(type);
+            return Ember.String.pluralize(decamelized);
+          }
+        });
+        ```
+
+        @method pathForType
+        @param {String} type
+        @return {String} path
+      **/
+      pathForType: function(type) {
+        var camelized = Ember.String.camelize(type);
+        return Ember.String.pluralize(camelized);
+      },
+
+      /**
+        Takes an ajax response, and returns a relevant error.
+
+        Returning a `DS.InvalidError` from this method will cause the
+        record to transition into the `invalid` state and make the
+        `errors` object available on the record.
+
+        ```javascript
+        App.ApplicationAdapter = DS.RESTAdapter.extend({
+          ajaxError: function(jqXHR) {
+            var error = this._super(jqXHR);
+
+            if (jqXHR &amp;&amp; jqXHR.status === 422) {
+              var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)[&quot;errors&quot;];
+
+              return new DS.InvalidError(jsonErrors);
+            } else {
+              return error;
+            }
+          }
+        });
+        ```
+
+        Note: As a correctness optimization, the default implementation of
+        the `ajaxError` method strips out the `then` method from jquery's
+        ajax response (jqXHR). This is important because the jqXHR's
+        `then` method fulfills the promise with itself resulting in a
+        circular &quot;thenable&quot; chain which may cause problems for some
+        promise libraries.
+
+        @method ajaxError
+        @param  {Object} jqXHR
+        @return {Object} jqXHR
+      */
+      ajaxError: function(jqXHR) {
+        if (jqXHR &amp;&amp; typeof jqXHR === 'object') {
+          jqXHR.then = null;
+        }
+
+        return jqXHR;
+      },
+
+      /**
+        Takes a URL, an HTTP method and a hash of data, and makes an
+        HTTP request.
+
+        When the server responds with a payload, Ember Data will call into `extractSingle`
+        or `extractArray` (depending on whether the original query was for one record or
+        many records).
+
+        By default, `ajax` method has the following behavior:
+
+        * It sets the response `dataType` to `&quot;json&quot;`
+        * If the HTTP method is not `&quot;GET&quot;`, it sets the `Content-Type` to be
+          `application/json; charset=utf-8`
+        * If the HTTP method is not `&quot;GET&quot;`, it stringifies the data passed in. The
+          data is the serialized record in the case of a save.
+        * Registers success and failure handlers.
+
+        @method ajax
+        @private
+        @param {String} url
+        @param {String} type The request type GET, POST, PUT, DELETE etc.
+        @param {Object} hash
+        @return {Promise} promise
+      */
+      ajax: function(url, type, hash) {
+        var adapter = this;
+
+        return new Ember.RSVP.Promise(function(resolve, reject) {
+          hash = adapter.ajaxOptions(url, type, hash);
+
+          hash.success = function(json) {
+            Ember.run(null, resolve, json);
+          };
+
+          hash.error = function(jqXHR, textStatus, errorThrown) {
+            Ember.run(null, reject, adapter.ajaxError(jqXHR));
+          };
+
+          Ember.$.ajax(hash);
+        }, &quot;DS: RestAdapter#ajax &quot; + type + &quot; to &quot; + url);
+      },
+
+      /**
+        @method ajaxOptions
+        @private
+        @param {String} url
+        @param {String} type The request type GET, POST, PUT, DELETE etc.
+        @param {Object} hash
+        @return {Object} hash
+      */
+      ajaxOptions: function(url, type, hash) {
+        hash = hash || {};
+        hash.url = url;
+        hash.type = type;
+        hash.dataType = 'json';
+        hash.context = this;
+
+        if (hash.data &amp;&amp; type !== 'GET') {
+          hash.contentType = 'application/json; charset=utf-8';
+          hash.data = JSON.stringify(hash.data);
+        }
+
+        var headers = get(this, 'headers');
+        if (headers !== undefined) {
+          hash.beforeSend = function (xhr) {
+            forEach.call(Ember.keys(headers), function(key) {
+              xhr.setRequestHeader(key, headers[key]);
+            });
+          };
+        }
+
+
+        return hash;
+      }
+
+    });
+
+    __exports__[&quot;default&quot;] = RESTAdapter;
+  });
+define(&quot;ember-data/lib/core&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    /**
+      All Ember Data methods and functions are defined inside of this namespace.
+
+      @class DS
+      @static
+    */
+    var DS;
+    if ('undefined' === typeof DS) {
+      /**
+        @property VERSION
+        @type String
+        @default '1.0.0-beta.8.2a68c63a'
+        @static
+      */
+      DS = Ember.Namespace.create({
+        VERSION: '1.0.0-beta.8.2a68c63a'
+      });
+
+      if (Ember.libraries) {
+        Ember.libraries.registerCoreLibrary('Ember Data', DS.VERSION);
+      }
+    }
+
+    __exports__[&quot;default&quot;] = DS;
+  });
+define(&quot;ember-data/lib/ember-initializer&quot;, 
+  [&quot;./setup-container&quot;],
+  function(__dependency1__) {
+    &quot;use strict&quot;;
+    var setupContainer = __dependency1__[&quot;default&quot;];
+
+    var K = Ember.K;
+
+    /**
+      @module ember-data
+    */
+
+    /**
+
+      This code initializes Ember-Data onto an Ember application.
+
+      If an Ember.js developer defines a subclass of DS.Store on their application,
+      as `App.ApplicationStore` (or via a module system that resolves to `store:application`)
+      this code will automatically instantiate it and make it available on the
+      router.
+
+      Additionally, after an application's controllers have been injected, they will
+      each have the store made available to them.
+
+      For example, imagine an Ember.js application with the following classes:
+
+      App.ApplicationStore = DS.Store.extend({
+        adapter: 'custom'
+      });
+
+      App.PostsController = Ember.ArrayController.extend({
+        // ...
+      });
+
+      When the application is initialized, `App.ApplicationStore` will automatically be
+      instantiated, and the instance of `App.PostsController` will have its `store`
+      property set to that instance.
+
+      Note that this code will only be run if the `ember-application` package is
+      loaded. If Ember Data is being used in an environment other than a
+      typical application (e.g., node.js where only `ember-runtime` is available),
+      this code will be ignored.
+    */
+
+    Ember.onLoad('Ember.Application', function(Application) {
+
+      Application.initializer({
+        name:       &quot;ember-data&quot;,
+        initialize: setupContainer
+      });
+
+      // Deprecated initializers to satisfy old code that depended on them
+
+      Application.initializer({
+        name:       &quot;store&quot;,
+        after:      &quot;ember-data&quot;,
+        initialize: K
+      });
+
+      Application.initializer({
+        name:       &quot;activeModelAdapter&quot;,
+        before:     &quot;store&quot;,
+        initialize: K
+      });
+
+      Application.initializer({
+        name:       &quot;transforms&quot;,
+        before:     &quot;store&quot;,
+        initialize: K
+      });
+
+      Application.initializer({
+        name:       &quot;data-adapter&quot;,
+        before:     &quot;store&quot;,
+        initialize: K
+      });
+
+      Application.initializer({
+        name:       &quot;injectStore&quot;,
+        before:     &quot;store&quot;,
+        initialize: K
+      });
+    });
+  });
+define(&quot;ember-data/lib/ext/date&quot;, 
+  [],
+  function() {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    /**
+      Date.parse with progressive enhancement for ISO 8601 &lt;https://github.com/csnover/js-iso8601&gt;
+
+      © 2011 Colin Snover &lt;http://zetafleet.com&gt;
+
+      Released under MIT license.
+
+      @class Date
+      @namespace Ember
+      @static
+    */
+    Ember.Date = Ember.Date || {};
+
+    var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
+
+    /**
+      @method parse
+      @param date
+    */
+    Ember.Date.parse = function (date) {
+        var timestamp, struct, minutesOffset = 0;
+
+        // ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
+        // before falling back to any implementation-specific date parsing, so that’s what we do, even if native
+        // implementations could be faster
+        //              1 YYYY                2 MM       3 DD           4 HH    5 mm       6 ss        7 msec        8 Z 9 ±    10 tzHH    11 tzmm
+        if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
+            // avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
+            for (var i = 0, k; (k = numericKeys[i]); ++i) {
+                struct[k] = +struct[k] || 0;
+            }
+
+            // allow undefined days and months
+            struct[2] = (+struct[2] || 1) - 1;
+            struct[3] = +struct[3] || 1;
+
+            if (struct[8] !== 'Z' &amp;&amp; struct[9] !== undefined) {
+                minutesOffset = struct[10] * 60 + struct[11];
+
+                if (struct[9] === '+') {
+                    minutesOffset = 0 - minutesOffset;
+                }
+            }
+
+            timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
+        }
+        else {
+            timestamp = origParse ? origParse(date) : NaN;
+        }
+
+        return timestamp;
+    };
+
+    if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Date) {
+      Date.parse = Ember.Date.parse;
+    }
+  });
+define(&quot;ember-data/lib/initializers/data_adapter&quot;, 
+  [&quot;../system/debug/debug_adapter&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var DebugAdapter = __dependency1__[&quot;default&quot;];
+
+    /**
+      Configures a container with injections on Ember applications
+      for the Ember-Data store. Accepts an optional namespace argument.
+
+      @method initializeStoreInjections
+      @param {Ember.Container} container
+    */
+    __exports__[&quot;default&quot;] = function initializeDebugAdapter(container){
+      container.register('data-adapter:main', DebugAdapter);
+    };
+  });
+define(&quot;ember-data/lib/initializers/store&quot;, 
+  [&quot;../serializers&quot;,&quot;../adapters&quot;,&quot;../system/container_proxy&quot;,&quot;../system/store&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+    &quot;use strict&quot;;
+    var JSONSerializer = __dependency1__.JSONSerializer;
+    var RESTSerializer = __dependency1__.RESTSerializer;
+    var RESTAdapter = __dependency2__.RESTAdapter;
+    var ContainerProxy = __dependency3__[&quot;default&quot;];
+    var Store = __dependency4__[&quot;default&quot;];
+
+    /**
+      Configures a container for use with an Ember-Data
+      store. Accepts an optional namespace argument.
+
+      @method initializeStore
+      @param {Ember.Container} container
+      @param {Object} [application] an application namespace
+    */
+    __exports__[&quot;default&quot;] = function initializeStore(container, application){
+      Ember.deprecate('Specifying a custom Store for Ember Data on your global namespace as `App.Store` ' +
+                      'has been deprecated. Please use `App.ApplicationStore` instead.', !(application &amp;&amp; application.Store));
+
+      container.register('store:main', container.lookupFactory('store:application') || (application &amp;&amp; application.Store) || Store);
+
+      // allow older names to be looked up
+
+      var proxy = new ContainerProxy(container);
+      proxy.registerDeprecations([
+        {deprecated: 'serializer:_default',  valid: 'serializer:-default'},
+        {deprecated: 'serializer:_rest',     valid: 'serializer:-rest'},
+        {deprecated: 'adapter:_rest',        valid: 'adapter:-rest'}
+      ]);
+
+      // new go forward paths
+      container.register('serializer:-default', JSONSerializer);
+      container.register('serializer:-rest', RESTSerializer);
+      container.register('adapter:-rest', RESTAdapter);
+
+      // Eagerly generate the store so defaultStore is populated.
+      // TODO: Do this in a finisher hook
+      container.lookup('store:main');
+    };
+  });
+define(&quot;ember-data/lib/initializers/store_injections&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    /**
+      Configures a container with injections on Ember applications
+      for the Ember-Data store. Accepts an optional namespace argument.
+
+      @method initializeStoreInjections
+      @param {Ember.Container} container
+    */
+    __exports__[&quot;default&quot;] = function initializeStoreInjections(container){
+      container.injection('controller',   'store', 'store:main');
+      container.injection('route',        'store', 'store:main');
+      container.injection('serializer',   'store', 'store:main');
+      container.injection('data-adapter', 'store', 'store:main');
+    };
+  });
+define(&quot;ember-data/lib/initializers/transforms&quot;, 
+  [&quot;../transforms&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var BooleanTransform = __dependency1__.BooleanTransform;
+    var DateTransform = __dependency1__.DateTransform;
+    var StringTransform = __dependency1__.StringTransform;
+    var NumberTransform = __dependency1__.NumberTransform;
+
+    /**
+      Configures a container for use with Ember-Data
+      transforms.
+
+      @method initializeTransforms
+      @param {Ember.Container} container
+    */
+    __exports__[&quot;default&quot;] = function initializeTransforms(container){
+      container.register('transform:boolean', BooleanTransform);
+      container.register('transform:date',    DateTransform);
+      container.register('transform:number',  NumberTransform);
+      container.register('transform:string',  StringTransform);
+    };
+  });
+define(&quot;ember-data/lib/main&quot;, 
+  [&quot;./core&quot;,&quot;./ext/date&quot;,&quot;./system/store&quot;,&quot;./system/model&quot;,&quot;./system/changes&quot;,&quot;./system/adapter&quot;,&quot;./system/debug&quot;,&quot;./system/record_arrays&quot;,&quot;./system/record_array_manager&quot;,&quot;./adapters&quot;,&quot;./serializers/json_serializer&quot;,&quot;./serializers/rest_serializer&quot;,&quot;../../ember-inflector/lib/main&quot;,&quot;../../activemodel-adapter/lib/main&quot;,&quot;./transforms&quot;,&quot;./system/relationships&quot;,&quot;./ember-initializer&quot;,&quot;./setup-container&quot;,&quot;./system/container_proxy&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      Ember Data
+
+      @module ember-data
+      @main ember-data
+    */
+
+    // support RSVP 2.x via resolve,  but prefer RSVP 3.x's Promise.cast
+    Ember.RSVP.Promise.cast = Ember.RSVP.Promise.cast || Ember.RSVP.resolve;
+
+    var DS = __dependency1__[&quot;default&quot;];
+
+    var Store = __dependency3__.Store;
+    var PromiseArray = __dependency3__.PromiseArray;
+    var PromiseObject = __dependency3__.PromiseObject;
+    var Model = __dependency4__.Model;
+    var Errors = __dependency4__.Errors;
+    var RootState = __dependency4__.RootState;
+    var attr = __dependency4__.attr;
+    var AttributeChange = __dependency5__.AttributeChange;
+    var RelationshipChange = __dependency5__.RelationshipChange;
+    var RelationshipChangeAdd = __dependency5__.RelationshipChangeAdd;
+    var RelationshipChangeRemove = __dependency5__.RelationshipChangeRemove;
+    var OneToManyChange = __dependency5__.OneToManyChange;
+    var ManyToNoneChange = __dependency5__.ManyToNoneChange;
+    var OneToOneChange = __dependency5__.OneToOneChange;
+    var ManyToManyChange = __dependency5__.ManyToManyChange;
+    var InvalidError = __dependency6__.InvalidError;
+    var Adapter = __dependency6__.Adapter;
+    var DebugAdapter = __dependency7__[&quot;default&quot;];
+    var RecordArray = __dependency8__.RecordArray;
+    var FilteredRecordArray = __dependency8__.FilteredRecordArray;
+    var AdapterPopulatedRecordArray = __dependency8__.AdapterPopulatedRecordArray;
+    var ManyArray = __dependency8__.ManyArray;
+    var RecordArrayManager = __dependency9__[&quot;default&quot;];
+    var RESTAdapter = __dependency10__.RESTAdapter;
+    var FixtureAdapter = __dependency10__.FixtureAdapter;
+    var JSONSerializer = __dependency11__[&quot;default&quot;];
+    var RESTSerializer = __dependency12__[&quot;default&quot;];
+    var ActiveModelAdapter = __dependency14__.ActiveModelAdapter;
+    var ActiveModelSerializer = __dependency14__.ActiveModelSerializer;
+    var EmbeddedRecordsMixin = __dependency14__.EmbeddedRecordsMixin;
+
+    var Transform = __dependency15__.Transform;
+    var DateTransform = __dependency15__.DateTransform;
+    var NumberTransform = __dependency15__.NumberTransform;
+    var StringTransform = __dependency15__.StringTransform;
+    var BooleanTransform = __dependency15__.BooleanTransform;
+
+    var hasMany = __dependency16__.hasMany;
+    var belongsTo = __dependency16__.belongsTo;
+    var setupContainer = __dependency18__[&quot;default&quot;];
+
+    var ContainerProxy = __dependency19__[&quot;default&quot;];
+
+    DS.Store         = Store;
+    DS.PromiseArray  = PromiseArray;
+    DS.PromiseObject = PromiseObject;
+
+    DS.Model     = Model;
+    DS.RootState = RootState;
+    DS.attr      = attr;
+    DS.Errors    = Errors;
+
+    DS.AttributeChange       = AttributeChange;
+    DS.RelationshipChange    = RelationshipChange;
+    DS.RelationshipChangeAdd = RelationshipChangeAdd;
+    DS.OneToManyChange       = OneToManyChange;
+    DS.ManyToNoneChange      = OneToManyChange;
+    DS.OneToOneChange        = OneToOneChange;
+    DS.ManyToManyChange      = ManyToManyChange;
+
+    DS.Adapter      = Adapter;
+    DS.InvalidError = InvalidError;
+
+    DS.DebugAdapter = DebugAdapter;
+
+    DS.RecordArray                 = RecordArray;
+    DS.FilteredRecordArray         = FilteredRecordArray;
+    DS.AdapterPopulatedRecordArray = AdapterPopulatedRecordArray;
+    DS.ManyArray                   = ManyArray;
+
+    DS.RecordArrayManager = RecordArrayManager;
+
+    DS.RESTAdapter    = RESTAdapter;
+    DS.FixtureAdapter = FixtureAdapter;
+
+    DS.RESTSerializer = RESTSerializer;
+    DS.JSONSerializer = JSONSerializer;
+
+    DS.Transform       = Transform;
+    DS.DateTransform   = DateTransform;
+    DS.StringTransform = StringTransform;
+    DS.NumberTransform = NumberTransform;
+    DS.BooleanTransform = BooleanTransform;
+
+    DS.ActiveModelAdapter    = ActiveModelAdapter;
+    DS.ActiveModelSerializer = ActiveModelSerializer;
+    DS.EmbeddedRecordsMixin  = EmbeddedRecordsMixin;
+
+    DS.belongsTo = belongsTo;
+    DS.hasMany   = hasMany;
+
+    DS.ContainerProxy = ContainerProxy;
+
+    DS._setupContainer = setupContainer;
+
+    Ember.lookup.DS = DS;
+
+    __exports__[&quot;default&quot;] = DS;
+  });
+define(&quot;ember-data/lib/serializers&quot;, 
+  [&quot;./serializers/json_serializer&quot;,&quot;./serializers/rest_serializer&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    var JSONSerializer = __dependency1__[&quot;default&quot;];
+    var RESTSerializer = __dependency2__[&quot;default&quot;];
+
+    __exports__.JSONSerializer = JSONSerializer;
+    __exports__.RESTSerializer = RESTSerializer;
+  });
+define(&quot;ember-data/lib/serializers/json_serializer&quot;, 
+  [&quot;../system/changes&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var RelationshipChange = __dependency1__.RelationshipChange;
+    var get = Ember.get, set = Ember.set, isNone = Ember.isNone,
+        map = Ember.ArrayPolyfills.map;
+
+    /**
+      In Ember Data a Serializer is used to serialize and deserialize
+      records when they are transferred in and out of an external source.
+      This process involves normalizing property names, transforming
+      attribute values and serializing relationships.
+
+      For maximum performance Ember Data recommends you use the
+      [RESTSerializer](DS.RESTSerializer.html) or one of its subclasses.
+
+      `JSONSerializer` is useful for simpler or legacy backends that may
+      not support the http://jsonapi.org/ spec.
+
+      @class JSONSerializer
+      @namespace DS
+    */
+    var JSONSerializer = Ember.Object.extend({
+      /**
+        The primaryKey is used when serializing and deserializing
+        data. Ember Data always uses the `id` property to store the id of
+        the record. The external source may not always follow this
+        convention. In these cases it is useful to override the
+        primaryKey property to match the primaryKey of your external
+        store.
+
+        Example
+
+        ```javascript
+        App.ApplicationSerializer = DS.JSONSerializer.extend({
+          primaryKey: '_id'
+        });
+        ```
+
+        @property primaryKey
+        @type {String}
+        @default 'id'
+      */
+      primaryKey: 'id',
+
+      /**
+        The `attrs` object can be used to declare a simple mapping between
+        property names on `DS.Model` records and payload keys in the
+        serialized JSON object representing the record. An object with the
+        propery `key` can also be used to designate the attribute's key on
+        the response payload.
+
+        Example
+
+        ```javascript
+        App.Person = DS.Model.extend({
+          firstName: DS.attr('string'),
+          lastName: DS.attr('string'),
+          occupation: DS.attr('string'),
+          admin: DS.attr('boolean')
+        });
+
+        App.PersonSerializer = DS.JSONSerializer.extend({
+          attrs: {
+            admin: 'is_admin',
+            occupation: {key: 'career'}
+          }
+        });
+        ```
+
+        @property attrs
+        @type {Object}
+      */
+
+      /**
+       Given a subclass of `DS.Model` and a JSON object this method will
+       iterate through each attribute of the `DS.Model` and invoke the
+       `DS.Transform#deserialize` method on the matching property of the
+       JSON object.  This method is typically called after the
+       serializer's `normalize` method.
+
+       @method applyTransforms
+       @private
+       @param {subclass of DS.Model} type
+       @param {Object} data The data to transform
+       @return {Object} data The transformed data object
+      */
+      applyTransforms: function(type, data) {
+        type.eachTransformedAttribute(function(key, type) {
+          var transform = this.transformFor(type);
+          data[key] = transform.deserialize(data[key]);
+        }, this);
+
+        return data;
+      },
+
+      /**
+        Normalizes a part of the JSON payload returned by
+        the server. You should override this method, munge the hash
+        and call super if you have generic normalization to do.
+
+        It takes the type of the record that is being normalized
+        (as a DS.Model class), the property where the hash was
+        originally found, and the hash to normalize.
+
+        You can use this method, for example, to normalize underscored keys to camelized
+        or other general-purpose normalizations.
+
+        Example
+
+        ```javascript
+        App.ApplicationSerializer = DS.JSONSerializer.extend({
+          normalize: function(type, hash) {
+            var fields = Ember.get(type, 'fields');
+            fields.forEach(function(field) {
+              var payloadField = Ember.String.underscore(field);
+              if (field === payloadField) { return; }
+
+              hash[field] = hash[payloadField];
+              delete hash[payloadField];
+            });
+            return this._super.apply(this, arguments);
+          }
+        });
+        ```
+
+        @method normalize
+        @param {subclass of DS.Model} type
+        @param {Object} hash
+        @return {Object}
+      */
+      normalize: function(type, hash) {
+        if (!hash) { return hash; }
+
+        this.normalizeId(hash);
+        this.normalizeUsingDeclaredMapping(type, hash);
+        this.applyTransforms(type, hash);
+        return hash;
+      },
+
+      /**
+        @method normalizeUsingDeclaredMapping
+        @private
+      */
+      normalizeUsingDeclaredMapping: function(type, hash) {
+        var attrs = get(this, 'attrs'), payloadKey, key;
+
+        if (attrs) {
+          for (key in attrs) {
+            payloadKey = attrs[key];
+            if (payloadKey &amp;&amp; payloadKey.key) {
+              payloadKey = payloadKey.key;
+            }
+            if (typeof payloadKey === 'string') {
+              hash[key] = hash[payloadKey];
+              delete hash[payloadKey];
+            }
+          }
+        }
+      },
+      /**
+        @method normalizeId
+        @private
+      */
+      normalizeId: function(hash) {
+        var primaryKey = get(this, 'primaryKey');
+
+        if (primaryKey === 'id') { return; }
+
+        hash.id = hash[primaryKey];
+        delete hash[primaryKey];
+      },
+
+      // SERIALIZE
+      /**
+        Called when a record is saved in order to convert the
+        record into JSON.
+
+        By default, it creates a JSON object with a key for
+        each attribute and belongsTo relationship.
+
+        For example, consider this model:
+
+        ```javascript
+        App.Comment = DS.Model.extend({
+          title: DS.attr(),
+          body: DS.attr(),
+
+          author: DS.belongsTo('user')
+        });
+        ```
+
+        The default serialization would create a JSON object like:
+
+        ```javascript
+        {
+          &quot;title&quot;: &quot;Rails is unagi&quot;,
+          &quot;body&quot;: &quot;Rails? Omakase? O_O&quot;,
+          &quot;author&quot;: 12
+        }
+        ```
+
+        By default, attributes are passed through as-is, unless
+        you specified an attribute type (`DS.attr('date')`). If
+        you specify a transform, the JavaScript value will be
+        serialized when inserted into the JSON hash.
+
+        By default, belongs-to relationships are converted into
+        IDs when inserted into the JSON hash.
+
+        ## IDs
+
+        `serialize` takes an options hash with a single option:
+        `includeId`. If this option is `true`, `serialize` will,
+        by default include the ID in the JSON object it builds.
+
+        The adapter passes in `includeId: true` when serializing
+        a record for `createRecord`, but not for `updateRecord`.
+
+        ## Customization
+
+        Your server may expect a different JSON format than the
+        built-in serialization format.
+
+        In that case, you can implement `serialize` yourself and
+        return a JSON hash of your choosing.
+
+        ```javascript
+        App.PostSerializer = DS.JSONSerializer.extend({
+          serialize: function(post, options) {
+            var json = {
+              POST_TTL: post.get('title'),
+              POST_BDY: post.get('body'),
+              POST_CMS: post.get('comments').mapProperty('id')
+            }
+
+            if (options.includeId) {
+              json.POST_ID_ = post.get('id');
+            }
+
+            return json;
+          }
+        });
+        ```
+
+        ## Customizing an App-Wide Serializer
+
+        If you want to define a serializer for your entire
+        application, you'll probably want to use `eachAttribute`
+        and `eachRelationship` on the record.
+
+        ```javascript
+        App.ApplicationSerializer = DS.JSONSerializer.extend({
+          serialize: function(record, options) {
+            var json = {};
+
+            record.eachAttribute(function(name) {
+              json[serverAttributeName(name)] = record.get(name);
+            })
+
+            record.eachRelationship(function(name, relationship) {
+              if (relationship.kind === 'hasMany') {
+                json[serverHasManyName(name)] = record.get(name).mapBy('id');
+              }
+            });
+
+            if (options.includeId) {
+              json.ID_ = record.get('id');
+            }
+
+            return json;
+          }
+        });
+
+        function serverAttributeName(attribute) {
+          return attribute.underscore().toUpperCase();
+        }
+
+        function serverHasManyName(name) {
+          return serverAttributeName(name.singularize()) + &quot;_IDS&quot;;
+        }
+        ```
+
+        This serializer will generate JSON that looks like this:
+
+        ```javascript
+        {
+          &quot;TITLE&quot;: &quot;Rails is omakase&quot;,
+          &quot;BODY&quot;: &quot;Yep. Omakase.&quot;,
+          &quot;COMMENT_IDS&quot;: [ 1, 2, 3 ]
+        }
+        ```
+
+        ## Tweaking the Default JSON
+
+        If you just want to do some small tweaks on the default JSON,
+        you can call super first and make the tweaks on the returned
+        JSON.
+
+        ```javascript
+        App.PostSerializer = DS.JSONSerializer.extend({
+          serialize: function(record, options) {
+            var json = this._super.apply(this, arguments);
+
+            json.subject = json.title;
+            delete json.title;
+
+            return json;
+          }
+        });
+        ```
+
+        @method serialize
+        @param {subclass of DS.Model} record
+        @param {Object} options
+        @return {Object} json
+      */
+      serialize: function(record, options) {
+        var json = {};
+
+        if (options &amp;&amp; options.includeId) {
+          var id = get(record, 'id');
+
+          if (id) {
+            json[get(this, 'primaryKey')] = id;
+          }
+        }
+
+        record.eachAttribute(function(key, attribute) {
+          this.serializeAttribute(record, json, key, attribute);
+        }, this);
+
+        record.eachRelationship(function(key, relationship) {
+          if (relationship.kind === 'belongsTo') {
+            this.serializeBelongsTo(record, json, relationship);
+          } else if (relationship.kind === 'hasMany') {
+            this.serializeHasMany(record, json, relationship);
+          }
+        }, this);
+
+        return json;
+      },
+
+      /**
+       `serializeAttribute` can be used to customize how `DS.attr`
+       properties are serialized
+
+       For example if you wanted to ensure all your attributes were always
+       serialized as properties on an `attributes` object you could
+       write:
+
+       ```javascript
+       App.ApplicationSerializer = DS.JSONSerializer.extend({
+         serializeAttribute: function(record, json, key, attributes) {
+           json.attributes = json.attributes || {};
+           this._super(record, json.attributes, key, attributes);
+         }
+       });
+       ```
+
+       @method serializeAttribute
+       @param {DS.Model} record
+       @param {Object} json
+       @param {String} key
+       @param {Object} attribute
+      */
+      serializeAttribute: function(record, json, key, attribute) {
+        var attrs = get(this, 'attrs');
+        var value = get(record, key), type = attribute.type;
+
+        if (type) {
+          var transform = this.transformFor(type);
+          value = transform.serialize(value);
+        }
+
+        // if provided, use the mapping provided by `attrs` in
+        // the serializer
+        key = attrs &amp;&amp; attrs[key] || (this.keyForAttribute ? this.keyForAttribute(key) : key);
+
+        json[key] = value;
+      },
+
+      /**
+       `serializeBelongsTo` can be used to customize how `DS.belongsTo`
+       properties are serialized.
+
+       Example
+
+       ```javascript
+       App.PostSerializer = DS.JSONSerializer.extend({
+         serializeBelongsTo: function(record, json, relationship) {
+           var key = relationship.key;
+
+           var belongsTo = get(record, key);
+
+           key = this.keyForRelationship ? this.keyForRelationship(key, &quot;belongsTo&quot;) : key;
+
+           json[key] = Ember.isNone(belongsTo) ? belongsTo : belongsTo.toJSON();
+         }
+       });
+       ```
+
+       @method serializeBelongsTo
+       @param {DS.Model} record
+       @param {Object} json
+       @param {Object} relationship
+      */
+      serializeBelongsTo: function(record, json, relationship) {
+        var key = relationship.key;
+
+        var belongsTo = get(record, key);
+
+        key = this.keyForRelationship ? this.keyForRelationship(key, &quot;belongsTo&quot;) : key;
+
+        if (isNone(belongsTo)) {
+          json[key] = belongsTo;
+        } else {
+          json[key] = get(belongsTo, 'id');
+        }
+
+        if (relationship.options.polymorphic) {
+          this.serializePolymorphicType(record, json, relationship);
+        }
+      },
+
+      /**
+       `serializeHasMany` can be used to customize how `DS.hasMany`
+       properties are serialized.
+
+       Example
+
+       ```javascript
+       App.PostSerializer = DS.JSONSerializer.extend({
+         serializeHasMany: function(record, json, relationship) {
+           var key = relationship.key;
+           if (key === 'comments') {
+             return;
+           } else {
+             this._super.apply(this, arguments);
+           }
+         }
+       });
+       ```
+
+       @method serializeHasMany
+       @param {DS.Model} record
+       @param {Object} json
+       @param {Object} relationship
+      */
+      serializeHasMany: function(record, json, relationship) {
+        var key = relationship.key;
+        var payloadKey = this.keyForRelationship ? this.keyForRelationship(key, &quot;hasMany&quot;) : key;
+        var relationshipType = RelationshipChange.determineRelationshipType(record.constructor, relationship);
+
+        if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany') {
+          json[payloadKey] = get(record, key).mapBy('id');
+          // TODO support for polymorphic manyToNone and manyToMany relationships
+        }
+      },
+
+      /**
+        You can use this method to customize how polymorphic objects are
+        serialized. Objects are considered to be polymorphic if
+        `{polymorphic: true}` is pass as the second argument to the
+        `DS.belongsTo` function.
+
+        Example
+
+        ```javascript
+        App.CommentSerializer = DS.JSONSerializer.extend({
+          serializePolymorphicType: function(record, json, relationship) {
+            var key = relationship.key,
+                belongsTo = get(record, key);
+            key = this.keyForAttribute ? this.keyForAttribute(key) : key;
+            json[key + &quot;_type&quot;] = belongsTo.constructor.typeKey;
+          }
+        });
+       ```
+
+        @method serializePolymorphicType
+        @param {DS.Model} record
+        @param {Object} json
+        @param {Object} relationship
+      */
+      serializePolymorphicType: Ember.K,
+
+      // EXTRACT
+
+      /**
+        The `extract` method is used to deserialize payload data from the
+        server. By default the `JSONSerializer` does not push the records
+        into the store. However records that subclass `JSONSerializer`
+        such as the `RESTSerializer` may push records into the store as
+        part of the extract call.
+
+        This method delegates to a more specific extract method based on
+        the `requestType`.
+
+        Example
+
+        ```javascript
+        var get = Ember.get;
+        socket.on('message', function(message) {
+          var modelName = message.model;
+          var data = message.data;
+          var type = store.modelFor(modelName);
+          var serializer = store.serializerFor(type.typeKey);
+          var record = serializer.extract(store, type, data, get(data, 'id'), 'single');
+          store.push(modelName, record);
+        });
+        ```
+
+        @method extract
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @param {String or Number} id
+        @param {String} requestType
+        @return {Object} json The deserialized payload
+      */
+      extract: function(store, type, payload, id, requestType) {
+        this.extractMeta(store, type, payload);
+
+        var specificExtract = &quot;extract&quot; + requestType.charAt(0).toUpperCase() + requestType.substr(1);
+        return this[specificExtract](store, type, payload, id, requestType);
+      },
+
+      /**
+        `extractFindAll` is a hook into the extract method used when a
+        call is made to `DS.Store#findAll`. By default this method is an
+        alias for [extractArray](#method_extractArray).
+
+        @method extractFindAll
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Array} array An array of deserialized objects
+      */
+      extractFindAll: function(store, type, payload){
+        return this.extractArray(store, type, payload);
+      },
+      /**
+        `extractFindQuery` is a hook into the extract method used when a
+        call is made to `DS.Store#findQuery`. By default this method is an
+        alias for [extractArray](#method_extractArray).
+
+        @method extractFindQuery
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Array} array An array of deserialized objects
+      */
+      extractFindQuery: function(store, type, payload){
+        return this.extractArray(store, type, payload);
+      },
+      /**
+        `extractFindMany` is a hook into the extract method used when a
+        call is made to `DS.Store#findMany`. By default this method is
+        alias for [extractArray](#method_extractArray).
+
+        @method extractFindMany
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Array} array An array of deserialized objects
+      */
+      extractFindMany: function(store, type, payload){
+        return this.extractArray(store, type, payload);
+      },
+      /**
+        `extractFindHasMany` is a hook into the extract method used when a
+        call is made to `DS.Store#findHasMany`. By default this method is
+        alias for [extractArray](#method_extractArray).
+
+        @method extractFindHasMany
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Array} array An array of deserialized objects
+      */
+      extractFindHasMany: function(store, type, payload){
+        return this.extractArray(store, type, payload);
+      },
+
+      /**
+        `extractCreateRecord` is a hook into the extract method used when a
+        call is made to `DS.Store#createRecord`. By default this method is
+        alias for [extractSave](#method_extractSave).
+
+        @method extractCreateRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractCreateRecord: function(store, type, payload) {
+        return this.extractSave(store, type, payload);
+      },
+      /**
+        `extractUpdateRecord` is a hook into the extract method used when
+        a call is made to `DS.Store#update`. By default this method is alias
+        for [extractSave](#method_extractSave).
+
+        @method extractUpdateRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractUpdateRecord: function(store, type, payload) {
+        return this.extractSave(store, type, payload);
+      },
+      /**
+        `extractDeleteRecord` is a hook into the extract method used when
+        a call is made to `DS.Store#deleteRecord`. By default this method is
+        alias for [extractSave](#method_extractSave).
+
+        @method extractDeleteRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractDeleteRecord: function(store, type, payload) {
+        return this.extractSave(store, type, payload);
+      },
+
+      /**
+        `extractFind` is a hook into the extract method used when
+        a call is made to `DS.Store#find`. By default this method is
+        alias for [extractSingle](#method_extractSingle).
+
+        @method extractFind
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractFind: function(store, type, payload) {
+        return this.extractSingle(store, type, payload);
+      },
+      /**
+        `extractFindBelongsTo` is a hook into the extract method used when
+        a call is made to `DS.Store#findBelongsTo`. By default this method is
+        alias for [extractSingle](#method_extractSingle).
+
+        @method extractFindBelongsTo
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractFindBelongsTo: function(store, type, payload) {
+        return this.extractSingle(store, type, payload);
+      },
+      /**
+        `extractSave` is a hook into the extract method used when a call
+        is made to `DS.Model#save`. By default this method is alias
+        for [extractSingle](#method_extractSingle).
+
+        @method extractSave
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractSave: function(store, type, payload) {
+        return this.extractSingle(store, type, payload);
+      },
+
+      /**
+        `extractSingle` is used to deserialize a single record returned
+        from the adapter.
+
+        Example
+
+        ```javascript
+        App.PostSerializer = DS.JSONSerializer.extend({
+          extractSingle: function(store, type, payload) {
+            payload.comments = payload._embedded.comment;
+            delete payload._embedded;
+
+            return this._super(store, type, payload);
+          },
+        });
+        ```
+
+        @method extractSingle
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Object} json The deserialized payload
+      */
+      extractSingle: function(store, type, payload) {
+        return this.normalize(type, payload);
+      },
+
+      /**
+        `extractArray` is used to deserialize an array of records
+        returned from the adapter.
+
+        Example
+
+        ```javascript
+        App.PostSerializer = DS.JSONSerializer.extend({
+          extractArray: function(store, type, payload) {
+            return payload.map(function(json) {
+              return this.extractSingle(store, type, json);
+            }, this);
+          }
+        });
+        ```
+
+        @method extractArray
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+        @return {Array} array An array of deserialized objects
+      */
+      extractArray: function(store, type, arrayPayload) {
+        var serializer = this;
+        return map.call(arrayPayload, function(singlePayload) {
+          return serializer.normalize(type, singlePayload);
+        });
+      },
+
+      /**
+        `extractMeta` is used to deserialize any meta information in the
+        adapter payload. By default Ember Data expects meta information to
+        be located on the `meta` property of the payload object.
+
+        Example
+
+        ```javascript
+        App.PostSerializer = DS.JSONSerializer.extend({
+          extractMeta: function(store, type, payload) {
+            if (payload &amp;&amp; payload._pagination) {
+              store.metaForType(type, payload._pagination);
+              delete payload._pagination;
+            }
+          }
+        });
+        ```
+
+        @method extractMeta
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} payload
+      */
+      extractMeta: function(store, type, payload) {
+        if (payload &amp;&amp; payload.meta) {
+          store.metaForType(type, payload.meta);
+          delete payload.meta;
+        }
+      },
+
+      /**
+       `keyForAttribute` can be used to define rules for how to convert an
+       attribute name in your model to a key in your JSON.
+
+       Example
+
+       ```javascript
+       App.ApplicationSerializer = DS.RESTSerializer.extend({
+         keyForAttribute: function(attr) {
+           return Ember.String.underscore(attr).toUpperCase();
+         }
+       });
+       ```
+
+       @method keyForAttribute
+       @param {String} key
+       @return {String} normalized key
+      */
+
+
+      /**
+       `keyForRelationship` can be used to define a custom key when
+       serializing relationship properties. By default `JSONSerializer`
+       does not provide an implementation of this method.
+
+       Example
+
+        ```javascript
+        App.PostSerializer = DS.JSONSerializer.extend({
+          keyForRelationship: function(key, relationship) {
+             return 'rel_' + Ember.String.underscore(key);
+          }
+        });
+        ```
+
+       @method keyForRelationship
+       @param {String} key
+       @param {String} relationship type
+       @return {String} normalized key
+      */
+
+      // HELPERS
+
+      /**
+       @method transformFor
+       @private
+       @param {String} attributeType
+       @param {Boolean} skipAssertion
+       @return {DS.Transform} transform
+      */
+      transformFor: function(attributeType, skipAssertion) {
+        var transform = this.container.lookup('transform:' + attributeType);
+        Ember.assert(&quot;Unable to find transform for '&quot; + attributeType + &quot;'&quot;, skipAssertion || !!transform);
+        return transform;
+      }
+    });
+
+    __exports__[&quot;default&quot;] = JSONSerializer;
+  });
+define(&quot;ember-data/lib/serializers/rest_serializer&quot;, 
+  [&quot;./json_serializer&quot;,&quot;ember-inflector/lib/system/string&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var JSONSerializer = __dependency1__[&quot;default&quot;];
+    var get = Ember.get, set = Ember.set;
+    var forEach = Ember.ArrayPolyfills.forEach;
+    var map = Ember.ArrayPolyfills.map;
+
+    var singularize = __dependency2__.singularize;
+    var camelize = Ember.String.camelize;
+
+    function coerceId(id) {
+      return id == null ? null : id+'';
+    }
+
+    /**
+      Normally, applications will use the `RESTSerializer` by implementing
+      the `normalize` method and individual normalizations under
+      `normalizeHash`.
+
+      This allows you to do whatever kind of munging you need, and is
+      especially useful if your server is inconsistent and you need to
+      do munging differently for many different kinds of responses.
+
+      See the `normalize` documentation for more information.
+
+      ## Across the Board Normalization
+
+      There are also a number of hooks that you might find useful to defined
+      across-the-board rules for your payload. These rules will be useful
+      if your server is consistent, or if you're building an adapter for
+      an infrastructure service, like Parse, and want to encode service
+      conventions.
+
+      For example, if all of your keys are underscored and all-caps, but
+      otherwise consistent with the names you use in your models, you
+      can implement across-the-board rules for how to convert an attribute
+      name in your model to a key in your JSON.
+
+      ```js
+      App.ApplicationSerializer = DS.RESTSerializer.extend({
+        keyForAttribute: function(attr) {
+          return Ember.String.underscore(attr).toUpperCase();
+        }
+      });
+      ```
+
+      You can also implement `keyForRelationship`, which takes the name
+      of the relationship as the first parameter, and the kind of
+      relationship (`hasMany` or `belongsTo`) as the second parameter.
+
+      @class RESTSerializer
+      @namespace DS
+      @extends DS.JSONSerializer
+    */
+    var RESTSerializer = JSONSerializer.extend({
+      /**
+        If you want to do normalizations specific to some part of the payload, you
+        can specify those under `normalizeHash`.
+
+        For example, given the following json where the the `IDs` under
+        `&quot;comments&quot;` are provided as `_id` instead of `id`.
+
+        ```javascript
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: 1,
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;comments&quot;: [ 1, 2 ]
+          },
+          &quot;comments&quot;: [{
+            &quot;_id&quot;: 1,
+            &quot;body&quot;: &quot;FIRST&quot;
+          }, {
+            &quot;_id&quot;: 2,
+            &quot;body&quot;: &quot;Rails is unagi&quot;
+          }]
+        }
+        ```
+
+        You use `normalizeHash` to normalize just the comments:
+
+        ```javascript
+        App.PostSerializer = DS.RESTSerializer.extend({
+          normalizeHash: {
+            comments: function(hash) {
+              hash.id = hash._id;
+              delete hash._id;
+              return hash;
+            }
+          }
+        });
+        ```
+
+        The key under `normalizeHash` is usually just the original key
+        that was in the original payload. However, key names will be
+        impacted by any modifications done in the `normalizePayload`
+        method. The `DS.RESTSerializer`'s default implementation makes no
+        changes to the payload keys.
+
+        @property normalizeHash
+        @type {Object}
+        @default undefined
+      */
+
+      /**
+        Normalizes a part of the JSON payload returned by
+        the server. You should override this method, munge the hash
+        and call super if you have generic normalization to do.
+
+        It takes the type of the record that is being normalized
+        (as a DS.Model class), the property where the hash was
+        originally found, and the hash to normalize.
+
+        For example, if you have a payload that looks like this:
+
+        ```js
+        {
+          &quot;post&quot;: {
+            &quot;id&quot;: 1,
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;comments&quot;: [ 1, 2 ]
+          },
+          &quot;comments&quot;: [{
+            &quot;id&quot;: 1,
+            &quot;body&quot;: &quot;FIRST&quot;
+          }, {
+            &quot;id&quot;: 2,
+            &quot;body&quot;: &quot;Rails is unagi&quot;
+          }]
+        }
+        ```
+
+        The `normalize` method will be called three times:
+
+        * With `App.Post`, `&quot;posts&quot;` and `{ id: 1, title: &quot;Rails is omakase&quot;, ... }`
+        * With `App.Comment`, `&quot;comments&quot;` and `{ id: 1, body: &quot;FIRST&quot; }`
+        * With `App.Comment`, `&quot;comments&quot;` and `{ id: 2, body: &quot;Rails is unagi&quot; }`
+
+        You can use this method, for example, to normalize underscored keys to camelized
+        or other general-purpose normalizations.
+
+        If you want to do normalizations specific to some part of the payload, you
+        can specify those under `normalizeHash`.
+
+        For example, if the `IDs` under `&quot;comments&quot;` are provided as `_id` instead of
+        `id`, you can specify how to normalize just the comments:
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend({
+          normalizeHash: {
+            comments: function(hash) {
+              hash.id = hash._id;
+              delete hash._id;
+              return hash;
+            }
+          }
+        });
+        ```
+
+        The key under `normalizeHash` is just the original key that was in the original
+        payload.
+
+        @method normalize
+        @param {subclass of DS.Model} type
+        @param {Object} hash
+        @param {String} prop
+        @return {Object}
+      */
+      normalize: function(type, hash, prop) {
+        this.normalizeId(hash);
+        this.normalizeAttributes(type, hash);
+        this.normalizeRelationships(type, hash);
+
+        this.normalizeUsingDeclaredMapping(type, hash);
+
+        if (this.normalizeHash &amp;&amp; this.normalizeHash[prop]) {
+          this.normalizeHash[prop](hash);
+        }
+
+        this.applyTransforms(type, hash);
+        return hash;
+      },
+
+      /**
+        You can use this method to normalize all payloads, regardless of whether they
+        represent single records or an array.
+
+        For example, you might want to remove some extraneous data from the payload:
+
+        ```js
+        App.ApplicationSerializer = DS.RESTSerializer.extend({
+          normalizePayload: function(payload) {
+            delete payload.version;
+            delete payload.status;
+            return payload;
+          }
+        });
+        ```
+
+        @method normalizePayload
+        @param {Object} payload
+        @return {Object} the normalized payload
+      */
+      normalizePayload: function(payload) {
+        return payload;
+      },
+
+      /**
+        @method normalizeAttributes
+        @private
+      */
+      normalizeAttributes: function(type, hash) {
+        var payloadKey, key;
+
+        if (this.keyForAttribute) {
+          type.eachAttribute(function(key) {
+            payloadKey = this.keyForAttribute(key);
+            if (key === payloadKey) { return; }
+
+            hash[key] = hash[payloadKey];
+            delete hash[payloadKey];
+          }, this);
+        }
+      },
+
+      /**
+        @method normalizeRelationships
+        @private
+      */
+      normalizeRelationships: function(type, hash) {
+        var payloadKey, key;
+
+        if (this.keyForRelationship) {
+          type.eachRelationship(function(key, relationship) {
+            payloadKey = this.keyForRelationship(key, relationship.kind);
+            if (key === payloadKey) { return; }
+
+            hash[key] = hash[payloadKey];
+            delete hash[payloadKey];
+          }, this);
+        }
+      },
+
+      /**
+        Called when the server has returned a payload representing
+        a single record, such as in response to a `find` or `save`.
+
+        It is your opportunity to clean up the server's response into the normalized
+        form expected by Ember Data.
+
+        If you want, you can just restructure the top-level of your payload, and
+        do more fine-grained normalization in the `normalize` method.
+
+        For example, if you have a payload like this in response to a request for
+        post 1:
+
+        ```js
+        {
+          &quot;id&quot;: 1,
+          &quot;title&quot;: &quot;Rails is omakase&quot;,
+
+          &quot;_embedded&quot;: {
+            &quot;comment&quot;: [{
+              &quot;_id&quot;: 1,
+              &quot;comment_title&quot;: &quot;FIRST&quot;
+            }, {
+              &quot;_id&quot;: 2,
+              &quot;comment_title&quot;: &quot;Rails is unagi&quot;
+            }]
+          }
+        }
+        ```
+
+        You could implement a serializer that looks like this to get your payload
+        into shape:
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend({
+          // First, restructure the top-level so it's organized by type
+          extractSingle: function(store, type, payload, id) {
+            var comments = payload._embedded.comment;
+            delete payload._embedded;
+
+            payload = { comments: comments, post: payload };
+            return this._super(store, type, payload, id);
+          },
+
+          normalizeHash: {
+            // Next, normalize individual comments, which (after `extract`)
+            // are now located under `comments`
+            comments: function(hash) {
+              hash.id = hash._id;
+              hash.title = hash.comment_title;
+              delete hash._id;
+              delete hash.comment_title;
+              return hash;
+            }
+          }
+        })
+        ```
+
+        When you call super from your own implementation of `extractSingle`, the
+        built-in implementation will find the primary record in your normalized
+        payload and push the remaining records into the store.
+
+        The primary record is the single hash found under `post` or the first
+        element of the `posts` array.
+
+        The primary record has special meaning when the record is being created
+        for the first time or updated (`createRecord` or `updateRecord`). In
+        particular, it will update the properties of the record that was saved.
+
+        @method extractSingle
+        @param {DS.Store} store
+        @param {subclass of DS.Model} primaryType
+        @param {Object} payload
+        @param {String} recordId
+        @return {Object} the primary response to the original request
+      */
+      extractSingle: function(store, primaryType, payload, recordId) {
+        payload = this.normalizePayload(payload);
+        var primaryTypeName = primaryType.typeKey,
+            primaryRecord;
+
+        for (var prop in payload) {
+          var typeName  = this.typeForRoot(prop),
+              type = store.modelFor(typeName),
+              isPrimary = type.typeKey === primaryTypeName;
+
+          // legacy support for singular resources
+          if (isPrimary &amp;&amp; Ember.typeOf(payload[prop]) !== &quot;array&quot; ) {
+            primaryRecord = this.normalize(primaryType, payload[prop], prop);
+            continue;
+          }
+
+          /*jshint loopfunc:true*/
+          forEach.call(payload[prop], function(hash) {
+            var typeName = this.typeForRoot(prop),
+                type = store.modelFor(typeName),
+                typeSerializer = store.serializerFor(type);
+
+            hash = typeSerializer.normalize(type, hash, prop);
+
+            var isFirstCreatedRecord = isPrimary &amp;&amp; !recordId &amp;&amp; !primaryRecord,
+                isUpdatedRecord = isPrimary &amp;&amp; coerceId(hash.id) === recordId;
+
+            // find the primary record.
+            //
+            // It's either:
+            // * the record with the same ID as the original request
+            // * in the case of a newly created record that didn't have an ID, the first
+            //   record in the Array
+            if (isFirstCreatedRecord || isUpdatedRecord) {
+              primaryRecord = hash;
+            } else {
+              store.push(typeName, hash);
+            }
+          }, this);
+        }
+
+        return primaryRecord;
+      },
+
+      /**
+        Called when the server has returned a payload representing
+        multiple records, such as in response to a `findAll` or `findQuery`.
+
+        It is your opportunity to clean up the server's response into the normalized
+        form expected by Ember Data.
+
+        If you want, you can just restructure the top-level of your payload, and
+        do more fine-grained normalization in the `normalize` method.
+
+        For example, if you have a payload like this in response to a request for
+        all posts:
+
+        ```js
+        {
+          &quot;_embedded&quot;: {
+            &quot;post&quot;: [{
+              &quot;id&quot;: 1,
+              &quot;title&quot;: &quot;Rails is omakase&quot;
+            }, {
+              &quot;id&quot;: 2,
+              &quot;title&quot;: &quot;The Parley Letter&quot;
+            }],
+            &quot;comment&quot;: [{
+              &quot;_id&quot;: 1,
+              &quot;comment_title&quot;: &quot;Rails is unagi&quot;
+              &quot;post_id&quot;: 1
+            }, {
+              &quot;_id&quot;: 2,
+              &quot;comment_title&quot;: &quot;Don't tread on me&quot;,
+              &quot;post_id&quot;: 2
+            }]
+          }
+        }
+        ```
+
+        You could implement a serializer that looks like this to get your payload
+        into shape:
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend({
+          // First, restructure the top-level so it's organized by type
+          // and the comments are listed under a post's `comments` key.
+          extractArray: function(store, type, payload) {
+            var posts = payload._embedded.post;
+            var comments = [];
+            var postCache = {};
+
+            posts.forEach(function(post) {
+              post.comments = [];
+              postCache[post.id] = post;
+            });
+
+            payload._embedded.comment.forEach(function(comment) {
+              comments.push(comment);
+              postCache[comment.post_id].comments.push(comment);
+              delete comment.post_id;
+            }
+
+            payload = { comments: comments, posts: payload };
+
+            return this._super(store, type, payload);
+          },
+
+          normalizeHash: {
+            // Next, normalize individual comments, which (after `extract`)
+            // are now located under `comments`
+            comments: function(hash) {
+              hash.id = hash._id;
+              hash.title = hash.comment_title;
+              delete hash._id;
+              delete hash.comment_title;
+              return hash;
+            }
+          }
+        })
+        ```
+
+        When you call super from your own implementation of `extractArray`, the
+        built-in implementation will find the primary array in your normalized
+        payload and push the remaining records into the store.
+
+        The primary array is the array found under `posts`.
+
+        The primary record has special meaning when responding to `findQuery`
+        or `findHasMany`. In particular, the primary array will become the
+        list of records in the record array that kicked off the request.
+
+        If your primary array contains secondary (embedded) records of the same type,
+        you cannot place these into the primary array `posts`. Instead, place the
+        secondary items into an underscore prefixed property `_posts`, which will
+        push these items into the store and will not affect the resulting query.
+
+        @method extractArray
+        @param {DS.Store} store
+        @param {subclass of DS.Model} primaryType
+        @param {Object} payload
+        @return {Array} The primary array that was returned in response
+          to the original query.
+      */
+      extractArray: function(store, primaryType, payload) {
+        payload = this.normalizePayload(payload);
+
+        var primaryTypeName = primaryType.typeKey,
+            primaryArray;
+
+        for (var prop in payload) {
+          var typeKey = prop,
+              forcedSecondary = false;
+
+          if (prop.charAt(0) === '_') {
+            forcedSecondary = true;
+            typeKey = prop.substr(1);
+          }
+
+          var typeName = this.typeForRoot(typeKey),
+              type = store.modelFor(typeName),
+              typeSerializer = store.serializerFor(type),
+              isPrimary = (!forcedSecondary &amp;&amp; (type.typeKey === primaryTypeName));
+
+          /*jshint loopfunc:true*/
+          var normalizedArray = map.call(payload[prop], function(hash) {
+            return typeSerializer.normalize(type, hash, prop);
+          }, this);
+
+          if (isPrimary) {
+            primaryArray = normalizedArray;
+          } else {
+            store.pushMany(typeName, normalizedArray);
+          }
+        }
+
+        return primaryArray;
+      },
+
+      /**
+        This method allows you to push a payload containing top-level
+        collections of records organized per type.
+
+        ```js
+        {
+          &quot;posts&quot;: [{
+            &quot;id&quot;: &quot;1&quot;,
+            &quot;title&quot;: &quot;Rails is omakase&quot;,
+            &quot;author&quot;, &quot;1&quot;,
+            &quot;comments&quot;: [ &quot;1&quot; ]
+          }],
+          &quot;comments&quot;: [{
+            &quot;id&quot;: &quot;1&quot;,
+            &quot;body&quot;: &quot;FIRST&quot;
+          }],
+          &quot;users&quot;: [{
+            &quot;id&quot;: &quot;1&quot;,
+            &quot;name&quot;: &quot;@d2h&quot;
+          }]
+        }
+        ```
+
+        It will first normalize the payload, so you can use this to push
+        in data streaming in from your server structured the same way
+        that fetches and saves are structured.
+
+        @method pushPayload
+        @param {DS.Store} store
+        @param {Object} payload
+      */
+      pushPayload: function(store, payload) {
+        payload = this.normalizePayload(payload);
+
+        for (var prop in payload) {
+          var typeName = this.typeForRoot(prop),
+              type = store.modelFor(typeName),
+              typeSerializer = store.serializerFor(type);
+
+          /*jshint loopfunc:true*/
+          var normalizedArray = map.call(Ember.makeArray(payload[prop]), function(hash) {
+            return typeSerializer.normalize(type, hash, prop);
+          }, this);
+
+          store.pushMany(typeName, normalizedArray);
+        }
+      },
+
+      /**
+        This method is used to convert each JSON root key in the payload
+        into a typeKey that it can use to look up the appropriate model for
+        that part of the payload. By default the typeKey for a model is its
+        name in camelCase, so if your JSON root key is 'fast-car' you would
+        use typeForRoot to convert it to 'fastCar' so that Ember Data finds
+        the `FastCar` model.
+
+        If you diverge from this norm you should also consider changes to
+        store._normalizeTypeKey as well.
+
+        For example, your server may return prefixed root keys like so:
+
+        ```js
+        {
+          &quot;response-fast-car&quot;: {
+            &quot;id&quot;: &quot;1&quot;,
+            &quot;name&quot;: &quot;corvette&quot;
+          }
+        }
+        ```
+
+        In order for Ember Data to know that the model corresponding to
+        the 'response-fast-car' hash is `FastCar` (typeKey: 'fastCar'),
+        you can override typeForRoot to convert 'response-fast-car' to
+        'fastCar' like so:
+
+        ```js
+        App.ApplicationSerializer = DS.RESTSerializer.extend({
+          typeForRoot: function(root) {
+            // 'response-fast-car' should become 'fast-car'
+            var subRoot = root.substring(9);
+
+            // _super normalizes 'fast-car' to 'fastCar'
+            return this._super(subRoot);
+          }
+        });
+        ```
+
+        @method typeForRoot
+        @param {String} key
+        @return {String} the model's typeKey
+      */
+      typeForRoot: function(key) {
+        return camelize(singularize(key));
+      },
+
+      // SERIALIZE
+
+      /**
+        Called when a record is saved in order to convert the
+        record into JSON.
+
+        By default, it creates a JSON object with a key for
+        each attribute and belongsTo relationship.
+
+        For example, consider this model:
+
+        ```js
+        App.Comment = DS.Model.extend({
+          title: DS.attr(),
+          body: DS.attr(),
+
+          author: DS.belongsTo('user')
+        });
+        ```
+
+        The default serialization would create a JSON object like:
+
+        ```js
+        {
+          &quot;title&quot;: &quot;Rails is unagi&quot;,
+          &quot;body&quot;: &quot;Rails? Omakase? O_O&quot;,
+          &quot;author&quot;: 12
+        }
+        ```
+
+        By default, attributes are passed through as-is, unless
+        you specified an attribute type (`DS.attr('date')`). If
+        you specify a transform, the JavaScript value will be
+        serialized when inserted into the JSON hash.
+
+        By default, belongs-to relationships are converted into
+        IDs when inserted into the JSON hash.
+
+        ## IDs
+
+        `serialize` takes an options hash with a single option:
+        `includeId`. If this option is `true`, `serialize` will,
+        by default include the ID in the JSON object it builds.
+
+        The adapter passes in `includeId: true` when serializing
+        a record for `createRecord`, but not for `updateRecord`.
+
+        ## Customization
+
+        Your server may expect a different JSON format than the
+        built-in serialization format.
+
+        In that case, you can implement `serialize` yourself and
+        return a JSON hash of your choosing.
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend({
+          serialize: function(post, options) {
+            var json = {
+              POST_TTL: post.get('title'),
+              POST_BDY: post.get('body'),
+              POST_CMS: post.get('comments').mapProperty('id')
+            }
+
+            if (options.includeId) {
+              json.POST_ID_ = post.get('id');
+            }
+
+            return json;
+          }
+        });
+        ```
+
+        ## Customizing an App-Wide Serializer
+
+        If you want to define a serializer for your entire
+        application, you'll probably want to use `eachAttribute`
+        and `eachRelationship` on the record.
+
+        ```js
+        App.ApplicationSerializer = DS.RESTSerializer.extend({
+          serialize: function(record, options) {
+            var json = {};
+
+            record.eachAttribute(function(name) {
+              json[serverAttributeName(name)] = record.get(name);
+            })
+
+            record.eachRelationship(function(name, relationship) {
+              if (relationship.kind === 'hasMany') {
+                json[serverHasManyName(name)] = record.get(name).mapBy('id');
+              }
+            });
+
+            if (options.includeId) {
+              json.ID_ = record.get('id');
+            }
+
+            return json;
+          }
+        });
+
+        function serverAttributeName(attribute) {
+          return attribute.underscore().toUpperCase();
+        }
+
+        function serverHasManyName(name) {
+          return serverAttributeName(name.singularize()) + &quot;_IDS&quot;;
+        }
+        ```
+
+        This serializer will generate JSON that looks like this:
+
+        ```js
+        {
+          &quot;TITLE&quot;: &quot;Rails is omakase&quot;,
+          &quot;BODY&quot;: &quot;Yep. Omakase.&quot;,
+          &quot;COMMENT_IDS&quot;: [ 1, 2, 3 ]
+        }
+        ```
+
+        ## Tweaking the Default JSON
+
+        If you just want to do some small tweaks on the default JSON,
+        you can call super first and make the tweaks on the returned
+        JSON.
+
+        ```js
+        App.PostSerializer = DS.RESTSerializer.extend({
+          serialize: function(record, options) {
+            var json = this._super(record, options);
+
+            json.subject = json.title;
+            delete json.title;
+
+            return json;
+          }
+        });
+        ```
+
+        @method serialize
+        @param record
+        @param options
+      */
+      serialize: function(record, options) {
+        return this._super.apply(this, arguments);
+      },
+
+      /**
+        You can use this method to customize the root keys serialized into the JSON.
+        By default the REST Serializer sends the typeKey of a model, whih is a camelized
+        version of the name.
+
+        For example, your server may expect underscored root objects.
+
+        ```js
+        App.ApplicationSerializer = DS.RESTSerializer.extend({
+          serializeIntoHash: function(data, type, record, options) {
+            var root = Ember.String.decamelize(type.typeKey);
+            data[root] = this.serialize(record, options);
+          }
+        });
+        ```
+
+        @method serializeIntoHash
+        @param {Object} hash
+        @param {subclass of DS.Model} type
+        @param {DS.Model} record
+        @param {Object} options
+      */
+      serializeIntoHash: function(hash, type, record, options) {
+        hash[type.typeKey] = this.serialize(record, options);
+      },
+
+      /**
+        You can use this method to customize how polymorphic objects are serialized.
+        By default the JSON Serializer creates the key by appending `Type` to
+        the attribute and value from the model's camelcased model name.
+
+        @method serializePolymorphicType
+        @param {DS.Model} record
+        @param {Object} json
+        @param {Object} relationship
+      */
+      serializePolymorphicType: function(record, json, relationship) {
+        var key = relationship.key,
+            belongsTo = get(record, key);
+        key = this.keyForAttribute ? this.keyForAttribute(key) : key;
+        json[key + &quot;Type&quot;] = belongsTo.constructor.typeKey;
+      }
+    });
+
+    __exports__[&quot;default&quot;] = RESTSerializer;
+  });
+define(&quot;ember-data/lib/setup-container&quot;, 
+  [&quot;./initializers/store&quot;,&quot;./initializers/transforms&quot;,&quot;./initializers/store_injections&quot;,&quot;./initializers/data_adapter&quot;,&quot;../../../activemodel-adapter/lib/setup-container&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+    &quot;use strict&quot;;
+    var initializeStore = __dependency1__[&quot;default&quot;];
+    var initializeTransforms = __dependency2__[&quot;default&quot;];
+    var initializeStoreInjections = __dependency3__[&quot;default&quot;];
+    var initializeDataAdapter = __dependency4__[&quot;default&quot;];
+    var setupActiveModelContainer = __dependency5__[&quot;default&quot;];
+
+    __exports__[&quot;default&quot;] = function setupContainer(container, application){
+      // application is not a required argument. This ensures
+      // testing setups can setup a container without booting an
+      // entire ember application.
+
+      initializeDataAdapter(container, application);
+      initializeTransforms(container, application);
+      initializeStoreInjections(container, application);
+      initializeStore(container, application);
+      setupActiveModelContainer(container, application);
+    };
+  });
+define(&quot;ember-data/lib/system/adapter&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get, set = Ember.set;
+    var map = Ember.ArrayPolyfills.map;
+
+    var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
+
+    /**
+      A `DS.InvalidError` is used by an adapter to signal the external API
+      was unable to process a request because the content was not
+      semantically correct or meaningful per the API. Usually this means a
+      record failed some form of server side validation. When a promise
+      from an adapter is rejected with a `DS.InvalidError` the record will
+      transition to the `invalid` state and the errors will be set to the
+      `errors` property on the record.
+
+      Example
+
+      ```javascript
+      App.ApplicationAdapter = DS.RESTAdapter.extend({
+        ajaxError: function(jqXHR) {
+          var error = this._super(jqXHR);
+
+          if (jqXHR &amp;&amp; jqXHR.status === 422) {
+            var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)[&quot;errors&quot;];
+            return new DS.InvalidError(jsonErrors);
+          } else {
+            return error;
+          }
+        }
+      });
+      ```
+
+      The `DS.InvalidError` must be constructed with a single object whose
+      keys are the invalid model properties, and whose values are the
+      corresponding error messages. For example:
+
+      ```javascript
+      return new DS.InvalidError({
+        length: 'Must be less than 15',
+        name: 'Must not be blank
+      });
+      ```
+
+      @class InvalidError
+      @namespace DS
+    */
+    var InvalidError = function(errors) {
+      var tmp = Error.prototype.constructor.call(this, &quot;The backend rejected the commit because it was invalid: &quot; + Ember.inspect(errors));
+      this.errors = errors;
+
+      for (var i=0, l=errorProps.length; i&lt;l; i++) {
+        this[errorProps[i]] = tmp[errorProps[i]];
+      }
+    };
+    InvalidError.prototype = Ember.create(Error.prototype);
+
+    /**
+      An adapter is an object that receives requests from a store and
+      translates them into the appropriate action to take against your
+      persistence layer. The persistence layer is usually an HTTP API, but
+      may be anything, such as the browser's local storage. Typically the
+      adapter is not invoked directly instead its functionality is accessed
+      through the `store`.
+
+      ### Creating an Adapter
+
+      Create a new subclass of `DS.Adapter`, then assign
+      it to the `ApplicationAdapter` property of the application.
+
+      ```javascript
+      var MyAdapter = DS.Adapter.extend({
+        // ...your code here
+      });
+
+      App.ApplicationAdapter = MyAdapter;
+      ```
+
+      Model-specific adapters can be created by assigning your adapter
+      class to the `ModelName` + `Adapter` property of the application.
+
+      ```javascript
+      var MyPostAdapter = DS.Adapter.extend({
+        // ...Post-specific adapter code goes here
+      });
+
+      App.PostAdapter = MyPostAdapter;
+      ```
+
+      `DS.Adapter` is an abstract base class that you should override in your
+      application to customize it for your backend. The minimum set of methods
+      that you should implement is:
+
+        * `find()`
+        * `createRecord()`
+        * `updateRecord()`
+        * `deleteRecord()`
+        * `findAll()`
+        * `findQuery()`
+
+      To improve the network performance of your application, you can optimize
+      your adapter by overriding these lower-level methods:
+
+        * `findMany()`
+
+
+      For an example implementation, see `DS.RESTAdapter`, the
+      included REST adapter.
+
+      @class Adapter
+      @namespace DS
+      @extends Ember.Object
+    */
+
+    var Adapter = Ember.Object.extend({
+
+      /**
+        If you would like your adapter to use a custom serializer you can
+        set the `defaultSerializer` property to be the name of the custom
+        serializer.
+
+        Note the `defaultSerializer` serializer has a lower priority then
+        a model specific serializer (i.e. `PostSerializer`) or the
+        `application` serializer.
+
+        ```javascript
+        var DjangoAdapter = DS.Adapter.extend({
+          defaultSerializer: 'django'
+        });
+        ```
+
+        @property defaultSerializer
+        @type {String}
+      */
+
+      /**
+        The `find()` method is invoked when the store is asked for a record that
+        has not previously been loaded. In response to `find()` being called, you
+        should query your persistence layer for a record with the given ID. Once
+        found, you can asynchronously call the store's `push()` method to push
+        the record into the store.
+
+        Here is an example `find` implementation:
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          find: function(store, type, id) {
+            var url = [type, id].join('/');
+
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.getJSON(url).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @method find
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {String} id
+        @return {Promise} promise
+      */
+      find: Ember.required(Function),
+
+      /**
+        The `findAll()` method is called when you call `find` on the store
+        without an ID (i.e. `store.find('post')`).
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          findAll: function(store, type, sinceToken) {
+            var url = type;
+            var query = { since: sinceToken };
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.getJSON(url, query).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @private
+        @method findAll
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {String} sinceToken
+        @return {Promise} promise
+      */
+      findAll: null,
+
+      /**
+        This method is called when you call `find` on the store with a
+        query object as the second parameter (i.e. `store.find('person', {
+        page: 1 })`).
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          findQuery: function(store, type, query) {
+            var url = type;
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.getJSON(url, query).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @private
+        @method findQuery
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type
+        @param {Object} query
+        @param {DS.AdapterPopulatedRecordArray} recordArray
+        @return {Promise} promise
+      */
+      findQuery: null,
+
+      /**
+        If the globally unique IDs for your records should be generated on the client,
+        implement the `generateIdForRecord()` method. This method will be invoked
+        each time you create a new record, and the value returned from it will be
+        assigned to the record's `primaryKey`.
+
+        Most traditional REST-like HTTP APIs will not use this method. Instead, the ID
+        of the record will be set by the server, and your adapter will update the store
+        with the new ID when it calls `didCreateRecord()`. Only implement this method if
+        you intend to generate record IDs on the client-side.
+
+        The `generateIdForRecord()` method will be invoked with the requesting store as
+        the first parameter and the newly created record as the second parameter:
+
+        ```javascript
+        generateIdForRecord: function(store, record) {
+          var uuid = App.generateUUIDWithStatisticallyLowOddsOfCollision();
+          return uuid;
+        }
+        ```
+
+        @method generateIdForRecord
+        @param {DS.Store} store
+        @param {DS.Model} record
+        @return {String|Number} id
+      */
+      generateIdForRecord: null,
+
+      /**
+        Proxies to the serializer's `serialize` method.
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          createRecord: function(store, type, record) {
+            var data = this.serialize(record, { includeId: true });
+            var url = type;
+
+            // ...
+          }
+        });
+        ```
+
+        @method serialize
+        @param {DS.Model} record
+        @param {Object}   options
+        @return {Object} serialized record
+      */
+      serialize: function(record, options) {
+        return get(record, 'store').serializerFor(record.constructor.typeKey).serialize(record, options);
+      },
+
+      /**
+        Implement this method in a subclass to handle the creation of
+        new records.
+
+        Serializes the record and send it to the server.
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          createRecord: function(store, type, record) {
+            var data = this.serialize(record, { includeId: true });
+            var url = type;
+
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.ajax({
+                type: 'POST',
+                url: url,
+                dataType: 'json',
+                data: data
+              }).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @method createRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type   the DS.Model class of the record
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      createRecord: Ember.required(Function),
+
+      /**
+        Implement this method in a subclass to handle the updating of
+        a record.
+
+        Serializes the record update and send it to the server.
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          updateRecord: function(store, type, record) {
+            var data = this.serialize(record, { includeId: true });
+            var id = record.get('id');
+            var url = [type, id].join('/');
+
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.ajax({
+                type: 'PUT',
+                url: url,
+                dataType: 'json',
+                data: data
+              }).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @method updateRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type   the DS.Model class of the record
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      updateRecord: Ember.required(Function),
+
+      /**
+        Implement this method in a subclass to handle the deletion of
+        a record.
+
+        Sends a delete request for the record to the server.
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          deleteRecord: function(store, type, record) {
+            var data = this.serialize(record, { includeId: true });
+            var id = record.get('id');
+            var url = [type, id].join('/');
+
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.ajax({
+                type: 'DELETE',
+                url: url,
+                dataType: 'json',
+                data: data
+              }).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @method deleteRecord
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type   the DS.Model class of the record
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      deleteRecord: Ember.required(Function),
+
+      /**
+        Find multiple records at once.
+
+        By default, it loops over the provided ids and calls `find` on each.
+        May be overwritten to improve performance and reduce the number of
+        server requests.
+
+        Example
+
+        ```javascript
+        App.ApplicationAdapter = DS.Adapter.extend({
+          findMany: function(store, type, ids) {
+            var url = type;
+            return new Ember.RSVP.Promise(function(resolve, reject) {
+              jQuery.getJSON(url, {ids: ids}).then(function(data) {
+                Ember.run(null, resolve, data);
+              }, function(jqXHR) {
+                jqXHR.then = null; // tame jQuery's ill mannered promises
+                Ember.run(null, reject, jqXHR);
+              });
+            });
+          }
+        });
+        ```
+
+        @method findMany
+        @param {DS.Store} store
+        @param {subclass of DS.Model} type   the DS.Model class of the records
+        @param {Array}    ids
+        @return {Promise} promise
+      */
+      findMany: function(store, type, ids) {
+        var promises = map.call(ids, function(id) {
+          return this.find(store, type, id);
+        }, this);
+
+        return Ember.RSVP.all(promises);
+      }
+    });
+
+    __exports__.InvalidError = InvalidError;
+    __exports__.Adapter = Adapter;
+    __exports__[&quot;default&quot;] = Adapter;
+  });
+define(&quot;ember-data/lib/system/changes&quot;, 
+  [&quot;./changes/relationship_change&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var RelationshipChange = __dependency1__.RelationshipChange;
+    var RelationshipChangeAdd = __dependency1__.RelationshipChangeAdd;
+    var RelationshipChangeRemove = __dependency1__.RelationshipChangeRemove;
+    var OneToManyChange = __dependency1__.OneToManyChange;
+    var ManyToNoneChange = __dependency1__.ManyToNoneChange;
+    var OneToOneChange = __dependency1__.OneToOneChange;
+    var ManyToManyChange = __dependency1__.ManyToManyChange;
+
+    __exports__.RelationshipChange = RelationshipChange;
+    __exports__.RelationshipChangeAdd = RelationshipChangeAdd;
+    __exports__.RelationshipChangeRemove = RelationshipChangeRemove;
+    __exports__.OneToManyChange = OneToManyChange;
+    __exports__.ManyToNoneChange = ManyToNoneChange;
+    __exports__.OneToOneChange = OneToOneChange;
+    __exports__.ManyToManyChange = ManyToManyChange;
+  });
+define(&quot;ember-data/lib/system/changes/relationship_change&quot;, 
+  [&quot;../model&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var Model = __dependency1__.Model;
+
+    var get = Ember.get, set = Ember.set;
+    var forEach = Ember.EnumerableUtils.forEach;
+
+    /**
+      @class RelationshipChange
+      @namespace DS
+      @private
+      @constructor
+    */
+    var RelationshipChange = function(options) {
+      this.parentRecord = options.parentRecord;
+      this.childRecord = options.childRecord;
+      this.firstRecord = options.firstRecord;
+      this.firstRecordKind = options.firstRecordKind;
+      this.firstRecordName = options.firstRecordName;
+      this.secondRecord = options.secondRecord;
+      this.secondRecordKind = options.secondRecordKind;
+      this.secondRecordName = options.secondRecordName;
+      this.changeType = options.changeType;
+      this.store = options.store;
+
+      this.committed = {};
+    };
+
+    /**
+      @class RelationshipChangeAdd
+      @namespace DS
+      @private
+      @constructor
+    */
+    var RelationshipChangeAdd = function(options){
+      RelationshipChange.call(this, options);
+    };
+
+    /**
+      @class RelationshipChangeRemove
+      @namespace DS
+      @private
+      @constructor
+    */
+    var RelationshipChangeRemove = function(options){
+      RelationshipChange.call(this, options);
+    };
+
+    RelationshipChange.create = function(options) {
+      return new RelationshipChange(options);
+    };
+
+    RelationshipChangeAdd.create = function(options) {
+      return new RelationshipChangeAdd(options);
+    };
+
+    RelationshipChangeRemove.create = function(options) {
+      return new RelationshipChangeRemove(options);
+    };
+
+    var OneToManyChange = {};
+    var OneToNoneChange = {};
+    var ManyToNoneChange = {};
+    var OneToOneChange = {};
+    var ManyToManyChange = {};
+
+    RelationshipChange._createChange = function(options){
+      if(options.changeType === &quot;add&quot;){
+        return RelationshipChangeAdd.create(options);
+      }
+      if(options.changeType === &quot;remove&quot;){
+        return RelationshipChangeRemove.create(options);
+      }
+    };
+
+
+    RelationshipChange.determineRelationshipType = function(recordType, knownSide){
+      var knownKey = knownSide.key, key, otherKind;
+      var knownKind = knownSide.kind;
+
+      var inverse = recordType.inverseFor(knownKey);
+
+      if (inverse){
+        key = inverse.name;
+        otherKind = inverse.kind;
+      }
+
+      if (!inverse){
+        return knownKind === &quot;belongsTo&quot; ? &quot;oneToNone&quot; : &quot;manyToNone&quot;;
+      }
+      else{
+        if(otherKind === &quot;belongsTo&quot;){
+          return knownKind === &quot;belongsTo&quot; ? &quot;oneToOne&quot; : &quot;manyToOne&quot;;
+        }
+        else{
+          return knownKind === &quot;belongsTo&quot; ? &quot;oneToMany&quot; : &quot;manyToMany&quot;;
+        }
+      }
+
+    };
+
+    RelationshipChange.createChange = function(firstRecord, secondRecord, store, options){
+      // Get the type of the child based on the child's client ID
+      var firstRecordType = firstRecord.constructor, changeType;
+      changeType = RelationshipChange.determineRelationshipType(firstRecordType, options);
+      if (changeType === &quot;oneToMany&quot;){
+        return OneToManyChange.createChange(firstRecord, secondRecord, store, options);
+      }
+      else if (changeType === &quot;manyToOne&quot;){
+        return OneToManyChange.createChange(secondRecord, firstRecord, store, options);
+      }
+      else if (changeType === &quot;oneToNone&quot;){
+        return OneToNoneChange.createChange(firstRecord, secondRecord, store, options);
+      }
+      else if (changeType === &quot;manyToNone&quot;){
+        return ManyToNoneChange.createChange(firstRecord, secondRecord, store, options);
+      }
+      else if (changeType === &quot;oneToOne&quot;){
+        return OneToOneChange.createChange(firstRecord, secondRecord, store, options);
+      }
+      else if (changeType === &quot;manyToMany&quot;){
+        return ManyToManyChange.createChange(firstRecord, secondRecord, store, options);
+      }
+    };
+
+    OneToNoneChange.createChange = function(childRecord, parentRecord, store, options) {
+      var key = options.key;
+      var change = RelationshipChange._createChange({
+          parentRecord: parentRecord,
+          childRecord: childRecord,
+          firstRecord: childRecord,
+          store: store,
+          changeType: options.changeType,
+          firstRecordName: key,
+          firstRecordKind: &quot;belongsTo&quot;
+      });
+
+      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);
+
+      return change;
+    };
+
+    ManyToNoneChange.createChange = function(childRecord, parentRecord, store, options) {
+      var key = options.key;
+      var change = RelationshipChange._createChange({
+          parentRecord: childRecord,
+          childRecord: parentRecord,
+          secondRecord: childRecord,
+          store: store,
+          changeType: options.changeType,
+          secondRecordName: options.key,
+          secondRecordKind: &quot;hasMany&quot;
+      });
+
+      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);
+      return change;
+    };
+
+
+    ManyToManyChange.createChange = function(childRecord, parentRecord, store, options) {
+      // If the name of the belongsTo side of the relationship is specified,
+      // use that
+      // If the type of the parent is specified, look it up on the child's type
+      // definition.
+      var key = options.key;
+
+      var change = RelationshipChange._createChange({
+          parentRecord: parentRecord,
+          childRecord: childRecord,
+          firstRecord: childRecord,
+          secondRecord: parentRecord,
+          firstRecordKind: &quot;hasMany&quot;,
+          secondRecordKind: &quot;hasMany&quot;,
+          store: store,
+          changeType: options.changeType,
+          firstRecordName:  key
+      });
+
+      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);
+
+
+      return change;
+    };
+
+    OneToOneChange.createChange = function(childRecord, parentRecord, store, options) {
+      var key;
+
+      // If the name of the belongsTo side of the relationship is specified,
+      // use that
+      // If the type of the parent is specified, look it up on the child's type
+      // definition.
+      if (options.parentType) {
+        key = options.parentType.inverseFor(options.key).name;
+      } else if (options.key) {
+        key = options.key;
+      } else {
+        Ember.assert(&quot;You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent&quot;, false);
+      }
+
+      var change = RelationshipChange._createChange({
+          parentRecord: parentRecord,
+          childRecord: childRecord,
+          firstRecord: childRecord,
+          secondRecord: parentRecord,
+          firstRecordKind: &quot;belongsTo&quot;,
+          secondRecordKind: &quot;belongsTo&quot;,
+          store: store,
+          changeType: options.changeType,
+          firstRecordName:  key
+      });
+
+      store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change);
+
+
+      return change;
+    };
+
+    OneToOneChange.maintainInvariant = function(options, store, childRecord, key){
+      if (options.changeType === &quot;add&quot; &amp;&amp; store.recordIsMaterialized(childRecord)) {
+        var oldParent = get(childRecord, key);
+        if (oldParent){
+          var correspondingChange = OneToOneChange.createChange(childRecord, oldParent, store, {
+              parentType: options.parentType,
+              hasManyName: options.hasManyName,
+              changeType: &quot;remove&quot;,
+              key: options.key
+            });
+          store.addRelationshipChangeFor(childRecord, key, options.parentRecord , null, correspondingChange);
+         correspondingChange.sync();
+        }
+      }
+    };
+
+    OneToManyChange.createChange = function(childRecord, parentRecord, store, options) {
+      var key;
+
+      // If the name of the belongsTo side of the relationship is specified,
+      // use that
+      // If the type of the parent is specified, look it up on the child's type
+      // definition.
+      if (options.parentType) {
+        key = options.parentType.inverseFor(options.key).name;
+        OneToManyChange.maintainInvariant( options, store, childRecord, key );
+      } else if (options.key) {
+        key = options.key;
+      } else {
+        Ember.assert(&quot;You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent&quot;, false);
+      }
+
+      var change = RelationshipChange._createChange({
+          parentRecord: parentRecord,
+          childRecord: childRecord,
+          firstRecord: childRecord,
+          secondRecord: parentRecord,
+          firstRecordKind: &quot;belongsTo&quot;,
+          secondRecordKind: &quot;hasMany&quot;,
+          store: store,
+          changeType: options.changeType,
+          firstRecordName:  key
+      });
+
+      store.addRelationshipChangeFor(childRecord, key, parentRecord, change.getSecondRecordName(), change);
+
+
+      return change;
+    };
+
+
+    OneToManyChange.maintainInvariant = function(options, store, childRecord, key){
+      if (options.changeType === &quot;add&quot; &amp;&amp; childRecord) {
+        var oldParent = get(childRecord, key);
+        if (oldParent){
+          var correspondingChange = OneToManyChange.createChange(childRecord, oldParent, store, {
+              parentType: options.parentType,
+              hasManyName: options.hasManyName,
+              changeType: &quot;remove&quot;,
+              key: options.key
+            });
+          store.addRelationshipChangeFor(childRecord, key, options.parentRecord, correspondingChange.getSecondRecordName(), correspondingChange);
+          correspondingChange.sync();
+        }
+      }
+    };
+
+    /**
+      @class RelationshipChange
+      @namespace DS
+    */
+    RelationshipChange.prototype = {
+
+      getSecondRecordName: function() {
+        var name = this.secondRecordName, parent;
+
+        if (!name) {
+          parent = this.secondRecord;
+          if (!parent) { return; }
+
+          var childType = this.firstRecord.constructor;
+          var inverse = childType.inverseFor(this.firstRecordName);
+          this.secondRecordName = inverse.name;
+        }
+
+        return this.secondRecordName;
+      },
+
+      /**
+        Get the name of the relationship on the belongsTo side.
+
+        @method getFirstRecordName
+        @return {String}
+      */
+      getFirstRecordName: function() {
+        var name = this.firstRecordName;
+        return name;
+      },
+
+      /**
+        @method destroy
+        @private
+      */
+      destroy: function() {
+        var childRecord = this.childRecord,
+            belongsToName = this.getFirstRecordName(),
+            hasManyName = this.getSecondRecordName(),
+            store = this.store;
+
+        store.removeRelationshipChangeFor(childRecord, belongsToName, this.parentRecord, hasManyName, this.changeType);
+      },
+
+      getSecondRecord: function(){
+        return this.secondRecord;
+      },
+
+      /**
+        @method getFirstRecord
+        @private
+      */
+      getFirstRecord: function() {
+        return this.firstRecord;
+      },
+
+      coalesce: function(){
+        var relationshipPairs = this.store.relationshipChangePairsFor(this.firstRecord);
+        forEach(relationshipPairs, function(pair){
+          var addedChange = pair[&quot;add&quot;];
+          var removedChange = pair[&quot;remove&quot;];
+          if(addedChange &amp;&amp; removedChange) {
+            addedChange.destroy();
+            removedChange.destroy();
+          }
+        });
+      }
+    };
+
+    RelationshipChangeAdd.prototype = Ember.create(RelationshipChange.create({}));
+    RelationshipChangeRemove.prototype = Ember.create(RelationshipChange.create({}));
+
+    // the object is a value, and not a promise
+    function isValue(object) {
+      return typeof object === 'object' &amp;&amp; (!object.then || typeof object.then !== 'function');
+    }
+
+    RelationshipChangeAdd.prototype.changeType = &quot;add&quot;;
+    RelationshipChangeAdd.prototype.sync = function() {
+      var secondRecordName = this.getSecondRecordName(),
+          firstRecordName = this.getFirstRecordName(),
+          firstRecord = this.getFirstRecord(),
+          secondRecord = this.getSecondRecord();
+
+      //Ember.assert(&quot;You specified a hasMany (&quot; + hasManyName + &quot;) on &quot; + (!belongsToName &amp;&amp; (newParent || oldParent || this.lastParent).constructor) + &quot; but did not specify an inverse belongsTo on &quot; + child.constructor, belongsToName);
+      //Ember.assert(&quot;You specified a belongsTo (&quot; + belongsToName + &quot;) on &quot; + child.constructor + &quot; but did not specify an inverse hasMany on &quot; + (!hasManyName &amp;&amp; (newParent || oldParent || this.lastParentRecord).constructor), hasManyName);
+
+      if (secondRecord instanceof Model &amp;&amp; firstRecord instanceof Model) {
+        if(this.secondRecordKind === &quot;belongsTo&quot;){
+          secondRecord.suspendRelationshipObservers(function(){
+            set(secondRecord, secondRecordName, firstRecord);
+          });
+
+         }
+         else if(this.secondRecordKind === &quot;hasMany&quot;){
+          secondRecord.suspendRelationshipObservers(function(){
+            var relationship = get(secondRecord, secondRecordName);
+            if (isValue(relationship)) { relationship.addObject(firstRecord); }
+          });
+        }
+      }
+
+      if (firstRecord instanceof Model &amp;&amp; secondRecord instanceof Model &amp;&amp; get(firstRecord, firstRecordName) !== secondRecord) {
+        if(this.firstRecordKind === &quot;belongsTo&quot;){
+          firstRecord.suspendRelationshipObservers(function(){
+            set(firstRecord, firstRecordName, secondRecord);
+          });
+        }
+        else if(this.firstRecordKind === &quot;hasMany&quot;){
+          firstRecord.suspendRelationshipObservers(function(){
+            var relationship = get(firstRecord, firstRecordName);
+            if (isValue(relationship)) { relationship.addObject(secondRecord); }
+          });
+        }
+      }
+
+      this.coalesce();
+    };
+
+    RelationshipChangeRemove.prototype.changeType = &quot;remove&quot;;
+    RelationshipChangeRemove.prototype.sync = function() {
+      var secondRecordName = this.getSecondRecordName(),
+          firstRecordName = this.getFirstRecordName(),
+          firstRecord = this.getFirstRecord(),
+          secondRecord = this.getSecondRecord();
+
+      //Ember.assert(&quot;You specified a hasMany (&quot; + hasManyName + &quot;) on &quot; + (!belongsToName &amp;&amp; (newParent || oldParent || this.lastParent).constructor) + &quot; but did not specify an inverse belongsTo on &quot; + child.constructor, belongsToName);
+      //Ember.assert(&quot;You specified a belongsTo (&quot; + belongsToName + &quot;) on &quot; + child.constructor + &quot; but did not specify an inverse hasMany on &quot; + (!hasManyName &amp;&amp; (newParent || oldParent || this.lastParentRecord).constructor), hasManyName);
+
+      if (secondRecord instanceof Model &amp;&amp; firstRecord instanceof Model) {
+        if(this.secondRecordKind === &quot;belongsTo&quot;){
+          secondRecord.suspendRelationshipObservers(function(){
+            set(secondRecord, secondRecordName, null);
+          });
+        }
+        else if(this.secondRecordKind === &quot;hasMany&quot;){
+          secondRecord.suspendRelationshipObservers(function(){
+            var relationship = get(secondRecord, secondRecordName);
+            if (isValue(relationship)) { relationship.removeObject(firstRecord); }
+          });
+        }
+      }
+
+      if (firstRecord instanceof Model &amp;&amp; get(firstRecord, firstRecordName)) {
+        if(this.firstRecordKind === &quot;belongsTo&quot;){
+          firstRecord.suspendRelationshipObservers(function(){
+            set(firstRecord, firstRecordName, null);
+          });
+         }
+         else if(this.firstRecordKind === &quot;hasMany&quot;){
+           firstRecord.suspendRelationshipObservers(function(){
+             var relationship = get(firstRecord, firstRecordName);
+             if (isValue(relationship)) { relationship.removeObject(secondRecord); }
+          });
+        }
+      }
+
+      this.coalesce();
+    };
+
+    __exports__.RelationshipChange = RelationshipChange;
+    __exports__.RelationshipChangeAdd = RelationshipChangeAdd;
+    __exports__.RelationshipChangeRemove = RelationshipChangeRemove;
+    __exports__.OneToManyChange = OneToManyChange;
+    __exports__.ManyToNoneChange = ManyToNoneChange;
+    __exports__.OneToOneChange = OneToOneChange;
+    __exports__.ManyToManyChange = ManyToManyChange;
+  });
+define(&quot;ember-data/lib/system/container_proxy&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    /**
+      This is used internally to enable deprecation of container paths and provide
+      a decent message to the user indicating how to fix the issue.
+
+      @class ContainerProxy
+      @namespace DS
+      @private
+    */
+    var ContainerProxy = function (container){
+      this.container = container;
+    };
+
+    ContainerProxy.prototype.aliasedFactory = function(path, preLookup) {
+      var _this = this;
+
+      return {create: function(){ 
+        if (preLookup) { preLookup(); }
+
+        return _this.container.lookup(path); 
+      }};
+    };
+
+    ContainerProxy.prototype.registerAlias = function(source, dest, preLookup) {
+      var factory = this.aliasedFactory(dest, preLookup);
+
+      return this.container.register(source, factory);
+    };
+
+    ContainerProxy.prototype.registerDeprecation = function(deprecated, valid) {
+      var preLookupCallback = function(){
+        Ember.deprecate(&quot;You tried to look up '&quot; + deprecated + &quot;', &quot; +
+                        &quot;but this has been deprecated in favor of '&quot; + valid + &quot;'.&quot;, false);
+      };
+
+      return this.registerAlias(deprecated, valid, preLookupCallback);
+    };
+
+    ContainerProxy.prototype.registerDeprecations = function(proxyPairs) {
+      for (var i = proxyPairs.length; i &gt; 0; i--) {
+        var proxyPair = proxyPairs[i - 1],
+            deprecated = proxyPair['deprecated'],
+            valid = proxyPair['valid'];
+
+        this.registerDeprecation(deprecated, valid);
+      }
+    };
+
+    __exports__[&quot;default&quot;] = ContainerProxy;
+  });
+define(&quot;ember-data/lib/system/debug&quot;, 
+  [&quot;./debug/debug_info&quot;,&quot;./debug/debug_adapter&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var DebugAdapter = __dependency2__[&quot;default&quot;];
+
+    __exports__[&quot;default&quot;] = DebugAdapter;
+  });
+define(&quot;ember-data/lib/system/debug/debug_adapter&quot;, 
+  [&quot;../model&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+    var Model = __dependency1__.Model;
+    var get = Ember.get, capitalize = Ember.String.capitalize, underscore = Ember.String.underscore;
+
+    /**
+      Extend `Ember.DataAdapter` with ED specific code.
+
+      @class DebugAdapter
+      @namespace DS
+      @extends Ember.DataAdapter
+      @private
+    */
+    var DebugAdapter = Ember.DataAdapter.extend({
+      getFilters: function() {
+        return [
+          { name: 'isNew', desc: 'New' },
+          { name: 'isModified', desc: 'Modified' },
+          { name: 'isClean', desc: 'Clean' }
+        ];
+      },
+
+      detect: function(klass) {
+        return klass !== Model &amp;&amp; Model.detect(klass);
+      },
+
+      columnsForType: function(type) {
+        var columns = [{ name: 'id', desc: 'Id' }], count = 0, self = this;
+        get(type, 'attributes').forEach(function(name, meta) {
+            if (count++ &gt; self.attributeLimit) { return false; }
+            var desc = capitalize(underscore(name).replace('_', ' '));
+            columns.push({ name: name, desc: desc });
+        });
+        return columns;
+      },
+
+      getRecords: function(type) {
+        return this.get('store').all(type);
+      },
+
+      getRecordColumnValues: function(record) {
+        var self = this, count = 0,
+            columnValues = { id: get(record, 'id') };
+
+        record.eachAttribute(function(key) {
+          if (count++ &gt; self.attributeLimit) {
+            return false;
+          }
+          var value = get(record, key);
+          columnValues[key] = value;
+        });
+        return columnValues;
+      },
+
+      getRecordKeywords: function(record) {
+        var keywords = [], keys = Ember.A(['id']);
+        record.eachAttribute(function(key) {
+          keys.push(key);
+        });
+        keys.forEach(function(key) {
+          keywords.push(get(record, key));
+        });
+        return keywords;
+      },
+
+      getRecordFilterValues: function(record) {
+        return {
+          isNew: record.get('isNew'),
+          isModified: record.get('isDirty') &amp;&amp; !record.get('isNew'),
+          isClean: !record.get('isDirty')
+        };
+      },
+
+      getRecordColor: function(record) {
+        var color = 'black';
+        if (record.get('isNew')) {
+          color = 'green';
+        } else if (record.get('isDirty')) {
+          color = 'blue';
+        }
+        return color;
+      },
+
+      observeRecord: function(record, recordUpdated) {
+        var releaseMethods = Ember.A(), self = this,
+            keysToObserve = Ember.A(['id', 'isNew', 'isDirty']);
+
+        record.eachAttribute(function(key) {
+          keysToObserve.push(key);
+        });
+
+        keysToObserve.forEach(function(key) {
+          var handler = function() {
+            recordUpdated(self.wrapRecord(record));
+          };
+          Ember.addObserver(record, key, handler);
+          releaseMethods.push(function() {
+            Ember.removeObserver(record, key, handler);
+          });
+        });
+
+        var release = function() {
+          releaseMethods.forEach(function(fn) { fn(); } );
+        };
+
+        return release;
+      }
+
+    });
+
+    __exports__[&quot;default&quot;] = DebugAdapter;
+  });
+define(&quot;ember-data/lib/system/debug/debug_info&quot;, 
+  [&quot;../model&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var Model = __dependency1__.Model;
+
+    Model.reopen({
+
+      /**
+        Provides info about the model for debugging purposes
+        by grouping the properties into more semantic groups.
+
+        Meant to be used by debugging tools such as the Chrome Ember Extension.
+
+        - Groups all attributes in &quot;Attributes&quot; group.
+        - Groups all belongsTo relationships in &quot;Belongs To&quot; group.
+        - Groups all hasMany relationships in &quot;Has Many&quot; group.
+        - Groups all flags in &quot;Flags&quot; group.
+        - Flags relationship CPs as expensive properties.
+
+        @method _debugInfo
+        @for DS.Model
+        @private
+      */
+      _debugInfo: function() {
+        var attributes = ['id'],
+            relationships = { belongsTo: [], hasMany: [] },
+            expensiveProperties = [];
+
+        this.eachAttribute(function(name, meta) {
+          attributes.push(name);
+        }, this);
+
+        this.eachRelationship(function(name, relationship) {
+          relationships[relationship.kind].push(name);
+          expensiveProperties.push(name);
+        });
+
+        var groups = [
+          {
+            name: 'Attributes',
+            properties: attributes,
+            expand: true
+          },
+          {
+            name: 'Belongs To',
+            properties: relationships.belongsTo,
+            expand: true
+          },
+          {
+            name: 'Has Many',
+            properties: relationships.hasMany,
+            expand: true
+          },
+          {
+            name: 'Flags',
+            properties: ['isLoaded', 'isDirty', 'isSaving', 'isDeleted', 'isError', 'isNew', 'isValid']
+          }
+        ];
+
+        return {
+          propertyInfo: {
+            // include all other mixins / properties (not just the grouped ones)
+            includeOtherProperties: true,
+            groups: groups,
+            // don't pre-calculate unless cached
+            expensiveProperties: expensiveProperties
+          }
+        };
+      }
+    });
+
+    __exports__[&quot;default&quot;] = Model;
+  });
+define(&quot;ember-data/lib/system/model&quot;, 
+  [&quot;./model/model&quot;,&quot;./model/attributes&quot;,&quot;./model/states&quot;,&quot;./model/errors&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var Model = __dependency1__[&quot;default&quot;];
+    var attr = __dependency2__[&quot;default&quot;];
+    var RootState = __dependency3__[&quot;default&quot;];
+    var Errors = __dependency4__[&quot;default&quot;];
+
+    __exports__.Model = Model;
+    __exports__.RootState = RootState;
+    __exports__.attr = attr;
+    __exports__.Errors = Errors;
+  });
+define(&quot;ember-data/lib/system/model/attributes&quot;, 
+  [&quot;./model&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var Model = __dependency1__[&quot;default&quot;];
+
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get;
+
+    /**
+      @class Model
+      @namespace DS
+    */
+    Model.reopenClass({
+      /**
+        A map whose keys are the attributes of the model (properties
+        described by DS.attr) and whose values are the meta object for the
+        property.
+
+        Example
+
+        ```javascript
+
+        App.Person = DS.Model.extend({
+          firstName: attr('string'),
+          lastName: attr('string'),
+          birthday: attr('date')
+        });
+
+        var attributes = Ember.get(App.Person, 'attributes')
+
+        attributes.forEach(function(name, meta) {
+          console.log(name, meta);
+        });
+
+        // prints:
+        // firstName {type: &quot;string&quot;, isAttribute: true, options: Object, parentType: function, name: &quot;firstName&quot;}
+        // lastName {type: &quot;string&quot;, isAttribute: true, options: Object, parentType: function, name: &quot;lastName&quot;}
+        // birthday {type: &quot;date&quot;, isAttribute: true, options: Object, parentType: function, name: &quot;birthday&quot;}
+        ```
+
+        @property attributes
+        @static
+        @type {Ember.Map}
+        @readOnly
+      */
+      attributes: Ember.computed(function() {
+        var map = Ember.Map.create();
+
+        this.eachComputedProperty(function(name, meta) {
+          if (meta.isAttribute) {
+            Ember.assert(&quot;You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('&lt;type&gt;')` from &quot; + this.toString(), name !== 'id');
+
+            meta.name = name;
+            map.set(name, meta);
+          }
+        });
+
+        return map;
+      }),
+
+      /**
+        A map whose keys are the attributes of the model (properties
+        described by DS.attr) and whose values are type of transformation
+        applied to each attribute. This map does not include any
+        attributes that do not have an transformation type.
+
+        Example
+
+        ```javascript
+        App.Person = DS.Model.extend({
+          firstName: attr(),
+          lastName: attr('string'),
+          birthday: attr('date')
+        });
+
+        var transformedAttributes = Ember.get(App.Person, 'transformedAttributes')
+
+        transformedAttributes.forEach(function(field, type) {
+          console.log(field, type);
+        });
+
+        // prints:
+        // lastName string
+        // birthday date
+        ```
+
+        @property transformedAttributes
+        @static
+        @type {Ember.Map}
+        @readOnly
+      */
+      transformedAttributes: Ember.computed(function() {
+        var map = Ember.Map.create();
+
+        this.eachAttribute(function(key, meta) {
+          if (meta.type) {
+            map.set(key, meta.type);
+          }
+        });
+
+        return map;
+      }),
+
+      /**
+        Iterates through the attributes of the model, calling the passed function on each
+        attribute.
+
+        The callback method you provide should have the following signature (all
+        parameters are optional):
+
+        ```javascript
+        function(name, meta);
+        ```
+
+        - `name` the name of the current property in the iteration
+        - `meta` the meta object for the attribute property in the iteration
+
+        Note that in addition to a callback, you can also pass an optional target
+        object that will be set as `this` on the context.
+
+        Example
+
+        ```javascript
+        App.Person = DS.Model.extend({
+          firstName: attr('string'),
+          lastName: attr('string'),
+          birthday: attr('date')
+        });
+
+        App.Person.eachAttribute(function(name, meta) {
+          console.log(name, meta);
+        });
+
+        // prints:
+        // firstName {type: &quot;string&quot;, isAttribute: true, options: Object, parentType: function, name: &quot;firstName&quot;}
+        // lastName {type: &quot;string&quot;, isAttribute: true, options: Object, parentType: function, name: &quot;lastName&quot;}
+        // birthday {type: &quot;date&quot;, isAttribute: true, options: Object, parentType: function, name: &quot;birthday&quot;}
+       ```
+
+        @method eachAttribute
+        @param {Function} callback The callback to execute
+        @param {Object} [target] The target object to use
+        @static
+      */
+      eachAttribute: function(callback, binding) {
+        get(this, 'attributes').forEach(function(name, meta) {
+          callback.call(binding, name, meta);
+        }, binding);
+      },
+
+      /**
+        Iterates through the transformedAttributes of the model, calling
+        the passed function on each attribute. Note the callback will not be
+        called for any attributes that do not have an transformation type.
+
+        The callback method you provide should have the following signature (all
+        parameters are optional):
+
+        ```javascript
+        function(name, type);
+        ```
+
+        - `name` the name of the current property in the iteration
+        - `type` a string containing the name of the type of transformed
+          applied to the attribute
+
+        Note that in addition to a callback, you can also pass an optional target
+        object that will be set as `this` on the context.
+
+        Example
+
+        ```javascript
+        App.Person = DS.Model.extend({
+          firstName: attr(),
+          lastName: attr('string'),
+          birthday: attr('date')
+        });
+
+        App.Person.eachTransformedAttribute(function(name, type) {
+          console.log(name, type);
+        });
+
+        // prints:
+        // lastName string
+        // birthday date
+       ```
+
+        @method eachTransformedAttribute
+        @param {Function} callback The callback to execute
+        @param {Object} [target] The target object to use
+        @static
+      */
+      eachTransformedAttribute: function(callback, binding) {
+        get(this, 'transformedAttributes').forEach(function(name, type) {
+          callback.call(binding, name, type);
+        });
+      }
+    });
+
+
+    Model.reopen({
+      eachAttribute: function(callback, binding) {
+        this.constructor.eachAttribute(callback, binding);
+      }
+    });
+
+    function getDefaultValue(record, options, key) {
+      if (typeof options.defaultValue === &quot;function&quot;) {
+        return options.defaultValue.apply(null, arguments);
+      } else {
+        return options.defaultValue;
+      }
+    }
+
+    function hasValue(record, key) {
+      return record._attributes.hasOwnProperty(key) ||
+             record._inFlightAttributes.hasOwnProperty(key) ||
+             record._data.hasOwnProperty(key);
+    }
+
+    function getValue(record, key) {
+      if (record._attributes.hasOwnProperty(key)) {
+        return record._attributes[key];
+      } else if (record._inFlightAttributes.hasOwnProperty(key)) {
+        return record._inFlightAttributes[key];
+      } else {
+        return record._data[key];
+      }
+    }
+
+    /**
+      `DS.attr` defines an attribute on a [DS.Model](/api/data/classes/DS.Model.html).
+      By default, attributes are passed through as-is, however you can specify an
+      optional type to have the value automatically transformed.
+      Ember Data ships with four basic transform types: `string`, `number`,
+      `boolean` and `date`. You can define your own transforms by subclassing
+      [DS.Transform](/api/data/classes/DS.Transform.html).
+
+      Note that you cannot use `attr` to define an attribute of `id`.
+
+      `DS.attr` takes an optional hash as a second parameter, currently
+      supported options are:
+
+      - `defaultValue`: Pass a string or a function to be called to set the attribute
+                        to a default value if none is supplied.
+
+      Example
+
+      ```javascript
+      var attr = DS.attr;
+
+      App.User = DS.Model.extend({
+        username: attr('string'),
+        email: attr('string'),
+        verified: attr('boolean', {defaultValue: false})
+      });
+      ```
+
+      @namespace
+      @method attr
+      @for DS
+      @param {String} type the attribute type
+      @param {Object} options a hash of options
+      @return {Attribute}
+    */
+
+    function attr(type, options) {
+      options = options || {};
+
+      var meta = {
+        type: type,
+        isAttribute: true,
+        options: options
+      };
+
+      return Ember.computed('data', function(key, value) {
+        if (arguments.length &gt; 1) {
+          Ember.assert(&quot;You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('&lt;type&gt;')` from &quot; + this.constructor.toString(), key !== 'id');
+          var oldValue = getValue(this, key);
+
+          if (value !== oldValue) {
+            // Add the new value to the changed attributes hash; it will get deleted by
+            // the 'didSetProperty' handler if it is no different from the original value
+            this._attributes[key] = value;
+
+            this.send('didSetProperty', {
+              name: key,
+              oldValue: oldValue,
+              originalValue: this._data[key],
+              value: value
+            });
+          }
+
+          return value;
+        } else if (hasValue(this, key)) {
+          return getValue(this, key);
+        } else {
+          return getDefaultValue(this, options, key);
+        }
+
+      // `data` is never set directly. However, it may be
+      // invalidated from the state manager's setData
+      // event.
+      }).meta(meta);
+    }
+
+    __exports__[&quot;default&quot;] = attr;
+  });
+define(&quot;ember-data/lib/system/model/errors&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    var get = Ember.get, isEmpty = Ember.isEmpty;
+    var map = Ember.EnumerableUtils.map;
+
+    /**
+    @module ember-data
+    */
+
+    /**
+      Holds validation errors for a given record organized by attribute names.
+
+      Every DS.Model has an `errors` property that is an instance of
+      `DS.Errors`. This can be used to display validation error
+      messages returned from the server when a `record.save()` rejects.
+
+      For Example, if you had an `User` model that looked like this:
+
+      ```javascript
+      App.User = DS.Model.extend({
+        username: attr('string'),
+        email: attr('string')
+      });
+      ```
+      And you attempted to save a record that did not validate on the backend.
+
+      ```javascript
+      var user = store.createRecord('user', {
+        username: 'tomster',
+        email: 'invalidEmail'
+      });
+      user.save();
+      ```
+
+      Your backend data store might return a response that looks like
+      this. This response will be used to populate the error object.
+
+      ```javascript
+      {
+        &quot;errors&quot;: {
+          &quot;username&quot;: [&quot;This username is already taken!&quot;],
+          &quot;email&quot;: [&quot;Doesn't look like a valid email.&quot;]
+        }
+      }
+      ```
+
+      Errors can be displayed to the user by accessing their property name
+      or using the `messages` property to get an array of all errors.
+
+      ```handlebars
+      {{#each errors.messages}}
+        &lt;div class=&quot;error&quot;&gt;
+          {{message}}
+        &lt;/div&gt;
+      {{/each}}
+
+      &lt;label&gt;Username: {{input value=username}} &lt;/label&gt;
+      {{#each errors.username}}
+        &lt;div class=&quot;error&quot;&gt;
+          {{message}}
+        &lt;/div&gt;
+      {{/each}}
+
+      &lt;label&gt;Email: {{input value=email}} &lt;/label&gt;
+      {{#each errors.email}}
+        &lt;div class=&quot;error&quot;&gt;
+          {{message}}
+        &lt;/div&gt;
+      {{/each}}
+      ```
+
+      @class Errors
+      @namespace DS
+      @extends Ember.Object
+      @uses Ember.Enumerable
+      @uses Ember.Evented
+     */
+    var Errors = Ember.Object.extend(Ember.Enumerable, Ember.Evented, {
+      /**
+        Register with target handler
+
+        @method registerHandlers
+        @param {Object} target
+        @param {Function} becameInvalid
+        @param {Function} becameValid
+      */
+      registerHandlers: function(target, becameInvalid, becameValid) {
+        this.on('becameInvalid', target, becameInvalid);
+        this.on('becameValid', target, becameValid);
+      },
+
+      /**
+        @property errorsByAttributeName
+        @type {Ember.MapWithDefault}
+        @private
+      */
+      errorsByAttributeName: Ember.reduceComputed(&quot;content&quot;, {
+        initialValue: function() {
+          return Ember.MapWithDefault.create({
+            defaultValue: function() {
+              return Ember.A();
+            }
+          });
+        },
+
+        addedItem: function(errors, error) {
+          errors.get(error.attribute).pushObject(error);
+
+          return errors;
+        },
+
+        removedItem: function(errors, error) {
+          errors.get(error.attribute).removeObject(error);
+
+          return errors;
+        }
+      }),
+
+      /**
+        Returns errors for a given attribute
+
+        ```javascript
+        var user = store.createRecord('user', {
+          username: 'tomster',
+          email: 'invalidEmail'
+        });
+        user.save().catch(function(){
+          user.get('errors').errorsFor('email'); // [&quot;Doesn't look like a valid email.&quot;]
+        });
+        ```
+
+        @method errorsFor
+        @param {String} attribute
+        @return {Array}
+      */
+      errorsFor: function(attribute) {
+        return get(this, 'errorsByAttributeName').get(attribute);
+      },
+
+      /**
+        An array containing all of the error messages for this
+        record. This is useful for displaying all errors to the user.
+
+        ```handlebars
+        {{#each errors.messages}}
+          &lt;div class=&quot;error&quot;&gt;
+            {{message}}
+          &lt;/div&gt;
+        {{/each}}
+        ```
+
+        @property messages
+        @type {Array}
+      */
+      messages: Ember.computed.mapBy('content', 'message'),
+
+      /**
+        @property content
+        @type {Array}
+        @private
+      */
+      content: Ember.computed(function() {
+        return Ember.A();
+      }),
+
+      /**
+        @method unknownProperty
+        @private
+      */
+      unknownProperty: function(attribute) {
+        var errors = this.errorsFor(attribute);
+        if (isEmpty(errors)) { return null; }
+        return errors;
+      },
+
+      /**
+        @method nextObject
+        @private
+      */
+      nextObject: function(index, previousObject, context) {
+        return get(this, 'content').objectAt(index);
+      },
+
+      /**
+        Total number of errors.
+
+        @property length
+        @type {Number}
+        @readOnly
+      */
+      length: Ember.computed.oneWay('content.length').readOnly(),
+
+      /**
+        @property isEmpty
+        @type {Boolean}
+        @readOnly
+      */
+      isEmpty: Ember.computed.not('length').readOnly(),
+
+      /**
+        Adds error messages to a given attribute and sends
+        `becameInvalid` event to the record.
+
+        Example:
+
+        ```javascript
+        if (!user.get('username') {
+          user.get('errors').add('username', 'This field is required');
+        }
+        ```
+
+        @method add
+        @param {String} attribute
+        @param {Array|String} messages
+      */
+      add: function(attribute, messages) {
+        var wasEmpty = get(this, 'isEmpty');
+
+        messages = this._findOrCreateMessages(attribute, messages);
+        get(this, 'content').addObjects(messages);
+
+        this.notifyPropertyChange(attribute);
+        this.enumerableContentDidChange();
+
+        if (wasEmpty &amp;&amp; !get(this, 'isEmpty')) {
+          this.trigger('becameInvalid');
+        }
+      },
+
+      /**
+        @method _findOrCreateMessages
+        @private
+      */
+      _findOrCreateMessages: function(attribute, messages) {
+        var errors = this.errorsFor(attribute);
+
+        return map(Ember.makeArray(messages), function(message) {
+          return errors.findBy('message', message) || {
+            attribute: attribute,
+            message: message
+          };
+        });
+      },
+
+      /**
+        Removes all error messages from the given attribute and sends
+        `becameValid` event to the record if there no more errors left.
+
+        Example:
+
+        ```javascript
+        App.User = DS.Model.extend({
+          email: DS.attr('string'),
+          twoFactorAuth: DS.attr('boolean'),
+          phone: DS.attr('string')
+        });
+
+        App.UserEditRoute = Ember.Route.extend({
+          actions: {
+            save: function(user) {
+               if (!user.get('twoFactorAuth')) {
+                 user.get('errors').remove('phone');
+               }
+               user.save();
+             }
+          }
+        });
+        ```
+
+        @method remove
+        @param {String} attribute
+      */
+      remove: function(attribute) {
+        if (get(this, 'isEmpty')) { return; }
+
+        var content = get(this, 'content').rejectBy('attribute', attribute);
+        get(this, 'content').setObjects(content);
+
+        this.notifyPropertyChange(attribute);
+        this.enumerableContentDidChange();
+
+        if (get(this, 'isEmpty')) {
+          this.trigger('becameValid');
+        }
+      },
+
+      /**
+        Removes all error messages and sends `becameValid` event
+        to the record.
+
+        Example:
+
+        ```javascript
+        App.UserEditRoute = Ember.Route.extend({
+          actions: {
+            retrySave: function(user) {
+               user.get('errors').clear();
+               user.save();
+             }
+          }
+        });
+        ```
+
+        @method clear
+      */
+      clear: function() {
+        if (get(this, 'isEmpty')) { return; }
+
+        get(this, 'content').clear();
+        this.enumerableContentDidChange();
+
+        this.trigger('becameValid');
+      },
+
+      /**
+        Checks if there is error messages for the given attribute.
+
+        ```javascript
+        App.UserEditRoute = Ember.Route.extend({
+          actions: {
+            save: function(user) {
+               if (user.get('errors').has('email')) {
+                 return alert('Please update your email before attempting to save.');
+               }
+               user.save();
+             }
+          }
+        });
+        ```
+
+        @method has
+        @param {String} attribute
+        @return {Boolean} true if there some errors on given attribute
+      */
+      has: function(attribute) {
+        return !isEmpty(this.errorsFor(attribute));
+      }
+    });
+
+    __exports__[&quot;default&quot;] = Errors;
+  });
+define(&quot;ember-data/lib/system/model/model&quot;, 
+  [&quot;./states&quot;,&quot;./errors&quot;,&quot;../store&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+    &quot;use strict&quot;;
+    var RootState = __dependency1__[&quot;default&quot;];
+    var Errors = __dependency2__[&quot;default&quot;];
+    var PromiseObject = __dependency3__.PromiseObject;
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get, set = Ember.set,
+        merge = Ember.merge,
+        Promise = Ember.RSVP.Promise;
+
+    var JSONSerializer;
+    var retrieveFromCurrentState = Ember.computed('currentState', function(key, value) {
+      return get(get(this, 'currentState'), key);
+    }).readOnly();
+
+    /**
+
+      The model class that all Ember Data records descend from.
+
+      @class Model
+      @namespace DS
+      @extends Ember.Object
+      @uses Ember.Evented
+    */
+    var Model = Ember.Object.extend(Ember.Evented, {
+      _recordArrays: undefined,
+      _relationships: undefined,
+      _loadingRecordArrays: undefined,
+      /**
+        If this property is `true` the record is in the `empty`
+        state. Empty is the first state all records enter after they have
+        been created. Most records created by the store will quickly
+        transition to the `loading` state if data needs to be fetched from
+        the server or the `created` state if the record is created on the
+        client. A record can also enter the empty state if the adapter is
+        unable to locate the record.
+
+        @property isEmpty
+        @type {Boolean}
+        @readOnly
+      */
+      isEmpty: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `loading` state. A
+        record enters this state when the store asks the adapter for its
+        data. It remains in this state until the adapter provides the
+        requested data.
+
+        @property isLoading
+        @type {Boolean}
+        @readOnly
+      */
+      isLoading: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `loaded` state. A
+        record enters this state when its data is populated. Most of a
+        record's lifecycle is spent inside substates of the `loaded`
+        state.
+
+        Example
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('isLoaded'); // true
+
+        store.find('model', 1).then(function(model) {
+          model.get('isLoaded'); // true
+        });
+        ```
+
+        @property isLoaded
+        @type {Boolean}
+        @readOnly
+      */
+      isLoaded: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `dirty` state. The
+        record has local changes that have not yet been saved by the
+        adapter. This includes records that have been created (but not yet
+        saved) or deleted.
+
+        Example
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('isDirty'); // true
+
+        store.find('model', 1).then(function(model) {
+          model.get('isDirty'); // false
+          model.set('foo', 'some value');
+          model.get('isDirty'); // true
+        });
+        ```
+
+        @property isDirty
+        @type {Boolean}
+        @readOnly
+      */
+      isDirty: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `saving` state. A
+        record enters the saving state when `save` is called, but the
+        adapter has not yet acknowledged that the changes have been
+        persisted to the backend.
+
+        Example
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('isSaving'); // false
+        var promise = record.save();
+        record.get('isSaving'); // true
+        promise.then(function() {
+          record.get('isSaving'); // false
+        });
+        ```
+
+        @property isSaving
+        @type {Boolean}
+        @readOnly
+      */
+      isSaving: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `deleted` state
+        and has been marked for deletion. When `isDeleted` is true and
+        `isDirty` is true, the record is deleted locally but the deletion
+        was not yet persisted. When `isSaving` is true, the change is
+        in-flight. When both `isDirty` and `isSaving` are false, the
+        change has persisted.
+
+        Example
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('isDeleted');    // false
+        record.deleteRecord();
+
+        // Locally deleted
+        record.get('isDeleted');    // true
+        record.get('isDirty');      // true
+        record.get('isSaving');     // false
+
+        // Persisting the deletion
+        var promise = record.save();
+        record.get('isDeleted');    // true
+        record.get('isSaving');     // true
+
+        // Deletion Persisted
+        promise.then(function() {
+          record.get('isDeleted');  // true
+          record.get('isSaving');   // false
+          record.get('isDirty');    // false
+        });
+        ```
+
+        @property isDeleted
+        @type {Boolean}
+        @readOnly
+      */
+      isDeleted: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `new` state. A
+        record will be in the `new` state when it has been created on the
+        client and the adapter has not yet report that it was successfully
+        saved.
+
+        Example
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('isNew'); // true
+
+        record.save().then(function(model) {
+          model.get('isNew'); // false
+        });
+        ```
+
+        @property isNew
+        @type {Boolean}
+        @readOnly
+      */
+      isNew: retrieveFromCurrentState,
+      /**
+        If this property is `true` the record is in the `valid` state.
+
+        A record will be in the `valid` state when the adapter did not report any
+        server-side validation failures.
+
+        @property isValid
+        @type {Boolean}
+        @readOnly
+      */
+      isValid: retrieveFromCurrentState,
+      /**
+        If the record is in the dirty state this property will report what
+        kind of change has caused it to move into the dirty
+        state. Possible values are:
+
+        - `created` The record has been created by the client and not yet saved to the adapter.
+        - `updated` The record has been updated by the client and not yet saved to the adapter.
+        - `deleted` The record has been deleted by the client and not yet saved to the adapter.
+
+        Example
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('dirtyType'); // 'created'
+        ```
+
+        @property dirtyType
+        @type {String}
+        @readOnly
+      */
+      dirtyType: retrieveFromCurrentState,
+
+      /**
+        If `true` the adapter reported that it was unable to save local
+        changes to the backend for any reason other than a server-side
+        validation error.
+
+        Example
+
+        ```javascript
+        record.get('isError'); // false
+        record.set('foo', 'valid value');
+        record.save().then(null, function() {
+          record.get('isError'); // true
+        });
+        ```
+
+        @property isError
+        @type {Boolean}
+        @readOnly
+      */
+      isError: false,
+      /**
+        If `true` the store is attempting to reload the record form the adapter.
+
+        Example
+
+        ```javascript
+        record.get('isReloading'); // false
+        record.reload();
+        record.get('isReloading'); // true
+        ```
+
+        @property isReloading
+        @type {Boolean}
+        @readOnly
+      */
+      isReloading: false,
+
+      /**
+        The `clientId` property is a transient numerical identifier
+        generated at runtime by the data store. It is important
+        primarily because newly created objects may not yet have an
+        externally generated id.
+
+        @property clientId
+        @private
+        @type {Number|String}
+      */
+      clientId: null,
+      /**
+        All ember models have an id property. This is an identifier
+        managed by an external source. These are always coerced to be
+        strings before being used internally. Note when declaring the
+        attributes for a model it is an error to declare an id
+        attribute.
+
+        ```javascript
+        var record = store.createRecord('model');
+        record.get('id'); // null
+
+        store.find('model', 1).then(function(model) {
+          model.get('id'); // '1'
+        });
+        ```
+
+        @property id
+        @type {String}
+      */
+      id: null,
+
+      /**
+        @property currentState
+        @private
+        @type {Object}
+      */
+      currentState: RootState.empty,
+
+      /**
+        When the record is in the `invalid` state this object will contain
+        any errors returned by the adapter. When present the errors hash
+        typically contains keys corresponding to the invalid property names
+        and values which are an array of error messages.
+
+        ```javascript
+        record.get('errors.length'); // 0
+        record.set('foo', 'invalid value');
+        record.save().then(null, function() {
+          record.get('errors').get('foo'); // ['foo should be a number.']
+        });
+        ```
+
+        @property errors
+        @type {DS.Errors}
+      */
+      errors: Ember.computed(function() {
+        var errors = Errors.create();
+
+        errors.registerHandlers(this, function() {
+          this.send('becameInvalid');
+        }, function() {
+          this.send('becameValid');
+        });
+
+        return errors;
+      }).readOnly(),
+
+      /**
+        Create a JSON representation of the record, using the serialization
+        strategy of the store's adapter.
+
+       `serialize` takes an optional hash as a parameter, currently
+        supported options are:
+
+       - `includeId`: `true` if the record's ID should be included in the
+          JSON representation.
+
+        @method serialize
+        @param {Object} options
+        @return {Object} an object whose values are primitive JSON values only
+      */
+      serialize: function(options) {
+        var store = get(this, 'store');
+        return store.serialize(this, options);
+      },
+
+      /**
+        Use [DS.JSONSerializer](DS.JSONSerializer.html) to
+        get the JSON representation of a record.
+
+        `toJSON` takes an optional hash as a parameter, currently
+        supported options are:
+
+        - `includeId`: `true` if the record's ID should be included in the
+          JSON representation.
+
+        @method toJSON
+        @param {Object} options
+        @return {Object} A JSON representation of the object.
+      */
+      toJSON: function(options) {
+        if (!JSONSerializer) { JSONSerializer = requireModule(&quot;ember-data/lib/serializers/json_serializer&quot;)[&quot;default&quot;]; }
+        // container is for lazy transform lookups
+        var serializer = JSONSerializer.create({ container: this.container });
+        return serializer.serialize(this, options);
+      },
+
+      /**
+        Fired when the record is loaded from the server.
+
+        @event didLoad
+      */
+      didLoad: Ember.K,
+
+      /**
+        Fired when the record is updated.
+
+        @event didUpdate
+      */
+      didUpdate: Ember.K,
+
+      /**
+        Fired when the record is created.
+
+        @event didCreate
+      */
+      didCreate: Ember.K,
+
+      /**
+        Fired when the record is deleted.
+
+        @event didDelete
+      */
+      didDelete: Ember.K,
+
+      /**
+        Fired when the record becomes invalid.
+
+        @event becameInvalid
+      */
+      becameInvalid: Ember.K,
+
+      /**
+        Fired when the record enters the error state.
+
+        @event becameError
+      */
+      becameError: Ember.K,
+
+      /**
+        @property data
+        @private
+        @type {Object}
+      */
+      data: Ember.computed(function() {
+        this._data = this._data || {};
+        return this._data;
+      }).readOnly(),
+
+      _data: null,
+
+      init: function() {
+        this._super();
+        this._setup();
+      },
+
+      _setup: function() {
+        this._changesToSync = {};
+        this._deferredTriggers = [];
+        this._data = {};
+        this._attributes = {};
+        this._inFlightAttributes = {};
+        this._relationships = {};
+      },
+
+      /**
+        @method send
+        @private
+        @param {String} name
+        @param {Object} context
+      */
+      send: function(name, context) {
+        var currentState = get(this, 'currentState');
+
+        if (!currentState[name]) {
+          this._unhandledEvent(currentState, name, context);
+        }
+
+        return currentState[name](this, context);
+      },
+
+      /**
+        @method transitionTo
+        @private
+        @param {String} name
+      */
+      transitionTo: function(name) {
+        // POSSIBLE TODO: Remove this code and replace with
+        // always having direct references to state objects
+
+        var pivotName = name.split(&quot;.&quot;, 1),
+            currentState = get(this, 'currentState'),
+            state = currentState;
+
+        do {
+          if (state.exit) { state.exit(this); }
+          state = state.parentState;
+        } while (!state.hasOwnProperty(pivotName));
+
+        var path = name.split(&quot;.&quot;);
+
+        var setups = [], enters = [], i, l;
+
+        for (i=0, l=path.length; i&lt;l; i++) {
+          state = state[path[i]];
+
+          if (state.enter) { enters.push(state); }
+          if (state.setup) { setups.push(state); }
+        }
+
+        for (i=0, l=enters.length; i&lt;l; i++) {
+          enters[i].enter(this);
+        }
+
+        set(this, 'currentState', state);
+
+        for (i=0, l=setups.length; i&lt;l; i++) {
+          setups[i].setup(this);
+        }
+
+        this.updateRecordArraysLater();
+      },
+
+      _unhandledEvent: function(state, name, context) {
+        var errorMessage = &quot;Attempted to handle event `&quot; + name + &quot;` &quot;;
+        errorMessage    += &quot;on &quot; + String(this) + &quot; while in state &quot;;
+        errorMessage    += state.stateName + &quot;. &quot;;
+
+        if (context !== undefined) {
+          errorMessage  += &quot;Called with &quot; + Ember.inspect(context) + &quot;.&quot;;
+        }
+
+        throw new Ember.Error(errorMessage);
+      },
+
+      withTransaction: function(fn) {
+        var transaction = get(this, 'transaction');
+        if (transaction) { fn(transaction); }
+      },
+
+      /**
+        @method loadingData
+        @private
+        @param {Promise} promise
+      */
+      loadingData: function(promise) {
+        this.send('loadingData', promise);
+      },
+
+      /**
+        @method loadedData
+        @private
+      */
+      loadedData: function() {
+        this.send('loadedData');
+      },
+
+      /**
+        @method notFound
+        @private
+      */
+      notFound: function() {
+        this.send('notFound');
+      },
+
+      /**
+        @method pushedData
+        @private
+      */
+      pushedData: function() {
+        this.send('pushedData');
+      },
+
+      /**
+        Marks the record as deleted but does not save it. You must call
+        `save` afterwards if you want to persist it. You might use this
+        method if you want to allow the user to still `rollback()` a
+        delete after it was made.
+
+        Example
+
+        ```javascript
+        App.ModelDeleteRoute = Ember.Route.extend({
+          actions: {
+            softDelete: function() {
+              this.get('model').deleteRecord();
+            },
+            confirm: function() {
+              this.get('model').save();
+            },
+            undo: function() {
+              this.get('model').rollback();
+            }
+          }
+        });
+        ```
+
+        @method deleteRecord
+      */
+      deleteRecord: function() {
+        this.send('deleteRecord');
+      },
+
+      /**
+        Same as `deleteRecord`, but saves the record immediately.
+
+        Example
+
+        ```javascript
+        App.ModelDeleteRoute = Ember.Route.extend({
+          actions: {
+            delete: function() {
+              var controller = this.controller;
+              this.get('model').destroyRecord().then(function() {
+                controller.transitionToRoute('model.index');
+              });
+            }
+          }
+        });
+        ```
+
+        @method destroyRecord
+        @return {Promise} a promise that will be resolved when the adapter returns
+        successfully or rejected if the adapter returns with an error.
+      */
+      destroyRecord: function() {
+        this.deleteRecord();
+        return this.save();
+      },
+
+      /**
+        @method unloadRecord
+        @private
+      */
+      unloadRecord: function() {
+        if (this.isDestroyed) { return; }
+
+        this.send('unloadRecord');
+      },
+
+      /**
+        @method clearRelationships
+        @private
+      */
+      clearRelationships: function() {
+        this.eachRelationship(function(name, relationship) {
+          if (relationship.kind === 'belongsTo') {
+            set(this, name, null);
+          } else if (relationship.kind === 'hasMany') {
+            var hasMany = this._relationships[name];
+            if (hasMany) { // relationships are created lazily
+              hasMany.destroy();
+            }
+          }
+        }, this);
+      },
+
+      /**
+        @method updateRecordArrays
+        @private
+      */
+      updateRecordArrays: function() {
+        this._updatingRecordArraysLater = false;
+        get(this, 'store').dataWasUpdated(this.constructor, this);
+      },
+
+      /**
+        Returns an object, whose keys are changed properties, and value is
+        an [oldProp, newProp] array.
+
+        Example
+
+        ```javascript
+        App.Mascot = DS.Model.extend({
+          name: attr('string')
+        });
+
+        var person = store.createRecord('person');
+        person.changedAttributes(); // {}
+        person.set('name', 'Tomster');
+        person.changedAttributes(); // {name: [undefined, 'Tomster']}
+        ```
+
+        @method changedAttributes
+        @return {Object} an object, whose keys are changed properties,
+          and value is an [oldProp, newProp] array.
+      */
+      changedAttributes: function() {
+        var oldData = get(this, '_data'),
+            newData = get(this, '_attributes'),
+            diffData = {},
+            prop;
+
+        for (prop in newData) {
+          diffData[prop] = [oldData[prop], newData[prop]];
+        }
+
+        return diffData;
+      },
+
+      /**
+        @method adapterWillCommit
+        @private
+      */
+      adapterWillCommit: function() {
+        this.send('willCommit');
+      },
+
+      /**
+        If the adapter did not return a hash in response to a commit,
+        merge the changed attributes and relationships into the existing
+        saved data.
+
+        @method adapterDidCommit
+      */
+      adapterDidCommit: function(data) {
+        set(this, 'isError', false);
+
+        if (data) {
+          this._data = data;
+        } else {
+          Ember.mixin(this._data, this._inFlightAttributes);
+        }
+
+        this._inFlightAttributes = {};
+
+        this.send('didCommit');
+        this.updateRecordArraysLater();
+
+        if (!data) { return; }
+
+        this.suspendRelationshipObservers(function() {
+          this.notifyPropertyChange('data');
+        });
+      },
+
+      /**
+        @method adapterDidDirty
+        @private
+      */
+      adapterDidDirty: function() {
+        this.send('becomeDirty');
+        this.updateRecordArraysLater();
+      },
+
+      dataDidChange: Ember.observer(function() {
+        this.reloadHasManys();
+      }, 'data'),
+
+      reloadHasManys: function() {
+        var relationships = get(this.constructor, 'relationshipsByName');
+        this.updateRecordArraysLater();
+        relationships.forEach(function(name, relationship) {
+          if (this._data.links &amp;&amp; this._data.links[name]) { return; }
+          if (relationship.kind === 'hasMany') {
+            this.hasManyDidChange(relationship.key);
+          }
+        }, this);
+      },
+
+      hasManyDidChange: function(key) {
+        var hasMany = this._relationships[key];
+
+        if (hasMany) {
+          var records = this._data[key] || [];
+
+          set(hasMany, 'content', Ember.A(records));
+          set(hasMany, 'isLoaded', true);
+          hasMany.trigger('didLoad');
+        }
+      },
+
+      /**
+        @method updateRecordArraysLater
+        @private
+      */
+      updateRecordArraysLater: function() {
+        // quick hack (something like this could be pushed into run.once
+        if (this._updatingRecordArraysLater) { return; }
+        this._updatingRecordArraysLater = true;
+
+        Ember.run.schedule('actions', this, this.updateRecordArrays);
+      },
+
+      /**
+        @method setupData
+        @private
+        @param {Object} data
+        @param {Boolean} partial the data should be merged into
+          the existing data, not replace it.
+      */
+      setupData: function(data, partial) {
+        if (partial) {
+          Ember.merge(this._data, data);
+        } else {
+          this._data = data;
+        }
+
+        var relationships = this._relationships;
+
+        this.eachRelationship(function(name, rel) {
+          if (data.links &amp;&amp; data.links[name]) { return; }
+          if (rel.options.async) { relationships[name] = null; }
+        });
+
+        if (data) { this.pushedData(); }
+
+        this.suspendRelationshipObservers(function() {
+          this.notifyPropertyChange('data');
+        });
+      },
+
+      materializeId: function(id) {
+        set(this, 'id', id);
+      },
+
+      materializeAttributes: function(attributes) {
+        Ember.assert(&quot;Must pass a hash of attributes to materializeAttributes&quot;, !!attributes);
+        merge(this._data, attributes);
+      },
+
+      materializeAttribute: function(name, value) {
+        this._data[name] = value;
+      },
+
+      /**
+        @method updateHasMany
+        @private
+        @param {String} name
+        @param {Array} records
+      */
+      updateHasMany: function(name, records) {
+        this._data[name] = records;
+        this.hasManyDidChange(name);
+      },
+
+      /**
+        @method updateBelongsTo
+        @private
+        @param {String} name
+        @param {DS.Model} record
+      */
+      updateBelongsTo: function(name, record) {
+        this._data[name] = record;
+      },
+
+      /**
+        If the model `isDirty` this function will discard any unsaved
+        changes
+
+        Example
+
+        ```javascript
+        record.get('name'); // 'Untitled Document'
+        record.set('name', 'Doc 1');
+        record.get('name'); // 'Doc 1'
+        record.rollback();
+        record.get('name'); // 'Untitled Document'
+        ```
+
+        @method rollback
+      */
+      rollback: function() {
+        this._attributes = {};
+
+        if (get(this, 'isError')) {
+          this._inFlightAttributes = {};
+          set(this, 'isError', false);
+        }
+
+        if (!get(this, 'isValid')) {
+          this._inFlightAttributes = {};
+        }
+
+        this.send('rolledBack');
+
+        this.suspendRelationshipObservers(function() {
+          this.notifyPropertyChange('data');
+        });
+      },
+
+      toStringExtension: function() {
+        return get(this, 'id');
+      },
+
+      /**
+        The goal of this method is to temporarily disable specific observers
+        that take action in response to application changes.
+
+        This allows the system to make changes (such as materialization and
+        rollback) that should not trigger secondary behavior (such as setting an
+        inverse relationship or marking records as dirty).
+
+        The specific implementation will likely change as Ember proper provides
+        better infrastructure for suspending groups of observers, and if Array
+        observation becomes more unified with regular observers.
+
+        @method suspendRelationshipObservers
+        @private
+        @param callback
+        @param binding
+      */
+      suspendRelationshipObservers: function(callback, binding) {
+        var observers = get(this.constructor, 'relationshipNames').belongsTo;
+        var self = this;
+
+        try {
+          this._suspendedRelationships = true;
+          Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() {
+            Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() {
+              callback.call(binding || self);
+            });
+          });
+        } finally {
+          this._suspendedRelationships = false;
+        }
+      },
+
+      /**
+        Save the record and persist any changes to the record to an
+        extenal source via the adapter.
+
+        Example
+
+        ```javascript
+        record.set('name', 'Tomster');
+        record.save().then(function(){
+          // Success callback
+        }, function() {
+          // Error callback
+        });
+        ```
+        @method save
+        @return {Promise} a promise that will be resolved when the adapter returns
+        successfully or rejected if the adapter returns with an error.
+      */
+      save: function() {
+        var promiseLabel = &quot;DS: Model#save &quot; + this;
+        var resolver = Ember.RSVP.defer(promiseLabel);
+
+        this.get('store').scheduleSave(this, resolver);
+        this._inFlightAttributes = this._attributes;
+        this._attributes = {};
+
+        return PromiseObject.create({ promise: resolver.promise });
+      },
+
+      /**
+        Reload the record from the adapter.
+
+        This will only work if the record has already finished loading
+        and has not yet been modified (`isLoaded` but not `isDirty`,
+        or `isSaving`).
+
+        Example
+
+        ```javascript
+        App.ModelViewRoute = Ember.Route.extend({
+          actions: {
+            reload: function() {
+              this.get('model').reload();
+            }
+          }
+        });
+        ```
+
+        @method reload
+        @return {Promise} a promise that will be resolved with the record when the
+        adapter returns successfully or rejected if the adapter returns
+        with an error.
+      */
+      reload: function() {
+        set(this, 'isReloading', true);
+
+        var  record = this;
+
+        var promiseLabel = &quot;DS: Model#reload of &quot; + this;
+        var promise = new Promise(function(resolve){
+           record.send('reloadRecord', resolve);
+        }, promiseLabel).then(function() {
+          record.set('isReloading', false);
+          record.set('isError', false);
+          return record;
+        }, function(reason) {
+          record.set('isError', true);
+          throw reason;
+        }, &quot;DS: Model#reload complete, update flags&quot;);
+
+        return PromiseObject.create({ promise: promise });
+      },
+
+      // FOR USE DURING COMMIT PROCESS
+
+      adapterDidUpdateAttribute: function(attributeName, value) {
+
+        // If a value is passed in, update the internal attributes and clear
+        // the attribute cache so it picks up the new value. Otherwise,
+        // collapse the current value into the internal attributes because
+        // the adapter has acknowledged it.
+        if (value !== undefined) {
+          this._data[attributeName] = value;
+          this.notifyPropertyChange(attributeName);
+        } else {
+          this._data[attributeName] = this._inFlightAttributes[attributeName];
+        }
+
+        this.updateRecordArraysLater();
+      },
+
+      /**
+        @method adapterDidInvalidate
+        @private
+      */
+      adapterDidInvalidate: function(errors) {
+        var recordErrors = get(this, 'errors');
+        function addError(name) {
+          if (errors[name]) {
+            recordErrors.add(name, errors[name]);
+          }
+        }
+
+        this.eachAttribute(addError);
+        this.eachRelationship(addError);
+      },
+
+      /**
+        @method adapterDidError
+        @private
+      */
+      adapterDidError: function() {
+        this.send('becameError');
+        set(this, 'isError', true);
+      },
+
+      /**
+        Override the default event firing from Ember.Evented to
+        also call methods with the given name.
+
+        @method trigger
+        @private
+        @param name
+      */
+      trigger: function(name) {
+        Ember.tryInvoke(this, name, [].slice.call(arguments, 1));
+        this._super.apply(this, arguments);
+      },
+
+      triggerLater: function() {
+        if (this._deferredTriggers.push(arguments) !== 1) { return; }
+        Ember.run.schedule('actions', this, '_triggerDeferredTriggers');
+      },
+
+      _triggerDeferredTriggers: function() {
+        for (var i=0, l=this._deferredTriggers.length; i&lt;l; i++) {
+          this.trigger.apply(this, this._deferredTriggers[i]);
+        }
+
+        this._deferredTriggers.length = 0;
+      },
+
+      willDestroy: function() {
+        this._super();
+        this.clearRelationships();
+      }
+    });
+
+    Model.reopenClass({
+
+      /**
+        Alias DS.Model's `create` method to `_create`. This allows us to create DS.Model
+        instances from within the store, but if end users accidentally call `create()`
+        (instead of `createRecord()`), we can raise an error.
+
+        @method _create
+        @private
+        @static
+      */
+      _create: Model.create,
+
+      /**
+        Override the class' `create()` method to raise an error. This
+        prevents end users from inadvertently calling `create()` instead
+        of `createRecord()`. The store is still able to create instances
+        by calling the `_create()` method. To create an instance of a
+        `DS.Model` use [store.createRecord](DS.Store.html#method_createRecord).
+
+        @method create
+        @private
+        @static
+      */
+      create: function() {
+        throw new Ember.Error(&quot;You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.&quot;);
+      }
+    });
+
+    __exports__[&quot;default&quot;] = Model;
+  });
+define(&quot;ember-data/lib/system/model/states&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get, set = Ember.set;
+    /*
+      This file encapsulates the various states that a record can transition
+      through during its lifecycle.
+    */
+    /**
+      ### State
+
+      Each record has a `currentState` property that explicitly tracks what
+      state a record is in at any given time. For instance, if a record is
+      newly created and has not yet been sent to the adapter to be saved,
+      it would be in the `root.loaded.created.uncommitted` state.  If a
+      record has had local modifications made to it that are in the
+      process of being saved, the record would be in the
+      `root.loaded.updated.inFlight` state. (These state paths will be
+      explained in more detail below.)
+
+      Events are sent by the record or its store to the record's
+      `currentState` property. How the state reacts to these events is
+      dependent on which state it is in. In some states, certain events
+      will be invalid and will cause an exception to be raised.
+
+      States are hierarchical and every state is a substate of the
+      `RootState`. For example, a record can be in the
+      `root.deleted.uncommitted` state, then transition into the
+      `root.deleted.inFlight` state. If a child state does not implement
+      an event handler, the state manager will attempt to invoke the event
+      on all parent states until the root state is reached. The state
+      hierarchy of a record is described in terms of a path string. You
+      can determine a record's current state by getting the state's
+      `stateName` property:
+
+      ```javascript
+      record.get('currentState.stateName');
+      //=&gt; &quot;root.created.uncommitted&quot;
+       ```
+
+      The hierarchy of valid states that ship with ember data looks like
+      this:
+
+      ```text
+      * root
+        * deleted
+          * saved
+          * uncommitted
+          * inFlight
+        * empty
+        * loaded
+          * created
+            * uncommitted
+            * inFlight
+          * saved
+          * updated
+            * uncommitted
+            * inFlight
+        * loading
+      ```
+
+      The `DS.Model` states are themselves stateless. What we mean is
+      that, the hierarchical states that each of *those* points to is a
+      shared data structure. For performance reasons, instead of each
+      record getting its own copy of the hierarchy of states, each record
+      points to this global, immutable shared instance. How does a state
+      know which record it should be acting on? We pass the record
+      instance into the state's event handlers as the first argument.
+
+      The record passed as the first parameter is where you should stash
+      state about the record if needed; you should never store data on the state
+      object itself.
+
+      ### Events and Flags
+
+      A state may implement zero or more events and flags.
+
+      #### Events
+
+      Events are named functions that are invoked when sent to a record. The
+      record will first look for a method with the given name on the
+      current state. If no method is found, it will search the current
+      state's parent, and then its grandparent, and so on until reaching
+      the top of the hierarchy. If the root is reached without an event
+      handler being found, an exception will be raised. This can be very
+      helpful when debugging new features.
+
+      Here's an example implementation of a state with a `myEvent` event handler:
+
+      ```javascript
+      aState: DS.State.create({
+        myEvent: function(manager, param) {
+          console.log(&quot;Received myEvent with&quot;, param);
+        }
+      })
+      ```
+
+      To trigger this event:
+
+      ```javascript
+      record.send('myEvent', 'foo');
+      //=&gt; &quot;Received myEvent with foo&quot;
+      ```
+
+      Note that an optional parameter can be sent to a record's `send()` method,
+      which will be passed as the second parameter to the event handler.
+
+      Events should transition to a different state if appropriate. This can be
+      done by calling the record's `transitionTo()` method with a path to the
+      desired state. The state manager will attempt to resolve the state path
+      relative to the current state. If no state is found at that path, it will
+      attempt to resolve it relative to the current state's parent, and then its
+      parent, and so on until the root is reached. For example, imagine a hierarchy
+      like this:
+
+          * created
+            * uncommitted &lt;-- currentState
+            * inFlight
+          * updated
+            * inFlight
+
+      If we are currently in the `uncommitted` state, calling
+      `transitionTo('inFlight')` would transition to the `created.inFlight` state,
+      while calling `transitionTo('updated.inFlight')` would transition to
+      the `updated.inFlight` state.
+
+      Remember that *only events* should ever cause a state transition. You should
+      never call `transitionTo()` from outside a state's event handler. If you are
+      tempted to do so, create a new event and send that to the state manager.
+
+      #### Flags
+
+      Flags are Boolean values that can be used to introspect a record's current
+      state in a more user-friendly way than examining its state path. For example,
+      instead of doing this:
+
+      ```javascript
+      var statePath = record.get('stateManager.currentPath');
+      if (statePath === 'created.inFlight') {
+        doSomething();
+      }
+      ```
+
+      You can say:
+
+      ```javascript
+      if (record.get('isNew') &amp;&amp; record.get('isSaving')) {
+        doSomething();
+      }
+      ```
+
+      If your state does not set a value for a given flag, the value will
+      be inherited from its parent (or the first place in the state hierarchy
+      where it is defined).
+
+      The current set of flags are defined below. If you want to add a new flag,
+      in addition to the area below, you will also need to declare it in the
+      `DS.Model` class.
+
+
+       * [isEmpty](DS.Model.html#property_isEmpty)
+       * [isLoading](DS.Model.html#property_isLoading)
+       * [isLoaded](DS.Model.html#property_isLoaded)
+       * [isDirty](DS.Model.html#property_isDirty)
+       * [isSaving](DS.Model.html#property_isSaving)
+       * [isDeleted](DS.Model.html#property_isDeleted)
+       * [isNew](DS.Model.html#property_isNew)
+       * [isValid](DS.Model.html#property_isValid)
+
+      @namespace DS
+      @class RootState
+    */
+
+    function hasDefinedProperties(object) {
+      // Ignore internal property defined by simulated `Ember.create`.
+      var names = Ember.keys(object);
+      var i, l, name;
+      for (i = 0, l = names.length; i &lt; l; i++ ) {
+        name = names[i];
+        if (object.hasOwnProperty(name) &amp;&amp; object[name]) { return true; }
+      }
+
+      return false;
+    }
+
+    function didSetProperty(record, context) {
+      if (context.value === context.originalValue) {
+        delete record._attributes[context.name];
+        record.send('propertyWasReset', context.name);
+      } else if (context.value !== context.oldValue) {
+        record.send('becomeDirty');
+      }
+
+      record.updateRecordArraysLater();
+    }
+
+    // Implementation notes:
+    //
+    // Each state has a boolean value for all of the following flags:
+    //
+    // * isLoaded: The record has a populated `data` property. When a
+    //   record is loaded via `store.find`, `isLoaded` is false
+    //   until the adapter sets it. When a record is created locally,
+    //   its `isLoaded` property is always true.
+    // * isDirty: The record has local changes that have not yet been
+    //   saved by the adapter. This includes records that have been
+    //   created (but not yet saved) or deleted.
+    // * isSaving: The record has been committed, but
+    //   the adapter has not yet acknowledged that the changes have
+    //   been persisted to the backend.
+    // * isDeleted: The record was marked for deletion. When `isDeleted`
+    //   is true and `isDirty` is true, the record is deleted locally
+    //   but the deletion was not yet persisted. When `isSaving` is
+    //   true, the change is in-flight. When both `isDirty` and
+    //   `isSaving` are false, the change has persisted.
+    // * isError: The adapter reported that it was unable to save
+    //   local changes to the backend. This may also result in the
+    //   record having its `isValid` property become false if the
+    //   adapter reported that server-side validations failed.
+    // * isNew: The record was created on the client and the adapter
+    //   did not yet report that it was successfully saved.
+    // * isValid: The adapter did not report any server-side validation
+    //   failures.
+
+    // The dirty state is a abstract state whose functionality is
+    // shared between the `created` and `updated` states.
+    //
+    // The deleted state shares the `isDirty` flag with the
+    // subclasses of `DirtyState`, but with a very different
+    // implementation.
+    //
+    // Dirty states have three child states:
+    //
+    // `uncommitted`: the store has not yet handed off the record
+    //   to be saved.
+    // `inFlight`: the store has handed off the record to be saved,
+    //   but the adapter has not yet acknowledged success.
+    // `invalid`: the record has invalid information and cannot be
+    //   send to the adapter yet.
+    var DirtyState = {
+      initialState: 'uncommitted',
+
+      // FLAGS
+      isDirty: true,
+
+      // SUBSTATES
+
+      // When a record first becomes dirty, it is `uncommitted`.
+      // This means that there are local pending changes, but they
+      // have not yet begun to be saved, and are not invalid.
+      uncommitted: {
+        // EVENTS
+        didSetProperty: didSetProperty,
+
+        propertyWasReset: function(record, name) {
+          var stillDirty = false;
+
+          for (var prop in record._attributes) {
+            stillDirty = true;
+            break;
+          }
+
+          if (!stillDirty) { record.send('rolledBack'); }
+        },
+
+        pushedData: Ember.K,
+
+        becomeDirty: Ember.K,
+
+        willCommit: function(record) {
+          record.transitionTo('inFlight');
+        },
+
+        reloadRecord: function(record, resolve) {
+          resolve(get(record, 'store').reloadRecord(record));
+        },
+
+        rolledBack: function(record) {
+          record.transitionTo('loaded.saved');
+        },
+
+        becameInvalid: function(record) {
+          record.transitionTo('invalid');
+        },
+
+        rollback: function(record) {
+          record.rollback();
+        }
+      },
+
+      // Once a record has been handed off to the adapter to be
+      // saved, it is in the 'in flight' state. Changes to the
+      // record cannot be made during this window.
+      inFlight: {
+        // FLAGS
+        isSaving: true,
+
+        // EVENTS
+        didSetProperty: didSetProperty,
+        becomeDirty: Ember.K,
+        pushedData: Ember.K,
+
+        unloadRecord: function(record) {
+          Ember.assert(&quot;You can only unload a record which is not inFlight. `&quot; + Ember.inspect(record) + &quot; `&quot;, false);
+        },
+
+        // TODO: More robust semantics around save-while-in-flight
+        willCommit: Ember.K,
+
+        didCommit: function(record) {
+          var dirtyType = get(this, 'dirtyType');
+
+          record.transitionTo('saved');
+          record.send('invokeLifecycleCallbacks', dirtyType);
+        },
+
+        becameInvalid: function(record) {
+          record.transitionTo('invalid');
+          record.send('invokeLifecycleCallbacks');
+        },
+
+        becameError: function(record) {
+          record.transitionTo('uncommitted');
+          record.triggerLater('becameError', record);
+        }
+      },
+
+      // A record is in the `invalid` if the adapter has indicated
+      // the the record failed server-side invalidations.
+      invalid: {
+        // FLAGS
+        isValid: false,
+
+        // EVENTS
+        deleteRecord: function(record) {
+          record.transitionTo('deleted.uncommitted');
+          record.clearRelationships();
+        },
+
+        didSetProperty: function(record, context) {
+          get(record, 'errors').remove(context.name);
+
+          didSetProperty(record, context);
+        },
+
+        becomeDirty: Ember.K,
+
+        willCommit: function(record) {
+          get(record, 'errors').clear();
+          record.transitionTo('inFlight');
+        },
+
+        rolledBack: function(record) {
+          get(record, 'errors').clear();
+        },
+
+        becameValid: function(record) {
+          record.transitionTo('uncommitted');
+        },
+
+        invokeLifecycleCallbacks: function(record) {
+          record.triggerLater('becameInvalid', record);
+        },
+
+        exit: function(record) {
+          record._inFlightAttributes = {};
+        }
+      }
+    };
+
+    // The created and updated states are created outside the state
+    // chart so we can reopen their substates and add mixins as
+    // necessary.
+
+    function deepClone(object) {
+      var clone = {}, value;
+
+      for (var prop in object) {
+        value = object[prop];
+        if (value &amp;&amp; typeof value === 'object') {
+          clone[prop] = deepClone(value);
+        } else {
+          clone[prop] = value;
+        }
+      }
+
+      return clone;
+    }
+
+    function mixin(original, hash) {
+      for (var prop in hash) {
+        original[prop] = hash[prop];
+      }
+
+      return original;
+    }
+
+    function dirtyState(options) {
+      var newState = deepClone(DirtyState);
+      return mixin(newState, options);
+    }
+
+    var createdState = dirtyState({
+      dirtyType: 'created',
+      // FLAGS
+      isNew: true
+    });
+
+    createdState.uncommitted.rolledBack = function(record) {
+      record.transitionTo('deleted.saved');
+    };
+
+    var updatedState = dirtyState({
+      dirtyType: 'updated'
+    });
+
+    createdState.uncommitted.deleteRecord = function(record) {
+      record.clearRelationships();
+      record.transitionTo('deleted.saved');
+    };
+
+    createdState.uncommitted.rollback = function(record) {
+      DirtyState.uncommitted.rollback.apply(this, arguments);
+      record.transitionTo('deleted.saved');
+    };
+
+    createdState.uncommitted.propertyWasReset = Ember.K;
+
+    function assertAgainstUnloadRecord(record) {
+      Ember.assert(&quot;You can only unload a record which is not inFlight. `&quot; + Ember.inspect(record) + &quot;`&quot;, false);
+    }
+
+    updatedState.inFlight.unloadRecord = assertAgainstUnloadRecord;
+
+    updatedState.uncommitted.deleteRecord = function(record) {
+      record.transitionTo('deleted.uncommitted');
+      record.clearRelationships();
+    };
+
+    var RootState = {
+      // FLAGS
+      isEmpty: false,
+      isLoading: false,
+      isLoaded: false,
+      isDirty: false,
+      isSaving: false,
+      isDeleted: false,
+      isNew: false,
+      isValid: true,
+
+      // DEFAULT EVENTS
+
+      // Trying to roll back if you're not in the dirty state
+      // doesn't change your state. For example, if you're in the
+      // in-flight state, rolling back the record doesn't move
+      // you out of the in-flight state.
+      rolledBack: Ember.K,
+      unloadRecord: function(record) {
+        // clear relationships before moving to deleted state
+        // otherwise it fails
+        record.clearRelationships();
+        record.transitionTo('deleted.saved');
+      },
+
+
+      propertyWasReset: Ember.K,
+
+      // SUBSTATES
+
+      // A record begins its lifecycle in the `empty` state.
+      // If its data will come from the adapter, it will
+      // transition into the `loading` state. Otherwise, if
+      // the record is being created on the client, it will
+      // transition into the `created` state.
+      empty: {
+        isEmpty: true,
+
+        // EVENTS
+        loadingData: function(record, promise) {
+          record._loadingPromise = promise;
+          record.transitionTo('loading');
+        },
+
+        loadedData: function(record) {
+          record.transitionTo('loaded.created.uncommitted');
+
+          record.suspendRelationshipObservers(function() {
+            record.notifyPropertyChange('data');
+          });
+        },
+
+        pushedData: function(record) {
+          record.transitionTo('loaded.saved');
+          record.triggerLater('didLoad');
+        }
+      },
+
+      // A record enters this state when the store asks
+      // the adapter for its data. It remains in this state
+      // until the adapter provides the requested data.
+      //
+      // Usually, this process is asynchronous, using an
+      // XHR to retrieve the data.
+      loading: {
+        // FLAGS
+        isLoading: true,
+
+        exit: function(record) {
+          record._loadingPromise = null;
+        },
+
+        // EVENTS
+        pushedData: function(record) {
+          record.transitionTo('loaded.saved');
+          record.triggerLater('didLoad');
+          set(record, 'isError', false);
+        },
+
+        becameError: function(record) {
+          record.triggerLater('becameError', record);
+        },
+
+        notFound: function(record) {
+          record.transitionTo('empty');
+        }
+      },
+
+      // A record enters this state when its data is populated.
+      // Most of a record's lifecycle is spent inside substates
+      // of the `loaded` state.
+      loaded: {
+        initialState: 'saved',
+
+        // FLAGS
+        isLoaded: true,
+
+        // SUBSTATES
+
+        // If there are no local changes to a record, it remains
+        // in the `saved` state.
+        saved: {
+          setup: function(record) {
+            var attrs = record._attributes,
+                isDirty = false;
+
+            for (var prop in attrs) {
+              if (attrs.hasOwnProperty(prop)) {
+                isDirty = true;
+                break;
+              }
+            }
+
+            if (isDirty) {
+              record.adapterDidDirty();
+            }
+          },
+
+          // EVENTS
+          didSetProperty: didSetProperty,
+
+          pushedData: Ember.K,
+
+          becomeDirty: function(record) {
+            record.transitionTo('updated.uncommitted');
+          },
+
+          willCommit: function(record) {
+            record.transitionTo('updated.inFlight');
+          },
+
+          reloadRecord: function(record, resolve) {
+            resolve(get(record, 'store').reloadRecord(record));
+          },
+
+          deleteRecord: function(record) {
+            record.transitionTo('deleted.uncommitted');
+            record.clearRelationships();
+          },
+
+          unloadRecord: function(record) {
+            // clear relationships before moving to deleted state
+            // otherwise it fails
+            record.clearRelationships();
+            record.transitionTo('deleted.saved');
+          },
+
+          didCommit: function(record) {
+            record.send('invokeLifecycleCallbacks', get(record, 'lastDirtyType'));
+          },
+
+          // loaded.saved.notFound would be triggered by a failed
+          // `reload()` on an unchanged record
+          notFound: Ember.K
+
+        },
+
+        // A record is in this state after it has been locally
+        // created but before the adapter has indicated that
+        // it has been saved.
+        created: createdState,
+
+        // A record is in this state if it has already been
+        // saved to the server, but there are new local changes
+        // that have not yet been saved.
+        updated: updatedState
+      },
+
+      // A record is in this state if it was deleted from the store.
+      deleted: {
+        initialState: 'uncommitted',
+        dirtyType: 'deleted',
+
+        // FLAGS
+        isDeleted: true,
+        isLoaded: true,
+        isDirty: true,
+
+        // TRANSITIONS
+        setup: function(record) {
+          record.updateRecordArrays();
+        },
+
+        // SUBSTATES
+
+        // When a record is deleted, it enters the `start`
+        // state. It will exit this state when the record
+        // starts to commit.
+        uncommitted: {
+
+          // EVENTS
+
+          willCommit: function(record) {
+            record.transitionTo('inFlight');
+          },
+
+          rollback: function(record) {
+            record.rollback();
+          },
+
+          becomeDirty: Ember.K,
+          deleteRecord: Ember.K,
+
+          rolledBack: function(record) {
+            record.transitionTo('loaded.saved');
+          }
+        },
+
+        // After a record starts committing, but
+        // before the adapter indicates that the deletion
+        // has saved to the server, a record is in the
+        // `inFlight` substate of `deleted`.
+        inFlight: {
+          // FLAGS
+          isSaving: true,
+
+          // EVENTS
+
+          unloadRecord: assertAgainstUnloadRecord,
+
+          // TODO: More robust semantics around save-while-in-flight
+          willCommit: Ember.K,
+          didCommit: function(record) {
+            record.transitionTo('saved');
+
+            record.send('invokeLifecycleCallbacks');
+          },
+
+          becameError: function(record) {
+            record.transitionTo('uncommitted');
+            record.triggerLater('becameError', record);
+          }
+        },
+
+        // Once the adapter indicates that the deletion has
+        // been saved, the record enters the `saved` substate
+        // of `deleted`.
+        saved: {
+          // FLAGS
+          isDirty: false,
+
+          setup: function(record) {
+            var store = get(record, 'store');
+            store.dematerializeRecord(record);
+          },
+
+          invokeLifecycleCallbacks: function(record) {
+            record.triggerLater('didDelete', record);
+            record.triggerLater('didCommit', record);
+          },
+
+          willCommit: Ember.K,
+
+          didCommit: Ember.K
+        }
+      },
+
+      invokeLifecycleCallbacks: function(record, dirtyType) {
+        if (dirtyType === 'created') {
+          record.triggerLater('didCreate', record);
+        } else {
+          record.triggerLater('didUpdate', record);
+        }
+
+        record.triggerLater('didCommit', record);
+      }
+    };
+
+    function wireState(object, parent, name) {
+      /*jshint proto:true*/
+      // TODO: Use Object.create and copy instead
+      object = mixin(parent ? Ember.create(parent) : {}, object);
+      object.parentState = parent;
+      object.stateName = name;
+
+      for (var prop in object) {
+        if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; }
+        if (typeof object[prop] === 'object') {
+          object[prop] = wireState(object[prop], object, name + &quot;.&quot; + prop);
+        }
+      }
+
+      return object;
+    }
+
+    RootState = wireState(RootState, null, &quot;root&quot;);
+
+    __exports__[&quot;default&quot;] = RootState;
+  });
+define(&quot;ember-data/lib/system/record_array_manager&quot;, 
+  [&quot;./record_arrays&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var RecordArray = __dependency1__.RecordArray;
+    var FilteredRecordArray = __dependency1__.FilteredRecordArray;
+    var AdapterPopulatedRecordArray = __dependency1__.AdapterPopulatedRecordArray;
+    var ManyArray = __dependency1__.ManyArray;
+    var get = Ember.get, set = Ember.set;
+    var forEach = Ember.EnumerableUtils.forEach;
+
+    /**
+      @class RecordArrayManager
+      @namespace DS
+      @private
+      @extends Ember.Object
+    */
+    var RecordArrayManager = Ember.Object.extend({
+      init: function() {
+        this.filteredRecordArrays = Ember.MapWithDefault.create({
+          defaultValue: function() { return []; }
+        });
+
+        this.changedRecords = [];
+        this._adapterPopulatedRecordArrays = [];
+      },
+
+      recordDidChange: function(record) {
+        if (this.changedRecords.push(record) !== 1) { return; }
+
+        Ember.run.schedule('actions', this, this.updateRecordArrays);
+      },
+
+      recordArraysForRecord: function(record) {
+        record._recordArrays = record._recordArrays || Ember.OrderedSet.create();
+        return record._recordArrays;
+      },
+
+      /**
+        This method is invoked whenever data is loaded into the store by the
+        adapter or updated by the adapter, or when a record has changed.
+
+        It updates all record arrays that a record belongs to.
+
+        To avoid thrashing, it only runs at most once per run loop.
+
+        @method updateRecordArrays
+        @param {Class} type
+        @param {Number|String} clientId
+      */
+      updateRecordArrays: function() {
+        forEach(this.changedRecords, function(record) {
+          if (get(record, 'isDeleted')) {
+            this._recordWasDeleted(record);
+          } else {
+            this._recordWasChanged(record);
+          }
+        }, this);
+
+        this.changedRecords.length = 0;
+      },
+
+      _recordWasDeleted: function (record) {
+        var recordArrays = record._recordArrays;
+
+        if (!recordArrays) { return; }
+
+        forEach(recordArrays, function(array) {
+          array.removeRecord(record);
+        });
+      },
+
+      _recordWasChanged: function (record) {
+        var type = record.constructor,
+            recordArrays = this.filteredRecordArrays.get(type),
+            filter;
+
+        forEach(recordArrays, function(array) {
+          filter = get(array, 'filterFunction');
+          this.updateRecordArray(array, filter, type, record);
+        }, this);
+
+        // loop through all manyArrays containing an unloaded copy of this
+        // clientId and notify them that the record was loaded.
+        var manyArrays = record._loadingRecordArrays;
+
+        if (manyArrays) {
+          for (var i=0, l=manyArrays.length; i&lt;l; i++) {
+            manyArrays[i].loadedRecord();
+          }
+
+          record._loadingRecordArrays = [];
+        }
+      },
+
+      /**
+        Update an individual filter.
+
+        @method updateRecordArray
+        @param {DS.FilteredRecordArray} array
+        @param {Function} filter
+        @param {Class} type
+        @param {Number|String} clientId
+      */
+      updateRecordArray: function(array, filter, type, record) {
+        var shouldBeInArray;
+
+        if (!filter) {
+          shouldBeInArray = true;
+        } else {
+          shouldBeInArray = filter(record);
+        }
+
+        var recordArrays = this.recordArraysForRecord(record);
+
+        if (shouldBeInArray) {
+          recordArrays.add(array);
+          array.addRecord(record);
+        } else if (!shouldBeInArray) {
+          recordArrays.remove(array);
+          array.removeRecord(record);
+        }
+      },
+
+      /**
+        This method is invoked if the `filterFunction` property is
+        changed on a `DS.FilteredRecordArray`.
+
+        It essentially re-runs the filter from scratch. This same
+        method is invoked when the filter is created in th first place.
+
+        @method updateFilter
+        @param array
+        @param type
+        @param filter
+      */
+      updateFilter: function(array, type, filter) {
+        var typeMap = this.store.typeMapFor(type),
+            records = typeMap.records, record;
+
+        for (var i=0, l=records.length; i&lt;l; i++) {
+          record = records[i];
+
+          if (!get(record, 'isDeleted') &amp;&amp; !get(record, 'isEmpty')) {
+            this.updateRecordArray(array, filter, type, record);
+          }
+        }
+      },
+
+      /**
+        Create a `DS.ManyArray` for a type and list of record references, and index
+        the `ManyArray` under each reference. This allows us to efficiently remove
+        records from `ManyArray`s when they are deleted.
+
+        @method createManyArray
+        @param {Class} type
+        @param {Array} references
+        @return {DS.ManyArray}
+      */
+      createManyArray: function(type, records) {
+        var manyArray = ManyArray.create({
+          type: type,
+          content: records,
+          store: this.store
+        });
+
+        forEach(records, function(record) {
+          var arrays = this.recordArraysForRecord(record);
+          arrays.add(manyArray);
+        }, this);
+
+        return manyArray;
+      },
+
+      /**
+        Create a `DS.RecordArray` for a type and register it for updates.
+
+        @method createRecordArray
+        @param {Class} type
+        @return {DS.RecordArray}
+      */
+      createRecordArray: function(type) {
+        var array = RecordArray.create({
+          type: type,
+          content: Ember.A(),
+          store: this.store,
+          isLoaded: true
+        });
+
+        this.registerFilteredRecordArray(array, type);
+
+        return array;
+      },
+
+      /**
+        Create a `DS.FilteredRecordArray` for a type and register it for updates.
+
+        @method createFilteredRecordArray
+        @param {Class} type
+        @param {Function} filter
+        @param {Object} query (optional
+        @return {DS.FilteredRecordArray}
+      */
+      createFilteredRecordArray: function(type, filter, query) {
+        var array = FilteredRecordArray.create({
+          query: query,
+          type: type,
+          content: Ember.A(),
+          store: this.store,
+          manager: this,
+          filterFunction: filter
+        });
+
+        this.registerFilteredRecordArray(array, type, filter);
+
+        return array;
+      },
+
+      /**
+        Create a `DS.AdapterPopulatedRecordArray` for a type with given query.
+
+        @method createAdapterPopulatedRecordArray
+        @param {Class} type
+        @param {Object} query
+        @return {DS.AdapterPopulatedRecordArray}
+      */
+      createAdapterPopulatedRecordArray: function(type, query) {
+        var array = AdapterPopulatedRecordArray.create({
+          type: type,
+          query: query,
+          content: Ember.A(),
+          store: this.store,
+          manager: this
+        });
+
+        this._adapterPopulatedRecordArrays.push(array);
+
+        return array;
+      },
+
+      /**
+        Register a RecordArray for a given type to be backed by
+        a filter function. This will cause the array to update
+        automatically when records of that type change attribute
+        values or states.
+
+        @method registerFilteredRecordArray
+        @param {DS.RecordArray} array
+        @param {Class} type
+        @param {Function} filter
+      */
+      registerFilteredRecordArray: function(array, type, filter) {
+        var recordArrays = this.filteredRecordArrays.get(type);
+        recordArrays.push(array);
+
+        this.updateFilter(array, type, filter);
+      },
+
+      // Internally, we maintain a map of all unloaded IDs requested by
+      // a ManyArray. As the adapter loads data into the store, the
+      // store notifies any interested ManyArrays. When the ManyArray's
+      // total number of loading records drops to zero, it becomes
+      // `isLoaded` and fires a `didLoad` event.
+      registerWaitingRecordArray: function(record, array) {
+        var loadingRecordArrays = record._loadingRecordArrays || [];
+        loadingRecordArrays.push(array);
+        record._loadingRecordArrays = loadingRecordArrays;
+      },
+
+      willDestroy: function(){
+        this._super();
+
+        forEach(flatten(values(this.filteredRecordArrays.values)), destroy);
+        forEach(this._adapterPopulatedRecordArrays, destroy);
+      }
+    });
+
+    function values(obj) {
+      var result = [];
+      var keys = Ember.keys(obj);
+
+      for (var i = 0; i &lt; keys.length; i++) {
+        result.push(obj[keys[i]]);
+      }
+
+      return result;
+    }
+
+    function destroy(entry) {
+      entry.destroy();
+    }
+
+    function flatten(list) {
+      var length = list.length;
+      var result = Ember.A();
+
+      for (var i = 0; i &lt; length; i++) {
+        result = result.concat(list[i]);
+      }
+
+      return result;
+    }
+
+    __exports__[&quot;default&quot;] = RecordArrayManager;
+  });
+define(&quot;ember-data/lib/system/record_arrays&quot;, 
+  [&quot;./record_arrays/record_array&quot;,&quot;./record_arrays/filtered_record_array&quot;,&quot;./record_arrays/adapter_populated_record_array&quot;,&quot;./record_arrays/many_array&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var RecordArray = __dependency1__[&quot;default&quot;];
+    var FilteredRecordArray = __dependency2__[&quot;default&quot;];
+    var AdapterPopulatedRecordArray = __dependency3__[&quot;default&quot;];
+    var ManyArray = __dependency4__[&quot;default&quot;];
+
+    __exports__.RecordArray = RecordArray;
+    __exports__.FilteredRecordArray = FilteredRecordArray;
+    __exports__.AdapterPopulatedRecordArray = AdapterPopulatedRecordArray;
+    __exports__.ManyArray = ManyArray;
+  });
+define(&quot;ember-data/lib/system/record_arrays/adapter_populated_record_array&quot;, 
+  [&quot;./record_array&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var RecordArray = __dependency1__[&quot;default&quot;];
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get, set = Ember.set;
+
+    /**
+      Represents an ordered list of records whose order and membership is
+      determined by the adapter. For example, a query sent to the adapter
+      may trigger a search on the server, whose results would be loaded
+      into an instance of the `AdapterPopulatedRecordArray`.
+
+      @class AdapterPopulatedRecordArray
+      @namespace DS
+      @extends DS.RecordArray
+    */
+    var AdapterPopulatedRecordArray = RecordArray.extend({
+      query: null,
+
+      replace: function() {
+        var type = get(this, 'type').toString();
+        throw new Error(&quot;The result of a server query (on &quot; + type + &quot;) is immutable.&quot;);
+      },
+
+      /**
+        @method load
+        @private
+        @param {Array} data
+      */
+      load: function(data) {
+        var store = get(this, 'store'),
+            type = get(this, 'type'),
+            records = store.pushMany(type, data),
+            meta = store.metadataFor(type);
+
+        this.setProperties({
+          content: Ember.A(records),
+          isLoaded: true,
+          meta: Ember.copy(meta)
+        });
+
+        records.forEach(function(record) {
+          this.manager.recordArraysForRecord(record).add(this);
+        }, this);
+
+        // TODO: should triggering didLoad event be the last action of the runLoop?
+        Ember.run.once(this, 'trigger', 'didLoad');
+      }
+    });
+
+    __exports__[&quot;default&quot;] = AdapterPopulatedRecordArray;
+  });
+define(&quot;ember-data/lib/system/record_arrays/filtered_record_array&quot;, 
+  [&quot;./record_array&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var RecordArray = __dependency1__[&quot;default&quot;];
+
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get;
+
+    /**
+      Represents a list of records whose membership is determined by the
+      store. As records are created, loaded, or modified, the store
+      evaluates them to determine if they should be part of the record
+      array.
+
+      @class FilteredRecordArray
+      @namespace DS
+      @extends DS.RecordArray
+    */
+    var FilteredRecordArray = RecordArray.extend({
+      /**
+        The filterFunction is a function used to test records from the store to
+        determine if they should be part of the record array.
+
+        Example
+
+        ```javascript
+        var allPeople = store.all('person');
+        allPeople.mapBy('name'); // [&quot;Tom Dale&quot;, &quot;Yehuda Katz&quot;, &quot;Trek Glowacki&quot;]
+
+        var people = store.filter('person', function(person) {
+          if (person.get('name').match(/Katz$/)) { return true; }
+        });
+        people.mapBy('name'); // [&quot;Yehuda Katz&quot;]
+
+        var notKatzFilter = function(person) {
+          return !person.get('name').match(/Katz$/);
+        };
+        people.set('filterFunction', notKatzFilter);
+        people.mapBy('name'); // [&quot;Tom Dale&quot;, &quot;Trek Glowacki&quot;]
+        ```
+
+        @method filterFunction
+        @param {DS.Model} record
+        @return {Boolean} `true` if the record should be in the array
+      */
+      filterFunction: null,
+      isLoaded: true,
+
+      replace: function() {
+        var type = get(this, 'type').toString();
+        throw new Error(&quot;The result of a client-side filter (on &quot; + type + &quot;) is immutable.&quot;);
+      },
+
+      /**
+        @method updateFilter
+        @private
+      */
+      _updateFilter: function() {
+        var manager = get(this, 'manager');
+        manager.updateFilter(this, get(this, 'type'), get(this, 'filterFunction'));
+      },
+
+      updateFilter: Ember.observer(function() {
+        Ember.run.once(this, this._updateFilter);
+      }, 'filterFunction')
+    });
+
+    __exports__[&quot;default&quot;] = FilteredRecordArray;
+  });
+define(&quot;ember-data/lib/system/record_arrays/many_array&quot;, 
+  [&quot;./record_array&quot;,&quot;../changes&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    var RecordArray = __dependency1__[&quot;default&quot;];
+    var RelationshipChange = __dependency2__.RelationshipChange;
+
+    /**
+      @module ember-data
+    */
+
+    var get = Ember.get, set = Ember.set;
+    var map = Ember.EnumerableUtils.map;
+
+    function sync(change) {
+      change.sync();
+    }
+
+    /**
+      A `ManyArray` is a `RecordArray` that represents the contents of a has-many
+      relationship.
+
+      The `ManyArray` is instantiated lazily the first time the relationship is
+      requested.
+
+      ### Inverses
+
+      Often, the relationships in Ember Data applications will have
+      an inverse. For example, imagine the following models are
+      defined:
+
+      ```javascript
+      App.Post = DS.Model.extend({
+        comments: DS.hasMany('comment')
+      });
+
+      App.Comment = DS.Model.extend({
+        post: DS.belongsTo('post')
+      });
+      ```
+
+      If you created a new instance of `App.Post` and added
+      a `App.Comment` record to its `comments` has-many
+      relationship, you would expect the comment's `post`
+      property to be set to the post that contained
+      the has-many.
+
+      We call the record to which a relationship belongs the
+      relationship's _owner_.
+
+      @class ManyArray
+      @namespace DS
+      @extends DS.RecordArray
+    */
+    var ManyArray = RecordArray.extend({
+      init: function() {
+        this._super.apply(this, arguments);
+        this._changesToSync = Ember.OrderedSet.create();
+      },
+
+      /**
+        The property name of the relationship
+
+        @property {String} name
+        @private
+      */
+      name: null,
+
+      /**
+        The record to which this relationship belongs.
+
+        @property {DS.Model} owner
+        @private
+      */
+      owner: null,
+
+      /**
+        `true` if the relationship is polymorphic, `false` otherwise.
+
+        @property {Boolean} isPolymorphic
+        @private
+      */
+      isPolymorphic: false,
+
+      // LOADING STATE
+
+      isLoaded: false,
+
+      /**
+        Used for async `hasMany` arrays
+        to keep track of when they will resolve.
+
+        @property {Ember.RSVP.Promise} promise
+        @private
+      */
+      promise: null,
+
+      /**
+        @method loadingRecordsCount
+        @param {Number} count
+        @private
+      */
+      loadingRecordsCount: function(count) {
+        this.loadingRecordsCount = count;
+      },
+
+      /**
+        @method loadedRecord
+        @private
+      */
+      loadedRecord: function() {
+        this.loadingRecordsCount--;
+        if (this.loadingRecordsCount === 0) {
+          set(this, 'isLoaded', true);
+          this.trigger('didLoad');
+        }
+      },
+
+      /**
+        @method fetch
+        @private
+      */
+      fetch: function() {
+        var records = get(this, 'content'),
+            store = get(this, 'store'),
+            owner = get(this, 'owner');
+
+        var unloadedRecords = records.filterProperty('isEmpty', true);
+        store.fetchMany(unloadedRecords, owner);
+      },
+
+      // Overrides Ember.Array's replace method to implement
+      replaceContent: function(index, removed, added) {
+        // Map the array of record objects into an array of  client ids.
+        added = map(added, function(record) {
+          Ember.assert(&quot;You cannot add '&quot; + record.constructor.typeKey + &quot;' records to this relationship (only '&quot; + this.type.typeKey + &quot;' allowed)&quot;, !this.type || record instanceof this.type);
+          return record;
+        }, this);
+
+        this._super(index, removed, added);
+      },
+
+      arrangedContentDidChange: function() {
+        Ember.run.once(this, 'fetch');
+      },
+
+      arrayContentWillChange: function(index, removed, added) {
+        var owner = get(this, 'owner'),
+            name = get(this, 'name');
+
+        if (!owner._suspendedRelationships) {
+          // This code is the first half of code that continues inside
+          // of arrayContentDidChange. It gets or creates a change from
+          // the child object, adds the current owner as the old
+          // parent if this is the first time the object was removed
+          // from a ManyArray, and sets `newParent` to null.
+          //
+          // Later, if the object is added to another ManyArray,
+          // the `arrayContentDidChange` will set `newParent` on
+          // the change.
+          for (var i=index; i&lt;index+removed; i++) {
+            var record = get(this, 'content').objectAt(i);
+
+            var change = RelationshipChange.createChange(owner, record, get(this, 'store'), {
+              parentType: owner.constructor,
+              changeType: &quot;remove&quot;,
+              kind: &quot;hasMany&quot;,
+              key: name
+            });
+
+            this._changesToSync.add(change);
+          }
+        }
+
+        return this._super.apply(this, arguments);
+      },
+
+      arrayContentDidChange: function(index, removed, added) {
+        this._super.apply(this, arguments);
+
+        var owner = get(this, 'owner'),
+            name = get(this, 'name'),
+            store = get(this, 'store');
+
+        if (!owner._suspendedRelationships) {
+          // This code is the second half of code that started in
+          // `arrayContentWillChange`. It gets or creates a change
+          // from the child object, and adds the current owner as
+          // the new parent.
+          for (var i=index; i&lt;index+added; i++) {
+            var record = get(this, 'content').objectAt(i);
+
+            var change = RelationshipChange.createChange(owner, record, store, {
+              parentType: owner.constructor,
+              changeType: &quot;add&quot;,
+              kind:&quot;hasMany&quot;,
+              key: name
+            });
+            change.hasManyName = name;
+
+            this._changesToSync.add(change);
+          }
+
+          // We wait until the array has finished being
+          // mutated before syncing the OneToManyChanges created
+          // in arrayContentWillChange, so that the array
+          // membership test in the sync() logic operates
+          // on the final results.
+          this._changesToSync.forEach(sync);
+
+          this._changesToSync.clear();
+        }
+      },
+
+      /**
+        Create a child record within the owner
+
+        @method createRecord
+        @private
+        @param {Object} hash
+        @return {DS.Model} record
+      */
+      createRecord: function(hash) {
+        var owner = get(this, 'owner'),
+            store = get(owner, 'store'),
+            type = get(this, 'type'),
+            record;
+
+        Ember.assert(&quot;You cannot add '&quot; + type.typeKey + &quot;' records to this polymorphic relationship.&quot;, !get(this, 'isPolymorphic'));
+
+        record = store.createRecord.call(store, type, hash);
+        this.pushObject(record);
+
+        return record;
+      }
+    });
+
+    __exports__[&quot;default&quot;] = ManyArray;
+  });
+define(&quot;ember-data/lib/system/record_arrays/record_array&quot;, 
+  [&quot;../store&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var PromiseArray = __dependency1__.PromiseArray;
+    var get = Ember.get, set = Ember.set;
+
+    /**
+      A record array is an array that contains records of a certain type. The record
+      array materializes records as needed when they are retrieved for the first
+      time. You should not create record arrays yourself. Instead, an instance of
+      `DS.RecordArray` or its subclasses will be returned by your application's store
+      in response to queries.
+
+      @class RecordArray
+      @namespace DS
+      @extends Ember.ArrayProxy
+      @uses Ember.Evented
+    */
+
+    var RecordArray = Ember.ArrayProxy.extend(Ember.Evented, {
+      /**
+        The model type contained by this record array.
+
+        @property type
+        @type DS.Model
+      */
+      type: null,
+
+      /**
+        The array of client ids backing the record array. When a
+        record is requested from the record array, the record
+        for the client id at the same index is materialized, if
+        necessary, by the store.
+
+        @property content
+        @private
+        @type Ember.Array
+      */
+      content: null,
+
+      /**
+        The flag to signal a `RecordArray` is currently loading data.
+
+        Example
+
+        ```javascript
+        var people = store.all('person');
+        people.get('isLoaded'); // true
+        ```
+
+        @property isLoaded
+        @type Boolean
+      */
+      isLoaded: false,
+      /**
+        The flag to signal a `RecordArray` is currently loading data.
+
+        Example
+
+        ```javascript
+        var people = store.all('person');
+        people.get('isUpdating'); // false
+        people.update();
+        people.get('isUpdating'); // true
+        ```
+
+        @property isUpdating
+        @type Boolean
+      */
+      isUpdating: false,
+
+      /**
+        The store that created this record array.
+
+        @property store
+        @private
+        @type DS.Store
+      */
+      store: null,
+
+      /**
+        Retrieves an object from the content by index.
+
+        @method objectAtContent
+        @private
+        @param {Number} index
+        @return {DS.Model} record
+      */
+      objectAtContent: function(index) {
+        var content = get(this, 'content');
+
+        return content.objectAt(index);
+      },
+
+      /**
+        Used to get the latest version of all of the records in this array
+        from the adapter.
+
+        Example
+
+        ```javascript
+        var people = store.all('person');
+        people.get('isUpdating'); // false
+        people.update();
+        people.get('isUpdating'); // true
+        ```
+
+        @method update
+      */
+      update: function() {
+        if (get(this, 'isUpdating')) { return; }
+
+        var store = get(this, 'store'),
+            type = get(this, 'type');
+
+        return store.fetchAll(type, this);
+      },
+
+      /**
+        Adds a record to the `RecordArray`.
+
+        @method addRecord
+        @private
+        @param {DS.Model} record
+      */
+      addRecord: function(record) {
+        get(this, 'content').addObject(record);
+      },
+
+      /**
+        Removes a record to the `RecordArray`.
+
+        @method removeRecord
+        @private
+        @param {DS.Model} record
+      */
+      removeRecord: function(record) {
+        get(this, 'content').removeObject(record);
+      },
+
+      /**
+        Saves all of the records in the `RecordArray`.
+
+        Example
+
+        ```javascript
+        var messages = store.all('message');
+        messages.forEach(function(message) {
+          message.set('hasBeenSeen', true);
+        });
+        messages.save();
+        ```
+
+        @method save
+        @return {DS.PromiseArray} promise
+      */
+      save: function() {
+        var promiseLabel = &quot;DS: RecordArray#save &quot; + get(this, 'type');
+        var promise = Ember.RSVP.all(this.invoke(&quot;save&quot;), promiseLabel).then(function(array) {
+          return Ember.A(array);
+        }, null, &quot;DS: RecordArray#save apply Ember.NativeArray&quot;);
+
+        return PromiseArray.create({ promise: promise });
+      },
+
+      _dissociateFromOwnRecords: function() {
+        var array = this;
+
+        this.forEach(function(record){
+          var recordArrays = record._recordArrays;
+
+          if (recordArrays) {
+            recordArrays.remove(array);
+          }
+        });
+      },
+
+      willDestroy: function(){
+        this._dissociateFromOwnRecords();
+        this._super();
+      }
+    });
+
+    __exports__[&quot;default&quot;] = RecordArray;
+  });
+define(&quot;ember-data/lib/system/relationship-meta&quot;, 
+  [&quot;../../../ember-inflector/lib/system&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var singularize = __dependency1__.singularize;
+
+    function typeForRelationshipMeta(store, meta) {
+      var typeKey, type;
+
+      typeKey = meta.type || meta.key;
+      if (typeof typeKey === 'string') {
+        if (meta.kind === 'hasMany') {
+          typeKey = singularize(typeKey);
+        }
+        type = store.modelFor(typeKey);
+      } else {
+        type = meta.type;
+      }
+
+      return type;
+    }
+
+    __exports__.typeForRelationshipMeta = typeForRelationshipMeta;function relationshipFromMeta(store, meta) {
+      return {
+        key:  meta.key,
+        kind: meta.kind,
+        type: typeForRelationshipMeta(store, meta),
+        options:    meta.options,
+        parentType: meta.parentType,
+        isRelationship: true
+      };
+    }
+
+    __exports__.relationshipFromMeta = relationshipFromMeta;
+  });
+define(&quot;ember-data/lib/system/relationships&quot;, 
+  [&quot;./relationships/belongs_to&quot;,&quot;./relationships/has_many&quot;,&quot;../system/relationships/ext&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var belongsTo = __dependency1__[&quot;default&quot;];
+    var hasMany = __dependency2__[&quot;default&quot;];
+
+
+    __exports__.belongsTo = belongsTo;
+    __exports__.hasMany = hasMany;
+  });
+define(&quot;ember-data/lib/system/relationships/belongs_to&quot;, 
+  [&quot;../model&quot;,&quot;../store&quot;,&quot;../changes&quot;,&quot;../relationship-meta&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+    &quot;use strict&quot;;
+    var get = Ember.get, set = Ember.set,
+        isNone = Ember.isNone;
+
+    var Promise = Ember.RSVP.Promise;
+
+    var Model = __dependency1__.Model;
+    var PromiseObject = __dependency2__.PromiseObject;
+    var RelationshipChange = __dependency3__.RelationshipChange;
+    var relationshipFromMeta = __dependency4__.relationshipFromMeta;
+    var typeForRelationshipMeta = __dependency4__.typeForRelationshipMeta;
+
+    /**
+      @module ember-data
+    */
+
+    function asyncBelongsTo(type, options, meta) {
+      return Ember.computed('data', function(key, value) {
+        var data = get(this, 'data'),
+            store = get(this, 'store'),
+            promiseLabel = &quot;DS: Async belongsTo &quot; + this + &quot; : &quot; + key,
+            promise;
+
+        meta.key = key;
+
+        if (arguments.length === 2) {
+          Ember.assert(&quot;You can only add a '&quot; + type + &quot;' record to this relationship&quot;, !value || value instanceof typeForRelationshipMeta(store, meta));
+          return value === undefined ? null : PromiseObject.create({
+            promise: Promise.cast(value, promiseLabel)
+          });
+        }
+
+        var link = data.links &amp;&amp; data.links[key],
+            belongsTo = data[key];
+
+        if(!isNone(belongsTo)) {
+          promise = store.fetchRecord(belongsTo) || Promise.cast(belongsTo, promiseLabel);
+          return PromiseObject.create({
+            promise: promise
+          });
+        } else if (link) {
+          promise = store.findBelongsTo(this, link, relationshipFromMeta(store, meta));
+          return PromiseObject.create({
+            promise: promise
+          });
+        } else {
+          return null;
+        }
+      }).meta(meta);
+    }
+
+    /**
+      `DS.belongsTo` is used to define One-To-One and One-To-Many
+      relationships on a [DS.Model](/api/data/classes/DS.Model.html).
+
+
+      `DS.belongsTo` takes an optional hash as a second parameter, currently
+      supported options are:
+
+      - `async`: A boolean value used to explicitly declare this to be an async relationship.
+      - `inverse`: A string used to identify the inverse property on a
+        related model in a One-To-Many relationship. See [Explicit Inverses](#toc_explicit-inverses)
+
+      #### One-To-One
+      To declare a one-to-one relationship between two models, use
+      `DS.belongsTo`:
+
+      ```javascript
+      App.User = DS.Model.extend({
+        profile: DS.belongsTo('profile')
+      });
+
+      App.Profile = DS.Model.extend({
+        user: DS.belongsTo('user')
+      });
+      ```
+
+      #### One-To-Many
+      To declare a one-to-many relationship between two models, use
+      `DS.belongsTo` in combination with `DS.hasMany`, like this:
+
+      ```javascript
+      App.Post = DS.Model.extend({
+        comments: DS.hasMany('comment')
+      });
+
+      App.Comment = DS.Model.extend({
+        post: DS.belongsTo('post')
+      });
+      ```
+
+      @namespace
+      @method belongsTo
+      @for DS
+      @param {String or DS.Model} type the model type of the relationship
+      @param {Object} options a hash of options
+      @return {Ember.computed} relationship
+    */
+    function belongsTo(type, options) {
+      if (typeof type === 'object') {
+        options = type;
+        type = undefined;
+      } else {
+        Ember.assert(&quot;The first argument to DS.belongsTo must be a string representing a model type key, e.g. use DS.belongsTo('person') to define a relation to the App.Person model&quot;, !!type &amp;&amp; (typeof type === 'string' || Model.detect(type)));
+      }
+
+      options = options || {};
+
+      var meta = {
+        type: type,
+        isRelationship: true,
+        options: options,
+        kind: 'belongsTo',
+        key: null
+      };
+
+      if (options.async) {
+        return asyncBelongsTo(type, options, meta);
+      }
+
+      return Ember.computed('data', function(key, value) {
+        var data = get(this, 'data'),
+            store = get(this, 'store'), belongsTo, typeClass;
+
+        if (typeof type === 'string') {
+          typeClass = store.modelFor(type);
+        } else {
+          typeClass = type;
+        }
+
+        if (arguments.length === 2) {
+          Ember.assert(&quot;You can only add a '&quot; + type + &quot;' record to this relationship&quot;, !value || value instanceof typeClass);
+          return value === undefined ? null : value;
+        }
+
+        belongsTo = data[key];
+
+        if (isNone(belongsTo)) { return null; }
+
+        store.fetchRecord(belongsTo);
+
+        return belongsTo;
+      }).meta(meta);
+    }
+
+    /**
+      These observers observe all `belongsTo` relationships on the record. See
+      `relationships/ext` to see how these observers get their dependencies.
+
+      @class Model
+      @namespace DS
+    */
+    Model.reopen({
+
+      /**
+        @method belongsToWillChange
+        @private
+        @static
+        @param record
+        @param key
+      */
+      belongsToWillChange: Ember.beforeObserver(function(record, key) {
+        if (get(record, 'isLoaded')) {
+          var oldParent = get(record, key);
+
+          if (oldParent) {
+            var store = get(record, 'store'),
+                change = RelationshipChange.createChange(record, oldParent, store, { key: key, kind: &quot;belongsTo&quot;, changeType: &quot;remove&quot; });
+
+            change.sync();
+            this._changesToSync[key] = change;
+          }
+        }
+      }),
+
+      /**
+        @method belongsToDidChange
+        @private
+        @static
+        @param record
+        @param key
+      */
+      belongsToDidChange: Ember.immediateObserver(function(record, key) {
+        if (get(record, 'isLoaded')) {
+          var newParent = get(record, key);
+
+          if (newParent) {
+            var store = get(record, 'store'),
+                change = RelationshipChange.createChange(record, newParent, store, { key: key, kind: &quot;belongsTo&quot;, changeType: &quot;add&quot; });
+
+            change.sync();
+          }
+        }
+
+        delete this._changesToSync[key];
+      })
+    });
+
+    __exports__[&quot;default&quot;] = belongsTo;
+  });
+define(&quot;ember-data/lib/system/relationships/ext&quot;, 
+  [&quot;../../../../ember-inflector/lib/system&quot;,&quot;../relationship-meta&quot;,&quot;../model&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__) {
+    &quot;use strict&quot;;
+    var singularize = __dependency1__.singularize;
+    var typeForRelationshipMeta = __dependency2__.typeForRelationshipMeta;
+    var relationshipFromMeta = __dependency2__.relationshipFromMeta;
+    var Model = __dependency3__.Model;
+
+    var get = Ember.get, set = Ember.set;
+
+    /**
+      @module ember-data
+    */
+
+    /*
+      This file defines several extensions to the base `DS.Model` class that
+      add support for one-to-many relationships.
+    */
+
+    /**
+      @class Model
+      @namespace DS
+    */
+    Model.reopen({
+
+      /**
+        This Ember.js hook allows an object to be notified when a property
+        is defined.
+
+        In this case, we use it to be notified when an Ember Data user defines a
+        belongs-to relationship. In that case, we need to set up observers for
+        each one, allowing us to track relationship changes and automatically
+        reflect changes in the inverse has-many array.
+
+        This hook passes the class being set up, as well as the key and value
+        being defined. So, for example, when the user does this:
+
+        ```javascript
+        DS.Model.extend({
+          parent: DS.belongsTo('user')
+        });
+        ```
+
+        This hook would be called with &quot;parent&quot; as the key and the computed
+        property returned by `DS.belongsTo` as the value.
+
+        @method didDefineProperty
+        @param proto
+        @param key
+        @param value
+      */
+      didDefineProperty: function(proto, key, value) {
+        // Check if the value being set is a computed property.
+        if (value instanceof Ember.Descriptor) {
+
+          // If it is, get the metadata for the relationship. This is
+          // populated by the `DS.belongsTo` helper when it is creating
+          // the computed property.
+          var meta = value.meta();
+
+          if (meta.isRelationship &amp;&amp; meta.kind === 'belongsTo') {
+            Ember.addObserver(proto, key, null, 'belongsToDidChange');
+            Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange');
+          }
+
+          meta.parentType = proto.constructor;
+        }
+      }
+    });
+
+    /*
+      These DS.Model extensions add class methods that provide relationship
+      introspection abilities about relationships.
+
+      A note about the computed properties contained here:
+
+      **These properties are effectively sealed once called for the first time.**
+      To avoid repeatedly doing expensive iteration over a model's fields, these
+      values are computed once and then cached for the remainder of the runtime of
+      your application.
+
+      If your application needs to modify a class after its initial definition
+      (for example, using `reopen()` to add additional attributes), make sure you
+      do it before using your model with the store, which uses these properties
+      extensively.
+    */
+
+    Model.reopenClass({
+      /**
+        For a given relationship name, returns the model type of the relationship.
+
+        For example, if you define a model like this:
+
+       ```javascript
+        App.Post = DS.Model.extend({
+          comments: DS.hasMany('comment')
+        });
+       ```
+
+        Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`.
+
+        @method typeForRelationship
+        @static
+        @param {String} name the name of the relationship
+        @return {subclass of DS.Model} the type of the relationship, or undefined
+      */
+      typeForRelationship: function(name) {
+        var relationship = get(this, 'relationshipsByName').get(name);
+        return relationship &amp;&amp; relationship.type;
+      },
+
+      inverseFor: function(name) {
+        var inverseType = this.typeForRelationship(name);
+
+        if (!inverseType) { return null; }
+
+        var options = this.metaForProperty(name).options;
+
+        if (options.inverse === null) { return null; }
+
+        var inverseName, inverseKind;
+
+        if (options.inverse) {
+          inverseName = options.inverse;
+          inverseKind = Ember.get(inverseType, 'relationshipsByName').get(inverseName).kind;
+        } else {
+          var possibleRelationships = findPossibleInverses(this, inverseType);
+
+          if (possibleRelationships.length === 0) { return null; }
+
+          Ember.assert(&quot;You defined the '&quot; + name + &quot;' relationship on &quot; + this + &quot;, but multiple possible inverse relationships of type &quot; + this + &quot; were found on &quot; + inverseType + &quot;. Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses&quot;, possibleRelationships.length === 1);
+
+          inverseName = possibleRelationships[0].name;
+          inverseKind = possibleRelationships[0].kind;
+        }
+
+        function findPossibleInverses(type, inverseType, possibleRelationships) {
+          possibleRelationships = possibleRelationships || [];
+
+          var relationshipMap = get(inverseType, 'relationships');
+          if (!relationshipMap) { return; }
+
+          var relationships = relationshipMap.get(type);
+          if (relationships) {
+            possibleRelationships.push.apply(possibleRelationships, relationshipMap.get(type));
+          }
+
+          if (type.superclass) {
+            findPossibleInverses(type.superclass, inverseType, possibleRelationships);
+          }
+
+          return possibleRelationships;
+        }
+
+        return {
+          type: inverseType,
+          name: inverseName,
+          kind: inverseKind
+        };
+      },
+
+      /**
+        The model's relationships as a map, keyed on the type of the
+        relationship. The value of each entry is an array containing a descriptor
+        for each relationship with that type, describing the name of the relationship
+        as well as the type.
+
+        For example, given the following model definition:
+
+        ```javascript
+        App.Blog = DS.Model.extend({
+          users: DS.hasMany('user'),
+          owner: DS.belongsTo('user'),
+          posts: DS.hasMany('post')
+        });
+        ```
+
+        This computed property would return a map describing these
+        relationships, like this:
+
+        ```javascript
+        var relationships = Ember.get(App.Blog, 'relationships');
+        relationships.get(App.User);
+        //=&gt; [ { name: 'users', kind: 'hasMany' },
+        //     { name: 'owner', kind: 'belongsTo' } ]
+        relationships.get(App.Post);
+        //=&gt; [ { name: 'posts', kind: 'hasMany' } ]
+        ```
+
+        @property relationships
+        @static
+        @type Ember.Map
+        @readOnly
+      */
+      relationships: Ember.computed(function() {
+        var map = new Ember.MapWithDefault({
+          defaultValue: function() { return []; }
+        });
+
+        // Loop through each computed property on the class
+        this.eachComputedProperty(function(name, meta) {
+
+          // If the computed property is a relationship, add
+          // it to the map.
+          if (meta.isRelationship) {
+            meta.key = name;
+            var relationshipsForType = map.get(typeForRelationshipMeta(this.store, meta));
+
+            relationshipsForType.push({ name: name, kind: meta.kind });
+          }
+        });
+
+        return map;
+      }).cacheable(false),
+
+      /**
+        A hash containing lists of the model's relationships, grouped
+        by the relationship kind. For example, given a model with this
+        definition:
+
+        ```javascript
+        App.Blog = DS.Model.extend({
+          users: DS.hasMany('user'),
+          owner: DS.belongsTo('user'),
+
+          posts: DS.hasMany('post')
+        });
+        ```
+
+        This property would contain the following:
+
+        ```javascript
+        var relationshipNames = Ember.get(App.Blog, 'relationshipNames');
+        relationshipNames.hasMany;
+        //=&gt; ['users', 'posts']
+        relationshipNames.belongsTo;
+        //=&gt; ['owner']
+        ```
+
+        @property relationshipNames
+        @static
+        @type Object
+        @readOnly
+      */
+      relationshipNames: Ember.computed(function() {
+        var names = { hasMany: [], belongsTo: [] };
+
+        this.eachComputedProperty(function(name, meta) {
+          if (meta.isRelationship) {
+            names[meta.kind].push(name);
+          }
+        });
+
+        return names;
+      }),
+
+      /**
+        An array of types directly related to a model. Each type will be
+        included once, regardless of the number of relationships it has with
+        the model.
+
+        For example, given a model with this definition:
+
+        ```javascript
+        App.Blog = DS.Model.extend({
+          users: DS.hasMany('user'),
+          owner: DS.belongsTo('user'),
+
+          posts: DS.hasMany('post')
+        });
+        ```
+
+        This property would contain the following:
+
+        ```javascript
+        var relatedTypes = Ember.get(App.Blog, 'relatedTypes');
+        //=&gt; [ App.User, App.Post ]
+        ```
+
+        @property relatedTypes
+        @static
+        @type Ember.Array
+        @readOnly
+      */
+      relatedTypes: Ember.computed(function() {
+        var type,
+            types = Ember.A();
+
+        // Loop through each computed property on the class,
+        // and create an array of the unique types involved
+        // in relationships
+        this.eachComputedProperty(function(name, meta) {
+          if (meta.isRelationship) {
+            meta.key = name;
+            type = typeForRelationshipMeta(this.store, meta);
+
+            Ember.assert(&quot;You specified a hasMany (&quot; + meta.type + &quot;) on &quot; + meta.parentType + &quot; but &quot; + meta.type + &quot; was not found.&quot;,  type);
+
+            if (!types.contains(type)) {
+              Ember.assert(&quot;Trying to sideload &quot; + name + &quot; on &quot; + this.toString() + &quot; but the type doesn't exist.&quot;, !!type);
+              types.push(type);
+            }
+          }
+        });
+
+        return types;
+      }).cacheable(false),
+
+      /**
+        A map whose keys are the relationships of a model and whose values are
+        relationship descriptors.
+
+        For example, given a model with this
+        definition:
+
+        ```javascript
+        App.Blog = DS.Model.extend({
+          users: DS.hasMany('user'),
+          owner: DS.belongsTo('user'),
+
+          posts: DS.hasMany('post')
+        });
+        ```
+
+        This property would contain the following:
+
+        ```javascript
+        var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName');
+        relationshipsByName.get('users');
+        //=&gt; { key: 'users', kind: 'hasMany', type: App.User }
+        relationshipsByName.get('owner');
+        //=&gt; { key: 'owner', kind: 'belongsTo', type: App.User }
+        ```
+
+        @property relationshipsByName
+        @static
+        @type Ember.Map
+        @readOnly
+      */
+      relationshipsByName: Ember.computed(function() {
+        var map = Ember.Map.create();
+
+        this.eachComputedProperty(function(name, meta) {
+          if (meta.isRelationship) {
+            meta.key = name;
+            var relationship = relationshipFromMeta(this.store, meta);
+            relationship.type = typeForRelationshipMeta(this.store, meta);
+            map.set(name, relationship);
+          }
+        });
+
+        return map;
+      }).cacheable(false),
+
+      /**
+        A map whose keys are the fields of the model and whose values are strings
+        describing the kind of the field. A model's fields are the union of all of its
+        attributes and relationships.
+
+        For example:
+
+        ```javascript
+
+        App.Blog = DS.Model.extend({
+          users: DS.hasMany('user'),
+          owner: DS.belongsTo('user'),
+
+          posts: DS.hasMany('post'),
+
+          title: DS.attr('string')
+        });
+
+        var fields = Ember.get(App.Blog, 'fields');
+        fields.forEach(function(field, kind) {
+          console.log(field, kind);
+        });
+
+        // prints:
+        // users, hasMany
+        // owner, belongsTo
+        // posts, hasMany
+        // title, attribute
+        ```
+
+        @property fields
+        @static
+        @type Ember.Map
+        @readOnly
+      */
+      fields: Ember.computed(function() {
+        var map = Ember.Map.create();
+
+        this.eachComputedProperty(function(name, meta) {
+          if (meta.isRelationship) {
+            map.set(name, meta.kind);
+          } else if (meta.isAttribute) {
+            map.set(name, 'attribute');
+          }
+        });
+
+        return map;
+      }),
+
+      /**
+        Given a callback, iterates over each of the relationships in the model,
+        invoking the callback with the name of each relationship and its relationship
+        descriptor.
+
+        @method eachRelationship
+        @static
+        @param {Function} callback the callback to invoke
+        @param {any} binding the value to which the callback's `this` should be bound
+      */
+      eachRelationship: function(callback, binding) {
+        get(this, 'relationshipsByName').forEach(function(name, relationship) {
+          callback.call(binding, name, relationship);
+        });
+      },
+
+      /**
+        Given a callback, iterates over each of the types related to a model,
+        invoking the callback with the related type's class. Each type will be
+        returned just once, regardless of how many different relationships it has
+        with a model.
+
+        @method eachRelatedType
+        @static
+        @param {Function} callback the callback to invoke
+        @param {any} binding the value to which the callback's `this` should be bound
+      */
+      eachRelatedType: function(callback, binding) {
+        get(this, 'relatedTypes').forEach(function(type) {
+          callback.call(binding, type);
+        });
+      }
+    });
+
+    Model.reopen({
+      /**
+        Given a callback, iterates over each of the relationships in the model,
+        invoking the callback with the name of each relationship and its relationship
+        descriptor.
+
+        @method eachRelationship
+        @param {Function} callback the callback to invoke
+        @param {any} binding the value to which the callback's `this` should be bound
+      */
+      eachRelationship: function(callback, binding) {
+        this.constructor.eachRelationship(callback, binding);
+      }
+    });
+  });
+define(&quot;ember-data/lib/system/relationships/has_many&quot;, 
+  [&quot;../store&quot;,&quot;../relationship-meta&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      @module ember-data
+    */
+
+    var PromiseArray = __dependency1__.PromiseArray;
+    var get = Ember.get, set = Ember.set, setProperties = Ember.setProperties;
+    var relationshipFromMeta = __dependency2__.relationshipFromMeta;
+    var typeForRelationshipMeta = __dependency2__.typeForRelationshipMeta;
+
+    function asyncHasMany(type, options, meta) {
+      return Ember.computed('data', function(key) {
+        var relationship = this._relationships[key],
+            promiseLabel = &quot;DS: Async hasMany &quot; + this + &quot; : &quot; + key;
+
+        meta.key = key;
+
+        if (!relationship) {
+          var resolver = Ember.RSVP.defer(promiseLabel);
+          relationship = buildRelationship(this, key, options, function(store, data) {
+            var link = data.links &amp;&amp; data.links[key];
+            var rel;
+            if (link) {
+              rel = store.findHasMany(this, link, relationshipFromMeta(store, meta), resolver);
+            } else {
+              rel = store.findMany(this, data[key], typeForRelationshipMeta(store, meta), resolver);
+            }
+            // cache the promise so we can use it
+            // when we come back and don't need to rebuild
+            // the relationship.
+            set(rel, 'promise', resolver.promise);
+            return rel;
+          });
+        }
+
+        var promise = relationship.get('promise').then(function() {
+          return relationship;
+        }, null, &quot;DS: Async hasMany records received&quot;);
+
+        return PromiseArray.create({
+          promise: promise
+        });
+      }).meta(meta).readOnly();
+    }
+
+    function buildRelationship(record, key, options, callback) {
+      var rels = record._relationships;
+
+      if (rels[key]) { return rels[key]; }
+
+      var data = get(record, 'data'),
+          store = get(record, 'store');
+
+      var relationship = rels[key] = callback.call(record, store, data);
+
+      return setProperties(relationship, {
+        owner: record,
+        name: key,
+        isPolymorphic: options.polymorphic
+      });
+    }
+
+    function hasRelationship(type, options) {
+      options = options || {};
+
+      var meta = {
+        type: type,
+        isRelationship: true,
+        options: options,
+        kind: 'hasMany',
+        key: null
+      };
+
+      if (options.async) {
+        return asyncHasMany(type, options, meta);
+      }
+
+      return Ember.computed('data', function(key) {
+        return buildRelationship(this, key, options, function(store, data) {
+          var records = data[key];
+          Ember.assert(&quot;You looked up the '&quot; + key + &quot;' relationship on '&quot; + this + &quot;' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`)&quot;, Ember.A(records).everyProperty('isEmpty', false));
+          return store.findMany(this, data[key], typeForRelationshipMeta(store, meta));
+        });
+      }).meta(meta).readOnly();
+    }
+
+    /**
+      `DS.hasMany` is used to define One-To-Many and Many-To-Many
+      relationships on a [DS.Model](/api/data/classes/DS.Model.html).
+
+      `DS.hasMany` takes an optional hash as a second parameter, currently
+      supported options are:
+
+      - `async`: A boolean value used to explicitly declare this to be an async relationship.
+      - `inverse`: A string used to identify the inverse property on a related model.
+
+      #### One-To-Many
+      To declare a one-to-many relationship between two models, use
+      `DS.belongsTo` in combination with `DS.hasMany`, like this:
+
+      ```javascript
+      App.Post = DS.Model.extend({
+        comments: DS.hasMany('comment')
+      });
+
+      App.Comment = DS.Model.extend({
+        post: DS.belongsTo('post')
+      });
+      ```
+
+      #### Many-To-Many
+      To declare a many-to-many relationship between two models, use
+      `DS.hasMany`:
+
+      ```javascript
+      App.Post = DS.Model.extend({
+        tags: DS.hasMany('tag')
+      });
+
+      App.Tag = DS.Model.extend({
+        posts: DS.hasMany('post')
+      });
+      ```
+
+      #### Explicit Inverses
+
+      Ember Data will do its best to discover which relationships map to
+      one another. In the one-to-many code above, for example, Ember Data
+      can figure out that changing the `comments` relationship should update
+      the `post` relationship on the inverse because post is the only
+      relationship to that model.
+
+      However, sometimes you may have multiple `belongsTo`/`hasManys` for the
+      same type. You can specify which property on the related model is
+      the inverse using `DS.hasMany`'s `inverse` option:
+
+      ```javascript
+      var belongsTo = DS.belongsTo,
+          hasMany = DS.hasMany;
+
+      App.Comment = DS.Model.extend({
+        onePost: belongsTo('post'),
+        twoPost: belongsTo('post'),
+        redPost: belongsTo('post'),
+        bluePost: belongsTo('post')
+      });
+
+      App.Post = DS.Model.extend({
+        comments: hasMany('comment', {
+          inverse: 'redPost'
+        })
+      });
+      ```
+
+      You can also specify an inverse on a `belongsTo`, which works how
+      you'd expect.
+
+      @namespace
+      @method hasMany
+      @for DS
+      @param {String or DS.Model} type the model type of the relationship
+      @param {Object} options a hash of options
+      @return {Ember.computed} relationship
+    */
+    function hasMany(type, options) {
+      if (typeof type === 'object') {
+        options = type;
+        type = undefined;
+      }
+      return hasRelationship(type, options);
+    }
+
+    __exports__[&quot;default&quot;] = hasMany;
+  });
+define(&quot;ember-data/lib/system/store&quot;, 
+  [&quot;./adapter&quot;,&quot;ember-inflector/lib/system/string&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    /*globals Ember*/
+    /*jshint eqnull:true*/
+
+    /**
+      @module ember-data
+    */
+
+    var InvalidError = __dependency1__.InvalidError;
+    var Adapter = __dependency1__.Adapter;
+    var singularize = __dependency2__.singularize;
+    var get = Ember.get, set = Ember.set;
+    var once = Ember.run.once;
+    var isNone = Ember.isNone;
+    var forEach = Ember.EnumerableUtils.forEach;
+    var indexOf = Ember.EnumerableUtils.indexOf;
+    var map = Ember.EnumerableUtils.map;
+    var Promise = Ember.RSVP.Promise;
+    var copy = Ember.copy;
+    var Store, PromiseObject, PromiseArray, RecordArrayManager, Model;
+
+    var camelize = Ember.String.camelize;
+
+    // Implementors Note:
+    //
+    //   The variables in this file are consistently named according to the following
+    //   scheme:
+    //
+    //   * +id+ means an identifier managed by an external source, provided inside
+    //     the data provided by that source. These are always coerced to be strings
+    //     before being used internally.
+    //   * +clientId+ means a transient numerical identifier generated at runtime by
+    //     the data store. It is important primarily because newly created objects may
+    //     not yet have an externally generated id.
+    //   * +reference+ means a record reference object, which holds metadata about a
+    //     record, even if it has not yet been fully materialized.
+    //   * +type+ means a subclass of DS.Model.
+
+    // Used by the store to normalize IDs entering the store.  Despite the fact
+    // that developers may provide IDs as numbers (e.g., `store.find(Person, 1)`),
+    // it is important that internally we use strings, since IDs may be serialized
+    // and lose type information.  For example, Ember's router may put a record's
+    // ID into the URL, and if we later try to deserialize that URL and find the
+    // corresponding record, we will not know if it is a string or a number.
+    function coerceId(id) {
+      return id == null ? null : id+'';
+    }
+
+    /**
+      The store contains all of the data for records loaded from the server.
+      It is also responsible for creating instances of `DS.Model` that wrap
+      the individual data for a record, so that they can be bound to in your
+      Handlebars templates.
+
+      Define your application's store like this:
+
+      ```javascript
+      MyApp.Store = DS.Store.extend();
+      ```
+
+      Most Ember.js applications will only have a single `DS.Store` that is
+      automatically created by their `Ember.Application`.
+
+      You can retrieve models from the store in several ways. To retrieve a record
+      for a specific id, use `DS.Store`'s `find()` method:
+
+      ```javascript
+      var person = store.find('person', 123);
+      ```
+
+      If your application has multiple `DS.Store` instances (an unusual case), you can
+      specify which store should be used:
+
+      ```javascript
+      var person = store.find('person', 123);
+      ```
+
+      By default, the store will talk to your backend using a standard
+      REST mechanism. You can customize how the store talks to your
+      backend by specifying a custom adapter:
+
+      ```javascript
+       MyApp.store = DS.Store.create({
+         adapter: 'MyApp.CustomAdapter'
+       });
+       ```
+
+      You can learn more about writing a custom adapter by reading the `DS.Adapter`
+      documentation.
+
+      ### Store createRecord() vs. push() vs. pushPayload() vs. update()
+
+      The store provides multiple ways to create new records object. They have
+      some subtle differences in their use which are detailed below:
+
+      [createRecord](#method_createRecord) is used for creating new
+      records on the client side. This will return a new record in the
+      `created.uncommitted` state. In order to persist this record to the
+      backend you will need to call `record.save()`.
+
+      [push](#method_push) is used to notify Ember Data's store of new or
+      updated records that exist in the backend. This will return a record
+      in the `loaded.saved` state. The primary use-case for `store#push` is
+      to notify Ember Data about record updates that happen
+      outside of the normal adapter methods (for example
+      [SSE](http://dev.w3.org/html5/eventsource/) or [Web
+      Sockets](http://www.w3.org/TR/2009/WD-websockets-20091222/)).
+
+      [pushPayload](#method_pushPayload) is a convenience wrapper for
+      `store#push` that will deserialize payloads if the
+      Serializer implements a `pushPayload` method.
+
+      [update](#method_update) works like `push`, except it can handle
+      partial attributes without overwriting the existing record
+      properties.
+
+      Note: When creating a new record using any of the above methods
+      Ember Data will update `DS.RecordArray`s such as those returned by
+      `store#all()`, `store#findAll()` or `store#filter()`. This means any
+      data bindings or computed properties that depend on the RecordArray
+      will automatically be synced to include the new or updated record
+      values.
+
+      @class Store
+      @namespace DS
+      @extends Ember.Object
+    */
+    Store = Ember.Object.extend({
+
+      /**
+        @method init
+        @private
+      */
+      init: function() {
+        // internal bookkeeping; not observable
+        if (!RecordArrayManager) { RecordArrayManager = requireModule(&quot;ember-data/lib/system/record_array_manager&quot;)[&quot;default&quot;]; }
+        this.typeMaps = {};
+        this.recordArrayManager = RecordArrayManager.create({
+          store: this
+        });
+        this._relationshipChanges = {};
+        this._pendingSave = [];
+      },
+
+      /**
+        The adapter to use to communicate to a backend server or other persistence layer.
+
+        This can be specified as an instance, class, or string.
+
+        If you want to specify `App.CustomAdapter` as a string, do:
+
+        ```js
+        adapter: 'custom'
+        ```
+
+        @property adapter
+        @default DS.RESTAdapter
+        @type {DS.Adapter|String}
+      */
+      adapter: '-rest',
+
+      /**
+        Returns a JSON representation of the record using a custom
+        type-specific serializer, if one exists.
+
+        The available options are:
+
+        * `includeId`: `true` if the record's ID should be included in
+          the JSON representation
+
+        @method serialize
+        @private
+        @param {DS.Model} record the record to serialize
+        @param {Object} options an options hash
+      */
+      serialize: function(record, options) {
+        return this.serializerFor(record.constructor.typeKey).serialize(record, options);
+      },
+
+      /**
+        This property returns the adapter, after resolving a possible
+        string key.
+
+        If the supplied `adapter` was a class, or a String property
+        path resolved to a class, this property will instantiate the
+        class.
+
+        This property is cacheable, so the same instance of a specified
+        adapter class should be used for the lifetime of the store.
+
+        @property defaultAdapter
+        @private
+        @return DS.Adapter
+      */
+      defaultAdapter: Ember.computed('adapter', function() {
+        var adapter = get(this, 'adapter');
+
+        Ember.assert('You tried to set `adapter` property to an instance of `DS.Adapter`, where it should be a name or a factory', !(adapter instanceof Adapter));
+
+        if (typeof adapter === 'string') {
+          adapter = this.container.lookup('adapter:' + adapter) || this.container.lookup('adapter:application') || this.container.lookup('adapter:-rest');
+        }
+
+        if (DS.Adapter.detect(adapter)) {
+          adapter = adapter.create({
+            container: this.container
+          });
+        }
+
+        return adapter;
+      }),
+
+      // .....................
+      // . CREATE NEW RECORD .
+      // .....................
+
+      /**
+        Create a new record in the current store. The properties passed
+        to this method are set on the newly created record.
+
+        To create a new instance of `App.Post`:
+
+        ```js
+        store.createRecord('post', {
+          title: &quot;Rails is omakase&quot;
+        });
+        ```
+
+        @method createRecord
+        @param {String} type
+        @param {Object} properties a hash of properties to set on the
+          newly created record.
+        @return {DS.Model} record
+      */
+      createRecord: function(type, properties) {
+        type = this.modelFor(type);
+
+        properties = copy(properties) || {};
+
+        // If the passed properties do not include a primary key,
+        // give the adapter an opportunity to generate one. Typically,
+        // client-side ID generators will use something like uuid.js
+        // to avoid conflicts.
+
+        if (isNone(properties.id)) {
+          properties.id = this._generateId(type);
+        }
+
+        // Coerce ID to a string
+        properties.id = coerceId(properties.id);
+
+        var record = this.buildRecord(type, properties.id);
+
+        // Move the record out of its initial `empty` state into
+        // the `loaded` state.
+        record.loadedData();
+
+        // Set the properties specified on the record.
+        record.setProperties(properties);
+
+        return record;
+      },
+
+      /**
+        If possible, this method asks the adapter to generate an ID for
+        a newly created record.
+
+        @method _generateId
+        @private
+        @param {String} type
+        @return {String} if the adapter can generate one, an ID
+      */
+      _generateId: function(type) {
+        var adapter = this.adapterFor(type);
+
+        if (adapter &amp;&amp; adapter.generateIdForRecord) {
+          return adapter.generateIdForRecord(this);
+        }
+
+        return null;
+      },
+
+      // .................
+      // . DELETE RECORD .
+      // .................
+
+      /**
+        For symmetry, a record can be deleted via the store.
+
+        Example
+
+        ```javascript
+        var post = store.createRecord('post', {
+          title: &quot;Rails is omakase&quot;
+        });
+
+        store.deleteRecord(post);
+        ```
+
+        @method deleteRecord
+        @param {DS.Model} record
+      */
+      deleteRecord: function(record) {
+        record.deleteRecord();
+      },
+
+      /**
+        For symmetry, a record can be unloaded via the store. Only
+        non-dirty records can be unloaded.
+
+        Example
+
+        ```javascript
+        store.find('post', 1).then(function(post) {
+          store.unloadRecord(post);
+        });
+        ```
+
+        @method unloadRecord
+        @param {DS.Model} record
+      */
+      unloadRecord: function(record) {
+        record.unloadRecord();
+      },
+
+      // ................
+      // . FIND RECORDS .
+      // ................
+
+      /**
+        This is the main entry point into finding records. The first parameter to
+        this method is the model's name as a string.
+
+        ---
+
+        To find a record by ID, pass the `id` as the second parameter:
+
+        ```javascript
+        store.find('person', 1);
+        ```
+
+        The `find` method will always return a **promise** that will be resolved
+        with the record. If the record was already in the store, the promise will
+        be resolved immediately. Otherwise, the store will ask the adapter's `find`
+        method to find the necessary data.
+
+        The `find` method will always resolve its promise with the same object for
+        a given type and `id`.
+
+        ---
+
+        To find all records for a type, call `find` with no additional parameters:
+
+        ```javascript
+        store.find('person');
+        ```
+
+        This will ask the adapter's `findAll` method to find the records for the
+        given type, and return a promise that will be resolved once the server
+        returns the values.
+
+        ---
+
+        To find a record by a query, call `find` with a hash as the second
+        parameter:
+
+        ```javascript
+        store.find('person', { page: 1 });
+        ```
+
+        This will ask the adapter's `findQuery` method to find the records for
+        the query, and return a promise that will be resolved once the server
+        responds.
+
+        @method find
+        @param {String or subclass of DS.Model} type
+        @param {Object|String|Integer|null} id
+        @return {Promise} promise
+      */
+      find: function(type, id) {
+        Ember.assert(&quot;You need to pass a type to the store's find method&quot;, arguments.length &gt;= 1);
+        Ember.assert(&quot;You may not pass `&quot; + id + &quot;` as id to the store's find method&quot;, arguments.length === 1 || !Ember.isNone(id));
+
+        if (arguments.length === 1) {
+          return this.findAll(type);
+        }
+
+        // We are passed a query instead of an id.
+        if (Ember.typeOf(id) === 'object') {
+          return this.findQuery(type, id);
+        }
+
+        return this.findById(type, coerceId(id));
+      },
+
+      /**
+        This method returns a record for a given type and id combination.
+
+        @method findById
+        @private
+        @param {String or subclass of DS.Model} type
+        @param {String|Integer} id
+        @return {Promise} promise
+      */
+      findById: function(type, id) {
+        type = this.modelFor(type);
+
+        var record = this.recordForId(type, id);
+        var fetchedRecord = this.fetchRecord(record);
+
+        return promiseObject(fetchedRecord || record, &quot;DS: Store#findById &quot; + type + &quot; with id: &quot; + id);
+      },
+
+      /**
+        This method makes a series of requests to the adapter's `find` method
+        and returns a promise that resolves once they are all loaded.
+
+        @private
+        @method findByIds
+        @param {String} type
+        @param {Array} ids
+        @return {Promise} promise
+      */
+      findByIds: function(type, ids) {
+        var store = this;
+        var promiseLabel = &quot;DS: Store#findByIds &quot; + type;
+        return promiseArray(Ember.RSVP.all(map(ids, function(id) {
+          return store.findById(type, id);
+        })).then(Ember.A, null, &quot;DS: Store#findByIds of &quot; + type + &quot; complete&quot;));
+      },
+
+      /**
+        This method is called by `findById` if it discovers that a particular
+        type/id pair hasn't been loaded yet to kick off a request to the
+        adapter.
+
+        @method fetchRecord
+        @private
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      fetchRecord: function(record) {
+        if (isNone(record)) { return null; }
+        if (record._loadingPromise) { return record._loadingPromise; }
+        if (!get(record, 'isEmpty')) { return null; }
+
+        var type = record.constructor,
+            id = get(record, 'id');
+
+        var adapter = this.adapterFor(type);
+
+        Ember.assert(&quot;You tried to find a record but you have no adapter (for &quot; + type + &quot;)&quot;, adapter);
+        Ember.assert(&quot;You tried to find a record but your adapter (for &quot; + type + &quot;) does not implement 'find'&quot;, adapter.find);
+
+        var promise = _find(adapter, this, type, id);
+        record.loadingData(promise);
+        return promise;
+      },
+
+      /**
+        Get a record by a given type and ID without triggering a fetch.
+
+        This method will synchronously return the record if it's available.
+        Otherwise, it will return null.
+
+        ```js
+        var post = store.getById('post', 1);
+        ```
+
+        @method getById
+        @param {String or subclass of DS.Model} type
+        @param {String|Integer} id
+        @param {DS.Model} record
+      */
+      getById: function(type, id) {
+        if (this.hasRecordForId(type, id)) {
+          return this.recordForId(type, id);
+        } else {
+          return null;
+        }
+      },
+
+      /**
+        This method is called by the record's `reload` method.
+
+        This method calls the adapter's `find` method, which returns a promise. When
+        **that** promise resolves, `reloadRecord` will resolve the promise returned
+        by the record's `reload`.
+
+        @method reloadRecord
+        @private
+        @param {DS.Model} record
+        @return {Promise} promise
+      */
+      reloadRecord: function(record) {
+        var type = record.constructor,
+            adapter = this.adapterFor(type),
+            id = get(record, 'id');
+
+        Ember.assert(&quot;You cannot reload a record without an ID&quot;, id);
+        Ember.assert(&quot;You tried to reload a record but you have no adapter (for &quot; + type + &quot;)&quot;, adapter);
+        Ember.assert(&quot;You tried to reload a record but your adapter does not implement `find`&quot;, adapter.find);
+
+        return _find(adapter, this, type, id);
+      },
+
+      /**
+        This method takes a list of records, groups the records by type,
+        converts the records into IDs, and then invokes the adapter's `findMany`
+        method.
+
+        The records are grouped by type to invoke `findMany` on adapters
+        for each unique type in records.
+
+        It is used both by a brand new relationship (via the `findMany`
+        method) or when the data underlying an existing relationship
+        changes.
+
+        @method fetchMany
+        @private
+        @param {Array} records
+        @param {DS.Model} owner
+        @return {Promise} promise
+      */
+      fetchMany: function(records, owner) {
+        if (!records.length) {
+          return Ember.RSVP.resolve(records);
+        }
+
+        // Group By Type
+        var recordsByTypeMap = Ember.MapWithDefault.create({
+          defaultValue: function() { return Ember.A(); }
+        });
+
+        forEach(records, function(record) {
+          recordsByTypeMap.get(record.constructor).push(record);
+        });
+
+        var promises = [];
+
+        forEach(recordsByTypeMap, function(type, records) {
+          var ids = records.mapProperty('id'),
+              adapter = this.adapterFor(type);
+
+          Ember.assert(&quot;You tried to load many records but you have no adapter (for &quot; + type + &quot;)&quot;, adapter);
+          Ember.assert(&quot;You tried to load many records but your adapter does not implement `findMany`&quot;, adapter.findMany);
+
+          promises.push(_findMany(adapter, this, type, ids, owner));
+        }, this);
+
+        return Ember.RSVP.all(promises);
+      },
+
+      /**
+        Returns true if a record for a given type and ID is already loaded.
+
+        @method hasRecordForId
+        @param {String or subclass of DS.Model} type
+        @param {String|Integer} id
+        @return {Boolean}
+      */
+      hasRecordForId: function(type, id) {
+        id = coerceId(id);
+        type = this.modelFor(type);
+        return !!this.typeMapFor(type).idToRecord[id];
+      },
+
+      /**
+        Returns id record for a given type and ID. If one isn't already loaded,
+        it builds a new record and leaves it in the `empty` state.
+
+        @method recordForId
+        @private
+        @param {String or subclass of DS.Model} type
+        @param {String|Integer} id
+        @return {DS.Model} record
+      */
+      recordForId: function(type, id) {
+        type = this.modelFor(type);
+
+        id = coerceId(id);
+
+        var record = this.typeMapFor(type).idToRecord[id];
+
+        if (!record) {
+          record = this.buildRecord(type, id);
+        }
+
+        return record;
+      },
+
+      /**
+        @method findMany
+        @private
+        @param {DS.Model} owner
+        @param {Array} records
+        @param {String or subclass of DS.Model} type
+        @param {Resolver} resolver
+        @return {DS.ManyArray} records
+      */
+      findMany: function(owner, records, type, resolver) {
+        type = this.modelFor(type);
+
+        records = Ember.A(records);
+
+        var unloadedRecords = records.filterProperty('isEmpty', true),
+            manyArray = this.recordArrayManager.createManyArray(type, records);
+
+        forEach(unloadedRecords, function(record) {
+          record.loadingData();
+        });
+
+        manyArray.loadingRecordsCount = unloadedRecords.length;
+
+        if (unloadedRecords.length) {
+          forEach(unloadedRecords, function(record) {
+            this.recordArrayManager.registerWaitingRecordArray(record, manyArray);
+          }, this);
+
+          resolver.resolve(this.fetchMany(unloadedRecords, owner));
+        } else {
+          if (resolver) { resolver.resolve(); }
+          manyArray.set('isLoaded', true);
+          once(manyArray, 'trigger', 'didLoad');
+        }
+
+        return manyArray;
+      },
+
+      /**
+        If a relationship was originally populated by the adapter as a link
+        (as opposed to a list of IDs), this method is called when the
+        relationship is fetched.
+
+        The link (which is usually a URL) is passed through unchanged, so the
+        adapter can make whatever request it wants.
+
+        The usual use-case is for the server to register a URL as a link, and
+        then use that URL in the future to make a request for the relationship.
+
+        @method findHasMany
+        @private
+        @param {DS.Model} owner
+        @param {any} link
+        @param {String or subclass of DS.Model} type
+        @return {Promise} promise
+      */
+      findHasMany: function(owner, link, relationship, resolver) {
+        var adapter = this.adapterFor(owner.constructor);
+
+        Ember.assert(&quot;You tried to load a hasMany relationship but you have no adapter (for &quot; + owner.constructor + &quot;)&quot;, adapter);
+        Ember.assert(&quot;You tried to load a hasMany relationship from a specified `link` in the original payload but your adapter does not implement `findHasMany`&quot;, adapter.findHasMany);
+
+        var records = this.recordArrayManager.createManyArray(relationship.type, Ember.A([]));
+        resolver.resolve(_findHasMany(adapter, this, owner, link, relationship));
+        return records;
+      },
+
+      /**
+        @method findBelongsTo
+        @private
+        @param {DS.Model} owner
+        @param {any} link
+        @param {Relationship} relationship
+        @return {Promise} promise
+      */
+      findBelongsTo: function(owner, link, relationship) {
+        var adapter = this.adapterFor(owner.constructor);
+
+        Ember.assert(&quot;You tried to load a belongsTo relationship but you have no adapter (for &quot; + owner.constructor + &quot;)&quot;, adapter);
+        Ember.assert(&quot;You tried to load a belongsTo relationship from a specified `link` in the original payload but your adapter does not implement `findBelongsTo`&quot;, adapter.findBelongsTo);
+
+        return _findBelongsTo(adapter, this, owner, link, relationship);
+      },
+
+      /**
+        This method delegates a query to the adapter. This is the one place where
+        adapter-level semantics are exposed to the application.
+
+        Exposing queries this way seems preferable to creating an abstract query
+        language for all server-side queries, and then require all adapters to
+        implement them.
+
+        This method returns a promise, which is resolved with a `RecordArray`
+        once the server returns.
+
+        @method findQuery
+        @private
+        @param {String or subclass of DS.Model} type
+        @param {any} query an opaque query to be used by the adapter
+        @return {Promise} promise
+      */
+      findQuery: function(type, query) {
+        type = this.modelFor(type);
+
+        var array = this.recordArrayManager
+          .createAdapterPopulatedRecordArray(type, query);
+
+        var adapter = this.adapterFor(type);
+
+        Ember.assert(&quot;You tried to load a query but you have no adapter (for &quot; + type + &quot;)&quot;, adapter);
+        Ember.assert(&quot;You tried to load a query but your adapter does not implement `findQuery`&quot;, adapter.findQuery);
+
+        return promiseArray(_findQuery(adapter, this, type, query, array));
+      },
+
+      /**
+        This method returns an array of all records adapter can find.
+        It triggers the adapter's `findAll` method to give it an opportunity to populate
+        the array with records of that type.
+
+        @method findAll
+        @private
+        @param {String or subclass of DS.Model} type
+        @return {DS.AdapterPopulatedRecordArray}
+      */
+      findAll: function(type) {
+        type = this.modelFor(type);
+
+        return this.fetchAll(type, this.all(type));
+      },
+
+      /**
+        @method fetchAll
+        @private
+        @param {DS.Model} type
+        @param {DS.RecordArray} array
+        @return {Promise} promise
+      */
+      fetchAll: function(type, array) {
+        var adapter = this.adapterFor(type),
+            sinceToken = this.typeMapFor(type).metadata.since;
+
+        set(array, 'isUpdating', true);
+
+        Ember.assert(&quot;You tried to load all records but you have no adapter (for &quot; + type + &quot;)&quot;, adapter);
+        Ember.assert(&quot;You tried to load all records but your adapter does not implement `findAll`&quot;, adapter.findAll);
+
+        return promiseArray(_findAll(adapter, this, type, sinceToken));
+      },
+
+      /**
+        @method didUpdateAll
+        @param {DS.Model} type
+      */
+      didUpdateAll: function(type) {
+        var findAllCache = this.typeMapFor(type).findAllCache;
+        set(findAllCache, 'isUpdating', false);
+      },
+
+      /**
+        This method returns a filtered array that contains all of the known records
+        for a given type.
+
+        Note that because it's just a filter, it will have any locally
+        created records of the type.
+
+        Also note that multiple calls to `all` for a given type will always
+        return the same RecordArray.
+
+        Example
+
+        ```javascript
+        var localPosts = store.all('post');
+        ```
+
+        @method all
+        @param {String or subclass of DS.Model} type
+        @return {DS.RecordArray}
+      */
+      all: function(type) {
+        type = this.modelFor(type);
+
+        var typeMap = this.typeMapFor(type),
+            findAllCache = typeMap.findAllCache;
+
+        if (findAllCache) { return findAllCache; }
+
+        var array = this.recordArrayManager.createRecordArray(type);
+
+        typeMap.findAllCache = array;
+        return array;
+      },
+
+
+      /**
+        This method unloads all of the known records for a given type.
+
+        ```javascript
+        store.unloadAll('post');
+        ```
+
+        @method unloadAll
+        @param {String or subclass of DS.Model} type
+      */
+      unloadAll: function(type) {
+        var modelType = this.modelFor(type);
+        var typeMap = this.typeMapFor(modelType);
+        var records = typeMap.records.slice();
+        var record;
+
+        for (var i = 0; i &lt; records.length; i++) {
+          record = records[i];
+          record.unloadRecord();
+          record.destroy(); // maybe within unloadRecord
+        }
+
+        typeMap.findAllCache = null;
+      },
+
+      /**
+        Takes a type and filter function, and returns a live RecordArray that
+        remains up to date as new records are loaded into the store or created
+        locally.
+
+        The callback function takes a materialized record, and returns true
+        if the record should be included in the filter and false if it should
+        not.
+
+        The filter function is called once on all records for the type when
+        it is created, and then once on each newly loaded or created record.
+
+        If any of a record's properties change, or if it changes state, the
+        filter function will be invoked again to determine whether it should
+        still be in the array.
+
+        Optionally you can pass a query which will be triggered at first. The
+        results returned by the server could then appear in the filter if they
+        match the filter function.
+
+        Example
+
+        ```javascript
+        store.filter('post', {unread: true}, function(post) {
+          return post.get('unread');
+        }).then(function(unreadPosts) {
+          unreadPosts.get('length'); // 5
+          var unreadPost = unreadPosts.objectAt(0);
+          unreadPost.set('unread', false);
+          unreadPosts.get('length'); // 4
+        });
+        ```
+
+        @method filter
+        @param {String or subclass of DS.Model} type
+        @param {Object} query optional query
+        @param {Function} filter
+        @return {DS.PromiseArray}
+      */
+      filter: function(type, query, filter) {
+        var promise;
+        var length = arguments.length;
+        var array;
+        var hasQuery = length === 3;
+
+        // allow an optional server query
+        if (hasQuery) {
+          promise = this.findQuery(type, query);
+        } else if (arguments.length === 2) {
+          filter = query;
+        }
+
+        type = this.modelFor(type);
+
+        if (hasQuery) {
+          array = this.recordArrayManager.createFilteredRecordArray(type, filter, query);
+        } else {
+          array = this.recordArrayManager.createFilteredRecordArray(type, filter);
+        }
+
+        promise = promise || Promise.cast(array);
+
+
+        return promiseArray(promise.then(function() {
+          return array;
+        }, null, &quot;DS: Store#filter of &quot; + type));
+      },
+
+      /**
+        This method returns if a certain record is already loaded
+        in the store. Use this function to know beforehand if a find()
+        will result in a request or that it will be a cache hit.
+
+         Example
+
+        ```javascript
+        store.recordIsLoaded('post', 1); // false
+        store.find('post', 1).then(function() {
+          store.recordIsLoaded('post', 1); // true
+        });
+        ```
+
+        @method recordIsLoaded
+        @param {String or subclass of DS.Model} type
+        @param {string} id
+        @return {boolean}
+      */
+      recordIsLoaded: function(type, id) {
+        if (!this.hasRecordForId(type, id)) { return false; }
+        return !get(this.recordForId(type, id), 'isEmpty');
+      },
+
+      /**
+        This method returns the metadata for a specific type.
+
+        @method metadataFor
+        @param {String or subclass of DS.Model} type
+        @return {object}
+      */
+      metadataFor: function(type) {
+        type = this.modelFor(type);
+        return this.typeMapFor(type).metadata;
+      },
+
+      // ............
+      // . UPDATING .
+      // ............
+
+      /**
+        If the adapter updates attributes or acknowledges creation
+        or deletion, the record will notify the store to update its
+        membership in any filters.
+        To avoid thrashing, this method is invoked only once per
+
+        run loop per record.
+
+        @method dataWasUpdated
+        @private
+        @param {Class} type
+        @param {DS.Model} record
+      */
+      dataWasUpdated: function(type, record) {
+        this.recordArrayManager.recordDidChange(record);
+      },
+
+      // ..............
+      // . PERSISTING .
+      // ..............
+
+      /**
+        This method is called by `record.save`, and gets passed a
+        resolver for the promise that `record.save` returns.
+
+        It schedules saving to happen at the end of the run loop.
+
+        @method scheduleSave
+        @private
+        @param {DS.Model} record
+        @param {Resolver} resolver
+      */
+      scheduleSave: function(record, resolver) {
+        record.adapterWillCommit();
+        this._pendingSave.push([record, resolver]);
+        once(this, 'flushPendingSave');
+      },
+
+      /**
+        This method is called at the end of the run loop, and
+        flushes any records passed into `scheduleSave`
+
+        @method flushPendingSave
+        @private
+      */
+      flushPendingSave: function() {
+        var pending = this._pendingSave.slice();
+        this._pendingSave = [];
+
+        forEach(pending, function(tuple) {
+          var record = tuple[0], resolver = tuple[1],
+              adapter = this.adapterFor(record.constructor),
+              operation;
+
+          if (get(record, 'currentState.stateName') === 'root.deleted.saved') {
+            return resolver.resolve(record);
+          } else if (get(record, 'isNew')) {
+            operation = 'createRecord';
+          } else if (get(record, 'isDeleted')) {
+            operation = 'deleteRecord';
+          } else {
+            operation = 'updateRecord';
+          }
+
+          resolver.resolve(_commit(adapter, this, operation, record));
+        }, this);
+      },
+
+      /**
+        This method is called once the promise returned by an
+        adapter's `createRecord`, `updateRecord` or `deleteRecord`
+        is resolved.
+
+        If the data provides a server-generated ID, it will
+        update the record and the store's indexes.
+
+        @method didSaveRecord
+        @private
+        @param {DS.Model} record the in-flight record
+        @param {Object} data optional data (see above)
+      */
+      didSaveRecord: function(record, data) {
+        if (data) {
+          // normalize relationship IDs into records
+          data = normalizeRelationships(this, record.constructor, data, record);
+
+          this.updateId(record, data);
+        }
+
+        record.adapterDidCommit(data);
+      },
+
+      /**
+        This method is called once the promise returned by an
+        adapter's `createRecord`, `updateRecord` or `deleteRecord`
+        is rejected with a `DS.InvalidError`.
+
+        @method recordWasInvalid
+        @private
+        @param {DS.Model} record
+        @param {Object} errors
+      */
+      recordWasInvalid: function(record, errors) {
+        record.adapterDidInvalidate(errors);
+      },
+
+      /**
+        This method is called once the promise returned by an
+        adapter's `createRecord`, `updateRecord` or `deleteRecord`
+        is rejected (with anything other than a `DS.InvalidError`).
+
+        @method recordWasError
+        @private
+        @param {DS.Model} record
+      */
+      recordWasError: function(record) {
+        record.adapterDidError();
+      },
+
+      /**
+        When an adapter's `createRecord`, `updateRecord` or `deleteRecord`
+        resolves with data, this method extracts the ID from the supplied
+        data.
+
+        @method updateId
+        @private
+        @param {DS.Model} record
+        @param {Object} data
+      */
+      updateId: function(record, data) {
+        var oldId = get(record, 'id'),
+            id = coerceId(data.id);
+
+        Ember.assert(&quot;An adapter cannot assign a new id to a record that already has an id. &quot; + record + &quot; had id: &quot; + oldId + &quot; and you tried to update it with &quot; + id + &quot;. This likely happened because your server returned data in response to a find or update that had a different id than the one you sent.&quot;, oldId === null || id === oldId);
+
+        this.typeMapFor(record.constructor).idToRecord[id] = record;
+
+        set(record, 'id', id);
+      },
+
+      /**
+        Returns a map of IDs to client IDs for a given type.
+
+        @method typeMapFor
+        @private
+        @param type
+        @return {Object} typeMap
+      */
+      typeMapFor: function(type) {
+        var typeMaps = get(this, 'typeMaps'),
+            guid = Ember.guidFor(type),
+            typeMap;
+
+        typeMap = typeMaps[guid];
+
+        if (typeMap) { return typeMap; }
+
+        typeMap = {
+          idToRecord: {},
+          records: [],
+          metadata: {},
+          type: type
+        };
+
+        typeMaps[guid] = typeMap;
+
+        return typeMap;
+      },
+
+      // ................
+      // . LOADING DATA .
+      // ................
+
+      /**
+        This internal method is used by `push`.
+
+        @method _load
+        @private
+        @param {String or subclass of DS.Model} type
+        @param {Object} data
+        @param {Boolean} partial the data should be merged into
+          the existing data, not replace it.
+      */
+      _load: function(type, data, partial) {
+        var id = coerceId(data.id),
+            record = this.recordForId(type, id);
+
+        record.setupData(data, partial);
+        this.recordArrayManager.recordDidChange(record);
+
+        return record;
+      },
+
+      /**
+        Returns a model class for a particular key. Used by
+        methods that take a type key (like `find`, `createRecord`,
+        etc.)
+
+        @method modelFor
+        @param {String or subclass of DS.Model} key
+        @return {subclass of DS.Model}
+      */
+      modelFor: function(key) {
+        var factory;
+
+
+        if (typeof key === 'string') {
+          var normalizedKey = this.container.normalize('model:' + key);
+
+          factory = this.container.lookupFactory(normalizedKey);
+          if (!factory) { throw new Ember.Error(&quot;No model was found for '&quot; + key + &quot;'&quot;); }
+          factory.typeKey = this._normalizeTypeKey(normalizedKey.split(':', 2)[1]);
+        } else {
+          // A factory already supplied. Ensure it has a normalized key.
+          factory = key;
+          if (factory.typeKey) {
+            factory.typeKey = this._normalizeTypeKey(factory.typeKey);
+          }
+        }
+
+        factory.store = this;
+        return factory;
+      },
+
+      /**
+        Push some data for a given type into the store.
+
+        This method expects normalized data:
+
+        * The ID is a key named `id` (an ID is mandatory)
+        * The names of attributes are the ones you used in
+          your model's `DS.attr`s.
+        * Your relationships must be:
+          * represented as IDs or Arrays of IDs
+          * represented as model instances
+          * represented as URLs, under the `links` key
+
+        For this model:
+
+        ```js
+        App.Person = DS.Model.extend({
+          firstName: DS.attr(),
+          lastName: DS.attr(),
+
+          children: DS.hasMany('person')
+        });
+        ```
+
+        To represent the children as IDs:
+
+        ```js
+        {
+          id: 1,
+          firstName: &quot;Tom&quot;,
+          lastName: &quot;Dale&quot;,
+          children: [1, 2, 3]
+        }
+        ```
+
+        To represent the children relationship as a URL:
+
+        ```js
+        {
+          id: 1,
+          firstName: &quot;Tom&quot;,
+          lastName: &quot;Dale&quot;,
+          links: {
+            children: &quot;/people/1/children&quot;
+          }
+        }
+        ```
+
+        If you're streaming data or implementing an adapter,
+        make sure that you have converted the incoming data
+        into this form.
+
+        This method can be used both to push in brand new
+        records, as well as to update existing records.
+
+        @method push
+        @param {String or subclass of DS.Model} type
+        @param {Object} data
+        @return {DS.Model} the record that was created or
+          updated.
+      */
+      push: function(type, data, _partial) {
+        // _partial is an internal param used by `update`.
+        // If passed, it means that the data should be
+        // merged into the existing data, not replace it.
+
+        Ember.assert(&quot;You must include an `id` for &quot; + type + &quot; in a hash passed to `push`&quot;, data.id != null);
+
+        type = this.modelFor(type);
+
+        // normalize relationship IDs into records
+        data = normalizeRelationships(this, type, data);
+
+        this._load(type, data, _partial);
+
+        return this.recordForId(type, data.id);
+      },
+
+      /**
+        Push some raw data into the store.
+
+        This method can be used both to push in brand new
+        records, as well as to update existing records. You
+        can push in more than one type of object at once.
+        All objects should be in the format expected by the
+        serializer.
+
+        ```js
+        App.ApplicationSerializer = DS.ActiveModelSerializer;
+
+        var pushData = {
+          posts: [
+            {id: 1, post_title: &quot;Great post&quot;, comment_ids: [2]}
+          ],
+          comments: [
+            {id: 2, comment_body: &quot;Insightful comment&quot;}
+          ]
+        }
+
+        store.pushPayload(pushData);
+        ```
+
+        By default, the data will be deserialized using a default
+        serializer (the application serializer if it exists).
+
+        Alternativly, `pushPayload` will accept a model type which
+        will determine which serializer will process the payload.
+        However, the serializer itself (processing this data via
+        `normalizePayload`) will not know which model it is
+        deserializing.
+
+        ```js
+        App.ApplicationSerializer = DS.ActiveModelSerializer;
+        App.PostSerializer = DS.JSONSerializer;
+        store.pushPayload('comment', pushData); // Will use the ApplicationSerializer
+        store.pushPayload('post', pushData); // Will use the PostSerializer
+        ```
+
+        @method pushPayload
+        @param {String} type Optionally, a model used to determine which serializer will be used
+        @param {Object} payload
+      */
+      pushPayload: function (type, payload) {
+        var serializer;
+        if (!payload) {
+          payload = type;
+          serializer = defaultSerializer(this.container);
+          Ember.assert(&quot;You cannot use `store#pushPayload` without a type unless your default serializer defines `pushPayload`&quot;, serializer.pushPayload);
+        } else {
+          serializer = this.serializerFor(type);
+        }
+        serializer.pushPayload(this, payload);
+      },
+
+      /**
+        Update existing records in the store. Unlike [push](#method_push),
+        update will merge the new data properties with the existing
+        properties. This makes it safe to use with a subset of record
+        attributes. This method expects normalized data.
+
+        `update` is useful if you app broadcasts partial updates to
+        records.
+
+        ```js
+        App.Person = DS.Model.extend({
+          firstName: DS.attr('string'),
+          lastName: DS.attr('string')
+        });
+
+        store.get('person', 1).then(function(tom) {
+          tom.get('firstName'); // Tom
+          tom.get('lastName'); // Dale
+
+          var updateEvent = {id: 1, firstName: &quot;TomHuda&quot;};
+          store.update('person', updateEvent);
+
+          tom.get('firstName'); // TomHuda
+          tom.get('lastName'); // Dale
+        });
+        ```
+
+        @method update
+        @param {String} type
+        @param {Object} data
+        @return {DS.Model} the record that was updated.
+      */
+      update: function(type, data) {
+        Ember.assert(&quot;You must include an `id` for &quot; + type + &quot; in a hash passed to `update`&quot;, data.id != null);
+
+        return this.push(type, data, true);
+      },
+
+      /**
+        If you have an Array of normalized data to push,
+        you can call `pushMany` with the Array, and it will
+        call `push` repeatedly for you.
+
+        @method pushMany
+        @param {String or subclass of DS.Model} type
+        @param {Array} datas
+        @return {Array}
+      */
+      pushMany: function(type, datas) {
+        return map(datas, function(data) {
+          return this.push(type, data);
+        }, this);
+      },
+
+      /**
+        If you have some metadata to set for a type
+        you can call `metaForType`.
+
+        @method metaForType
+        @param {String or subclass of DS.Model} type
+        @param {Object} metadata
+      */
+      metaForType: function(type, metadata) {
+        type = this.modelFor(type);
+
+        Ember.merge(this.typeMapFor(type).metadata, metadata);
+      },
+
+      /**
+        Build a brand new record for a given type, ID, and
+        initial data.
+
+        @method buildRecord
+        @private
+        @param {subclass of DS.Model} type
+        @param {String} id
+        @param {Object} data
+        @return {DS.Model} record
+      */
+      buildRecord: function(type, id, data) {
+        var typeMap = this.typeMapFor(type),
+            idToRecord = typeMap.idToRecord;
+
+        Ember.assert('The id ' + id + ' has already been used with another record of type ' + type.toString() + '.', !id || !idToRecord[id]);
+        Ember.assert(&quot;`&quot; + Ember.inspect(type)+ &quot;` does not appear to be an ember-data model&quot;, (typeof type._create === 'function') );
+
+        // lookupFactory should really return an object that creates
+        // instances with the injections applied
+        var record = type._create({
+          id: id,
+          store: this,
+          container: this.container
+        });
+
+        if (data) {
+          record.setupData(data);
+        }
+
+        // if we're creating an item, this process will be done
+        // later, once the object has been persisted.
+        if (id) {
+          idToRecord[id] = record;
+        }
+
+        typeMap.records.push(record);
+
+        return record;
+      },
+
+      // ...............
+      // . DESTRUCTION .
+      // ...............
+
+      /**
+        When a record is destroyed, this un-indexes it and
+        removes it from any record arrays so it can be GCed.
+
+        @method dematerializeRecord
+        @private
+        @param {DS.Model} record
+      */
+      dematerializeRecord: function(record) {
+        var type = record.constructor,
+            typeMap = this.typeMapFor(type),
+            id = get(record, 'id');
+
+        record.updateRecordArrays();
+
+        if (id) {
+          delete typeMap.idToRecord[id];
+        }
+
+        var loc = indexOf(typeMap.records, record);
+        typeMap.records.splice(loc, 1);
+      },
+
+      // ........................
+      // . RELATIONSHIP CHANGES .
+      // ........................
+
+      addRelationshipChangeFor: function(childRecord, childKey, parentRecord, parentKey, change) {
+        var clientId = childRecord.clientId,
+            parentClientId = parentRecord ? parentRecord : parentRecord;
+        var key = childKey + parentKey;
+        var changes = this._relationshipChanges;
+        if (!(clientId in changes)) {
+          changes[clientId] = {};
+        }
+        if (!(parentClientId in changes[clientId])) {
+          changes[clientId][parentClientId] = {};
+        }
+        if (!(key in changes[clientId][parentClientId])) {
+          changes[clientId][parentClientId][key] = {};
+        }
+        changes[clientId][parentClientId][key][change.changeType] = change;
+      },
+
+      removeRelationshipChangeFor: function(clientRecord, childKey, parentRecord, parentKey, type) {
+        var clientId = clientRecord.clientId,
+            parentClientId = parentRecord ? parentRecord.clientId : parentRecord;
+        var changes = this._relationshipChanges;
+        var key = childKey + parentKey;
+        if (!(clientId in changes) || !(parentClientId in changes[clientId]) || !(key in changes[clientId][parentClientId])){
+          return;
+        }
+        delete changes[clientId][parentClientId][key][type];
+      },
+
+      relationshipChangePairsFor: function(record){
+        var toReturn = [];
+
+        if( !record ) { return toReturn; }
+
+        //TODO(Igor) What about the other side
+        var changesObject = this._relationshipChanges[record.clientId];
+        for (var objKey in changesObject){
+          if(changesObject.hasOwnProperty(objKey)){
+            for (var changeKey in changesObject[objKey]){
+              if(changesObject[objKey].hasOwnProperty(changeKey)){
+                toReturn.push(changesObject[objKey][changeKey]);
+              }
+            }
+          }
+        }
+        return toReturn;
+      },
+
+      // ......................
+      // . PER-TYPE ADAPTERS
+      // ......................
+
+      /**
+        Returns the adapter for a given type.
+
+        @method adapterFor
+        @private
+        @param {subclass of DS.Model} type
+        @return DS.Adapter
+      */
+      adapterFor: function(type) {
+        var container = this.container, adapter;
+
+        if (container) {
+          adapter = container.lookup('adapter:' + type.typeKey) || container.lookup('adapter:application');
+        }
+
+        return adapter || get(this, 'defaultAdapter');
+      },
+
+      // ..............................
+      // . RECORD CHANGE NOTIFICATION .
+      // ..............................
+
+      /**
+        Returns an instance of the serializer for a given type. For
+        example, `serializerFor('person')` will return an instance of
+        `App.PersonSerializer`.
+
+        If no `App.PersonSerializer` is found, this method will look
+        for an `App.ApplicationSerializer` (the default serializer for
+        your entire application).
+
+        If no `App.ApplicationSerializer` is found, it will fall back
+        to an instance of `DS.JSONSerializer`.
+
+        @method serializerFor
+        @private
+        @param {String} type the record to serialize
+        @return {DS.Serializer}
+      */
+      serializerFor: function(type) {
+        type = this.modelFor(type);
+        var adapter = this.adapterFor(type);
+
+        return serializerFor(this.container, type.typeKey, adapter &amp;&amp; adapter.defaultSerializer);
+      },
+
+      willDestroy: function() {
+        var typeMaps = this.typeMaps;
+        var keys = Ember.keys(typeMaps);
+        var store = this;
+
+        var types = map(keys, byType);
+
+        this.recordArrayManager.destroy();
+
+        forEach(types, this.unloadAll, this);
+
+        function byType(entry) {
+          return typeMaps[entry]['type'];
+        }
+
+      },
+
+      /**
+        All typeKeys are camelCase internally. Changing this function may
+        require changes to other normalization hooks (such as typeForRoot).
+
+        @method _normalizeTypeKey
+        @private
+        @param {String} type
+        @return {String} if the adapter can generate one, an ID
+      */
+      _normalizeTypeKey: function(key) {
+        return camelize(singularize(key));
+      }
+    });
+
+    function normalizeRelationships(store, type, data, record) {
+      type.eachRelationship(function(key, relationship) {
+        // A link (usually a URL) was already provided in
+        // normalized form
+        if (data.links &amp;&amp; data.links[key]) {
+          if (record &amp;&amp; relationship.options.async) { record._relationships[key] = null; }
+          return;
+        }
+
+        var kind = relationship.kind,
+            value = data[key];
+
+        if (value == null) { return; }
+
+        if (kind === 'belongsTo') {
+          deserializeRecordId(store, data, key, relationship, value);
+        } else if (kind === 'hasMany') {
+          deserializeRecordIds(store, data, key, relationship, value);
+          addUnsavedRecords(record, key, value);
+        }
+      });
+
+      return data;
+    }
+
+    function deserializeRecordId(store, data, key, relationship, id) {
+      if (!Model) { Model = requireModule(&quot;ember-data/lib/system/model&quot;)[&quot;Model&quot;]; }
+      if (isNone(id) || id instanceof Model) {
+        return;
+      }
+
+      var type;
+
+      if (typeof id === 'number' || typeof id === 'string') {
+        type = typeFor(relationship, key, data);
+        data[key] = store.recordForId(type, id);
+      } else if (typeof id === 'object') {
+        // polymorphic
+        data[key] = store.recordForId(id.type, id.id);
+      }
+    }
+
+    function typeFor(relationship, key, data) {
+      if (relationship.options.polymorphic) {
+        return data[key + &quot;Type&quot;];
+      } else {
+        return relationship.type;
+      }
+    }
+
+    function deserializeRecordIds(store, data, key, relationship, ids) {
+      for (var i=0, l=ids.length; i&lt;l; i++) {
+        deserializeRecordId(store, ids, i, relationship, ids[i]);
+      }
+    }
+
+    // If there are any unsaved records that are in a hasMany they won't be
+    // in the payload, so add them back in manually.
+    function addUnsavedRecords(record, key, data) {
+      if(record) {
+        Ember.A(data).pushObjects(record.get(key).filterBy('isNew'));
+      }
+    }
+
+    // Delegation to the adapter and promise management
+    /**
+      A `PromiseArray` is an object that acts like both an `Ember.Array`
+      and a promise. When the promise is resolved the resulting value
+      will be set to the `PromiseArray`'s `content` property. This makes
+      it easy to create data bindings with the `PromiseArray` that will be
+      updated when the promise resolves.
+
+      For more information see the [Ember.PromiseProxyMixin
+      documentation](/api/classes/Ember.PromiseProxyMixin.html).
+
+      Example
+
+      ```javascript
+      var promiseArray = DS.PromiseArray.create({
+        promise: $.getJSON('/some/remote/data.json')
+      });
+
+      promiseArray.get('length'); // 0
+
+      promiseArray.then(function() {
+        promiseArray.get('length'); // 100
+      });
+      ```
+
+      @class PromiseArray
+      @namespace DS
+      @extends Ember.ArrayProxy
+      @uses Ember.PromiseProxyMixin
+    */
+    PromiseArray = Ember.ArrayProxy.extend(Ember.PromiseProxyMixin);
+    /**
+      A `PromiseObject` is an object that acts like both an `Ember.Object`
+      and a promise. When the promise is resolved the the resulting value
+      will be set to the `PromiseObject`'s `content` property. This makes
+      it easy to create data bindings with the `PromiseObject` that will
+      be updated when the promise resolves.
+
+      For more information see the [Ember.PromiseProxyMixin
+      documentation](/api/classes/Ember.PromiseProxyMixin.html).
+
+      Example
+
+      ```javascript
+      var promiseObject = DS.PromiseObject.create({
+        promise: $.getJSON('/some/remote/data.json')
+      });
+
+      promiseObject.get('name'); // null
+
+      promiseObject.then(function() {
+        promiseObject.get('name'); // 'Tomster'
+      });
+      ```
+
+      @class PromiseObject
+      @namespace DS
+      @extends Ember.ObjectProxy
+      @uses Ember.PromiseProxyMixin
+    */
+    PromiseObject = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);
+
+    function promiseObject(promise, label) {
+      return PromiseObject.create({
+        promise: Promise.cast(promise, label)
+      });
+    }
+
+    function promiseArray(promise, label) {
+      return PromiseArray.create({
+        promise: Promise.cast(promise, label)
+      });
+    }
+
+    function isThenable(object) {
+      return object &amp;&amp; typeof object.then === 'function';
+    }
+
+    function serializerFor(container, type, defaultSerializer) {
+      return container.lookup('serializer:'+type) ||
+                     container.lookup('serializer:application') ||
+                     container.lookup('serializer:' + defaultSerializer) ||
+                     container.lookup('serializer:-default');
+    }
+
+    function defaultSerializer(container) {
+      return container.lookup('serializer:application') ||
+             container.lookup('serializer:-default');
+    }
+
+    function serializerForAdapter(adapter, type) {
+      var serializer = adapter.serializer,
+          defaultSerializer = adapter.defaultSerializer,
+          container = adapter.container;
+
+      if (container &amp;&amp; serializer === undefined) {
+        serializer = serializerFor(container, type.typeKey, defaultSerializer);
+      }
+
+      if (serializer === null || serializer === undefined) {
+        serializer = {
+          extract: function(store, type, payload) { return payload; }
+        };
+      }
+
+      return serializer;
+    }
+
+    function _find(adapter, store, type, id) {
+      var promise = adapter.find(store, type, id),
+          serializer = serializerForAdapter(adapter, type),
+          label = &quot;DS: Handle Adapter#find of &quot; + type + &quot; with id: &quot; + id;
+
+      return Promise.cast(promise, label).then(function(adapterPayload) {
+        Ember.assert(&quot;You made a request for a &quot; + type.typeKey + &quot; with id &quot; + id + &quot;, but the adapter's response did not have any data&quot;, adapterPayload);
+        var payload = serializer.extract(store, type, adapterPayload, id, 'find');
+
+        return store.push(type, payload);
+      }, function(error) {
+        var record = store.getById(type, id);
+        record.notFound();
+        throw error;
+      }, &quot;DS: Extract payload of '&quot; + type + &quot;'&quot;);
+    }
+
+    function _findMany(adapter, store, type, ids, owner) {
+      var promise = adapter.findMany(store, type, ids, owner),
+          serializer = serializerForAdapter(adapter, type),
+          label = &quot;DS: Handle Adapter#findMany of &quot; + type;
+
+      return Promise.cast(promise, label).then(function(adapterPayload) {
+        var payload = serializer.extract(store, type, adapterPayload, null, 'findMany');
+
+        Ember.assert(&quot;The response from a findMany must be an Array, not &quot; + Ember.inspect(payload), Ember.typeOf(payload) === 'array');
+
+        store.pushMany(type, payload);
+      }, null, &quot;DS: Extract payload of &quot; + type);
+    }
+
+    function _findHasMany(adapter, store, record, link, relationship) {
+      var promise = adapter.findHasMany(store, record, link, relationship),
+          serializer = serializerForAdapter(adapter, relationship.type),
+          label = &quot;DS: Handle Adapter#findHasMany of &quot; + record + &quot; : &quot; + relationship.type;
+
+      return Promise.cast(promise, label).then(function(adapterPayload) {
+        var payload = serializer.extract(store, relationship.type, adapterPayload, null, 'findHasMany');
+
+        Ember.assert(&quot;The response from a findHasMany must be an Array, not &quot; + Ember.inspect(payload), Ember.typeOf(payload) === 'array');
+
+        var records = store.pushMany(relationship.type, payload);
+        record.updateHasMany(relationship.key, records);
+      }, null, &quot;DS: Extract payload of &quot; + record + &quot; : hasMany &quot; + relationship.type);
+    }
+
+    function _findBelongsTo(adapter, store, record, link, relationship) {
+      var promise = adapter.findBelongsTo(store, record, link, relationship),
+          serializer = serializerForAdapter(adapter, relationship.type),
+          label = &quot;DS: Handle Adapter#findBelongsTo of &quot; + record + &quot; : &quot; + relationship.type;
+
+      return Promise.cast(promise, label).then(function(adapterPayload) {
+        var payload = serializer.extract(store, relationship.type, adapterPayload, null, 'findBelongsTo');
+        var record = store.push(relationship.type, payload);
+
+        record.updateBelongsTo(relationship.key, record);
+        return record;
+      }, null, &quot;DS: Extract payload of &quot; + record + &quot; : &quot; + relationship.type);
+    }
+
+    function _findAll(adapter, store, type, sinceToken) {
+      var promise = adapter.findAll(store, type, sinceToken),
+          serializer = serializerForAdapter(adapter, type),
+          label = &quot;DS: Handle Adapter#findAll of &quot; + type;
+
+      return Promise.cast(promise, label).then(function(adapterPayload) {
+        var payload = serializer.extract(store, type, adapterPayload, null, 'findAll');
+
+        Ember.assert(&quot;The response from a findAll must be an Array, not &quot; + Ember.inspect(payload), Ember.typeOf(payload) === 'array');
+
+        store.pushMany(type, payload);
+        store.didUpdateAll(type);
+        return store.all(type);
+      }, null, &quot;DS: Extract payload of findAll &quot; + type);
+    }
+
+    function _findQuery(adapter, store, type, query, recordArray) {
+      var promise = adapter.findQuery(store, type, query, recordArray),
+          serializer = serializerForAdapter(adapter, type),
+          label = &quot;DS: Handle Adapter#findQuery of &quot; + type;
+
+      return Promise.cast(promise, label).then(function(adapterPayload) {
+        var payload = serializer.extract(store, type, adapterPayload, null, 'findQuery');
+
+        Ember.assert(&quot;The response from a findQuery must be an Array, not &quot; + Ember.inspect(payload), Ember.typeOf(payload) === 'array');
+
+        recordArray.load(payload);
+        return recordArray;
+      }, null, &quot;DS: Extract payload of findQuery &quot; + type);
+    }
+
+    function _commit(adapter, store, operation, record) {
+      var type = record.constructor,
+          promise = adapter[operation](store, type, record),
+          serializer = serializerForAdapter(adapter, type),
+          label = &quot;DS: Extract and notify about &quot; + operation + &quot; completion of &quot; + record;
+
+      Ember.assert(&quot;Your adapter's '&quot; + operation + &quot;' method must return a promise, but it returned &quot; + promise, isThenable(promise));
+
+      return promise.then(function(adapterPayload) {
+        var payload;
+
+        if (adapterPayload) {
+          payload = serializer.extract(store, type, adapterPayload, get(record, 'id'), operation);
+        } else {
+          payload = adapterPayload;
+        }
+
+        store.didSaveRecord(record, payload);
+        return record;
+      }, function(reason) {
+        if (reason instanceof InvalidError) {
+          store.recordWasInvalid(record, reason.errors);
+        } else {
+          store.recordWasError(record, reason);
+        }
+
+        throw reason;
+      }, label);
+    }
+
+    __exports__.Store = Store;
+    __exports__.PromiseArray = PromiseArray;
+    __exports__.PromiseObject = PromiseObject;
+    __exports__[&quot;default&quot;] = Store;
+  });
+define(&quot;ember-data/lib/transforms&quot;, 
+  [&quot;./transforms/base&quot;,&quot;./transforms/number&quot;,&quot;./transforms/date&quot;,&quot;./transforms/string&quot;,&quot;./transforms/boolean&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+    &quot;use strict&quot;;
+    var Transform = __dependency1__[&quot;default&quot;];
+    var NumberTransform = __dependency2__[&quot;default&quot;];
+    var DateTransform = __dependency3__[&quot;default&quot;];
+    var StringTransform = __dependency4__[&quot;default&quot;];
+    var BooleanTransform = __dependency5__[&quot;default&quot;];
+
+    __exports__.Transform = Transform;
+    __exports__.NumberTransform = NumberTransform;
+    __exports__.DateTransform = DateTransform;
+    __exports__.StringTransform = StringTransform;
+    __exports__.BooleanTransform = BooleanTransform;
+  });
+define(&quot;ember-data/lib/transforms/base&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    /**
+      The `DS.Transform` class is used to serialize and deserialize model
+      attributes when they are saved or loaded from an
+      adapter. Subclassing `DS.Transform` is useful for creating custom
+      attributes. All subclasses of `DS.Transform` must implement a
+      `serialize` and a `deserialize` method.
+
+      Example
+
+      ```javascript
+      // Converts centigrade in the JSON to fahrenheit in the app
+      App.TemperatureTransform = DS.Transform.extend({
+        deserialize: function(serialized) {
+          return (serialized *  1.8) + 32;
+        },
+        serialize: function(deserialized) {
+          return (deserialized - 32) / 1.8;
+        }
+      });
+      ```
+
+      Usage
+
+      ```javascript
+      var attr = DS.attr;
+      App.Requirement = DS.Model.extend({
+        name: attr('string'),
+        optionsArray: attr('raw')
+      });
+      ```
+
+      @class Transform
+      @namespace DS
+     */
+    var Transform = Ember.Object.extend({
+      /**
+        When given a deserialized value from a record attribute this
+        method must return the serialized value.
+
+        Example
+
+        ```javascript
+        serialize: function(deserialized) {
+          return Ember.isEmpty(deserialized) ? null : Number(deserialized);
+        }
+        ```
+
+        @method serialize
+        @param deserialized The deserialized value
+        @return The serialized value
+      */
+      serialize: Ember.required(),
+
+      /**
+        When given a serialize value from a JSON object this method must
+        return the deserialized value for the record attribute.
+
+        Example
+
+        ```javascript
+        deserialize: function(serialized) {
+          return empty(serialized) ? null : Number(serialized);
+        }
+        ```
+
+        @method deserialize
+        @param serialized The serialized value
+        @return The deserialized value
+      */
+      deserialize: Ember.required()
+
+    });
+
+    __exports__[&quot;default&quot;] = Transform;
+  });
+define(&quot;ember-data/lib/transforms/boolean&quot;, 
+  [&quot;./base&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var Transform = __dependency1__[&quot;default&quot;];
+
+    /**
+      The `DS.BooleanTransform` class is used to serialize and deserialize
+      boolean attributes on Ember Data record objects. This transform is
+      used when `boolean` is passed as the type parameter to the
+      [DS.attr](../../data#method_attr) function.
+
+      Usage
+
+      ```javascript
+      var attr = DS.attr;
+      App.User = DS.Model.extend({
+        isAdmin: attr('boolean'),
+        name: attr('string'),
+        email: attr('string')
+      });
+      ```
+
+      @class BooleanTransform
+      @extends DS.Transform
+      @namespace DS
+     */
+    var BooleanTransform = Transform.extend({
+      deserialize: function(serialized) {
+        var type = typeof serialized;
+
+        if (type === &quot;boolean&quot;) {
+          return serialized;
+        } else if (type === &quot;string&quot;) {
+          return serialized.match(/^true$|^t$|^1$/i) !== null;
+        } else if (type === &quot;number&quot;) {
+          return serialized === 1;
+        } else {
+          return false;
+        }
+      },
+
+      serialize: function(deserialized) {
+        return Boolean(deserialized);
+      }
+    });
+    __exports__[&quot;default&quot;] = BooleanTransform;
+  });
+define(&quot;ember-data/lib/transforms/date&quot;, 
+  [&quot;./base&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    /**
+      The `DS.DateTransform` class is used to serialize and deserialize
+      date attributes on Ember Data record objects. This transform is used
+      when `date` is passed as the type parameter to the
+      [DS.attr](../../data#method_attr) function.
+
+      ```javascript
+      var attr = DS.attr;
+      App.Score = DS.Model.extend({
+        value: attr('number'),
+        player: DS.belongsTo('player'),
+        date: attr('date')
+      });
+      ```
+
+      @class DateTransform
+      @extends DS.Transform
+      @namespace DS
+     */
+    var Transform = __dependency1__[&quot;default&quot;];
+    var DateTransform = Transform.extend({
+
+      deserialize: function(serialized) {
+        var type = typeof serialized;
+
+        if (type === &quot;string&quot;) {
+          return new Date(Ember.Date.parse(serialized));
+        } else if (type === &quot;number&quot;) {
+          return new Date(serialized);
+        } else if (serialized === null || serialized === undefined) {
+          // if the value is not present in the data,
+          // return undefined, not null.
+          return serialized;
+        } else {
+          return null;
+        }
+      },
+
+      serialize: function(date) {
+        if (date instanceof Date) {
+          var days = [&quot;Sun&quot;, &quot;Mon&quot;, &quot;Tue&quot;, &quot;Wed&quot;, &quot;Thu&quot;, &quot;Fri&quot;, &quot;Sat&quot;];
+          var months = [&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, &quot;Apr&quot;, &quot;May&quot;, &quot;Jun&quot;, &quot;Jul&quot;, &quot;Aug&quot;, &quot;Sep&quot;, &quot;Oct&quot;, &quot;Nov&quot;, &quot;Dec&quot;];
+
+          var pad = function(num) {
+            return num &lt; 10 ? &quot;0&quot;+num : &quot;&quot;+num;
+          };
+
+          var utcYear = date.getUTCFullYear(),
+              utcMonth = date.getUTCMonth(),
+              utcDayOfMonth = date.getUTCDate(),
+              utcDay = date.getUTCDay(),
+              utcHours = date.getUTCHours(),
+              utcMinutes = date.getUTCMinutes(),
+              utcSeconds = date.getUTCSeconds();
+
+
+          var dayOfWeek = days[utcDay];
+          var dayOfMonth = pad(utcDayOfMonth);
+          var month = months[utcMonth];
+
+          return dayOfWeek + &quot;, &quot; + dayOfMonth + &quot; &quot; + month + &quot; &quot; + utcYear + &quot; &quot; +
+                 pad(utcHours) + &quot;:&quot; + pad(utcMinutes) + &quot;:&quot; + pad(utcSeconds) + &quot; GMT&quot;;
+        } else {
+          return null;
+        }
+      } 
+
+    });
+
+    __exports__[&quot;default&quot;] = DateTransform;
+  });
+define(&quot;ember-data/lib/transforms/number&quot;, 
+  [&quot;./base&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var Transform = __dependency1__[&quot;default&quot;];
+
+    var empty = Ember.isEmpty;
+
+    /**
+      The `DS.NumberTransform` class is used to serialize and deserialize
+      numeric attributes on Ember Data record objects. This transform is
+      used when `number` is passed as the type parameter to the
+      [DS.attr](../../data#method_attr) function.
+
+      Usage
+
+      ```javascript
+      var attr = DS.attr;
+      App.Score = DS.Model.extend({
+        value: attr('number'),
+        player: DS.belongsTo('player'),
+        date: attr('date')
+      });
+      ```
+
+      @class NumberTransform
+      @extends DS.Transform
+      @namespace DS
+     */
+    var NumberTransform = Transform.extend({
+
+      deserialize: function(serialized) {
+        return empty(serialized) ? null : Number(serialized);
+      },
+
+      serialize: function(deserialized) {
+        return empty(deserialized) ? null : Number(deserialized);
+      }
+    });
+
+    __exports__[&quot;default&quot;] = NumberTransform;
+  });
+define(&quot;ember-data/lib/transforms/string&quot;, 
+  [&quot;./base&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var Transform = __dependency1__[&quot;default&quot;];
+    var none = Ember.isNone;
+
+    /**
+      The `DS.StringTransform` class is used to serialize and deserialize
+      string attributes on Ember Data record objects. This transform is
+      used when `string` is passed as the type parameter to the
+      [DS.attr](../../data#method_attr) function.
+
+      Usage
+
+      ```javascript
+      var attr = DS.attr;
+      App.User = DS.Model.extend({
+        isAdmin: attr('boolean'),
+        name: attr('string'),
+        email: attr('string')
+      });
+      ```
+
+      @class StringTransform
+      @extends DS.Transform
+      @namespace DS
+     */
+    var StringTransform = Transform.extend({
+
+      deserialize: function(serialized) {
+        return none(serialized) ? null : String(serialized);
+      },
+
+      serialize: function(deserialized) {
+        return none(deserialized) ? null : String(deserialized);
+      }
+
+    });
+
+    __exports__[&quot;default&quot;] = StringTransform;
+  });
+define(&quot;ember-inflector/lib/ext/string&quot;, 
+  [&quot;../system/string&quot;],
+  function(__dependency1__) {
+    &quot;use strict&quot;;
+    var pluralize = __dependency1__.pluralize;
+    var singularize = __dependency1__.singularize;
+
+    if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
+      /**
+        See {{#crossLink &quot;Ember.String/pluralize&quot;}}{{/crossLink}}
+
+        @method pluralize
+        @for String
+      */
+      String.prototype.pluralize = function() {
+        return pluralize(this);
+      };
+
+      /**
+        See {{#crossLink &quot;Ember.String/singularize&quot;}}{{/crossLink}}
+
+        @method singularize
+        @for String
+      */
+      String.prototype.singularize = function() {
+        return singularize(this);
+      };
+    }
+  });
+define(&quot;ember-inflector/lib/main&quot;, 
+  [&quot;./system&quot;,&quot;./ext/string&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __exports__) {
+    &quot;use strict&quot;;
+    var Inflector = __dependency1__.Inflector;
+    var defaultRules = __dependency1__.defaultRules;
+    var pluralize = __dependency1__.pluralize;
+    var singularize = __dependency1__.singularize;
+
+    Inflector.defaultRules = defaultRules;
+    Ember.Inflector        = Inflector;
+
+    Ember.String.pluralize   = pluralize;
+    Ember.String.singularize = singularize;
+
+
+    __exports__[&quot;default&quot;] = Inflector;
+
+    __exports__.pluralize = pluralize;
+    __exports__.singularize = singularize;
+  });
+define(&quot;ember-inflector/lib/system&quot;, 
+  [&quot;./system/inflector&quot;,&quot;./system/string&quot;,&quot;./system/inflections&quot;,&quot;exports&quot;],
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+    &quot;use strict&quot;;
+    var Inflector = __dependency1__[&quot;default&quot;];
+
+    var pluralize = __dependency2__.pluralize;
+    var singularize = __dependency2__.singularize;
+
+    var defaultRules = __dependency3__[&quot;default&quot;];
+
+    
+    Inflector.inflector = new Inflector(defaultRules);
+    
+    __exports__.Inflector = Inflector;
+    __exports__.singularize = singularize;
+    __exports__.pluralize = pluralize;
+    __exports__.defaultRules = defaultRules;
+  });
+define(&quot;ember-inflector/lib/system/inflections&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    var defaultRules = {
+      plurals: [
+        [/$/, 's'],
+        [/s$/i, 's'],
+        [/^(ax|test)is$/i, '$1es'],
+        [/(octop|vir)us$/i, '$1i'],
+        [/(octop|vir)i$/i, '$1i'],
+        [/(alias|status)$/i, '$1es'],
+        [/(bu)s$/i, '$1ses'],
+        [/(buffal|tomat)o$/i, '$1oes'],
+        [/([ti])um$/i, '$1a'],
+        [/([ti])a$/i, '$1a'],
+        [/sis$/i, 'ses'],
+        [/(?:([^f])fe|([lr])f)$/i, '$1$2ves'],
+        [/(hive)$/i, '$1s'],
+        [/([^aeiouy]|qu)y$/i, '$1ies'],
+        [/(x|ch|ss|sh)$/i, '$1es'],
+        [/(matr|vert|ind)(?:ix|ex)$/i, '$1ices'],
+        [/^(m|l)ouse$/i, '$1ice'],
+        [/^(m|l)ice$/i, '$1ice'],
+        [/^(ox)$/i, '$1en'],
+        [/^(oxen)$/i, '$1'],
+        [/(quiz)$/i, '$1zes']
+      ],
+
+      singular: [
+        [/s$/i, ''],
+        [/(ss)$/i, '$1'],
+        [/(n)ews$/i, '$1ews'],
+        [/([ti])a$/i, '$1um'],
+        [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1sis'],
+        [/(^analy)(sis|ses)$/i, '$1sis'],
+        [/([^f])ves$/i, '$1fe'],
+        [/(hive)s$/i, '$1'],
+        [/(tive)s$/i, '$1'],
+        [/([lr])ves$/i, '$1f'],
+        [/([^aeiouy]|qu)ies$/i, '$1y'],
+        [/(s)eries$/i, '$1eries'],
+        [/(m)ovies$/i, '$1ovie'],
+        [/(x|ch|ss|sh)es$/i, '$1'],
+        [/^(m|l)ice$/i, '$1ouse'],
+        [/(bus)(es)?$/i, '$1'],
+        [/(o)es$/i, '$1'],
+        [/(shoe)s$/i, '$1'],
+        [/(cris|test)(is|es)$/i, '$1is'],
+        [/^(a)x[ie]s$/i, '$1xis'],
+        [/(octop|vir)(us|i)$/i, '$1us'],
+        [/(alias|status)(es)?$/i, '$1'],
+        [/^(ox)en/i, '$1'],
+        [/(vert|ind)ices$/i, '$1ex'],
+        [/(matr)ices$/i, '$1ix'],
+        [/(quiz)zes$/i, '$1'],
+        [/(database)s$/i, '$1']
+      ],
+
+      irregularPairs: [
+        ['person', 'people'],
+        ['man', 'men'],
+        ['child', 'children'],
+        ['sex', 'sexes'],
+        ['move', 'moves'],
+        ['cow', 'kine'],
+        ['zombie', 'zombies']
+      ],
+
+      uncountable: [
+        'equipment',
+        'information',
+        'rice',
+        'money',
+        'species',
+        'series',
+        'fish',
+        'sheep',
+        'jeans',
+        'police'
+      ]
+    };
+
+    __exports__[&quot;default&quot;] = defaultRules;
+  });
+define(&quot;ember-inflector/lib/system/inflector&quot;, 
+  [&quot;exports&quot;],
+  function(__exports__) {
+    &quot;use strict&quot;;
+    var BLANK_REGEX = /^\s*$/;
+
+    function loadUncountable(rules, uncountable) {
+      for (var i = 0, length = uncountable.length; i &lt; length; i++) {
+        rules.uncountable[uncountable[i].toLowerCase()] = true;
+      }
+    }
+
+    function loadIrregular(rules, irregularPairs) {
+      var pair;
+
+      for (var i = 0, length = irregularPairs.length; i &lt; length; i++) {
+        pair = irregularPairs[i];
+
+        rules.irregular[pair[0].toLowerCase()] = pair[1];
+        rules.irregularInverse[pair[1].toLowerCase()] = pair[0];
+      }
+    }
+
+    /**
+      Inflector.Ember provides a mechanism for supplying inflection rules for your
+      application. Ember includes a default set of inflection rules, and provides an
+      API for providing additional rules.
+
+      Examples:
+
+      Creating an inflector with no rules.
+
+      ```js
+      var inflector = new Ember.Inflector();
+      ```
+
+      Creating an inflector with the default ember ruleset.
+
+      ```js
+      var inflector = new Ember.Inflector(Ember.Inflector.defaultRules);
+
+      inflector.pluralize('cow'); //=&gt; 'kine'
+      inflector.singularize('kine'); //=&gt; 'cow'
+      ```
+
+      Creating an inflector and adding rules later.
+
+      ```javascript
+      var inflector = Ember.Inflector.inflector;
+
+      inflector.pluralize('advice'); // =&gt; 'advices'
+      inflector.uncountable('advice');
+      inflector.pluralize('advice'); // =&gt; 'advice'
+
+      inflector.pluralize('formula'); // =&gt; 'formulas'
+      inflector.irregular('formula', 'formulae');
+      inflector.pluralize('formula'); // =&gt; 'formulae'
+
+      // you would not need to add these as they are the default rules
+      inflector.plural(/$/, 's');
+      inflector.singular(/s$/i, '');
+      ```
+
+      Creating an inflector with a nondefault ruleset.
+
+      ```javascript
+      var rules = {
+        plurals:  [ /$/, 's' ],
+        singular: [ /\s$/, '' ],
+        irregularPairs: [
+          [ 'cow', 'kine' ]
+        ],
+        uncountable: [ 'fish' ]
+      };
+
+      var inflector = new Ember.Inflector(rules);
+      ```
+
+      @class Inflector
+      @namespace Ember
+    */
+    function Inflector(ruleSet) {
+      ruleSet = ruleSet || {};
+      ruleSet.uncountable = ruleSet.uncountable || {};
+      ruleSet.irregularPairs = ruleSet.irregularPairs || {};
+
+      var rules = this.rules = {
+        plurals:  ruleSet.plurals || [],
+        singular: ruleSet.singular || [],
+        irregular: {},
+        irregularInverse: {},
+        uncountable: {}
+      };
+
+      loadUncountable(rules, ruleSet.uncountable);
+      loadIrregular(rules, ruleSet.irregularPairs);
+    }
+
+    Inflector.prototype = {
+      /**
+        @method plural
+        @param {RegExp} regex
+        @param {String} string
+      */
+      plural: function(regex, string) {
+        this.rules.plurals.push([regex, string.toLowerCase()]);
+      },
+
+      /**
+        @method singular
+        @param {RegExp} regex
+        @param {String} string
+      */
+      singular: function(regex, string) {
+        this.rules.singular.push([regex, string.toLowerCase()]);
+      },
+
+      /**
+        @method uncountable
+        @param {String} regex
+      */
+      uncountable: function(string) {
+        loadUncountable(this.rules, [string.toLowerCase()]);
+      },
+
+      /**
+        @method irregular
+        @param {String} singular
+        @param {String} plural
+      */
+      irregular: function (singular, plural) {
+        loadIrregular(this.rules, [[singular, plural]]);
+      },
+
+      /**
+        @method pluralize
+        @param {String} word
+      */
+      pluralize: function(word) {
+        return this.inflect(word, this.rules.plurals, this.rules.irregular);
+      },
+
+      /**
+        @method singularize
+        @param {String} word
+      */
+      singularize: function(word) {
+        return this.inflect(word, this.rules.singular,  this.rules.irregularInverse);
+      },
+
+      /**
+        @protected
+
+        @method inflect
+        @param {String} word
+        @param {Object} typeRules
+        @param {Object} irregular
+      */
+      inflect: function(word, typeRules, irregular) {
+        var inflection, substitution, result, lowercase, isBlank,
+        isUncountable, isIrregular, isIrregularInverse, rule;
+
+        isBlank = BLANK_REGEX.test(word);
+
+        if (isBlank) {
+          return word;
+        }
+
+        lowercase = word.toLowerCase();
+
+        isUncountable = this.rules.uncountable[lowercase];
+
+        if (isUncountable) {
+          return word;
+        }
+
+        isIrregular = irregular &amp;&amp; irregular[lowercase];
+
+        if (isIrregular) {
+          return isIrregular;
+        }
+
+        for (var i = typeRules.length, min = 0; i &gt; min; i--) {
+           inflection = typeRules[i-1];
+           rule = inflection[0];
+
+          if (rule.test(word)) {
+            break;
+          }
+        }
+
+        inflection = inflection || [];
+
+        rule = inflection[0];
+        substitution = inflection[1];
+
+        result = word.replace(rule, substitution);
+
+        return result;
+      }
+    };
+
+    __exports__[&quot;default&quot;] = Inflector;
+  });
+define(&quot;ember-inflector/lib/system/string&quot;, 
+  [&quot;./inflector&quot;,&quot;exports&quot;],
+  function(__dependency1__, __exports__) {
+    &quot;use strict&quot;;
+    var Inflector = __dependency1__[&quot;default&quot;];
+    var pluralize = function(word) {
+      return Inflector.inflector.pluralize(word);
+    };
+
+    var singularize = function(word) {
+      return Inflector.inflector.singularize(word);
+    };
+
+    __exports__.pluralize = pluralize;
+    __exports__.singularize = singularize;
+  });
+global.DS = requireModule('ember-data/lib/main')['default'];
+}(Ember.lookup));
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/ember-data.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsemberjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/ember.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/ember.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/ember.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,48886 @@
</span><ins>+/*!
+ * @overview  Ember - JavaScript Application Framework
+ * @copyright Copyright 2011-2014 Tilde Inc. and contributors
+ *            Portions Copyright 2006-2011 Strobe Inc.
+ *            Portions Copyright 2008-2011 Apple Inc. All rights reserved.
+ * @license   Licensed under MIT license
+ *            See https://raw.github.com/emberjs/ember.js/master/LICENSE
+ * @version   1.7.0-beta.4+pre.4b6ff143
+ */
+
+(function() {
+    var define, requireModule, require, requirejs, Ember;
+
+    (function() {
+        Ember = this.Ember = this.Ember || {};
+        if (typeof Ember === 'undefined') {
+            Ember = {}
+        };
+
+        if (typeof Ember.__loader === 'undefined') {
+            var registry = {}, seen = {};
+
+            define = function(name, deps, callback) {
+                registry[name] = {
+                    deps: deps,
+                    callback: callback 
+                };
+            };
+
+            requirejs = require = requireModule = function(name) {
+                if (seen.hasOwnProperty(name)) {
+                    return seen[name];
+                }
+                seen[name] = {};
+
+                if (!registry[name]) {
+                    throw new Error(&quot;Could not find module &quot; + name);
+                }
+
+                var mod = registry[name],
+                deps = mod.deps,
+                callback = mod.callback,
+                reified = [],
+                exports;
+
+                for (var i = 0, l = deps.length; i &lt; l; i++) {
+                    if (deps[i] === 'exports') {
+                        reified.push(exports = {});
+                    } else {
+                        reified.push(requireModule(resolve(deps[i])));
+                    }
+                }
+
+                var value = callback.apply(this, reified);
+                return seen[name] = exports || value;
+
+                function resolve(child) {
+                    if (child.charAt(0) !== '.') {
+                        return child;
+                    }
+                    var parts = child.split(&quot;/&quot;);
+                    var parentBase = name.split(&quot;/&quot;).slice(0, -1);
+
+                    for (var i = 0, l = parts.length; i &lt; l; i++) {
+                        var part = parts[i];
+
+                        if (part === '..') {
+                            parentBase.pop();
+                        } else if (part === '.') {
+                            continue;
+                        } else {
+                            parentBase.push(part);
+                        }
+                    }
+
+                    return parentBase.join(&quot;/&quot;);
+                }
+            };
+            requirejs._eak_seen = registry;
+
+            Ember.__loader = {
+                define: define,
+                require: require,
+                registry: registry
+            };
+        } else {
+            define = Ember.__loader.define;
+            requirejs = require = requireModule = Ember.__loader.require;
+        }
+    })();
+
+    define(&quot;backburner&quot;,
+    [&quot;backburner/utils&quot;, &quot;backburner/deferred_action_queues&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Utils = __dependency1__[&quot;default&quot;];
+        var DeferredActionQueues = __dependency2__.DeferredActionQueues;
+
+        var slice = [].slice,
+        pop = [].pop,
+        each = Utils.each,
+        isString = Utils.isString,
+        isFunction = Utils.isFunction,
+        isNumber = Utils.isNumber,
+        timers = [],
+        global = this,
+        NUMBER = /\d+/;
+
+        // In IE 6-8, try/finally doesn't work without a catch.
+        // Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug.
+        // This tests for another broken try/catch behavior that only exhibits in the same versions of IE.
+        var needsIETryCatchFix = (function(e, x) {
+            try {
+                x();
+            } catch (e) {}
+            // jshint ignore:line
+            return !!e;
+        })();
+
+        function isCoercableNumber(number) {
+            return isNumber(number) || NUMBER.test(number);
+        }
+
+        function Backburner(queueNames, options) {
+            this.queueNames = queueNames;
+            this.options = options || {};
+            if (!this.options.defaultQueue) {
+                this.options.defaultQueue = queueNames[0];
+            }
+            this.instanceStack = [];
+            this._debouncees = [];
+            this._throttlers = [];
+        }
+
+        Backburner.prototype = {
+            queueNames: null,
+            options: null,
+            currentInstance: null,
+            instanceStack: null,
+
+            begin: function() {
+                var options = this.options,
+                onBegin = options &amp;&amp; options.onBegin,
+                previousInstance = this.currentInstance;
+
+                if (previousInstance) {
+                    this.instanceStack.push(previousInstance);
+                }
+
+                this.currentInstance = new DeferredActionQueues(this.queueNames, options);
+                if (onBegin) {
+                    onBegin(this.currentInstance, previousInstance);
+                }
+            },
+
+            end: function() {
+                var options = this.options,
+                onEnd = options &amp;&amp; options.onEnd,
+                currentInstance = this.currentInstance,
+                nextInstance = null;
+
+                // Prevent double-finally bug in Safari 6.0.2 and iOS 6
+                // This bug appears to be resolved in Safari 6.0.5 and iOS 7
+                var finallyAlreadyCalled = false;
+                try {
+                    currentInstance.flush();
+                } finally {
+                    if (!finallyAlreadyCalled) {
+                        finallyAlreadyCalled = true;
+
+                        this.currentInstance = null;
+
+                        if (this.instanceStack.length) {
+                            nextInstance = this.instanceStack.pop();
+                            this.currentInstance = nextInstance;
+                        }
+
+                        if (onEnd) {
+                            onEnd(currentInstance, nextInstance);
+                        }
+                    }
+                }
+            },
+
+            run: function(target, method /*, args */
+            ) {
+                var onError = getOnError(this.options);
+
+                this.begin();
+
+                if (!method) {
+                    method = target;
+                    target = null;
+                }
+
+                if (isString(method)) {
+                    method = target[method];
+                }
+
+                var args = slice.call(arguments, 2);
+
+                // guard against Safari 6's double-finally bug
+                var didFinally = false;
+
+                if (onError) {
+                    try {
+                        return method.apply(target, args);
+                    } catch (error) {
+                        onError(error);
+                    } finally {
+                        if (!didFinally) {
+                            didFinally = true;
+                            this.end();
+                        }
+                    }
+                } else {
+                    try {
+                        return method.apply(target, args);
+                    } finally {
+                        if (!didFinally) {
+                            didFinally = true;
+                            this.end();
+                        }
+                    }
+                }
+            },
+
+            defer: function(queueName, target, method /* , args */
+            ) {
+                if (!method) {
+                    method = target;
+                    target = null;
+                }
+
+                if (isString(method)) {
+                    method = target[method];
+                }
+
+                var stack = this.DEBUG ? new Error() : undefined,
+                args = arguments.length &gt; 3 ? slice.call(arguments, 3) : undefined;
+                if (!this.currentInstance) {
+                    createAutorun(this);
+                }
+                return this.currentInstance.schedule(queueName, target, method, args, false, stack);
+            },
+
+            deferOnce: function(queueName, target, method /* , args */
+            ) {
+                if (!method) {
+                    method = target;
+                    target = null;
+                }
+
+                if (isString(method)) {
+                    method = target[method];
+                }
+
+                var stack = this.DEBUG ? new Error() : undefined,
+                args = arguments.length &gt; 3 ? slice.call(arguments, 3) : undefined;
+                if (!this.currentInstance) {
+                    createAutorun(this);
+                }
+                return this.currentInstance.schedule(queueName, target, method, args, true, stack);
+            },
+
+            setTimeout: function() {
+                var args = slice.call(arguments),
+                length = args.length,
+                method, wait, target,
+                methodOrTarget, methodOrWait, methodOrArgs;
+
+                if (length === 0) {
+                    return;
+                } else if (length === 1) {
+                    method = args.shift();
+                    wait = 0;
+                } else if (length === 2) {
+                    methodOrTarget = args[0];
+                    methodOrWait = args[1];
+
+                    if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) {
+                        target = args.shift();
+                        method = args.shift();
+                        wait = 0;
+                    } else if (isCoercableNumber(methodOrWait)) {
+                        method = args.shift();
+                        wait = args.shift();
+                    } else {
+                        method = args.shift();
+                        wait = 0;
+                    }
+                } else {
+                    var last = args[args.length - 1];
+
+                    if (isCoercableNumber(last)) {
+                        wait = args.pop();
+                    } else {
+                        wait = 0;
+                    }
+
+                    methodOrTarget = args[0];
+                    methodOrArgs = args[1];
+
+                    if (isFunction(methodOrArgs) || (isString(methodOrArgs) &amp;&amp;
+                    methodOrTarget !== null &amp;&amp;
+                    methodOrArgs in methodOrTarget)) {
+                        target = args.shift();
+                        method = args.shift();
+                    } else {
+                        method = args.shift();
+                    }
+                }
+
+                var executeAt = ( + new Date()) + parseInt(wait, 10);
+
+                if (isString(method)) {
+                    method = target[method];
+                }
+
+                var onError = getOnError(this.options);
+
+                function fn() {
+                    if (onError) {
+                        try {
+                            method.apply(target, args);
+                        } catch (e) {
+                            onError(e);
+                        }
+                    } else {
+                        method.apply(target, args);
+                    }
+                }
+
+                // find position to insert
+                var i = searchTimer(executeAt, timers);
+
+                timers.splice(i, 0, executeAt, fn);
+
+                updateLaterTimer(this, executeAt, wait);
+
+                return fn;
+            },
+
+            throttle: function(target, method /* , args, wait, [immediate] */
+            ) {
+                var self = this,
+                args = arguments,
+                immediate = pop.call(args),
+                wait,
+                throttler,
+                index,
+                timer;
+
+                if (isNumber(immediate) || isString(immediate)) {
+                    wait = immediate;
+                    immediate = true;
+                } else {
+                    wait = pop.call(args);
+                }
+
+                wait = parseInt(wait, 10);
+
+                index = findThrottler(target, method, this._throttlers);
+                if (index &gt; -1) {
+                    return this._throttlers[index];
+                }
+                // throttled
+
+                timer = global.setTimeout(function() {
+                    if (!immediate) {
+                        self.run.apply(self, args);
+                    }
+                    var index = findThrottler(target, method, self._throttlers);
+                    if (index &gt; -1) {
+                        self._throttlers.splice(index, 1);
+                    }
+                }, wait);
+
+                if (immediate) {
+                    self.run.apply(self, args);
+                }
+
+                throttler = [target, method, timer];
+
+                this._throttlers.push(throttler);
+
+                return throttler;
+            },
+
+            debounce: function(target, method /* , args, wait, [immediate] */
+            ) {
+                var self = this,
+                args = arguments,
+                immediate = pop.call(args),
+                wait,
+                index,
+                debouncee,
+                timer;
+
+                if (isNumber(immediate) || isString(immediate)) {
+                    wait = immediate;
+                    immediate = false;
+                } else {
+                    wait = pop.call(args);
+                }
+
+                wait = parseInt(wait, 10);
+                // Remove debouncee
+                index = findDebouncee(target, method, this._debouncees);
+
+                if (index &gt; -1) {
+                    debouncee = this._debouncees[index];
+                    this._debouncees.splice(index, 1);
+                    clearTimeout(debouncee[2]);
+                }
+
+                timer = global.setTimeout(function() {
+                    if (!immediate) {
+                        self.run.apply(self, args);
+                    }
+                    var index = findDebouncee(target, method, self._debouncees);
+                    if (index &gt; -1) {
+                        self._debouncees.splice(index, 1);
+                    }
+                }, wait);
+
+                if (immediate &amp;&amp; index === -1) {
+                    self.run.apply(self, args);
+                }
+
+                debouncee = [target, method, timer];
+
+                self._debouncees.push(debouncee);
+
+                return debouncee;
+            },
+
+            cancelTimers: function() {
+                var clearItems = function(item) {
+                    clearTimeout(item[2]);
+                };
+
+                each(this._throttlers, clearItems);
+                this._throttlers = [];
+
+                each(this._debouncees, clearItems);
+                this._debouncees = [];
+
+                if (this._laterTimer) {
+                    clearTimeout(this._laterTimer);
+                    this._laterTimer = null;
+                }
+                timers = [];
+
+                if (this._autorun) {
+                    clearTimeout(this._autorun);
+                    this._autorun = null;
+                }
+            },
+
+            hasTimers: function() {
+                return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
+            },
+
+            cancel: function(timer) {
+                var timerType = typeof timer;
+
+                if (timer &amp;&amp; timerType === 'object' &amp;&amp; timer.queue &amp;&amp; timer.method) {
+                    // we're cancelling a deferOnce
+                    return timer.queue.cancel(timer);
+                } else if (timerType === 'function') {
+                    // we're cancelling a setTimeout
+                    for (var i = 0, l = timers.length; i &lt; l; i += 2) {
+                        if (timers[i + 1] === timer) {
+                            timers.splice(i, 2); // remove the two elements
+                            return true;
+                        }
+                    }
+                } else if (Object.prototype.toString.call(timer) === &quot;[object Array]&quot;) {
+                    // we're cancelling a throttle or debounce
+                    return this._cancelItem(findThrottler, this._throttlers, timer) ||
+                    this._cancelItem(findDebouncee, this._debouncees, timer);
+                } else {
+                    return; // timer was null or not a timer
+                }
+            },
+
+            _cancelItem: function(findMethod, array, timer) {
+                var item,
+                index;
+
+                if (timer.length &lt; 3) {
+                    return false;
+                }
+
+                index = findMethod(timer[0], timer[1], array);
+
+                if (index &gt; -1) {
+
+                    item = array[index];
+
+                    if (item[2] === timer[2]) {
+                        array.splice(index, 1);
+                        clearTimeout(timer[2]);
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+        };
+
+        Backburner.prototype.schedule = Backburner.prototype.defer;
+        Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
+        Backburner.prototype.later = Backburner.prototype.setTimeout;
+
+        if (needsIETryCatchFix) {
+            var originalRun = Backburner.prototype.run;
+            Backburner.prototype.run = wrapInTryCatch(originalRun);
+
+            var originalEnd = Backburner.prototype.end;
+            Backburner.prototype.end = wrapInTryCatch(originalEnd);
+        }
+
+        function wrapInTryCatch(func) {
+            return function () {
+                try {
+                    return func.apply(this, arguments);
+                } catch (e) {
+                    throw e;
+                }
+            };
+        }
+
+        function getOnError(options) {
+            return options.onError || (options.onErrorTarget &amp;&amp; options.onErrorTarget[options.onErrorMethod]);
+        }
+
+
+        function createAutorun(backburner) {
+            backburner.begin();
+            backburner._autorun = global.setTimeout(function() {
+                backburner._autorun = null;
+                backburner.end();
+            });
+        }
+
+        function updateLaterTimer(self, executeAt, wait) {
+            if (!self._laterTimer || executeAt &lt; self._laterTimerExpiresAt) {
+                self._laterTimer = global.setTimeout(function() {
+                    self._laterTimer = null;
+                    self._laterTimerExpiresAt = null;
+                    executeTimers(self);
+                }, wait);
+                self._laterTimerExpiresAt = executeAt;
+            }
+        }
+
+        function executeTimers(self) {
+            var now = + new Date(),
+            time, fns, i, l;
+
+            self.run(function() {
+                i = searchTimer(now, timers);
+
+                fns = timers.splice(0, i);
+
+                for (i = 1, l = fns.length; i &lt; l; i += 2) {
+                    self.schedule(self.options.defaultQueue, null, fns[i]);
+                }
+            });
+
+            if (timers.length) {
+                updateLaterTimer(self, timers[0], timers[0] - now);
+            }
+        }
+
+        function findDebouncee(target, method, debouncees) {
+            return findItem(target, method, debouncees);
+        }
+
+        function findThrottler(target, method, throttlers) {
+            return findItem(target, method, throttlers);
+        }
+
+        function findItem(target, method, collection) {
+            var item,
+            index = -1;
+
+            for (var i = 0, l = collection.length; i &lt; l; i++) {
+                item = collection[i];
+                if (item[0] === target &amp;&amp; item[1] === method) {
+                    index = i;
+                    break;
+                }
+            }
+
+            return index;
+        }
+
+        function searchTimer(time, timers) {
+            var start = 0,
+            end = timers.length - 2,
+            middle, l;
+
+            while (start &lt; end) {
+                // since timers is an array of pairs 'l' will always
+                // be an integer
+                l = (end - start) / 2;
+
+                // compensate for the index in case even number
+                // of pairs inside timers
+                middle = start + l - (l % 2);
+
+                if (time &gt;= timers[middle]) {
+                    start = middle + 2;
+                } else {
+                    end = middle;
+                }
+            }
+
+            return (time &gt;= timers[start]) ? start + 2 : start;
+        }
+
+        __exports__.Backburner = Backburner;
+    });
+    define(&quot;backburner/deferred_action_queues&quot;,
+    [&quot;backburner/utils&quot;, &quot;backburner/queue&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Utils = __dependency1__[&quot;default&quot;];
+        var Queue = __dependency2__.Queue;
+
+        var each = Utils.each,
+        isString = Utils.isString;
+
+        function DeferredActionQueues(queueNames, options) {
+            var queues = this.queues = {};
+            this.queueNames = queueNames = queueNames || [];
+
+            this.options = options;
+
+            each(queueNames, function(queueName) {
+                queues[queueName] = new Queue(this, queueName, options);
+            });
+        }
+
+        DeferredActionQueues.prototype = {
+            queueNames: null,
+            queues: null,
+            options: null,
+
+            schedule: function(queueName, target, method, args, onceFlag, stack) {
+                var queues = this.queues,
+                queue = queues[queueName];
+
+                if (!queue) {
+                    throw new Error(&quot;You attempted to schedule an action in a queue (&quot; + queueName + &quot;) that doesn't exist&quot;);
+                }
+
+                if (onceFlag) {
+                    return queue.pushUnique(target, method, args, stack);
+                } else {
+                    return queue.push(target, method, args, stack);
+                }
+            },
+
+            invoke: function(target, method, args, _) {
+                if (args &amp;&amp; args.length &gt; 0) {
+                    method.apply(target, args);
+                } else {
+                    method.call(target);
+                }
+            },
+
+            invokeWithOnError: function(target, method, args, onError) {
+                try {
+                    if (args &amp;&amp; args.length &gt; 0) {
+                        method.apply(target, args);
+                    } else {
+                        method.call(target);
+                    }
+                } catch (error) {
+                    onError(error);
+                }
+            },
+
+            flush: function() {
+                var queues = this.queues,
+                queueNames = this.queueNames,
+                queueName, queue, queueItems, priorQueueNameIndex,
+                queueNameIndex = 0, numberOfQueues = queueNames.length,
+                options = this.options,
+                onError = options.onError || (options.onErrorTarget &amp;&amp; options.onErrorTarget[options.onErrorMethod]),
+                invoke = onError ? this.invokeWithOnError : this.invoke;
+
+                outerloop:
+                while (queueNameIndex &lt; numberOfQueues) {
+                    queueName = queueNames[queueNameIndex];
+                    queue = queues[queueName];
+                    queueItems = queue._queueBeingFlushed = queue._queue.slice();
+                    queue._queue = [];
+
+                    var queueOptions = queue.options, // TODO: write a test for this
+                    before = queueOptions &amp;&amp; queueOptions.before,
+                    after = queueOptions &amp;&amp; queueOptions.after,
+                    target, method, args, stack,
+                    queueIndex = 0, numberOfQueueItems = queueItems.length;
+
+                    if (numberOfQueueItems &amp;&amp; before) {
+                        before();
+                    }
+
+                    while (queueIndex &lt; numberOfQueueItems) {
+                        target = queueItems[queueIndex];
+                        method = queueItems[queueIndex + 1];
+                        args = queueItems[queueIndex + 2];
+                        stack = queueItems[queueIndex + 3]; // Debugging assistance
+
+                        if (isString(method)) {
+                            method = target[method];
+                        }
+
+                        // method could have been nullified / canceled during flush
+                        if (method) {
+                            invoke(target, method, args, onError);
+                        }
+
+                        queueIndex += 4;
+                    }
+
+                    queue._queueBeingFlushed = null;
+                    if (numberOfQueueItems &amp;&amp; after) {
+                        after();
+                    }
+
+                    if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
+                        queueNameIndex = priorQueueNameIndex;
+                        continue outerloop;
+                    }
+
+                    queueNameIndex++;
+                }
+            }
+        };
+
+        function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
+            var queueName, queue;
+
+            for (var i = 0, l = currentQueueIndex; i &lt;= l; i++) {
+                queueName = daq.queueNames[i];
+                queue = daq.queues[queueName];
+                if (queue._queue.length) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        __exports__.DeferredActionQueues = DeferredActionQueues;
+    });
+    define(&quot;backburner/queue&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        function Queue(daq, name, options) {
+            this.daq = daq;
+            this.name = name;
+            this.globalOptions = options;
+            this.options = options[name];
+            this._queue = [];
+        }
+
+        Queue.prototype = {
+            daq: null,
+            name: null,
+            options: null,
+            onError: null,
+            _queue: null,
+
+            push: function(target, method, args, stack) {
+                var queue = this._queue;
+                queue.push(target, method, args, stack);
+                return {
+                    queue: this,
+                    target: target,
+                    method: method
+                };
+            },
+
+            pushUnique: function(target, method, args, stack) {
+                var queue = this._queue, currentTarget, currentMethod, i, l;
+
+                for (i = 0, l = queue.length; i &lt; l; i += 4) {
+                    currentTarget = queue[i];
+                    currentMethod = queue[i + 1];
+
+                    if (currentTarget === target &amp;&amp; currentMethod === method) {
+                        queue[i + 2] = args; // replace args
+                        queue[i + 3] = stack; // replace stack
+                        return {
+                            queue: this,
+                            target: target,
+                            method: method
+                        };
+                    }
+                }
+
+                queue.push(target, method, args, stack);
+                return {
+                    queue: this,
+                    target: target,
+                    method: method
+                };
+            },
+
+            // TODO: remove me, only being used for Ember.run.sync
+            flush: function() {
+                var queue = this._queue,
+                globalOptions = this.globalOptions,
+                options = this.options,
+                before = options &amp;&amp; options.before,
+                after = options &amp;&amp; options.after,
+                onError = globalOptions.onError || (globalOptions.onErrorTarget &amp;&amp; globalOptions.onErrorTarget[globalOptions.onErrorMethod]),
+                target, method, args, stack, i, l = queue.length;
+
+                if (l &amp;&amp; before) {
+                    before();
+                }
+                for (i = 0; i &lt; l; i += 4) {
+                    target = queue[i];
+                    method = queue[i + 1];
+                    args = queue[i + 2];
+                    stack = queue[i + 3]; // Debugging assistance
+
+                    // TODO: error handling
+                    if (args &amp;&amp; args.length &gt; 0) {
+                        if (onError) {
+                            try {
+                                method.apply(target, args);
+                            } catch (e) {
+                                onError(e);
+                            }
+                        } else {
+                            method.apply(target, args);
+                        }
+                    } else {
+                        if (onError) {
+                            try {
+                                method.call(target);
+                            } catch (e) {
+                                onError(e);
+                            }
+                        } else {
+                            method.call(target);
+                        }
+                    }
+                }
+                if (l &amp;&amp; after) {
+                    after();
+                }
+
+                // check if new items have been added
+                if (queue.length &gt; l) {
+                    this._queue = queue.slice(l);
+                    this.flush();
+                } else {
+                    this._queue.length = 0;
+                }
+            },
+
+            cancel: function(actionToCancel) {
+                var queue = this._queue, currentTarget, currentMethod, i, l;
+
+                for (i = 0, l = queue.length; i &lt; l; i += 4) {
+                    currentTarget = queue[i];
+                    currentMethod = queue[i + 1];
+
+                    if (currentTarget === actionToCancel.target &amp;&amp; currentMethod === actionToCancel.method) {
+                        queue.splice(i, 4);
+                        return true;
+                    }
+                }
+
+                // if not found in current queue
+                // could be in the queue that is being flushed
+                queue = this._queueBeingFlushed;
+                if (!queue) {
+                    return;
+                }
+                for (i = 0, l = queue.length; i &lt; l; i += 4) {
+                    currentTarget = queue[i];
+                    currentMethod = queue[i + 1];
+
+                    if (currentTarget === actionToCancel.target &amp;&amp; currentMethod === actionToCancel.method) {
+                        // don't mess with array during flush
+                        // just nullify the method
+                        queue[i + 1] = null;
+                        return true;
+                    }
+                }
+            }
+        };
+
+        __exports__.Queue = Queue;
+    });
+    define(&quot;backburner/utils&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        __exports__[&quot;default&quot;] = {
+            each: function(collection, callback) {
+                for (var i = 0; i &lt; collection.length; i++) {
+                    callback(collection[i]);
+                }
+            },
+
+            isString: function(suspect) {
+                return typeof suspect === 'string';
+            },
+
+            isFunction: function(suspect) {
+                return typeof suspect === 'function';
+            },
+
+            isNumber: function(suspect) {
+                return typeof suspect === 'number';
+            }
+        };
+    });
+
+    define(&quot;container&quot;,
+    [&quot;container/container&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        /*
+            Public api for the container is still in flux.
+            The public api, specified on the application namespace should be considered the stable api.
+            // @module container
+              @private
+            */
+
+        /*
+             Flag to enable/disable model factory injections (disabled by default)
+             If model factory injections are enabled, models should not be
+             accessed globally (only through `container.lookupFactory('model:modelName'))`);
+            */
+        Ember.MODEL_FACTORY_INJECTIONS = false;
+
+        if (Ember.ENV &amp;&amp; typeof Ember.ENV.MODEL_FACTORY_INJECTIONS !== 'undefined') {
+            Ember.MODEL_FACTORY_INJECTIONS = !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
+        }
+
+
+        var Container = __dependency1__[&quot;default&quot;];
+
+        __exports__[&quot;default&quot;] = Container;
+    });
+    define(&quot;container/container&quot;,
+    [&quot;container/inheriting_dict&quot;, &quot;ember-metal/core&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var InheritingDict = __dependency1__[&quot;default&quot;];
+        var Ember = __dependency2__[&quot;default&quot;];
+        // Ember.assert
+
+        // A lightweight container that helps to assemble and decouple components.
+        // Public api for the container is still in flux.
+        // The public api, specified on the application namespace should be considered the stable api.
+        function Container(parent) {
+            this.parent = parent;
+            this.children = [];
+
+            this.resolver = parent &amp;&amp; parent.resolver || function() {};
+
+            this.registry = new InheritingDict(parent &amp;&amp; parent.registry);
+            this.cache = new InheritingDict(parent &amp;&amp; parent.cache);
+            this.factoryCache = new InheritingDict(parent &amp;&amp; parent.factoryCache);
+            this.resolveCache = new InheritingDict(parent &amp;&amp; parent.resolveCache);
+            this.typeInjections = new InheritingDict(parent &amp;&amp; parent.typeInjections);
+            this.injections = {};
+
+            this.factoryTypeInjections = new InheritingDict(parent &amp;&amp; parent.factoryTypeInjections);
+            this.factoryInjections = {};
+
+            this._options = new InheritingDict(parent &amp;&amp; parent._options);
+            this._typeOptions = new InheritingDict(parent &amp;&amp; parent._typeOptions);
+        }
+
+        Container.prototype = {
+
+            /**
+                    @property parent
+                    @type Container
+                    @default null
+                  */
+            parent: null,
+
+            /**
+                    @property children
+                    @type Array
+                    @default []
+                  */
+            children: null,
+
+            /**
+                    @property resolver
+                    @type function
+                  */
+            resolver: null,
+
+            /**
+                    @property registry
+                    @type InheritingDict
+                  */
+            registry: null,
+
+            /**
+                    @property cache
+                    @type InheritingDict
+                  */
+            cache: null,
+
+            /**
+                    @property typeInjections
+                    @type InheritingDict
+                  */
+            typeInjections: null,
+
+            /**
+                    @property injections
+                    @type Object
+                    @default {}
+                  */
+            injections: null,
+
+            /**
+                    @private
+
+                    @property _options
+                    @type InheritingDict
+                    @default null
+                  */
+            _options: null,
+
+            /**
+                    @private
+
+                    @property _typeOptions
+                    @type InheritingDict
+                  */
+            _typeOptions: null,
+
+            /**
+                    Returns a new child of the current container. These children are configured
+                    to correctly inherit from the current container.
+
+                    @method child
+                    @return {Container}
+                  */
+            child: function() {
+                var container = new Container(this);
+                this.children.push(container);
+                return container;
+            },
+
+            /**
+                    Sets a key-value pair on the current container. If a parent container,
+                    has the same key, once set on a child, the parent and child will diverge
+                    as expected.
+
+                    @method set
+                    @param {Object} object
+                    @param {String} key
+                    @param {any} value
+                  */
+            set: function(object, key, value) {
+                object[key] = value;
+            },
+
+            /**
+                    Registers a factory for later injection.
+
+                    Example:
+
+                    ```javascript
+                    var container = new Container();
+
+                    container.register('model:user', Person, {singleton: false });
+                    container.register('fruit:favorite', Orange);
+                    container.register('communication:main', Email, {singleton: false});
+                    ```
+
+                    @method register
+                    @param {String} fullName
+                    @param {Function} factory
+                    @param {Object} options
+                  */
+            register: function(fullName, factory, options) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+
+                if (factory === undefined) {
+                    throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`');
+                }
+
+                var normalizedName = this.normalize(fullName);
+
+                if (this.cache.has(normalizedName)) {
+                    throw new Error('Cannot re-register: `' + fullName + '`, as it has already been looked up.');
+                }
+
+                this.registry.set(normalizedName, factory);
+                this._options.set(normalizedName, options || {});
+            },
+
+            /**
+                    Unregister a fullName
+
+                    ```javascript
+                    var container = new Container();
+                    container.register('model:user', User);
+
+                    container.lookup('model:user') instanceof User //=&gt; true
+
+                    container.unregister('model:user')
+                    container.lookup('model:user') === undefined //=&gt; true
+                    ```
+
+                    @method unregister
+                    @param {String} fullName
+                   */
+            unregister: function(fullName) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+
+                var normalizedName = this.normalize(fullName);
+
+                this.registry.remove(normalizedName);
+                this.cache.remove(normalizedName);
+                this.factoryCache.remove(normalizedName);
+                this.resolveCache.remove(normalizedName);
+                this._options.remove(normalizedName);
+            },
+
+            /**
+                    Given a fullName return the corresponding factory.
+
+                    By default `resolve` will retrieve the factory from
+                    its container's registry.
+
+                    ```javascript
+                    var container = new Container();
+                    container.register('api:twitter', Twitter);
+
+                    container.resolve('api:twitter') // =&gt; Twitter
+                    ```
+
+                    Optionally the container can be provided with a custom resolver.
+                    If provided, `resolve` will first provide the custom resolver
+                    the opportunity to resolve the fullName, otherwise it will fallback
+                    to the registry.
+
+                    ```javascript
+                    var container = new Container();
+                    container.resolver = function(fullName) {
+                      // lookup via the module system of choice
+                    };
+
+                    // the twitter factory is added to the module system
+                    container.resolve('api:twitter') // =&gt; Twitter
+                    ```
+
+                    @method resolve
+                    @param {String} fullName
+                    @return {Function} fullName's factory
+                  */
+            resolve: function(fullName) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+                return resolve(this, this.normalize(fullName));
+            },
+
+            /**
+                    A hook that can be used to describe how the resolver will
+                    attempt to find the factory.
+
+                    For example, the default Ember `.describe` returns the full
+                    class name (including namespace) where Ember's resolver expects
+                    to find the `fullName`.
+
+                    @method describe
+                    @param {String} fullName
+                    @return {string} described fullName
+                  */
+            describe: function(fullName) {
+                return fullName;
+            },
+
+            /**
+                    A hook to enable custom fullName normalization behaviour
+
+                    @method normalize
+                    @param {String} fullName
+                    @return {string} normalized fullName
+                  */
+            normalize: function(fullName) {
+                return fullName;
+            },
+
+            /**
+                    @method makeToString
+
+                    @param {any} factory
+                    @param {string} fullName
+                    @return {function} toString function
+                  */
+            makeToString: function(factory, fullName) {
+                return factory.toString();
+            },
+
+            /**
+                    Given a fullName return a corresponding instance.
+
+                    The default behaviour is for lookup to return a singleton instance.
+                    The singleton is scoped to the container, allowing multiple containers
+                    to all have their own locally scoped singletons.
+
+                    ```javascript
+                    var container = new Container();
+                    container.register('api:twitter', Twitter);
+
+                    var twitter = container.lookup('api:twitter');
+
+                    twitter instanceof Twitter; // =&gt; true
+
+                    // by default the container will return singletons
+                    var twitter2 = container.lookup('api:twitter');
+                    twitter2 instanceof Twitter; // =&gt; true
+
+                    twitter === twitter2; //=&gt; true
+                    ```
+
+                    If singletons are not wanted an optional flag can be provided at lookup.
+
+                    ```javascript
+                    var container = new Container();
+                    container.register('api:twitter', Twitter);
+
+                    var twitter = container.lookup('api:twitter', { singleton: false });
+                    var twitter2 = container.lookup('api:twitter', { singleton: false });
+
+                    twitter === twitter2; //=&gt; false
+                    ```
+
+                    @method lookup
+                    @param {String} fullName
+                    @param {Object} options
+                    @return {any}
+                  */
+            lookup: function(fullName, options) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+                return lookup(this, this.normalize(fullName), options);
+            },
+
+            /**
+                    Given a fullName return the corresponding factory.
+
+                    @method lookupFactory
+                    @param {String} fullName
+                    @return {any}
+                  */
+            lookupFactory: function(fullName) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+                return factoryFor(this, this.normalize(fullName));
+            },
+
+            /**
+                    Given a fullName check if the container is aware of its factory
+                    or singleton instance.
+
+                    @method has
+                    @param {String} fullName
+                    @return {Boolean}
+                  */
+            has: function(fullName) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+                return has(this, this.normalize(fullName));
+            },
+
+            /**
+                    Allow registering options for all factories of a type.
+
+                    ```javascript
+                    var container = new Container();
+
+                    // if all of type `connection` must not be singletons
+                    container.optionsForType('connection', { singleton: false });
+
+                    container.register('connection:twitter', TwitterConnection);
+                    container.register('connection:facebook', FacebookConnection);
+
+                    var twitter = container.lookup('connection:twitter');
+                    var twitter2 = container.lookup('connection:twitter');
+
+                    twitter === twitter2; // =&gt; false
+
+                    var facebook = container.lookup('connection:facebook');
+                    var facebook2 = container.lookup('connection:facebook');
+
+                    facebook === facebook2; // =&gt; false
+                    ```
+
+                    @method optionsForType
+                    @param {String} type
+                    @param {Object} options
+                  */
+            optionsForType: function(type, options) {
+                if (this.parent) {
+                    illegalChildOperation('optionsForType');
+                }
+
+                this._typeOptions.set(type, options);
+            },
+
+            /**
+                    @method options
+                    @param {String} type
+                    @param {Object} options
+                  */
+            options: function(type, options) {
+                this.optionsForType(type, options);
+            },
+
+            /**
+                    Used only via `injection`.
+
+                    Provides a specialized form of injection, specifically enabling
+                    all objects of one type to be injected with a reference to another
+                    object.
+
+                    For example, provided each object of type `controller` needed a `router`.
+                    one would do the following:
+
+                    ```javascript
+                    var container = new Container();
+
+                    container.register('router:main', Router);
+                    container.register('controller:user', UserController);
+                    container.register('controller:post', PostController);
+
+                    container.typeInjection('controller', 'router', 'router:main');
+
+                    var user = container.lookup('controller:user');
+                    var post = container.lookup('controller:post');
+
+                    user.router instanceof Router; //=&gt; true
+                    post.router instanceof Router; //=&gt; true
+
+                    // both controllers share the same router
+                    user.router === post.router; //=&gt; true
+                    ```
+
+                    @private
+                    @method typeInjection
+                    @param {String} type
+                    @param {String} property
+                    @param {String} fullName
+                  */
+            typeInjection: function(type, property, fullName) {
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+                if (this.parent) {
+                    illegalChildOperation('typeInjection');
+                }
+
+                var fullNameType = fullName.split(':')[0];
+                if (fullNameType === type) {
+                    throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.');
+                }
+                addTypeInjection(this.typeInjections, type, property, fullName);
+            },
+
+            /**
+                    Defines injection rules.
+
+                    These rules are used to inject dependencies onto objects when they
+                    are instantiated.
+
+                    Two forms of injections are possible:
+
+                    * Injecting one fullName on another fullName
+                    * Injecting one fullName on a type
+
+                    Example:
+
+                    ```javascript
+                    var container = new Container();
+
+                    container.register('source:main', Source);
+                    container.register('model:user', User);
+                    container.register('model:post', Post);
+
+                    // injecting one fullName on another fullName
+                    // eg. each user model gets a post model
+                    container.injection('model:user', 'post', 'model:post');
+
+                    // injecting one fullName on another type
+                    container.injection('model', 'source', 'source:main');
+
+                    var user = container.lookup('model:user');
+                    var post = container.lookup('model:post');
+
+                    user.source instanceof Source; //=&gt; true
+                    post.source instanceof Source; //=&gt; true
+
+                    user.post instanceof Post; //=&gt; true
+
+                    // and both models share the same source
+                    user.source === post.source; //=&gt; true
+                    ```
+
+                    @method injection
+                    @param {String} factoryName
+                    @param {String} property
+                    @param {String} injectionName
+                  */
+            injection: function(fullName, property, injectionName) {
+                if (this.parent) {
+                    illegalChildOperation('injection');
+                }
+
+                validateFullName(injectionName);
+                var normalizedInjectionName = this.normalize(injectionName);
+
+                if (fullName.indexOf(':') === -1) {
+                    return this.typeInjection(fullName, property, normalizedInjectionName);
+                }
+
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+                var normalizedName = this.normalize(fullName);
+
+                if (this.cache.has(normalizedName)) {
+                    throw new Error(&quot;Attempted to register an injection for a type that has already been looked up. ('&quot; + normalizedName + &quot;', '&quot; + property + &quot;', '&quot; + injectionName + &quot;')&quot;);
+                }
+                addInjection(this.injections, normalizedName, property, normalizedInjectionName);
+            },
+
+
+            /**
+                    Used only via `factoryInjection`.
+
+                    Provides a specialized form of injection, specifically enabling
+                    all factory of one type to be injected with a reference to another
+                    object.
+
+                    For example, provided each factory of type `model` needed a `store`.
+                    one would do the following:
+
+                    ```javascript
+                    var container = new Container();
+
+                    container.register('store:main', SomeStore);
+
+                    container.factoryTypeInjection('model', 'store', 'store:main');
+
+                    var store = container.lookup('store:main');
+                    var UserFactory = container.lookupFactory('model:user');
+
+                    UserFactory.store instanceof SomeStore; //=&gt; true
+                    ```
+
+                    @private
+                    @method factoryTypeInjection
+                    @param {String} type
+                    @param {String} property
+                    @param {String} fullName
+                  */
+            factoryTypeInjection: function(type, property, fullName) {
+                if (this.parent) {
+                    illegalChildOperation('factoryTypeInjection');
+                }
+
+                addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName));
+            },
+
+            /**
+                    Defines factory injection rules.
+
+                    Similar to regular injection rules, but are run against factories, via
+                    `Container#lookupFactory`.
+
+                    These rules are used to inject objects onto factories when they
+                    are looked up.
+
+                    Two forms of injections are possible:
+
+                  * Injecting one fullName on another fullName
+                  * Injecting one fullName on a type
+
+                    Example:
+
+                    ```javascript
+                    var container = new Container();
+
+                    container.register('store:main', Store);
+                    container.register('store:secondary', OtherStore);
+                    container.register('model:user', User);
+                    container.register('model:post', Post);
+
+                    // injecting one fullName on another type
+                    container.factoryInjection('model', 'store', 'store:main');
+
+                    // injecting one fullName on another fullName
+                    container.factoryInjection('model:post', 'secondaryStore', 'store:secondary');
+
+                    var UserFactory = container.lookupFactory('model:user');
+                    var PostFactory = container.lookupFactory('model:post');
+                    var store = container.lookup('store:main');
+
+                    UserFactory.store instanceof Store; //=&gt; true
+                    UserFactory.secondaryStore instanceof OtherStore; //=&gt; false
+
+                    PostFactory.store instanceof Store; //=&gt; true
+                    PostFactory.secondaryStore instanceof OtherStore; //=&gt; true
+
+                    // and both models share the same source instance
+                    UserFactory.store === PostFactory.store; //=&gt; true
+                    ```
+
+                    @method factoryInjection
+                    @param {String} factoryName
+                    @param {String} property
+                    @param {String} injectionName
+                  */
+            factoryInjection: function(fullName, property, injectionName) {
+                if (this.parent) {
+                    illegalChildOperation('injection');
+                }
+
+                var normalizedName = this.normalize(fullName);
+                var normalizedInjectionName = this.normalize(injectionName);
+
+                validateFullName(injectionName);
+
+                if (fullName.indexOf(':') === -1) {
+                    return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
+                }
+
+                Ember.assert('fullName must be a proper full name', validateFullName(fullName));
+
+                if (this.factoryCache.has(normalizedName)) {
+                    throw new Error('Attempted to register a factoryInjection for a type that has already ' +
+                    'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')');
+                }
+
+                addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName);
+            },
+
+            /**
+                    A depth first traversal, destroying the container, its descendant containers and all
+                    their managed objects.
+
+                    @method destroy
+                  */
+            destroy: function() {
+                for (var i = 0, length = this.children.length; i &lt; length; i++) {
+                    this.children[i].destroy();
+                }
+
+                this.children = [];
+
+                eachDestroyable(this, function(item) {
+                    item.destroy();
+                });
+
+                this.parent = undefined;
+                this.isDestroyed = true;
+            },
+
+            /**
+                    @method reset
+                  */
+            reset: function() {
+                for (var i = 0, length = this.children.length; i &lt; length; i++) {
+                    resetCache(this.children[i]);
+                }
+
+                resetCache(this);
+            }
+        };
+
+        function resolve(container, normalizedName) {
+            var cached = container.resolveCache.get(normalizedName);
+            if (cached) {
+                return cached;
+            }
+
+            var resolved = container.resolver(normalizedName) || container.registry.get(normalizedName);
+            container.resolveCache.set(normalizedName, resolved);
+
+            return resolved;
+        }
+
+        function has(container, fullName) {
+            if (container.cache.has(fullName)) {
+                return true;
+            }
+
+            return !!container.resolve(fullName);
+        }
+
+        function lookup(container, fullName, options) {
+            options = options || {};
+
+            if (container.cache.has(fullName) &amp;&amp; options.singleton !== false) {
+                return container.cache.get(fullName);
+            }
+
+            var value = instantiate(container, fullName);
+
+            if (value === undefined) {
+                return;
+            }
+
+            if (isSingleton(container, fullName) &amp;&amp; options.singleton !== false) {
+                container.cache.set(fullName, value);
+            }
+
+            return value;
+        }
+
+        function illegalChildOperation(operation) {
+            throw new Error(operation + ' is not currently supported on child containers');
+        }
+
+        function isSingleton(container, fullName) {
+            var singleton = option(container, fullName, 'singleton');
+
+            return singleton !== false;
+        }
+
+        function buildInjections(container, injections) {
+            var hash = {};
+
+            if (!injections) {
+                return hash;
+            }
+
+            var injection, injectable;
+
+            for (var i = 0, length = injections.length; i &lt; length; i++) {
+                injection = injections[i];
+                injectable = lookup(container, injection.fullName);
+
+                if (injectable !== undefined) {
+                    hash[injection.property] = injectable;
+                } else {
+                    throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`');
+                }
+            }
+
+            return hash;
+        }
+
+        function option(container, fullName, optionName) {
+            var options = container._options.get(fullName);
+
+            if (options &amp;&amp; options[optionName] !== undefined) {
+                return options[optionName];
+            }
+
+            var type = fullName.split(':')[0];
+            options = container._typeOptions.get(type);
+
+            if (options) {
+                return options[optionName];
+            }
+        }
+
+        function factoryFor(container, fullName) {
+            var cache = container.factoryCache;
+            if (cache.has(fullName)) {
+                return cache.get(fullName);
+            }
+            var factory = container.resolve(fullName);
+            if (factory === undefined) {
+                return;
+            }
+
+            var type = fullName.split(':')[0];
+            if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS &amp;&amp; type === 'model')) {
+                // TODO: think about a 'safe' merge style extension
+                // for now just fallback to create time injection
+                return factory;
+            } else {
+                var injections = injectionsFor(container, fullName);
+                var factoryInjections = factoryInjectionsFor(container, fullName);
+
+                factoryInjections._toString = container.makeToString(factory, fullName);
+
+                var injectedFactory = factory.extend(injections);
+                injectedFactory.reopenClass(factoryInjections);
+
+                cache.set(fullName, injectedFactory);
+
+                return injectedFactory;
+            }
+        }
+
+        function injectionsFor(container, fullName) {
+            var splitName = fullName.split(':'),
+            type = splitName[0],
+            injections = [];
+
+            injections = injections.concat(container.typeInjections.get(type) || []);
+            injections = injections.concat(container.injections[fullName] || []);
+
+            injections = buildInjections(container, injections);
+            injections._debugContainerKey = fullName;
+            injections.container = container;
+
+            return injections;
+        }
+
+        function factoryInjectionsFor(container, fullName) {
+            var splitName = fullName.split(':'),
+            type = splitName[0],
+            factoryInjections = [];
+
+            factoryInjections = factoryInjections.concat(container.factoryTypeInjections.get(type) || []);
+            factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []);
+
+            factoryInjections = buildInjections(container, factoryInjections);
+            factoryInjections._debugContainerKey = fullName;
+
+            return factoryInjections;
+        }
+
+        function instantiate(container, fullName) {
+            var factory = factoryFor(container, fullName);
+
+            if (option(container, fullName, 'instantiate') === false) {
+                return factory;
+            }
+
+            if (factory) {
+                if (typeof factory.create !== 'function') {
+                    throw new Error('Failed to create an instance of \'' + fullName + '\'. ' +
+                    'Most likely an improperly defined class or an invalid module export.');
+                }
+
+                if (typeof factory.extend === 'function') {
+                    // assume the factory was extendable and is already injected
+                    return factory.create();
+                } else {
+                    // assume the factory was extendable
+                    // to create time injections
+                    // TODO: support new'ing for instantiation and merge injections for pure JS Functions
+                    return factory.create(injectionsFor(container, fullName));
+                }
+            }
+        }
+
+        function eachDestroyable(container, callback) {
+            container.cache.eachLocal(function(key, value) {
+                if (option(container, key, 'instantiate') === false) {
+                    return;
+                }
+                callback(value);
+            });
+        }
+
+        function resetCache(container) {
+            container.cache.eachLocal(function(key, value) {
+                if (option(container, key, 'instantiate') === false) {
+                    return;
+                }
+                value.destroy();
+            });
+            container.cache.dict = {};
+        }
+
+        function addTypeInjection(rules, type, property, fullName) {
+            var injections = rules.get(type);
+
+            if (!injections) {
+                injections = [];
+                rules.set(type, injections);
+            }
+
+            injections.push({
+                property: property,
+                fullName: fullName
+            });
+        }
+
+        var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
+        function validateFullName(fullName) {
+            if (!VALID_FULL_NAME_REGEXP.test(fullName)) {
+                throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
+            }
+            return true;
+        }
+
+        function addInjection(rules, factoryName, property, injectionName) {
+            var injections = rules[factoryName] = rules[factoryName] || [];
+            injections.push({
+                property: property,
+                fullName: injectionName 
+            });
+        }
+
+        __exports__[&quot;default&quot;] = Container;
+    });
+    define(&quot;container/inheriting_dict&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        // A safe and simple inheriting object.
+        function InheritingDict(parent) {
+            this.parent = parent;
+            this.dict = {};
+        }
+
+        InheritingDict.prototype = {
+
+            /**
+                    @property parent
+                    @type InheritingDict
+                    @default null
+                  */
+
+            parent: null,
+
+            /**
+                    Object used to store the current nodes data.
+
+                    @property dict
+                    @type Object
+                    @default Object
+                  */
+            dict: null,
+
+            /**
+                    Retrieve the value given a key, if the value is present at the current
+                    level use it, otherwise walk up the parent hierarchy and try again. If
+                    no matching key is found, return undefined.
+
+                    @method get
+                    @param {String} key
+                    @return {any}
+                  */
+            get: function(key) {
+                var dict = this.dict;
+
+                if (dict.hasOwnProperty(key)) {
+                    return dict[key];
+                }
+
+                if (this.parent) {
+                    return this.parent.get(key);
+                }
+            },
+
+            /**
+                    Set the given value for the given key, at the current level.
+
+                    @method set
+                    @param {String} key
+                    @param {Any} value
+                  */
+            set: function(key, value) {
+                this.dict[key] = value;
+            },
+
+            /**
+                    Delete the given key
+
+                    @method remove
+                    @param {String} key
+                  */
+            remove: function(key) {
+                delete this.dict[key];
+            },
+
+            /**
+                    Check for the existence of given a key, if the key is present at the current
+                    level return true, otherwise walk up the parent hierarchy and try again. If
+                    no matching key is found, return false.
+
+                    @method has
+                    @param {String} key
+                    @return {Boolean}
+                  */
+            has: function(key) {
+                var dict = this.dict;
+
+                if (dict.hasOwnProperty(key)) {
+                    return true;
+                }
+
+                if (this.parent) {
+                    return this.parent.has(key);
+                }
+
+                return false;
+            },
+
+            /**
+                    Iterate and invoke a callback for each local key-value pair.
+
+                    @method eachLocal
+                    @param {Function} callback
+                    @param {Object} binding
+                  */
+            eachLocal: function(callback, binding) {
+                var dict = this.dict;
+
+                for (var prop in dict) {
+                    if (dict.hasOwnProperty(prop)) {
+                        callback.call(binding, prop, dict[prop]);
+                    }
+                }
+            }
+        };
+
+        __exports__[&quot;default&quot;] = InheritingDict;
+    });
+    define(&quot;ember-application&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-application/system/dag&quot;, &quot;ember-application/system/resolver&quot;, &quot;ember-application/system/application&quot;, &quot;ember-application/ext/controller&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var runLoadHooks = __dependency2__.runLoadHooks;
+
+        /**
+            Ember Application
+
+            @module ember
+            @submodule ember-application
+            @requires ember-views, ember-routing
+            */
+
+        var DAG = __dependency3__[&quot;default&quot;];
+        var Resolver = __dependency4__.Resolver;
+        var DefaultResolver = __dependency4__[&quot;default&quot;];
+        var Application = __dependency5__[&quot;default&quot;];
+        // side effect of extending ControllerMixin
+
+        Ember.Application = Application;
+        Ember.DAG = DAG;
+        Ember.Resolver = Resolver;
+        Ember.DefaultResolver = DefaultResolver;
+
+        runLoadHooks('Ember.Application', Application);
+    });
+    define(&quot;ember-application/ext/controller&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/computed&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;ember-routing/system/controller_for&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-application
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var EmberError = __dependency4__[&quot;default&quot;];
+        var inspect = __dependency5__.inspect;
+        var computed = __dependency6__.computed;
+        var ControllerMixin = __dependency7__[&quot;default&quot;];
+        var meta = __dependency5__.meta;
+        var controllerFor = __dependency8__[&quot;default&quot;];
+
+        function verifyNeedsDependencies(controller, container, needs) {
+            var dependency, i, l, missing = [];
+
+            for (i = 0, l = needs.length; i &lt; l; i++) {
+                dependency = needs[i];
+
+                Ember.assert(inspect(controller) + &quot;#needs must not specify dependencies with periods in their names (&quot; + dependency + &quot;)&quot;, dependency.indexOf('.') === -1);
+
+                if (dependency.indexOf(':') === -1) {
+                    dependency = &quot;controller:&quot; + dependency;
+                }
+
+                // Structure assert to still do verification but not string concat in production
+                if (!container.has(dependency)) {
+                    missing.push(dependency);
+                }
+            }
+            if (missing.length) {
+                throw new EmberError(inspect(controller) + &quot; needs [ &quot; + missing.join(', ') + &quot; ] but &quot; + (missing.length &gt; 1 ? 'they' : 'it') + &quot; could not be found&quot;);
+            }
+        }
+
+        var defaultControllersComputedProperty = computed(function() {
+            var controller = this;
+
+            return {
+                needs: get(controller, 'needs'),
+                container: get(controller, 'container'),
+                unknownProperty: function(controllerName) {
+                    var needs = this.needs,
+                    dependency, i, l;
+                    for (i = 0, l = needs.length; i &lt; l; i++) {
+                        dependency = needs[i];
+                        if (dependency === controllerName) {
+                            return this.container.lookup('controller:' + controllerName);
+                        }
+                    }
+
+                    var errorMessage = inspect(controller) + '#needs does not include `' + controllerName + '`. To access the ' + controllerName + ' controller from ' + inspect(controller) + ', ' + inspect(controller) + ' should have a `needs` property that is an array of the controllers it has access to.';
+                    throw new ReferenceError(errorMessage);
+                },
+                setUnknownProperty: function (key, value) {
+                    throw new Error(&quot;You cannot overwrite the value of `controllers.&quot; + key + &quot;` of &quot; + inspect(controller));
+                }
+            };
+        });
+
+        /**
+              @class ControllerMixin
+              @namespace Ember
+            */
+        ControllerMixin.reopen({
+            concatenatedProperties: ['needs'],
+
+            /**
+                    An array of other controller objects available inside
+                    instances of this controller via the `controllers`
+                    property:
+
+                    For example, when you define a controller:
+
+                    ```javascript
+                    App.CommentsController = Ember.ArrayController.extend({
+                      needs: ['post']
+                    });
+                    ```
+
+                    The application's single instance of these other
+                    controllers are accessible by name through the
+                    `controllers` property:
+
+                    ```javascript
+                    this.get('controllers.post'); // instance of App.PostController
+                    ```
+
+                    Given that you have a nested controller (nested resource):
+
+                    ```javascript
+                    App.CommentsNewController = Ember.ObjectController.extend({
+                    });
+                    ```
+
+                    When you define a controller that requires access to a nested one:
+
+                    ```javascript
+                    App.IndexController = Ember.ObjectController.extend({
+                      needs: ['commentsNew']
+                    });
+                    ```
+
+                    You will be able to get access to it:
+
+                    ```javascript
+                    this.get('controllers.commentsNew'); // instance of App.CommentsNewController
+                    ```
+
+                    This is only available for singleton controllers.
+
+                    @property {Array} needs
+                    @default []
+                  */
+            needs: [],
+
+            init: function() {
+                var needs = get(this, 'needs');
+                var length = get(needs, 'length');
+
+                if (length &gt; 0) {
+                    Ember.assert(' `' + inspect(this) + ' specifies `needs`, but does ' +
+                    &quot;not have a container. Please ensure this controller was &quot; +
+                    &quot;instantiated with a container.&quot;,
+                    this.container || meta(this, false).descs.controllers !== defaultControllersComputedProperty);
+
+                    if (this.container) {
+                        verifyNeedsDependencies(this, this.container, needs);
+                    }
+
+                    // if needs then initialize controllers proxy
+                    get(this, 'controllers');
+                }
+
+                this._super.apply(this, arguments);
+            },
+
+            /**
+                    @method controllerFor
+                    @see {Ember.Route#controllerFor}
+                    @deprecated Use `needs` instead
+                  */
+            controllerFor: function(controllerName) {
+                Ember.deprecate(&quot;Controller#controllerFor is deprecated, please use Controller#needs instead&quot;);
+                return controllerFor(get(this, 'container'), controllerName);
+            },
+
+            /**
+                    Stores the instances of other controllers available from within
+                    this controller. Any controller listed by name in the `needs`
+                    property will be accessible by name through this property.
+
+                    ```javascript
+                    App.CommentsController = Ember.ArrayController.extend({
+                      needs: ['post'],
+                      postTitle: function(){
+                        var currentPost = this.get('controllers.post'); // instance of App.PostController
+                        return currentPost.get('title');
+                      }.property('controllers.post.title')
+                    });
+                    ```
+
+                    @see {Ember.ControllerMixin#needs}
+                    @property {Object} controllers
+                    @default null
+                  */
+            controllers: defaultControllersComputedProperty
+        });
+
+        __exports__[&quot;default&quot;] = ControllerMixin;
+    });
+    define(&quot;ember-application/system/application&quot;,
+    [&quot;ember-metal&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-application/system/dag&quot;, &quot;ember-runtime/system/namespace&quot;, &quot;ember-runtime/mixins/deferred&quot;, &quot;ember-application/system/resolver&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/utils&quot;, &quot;container/container&quot;, &quot;ember-runtime/controllers/controller&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/controllers/object_controller&quot;, &quot;ember-runtime/controllers/array_controller&quot;, &quot;ember-views/system/event_dispatcher&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-routing/system/route&quot;, &quot;ember-routing/system/router&quot;, &quot;ember-routing/location/hash_location&quot;, &quot;ember-routing/location/history_location&quot;, &quot;ember-routing/location/auto_location&quot;, &quot;ember-routing/location/none_location&quot;, &quot;ember-routing/system/cache&quot;, &quot;ember-metal/core&quot;, &quot;ember-handlebars-compiler&quot;, &quot;ember-application/system/deprecated-container&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-application
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var runLoadHooks = __dependency4__.runLoadHooks;
+        var DAG = __dependency5__[&quot;default&quot;];
+        var Namespace = __dependency6__[&quot;default&quot;];
+        var DeferredMixin = __dependency7__[&quot;default&quot;];
+        var DefaultResolver = __dependency8__[&quot;default&quot;];
+        var create = __dependency9__.create;
+        var run = __dependency10__[&quot;default&quot;];
+        var canInvoke = __dependency11__.canInvoke;
+        var Container = __dependency12__[&quot;default&quot;];
+        var Controller = __dependency13__[&quot;default&quot;];
+        var EnumerableUtils = __dependency14__[&quot;default&quot;];
+        var ObjectController = __dependency15__[&quot;default&quot;];
+        var ArrayController = __dependency16__[&quot;default&quot;];
+        var EventDispatcher = __dependency17__[&quot;default&quot;];
+        //import ContainerDebugAdapter from &quot;ember-extension-support/container_debug_adapter&quot;;
+        var jQuery = __dependency18__[&quot;default&quot;];
+        var Route = __dependency19__[&quot;default&quot;];
+        var Router = __dependency20__[&quot;default&quot;];
+        var HashLocation = __dependency21__[&quot;default&quot;];
+        var HistoryLocation = __dependency22__[&quot;default&quot;];
+        var AutoLocation = __dependency23__[&quot;default&quot;];
+        var NoneLocation = __dependency24__[&quot;default&quot;];
+        var BucketCache = __dependency25__[&quot;default&quot;];
+
+        var K = __dependency26__.K;
+        var EmberHandlebars = __dependency27__[&quot;default&quot;];
+        var DeprecatedContainer = __dependency28__[&quot;default&quot;];
+
+        var ContainerDebugAdapter;
+
+        /**
+              An instance of `Ember.Application` is the starting point for every Ember
+              application. It helps to instantiate, initialize and coordinate the many
+              objects that make up your app.
+
+              Each Ember app has one and only one `Ember.Application` object. In fact, the
+              very first thing you should do in your application is create the instance:
+
+              ```javascript
+              window.App = Ember.Application.create();
+              ```
+
+              Typically, the application object is the only global variable. All other
+              classes in your app should be properties on the `Ember.Application` instance,
+              which highlights its first role: a global namespace.
+
+              For example, if you define a view class, it might look like this:
+
+              ```javascript
+              App.MyView = Ember.View.extend();
+              ```
+
+              By default, calling `Ember.Application.create()` will automatically initialize
+              your application by calling the `Ember.Application.initialize()` method. If
+              you need to delay initialization, you can call your app's `deferReadiness()`
+              method. When you are ready for your app to be initialized, call its
+              `advanceReadiness()` method.
+
+              You can define a `ready` method on the `Ember.Application` instance, which
+              will be run by Ember when the application is initialized.
+
+              Because `Ember.Application` inherits from `Ember.Namespace`, any classes
+              you create will have useful string representations when calling `toString()`.
+              See the `Ember.Namespace` documentation for more information.
+
+              While you can think of your `Ember.Application` as a container that holds the
+              other classes in your application, there are several other responsibilities
+              going on under-the-hood that you may want to understand.
+
+              ### Event Delegation
+
+              Ember uses a technique called _event delegation_. This allows the framework
+              to set up a global, shared event listener instead of requiring each view to
+              do it manually. For example, instead of each view registering its own
+              `mousedown` listener on its associated element, Ember sets up a `mousedown`
+              listener on the `body`.
+
+              If a `mousedown` event occurs, Ember will look at the target of the event and
+              start walking up the DOM node tree, finding corresponding views and invoking
+              their `mouseDown` method as it goes.
+
+              `Ember.Application` has a number of default events that it listens for, as
+              well as a mapping from lowercase events to camel-cased view method names. For
+              example, the `keypress` event causes the `keyPress` method on the view to be
+              called, the `dblclick` event causes `doubleClick` to be called, and so on.
+
+              If there is a bubbling browser event that Ember does not listen for by
+              default, you can specify custom events and their corresponding view method
+              names by setting the application's `customEvents` property:
+
+              ```javascript
+              App = Ember.Application.create({
+                customEvents: {
+                  // add support for the paste event
+                  paste: &quot;paste&quot;
+                }
+              });
+              ```
+
+              By default, the application sets up these event listeners on the document
+              body. However, in cases where you are embedding an Ember application inside
+              an existing page, you may want it to set up the listeners on an element
+              inside the body.
+
+              For example, if only events inside a DOM element with the ID of `ember-app`
+              should be delegated, set your application's `rootElement` property:
+
+              ```javascript
+              window.App = Ember.Application.create({
+                rootElement: '#ember-app'
+              });
+              ```
+
+              The `rootElement` can be either a DOM element or a jQuery-compatible selector
+              string. Note that *views appended to the DOM outside the root element will
+              not receive events.* If you specify a custom root element, make sure you only
+              append views inside it!
+
+              To learn more about the advantages of event delegation and the Ember view
+              layer, and a list of the event listeners that are setup by default, visit the
+              [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation).
+
+              ### Initializers
+
+              Libraries on top of Ember can add initializers, like so:
+
+              ```javascript
+              Ember.Application.initializer({
+                name: 'api-adapter',
+
+                initialize: function(container, application) {
+                  application.register('api-adapter:main', ApiAdapter);
+                }
+              });
+              ```
+
+              Initializers provide an opportunity to access the container, which
+              organizes the different components of an Ember application. Additionally
+              they provide a chance to access the instantiated application. Beyond
+              being used for libraries, initializers are also a great way to organize
+              dependency injection or setup in your own application.
+
+              ### Routing
+
+              In addition to creating your application's router, `Ember.Application` is
+              also responsible for telling the router when to start routing. Transitions
+              between routes can be logged with the `LOG_TRANSITIONS` flag, and more
+              detailed intra-transition logging can be logged with
+              the `LOG_TRANSITIONS_INTERNAL` flag:
+
+              ```javascript
+              window.App = Ember.Application.create({
+                LOG_TRANSITIONS: true, // basic logging of successful transitions
+                LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps
+              });
+              ```
+
+              By default, the router will begin trying to translate the current URL into
+              application state once the browser emits the `DOMContentReady` event. If you
+              need to defer routing, you can call the application's `deferReadiness()`
+              method. Once routing can begin, call the `advanceReadiness()` method.
+
+              If there is any setup required before routing begins, you can implement a
+              `ready()` method on your app that will be invoked immediately before routing
+              begins.
+              ```
+
+              @class Application
+              @namespace Ember
+              @extends Ember.Namespace
+            */
+
+        var Application = Namespace.extend(DeferredMixin, {
+            _suppressDeferredDeprecation: true,
+
+            /**
+                    The root DOM element of the Application. This can be specified as an
+                    element or a
+                    [jQuery-compatible selector string](http://api.jquery.com/category/selectors/).
+
+                    This is the element that will be passed to the Application's,
+                    `eventDispatcher`, which sets up the listeners for event delegation. Every
+                    view in your application should be a child of the element you specify here.
+
+                    @property rootElement
+                    @type DOMElement
+                    @default 'body'
+                  */
+            rootElement: 'body',
+
+            /**
+                    The `Ember.EventDispatcher` responsible for delegating events to this
+                    application's views.
+
+                    The event dispatcher is created by the application at initialization time
+                    and sets up event listeners on the DOM element described by the
+                    application's `rootElement` property.
+
+                    See the documentation for `Ember.EventDispatcher` for more information.
+
+                    @property eventDispatcher
+                    @type Ember.EventDispatcher
+                    @default null
+                  */
+            eventDispatcher: null,
+
+            /**
+                    The DOM events for which the event dispatcher should listen.
+
+                    By default, the application's `Ember.EventDispatcher` listens
+                    for a set of standard DOM events, such as `mousedown` and
+                    `keyup`, and delegates them to your application's `Ember.View`
+                    instances.
+
+                    If you would like additional bubbling events to be delegated to your
+                    views, set your `Ember.Application`'s `customEvents` property
+                    to a hash containing the DOM event name as the key and the
+                    corresponding view method name as the value. For example:
+
+                    ```javascript
+                    App = Ember.Application.create({
+                      customEvents: {
+                        // add support for the paste event
+                        paste: &quot;paste&quot;
+                      }
+                    });
+                    ```
+
+                    @property customEvents
+                    @type Object
+                    @default null
+                  */
+            customEvents: null,
+
+            // Start off the number of deferrals at 1. This will be
+            // decremented by the Application's own `initialize` method.
+            _readinessDeferrals: 1,
+
+            init: function() {
+                if (!this.$) {
+                    this.$ = jQuery;
+                }
+                this.__container__ = this.buildContainer();
+
+                this.Router = this.defaultRouter();
+
+                this._super();
+
+                this.scheduleInitialize();
+
+                Ember.libraries.registerCoreLibrary('Handlebars', EmberHandlebars.VERSION);
+                Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery);
+
+                if ( Ember.LOG_VERSION ) {
+                    Ember.LOG_VERSION = false; // we only need to see this once per Application#init
+
+                    var nameLengths = EnumerableUtils.map(Ember.libraries, function(item) {
+                        return get(item, &quot;name.length&quot;);
+                    });
+
+                    var maxNameLength = Math.max.apply(this, nameLengths);
+
+                    Ember.debug('-------------------------------');
+                    Ember.libraries.each(function(name, version) {
+                        var spaces = new Array(maxNameLength - name.length + 1).join(&quot; &quot;);
+                        Ember.debug([name, spaces, ' : ', version].join(&quot;&quot;));
+                    });
+                    Ember.debug('-------------------------------');
+                }
+            },
+
+            /**
+                    Build the container for the current application.
+
+                    Also register a default application view in case the application
+                    itself does not.
+
+                    @private
+                    @method buildContainer
+                    @return {Ember.Container} the configured container
+                  */
+            buildContainer: function() {
+                var container = this.__container__ = Application.buildContainer(this);
+
+                return container;
+            },
+
+            /**
+                    If the application has not opted out of routing and has not explicitly
+                    defined a router, supply a default router for the application author
+                    to configure.
+
+                    This allows application developers to do:
+
+                    ```javascript
+                    var App = Ember.Application.create();
+
+                    App.Router.map(function() {
+                      this.resource('posts');
+                    });
+                    ```
+
+                    @private
+                    @method defaultRouter
+                    @return {Ember.Router} the default router
+                  */
+
+            defaultRouter: function() {
+                if (this.Router === false) {
+                    return;
+                }
+                var container = this.__container__;
+
+                if (this.Router) {
+                    container.unregister('router:main');
+                    container.register('router:main', this.Router);
+                }
+
+                return container.lookupFactory('router:main');
+            },
+
+            /**
+                    Automatically initialize the application once the DOM has
+                    become ready.
+
+                    The initialization itself is scheduled on the actions queue
+                    which ensures that application loading finishes before
+                    booting.
+
+                    If you are asynchronously loading code, you should call
+                    `deferReadiness()` to defer booting, and then call
+                    `advanceReadiness()` once all of your code has finished
+                    loading.
+
+                    @private
+                    @method scheduleInitialize
+                  */
+            scheduleInitialize: function() {
+                var self = this;
+
+                if (!this.$ || this.$.isReady) {
+                    run.schedule('actions', self, '_initialize');
+                } else {
+                    this.$().ready(function runInitialize() {
+                        run(self, '_initialize');
+                    });
+                }
+            },
+
+            /**
+                    Use this to defer readiness until some condition is true.
+
+                    Example:
+
+                    ```javascript
+                    App = Ember.Application.create();
+                    App.deferReadiness();
+
+                    jQuery.getJSON(&quot;/auth-token&quot;, function(token) {
+                      App.token = token;
+                      App.advanceReadiness();
+                    });
+                    ```
+
+                    This allows you to perform asynchronous setup logic and defer
+                    booting your application until the setup has finished.
+
+                    However, if the setup requires a loading UI, it might be better
+                    to use the router for this purpose.
+
+                    @method deferReadiness
+                  */
+            deferReadiness: function() {
+                Ember.assert(&quot;You must call deferReadiness on an instance of Ember.Application&quot;, this instanceof Application);
+                Ember.assert(&quot;You cannot defer readiness since the `ready()` hook has already been called.&quot;, this._readinessDeferrals &gt; 0);
+                this._readinessDeferrals++;
+            },
+
+            /**
+                    Call `advanceReadiness` after any asynchronous setup logic has completed.
+                    Each call to `deferReadiness` must be matched by a call to `advanceReadiness`
+                    or the application will never become ready and routing will not begin.
+
+                    @method advanceReadiness
+                    @see {Ember.Application#deferReadiness}
+                  */
+            advanceReadiness: function() {
+                Ember.assert(&quot;You must call advanceReadiness on an instance of Ember.Application&quot;, this instanceof Application);
+                this._readinessDeferrals--;
+
+                if (this._readinessDeferrals === 0) {
+                    run.once(this, this.didBecomeReady);
+                }
+            },
+
+            /**
+                    Registers a factory that can be used for dependency injection (with
+                    `App.inject`) or for service lookup. Each factory is registered with
+                    a full name including two parts: `type:name`.
+
+                    A simple example:
+
+                    ```javascript
+                    var App = Ember.Application.create();
+                    App.Orange  = Ember.Object.extend();
+                    App.register('fruit:favorite', App.Orange);
+                    ```
+
+                    Ember will resolve factories from the `App` namespace automatically.
+                    For example `App.CarsController` will be discovered and returned if
+                    an application requests `controller:cars`.
+
+                    An example of registering a controller with a non-standard name:
+
+                    ```javascript
+                    var App = Ember.Application.create(),
+                        Session  = Ember.Controller.extend();
+
+                    App.register('controller:session', Session);
+
+                    // The Session controller can now be treated like a normal controller,
+                    // despite its non-standard name.
+                    App.ApplicationController = Ember.Controller.extend({
+                      needs: ['session']
+                    });
+                    ```
+
+                    Registered factories are **instantiated** by having `create`
+                    called on them. Additionally they are **singletons**, each time
+                    they are looked up they return the same instance.
+
+                    Some examples modifying that default behavior:
+
+                    ```javascript
+                    var App = Ember.Application.create();
+
+                    App.Person  = Ember.Object.extend();
+                    App.Orange  = Ember.Object.extend();
+                    App.Email   = Ember.Object.extend();
+                    App.session = Ember.Object.create();
+
+                    App.register('model:user', App.Person, {singleton: false });
+                    App.register('fruit:favorite', App.Orange);
+                    App.register('communication:main', App.Email, {singleton: false});
+                    App.register('session', App.session, {instantiate: false});
+                    ```
+
+                    @method register
+                    @param  fullName {String} type:name (e.g., 'model:user')
+                    @param  factory {Function} (e.g., App.Person)
+                    @param  options {Object} (optional) disable instantiation or singleton usage
+                  **/
+            register: function() {
+                var container = this.__container__;
+                container.register.apply(container, arguments);
+            },
+
+            /**
+                    Define a dependency injection onto a specific factory or all factories
+                    of a type.
+
+                    When Ember instantiates a controller, view, or other framework component
+                    it can attach a dependency to that component. This is often used to
+                    provide services to a set of framework components.
+
+                    An example of providing a session object to all controllers:
+
+                    ```javascript
+                    var App = Ember.Application.create(),
+                        Session = Ember.Object.extend({ isAuthenticated: false });
+
+                    // A factory must be registered before it can be injected
+                    App.register('session:main', Session);
+
+                    // Inject 'session:main' onto all factories of the type 'controller'
+                    // with the name 'session'
+                    App.inject('controller', 'session', 'session:main');
+
+                    App.IndexController = Ember.Controller.extend({
+                      isLoggedIn: Ember.computed.alias('session.isAuthenticated')
+                    });
+                    ```
+
+                    Injections can also be performed on specific factories.
+
+                    ```javascript
+                    App.inject(&lt;full_name or type&gt;, &lt;property name&gt;, &lt;full_name&gt;)
+                    App.inject('route', 'source', 'source:main')
+                    App.inject('route:application', 'email', 'model:email')
+                    ```
+
+                    It is important to note that injections can only be performed on
+                    classes that are instantiated by Ember itself. Instantiating a class
+                    directly (via `create` or `new`) bypasses the dependency injection
+                    system.
+
+                    Ember-Data instantiates its models in a unique manner, and consequently
+                    injections onto models (or all models) will not work as expected. Injections
+                    on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS`
+                    to `true`.
+
+                    @method inject
+                    @param  factoryNameOrType {String}
+                    @param  property {String}
+                    @param  injectionName {String}
+                  **/
+            inject: function() {
+                var container = this.__container__;
+                container.injection.apply(container, arguments);
+            },
+
+            /**
+                    Calling initialize manually is not supported.
+
+                    Please see Ember.Application#advanceReadiness and
+                    Ember.Application#deferReadiness.
+
+                    @private
+                    @deprecated
+                    @method initialize
+                   **/
+            initialize: function() {
+                Ember.deprecate('Calling initialize manually is not supported. Please see Ember.Application#advanceReadiness and Ember.Application#deferReadiness');
+            },
+
+            /**
+                    Initialize the application. This happens automatically.
+
+                    Run any initializers and run the application load hook. These hooks may
+                    choose to defer readiness. For example, an authentication hook might want
+                    to defer readiness until the auth token has been retrieved.
+
+                    @private
+                    @method _initialize
+                  */
+            _initialize: function() {
+                if (this.isDestroyed) {
+                    return;
+                }
+
+                // At this point, the App.Router must already be assigned
+                if (this.Router) {
+                    var container = this.__container__;
+                    container.unregister('router:main');
+                    container.register('router:main', this.Router);
+                }
+
+                this.runInitializers();
+                runLoadHooks('application', this);
+
+                // At this point, any initializers or load hooks that would have wanted
+                // to defer readiness have fired. In general, advancing readiness here
+                // will proceed to didBecomeReady.
+                this.advanceReadiness();
+
+                return this;
+            },
+
+            /**
+                    Reset the application. This is typically used only in tests. It cleans up
+                    the application in the following order:
+
+                    1. Deactivate existing routes
+                    2. Destroy all objects in the container
+                    3. Create a new application container
+                    4. Re-route to the existing url
+
+                    Typical Example:
+
+                    ```javascript
+
+                    var App;
+
+                    run(function() {
+                      App = Ember.Application.create();
+                    });
+
+                    module(&quot;acceptance test&quot;, {
+                      setup: function() {
+                        App.reset();
+                      }
+                    });
+
+                    test(&quot;first test&quot;, function() {
+                      // App is freshly reset
+                    });
+
+                    test(&quot;first test&quot;, function() {
+                      // App is again freshly reset
+                    });
+                    ```
+
+                    Advanced Example:
+
+                    Occasionally you may want to prevent the app from initializing during
+                    setup. This could enable extra configuration, or enable asserting prior
+                    to the app becoming ready.
+
+                    ```javascript
+
+                    var App;
+
+                    run(function() {
+                      App = Ember.Application.create();
+                    });
+
+                    module(&quot;acceptance test&quot;, {
+                      setup: function() {
+                        run(function() {
+                          App.reset();
+                          App.deferReadiness();
+                        });
+                      }
+                    });
+
+                    test(&quot;first test&quot;, function() {
+                      ok(true, 'something before app is initialized');
+
+                      run(function() {
+                        App.advanceReadiness();
+                      });
+                      ok(true, 'something after app is initialized');
+                    });
+                    ```
+
+                    @method reset
+                  **/
+            reset: function() {
+                this._readinessDeferrals = 1;
+
+                function handleReset() {
+                    var router = this.__container__.lookup('router:main');
+                    router.reset();
+
+                    run(this.__container__, 'destroy');
+
+                    this.buildContainer();
+
+                    run.schedule('actions', this, function() {
+                        this._initialize();
+                    });
+                }
+
+                run.join(this, handleReset);
+            },
+
+            /**
+                    @private
+                    @method runInitializers
+                  */
+            runInitializers: function() {
+                var initializers = get(this.constructor, 'initializers');
+                var container = this.__container__;
+                var graph = new DAG();
+                var namespace = this;
+                var name, initializer;
+
+                for (name in initializers) {
+                    initializer = initializers[name];
+                    graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after);
+                }
+
+                graph.topsort(function (vertex) {
+                    var initializer = vertex.value;
+                    Ember.assert(&quot;No application initializer named '&quot; + vertex.name + &quot;'&quot;, initializer);
+                    initializer(container, namespace);
+                });
+            },
+
+            /**
+                    @private
+                    @method didBecomeReady
+                  */
+            didBecomeReady: function() {
+                this.setupEventDispatcher();
+                this.ready(); // user hook
+                this.startRouting();
+
+                if (!Ember.testing) {
+                    // Eagerly name all classes that are already loaded
+                    Ember.Namespace.processAll();
+                    Ember.BOOTED = true;
+                }
+
+                this.resolve(this);
+            },
+
+            /**
+                    Setup up the event dispatcher to receive events on the
+                    application's `rootElement` with any registered
+                    `customEvents`.
+
+                    @private
+                    @method setupEventDispatcher
+                  */
+            setupEventDispatcher: function() {
+                var customEvents = get(this, 'customEvents');
+                var rootElement = get(this, 'rootElement');
+                var dispatcher = this.__container__.lookup('event_dispatcher:main');
+
+                set(this, 'eventDispatcher', dispatcher);
+                dispatcher.setup(customEvents, rootElement);
+            },
+
+            /**
+                    If the application has a router, use it to route to the current URL, and
+                    trigger a new call to `route` whenever the URL changes.
+
+                    @private
+                    @method startRouting
+                    @property router {Ember.Router}
+                  */
+            startRouting: function() {
+                var router = this.__container__.lookup('router:main');
+                if (!router) {
+                    return;
+                }
+
+                router.startRouting();
+            },
+
+            handleURL: function(url) {
+                var router = this.__container__.lookup('router:main');
+
+                router.handleURL(url);
+            },
+
+            /**
+                    Called when the Application has become ready.
+                    The call will be delayed until the DOM has become ready.
+
+                    @event ready
+                  */
+            ready: K,
+
+            /**
+                    @deprecated Use 'Resolver' instead
+                    Set this to provide an alternate class to `Ember.DefaultResolver`
+
+
+                    @property resolver
+                  */
+            resolver: null,
+
+            /**
+                    Set this to provide an alternate class to `Ember.DefaultResolver`
+
+                    @property resolver
+                  */
+            Resolver: null,
+
+            willDestroy: function() {
+                Ember.BOOTED = false;
+                // Ensure deactivation of routes before objects are destroyed
+                this.__container__.lookup('router:main').reset();
+
+                this.__container__.destroy();
+            },
+
+            initializer: function(options) {
+                this.constructor.initializer(options);
+            },
+
+            /**
+                    @method then
+                    @private
+                    @deprecated
+                  */
+            then: function() {
+                Ember.deprecate('Do not use `.then` on an instance of Ember.Application.  Please use the `.ready` hook instead.');
+
+                this._super.apply(this, arguments);
+            }
+        });
+
+        Application.reopenClass({
+            initializers: {},
+
+            /**
+                    Initializer receives an object which has the following attributes:
+                    `name`, `before`, `after`, `initialize`. The only required attribute is
+                    `initialize, all others are optional.
+
+                    * `name` allows you to specify under which name the initializer is registered.
+                    This must be a unique name, as trying to register two initializers with the
+                    same name will result in an error.
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: 'namedInitializer',
+                      initialize: function(container, application) {
+                        Ember.debug(&quot;Running namedInitializer!&quot;);
+                      }
+                    });
+                    ```
+
+                    * `before` and `after` are used to ensure that this initializer is ran prior
+                    or after the one identified by the value. This value can be a single string
+                    or an array of strings, referencing the `name` of other initializers.
+
+                    An example of ordering initializers, we create an initializer named `first`:
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: 'first',
+                      initialize: function(container, application) {
+                        Ember.debug(&quot;First initializer!&quot;);
+                      }
+                    });
+
+                    // DEBUG: First initializer!
+                    ```
+
+                    We add another initializer named `second`, specifying that it should run
+                    after the initializer named `first`:
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: 'second',
+                      after: 'first',
+
+                      initialize: function(container, application) {
+                        Ember.debug(&quot;Second initializer!&quot;);
+                      }
+                    });
+
+                    // DEBUG: First initializer!
+                    // DEBUG: Second initializer!
+                    ```
+
+                    Afterwards we add a further initializer named `pre`, this time specifying
+                    that it should run before the initializer named `first`:
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: 'pre',
+                      before: 'first',
+
+                      initialize: function(container, application) {
+                        Ember.debug(&quot;Pre initializer!&quot;);
+                      }
+                    });
+
+                    // DEBUG: Pre initializer!
+                    // DEBUG: First initializer!
+                    // DEBUG: Second initializer!
+                    ```
+
+                    Finally we add an initializer named `post`, specifying it should run after
+                    both the `first` and the `second` initializers:
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: 'post',
+                      after: ['first', 'second'],
+
+                      initialize: function(container, application) {
+                        Ember.debug(&quot;Post initializer!&quot;);
+                      }
+                    });
+
+                    // DEBUG: Pre initializer!
+                    // DEBUG: First initializer!
+                    // DEBUG: Second initializer!
+                    // DEBUG: Post initializer!
+                    ```
+
+                    * `initialize` is a callback function that receives two arguments, `container`
+                    and `application` on which you can operate.
+
+                    Example of using `container` to preload data into the store:
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: &quot;preload-data&quot;,
+
+                      initialize: function(container, application) {
+                        var store = container.lookup('store:main');
+                        store.pushPayload(preloadedData);
+                      }
+                    });
+                    ```
+
+                    Example of using `application` to register an adapter:
+
+                    ```javascript
+                    Ember.Application.initializer({
+                      name: 'api-adapter',
+
+                      initialize: function(container, application) {
+                        application.register('api-adapter:main', ApiAdapter);
+                      }
+                    });
+                    ```
+
+                    @method initializer
+                    @param initializer {Object}
+                   */
+            initializer: function(initializer) {
+                // If this is the first initializer being added to a subclass, we are going to reopen the class
+                // to make sure we have a new `initializers` object, which extends from the parent class' using
+                // prototypal inheritance. Without this, attempting to add initializers to the subclass would
+                // pollute the parent class as well as other subclasses.
+                if (this.superclass.initializers !== undefined &amp;&amp; this.superclass.initializers === this.initializers) {
+                    this.reopenClass({
+                        initializers: create(this.initializers)
+                    });
+                }
+
+                Ember.assert(&quot;The initializer '&quot; + initializer.name + &quot;' has already been registered&quot;, !this.initializers[initializer.name]);
+                Ember.assert(&quot;An initializer cannot be registered without an initialize function&quot;, canInvoke(initializer, 'initialize'));
+
+                this.initializers[initializer.name] = initializer;
+            },
+
+            /**
+                    This creates a container with the default Ember naming conventions.
+
+                    It also configures the container:
+
+                    * registered views are created every time they are looked up (they are
+                      not singletons)
+                    * registered templates are not factories; the registered value is
+                      returned directly.
+                    * the router receives the application as its `namespace` property
+                    * all controllers receive the router as their `target` and `controllers`
+                      properties
+                    * all controllers receive the application as their `namespace` property
+                    * the application view receives the application controller as its
+                      `controller` property
+                    * the application view receives the application template as its
+                      `defaultTemplate` property
+
+                    @private
+                    @method buildContainer
+                    @static
+                    @param {Ember.Application} namespace the application to build the
+                      container for.
+                    @return {Ember.Container} the built container
+                  */
+            buildContainer: function(namespace) {
+                var container = new Container();
+
+                Container.defaultContainer = new DeprecatedContainer(container);
+
+                container.set = set;
+                container.resolver = resolverFor(namespace);
+                container.normalize = container.resolver.normalize;
+                container.describe = container.resolver.describe;
+                container.makeToString = container.resolver.makeToString;
+
+                container.optionsForType('component', {
+                    singleton: false 
+                });
+                container.optionsForType('view', {
+                    singleton: false 
+                });
+                container.optionsForType('template', {
+                    instantiate: false 
+                });
+                container.optionsForType('helper', {
+                    instantiate: false 
+                });
+
+                container.register('application:main', namespace, {
+                    instantiate: false 
+                });
+
+                container.register('controller:basic', Controller, {
+                    instantiate: false 
+                });
+                container.register('controller:object', ObjectController, {
+                    instantiate: false 
+                });
+                container.register('controller:array', ArrayController, {
+                    instantiate: false 
+                });
+                container.register('route:basic', Route, {
+                    instantiate: false 
+                });
+                container.register('event_dispatcher:main', EventDispatcher);
+
+                container.register('router:main', Router);
+                container.injection('router:main', 'namespace', 'application:main');
+
+                container.register('location:auto', AutoLocation);
+                container.register('location:hash', HashLocation);
+                container.register('location:history', HistoryLocation);
+                container.register('location:none', NoneLocation);
+
+                container.injection('controller', 'target', 'router:main');
+                container.injection('controller', 'namespace', 'application:main');
+
+                container.register('-bucket-cache:main', BucketCache);
+                container.injection('router', '_bucketCache', '-bucket-cache:main');
+                container.injection('route', '_bucketCache', '-bucket-cache:main');
+                container.injection('controller', '_bucketCache', '-bucket-cache:main');
+
+                container.injection('route', 'router', 'router:main');
+                container.injection('location', 'rootURL', '-location-setting:root-url');
+
+                // DEBUGGING
+                container.register('resolver-for-debugging:main', container.resolver.__resolver__, {
+                    instantiate: false 
+                });
+                container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main');
+                container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main');
+                // Custom resolver authors may want to register their own ContainerDebugAdapter with this key
+
+                // ES6TODO: resolve this via import once ember-application package is ES6'ed
+                if (!ContainerDebugAdapter) {
+                    ContainerDebugAdapter = requireModule('ember-extension-support/container_debug_adapter')['default'];
+                }
+                container.register('container-debug-adapter:main', ContainerDebugAdapter);
+
+                return container;
+            }
+        });
+
+        /**
+              This function defines the default lookup rules for container lookups:
+
+              * templates are looked up on `Ember.TEMPLATES`
+              * other names are looked up on the application after classifying the name.
+                For example, `controller:post` looks up `App.PostController` by default.
+              * if the default lookup fails, look for registered classes on the container
+
+              This allows the application to register default injections in the container
+              that could be overridden by the normal naming convention.
+
+              @private
+              @method resolverFor
+              @param {Ember.Namespace} namespace the namespace to look for classes
+              @return {*} the resolved value for a given lookup
+            */
+        function resolverFor(namespace) {
+            if (namespace.get('resolver')) {
+                Ember.deprecate('Application.resolver is deprecated in favor of Application.Resolver', false);
+            }
+
+            var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver;
+            var resolver = ResolverClass.create({
+                namespace: namespace
+            });
+
+            function resolve(fullName) {
+                return resolver.resolve(fullName);
+            }
+
+            resolve.describe = function(fullName) {
+                return resolver.lookupDescription(fullName);
+            };
+
+            resolve.makeToString = function(factory, fullName) {
+                return resolver.makeToString(factory, fullName);
+            };
+
+            resolve.normalize = function(fullName) {
+                if (resolver.normalize) {
+                    return resolver.normalize(fullName);
+                } else {
+                    Ember.deprecate('The Resolver should now provide a \'normalize\' function', false);
+                    return fullName;
+                }
+            };
+
+            resolve.__resolver__ = resolver;
+
+            return resolve;
+        }
+
+        __exports__[&quot;default&quot;] = Application;
+    });
+    define(&quot;ember-application/system/dag&quot;,
+    [&quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var EmberError = __dependency1__[&quot;default&quot;];
+
+        function visit(vertex, fn, visited, path) {
+            var name = vertex.name;
+            var vertices = vertex.incoming;
+            var names = vertex.incomingNames;
+            var len = names.length;
+            var i;
+
+            if (!visited) {
+                visited = {};
+            }
+            if (!path) {
+                path = [];
+            }
+            if (visited.hasOwnProperty(name)) {
+                return;
+            }
+            path.push(name);
+            visited[name] = true;
+            for (i = 0; i &lt; len; i++) {
+                visit(vertices[names[i]], fn, visited, path);
+            }
+            fn(vertex, path);
+            path.pop();
+        }
+
+        function DAG() {
+            this.names = [];
+            this.vertices = {};
+        }
+
+        DAG.prototype.add = function(name) {
+            if (!name) {
+                return;
+            }
+            if (this.vertices.hasOwnProperty(name)) {
+                return this.vertices[name];
+            }
+            var vertex = {
+                name: name,
+                incoming: {},
+                incomingNames: [],
+                hasOutgoing: false,
+                value: null
+            };
+            this.vertices[name] = vertex;
+            this.names.push(name);
+            return vertex;
+        };
+
+        DAG.prototype.map = function(name, value) {
+            this.add(name).value = value;
+        };
+
+        DAG.prototype.addEdge = function(fromName, toName) {
+            if (!fromName || !toName || fromName === toName) {
+                return;
+            }
+            var from = this.add(fromName), to = this.add(toName);
+            if (to.incoming.hasOwnProperty(fromName)) {
+                return;
+            }
+            function checkCycle(vertex, path) {
+                if (vertex.name === toName) {
+                    throw new EmberError(&quot;cycle detected: &quot; + toName + &quot; &lt;- &quot; + path.join(&quot; &lt;- &quot;));
+                }
+            }
+            visit(from, checkCycle);
+            from.hasOutgoing = true;
+            to.incoming[fromName] = from;
+            to.incomingNames.push(fromName);
+        };
+
+        DAG.prototype.topsort = function(fn) {
+            var visited = {};
+            var vertices = this.vertices;
+            var names = this.names;
+            var len = names.length;
+            var i, vertex;
+
+            for (i = 0; i &lt; len; i++) {
+                vertex = vertices[names[i]];
+                if (!vertex.hasOutgoing) {
+                    visit(vertex, fn, visited);
+                }
+            }
+        };
+
+        DAG.prototype.addEdges = function(name, value, before, after) {
+            var i;
+            this.map(name, value);
+            if (before) {
+                if (typeof before === 'string') {
+                    this.addEdge(name, before);
+                } else {
+                    for (i = 0; i &lt; before.length; i++) {
+                        this.addEdge(name, before[i]);
+                    }
+                }
+            }
+            if (after) {
+                if (typeof after === 'string') {
+                    this.addEdge(after, name);
+                } else {
+                    for (i = 0; i &lt; after.length; i++) {
+                        this.addEdge(after[i], name);
+                    }
+                }
+            }
+        };
+
+        __exports__[&quot;default&quot;] = DAG;
+    });
+    define(&quot;ember-application/system/deprecated-container&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        function DeprecatedContainer(container) {
+            this._container = container;
+        }
+
+        DeprecatedContainer.deprecate = function(method) {
+            return function() {
+                var container = this._container;
+
+                Ember.deprecate('Using the defaultContainer is no longer supported. [defaultContainer#' + method + '] see: http://git.io/EKPpnA', false);
+                return container[method].apply(container, arguments);
+            };
+        };
+
+        DeprecatedContainer.prototype = {
+            _container: null,
+            lookup: DeprecatedContainer.deprecate('lookup'),
+            resolve: DeprecatedContainer.deprecate('resolve'),
+            register: DeprecatedContainer.deprecate('register')
+        };
+
+        __exports__[&quot;default&quot;] = DeprecatedContainer;
+    });
+    define(&quot;ember-application/system/resolver&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/logger&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/system/namespace&quot;, &quot;ember-handlebars&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-application
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.TEMPLATES, Ember.assert
+        var get = __dependency2__.get;
+        var Logger = __dependency3__[&quot;default&quot;];
+        var classify = __dependency4__.classify;
+        var capitalize = __dependency4__.capitalize;
+        var decamelize = __dependency4__.decamelize;
+        var EmberObject = __dependency5__[&quot;default&quot;];
+        var Namespace = __dependency6__[&quot;default&quot;];
+        var EmberHandlebars = __dependency7__[&quot;default&quot;];
+
+        var Resolver = EmberObject.extend({
+            /**
+                    This will be set to the Application instance when it is
+                    created.
+
+                    @property namespace
+                  */
+            namespace: null,
+            normalize: Ember.required(Function),
+            resolve: Ember.required(Function),
+            parseName: Ember.required(Function),
+            lookupDescription: Ember.required(Function),
+            makeToString: Ember.required(Function),
+            resolveOther: Ember.required(Function),
+            _logLookup: Ember.required(Function)
+        });
+        __exports__.Resolver = Resolver;
+        /**
+              The DefaultResolver defines the default lookup rules to resolve
+              container lookups before consulting the container for registered
+              items:
+
+              * templates are looked up on `Ember.TEMPLATES`
+              * other names are looked up on the application after converting
+                the name. For example, `controller:post` looks up
+                `App.PostController` by default.
+              * there are some nuances (see examples below)
+
+              ### How Resolving Works
+
+              The container calls this object's `resolve` method with the
+              `fullName` argument.
+
+              It first parses the fullName into an object using `parseName`.
+
+              Then it checks for the presence of a type-specific instance
+              method of the form `resolve[Type]` and calls it if it exists.
+              For example if it was resolving 'template:post', it would call
+              the `resolveTemplate` method.
+
+              Its last resort is to call the `resolveOther` method.
+
+              The methods of this object are designed to be easy to override
+              in a subclass. For example, you could enhance how a template
+              is resolved like so:
+
+              ```javascript
+              App = Ember.Application.create({
+                Resolver: Ember.DefaultResolver.extend({
+                  resolveTemplate: function(parsedName) {
+                    var resolvedTemplate = this._super(parsedName);
+                    if (resolvedTemplate) { return resolvedTemplate; }
+                    return Ember.TEMPLATES['not_found'];
+                  }
+                })
+              });
+              ```
+
+              Some examples of how names are resolved:
+
+              ```
+              'template:post' //=&gt; Ember.TEMPLATES['post']
+              'template:posts/byline' //=&gt; Ember.TEMPLATES['posts/byline']
+              'template:posts.byline' //=&gt; Ember.TEMPLATES['posts/byline']
+              'template:blogPost' //=&gt; Ember.TEMPLATES['blogPost']
+                                  //   OR
+                                  //   Ember.TEMPLATES['blog_post']
+              'controller:post' //=&gt; App.PostController
+              'controller:posts.index' //=&gt; App.PostsIndexController
+              'controller:blog/post' //=&gt; Blog.PostController
+              'controller:basic' //=&gt; Ember.Controller
+              'route:post' //=&gt; App.PostRoute
+              'route:posts.index' //=&gt; App.PostsIndexRoute
+              'route:blog/post' //=&gt; Blog.PostRoute
+              'route:basic' //=&gt; Ember.Route
+              'view:post' //=&gt; App.PostView
+              'view:posts.index' //=&gt; App.PostsIndexView
+              'view:blog/post' //=&gt; Blog.PostView
+              'view:basic' //=&gt; Ember.View
+              'foo:post' //=&gt; App.PostFoo
+              'model:post' //=&gt; App.Post
+              ```
+
+              @class DefaultResolver
+              @namespace Ember
+              @extends Ember.Object
+            */
+
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            /**
+                    This will be set to the Application instance when it is
+                    created.
+
+                    @property namespace
+                  */
+            namespace: null,
+
+            normalize: function(fullName) {
+                var split = fullName.split(':', 2),
+                type = split[0],
+                name = split[1];
+
+                Ember.assert(&quot;Tried to normalize a container name without a colon (:) in it. You probably tried to lookup a name that did not contain a type, a colon, and a name. A proper lookup name would be `view:post`.&quot;, split.length === 2);
+
+                if (type !== 'template') {
+                    var result = name;
+
+                    if (result.indexOf('.') &gt; -1) {
+                        result = result.replace(/\.(.)/g, function(m) {
+                            return m.charAt(1).toUpperCase();
+                        });
+                    }
+
+                    if (name.indexOf('_') &gt; -1) {
+                        result = result.replace(/_(.)/g, function(m) {
+                            return m.charAt(1).toUpperCase();
+                        });
+                    }
+
+                    return type + ':' + result;
+                } else {
+                    return fullName;
+                }
+            },
+
+
+            /**
+                    This method is called via the container's resolver method.
+                    It parses the provided `fullName` and then looks up and
+                    returns the appropriate template or class.
+
+                    @method resolve
+                    @param {String} fullName the lookup string
+                    @return {Object} the resolved factory
+                  */
+            resolve: function(fullName) {
+                var parsedName = this.parseName(fullName),
+                resolveMethodName = parsedName.resolveMethodName,
+                resolved;
+
+                if (!(parsedName.name &amp;&amp; parsedName.type)) {
+                    throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` ');
+                }
+
+                if (this[resolveMethodName]) {
+                    resolved = this[resolveMethodName](parsedName);
+                }
+
+                if (!resolved) {
+                    resolved = this.resolveOther(parsedName);
+                }
+
+                if (parsedName.root &amp;&amp; parsedName.root.LOG_RESOLVER) {
+                    this._logLookup(resolved, parsedName);
+                }
+
+                return resolved;
+            },
+            /**
+                    Convert the string name of the form 'type:name' to
+                    a Javascript object with the parsed aspects of the name
+                    broken out.
+
+                    @protected
+                    @param {String} fullName the lookup string
+                    @method parseName
+                  */
+            parseName: function(fullName) {
+                var nameParts = fullName.split(':'),
+                type = nameParts[0], fullNameWithoutType = nameParts[1],
+                name = fullNameWithoutType,
+                namespace = get(this, 'namespace'),
+                root = namespace;
+
+                if (type !== 'template' &amp;&amp; name.indexOf('/') !== -1) {
+                    var parts = name.split('/');
+                    name = parts[parts.length - 1];
+                    var namespaceName = capitalize(parts.slice(0, -1).join('.'));
+                    root = Namespace.byName(namespaceName);
+
+                    Ember.assert('You are looking for a ' + name + ' ' + type + ' in the ' + namespaceName + ' namespace, but the namespace could not be found', root);
+                }
+
+                return {
+                    fullName: fullName,
+                    type: type,
+                    fullNameWithoutType: fullNameWithoutType,
+                    name: name,
+                    root: root,
+                    resolveMethodName: 'resolve' + classify(type)
+                };
+            },
+
+            /**
+                    Returns a human-readable description for a fullName. Used by the
+                    Application namespace in assertions to describe the
+                    precise name of the class that Ember is looking for, rather than
+                    container keys.
+
+                    @protected
+                    @param {String} fullName the lookup string
+                    @method lookupDescription
+                  */
+            lookupDescription: function(fullName) {
+                var parsedName = this.parseName(fullName);
+
+                if (parsedName.type === 'template') {
+                    return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/');
+                }
+
+                var description = parsedName.root + '.' + classify(parsedName.name);
+                if (parsedName.type !== 'model') {
+                    description += classify(parsedName.type);
+                }
+
+                return description;
+            },
+
+            makeToString: function(factory, fullName) {
+                return factory.toString();
+            },
+            /**
+                    Given a parseName object (output from `parseName`), apply
+                    the conventions expected by `Ember.Router`
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method useRouterNaming
+                  */
+            useRouterNaming: function(parsedName) {
+                parsedName.name = parsedName.name.replace(/\./g, '_');
+                if (parsedName.name === 'basic') {
+                    parsedName.name = '';
+                }
+            },
+            /**
+                    Look up the template in Ember.TEMPLATES
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveTemplate
+                  */
+            resolveTemplate: function(parsedName) {
+                var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/');
+
+                if (Ember.TEMPLATES[templateName]) {
+                    return Ember.TEMPLATES[templateName];
+                }
+
+                templateName = decamelize(templateName);
+                if (Ember.TEMPLATES[templateName]) {
+                    return Ember.TEMPLATES[templateName];
+                }
+            },
+            /**
+                    Lookup the view using `resolveOther`
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveView
+                  */
+            resolveView: function(parsedName) {
+                this.useRouterNaming(parsedName);
+                return this.resolveOther(parsedName);
+            },
+            /**
+                    Lookup the controller using `resolveOther`
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveController
+                  */
+            resolveController: function(parsedName) {
+                this.useRouterNaming(parsedName);
+                return this.resolveOther(parsedName);
+            },
+            /**
+                    Lookup the route using `resolveOther`
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveRoute
+                  */
+            resolveRoute: function(parsedName) {
+                this.useRouterNaming(parsedName);
+                return this.resolveOther(parsedName);
+            },
+
+            /**
+                    Lookup the model on the Application namespace
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveModel
+                  */
+            resolveModel: function(parsedName) {
+                var className = classify(parsedName.name);
+                var factory = get(parsedName.root, className);
+
+                if (factory) {
+                    return factory;
+                }
+            },
+            /**
+                    Look up the specified object (from parsedName) on the appropriate
+                    namespace (usually on the Application)
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveHelper
+                  */
+            resolveHelper: function(parsedName) {
+                return this.resolveOther(parsedName) || EmberHandlebars.helpers[parsedName.fullNameWithoutType];
+            },
+            /**
+                    Look up the specified object (from parsedName) on the appropriate
+                    namespace (usually on the Application)
+
+                    @protected
+                    @param {Object} parsedName a parseName object with the parsed
+                      fullName lookup string
+                    @method resolveOther
+                  */
+            resolveOther: function(parsedName) {
+                var className = classify(parsedName.name) + classify(parsedName.type);
+                var factory = get(parsedName.root, className);
+                if (factory) {
+                    return factory;
+                }
+            },
+
+            /**
+                   @method _logLookup
+                   @param {Boolean} found
+                   @param {Object} parsedName
+                   @private
+                  */
+            _logLookup: function(found, parsedName) {
+                var symbol, padding;
+
+                if (found) {
+                    symbol = '[✓]';
+                } else {
+                    symbol = '[ ]';
+                }
+
+                if (parsedName.fullName.length &gt; 60) {
+                    padding = '.';
+                } else {
+                    padding = new Array(60 - parsedName.fullName.length).join('.');
+                }
+
+                Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName));
+            }
+        });
+    });
+    define(&quot;ember-debug&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/logger&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__) {
+        &quot;use strict&quot;;
+        /*global __fail__*/
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var EmberError = __dependency2__[&quot;default&quot;];
+        var Logger = __dependency3__[&quot;default&quot;];
+
+        /**
+            Ember Debug
+
+            @module ember
+            @submodule ember-debug
+            */
+
+        /**
+            @class Ember
+            */
+
+        /**
+              Define an assertion that will throw an exception if the condition is not
+              met. Ember build tools will remove any calls to `Ember.assert()` when
+              doing a production build. Example:
+
+              ```javascript
+              // Test for truthiness
+              Ember.assert('Must pass a valid object', obj);
+
+              // Fail unconditionally
+              Ember.assert('This code path should never be run');
+              ```
+
+              @method assert
+              @param {String} desc A description of the assertion. This will become
+                the text of the Error thrown if the assertion fails.
+              @param {Boolean} test Must be truthy for the assertion to pass. If
+                falsy, an exception will be thrown.
+            */
+        Ember.assert = function(desc, test) {
+            if (!test) {
+                throw new EmberError(&quot;Assertion Failed: &quot; + desc);
+            }
+        };
+
+
+        /**
+              Display a warning with the provided message. Ember build tools will
+              remove any calls to `Ember.warn()` when doing a production build.
+
+              @method warn
+              @param {String} message A warning to display.
+              @param {Boolean} test An optional boolean. If falsy, the warning
+                will be displayed.
+            */
+        Ember.warn = function(message, test) {
+            if (!test) {
+                Logger.warn(&quot;WARNING: &quot; + message);
+                if ('trace' in Logger) 
+                    Logger.trace();
+            }
+        };
+
+        /**
+              Display a debug notice. Ember build tools will remove any calls to
+              `Ember.debug()` when doing a production build.
+
+              ```javascript
+              Ember.debug('I\'m a debug notice!');
+              ```
+
+              @method debug
+              @param {String} message A debug message to display.
+            */
+        Ember.debug = function(message) {
+            Logger.debug(&quot;DEBUG: &quot; + message);
+        };
+
+        /**
+              Display a deprecation warning with the provided message and a stack trace
+              (Chrome and Firefox only). Ember build tools will remove any calls to
+              `Ember.deprecate()` when doing a production build.
+
+              @method deprecate
+              @param {String} message A description of the deprecation.
+              @param {Boolean} test An optional boolean. If falsy, the deprecation
+                will be displayed.
+            */
+        Ember.deprecate = function(message, test) {
+            if (test) {
+                return;
+            }
+
+            if (Ember.ENV.RAISE_ON_DEPRECATION) {
+                throw new EmberError(message);
+            }
+
+            var error;
+
+            // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome
+            try {
+                __fail__.fail();
+            } catch (e) {
+                error = e;
+            }
+
+            if (Ember.LOG_STACKTRACE_ON_DEPRECATION &amp;&amp; error.stack) {
+                var stack, stackStr = '';
+                if (error['arguments']) {
+                    // Chrome
+                    stack = error.stack.replace(/^\s+at\s+/gm, '').
+                    replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2').
+                    replace(/^Object.&lt;anonymous&gt;\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n');
+                    stack.shift();
+                } else {
+                    // Firefox
+                    stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').
+                    replace(/^\(/gm, '{anonymous}(').split('\n');
+                }
+
+                stackStr = &quot;\n    &quot; + stack.slice(2).join(&quot;\n    &quot;);
+                message = message + stackStr;
+            }
+
+            Logger.warn(&quot;DEPRECATION: &quot; + message);
+        };
+
+
+
+        /**
+              Alias an old, deprecated method with its new counterpart.
+
+              Display a deprecation warning with the provided message and a stack trace
+              (Chrome and Firefox only) when the assigned method is called.
+
+              Ember build tools will not remove calls to `Ember.deprecateFunc()`, though
+              no warnings will be shown in production.
+
+              ```javascript
+              Ember.oldMethod = Ember.deprecateFunc('Please use the new, updated method', Ember.newMethod);
+              ```
+
+              @method deprecateFunc
+              @param {String} message A description of the deprecation.
+              @param {Function} func The new function called to replace its deprecated counterpart.
+              @return {Function} a new function that wrapped the original function with a deprecation warning
+            */
+        Ember.deprecateFunc = function(message, func) {
+            return function() {
+                Ember.deprecate(message);
+                return func.apply(this, arguments);
+            };
+        };
+
+
+        /**
+              Run a function meant for debugging. Ember build tools will remove any calls to
+              `Ember.runInDebug()` when doing a production build.
+
+              ```javascript
+              Ember.runInDebug(function() {
+                Ember.Handlebars.EachView.reopen({
+                  didInsertElement: function() {
+                    console.log('I\'m happy');
+                  }
+                });
+              });
+              ```
+
+              @method runInDebug
+              @param {Function} func The function to be executed.
+              @since 1.5.0
+            */
+        Ember.runInDebug = function(func) {
+            func();
+        };
+
+        // Inform the developer about the Ember Inspector if not installed.
+        if (!Ember.testing) {
+            var isFirefox = typeof InstallTrigger !== 'undefined';
+            var isChrome = !!window.chrome &amp;&amp; !window.opera;
+
+            if (typeof window !== 'undefined' &amp;&amp; (isFirefox || isChrome) &amp;&amp; window.addEventListener) {
+                window.addEventListener(&quot;load&quot;, function() {
+                    if (document.documentElement &amp;&amp; document.documentElement.dataset &amp;&amp; !document.documentElement.dataset.emberExtension) {
+                        var downloadURL;
+
+                        if (isChrome) {
+                            downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi';
+                        } else if (isFirefox) {
+                            downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/';
+                        }
+
+                        Ember.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL);
+                    }
+                }, false);
+            }
+        }
+    });
+    define(&quot;ember-extension-support&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-extension-support/data_adapter&quot;, &quot;ember-extension-support/container_debug_adapter&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__) {
+        &quot;use strict&quot;;
+        /**
+            Ember Extension Support
+
+            @module ember
+            @submodule ember-extension-support
+            @requires ember-application
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var DataAdapter = __dependency2__[&quot;default&quot;];
+        var ContainerDebugAdapter = __dependency3__[&quot;default&quot;];
+
+        Ember.DataAdapter = DataAdapter;
+        Ember.ContainerDebugAdapter = ContainerDebugAdapter;
+    });
+    define(&quot;ember-extension-support/container_debug_adapter&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/namespace&quot;, &quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var emberA = __dependency2__.A;
+        var typeOf = __dependency3__.typeOf;
+        var dasherize = __dependency4__.dasherize;
+        var classify = __dependency4__.classify;
+        var Namespace = __dependency5__[&quot;default&quot;];
+        var EmberObject = __dependency6__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-extension-support
+            */
+
+        /**
+              The `ContainerDebugAdapter` helps the container and resolver interface
+              with tools that debug Ember such as the
+              [Ember Extension](https://github.com/tildeio/ember-extension)
+              for Chrome and Firefox.
+
+              This class can be extended by a custom resolver implementer
+              to override some of the methods with library-specific code.
+
+              The methods likely to be overridden are:
+
+              * `canCatalogEntriesByType`
+              * `catalogEntriesByType`
+
+              The adapter will need to be registered
+              in the application's container as `container-debug-adapter:main`
+
+              Example:
+
+              ```javascript
+              Application.initializer({
+                name: &quot;containerDebugAdapter&quot;,
+
+                initialize: function(container, application) {
+                  application.register('container-debug-adapter:main', require('app/container-debug-adapter'));
+                }
+              });
+              ```
+
+              @class ContainerDebugAdapter
+              @namespace Ember
+              @extends EmberObject
+              @since 1.5.0
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            /**
+                    The container of the application being debugged.
+                    This property will be injected
+                    on creation.
+
+                    @property container
+                    @default null
+                  */
+            container: null,
+
+            /**
+                    The resolver instance of the application
+                    being debugged. This property will be injected
+                    on creation.
+
+                    @property resolver
+                    @default null
+                  */
+            resolver: null,
+
+            /**
+                    Returns true if it is possible to catalog a list of available
+                    classes in the resolver for a given type.
+
+                    @method canCatalogEntriesByType
+                    @param {string} type The type. e.g. &quot;model&quot;, &quot;controller&quot;, &quot;route&quot;
+                    @return {boolean} whether a list is available for this type.
+                  */
+            canCatalogEntriesByType: function(type) {
+                if (type === 'model' || type === 'template') 
+                    return false;
+                return true;
+            },
+
+            /**
+                    Returns the available classes a given type.
+
+                    @method catalogEntriesByType
+                    @param {string} type The type. e.g. &quot;model&quot;, &quot;controller&quot;, &quot;route&quot;
+                    @return {Array} An array of strings.
+                  */
+            catalogEntriesByType: function(type) {
+                var namespaces = emberA(Namespace.NAMESPACES), types = emberA(), self = this;
+                var typeSuffixRegex = new RegExp(classify(type) + &quot;$&quot;);
+
+                namespaces.forEach(function(namespace) {
+                    if (namespace !== Ember) {
+                        for (var key in namespace) {
+                            if (!namespace.hasOwnProperty(key)) {
+                                continue;
+                            }
+                            if (typeSuffixRegex.test(key)) {
+                                var klass = namespace[key];
+                                if (typeOf(klass) === 'class') {
+                                    types.push(dasherize(key.replace(typeSuffixRegex, '')));
+                                }
+                            }
+                        }
+                    }
+                });
+                return types;
+            }
+        });
+    });
+    define(&quot;ember-extension-support/data_adapter&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/namespace&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;ember-application/system/application&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var get = __dependency2__.get;
+        var run = __dependency3__[&quot;default&quot;];
+        var dasherize = __dependency4__.dasherize;
+        var Namespace = __dependency5__[&quot;default&quot;];
+        var EmberObject = __dependency6__[&quot;default&quot;];
+        var emberA = __dependency7__.A;
+        var Application = __dependency8__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-extension-support
+            */
+
+        /**
+              The `DataAdapter` helps a data persistence library
+              interface with tools that debug Ember such
+              as the [Ember Extension](https://github.com/tildeio/ember-extension)
+              for Chrome and Firefox.
+
+              This class will be extended by a persistence library
+              which will override some of the methods with
+              library-specific code.
+
+              The methods likely to be overridden are:
+
+              * `getFilters`
+              * `detect`
+              * `columnsForType`
+              * `getRecords`
+              * `getRecordColumnValues`
+              * `getRecordKeywords`
+              * `getRecordFilterValues`
+              * `getRecordColor`
+              * `observeRecord`
+
+              The adapter will need to be registered
+              in the application's container as `dataAdapter:main`
+
+              Example:
+
+              ```javascript
+              Application.initializer({
+                name: &quot;data-adapter&quot;,
+
+                initialize: function(container, application) {
+                  application.register('data-adapter:main', DS.DataAdapter);
+                }
+              });
+              ```
+
+              @class DataAdapter
+              @namespace Ember
+              @extends EmberObject
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            init: function() {
+                this._super();
+                this.releaseMethods = emberA();
+            },
+
+            /**
+                    The container of the application being debugged.
+                    This property will be injected
+                    on creation.
+
+                    @property container
+                    @default null
+                    @since 1.3.0
+                  */
+            container: null,
+
+
+            /**
+                    The container-debug-adapter which is used
+                    to list all models.
+
+                    @property containerDebugAdapter
+                    @default undefined
+                    @since 1.5.0
+                  **/
+            containerDebugAdapter: undefined,
+
+            /**
+                    Number of attributes to send
+                    as columns. (Enough to make the record
+                    identifiable).
+
+                    @private
+                    @property attributeLimit
+                    @default 3
+                    @since 1.3.0
+                  */
+            attributeLimit: 3,
+
+            /**
+                    Stores all methods that clear observers.
+                    These methods will be called on destruction.
+
+                    @private
+                    @property releaseMethods
+                    @since 1.3.0
+                  */
+            releaseMethods: emberA(),
+
+            /**
+                    Specifies how records can be filtered.
+                    Records returned will need to have a `filterValues`
+                    property with a key for every name in the returned array.
+
+                    @public
+                    @method getFilters
+                    @return {Array} List of objects defining filters.
+                     The object should have a `name` and `desc` property.
+                  */
+            getFilters: function() {
+                return emberA();
+            },
+
+            /**
+                    Fetch the model types and observe them for changes.
+
+                    @public
+                    @method watchModelTypes
+
+                    @param {Function} typesAdded Callback to call to add types.
+                    Takes an array of objects containing wrapped types (returned from `wrapModelType`).
+
+                    @param {Function} typesUpdated Callback to call when a type has changed.
+                    Takes an array of objects containing wrapped types.
+
+                    @return {Function} Method to call to remove all observers
+                  */
+            watchModelTypes: function(typesAdded, typesUpdated) {
+                var modelTypes = this.getModelTypes(),
+                self = this, typesToSend, releaseMethods = emberA();
+
+                typesToSend = modelTypes.map(function(type) {
+                    var klass = type.klass;
+                    var wrapped = self.wrapModelType(klass, type.name);
+                    releaseMethods.push(self.observeModelType(klass, typesUpdated));
+                    return wrapped;
+                });
+
+                typesAdded(typesToSend);
+
+                var release = function() {
+                    releaseMethods.forEach(function(fn) {
+                        fn();
+                    });
+                    self.releaseMethods.removeObject(release);
+                };
+                this.releaseMethods.pushObject(release);
+                return release;
+            },
+
+            _nameToClass: function(type) {
+                if (typeof type === 'string') {
+                    type = this.container.lookupFactory('model:' + type);
+                }
+                return type;
+            },
+
+            /**
+                    Fetch the records of a given type and observe them for changes.
+
+                    @public
+                    @method watchRecords
+
+                    @param {Function} recordsAdded Callback to call to add records.
+                    Takes an array of objects containing wrapped records.
+                    The object should have the following properties:
+                      columnValues: {Object} key and value of a table cell
+                      object: {Object} the actual record object
+
+                    @param {Function} recordsUpdated Callback to call when a record has changed.
+                    Takes an array of objects containing wrapped records.
+
+                    @param {Function} recordsRemoved Callback to call when a record has removed.
+                    Takes the following parameters:
+                      index: the array index where the records were removed
+                      count: the number of records removed
+
+                    @return {Function} Method to call to remove all observers
+                  */
+            watchRecords: function(type, recordsAdded, recordsUpdated, recordsRemoved) {
+                var self = this, releaseMethods = emberA(), records = this.getRecords(type), release;
+
+                var recordUpdated = function(updatedRecord) {
+                    recordsUpdated([updatedRecord]);
+                };
+
+                var recordsToSend = records.map(function(record) {
+                    releaseMethods.push(self.observeRecord(record, recordUpdated));
+                    return self.wrapRecord(record);
+                });
+
+
+                var contentDidChange = function(array, idx, removedCount, addedCount) {
+                    for (var i = idx; i &lt; idx + addedCount; i++) {
+                        var record = array.objectAt(i);
+                        var wrapped = self.wrapRecord(record);
+                        releaseMethods.push(self.observeRecord(record, recordUpdated));
+                        recordsAdded([wrapped]);
+                    }
+
+                    if (removedCount) {
+                        recordsRemoved(idx, removedCount);
+                    }
+                };
+
+                var observer = {
+                    didChange: contentDidChange,
+                    willChange: Ember.K 
+                };
+                records.addArrayObserver(self, observer);
+
+                release = function() {
+                    releaseMethods.forEach(function(fn) {
+                        fn();
+                    });
+                    records.removeArrayObserver(self, observer);
+                    self.releaseMethods.removeObject(release);
+                };
+
+                recordsAdded(recordsToSend);
+
+                this.releaseMethods.pushObject(release);
+                return release;
+            },
+
+            /**
+                    Clear all observers before destruction
+                    @private
+                    @method willDestroy
+                  */
+            willDestroy: function() {
+                this._super();
+                this.releaseMethods.forEach(function(fn) {
+                    fn();
+                });
+            },
+
+            /**
+                    Detect whether a class is a model.
+
+                    Test that against the model class
+                    of your persistence library
+
+                    @private
+                    @method detect
+                    @param {Class} klass The class to test
+                    @return boolean Whether the class is a model class or not
+                  */
+            detect: function(klass) {
+                return false;
+            },
+
+            /**
+                    Get the columns for a given model type.
+
+                    @private
+                    @method columnsForType
+                    @param {Class} type The model type
+                    @return {Array} An array of columns of the following format:
+                     name: {String} name of the column
+                     desc: {String} Humanized description (what would show in a table column name)
+                  */
+            columnsForType: function(type) {
+                return emberA();
+            },
+
+            /**
+                    Adds observers to a model type class.
+
+                    @private
+                    @method observeModelType
+                    @param {Class} type The model type class
+                    @param {Function} typesUpdated Called when a type is modified.
+                    @return {Function} The function to call to remove observers
+                  */
+
+            observeModelType: function(type, typesUpdated) {
+                var self = this, records = this.getRecords(type);
+
+                var onChange = function() {
+                    typesUpdated([self.wrapModelType(type)]);
+                };
+                var observer = {
+                    didChange: function() {
+                        run.scheduleOnce('actions', this, onChange);
+                    },
+                    willChange: Ember.K
+                };
+
+                records.addArrayObserver(this, observer);
+
+                var release = function() {
+                    records.removeArrayObserver(self, observer);
+                };
+
+                return release;
+            },
+
+
+            /**
+                    Wraps a given model type and observes changes to it.
+
+                    @private
+                    @method wrapModelType
+                    @param {Class} type A model class
+                    @param {String}  Optional name of the class
+                    @return {Object} contains the wrapped type and the function to remove observers
+                    Format:
+                      type: {Object} the wrapped type
+                        The wrapped type has the following format:
+                          name: {String} name of the type
+                          count: {Integer} number of records available
+                          columns: {Columns} array of columns to describe the record
+                          object: {Class} the actual Model type class
+                      release: {Function} The function to remove observers
+                  */
+            wrapModelType: function(type, name) {
+                var release, records = this.getRecords(type),
+                typeToSend, self = this;
+
+                typeToSend = {
+                    name: name || type.toString(),
+                    count: get(records, 'length'),
+                    columns: this.columnsForType(type),
+                    object: type
+                };
+
+
+                return typeToSend;
+            },
+
+
+            /**
+                    Fetches all models defined in the application.
+
+                    @private
+                    @method getModelTypes
+                    @return {Array} Array of model types
+                  */
+            getModelTypes: function() {
+                var types, self = this,
+                containerDebugAdapter = this.get('containerDebugAdapter');
+
+                if (containerDebugAdapter.canCatalogEntriesByType('model')) {
+                    types = containerDebugAdapter.catalogEntriesByType('model');
+                } else {
+                    types = this._getObjectsOnNamespaces();
+                }
+
+                // New adapters return strings instead of classes
+                types = emberA(types).map(function(name) {
+                    return {
+                        klass: self._nameToClass(name),
+                        name: name
+                    };
+                });
+                types = emberA(types).filter(function(type) {
+                    return self.detect(type.klass);
+                });
+
+                return emberA(types);
+            },
+
+            /**
+                    Loops over all namespaces and all objects
+                    attached to them
+
+                    @private
+                    @method _getObjectsOnNamespaces
+                    @return {Array} Array of model type strings
+                  */
+            _getObjectsOnNamespaces: function() {
+                var namespaces = emberA(Namespace.NAMESPACES),
+                types = emberA(),
+                self = this;
+
+                namespaces.forEach(function(namespace) {
+                    for (var key in namespace) {
+                        if (!namespace.hasOwnProperty(key)) {
+                            continue;
+                        }
+                        // Even though we will filter again in `getModelTypes`,
+                        // we should not call `lookupContainer` on non-models
+                        // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`)
+                        if (!self.detect(namespace[key])) {
+                            continue;
+                        }
+                        var name = dasherize(key);
+                        if (!(namespace instanceof Application) &amp;&amp; namespace.toString()) {
+                            name = namespace + '/' + name;
+                        }
+                        types.push(name);
+                    }
+                });
+                return types;
+            },
+
+            /**
+                    Fetches all loaded records for a given type.
+
+                    @private
+                    @method getRecords
+                    @return {Array} An array of records.
+                     This array will be observed for changes,
+                     so it should update when new records are added/removed.
+                  */
+            getRecords: function(type) {
+                return emberA();
+            },
+
+            /**
+                    Wraps a record and observers changes to it.
+
+                    @private
+                    @method wrapRecord
+                    @param {Object} record The record instance.
+                    @return {Object} The wrapped record. Format:
+                    columnValues: {Array}
+                    searchKeywords: {Array}
+                  */
+            wrapRecord: function(record) {
+                var recordToSend = {
+                    object: record 
+                }, columnValues = {}, self = this;
+
+                recordToSend.columnValues = this.getRecordColumnValues(record);
+                recordToSend.searchKeywords = this.getRecordKeywords(record);
+                recordToSend.filterValues = this.getRecordFilterValues(record);
+                recordToSend.color = this.getRecordColor(record);
+
+                return recordToSend;
+            },
+
+            /**
+                    Gets the values for each column.
+
+                    @private
+                    @method getRecordColumnValues
+                    @return {Object} Keys should match column names defined
+                    by the model type.
+                  */
+            getRecordColumnValues: function(record) {
+                return {};
+            },
+
+            /**
+                    Returns keywords to match when searching records.
+
+                    @private
+                    @method getRecordKeywords
+                    @return {Array} Relevant keywords for search.
+                  */
+            getRecordKeywords: function(record) {
+                return emberA();
+            },
+
+            /**
+                    Returns the values of filters defined by `getFilters`.
+
+                    @private
+                    @method getRecordFilterValues
+                    @param {Object} record The record instance
+                    @return {Object} The filter values
+                  */
+            getRecordFilterValues: function(record) {
+                return {};
+            },
+
+            /**
+                    Each record can have a color that represents its state.
+
+                    @private
+                    @method getRecordColor
+                    @param {Object} record The record instance
+                    @return {String} The record's color
+                      Possible options: black, red, blue, green
+                  */
+            getRecordColor: function(record) {
+                return null;
+            },
+
+            /**
+                    Observes all relevant properties and re-sends the wrapped record
+                    when a change occurs.
+
+                    @private
+                    @method observerRecord
+                    @param {Object} record The record instance
+                    @param {Function} recordUpdated The callback to call when a record is updated.
+                    @return {Function} The function to call to remove all observers.
+                  */
+            observeRecord: function(record, recordUpdated) {
+                return function() {};
+            }
+        });
+    });
+    define(&quot;ember-extension-support/initializers&quot;,
+    [],
+    function() {
+        &quot;use strict&quot;;
+
+    });
+    define(&quot;ember-handlebars-compiler&quot;,
+    [&quot;ember-metal/core&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        /* global Handlebars:true */
+
+        /**
+            @module ember
+            @submodule ember-handlebars-compiler
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+
+        // ES6Todo: you'll need to import debugger once debugger is es6'd.
+        if (typeof Ember.assert === 'undefined') {
+            Ember.assert = function() {};
+        }
+        if (typeof Ember.FEATURES === 'undefined') {
+            Ember.FEATURES = {
+                isEnabled: function() {}
+            };
+        }
+
+        var objectCreate = Object.create || function(parent) {
+            function F() {}
+            F.prototype = parent;
+            return new F();
+        };
+
+        // set up for circular references later
+        var View, Component;
+
+        // ES6Todo: when ember-debug is es6'ed import this.
+        // var emberAssert = Ember.assert;
+        var Handlebars = (Ember.imports &amp;&amp; Ember.imports.Handlebars) || (this &amp;&amp; this.Handlebars);
+        if (!Handlebars &amp;&amp; typeof require === 'function') {
+            Handlebars = require('handlebars');
+        }
+
+        Ember.assert(&quot;Ember Handlebars requires Handlebars version 1.0 or 1.1. Include &quot; +
+        &quot;a SCRIPT tag in the HTML HEAD linking to the Handlebars file &quot; +
+        &quot;before you link to Ember.&quot;, Handlebars);
+
+        Ember.assert(&quot;Ember Handlebars requires Handlebars version 1.0 or 1.1, &quot; +
+        &quot;COMPILER_REVISION expected: 4, got: &quot; + Handlebars.COMPILER_REVISION +
+        &quot; - Please note: Builds of master may have other COMPILER_REVISION values.&quot;,
+        Handlebars.COMPILER_REVISION === 4);
+
+        /**
+              Prepares the Handlebars templating library for use inside Ember's view
+              system.
+
+              The `Ember.Handlebars` object is the standard Handlebars library, extended to
+              use Ember's `get()` method instead of direct property access, which allows
+              computed properties to be used inside templates.
+
+              To create an `Ember.Handlebars` template, call `Ember.Handlebars.compile()`.
+              This will return a function that can be used by `Ember.View` for rendering.
+
+              @class Handlebars
+              @namespace Ember
+            */
+        var EmberHandlebars = Ember.Handlebars = objectCreate(Handlebars);
+
+        /**
+              Register a bound helper or custom view helper.
+
+              ## Simple bound helper example
+
+              ```javascript
+              Ember.Handlebars.helper('capitalize', function(value) {
+                return value.toUpperCase();
+              });
+              ```
+
+              The above bound helper can be used inside of templates as follows:
+
+              ```handlebars
+              {{capitalize name}}
+              ```
+
+              In this case, when the `name` property of the template's context changes,
+              the rendered value of the helper will update to reflect this change.
+
+              For more examples of bound helpers, see documentation for
+              `Ember.Handlebars.registerBoundHelper`.
+
+              ## Custom view helper example
+
+              Assuming a view subclass named `App.CalendarView` were defined, a helper
+              for rendering instances of this view could be registered as follows:
+
+              ```javascript
+              Ember.Handlebars.helper('calendar', App.CalendarView):
+              ```
+
+              The above bound helper can be used inside of templates as follows:
+
+              ```handlebars
+              {{calendar}}
+              ```
+
+              Which is functionally equivalent to:
+
+              ```handlebars
+              {{view App.CalendarView}}
+              ```
+
+              Options in the helper will be passed to the view in exactly the same
+              manner as with the `view` helper.
+
+              @method helper
+              @for Ember.Handlebars
+              @param {String} name
+              @param {Function|Ember.View} function or view class constructor
+              @param {String} dependentKeys*
+            */
+        EmberHandlebars.helper = function(name, value) {
+            if (!View) {
+                View = requireModule('ember-views/views/view')['default'];
+            }
+            // ES6TODO: stupid circular dep
+            if (!Component) {
+                Component = requireModule('ember-views/views/component')['default'];
+            }
+            // ES6TODO: stupid circular dep
+
+            Ember.assert(&quot;You tried to register a component named '&quot; + name + &quot;', but component names must include a '-'&quot;, !Component.detect(value) || name.match(/-/));
+
+            if (View.detect(value)) {
+                EmberHandlebars.registerHelper(name, EmberHandlebars.makeViewHelper(value));
+            } else {
+                EmberHandlebars.registerBoundHelper.apply(null, arguments);
+            }
+        };
+
+        /**
+              Returns a helper function that renders the provided ViewClass.
+
+              Used internally by Ember.Handlebars.helper and other methods
+              involving helper/component registration.
+
+              @private
+              @method makeViewHelper
+              @for Ember.Handlebars
+              @param {Function} ViewClass view class constructor
+              @since 1.2.0
+            */
+        EmberHandlebars.makeViewHelper = function(ViewClass) {
+            return function(options) {
+                Ember.assert(&quot;You can only pass attributes (such as name=value) not bare values to a helper for a View found in '&quot; + ViewClass.toString() + &quot;'&quot;, arguments.length &lt; 2);
+                return EmberHandlebars.helpers.view.call(this, ViewClass, options);
+            };
+        };
+
+        /**
+            @class helpers
+            @namespace Ember.Handlebars
+            */
+        EmberHandlebars.helpers = objectCreate(Handlebars.helpers);
+
+        /**
+              Override the the opcode compiler and JavaScript compiler for Handlebars.
+
+              @class Compiler
+              @namespace Ember.Handlebars
+              @private
+              @constructor
+            */
+        EmberHandlebars.Compiler = function() {};
+
+        // Handlebars.Compiler doesn't exist in runtime-only
+        if (Handlebars.Compiler) {
+            EmberHandlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype);
+        }
+
+        EmberHandlebars.Compiler.prototype.compiler = EmberHandlebars.Compiler;
+
+        /**
+              @class JavaScriptCompiler
+              @namespace Ember.Handlebars
+              @private
+              @constructor
+            */
+        EmberHandlebars.JavaScriptCompiler = function() {};
+
+        // Handlebars.JavaScriptCompiler doesn't exist in runtime-only
+        if (Handlebars.JavaScriptCompiler) {
+            EmberHandlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype);
+            EmberHandlebars.JavaScriptCompiler.prototype.compiler = EmberHandlebars.JavaScriptCompiler;
+        }
+
+
+        EmberHandlebars.JavaScriptCompiler.prototype.namespace = &quot;Ember.Handlebars&quot;;
+
+        EmberHandlebars.JavaScriptCompiler.prototype.initializeBuffer = function() {
+            return &quot;''&quot;;
+        };
+
+        /**
+              Override the default buffer for Ember Handlebars. By default, Handlebars
+              creates an empty String at the beginning of each invocation and appends to
+              it. Ember's Handlebars overrides this to append to a single shared buffer.
+
+              @private
+              @method appendToBuffer
+              @param string {String}
+            */
+        EmberHandlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) {
+            return &quot;data.buffer.push(&quot; + string + &quot;);&quot;;
+        };
+
+        // Hacks ahead:
+        // Handlebars presently has a bug where the `blockHelperMissing` hook
+        // doesn't get passed the name of the missing helper name, but rather
+        // gets passed the value of that missing helper evaluated on the current
+        // context, which is most likely `undefined` and totally useless.
+        //
+        // So we alter the compiled template function to pass the name of the helper
+        // instead, as expected.
+        //
+        // This can go away once the following is closed:
+        // https://github.com/wycats/handlebars.js/issues/634
+
+        var DOT_LOOKUP_REGEX = /helpers\.(.*?)\)/,
+        BRACKET_STRING_LOOKUP_REGEX = /helpers\['(.*?)'/,
+        INVOCATION_SPLITTING_REGEX = /(.*blockHelperMissing\.call\(.*)(stack[0-9]+)(,.*)/;
+
+        EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation = function(source) {
+            var helperInvocation = source[source.length - 1],
+            helperName = (DOT_LOOKUP_REGEX.exec(helperInvocation) || BRACKET_STRING_LOOKUP_REGEX.exec(helperInvocation))[1],
+            matches = INVOCATION_SPLITTING_REGEX.exec(helperInvocation);
+
+            source[source.length - 1] = matches[1] + &quot;'&quot; + helperName + &quot;'&quot; + matches[3];
+        };
+
+        var stringifyBlockHelperMissing = EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation;
+
+        var originalBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.blockValue;
+        EmberHandlebars.JavaScriptCompiler.prototype.blockValue = function() {
+            originalBlockValue.apply(this, arguments);
+            stringifyBlockHelperMissing(this.source);
+        };
+
+        var originalAmbiguousBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue;
+        EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue = function() {
+            originalAmbiguousBlockValue.apply(this, arguments);
+            stringifyBlockHelperMissing(this.source);
+        };
+
+        /**
+              Rewrite simple mustaches from `{{foo}}` to `{{bind &quot;foo&quot;}}`. This means that
+              all simple mustaches in Ember's Handlebars will also set up an observer to
+              keep the DOM up to date when the underlying property changes.
+
+              @private
+              @method mustache
+              @for Ember.Handlebars.Compiler
+              @param mustache
+            */
+        EmberHandlebars.Compiler.prototype.mustache = function(mustache) {
+            if (!(mustache.params.length || mustache.hash)) {
+                var id = new Handlebars.AST.IdNode([{
+                    part: '_triageMustache' 
+                }
+                ]);
+
+                // Update the mustache node to include a hash value indicating whether the original node
+                // was escaped. This will allow us to properly escape values when the underlying value
+                // changes and we need to re-render the value.
+                if (!mustache.escaped) {
+                    mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
+                    mustache.hash.pairs.push([&quot;unescaped&quot;, new Handlebars.AST.StringNode(&quot;true&quot;)]);
+                }
+                mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped);
+            }
+
+            return Handlebars.Compiler.prototype.mustache.call(this, mustache);
+        };
+
+        /**
+              Used for precompilation of Ember Handlebars templates. This will not be used
+              during normal app execution.
+
+              @method precompile
+              @for Ember.Handlebars
+              @static
+              @param {String} string The template to precompile
+              @param {Boolean} asObject optional parameter, defaulting to true, of whether or not the
+                                        compiled template should be returned as an Object or a String
+            */
+        EmberHandlebars.precompile = function(string, asObject) {
+            var ast = Handlebars.parse(string);
+
+            var options = {
+                knownHelpers: {
+                    action: true,
+                    unbound: true,
+                    'bind-attr': true,
+                    template: true,
+                    view: true,
+                    _triageMustache: true
+                },
+                data: true,
+                stringParams: true
+            };
+
+            asObject = asObject === undefined ? true : asObject;
+
+            var environment = new EmberHandlebars.Compiler().compile(ast, options);
+            return new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, asObject);
+        };
+
+        // We don't support this for Handlebars runtime-only
+        if (Handlebars.compile) {
+            /**
+                    The entry point for Ember Handlebars. This replaces the default
+                    `Handlebars.compile` and turns on template-local data and String
+                    parameters.
+
+                    @method compile
+                    @for Ember.Handlebars
+                    @static
+                    @param {String} string The template to compile
+                    @return {Function}
+                  */
+            EmberHandlebars.compile = function(string) {
+                var ast = Handlebars.parse(string);
+                var options = {
+                    data: true,
+                    stringParams: true 
+                };
+                var environment = new EmberHandlebars.Compiler().compile(ast, options);
+                var templateSpec = new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
+
+                var template = EmberHandlebars.template(templateSpec);
+                template.isMethod = false; //Make sure we don't wrap templates with ._super
+
+                return template;
+            };
+        }
+
+        __exports__[&quot;default&quot;] = EmberHandlebars;
+    });
+    define(&quot;ember-handlebars&quot;,
+    [&quot;ember-handlebars-compiler&quot;, &quot;ember-metal/core&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-handlebars/loader&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-handlebars/string&quot;, &quot;ember-handlebars/helpers/shared&quot;, &quot;ember-handlebars/helpers/binding&quot;, &quot;ember-handlebars/helpers/collection&quot;, &quot;ember-handlebars/helpers/view&quot;, &quot;ember-handlebars/helpers/unbound&quot;, &quot;ember-handlebars/helpers/debug&quot;, &quot;ember-handlebars/helpers/each&quot;, &quot;ember-handlebars/helpers/template&quot;, &quot;ember-handlebars/helpers/partial&quot;, &quot;ember-handlebars/helpers/yield&quot;, &quot;ember-handlebars/helpers/loc&quot;, &quot;ember-handlebars/controls/checkbox&quot;, &quot;ember-handlebars/controls/select&quot;, &quot;ember-handlebars/controls/text_area&quot;, &quot;ember-handlebars/controls/text_field&quot;, &quot;ember-handlebars/controls/text_support&quot;, &quot;ember-handlebars/controls&quot;, &quot;ember-handlebars/component_lookup&quot;, &quot;ember-handlebars/views/handlebars_bound_view&quot;, &quot;ember-handlebars/views/metamorph_view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __exports__) {
+        &quot;use strict&quot;;
+        var EmberHandlebars = __dependency1__[&quot;default&quot;];
+        var Ember = __dependency2__[&quot;default&quot;];
+        // to add to globals
+
+        var runLoadHooks = __dependency3__.runLoadHooks;
+        var bootstrap = __dependency4__[&quot;default&quot;];
+
+        var normalizePath = __dependency5__.normalizePath;
+        var template = __dependency5__.template;
+        var makeBoundHelper = __dependency5__.makeBoundHelper;
+        var registerBoundHelper = __dependency5__.registerBoundHelper;
+        var resolveHash = __dependency5__.resolveHash;
+        var resolveParams = __dependency5__.resolveParams;
+        var getEscaped = __dependency5__.getEscaped;
+        var handlebarsGet = __dependency5__.handlebarsGet;
+        var evaluateUnboundHelper = __dependency5__.evaluateUnboundHelper;
+        var helperMissingHelper = __dependency5__.helperMissingHelper;
+        var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper;
+
+
+        // side effect of extending StringUtils of htmlSafe
+
+        var resolvePaths = __dependency7__[&quot;default&quot;];
+        var bind = __dependency8__.bind;
+        var _triageMustacheHelper = __dependency8__._triageMustacheHelper;
+        var resolveHelper = __dependency8__.resolveHelper;
+        var bindHelper = __dependency8__.bindHelper;
+        var boundIfHelper = __dependency8__.boundIfHelper;
+        var unboundIfHelper = __dependency8__.unboundIfHelper;
+        var withHelper = __dependency8__.withHelper;
+        var ifHelper = __dependency8__.ifHelper;
+        var unlessHelper = __dependency8__.unlessHelper;
+        var bindAttrHelper = __dependency8__.bindAttrHelper;
+        var bindAttrHelperDeprecated = __dependency8__.bindAttrHelperDeprecated;
+        var bindClasses = __dependency8__.bindClasses;
+
+        var collectionHelper = __dependency9__[&quot;default&quot;];
+        var ViewHelper = __dependency10__.ViewHelper;
+        var viewHelper = __dependency10__.viewHelper;
+        var unboundHelper = __dependency11__[&quot;default&quot;];
+        var logHelper = __dependency12__.logHelper;
+        var debuggerHelper = __dependency12__.debuggerHelper;
+        var EachView = __dependency13__.EachView;
+        var GroupedEach = __dependency13__.GroupedEach;
+        var eachHelper = __dependency13__.eachHelper;
+        var templateHelper = __dependency14__[&quot;default&quot;];
+        var partialHelper = __dependency15__[&quot;default&quot;];
+        var yieldHelper = __dependency16__[&quot;default&quot;];
+        var locHelper = __dependency17__[&quot;default&quot;];
+
+
+        var Checkbox = __dependency18__[&quot;default&quot;];
+        var Select = __dependency19__.Select;
+        var SelectOption = __dependency19__.SelectOption;
+        var SelectOptgroup = __dependency19__.SelectOptgroup;
+        var TextArea = __dependency20__[&quot;default&quot;];
+        var TextField = __dependency21__[&quot;default&quot;];
+        var TextSupport = __dependency22__[&quot;default&quot;];
+        var inputHelper = __dependency23__.inputHelper;
+        var textareaHelper = __dependency23__.textareaHelper;
+
+
+        var ComponentLookup = __dependency24__[&quot;default&quot;];
+        var _HandlebarsBoundView = __dependency25__._HandlebarsBoundView;
+        var SimpleHandlebarsView = __dependency25__.SimpleHandlebarsView;
+        var _wrapMap = __dependency26__._wrapMap;
+        var _SimpleMetamorphView = __dependency26__._SimpleMetamorphView;
+        var _MetamorphView = __dependency26__._MetamorphView;
+        var _Metamorph = __dependency26__._Metamorph;
+
+
+        /**
+            Ember Handlebars
+
+            @module ember
+            @submodule ember-handlebars
+            @requires ember-views
+            */
+
+        // Ember.Handlebars.Globals
+        EmberHandlebars.bootstrap = bootstrap;
+        EmberHandlebars.template = template;
+        EmberHandlebars.makeBoundHelper = makeBoundHelper;
+        EmberHandlebars.registerBoundHelper = registerBoundHelper;
+        EmberHandlebars.resolveHash = resolveHash;
+        EmberHandlebars.resolveParams = resolveParams;
+        EmberHandlebars.resolveHelper = resolveHelper;
+        EmberHandlebars.get = handlebarsGet;
+        EmberHandlebars.getEscaped = getEscaped;
+        EmberHandlebars.evaluateUnboundHelper = evaluateUnboundHelper;
+        EmberHandlebars.bind = bind;
+        EmberHandlebars.bindClasses = bindClasses;
+        EmberHandlebars.EachView = EachView;
+        EmberHandlebars.GroupedEach = GroupedEach;
+        EmberHandlebars.resolvePaths = resolvePaths;
+        EmberHandlebars.ViewHelper = ViewHelper;
+        EmberHandlebars.normalizePath = normalizePath;
+
+
+        // Ember Globals
+        Ember.Handlebars = EmberHandlebars;
+        Ember.ComponentLookup = ComponentLookup;
+        Ember._SimpleHandlebarsView = SimpleHandlebarsView;
+        Ember._HandlebarsBoundView = _HandlebarsBoundView;
+        Ember._SimpleMetamorphView = _SimpleMetamorphView;
+        Ember._MetamorphView = _MetamorphView;
+        Ember._Metamorph = _Metamorph;
+        Ember._metamorphWrapMap = _wrapMap;
+        Ember.TextSupport = TextSupport;
+        Ember.Checkbox = Checkbox;
+        Ember.Select = Select;
+        Ember.SelectOption = SelectOption;
+        Ember.SelectOptgroup = SelectOptgroup;
+        Ember.TextArea = TextArea;
+        Ember.TextField = TextField;
+        Ember.TextSupport = TextSupport;
+
+        // register helpers
+        EmberHandlebars.registerHelper('helperMissing', helperMissingHelper);
+        EmberHandlebars.registerHelper('blockHelperMissing', blockHelperMissingHelper);
+        EmberHandlebars.registerHelper('bind', bindHelper);
+        EmberHandlebars.registerHelper('boundIf', boundIfHelper);
+        EmberHandlebars.registerHelper('_triageMustache', _triageMustacheHelper);
+        EmberHandlebars.registerHelper('unboundIf', unboundIfHelper);
+        EmberHandlebars.registerHelper('with', withHelper);
+        EmberHandlebars.registerHelper('if', ifHelper);
+        EmberHandlebars.registerHelper('unless', unlessHelper);
+        EmberHandlebars.registerHelper('bind-attr', bindAttrHelper);
+        EmberHandlebars.registerHelper('bindAttr', bindAttrHelperDeprecated);
+        EmberHandlebars.registerHelper('collection', collectionHelper);
+        EmberHandlebars.registerHelper(&quot;log&quot;, logHelper);
+        EmberHandlebars.registerHelper(&quot;debugger&quot;, debuggerHelper);
+        EmberHandlebars.registerHelper(&quot;each&quot;, eachHelper);
+        EmberHandlebars.registerHelper(&quot;loc&quot;, locHelper);
+        EmberHandlebars.registerHelper(&quot;partial&quot;, partialHelper);
+        EmberHandlebars.registerHelper(&quot;template&quot;, templateHelper);
+        EmberHandlebars.registerHelper(&quot;yield&quot;, yieldHelper);
+        EmberHandlebars.registerHelper(&quot;view&quot;, viewHelper);
+        EmberHandlebars.registerHelper(&quot;unbound&quot;, unboundHelper);
+        EmberHandlebars.registerHelper(&quot;input&quot;, inputHelper);
+        EmberHandlebars.registerHelper(&quot;textarea&quot;, textareaHelper);
+
+        // run load hooks
+        runLoadHooks('Ember.Handlebars', EmberHandlebars);
+
+        __exports__[&quot;default&quot;] = EmberHandlebars;
+    });
+    define(&quot;ember-handlebars/component_lookup&quot;,
+    [&quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var EmberObject = __dependency1__[&quot;default&quot;];
+
+        var ComponentLookup = EmberObject.extend({
+            lookupFactory: function(name, container) {
+
+                container = container || this.container;
+
+                var fullName = 'component:' + name,
+                templateFullName = 'template:components/' + name,
+                templateRegistered = container &amp;&amp; container.has(templateFullName);
+
+                if (templateRegistered) {
+                    container.injection(fullName, 'layout', templateFullName);
+                }
+
+                var Component = container.lookupFactory(fullName);
+
+                // Only treat as a component if either the component
+                // or a template has been registered.
+                if (templateRegistered || Component) {
+                    if (!Component) {
+                        container.register(fullName, Ember.Component);
+                        Component = container.lookupFactory(fullName);
+                    }
+                    return Component;
+                }
+            }
+        });
+
+        __exports__[&quot;default&quot;] = ComponentLookup;
+    });
+    define(&quot;ember-handlebars/controls&quot;,
+    [&quot;ember-handlebars/controls/checkbox&quot;, &quot;ember-handlebars/controls/text_field&quot;, &quot;ember-handlebars/controls/text_area&quot;, &quot;ember-metal/core&quot;, &quot;ember-handlebars-compiler&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var Checkbox = __dependency1__[&quot;default&quot;];
+        var TextField = __dependency2__[&quot;default&quot;];
+        var TextArea = __dependency3__[&quot;default&quot;];
+
+        var Ember = __dependency4__[&quot;default&quot;];
+        // Ember.assert
+        // var emberAssert = Ember.assert;
+
+        var EmberHandlebars = __dependency5__[&quot;default&quot;];
+        var helpers = EmberHandlebars.helpers;
+        /**
+            @module ember
+            @submodule ember-handlebars-compiler
+            */
+
+        /**
+
+              The `{{input}}` helper inserts an HTML `&lt;input&gt;` tag into the template,
+              with a `type` value of either `text` or `checkbox`. If no `type` is provided,
+              `text` will be the default value applied. The attributes of `{{input}}`
+              match those of the native HTML tag as closely as possible for these two types.
+
+              ## Use as text field
+              An `{{input}}` with no `type` or a `type` of `text` will render an HTML text input.
+              The following HTML attributes can be set via the helper:
+
+             &lt;table&gt;
+              &lt;tr&gt;&lt;td&gt;`readonly`&lt;/td&gt;&lt;td&gt;`required`&lt;/td&gt;&lt;td&gt;`autofocus`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`value`&lt;/td&gt;&lt;td&gt;`placeholder`&lt;/td&gt;&lt;td&gt;`disabled`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`size`&lt;/td&gt;&lt;td&gt;`tabindex`&lt;/td&gt;&lt;td&gt;`maxlength`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`name`&lt;/td&gt;&lt;td&gt;`min`&lt;/td&gt;&lt;td&gt;`max`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`pattern`&lt;/td&gt;&lt;td&gt;`accept`&lt;/td&gt;&lt;td&gt;`autocomplete`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`autosave`&lt;/td&gt;&lt;td&gt;`formaction`&lt;/td&gt;&lt;td&gt;`formenctype`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`formmethod`&lt;/td&gt;&lt;td&gt;`formnovalidate`&lt;/td&gt;&lt;td&gt;`formtarget`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`height`&lt;/td&gt;&lt;td&gt;`inputmode`&lt;/td&gt;&lt;td&gt;`multiple`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`step`&lt;/td&gt;&lt;td&gt;`width`&lt;/td&gt;&lt;td&gt;`form`&lt;/td&gt;&lt;/tr&gt;
+              &lt;tr&gt;&lt;td&gt;`selectionDirection`&lt;/td&gt;&lt;td&gt;`spellcheck`&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
+             &lt;/table&gt;
+
+
+              When set to a quoted string, these values will be directly applied to the HTML
+              element. When left unquoted, these values will be bound to a property on the
+              template's current rendering context (most typically a controller instance).
+
+              ## Unbound:
+
+              ```handlebars
+              {{input value=&quot;http://www.facebook.com&quot;}}
+              ```
+
+
+              ```html
+              &lt;input type=&quot;text&quot; value=&quot;http://www.facebook.com&quot;/&gt;
+              ```
+
+              ## Bound:
+
+              ```javascript
+              App.ApplicationController = Ember.Controller.extend({
+                firstName: &quot;Stanley&quot;,
+                entryNotAllowed: true
+              });
+              ```
+
+
+              ```handlebars
+              {{input type=&quot;text&quot; value=firstName disabled=entryNotAllowed size=&quot;50&quot;}}
+              ```
+
+
+              ```html
+              &lt;input type=&quot;text&quot; value=&quot;Stanley&quot; disabled=&quot;disabled&quot; size=&quot;50&quot;/&gt;
+              ```
+
+              ## Actions
+
+              The helper can send multiple actions based on user events.
+
+              The action property defines the action which is send when
+              the user presses the return key.
+
+              ```handlebars
+              {{input action=&quot;submit&quot;}}
+              ```
+
+              The helper allows some user events to send actions.
+
+            * `enter`
+            * `insert-newline`
+            * `escape-press`
+            * `focus-in`
+            * `focus-out`
+            * `key-press`
+
+              For example, if you desire an action to be sent when the input is blurred,
+              you only need to setup the action name to the event name property.
+
+              ```handlebars
+              {{input focus-in=&quot;alertMessage&quot;}}
+              ```
+
+              See more about [Text Support Actions](api/classes/Ember.TextField.html)
+
+              ## Extension
+
+              Internally, `{{input type=&quot;text&quot;}}` creates an instance of `Ember.TextField`, passing
+              arguments from the helper to `Ember.TextField`'s `create` method. You can extend the
+              capabilities of text inputs in your applications by reopening this class. For example,
+              if you are building a Bootstrap project where `data-*` attributes are used, you
+              can add one to the `TextField`'s `attributeBindings` property:
+
+
+              ```javascript
+              Ember.TextField.reopen({
+                attributeBindings: ['data-error']
+              });
+              ```
+
+              Keep in mind when writing `Ember.TextField` subclasses that `Ember.TextField`
+              itself extends `Ember.Component`, meaning that it does NOT inherit
+              the `controller` of the parent view.
+
+              See more about [Ember components](api/classes/Ember.Component.html)
+
+
+              ## Use as checkbox
+
+              An `{{input}}` with a `type` of `checkbox` will render an HTML checkbox input.
+              The following HTML attributes can be set via the helper:
+
+            * `checked`
+            * `disabled`
+            * `tabindex`
+            * `indeterminate`
+            * `name`
+            * `autofocus`
+            * `form`
+
+
+              When set to a quoted string, these values will be directly applied to the HTML
+              element. When left unquoted, these values will be bound to a property on the
+              template's current rendering context (most typically a controller instance).
+
+              ## Unbound:
+
+              ```handlebars
+              {{input type=&quot;checkbox&quot; name=&quot;isAdmin&quot;}}
+              ```
+
+              ```html
+              &lt;input type=&quot;checkbox&quot; name=&quot;isAdmin&quot; /&gt;
+              ```
+
+              ## Bound:
+
+              ```javascript
+              App.ApplicationController = Ember.Controller.extend({
+                isAdmin: true
+              });
+              ```
+
+
+              ```handlebars
+              {{input type=&quot;checkbox&quot; checked=isAdmin }}
+              ```
+
+
+              ```html
+              &lt;input type=&quot;checkbox&quot; checked=&quot;checked&quot; /&gt;
+              ```
+
+              ## Extension
+
+              Internally, `{{input type=&quot;checkbox&quot;}}` creates an instance of `Ember.Checkbox`, passing
+              arguments from the helper to `Ember.Checkbox`'s `create` method. You can extend the
+              capablilties of checkbox inputs in your applications by reopening this class. For example,
+              if you wanted to add a css class to all checkboxes in your application:
+
+
+              ```javascript
+              Ember.Checkbox.reopen({
+                classNames: ['my-app-checkbox']
+              });
+              ```
+
+
+              @method input
+              @for Ember.Handlebars.helpers
+              @param {Hash} options
+            */
+        function inputHelper(options) {
+            Ember.assert('You can only pass attributes to the `input` helper, not arguments', arguments.length &lt; 2);
+
+            var hash = options.hash,
+            types = options.hashTypes,
+            inputType = hash.type,
+            onEvent = hash.on;
+
+            delete hash.type;
+            delete hash.on;
+
+            if (inputType === 'checkbox') {
+                Ember.assert(&quot;{{input type='checkbox'}} does not support setting `value=someBooleanValue`; you must use `checked=someBooleanValue` instead.&quot;, options.hashTypes.value !== 'ID');
+                return helpers.view.call(this, Checkbox, options);
+            } else {
+                if (inputType) {
+                    hash.type = inputType;
+                }
+                hash.onEvent = onEvent || 'enter';
+                return helpers.view.call(this, TextField, options);
+            }
+        }
+
+        __exports__.inputHelper = inputHelper; /**
+              `{{textarea}}` inserts a new instance of `&lt;textarea&gt;` tag into the template.
+              The attributes of `{{textarea}}` match those of the native HTML tags as
+              closely as possible.
+
+              The following HTML attributes can be set:
+
+                * `value`
+                * `name`
+                * `rows`
+                * `cols`
+                * `placeholder`
+                * `disabled`
+                * `maxlength`
+                * `tabindex`
+                * `selectionEnd`
+                * `selectionStart`
+                * `selectionDirection`
+                * `wrap`
+                * `readonly`
+                * `autofocus`
+                * `form`
+                * `spellcheck`
+                * `required`
+
+              When set to a quoted string, these value will be directly applied to the HTML
+              element. When left unquoted, these values will be bound to a property on the
+              template's current rendering context (most typically a controller instance).
+
+              Unbound:
+
+              ```handlebars
+              {{textarea value=&quot;Lots of static text that ISN'T bound&quot;}}
+              ```
+
+              Would result in the following HTML:
+
+              ```html
+              &lt;textarea class=&quot;ember-text-area&quot;&gt;
+                Lots of static text that ISN'T bound
+              &lt;/textarea&gt;
+              ```
+
+              Bound:
+
+              In the following example, the `writtenWords` property on `App.ApplicationController`
+              will be updated live as the user types 'Lots of text that IS bound' into
+              the text area of their browser's window.
+
+              ```javascript
+              App.ApplicationController = Ember.Controller.extend({
+                writtenWords: &quot;Lots of text that IS bound&quot;
+              });
+              ```
+
+              ```handlebars
+              {{textarea value=writtenWords}}
+              ```
+
+               Would result in the following HTML:
+
+              ```html
+              &lt;textarea class=&quot;ember-text-area&quot;&gt;
+                Lots of text that IS bound
+              &lt;/textarea&gt;
+              ```
+
+              If you wanted a one way binding between the text area and a div tag
+              somewhere else on your screen, you could use `Ember.computed.oneWay`:
+
+              ```javascript
+              App.ApplicationController = Ember.Controller.extend({
+                writtenWords: &quot;Lots of text that IS bound&quot;,
+                outputWrittenWords: Ember.computed.oneWay(&quot;writtenWords&quot;)
+              });
+              ```
+
+              ```handlebars
+              {{textarea value=writtenWords}}
+
+              &lt;div&gt;
+                {{outputWrittenWords}}
+              &lt;/div&gt;
+              ```
+
+              Would result in the following HTML:
+
+              ```html
+              &lt;textarea class=&quot;ember-text-area&quot;&gt;
+                Lots of text that IS bound
+              &lt;/textarea&gt;
+
+              &lt;-- the following div will be updated in real time as you type --&gt;
+
+              &lt;div&gt;
+                Lots of text that IS bound
+              &lt;/div&gt;
+              ```
+
+              Finally, this example really shows the power and ease of Ember when two
+              properties are bound to eachother via `Ember.computed.alias`. Type into
+              either text area box and they'll both stay in sync. Note that
+              `Ember.computed.alias` costs more in terms of performance, so only use it when
+              your really binding in both directions:
+
+              ```javascript
+              App.ApplicationController = Ember.Controller.extend({
+                writtenWords: &quot;Lots of text that IS bound&quot;,
+                twoWayWrittenWords: Ember.computed.alias(&quot;writtenWords&quot;)
+              });
+              ```
+
+              ```handlebars
+              {{textarea value=writtenWords}}
+              {{textarea value=twoWayWrittenWords}}
+              ```
+
+              ```html
+              &lt;textarea id=&quot;ember1&quot; class=&quot;ember-text-area&quot;&gt;
+                Lots of text that IS bound
+              &lt;/textarea&gt;
+
+              &lt;-- both updated in real time --&gt;
+
+              &lt;textarea id=&quot;ember2&quot; class=&quot;ember-text-area&quot;&gt;
+                Lots of text that IS bound
+              &lt;/textarea&gt;
+              ```
+
+              ## Actions
+
+              The helper can send multiple actions based on user events.
+
+              The action property defines the action which is send when
+              the user presses the return key.
+
+              ```handlebars
+              {{input action=&quot;submit&quot;}}
+              ```
+
+              The helper allows some user events to send actions.
+
+            * `enter`
+            * `insert-newline`
+            * `escape-press`
+            * `focus-in`
+            * `focus-out`
+            * `key-press`
+
+              For example, if you desire an action to be sent when the input is blurred,
+              you only need to setup the action name to the event name property.
+
+              ```handlebars
+              {{textarea focus-in=&quot;alertMessage&quot;}}
+              ```
+
+              See more about [Text Support Actions](api/classes/Ember.TextArea.html)
+
+              ## Extension
+
+              Internally, `{{textarea}}` creates an instance of `Ember.TextArea`, passing
+              arguments from the helper to `Ember.TextArea`'s `create` method. You can
+              extend the capabilities of text areas in your application by reopening this
+              class. For example, if you are building a Bootstrap project where `data-*` 
+              attributes are used, you can globally add support for a `data-*` attribute
+              on all `{{textarea}}`s' in your app by reopening `Ember.TextArea` or
+              `Ember.TextSupport` and adding it to the `attributeBindings` concatenated
+              property:
+
+              ```javascript
+              Ember.TextArea.reopen({
+                attributeBindings: ['data-error']
+              });
+              ```
+
+              Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea`
+              itself extends `Ember.Component`, meaning that it does NOT inherit
+              the `controller` of the parent view.
+
+              See more about [Ember components](api/classes/Ember.Component.html)
+
+              @method textarea
+              @for Ember.Handlebars.helpers
+              @param {Hash} options
+            */
+        function textareaHelper(options) {
+            Ember.assert('You can only pass attributes to the `textarea` helper, not arguments', arguments.length &lt; 2);
+
+            var hash = options.hash,
+            types = options.hashTypes;
+
+            return helpers.view.call(this, TextArea, options);
+        }
+
+        __exports__.textareaHelper = textareaHelper;
+    });
+    define(&quot;ember-handlebars/controls/checkbox&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/views/view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var View = __dependency3__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        /**
+              The internal class used to create text inputs when the `{{input}}`
+              helper is used with `type` of `checkbox`.
+
+              See [handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input)  for usage details.
+
+              ## Direct manipulation of `checked`
+
+              The `checked` attribute of an `Ember.Checkbox` object should always be set
+              through the Ember object or by interacting with its rendered element
+              representation via the mouse, keyboard, or touch. Updating the value of the
+              checkbox via jQuery will result in the checked value of the object and its
+              element losing synchronization.
+
+              ## Layout and LayoutName properties
+
+              Because HTML `input` elements are self closing `layout` and `layoutName`
+              properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
+              layout section for more information.
+
+              @class Checkbox
+              @namespace Ember
+              @extends Ember.View
+            */
+        __exports__[&quot;default&quot;] = View.extend({
+            instrumentDisplay: '{{input type=&quot;checkbox&quot;}}',
+
+            classNames: ['ember-checkbox'],
+
+            tagName: 'input',
+
+            attributeBindings: [
+            'type',
+            'checked',
+            'indeterminate',
+            'disabled',
+            'tabindex',
+            'name',
+            'autofocus',
+            'required',
+            'form'
+            ],
+
+            type: 'checkbox',
+            checked: false,
+            disabled: false,
+            indeterminate: false,
+
+            init: function() {
+                this._super();
+                this.on('change', this, this._updateElementValue);
+            },
+
+            didInsertElement: function() {
+                this._super();
+                get(this, 'element').indeterminate = !!get(this, 'indeterminate');
+            },
+
+            _updateElementValue: function() {
+                set(this, 'checked', this.$().prop('checked'));
+            }
+        });
+    });
+    define(&quot;ember-handlebars/controls/select&quot;,
+    [&quot;ember-handlebars-compiler&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/views/view&quot;, &quot;ember-views/views/collection_view&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/computed&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/properties&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var EmberHandlebars = __dependency1__[&quot;default&quot;];
+
+        var forEach = __dependency2__.forEach;
+        var indexOf = __dependency2__.indexOf;
+        var indexesOf = __dependency2__.indexesOf;
+        var replace = __dependency2__.replace;
+
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var View = __dependency5__[&quot;default&quot;];
+        var CollectionView = __dependency6__[&quot;default&quot;];
+        var isArray = __dependency7__.isArray;
+        var isNone = __dependency8__[&quot;default&quot;];
+        var computed = __dependency9__.computed;
+        var emberA = __dependency10__.A;
+        var observer = __dependency11__.observer;
+        var defineProperty = __dependency12__.defineProperty;
+
+        var precompileTemplate = EmberHandlebars.compile;
+
+        var SelectOption = View.extend({
+            instrumentDisplay: 'Ember.SelectOption',
+
+            tagName: 'option',
+            attributeBindings: ['value', 'selected'],
+
+            defaultTemplate: function(context, options) {
+                options = {
+                    data: options.data,
+                    hash: {}
+                };
+                EmberHandlebars.helpers.bind.call(context, &quot;view.label&quot;, options);
+            },
+
+            init: function() {
+                this.labelPathDidChange();
+                this.valuePathDidChange();
+
+                this._super();
+            },
+
+            selected: computed(function() {
+                var content = get(this, 'content'),
+                selection = get(this, 'parentView.selection');
+                if (get(this, 'parentView.multiple')) {
+                    return selection &amp;&amp; indexOf(selection, content.valueOf()) &gt; -1;
+                } else {
+                    // Primitives get passed through bindings as objects... since
+                    // `new Number(4) !== 4`, we use `==` below
+                    return content == selection; // jshint ignore:line
+                }
+            }).property('content', 'parentView.selection'),
+
+            labelPathDidChange: observer('parentView.optionLabelPath', function() {
+                var labelPath = get(this, 'parentView.optionLabelPath');
+
+                if (!labelPath) {
+                    return;
+                }
+
+                defineProperty(this, 'label', computed(function() {
+                    return get(this, labelPath);
+                }).property(labelPath));
+            }),
+
+            valuePathDidChange: observer('parentView.optionValuePath', function() {
+                var valuePath = get(this, 'parentView.optionValuePath');
+
+                if (!valuePath) {
+                    return;
+                }
+
+                defineProperty(this, 'value', computed(function() {
+                    return get(this, valuePath);
+                }).property(valuePath));
+            })
+        });
+
+        var SelectOptgroup = CollectionView.extend({
+            instrumentDisplay: 'Ember.SelectOptgroup',
+
+            tagName: 'optgroup',
+            attributeBindings: ['label'],
+
+            selectionBinding: 'parentView.selection',
+            multipleBinding: 'parentView.multiple',
+            optionLabelPathBinding: 'parentView.optionLabelPath',
+            optionValuePathBinding: 'parentView.optionValuePath',
+
+            itemViewClassBinding: 'parentView.optionView'
+        });
+
+        /**
+              The `Ember.Select` view class renders a
+              [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element,
+              allowing the user to choose from a list of options.
+
+              The text and `value` property of each `&lt;option&gt;` element within the
+              `&lt;select&gt;` element are populated from the objects in the `Element.Select`'s
+              `content` property. The underlying data object of the selected `&lt;option&gt;` is
+              stored in the `Element.Select`'s `value` property.
+
+              ## The Content Property (array of strings)
+
+              The simplest version of an `Ember.Select` takes an array of strings as its
+              `content` property. The string will be used as both the `value` property and
+              the inner text of each `&lt;option&gt;` element inside the rendered `&lt;select&gt;`.
+
+              Example:
+
+              ```javascript
+              App.ApplicationController = Ember.ObjectController.extend({
+                names: [&quot;Yehuda&quot;, &quot;Tom&quot;]
+              });
+              ```
+
+              ```handlebars
+              {{view Ember.Select content=names}}
+              ```
+
+              Would result in the following HTML:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option value=&quot;Yehuda&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;Tom&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              You can control which `&lt;option&gt;` is selected through the `Ember.Select`'s
+              `value` property:
+
+              ```javascript
+              App.ApplicationController = Ember.ObjectController.extend({
+                selectedName: 'Tom',
+                names: [&quot;Yehuda&quot;, &quot;Tom&quot;]
+              });
+              ```
+
+              ```handlebars
+              {{view Ember.Select
+                     content=names
+                     value=selectedName
+              }}
+              ```
+
+              Would result in the following HTML with the `&lt;option&gt;` for 'Tom' selected:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option value=&quot;Yehuda&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;Tom&quot; selected=&quot;selected&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              A user interacting with the rendered `&lt;select&gt;` to choose &quot;Yehuda&quot; would
+              update the value of `selectedName` to &quot;Yehuda&quot;.
+
+              ## The Content Property (array of Objects)
+
+              An `Ember.Select` can also take an array of JavaScript or Ember objects as
+              its `content` property.
+
+              When using objects you need to tell the `Ember.Select` which property should
+              be accessed on each object to supply the `value` attribute of the `&lt;option&gt;`
+              and which property should be used to supply the element text.
+
+              The `optionValuePath` option is used to specify the path on each object to
+              the desired property for the `value` attribute. The `optionLabelPath`
+              specifies the path on each object to the desired property for the
+              element's text. Both paths must reference each object itself as `content`:
+
+              ```javascript
+              App.ApplicationController = Ember.ObjectController.extend({
+                programmers: [
+                  {firstName: &quot;Yehuda&quot;, id: 1},
+                  {firstName: &quot;Tom&quot;,    id: 2}
+                ]
+              });
+              ```
+
+              ```handlebars
+              {{view Ember.Select
+                     content=programmers
+                     optionValuePath=&quot;content.id&quot;
+                     optionLabelPath=&quot;content.firstName&quot;}}
+              ```
+
+              Would result in the following HTML:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option value=&quot;1&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;2&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              The `value` attribute of the selected `&lt;option&gt;` within an `Ember.Select`
+              can be bound to a property on another object:
+
+              ```javascript
+              App.ApplicationController = Ember.ObjectController.extend({
+                programmers: [
+                  {firstName: &quot;Yehuda&quot;, id: 1},
+                  {firstName: &quot;Tom&quot;,    id: 2}
+                ],
+                currentProgrammer: {
+                  id: 2
+                }
+              });
+              ```
+
+              ```handlebars
+              {{view Ember.Select
+                     content=programmers
+                     optionValuePath=&quot;content.id&quot;
+                     optionLabelPath=&quot;content.firstName&quot;
+                     value=currentProgrammer.id}}
+              ```
+
+              Would result in the following HTML with a selected option:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option value=&quot;1&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;2&quot; selected=&quot;selected&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              Interacting with the rendered element by selecting the first option
+              ('Yehuda') will update the `id` of `currentProgrammer`
+              to match the `value` property of the newly selected `&lt;option&gt;`.
+
+              Alternatively, you can control selection through the underlying objects
+              used to render each object by binding the `selection` option. When the selected
+              `&lt;option&gt;` is changed, the property path provided to `selection`
+              will be updated to match the content object of the rendered `&lt;option&gt;`
+              element:
+
+              ```javascript
+
+              var yehuda = {firstName: &quot;Yehuda&quot;, id: 1, bff4eva: 'tom'}
+              var tom = {firstName: &quot;Tom&quot;, id: 2, bff4eva: 'yehuda'};
+
+              App.ApplicationController = Ember.ObjectController.extend({
+                selectedPerson: tom,
+                programmers: [
+                  yehuda,
+                  tom
+                ]
+              });
+              ```
+
+              ```handlebars
+              {{view Ember.Select
+                     content=programmers
+                     optionValuePath=&quot;content.id&quot;
+                     optionLabelPath=&quot;content.firstName&quot;
+                     selection=selectedPerson}}
+              ```
+
+              Would result in the following HTML with a selected option:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option value=&quot;1&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;2&quot; selected=&quot;selected&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              Interacting with the rendered element by selecting the first option
+              ('Yehuda') will update the `selectedPerson` to match the object of
+              the newly selected `&lt;option&gt;`. In this case it is the first object
+              in the `programmers`
+
+              ## Supplying a Prompt
+
+              A `null` value for the `Ember.Select`'s `value` or `selection` property
+              results in there being no `&lt;option&gt;` with a `selected` attribute:
+
+              ```javascript
+              App.ApplicationController = Ember.ObjectController.extend({
+                selectedProgrammer: null,
+                programmers: [
+                  &quot;Yehuda&quot;,
+                  &quot;Tom&quot;
+                ]
+              });
+              ```
+
+              ``` handlebars
+              {{view Ember.Select
+                     content=programmers
+                     value=selectedProgrammer
+              }}
+              ```
+
+              Would result in the following HTML:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option value=&quot;Yehuda&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;Tom&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              Although `selectedProgrammer` is `null` and no `&lt;option&gt;`
+              has a `selected` attribute the rendered HTML will display the
+              first item as though it were selected. You can supply a string
+              value for the `Ember.Select` to display when there is no selection
+              with the `prompt` option:
+
+              ```javascript
+              App.ApplicationController = Ember.ObjectController.extend({
+                selectedProgrammer: null,
+                programmers: [
+                  &quot;Yehuda&quot;,
+                  &quot;Tom&quot;
+                ]
+              });
+              ```
+
+              ```handlebars
+              {{view Ember.Select
+                     content=programmers
+                     value=selectedProgrammer
+                     prompt=&quot;Please select a name&quot;
+              }}
+              ```
+
+              Would result in the following HTML:
+
+              ```html
+              &lt;select class=&quot;ember-select&quot;&gt;
+                &lt;option&gt;Please select a name&lt;/option&gt;
+                &lt;option value=&quot;Yehuda&quot;&gt;Yehuda&lt;/option&gt;
+                &lt;option value=&quot;Tom&quot;&gt;Tom&lt;/option&gt;
+              &lt;/select&gt;
+              ```
+
+              @class Select
+              @namespace Ember
+              @extends Ember.View
+            */
+        var Select = View.extend({
+            instrumentDisplay: 'Ember.Select',
+
+            tagName: 'select',
+            classNames: ['ember-select'],
+            defaultTemplate: Ember.Handlebars.template(function anonymous(Handlebars, depth0, helpers, partials, data) {
+                this.compilerInfo = [4, '&gt;= 1.0.0'];
+                helpers = this.merge(helpers, Ember.Handlebars.helpers);
+                data = data || {};
+                var buffer = '', stack1, escapeExpression = this.escapeExpression, self = this;
+
+                function program1(depth0, data) {
+
+                    var buffer = '', stack1;
+                    data.buffer.push(&quot;&lt;option value=\&quot;\&quot;&gt;&quot;);
+                    stack1 = helpers._triageMustache.call(depth0, &quot;view.prompt&quot;, {
+                        hash: {},
+                        hashTypes: {},
+                        hashContexts: {},
+                        contexts: [depth0],
+                        types: [&quot;ID&quot;],
+                        data: data
+                    });
+                    if (stack1 || stack1 === 0) {
+                        data.buffer.push(stack1);
+                    }
+                    data.buffer.push(&quot;&lt;/option&gt;&quot;);
+                    return buffer;
+                }
+
+                function program3(depth0, data) {
+
+                    var stack1;
+                    stack1 = helpers.each.call(depth0, &quot;view.groupedContent&quot;, {
+                        hash: {},
+                        hashTypes: {},
+                        hashContexts: {},
+                        inverse: self.noop,
+                        fn: self.program(4, program4, data),
+                        contexts: [depth0],
+                        types: [&quot;ID&quot;],
+                        data: data
+                    });
+                    if (stack1 || stack1 === 0) {
+                        data.buffer.push(stack1);
+                    } else {
+                        data.buffer.push('');
+                    }
+                }
+                function program4(depth0, data) {
+
+
+                    data.buffer.push(escapeExpression(helpers.view.call(depth0, &quot;view.groupView&quot;, {
+                        hash: {
+                            'content': (&quot;content&quot;),
+                            'label': (&quot;label&quot;)
+                        },
+                        hashTypes: {
+                            'content': &quot;ID&quot;,
+                            'label': &quot;ID&quot;
+                        },
+                        hashContexts: {
+                            'content': depth0,
+                            'label': depth0
+                        },
+                        contexts: [depth0],
+                        types: [&quot;ID&quot;],
+                        data: data
+                    })));
+                }
+
+                function program6(depth0, data) {
+
+                    var stack1;
+                    stack1 = helpers.each.call(depth0, &quot;view.content&quot;, {
+                        hash: {},
+                        hashTypes: {},
+                        hashContexts: {},
+                        inverse: self.noop,
+                        fn: self.program(7, program7, data),
+                        contexts: [depth0],
+                        types: [&quot;ID&quot;],
+                        data: data
+                    });
+                    if (stack1 || stack1 === 0) {
+                        data.buffer.push(stack1);
+                    } else {
+                        data.buffer.push('');
+                    }
+                }
+                function program7(depth0, data) {
+
+
+                    data.buffer.push(escapeExpression(helpers.view.call(depth0, &quot;view.optionView&quot;, {
+                        hash: {
+                            'content': (&quot;&quot;)
+                        },
+                        hashTypes: {
+                            'content': &quot;ID&quot;
+                        },
+                        hashContexts: {
+                            'content': depth0
+                        },
+                        contexts: [depth0],
+                        types: [&quot;ID&quot;],
+                        data: data
+                    })));
+                }
+
+                stack1 = helpers['if'].call(depth0, &quot;view.prompt&quot;, {
+                    hash: {},
+                    hashTypes: {},
+                    hashContexts: {},
+                    inverse: self.noop,
+                    fn: self.program(1, program1, data),
+                    contexts: [depth0],
+                    types: [&quot;ID&quot;],
+                    data: data
+                });
+                if (stack1 || stack1 === 0) {
+                    data.buffer.push(stack1);
+                }
+                stack1 = helpers['if'].call(depth0, &quot;view.optionGroupPath&quot;, {
+                    hash: {},
+                    hashTypes: {},
+                    hashContexts: {},
+                    inverse: self.program(6, program6, data),
+                    fn: self.program(3, program3, data),
+                    contexts: [depth0],
+                    types: [&quot;ID&quot;],
+                    data: data
+                });
+                if (stack1 || stack1 === 0) {
+                    data.buffer.push(stack1);
+                }
+                return buffer;
+
+            }),
+            attributeBindings: ['multiple', 'disabled', 'tabindex', 'name', 'required', 'autofocus',
+            'form', 'size'],
+
+            /**
+                    The `multiple` attribute of the select element. Indicates whether multiple
+                    options can be selected.
+
+                    @property multiple
+                    @type Boolean
+                    @default false
+                  */
+            multiple: false,
+
+            /**
+                    The `disabled` attribute of the select element. Indicates whether
+                    the element is disabled from interactions.
+
+                    @property disabled
+                    @type Boolean
+                    @default false
+                  */
+            disabled: false,
+
+            /**
+                    The `required` attribute of the select element. Indicates whether
+                    a selected option is required for form validation.
+
+                    @property required
+                    @type Boolean
+                    @default false
+                    @since 1.5.0
+                  */
+            required: false,
+
+            /**
+                    The list of options.
+
+                    If `optionLabelPath` and `optionValuePath` are not overridden, this should
+                    be a list of strings, which will serve simultaneously as labels and values.
+
+                    Otherwise, this should be a list of objects. For instance:
+
+                    ```javascript
+                    Ember.Select.create({
+                      content: Ember.A([
+                          { id: 1, firstName: 'Yehuda' },
+                          { id: 2, firstName: 'Tom' }
+                        ]),
+                      optionLabelPath: 'content.firstName',
+                      optionValuePath: 'content.id'
+                    });
+                    ```
+
+                    @property content
+                    @type Array
+                    @default null
+                  */
+            content: null,
+
+            /**
+                    When `multiple` is `false`, the element of `content` that is currently
+                    selected, if any.
+
+                    When `multiple` is `true`, an array of such elements.
+
+                    @property selection
+                    @type Object or Array
+                    @default null
+                  */
+            selection: null,
+
+            /**
+                    In single selection mode (when `multiple` is `false`), value can be used to
+                    get the current selection's value or set the selection by it's value.
+
+                    It is not currently supported in multiple selection mode.
+
+                    @property value
+                    @type String
+                    @default null
+                  */
+            value: computed(function(key, value) {
+                if (arguments.length === 2) {
+                    return value;
+                }
+                var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, '');
+                return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection');
+            }).property('selection'),
+
+            /**
+                    If given, a top-most dummy option will be rendered to serve as a user
+                    prompt.
+
+                    @property prompt
+                    @type String
+                    @default null
+                  */
+            prompt: null,
+
+            /**
+                    The path of the option labels. See [content](/api/classes/Ember.Select.html#property_content).
+
+                    @property optionLabelPath
+                    @type String
+                    @default 'content'
+                  */
+            optionLabelPath: 'content',
+
+            /**
+                    The path of the option values. See [content](/api/classes/Ember.Select.html#property_content).
+
+                    @property optionValuePath
+                    @type String
+                    @default 'content'
+                  */
+            optionValuePath: 'content',
+
+            /**
+                    The path of the option group.
+                    When this property is used, `content` should be sorted by `optionGroupPath`.
+
+                    @property optionGroupPath
+                    @type String
+                    @default null
+                  */
+            optionGroupPath: null,
+
+            /**
+                    The view class for optgroup.
+
+                    @property groupView
+                    @type Ember.View
+                    @default Ember.SelectOptgroup
+                  */
+            groupView: SelectOptgroup,
+
+            groupedContent: computed(function() {
+                var groupPath = get(this, 'optionGroupPath');
+                var groupedContent = emberA();
+                var content = get(this, 'content') || [];
+
+                forEach(content, function(item) {
+                    var label = get(item, groupPath);
+
+                    if (get(groupedContent, 'lastObject.label') !== label) {
+                        groupedContent.pushObject({
+                            label: label,
+                            content: emberA()
+                        });
+                    }
+
+                    get(groupedContent, 'lastObject.content').push(item);
+                });
+
+                return groupedContent;
+            }).property('optionGroupPath', 'content.@each'),
+
+            /**
+                    The view class for option.
+
+                    @property optionView
+                    @type Ember.View
+                    @default Ember.SelectOption
+                  */
+            optionView: SelectOption,
+
+            _change: function() {
+                if (get(this, 'multiple')) {
+                    this._changeMultiple();
+                } else {
+                    this._changeSingle();
+                }
+            },
+
+            selectionDidChange: observer('selection.@each', function() {
+                var selection = get(this, 'selection');
+                if (get(this, 'multiple')) {
+                    if (!isArray(selection)) {
+                        set(this, 'selection', emberA([selection]));
+                        return;
+                    }
+                    this._selectionDidChangeMultiple();
+                } else {
+                    this._selectionDidChangeSingle();
+                }
+            }),
+
+            valueDidChange: observer('value', function() {
+                var content = get(this, 'content'),
+                value = get(this, 'value'),
+                valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''),
+                selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')),
+                selection;
+
+                if (value !== selectedValue) {
+                    selection = content ? content.find(function(obj) {
+                        return value === (valuePath ? get(obj, valuePath) : obj);
+                    }) : null;
+
+                    this.set('selection', selection);
+                }
+            }),
+
+
+            _triggerChange: function() {
+                var selection = get(this, 'selection');
+                var value = get(this, 'value');
+
+                if (!isNone(selection)) {
+                    this.selectionDidChange();
+                }
+                if (!isNone(value)) {
+                    this.valueDidChange();
+                }
+
+                this._change();
+            },
+
+            _changeSingle: function() {
+                var selectedIndex = this.$()[0].selectedIndex,
+                content = get(this, 'content'),
+                prompt = get(this, 'prompt');
+
+                if (!content || !get(content, 'length')) {
+                    return;
+                }
+                if (prompt &amp;&amp; selectedIndex === 0) {
+                    set(this, 'selection', null);
+                    return;
+                }
+
+                if (prompt) {
+                    selectedIndex -= 1;
+                }
+                set(this, 'selection', content.objectAt(selectedIndex));
+            },
+
+
+            _changeMultiple: function() {
+                var options = this.$('option:selected'),
+                prompt = get(this, 'prompt'),
+                offset = prompt ? 1 : 0,
+                content = get(this, 'content'),
+                selection = get(this, 'selection');
+
+                if (!content) {
+                    return;
+                }
+                if (options) {
+                    var selectedIndexes = options.map(function() {
+                        return this.index - offset;
+                    }).toArray();
+                    var newSelection = content.objectsAt(selectedIndexes);
+
+                    if (isArray(selection)) {
+                        replace(selection, 0, get(selection, 'length'), newSelection);
+                    } else {
+                        set(this, 'selection', newSelection);
+                    }
+                }
+            },
+
+            _selectionDidChangeSingle: function() {
+                var el = this.get('element');
+                if (!el) {
+                    return;
+                }
+
+                var content = get(this, 'content'),
+                selection = get(this, 'selection'),
+                selectionIndex = content ? indexOf(content, selection) : -1,
+                prompt = get(this, 'prompt');
+
+                if (prompt) {
+                    selectionIndex += 1;
+                }
+                if (el) {
+                    el.selectedIndex = selectionIndex;
+                }
+            },
+
+            _selectionDidChangeMultiple: function() {
+                var content = get(this, 'content'),
+                selection = get(this, 'selection'),
+                selectedIndexes = content ? indexesOf(content, selection) : [-1],
+                prompt = get(this, 'prompt'),
+                offset = prompt ? 1 : 0,
+                options = this.$('option'),
+                adjusted;
+
+                if (options) {
+                    options.each(function() {
+                        adjusted = this.index &gt; -1 ? this.index - offset : -1;
+                        this.selected = indexOf(selectedIndexes, adjusted) &gt; -1;
+                    });
+                }
+            },
+
+            init: function() {
+                this._super();
+                this.on(&quot;didInsertElement&quot;, this, this._triggerChange);
+                this.on(&quot;change&quot;, this, this._change);
+            }
+        });
+
+        __exports__[&quot;default&quot;] = Select;
+        __exports__.Select = Select;
+        __exports__.SelectOption = SelectOption;
+        __exports__.SelectOptgroup = SelectOptgroup;
+    });
+    define(&quot;ember-handlebars/controls/text_area&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-views/views/component&quot;, &quot;ember-handlebars/controls/text_support&quot;, &quot;ember-metal/mixin&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+        var get = __dependency1__.get;
+        var Component = __dependency2__[&quot;default&quot;];
+        var TextSupport = __dependency3__[&quot;default&quot;];
+        var observer = __dependency4__.observer;
+
+        /**
+              The internal class used to create textarea element when the `{{textarea}}`
+              helper is used.
+
+              See [handlebars.helpers.textarea](/api/classes/Ember.Handlebars.helpers.html#method_textarea)  for usage details.
+
+              ## Layout and LayoutName properties
+
+              Because HTML `textarea` elements do not contain inner HTML the `layout` and
+              `layoutName` properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
+              layout section for more information.
+
+              @class TextArea
+              @namespace Ember
+              @extends Ember.Component
+              @uses Ember.TextSupport
+            */
+        __exports__[&quot;default&quot;] = Component.extend(TextSupport, {
+            instrumentDisplay: '{{textarea}}',
+
+            classNames: ['ember-text-area'],
+
+            tagName: &quot;textarea&quot;,
+            attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap'],
+            rows: null,
+            cols: null,
+
+            _updateElementValue: observer('value', function() {
+                // We do this check so cursor position doesn't get affected in IE
+                var value = get(this, 'value'),
+                $el = this.$();
+                if ($el &amp;&amp; value !== $el.val()) {
+                    $el.val(value);
+                }
+            }),
+
+            init: function() {
+                this._super();
+                this.on(&quot;didInsertElement&quot;, this, this._updateElementValue);
+            }
+        });
+    });
+    define(&quot;ember-handlebars/controls/text_field&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/views/component&quot;, &quot;ember-handlebars/controls/text_support&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var Component = __dependency3__[&quot;default&quot;];
+        var TextSupport = __dependency4__[&quot;default&quot;];
+
+        /**
+
+              The internal class used to create text inputs when the `{{input}}`
+              helper is used with `type` of `text`.
+
+              See [Handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input)  for usage details.
+
+              ## Layout and LayoutName properties
+
+              Because HTML `input` elements are self closing `layout` and `layoutName`
+              properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s
+              layout section for more information.
+
+              @class TextField
+              @namespace Ember
+              @extends Ember.Component
+              @uses Ember.TextSupport
+            */
+        __exports__[&quot;default&quot;] = Component.extend(TextSupport, {
+            instrumentDisplay: '{{input type=&quot;text&quot;}}',
+
+            classNames: ['ember-text-field'],
+            tagName: &quot;input&quot;,
+            attributeBindings: ['type', 'value', 'size', 'pattern', 'name', 'min', 'max',
+            'accept', 'autocomplete', 'autosave', 'formaction',
+            'formenctype', 'formmethod', 'formnovalidate', 'formtarget',
+            'height', 'inputmode', 'list', 'multiple', 'step',
+            'width'],
+
+            /**
+                    The `value` attribute of the input element. As the user inputs text, this
+                    property is updated live.
+
+                    @property value
+                    @type String
+                    @default &quot;&quot;
+                  */
+            value: &quot;&quot;,
+
+            /**
+                    The `type` attribute of the input element.
+
+                    @property type
+                    @type String
+                    @default &quot;text&quot;
+                  */
+            type: &quot;text&quot;,
+
+            /**
+                    The `size` of the text field in characters.
+
+                    @property size
+                    @type String
+                    @default null
+                  */
+            size: null,
+
+            /**
+                    The `pattern` attribute of input element.
+
+                    @property pattern
+                    @type String
+                    @default null
+                  */
+            pattern: null,
+
+            /**
+                    The `min` attribute of input element used with `type=&quot;number&quot;` or `type=&quot;range&quot;`.
+
+                    @property min
+                    @type String
+                    @default null
+                    @since 1.4.0
+                  */
+            min: null,
+
+            /**
+                    The `max` attribute of input element used with `type=&quot;number&quot;` or `type=&quot;range&quot;`.
+
+                    @property max
+                    @type String
+                    @default null
+                    @since 1.4.0
+                  */
+            max: null
+        });
+    });
+    define(&quot;ember-handlebars/controls/text_support&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/target_action_support&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var Mixin = __dependency3__.Mixin;
+        var TargetActionSupport = __dependency4__[&quot;default&quot;];
+
+        /**
+              Shared mixin used by `Ember.TextField` and `Ember.TextArea`.
+
+              @class TextSupport
+              @namespace Ember
+              @uses Ember.TargetActionSupport
+              @extends Ember.Mixin
+              @private
+            */
+        var TextSupport = Mixin.create(TargetActionSupport, {
+            value: &quot;&quot;,
+
+            attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex', 'readonly',
+            'autofocus', 'form', 'selectionDirection', 'spellcheck', 'required',
+            'title', 'autocapitalize', 'autocorrect'],
+            placeholder: null,
+            disabled: false,
+            maxlength: null,
+
+            init: function() {
+                this._super();
+                this.on(&quot;focusOut&quot;, this, this._elementValueDidChange);
+                this.on(&quot;change&quot;, this, this._elementValueDidChange);
+                this.on(&quot;paste&quot;, this, this._elementValueDidChange);
+                this.on(&quot;cut&quot;, this, this._elementValueDidChange);
+                this.on(&quot;input&quot;, this, this._elementValueDidChange);
+                this.on(&quot;keyUp&quot;, this, this.interpretKeyEvents);
+            },
+
+            /**
+                    The action to be sent when the user presses the return key.
+
+                    This is similar to the `{{action}}` helper, but is fired when
+                    the user presses the return key when editing a text field, and sends
+                    the value of the field as the context.
+
+                    @property action
+                    @type String
+                    @default null
+                  */
+            action: null,
+
+            /**
+                    The event that should send the action.
+
+                    Options are:
+
+                    * `enter`: the user pressed enter
+                    * `keyPress`: the user pressed a key
+
+                    @property onEvent
+                    @type String
+                    @default enter
+                  */
+            onEvent: 'enter',
+
+            /**
+                    Whether they `keyUp` event that triggers an `action` to be sent continues
+                    propagating to other views.
+
+                    By default, when the user presses the return key on their keyboard and
+                    the text field has an `action` set, the action will be sent to the view's
+                    controller and the key event will stop propagating.
+
+                    If you would like parent views to receive the `keyUp` event even after an
+                    action has been dispatched, set `bubbles` to true.
+
+                    @property bubbles
+                    @type Boolean
+                    @default false
+                  */
+            bubbles: false,
+
+            interpretKeyEvents: function(event) {
+                var map = TextSupport.KEY_EVENTS;
+                var method = map[event.keyCode];
+
+                this._elementValueDidChange();
+                if (method) {
+                    return this[method](event);
+                }
+            },
+
+            _elementValueDidChange: function() {
+                set(this, 'value', this.$().val());
+            },
+
+            /**
+                    Called when the user inserts a new line.
+
+                    Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13.
+                    Uses sendAction to send the `enter` action.
+
+                    @method insertNewline
+                    @param {Event} event
+                  */
+            insertNewline: function(event) {
+                sendAction('enter', this, event);
+                sendAction('insert-newline', this, event);
+            },
+
+            /**
+                    Called when the user hits escape.
+
+                    Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 27.
+                    Uses sendAction to send the `escape-press` action.
+
+                    @method cancel
+                    @param {Event} event
+                  */
+            cancel: function(event) {
+                sendAction('escape-press', this, event);
+            },
+
+            /**
+                    Called when the text area is focused.
+
+                    Uses sendAction to send the `focus-in` action.
+
+                    @method focusIn
+                    @param {Event} event
+                  */
+            focusIn: function(event) {
+                sendAction('focus-in', this, event);
+            },
+
+            /**
+                    Called when the text area is blurred. 
+
+                    Uses sendAction to send the `focus-out` action.
+
+                    @method focusOut
+                    @param {Event} event
+                  */
+            focusOut: function(event) {
+                sendAction('focus-out', this, event);
+            },
+
+            /**
+                    Called when the user presses a key. Enabled by setting
+                    the `onEvent` property to `keyPress`.
+
+                    Uses sendAction to send the `key-press` action.
+
+                    @method keyPress
+                    @param {Event} event
+                  */
+            keyPress: function(event) {
+                sendAction('key-press', this, event);
+            }
+
+        });
+
+        TextSupport.KEY_EVENTS = {
+            13: 'insertNewline',
+            27: 'cancel'
+        };
+
+        // In principle, this shouldn't be necessary, but the legacy
+        // sendAction semantics for TextField are different from
+        // the component semantics so this method normalizes them.
+        function sendAction(eventName, view, event) {
+            var action = get(view, eventName),
+            on = get(view, 'onEvent'),
+            value = get(view, 'value');
+
+            // back-compat support for keyPress as an event name even though
+            // it's also a method name that consumes the event (and therefore
+            // incompatible with sendAction semantics).
+            if (on === eventName || (on === 'keyPress' &amp;&amp; eventName === 'key-press')) {
+                view.sendAction('action', value);
+            }
+
+            view.sendAction(eventName, value);
+
+            if (action || on === eventName) {
+                if (!get(view, 'bubbles')) {
+                    event.stopPropagation();
+                }
+            }
+        }
+
+        __exports__[&quot;default&quot;] = TextSupport;
+    });
+    define(&quot;ember-handlebars/ext&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-handlebars-compiler&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/binding&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/is_empty&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.FEATURES, Ember.assert, Ember.Handlebars, Ember.lookup
+        // var emberAssert = Ember.assert;
+
+        var fmt = __dependency2__.fmt;
+
+        var EmberHandlebars = __dependency3__[&quot;default&quot;];
+        var helpers = EmberHandlebars.helpers;
+
+        var get = __dependency4__.get;
+        var isGlobalPath = __dependency5__.isGlobalPath;
+        var EmberError = __dependency6__[&quot;default&quot;];
+        var IS_BINDING = __dependency7__.IS_BINDING;
+
+        // late bound via requireModule because of circular dependencies.
+        var resolveHelper,
+        SimpleHandlebarsView;
+
+        var isEmpty = __dependency8__[&quot;default&quot;];
+
+        var slice = [].slice, originalTemplate = EmberHandlebars.template;
+
+        /**
+              If a path starts with a reserved keyword, returns the root
+              that should be used.
+
+              @private
+              @method normalizePath
+              @for Ember
+              @param root {Object}
+              @param path {String}
+              @param data {Hash}
+            */
+        function normalizePath(root, path, data) {
+            var keywords = (data &amp;&amp; data.keywords) || {},
+            keyword, isKeyword;
+
+            // Get the first segment of the path. For example, if the
+            // path is &quot;foo.bar.baz&quot;, returns &quot;foo&quot;.
+            keyword = path.split('.', 1)[0];
+
+            // Test to see if the first path is a keyword that has been
+            // passed along in the view's data hash. If so, we will treat
+            // that object as the new root.
+            if (keywords.hasOwnProperty(keyword)) {
+                // Look up the value in the template's data hash.
+                root = keywords[keyword];
+                isKeyword = true;
+
+                // Handle cases where the entire path is the reserved
+                // word. In that case, return the object itself.
+                if (path === keyword) {
+                    path = '';
+                } else {
+                    // Strip the keyword from the path and look up
+                    // the remainder from the newly found root.
+                    path = path.substr(keyword.length + 1);
+                }
+            }
+
+            return {
+                root: root,
+                path: path,
+                isKeyword: isKeyword 
+            };
+        }
+
+
+        /**
+              Lookup both on root and on window. If the path starts with
+              a keyword, the corresponding object will be looked up in the
+              template's data hash and used to resolve the path.
+
+              @method get
+              @for Ember.Handlebars
+              @param {Object} root The object to look up the property on
+              @param {String} path The path to be lookedup
+              @param {Object} options The template's option hash
+            */
+        function handlebarsGet(root, path, options) {
+            var data = options &amp;&amp; options.data,
+            normalizedPath = normalizePath(root, path, data),
+            value;
+
+
+            root = normalizedPath.root;
+            path = normalizedPath.path;
+
+            value = get(root, path);
+
+            if (value === undefined &amp;&amp; root !== Ember.lookup &amp;&amp; isGlobalPath(path)) {
+                value = get(Ember.lookup, path);
+            }
+
+
+            return value;
+        }
+
+        /**
+              This method uses `Ember.Handlebars.get` to lookup a value, then ensures
+              that the value is escaped properly.
+
+              If `unescaped` is a truthy value then the escaping will not be performed.
+
+              @method getEscaped
+              @for Ember.Handlebars
+              @param {Object} root The object to look up the property on
+              @param {String} path The path to be lookedup
+              @param {Object} options The template's option hash
+              @since 1.4.0
+            */
+        function getEscaped(root, path, options) {
+            var result = handlebarsGet(root, path, options);
+
+            if (result === null || result === undefined) {
+                result = &quot;&quot;;
+            } else if (!(result instanceof Handlebars.SafeString)) {
+                result = String(result);
+            }
+            if (!options.hash.unescaped) {
+                result = Handlebars.Utils.escapeExpression(result);
+            }
+
+            return result;
+        }
+
+        __exports__.getEscaped = getEscaped;
+        function resolveParams(context, params, options) {
+            var resolvedParams = [], types = options.types, param, type;
+
+            for (var i = 0, l = params.length; i &lt; l; i++) {
+                param = params[i];
+                type = types[i];
+
+                if (type === 'ID') {
+                    resolvedParams.push(handlebarsGet(context, param, options));
+                } else {
+                    resolvedParams.push(param);
+                }
+            }
+
+            return resolvedParams;
+        }
+
+        __exports__.resolveParams = resolveParams;
+        function resolveHash(context, hash, options) {
+            var resolvedHash = {}, types = options.hashTypes, type;
+
+            for (var key in hash) {
+                if (!hash.hasOwnProperty(key)) {
+                    continue;
+                }
+
+                type = types[key];
+
+                if (type === 'ID') {
+                    resolvedHash[key] = handlebarsGet(context, hash[key], options);
+                } else {
+                    resolvedHash[key] = hash[key];
+                }
+            }
+
+            return resolvedHash;
+        }
+
+        __exports__.resolveHash = resolveHash; /**
+              Registers a helper in Handlebars that will be called if no property with the
+              given name can be found on the current context object, and no helper with
+              that name is registered.
+
+              This throws an exception with a more helpful error message so the user can
+              track down where the problem is happening.
+
+              @private
+              @method helperMissing
+              @for Ember.Handlebars.helpers
+              @param {String} path
+              @param {Hash} options
+            */
+        function helperMissingHelper(path) {
+            if (!resolveHelper) {
+                resolveHelper = requireModule('ember-handlebars/helpers/binding')['resolveHelper'];
+            }
+            // ES6TODO: stupid circular dep
+
+            var error, view = &quot;&quot;;
+
+            var options = arguments[arguments.length - 1];
+
+            var helper = resolveHelper(options.data.view.container, path);
+
+            if (helper) {
+                return helper.apply(this, slice.call(arguments, 1));
+            }
+
+            error = &quot;%@ Handlebars error: Could not find property '%@' on object %@.&quot;;
+            if (options.data) {
+                view = options.data.view;
+            }
+            throw new EmberError(fmt(error, [view, path, this]));
+        }
+
+        __exports__.helperMissingHelper = helperMissingHelper; /**
+              Registers a helper in Handlebars that will be called if no property with the
+              given name can be found on the current context object, and no helper with
+              that name is registered.
+
+              This throws an exception with a more helpful error message so the user can
+              track down where the problem is happening.
+
+              @private
+              @method helperMissing
+              @for Ember.Handlebars.helpers
+              @param {String} path
+              @param {Hash} options
+            */
+        function blockHelperMissingHelper(path) {
+            if (!resolveHelper) {
+                resolveHelper = requireModule('ember-handlebars/helpers/binding')['resolveHelper'];
+            }
+            // ES6TODO: stupid circular dep
+
+            var options = arguments[arguments.length - 1];
+
+            Ember.assert(&quot;`blockHelperMissing` was invoked without a helper name, which &quot; +
+            &quot;is most likely due to a mismatch between the version of &quot; +
+            &quot;Ember.js you're running now and the one used to precompile your &quot; +
+            &quot;templates. Please make sure the version of &quot; +
+            &quot;`ember-handlebars-compiler` you're using is up to date.&quot;, path);
+
+            var helper = resolveHelper(options.data.view.container, path);
+
+            if (helper) {
+                return helper.apply(this, slice.call(arguments, 1));
+            } else {
+                return helpers.helperMissing.call(this, path);
+            }
+        }
+
+        __exports__.blockHelperMissingHelper = blockHelperMissingHelper; /**
+              Register a bound handlebars helper. Bound helpers behave similarly to regular
+              handlebars helpers, with the added ability to re-render when the underlying data
+              changes.
+
+              ## Simple example
+
+              ```javascript
+              Ember.Handlebars.registerBoundHelper('capitalize', function(value) {
+                return Ember.String.capitalize(value);
+              });
+              ```
+
+              The above bound helper can be used inside of templates as follows:
+
+              ```handlebars
+              {{capitalize name}}
+              ```
+
+              In this case, when the `name` property of the template's context changes,
+              the rendered value of the helper will update to reflect this change.
+
+              ## Example with options
+
+              Like normal handlebars helpers, bound helpers have access to the options
+              passed into the helper call.
+
+              ```javascript
+              Ember.Handlebars.registerBoundHelper('repeat', function(value, options) {
+                var count = options.hash.count;
+                var a = [];
+                while(a.length &lt; count) {
+                    a.push(value);
+                }
+                return a.join('');
+              });
+              ```
+
+              This helper could be used in a template as follows:
+
+              ```handlebars
+              {{repeat text count=3}}
+              ```
+
+              ## Example with bound options
+
+              Bound hash options are also supported. Example:
+
+              ```handlebars
+              {{repeat text count=numRepeats}}
+              ```
+
+              In this example, count will be bound to the value of
+              the `numRepeats` property on the context. If that property
+              changes, the helper will be re-rendered.
+
+              ## Example with extra dependencies
+
+              The `Ember.Handlebars.registerBoundHelper` method takes a variable length
+              third parameter which indicates extra dependencies on the passed in value.
+              This allows the handlebars helper to update when these dependencies change.
+
+              ```javascript
+              Ember.Handlebars.registerBoundHelper('capitalizeName', function(value) {
+                return value.get('name').toUpperCase();
+              }, 'name');
+              ```
+
+              ## Example with multiple bound properties
+
+              `Ember.Handlebars.registerBoundHelper` supports binding to
+              multiple properties, e.g.:
+
+              ```javascript
+              Ember.Handlebars.registerBoundHelper('concatenate', function() {
+                var values = Array.prototype.slice.call(arguments, 0, -1);
+                return values.join('||');
+              });
+              ```
+
+              Which allows for template syntax such as `{{concatenate prop1 prop2}}` or
+              `{{concatenate prop1 prop2 prop3}}`. If any of the properties change,
+              the helper will re-render.  Note that dependency keys cannot be
+              using in conjunction with multi-property helpers, since it is ambiguous
+              which property the dependent keys would belong to.
+
+              ## Use with unbound helper
+
+              The `{{unbound}}` helper can be used with bound helper invocations
+              to render them in their unbound form, e.g.
+
+              ```handlebars
+              {{unbound capitalize name}}
+              ```
+
+              In this example, if the name property changes, the helper
+              will not re-render.
+
+              ## Use with blocks not supported
+
+              Bound helpers do not support use with Handlebars blocks or
+              the addition of child views of any kind.
+
+              @method registerBoundHelper
+              @for Ember.Handlebars
+              @param {String} name
+              @param {Function} function
+              @param {String} dependentKeys*
+            */
+        function registerBoundHelper(name, fn) {
+            var boundHelperArgs = slice.call(arguments, 1),
+            boundFn = makeBoundHelper.apply(this, boundHelperArgs);
+            EmberHandlebars.registerHelper(name, boundFn);
+        }
+
+        __exports__.registerBoundHelper = registerBoundHelper; /**
+              A helper function used by `registerBoundHelper`. Takes the
+              provided Handlebars helper function fn and returns it in wrapped
+              bound helper form.
+
+              The main use case for using this outside of `registerBoundHelper`
+              is for registering helpers on the container:
+
+              ```js
+              var boundHelperFn = Ember.Handlebars.makeBoundHelper(function(word) {
+                return word.toUpperCase();
+              });
+
+              container.register('helper:my-bound-helper', boundHelperFn);
+              ```
+
+              In the above example, if the helper function hadn't been wrapped in
+              `makeBoundHelper`, the registered helper would be unbound.
+
+              @method makeBoundHelper
+              @for Ember.Handlebars
+              @param {Function} function
+              @param {String} dependentKeys*
+              @since 1.2.0
+            */
+        function makeBoundHelper(fn) {
+            if (!SimpleHandlebarsView) {
+                SimpleHandlebarsView = requireModule('ember-handlebars/views/handlebars_bound_view')['SimpleHandlebarsView'];
+            }
+            // ES6TODO: stupid circular dep
+
+            var dependentKeys = slice.call(arguments, 1);
+
+            function helper() {
+                var properties = slice.call(arguments, 0, -1),
+                numProperties = properties.length,
+                options = arguments[arguments.length - 1],
+                normalizedProperties = [],
+                data = options.data,
+                types = data.isUnbound ? slice.call(options.types, 1) : options.types,
+                hash = options.hash,
+                view = data.view,
+                contexts = options.contexts,
+                currentContext = (contexts &amp;&amp; contexts.length) ? contexts[0] : this,
+                prefixPathForDependentKeys = '',
+                loc, len, hashOption,
+                boundOption, property,
+                normalizedValue = SimpleHandlebarsView.prototype.normalizedValue;
+
+                Ember.assert(&quot;registerBoundHelper-generated helpers do not support use with Handlebars blocks.&quot;, !options.fn);
+
+                // Detect bound options (e.g. countBinding=&quot;otherCount&quot;)
+                var boundOptions = hash.boundOptions = {};
+                for (hashOption in hash) {
+                    if (IS_BINDING.test(hashOption)) {
+                        // Lop off 'Binding' suffix.
+                        boundOptions[hashOption.slice(0, -7)] = hash[hashOption];
+                    }
+                }
+
+                // Expose property names on data.properties object.
+                var watchedProperties = [];
+                data.properties = [];
+                for (loc = 0; loc &lt; numProperties; ++loc) {
+                    data.properties.push(properties[loc]);
+                    if (types[loc] === 'ID') {
+                        var normalizedProp = normalizePath(currentContext, properties[loc], data);
+                        normalizedProperties.push(normalizedProp);
+                        watchedProperties.push(normalizedProp);
+                    } else {
+                        if (data.isUnbound) {
+                            normalizedProperties.push({
+                                path: properties[loc]
+                            });
+                        } else {
+                            normalizedProperties.push(null);
+                        }
+                    }
+                }
+
+                // Handle case when helper invocation is preceded by `unbound`, e.g.
+                // {{unbound myHelper foo}}
+                if (data.isUnbound) {
+                    return evaluateUnboundHelper(this, fn, normalizedProperties, options);
+                }
+
+                var bindView = new SimpleHandlebarsView(null, null, !options.hash.unescaped, options.data);
+
+                // Override SimpleHandlebarsView's method for generating the view's content.
+                bindView.normalizedValue = function() {
+                    var args = [], boundOption;
+
+                    // Copy over bound hash options.
+                    for (boundOption in boundOptions) {
+                        if (!boundOptions.hasOwnProperty(boundOption)) {
+                            continue;
+                        }
+                        property = normalizePath(currentContext, boundOptions[boundOption], data);
+                        bindView.path = property.path;
+                        bindView.pathRoot = property.root;
+                        hash[boundOption] = normalizedValue.call(bindView);
+                    }
+
+                    for (loc = 0; loc &lt; numProperties; ++loc) {
+                        property = normalizedProperties[loc];
+                        if (property) {
+                            bindView.path = property.path;
+                            bindView.pathRoot = property.root;
+                            args.push(normalizedValue.call(bindView));
+                        } else {
+                            args.push(properties[loc]);
+                        }
+                    }
+                    args.push(options);
+
+                    // Run the supplied helper function.
+                    return fn.apply(currentContext, args);
+                };
+
+                view.appendChild(bindView);
+
+                // Assemble list of watched properties that'll re-render this helper.
+                for (boundOption in boundOptions) {
+                    if (boundOptions.hasOwnProperty(boundOption)) {
+                        watchedProperties.push(normalizePath(currentContext, boundOptions[boundOption], data));
+                    }
+                }
+
+                // Observe each property.
+                for (loc = 0, len = watchedProperties.length; loc &lt; len; ++loc) {
+                    property = watchedProperties[loc];
+                    view.registerObserver(property.root, property.path, bindView, bindView.rerender);
+                }
+
+                if (types[0] !== 'ID' || normalizedProperties.length === 0) {
+                    return;
+                }
+
+                // Add dependent key observers to the first param
+                var normalized = normalizedProperties[0],
+                pathRoot = normalized.root,
+                path = normalized.path;
+
+                if (!isEmpty(path)) {
+                    prefixPathForDependentKeys = path + '.';
+                }
+                for (var i = 0, l = dependentKeys.length; i &lt; l; i++) {
+                    view.registerObserver(pathRoot, prefixPathForDependentKeys + dependentKeys[i], bindView, bindView.rerender);
+                }
+            }
+
+            helper._rawFunction = fn;
+            return helper;
+        }
+
+        /**
+              Renders the unbound form of an otherwise bound helper function.
+
+              @private
+              @method evaluateUnboundHelper
+              @param {Function} fn
+              @param {Object} context
+              @param {Array} normalizedProperties
+              @param {String} options
+            */
+        function evaluateUnboundHelper(context, fn, normalizedProperties, options) {
+            var args = [],
+            hash = options.hash,
+            boundOptions = hash.boundOptions,
+            types = slice.call(options.types, 1),
+            loc,
+            len,
+            property,
+            propertyType,
+            boundOption;
+
+            for (boundOption in boundOptions) {
+                if (!boundOptions.hasOwnProperty(boundOption)) {
+                    continue;
+                }
+                hash[boundOption] = handlebarsGet(context, boundOptions[boundOption], options);
+            }
+
+            for (loc = 0, len = normalizedProperties.length; loc &lt; len; ++loc) {
+                property = normalizedProperties[loc];
+                propertyType = types[loc];
+                if (propertyType === &quot;ID&quot;) {
+                    args.push(handlebarsGet(property.root, property.path, options));
+                } else {
+                    args.push(property.path);
+                }
+            }
+            args.push(options);
+            return fn.apply(context, args);
+        }
+
+        /**
+              Overrides Handlebars.template so that we can distinguish
+              user-created, top-level templates from inner contexts.
+
+              @private
+              @method template
+              @for Ember.Handlebars
+              @param {String} spec
+            */
+        function template(spec) {
+            var t = originalTemplate(spec);
+            t.isTop = true;
+            return t;
+        }
+
+        __exports__.template = template;
+        __exports__.normalizePath = normalizePath;
+        __exports__.makeBoundHelper = makeBoundHelper;
+        __exports__.handlebarsGet = handlebarsGet;
+        __exports__.evaluateUnboundHelper = evaluateUnboundHelper;
+    });
+    define(&quot;ember-handlebars/helpers/binding&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-handlebars-compiler&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/array&quot;, &quot;ember-views/views/view&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/binding&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-runtime/keys&quot;, &quot;ember-handlebars/views/handlebars_bound_view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert, Ember.warn, uuid
+        // var emberAssert = Ember.assert, Ember.warn = Ember.warn;
+
+        var EmberHandlebars = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var apply = __dependency5__.apply;
+        var uuid = __dependency5__.uuid;
+        var fmt = __dependency6__.fmt;
+        var o_create = __dependency7__.create;
+        var isNone = __dependency8__[&quot;default&quot;];
+        var EnumerableUtils = __dependency9__[&quot;default&quot;];
+        var forEach = __dependency10__.forEach;
+        var View = __dependency11__[&quot;default&quot;];
+        var run = __dependency12__[&quot;default&quot;];
+        var removeObserver = __dependency13__.removeObserver;
+        var isGlobalPath = __dependency14__.isGlobalPath;
+        var emberBind = __dependency14__.bind;
+        var jQuery = __dependency15__[&quot;default&quot;];
+        var isArray = __dependency5__.isArray;
+        var handlebarsGetEscaped = __dependency16__.getEscaped;
+        var keys = __dependency17__[&quot;default&quot;];
+
+        var _HandlebarsBoundView = __dependency18__._HandlebarsBoundView;
+        var SimpleHandlebarsView = __dependency18__.SimpleHandlebarsView;
+
+        var normalizePath = __dependency16__.normalizePath;
+        var handlebarsGet = __dependency16__.handlebarsGet;
+        var getEscaped = __dependency16__.getEscaped;
+
+        var guidFor = __dependency5__.guidFor;
+        var typeOf = __dependency5__.typeOf;
+
+        var helpers = EmberHandlebars.helpers;
+        var SafeString = EmberHandlebars.SafeString;
+
+        function exists(value) {
+            return !isNone(value);
+        }
+
+        var WithView = _HandlebarsBoundView.extend({
+            init: function() {
+                var controller;
+
+                apply(this, this._super, arguments);
+
+                var keywords = this.templateData.keywords;
+                var keywordName = this.templateHash.keywordName;
+                var keywordPath = this.templateHash.keywordPath;
+                var controllerName = this.templateHash.controller;
+                var preserveContext = this.preserveContext;
+
+                if (controllerName) {
+                    var previousContext = this.previousContext;
+                    controller = this.container.lookupFactory('controller:' + controllerName).create({
+                        parentController: previousContext,
+                        target: previousContext
+                    });
+
+                    this._generatedController = controller;
+
+                    if (!preserveContext) {
+                        this.set('controller', controller);
+
+                        this.valueNormalizerFunc = function(result) {
+                            controller.set('model', result);
+                            return controller;
+                        };
+                    } else {
+                        var controllerPath = jQuery.expando + guidFor(controller);
+                        keywords[controllerPath] = controller;
+                        emberBind(keywords, controllerPath + '.model', keywordPath);
+                        keywordPath = controllerPath;
+                    }
+                }
+
+                if (preserveContext) {
+                    emberBind(keywords, keywordName, keywordPath);
+                }
+
+            },
+            willDestroy: function() {
+                this._super();
+
+                if (this._generatedController) {
+                    this._generatedController.destroy();
+                }
+            }
+        });
+
+        // Binds a property into the DOM. This will create a hook in DOM that the
+        // KVO system will look for and update if the property changes.
+        function bind(property, options, preserveContext, shouldDisplay, valueNormalizer, childProperties) {
+            var data = options.data,
+            fn = options.fn,
+            inverse = options.inverse,
+            view = data.view,
+            normalized, observer, i;
+
+            // we relied on the behavior of calling without
+            // context to mean this === window, but when running
+            // &quot;use strict&quot;, it's possible for this to === undefined;
+            var currentContext = this || window;
+
+            normalized = normalizePath(currentContext, property, data);
+
+            // Set up observers for observable objects
+            if ('object' === typeof this) {
+                if (data.insideGroup) {
+                    observer = function() {
+                        while (view._contextView) {
+                            view = view._contextView;
+                        }
+                        run.once(view, 'rerender');
+                    };
+
+                    var template, context, result = handlebarsGet(currentContext, property, options);
+
+                    result = valueNormalizer ? valueNormalizer(result) : result;
+
+                    context = preserveContext ? currentContext : result;
+                    if (shouldDisplay(result)) {
+                        template = fn;
+                    } else if (inverse) {
+                        template = inverse;
+                    }
+
+                    template(context, {
+                        data: options.data 
+                    });
+                } else {
+                    var viewClass = _HandlebarsBoundView;
+                    var viewOptions = {
+                        preserveContext: preserveContext,
+                        shouldDisplayFunc: shouldDisplay,
+                        valueNormalizerFunc: valueNormalizer,
+                        displayTemplate: fn,
+                        inverseTemplate: inverse,
+                        path: property,
+                        pathRoot: currentContext,
+                        previousContext: currentContext,
+                        isEscaped: !options.hash.unescaped,
+                        templateData: options.data,
+                        templateHash: options.hash,
+                        helperName: options.helperName
+                    };
+
+                    if (options.isWithHelper) {
+                        viewClass = WithView;
+                    }
+
+                    // Create the view that will wrap the output of this template/property
+                    // and add it to the nearest view's childViews array.
+                    // See the documentation of Ember._HandlebarsBoundView for more.
+                    var bindView = view.createChildView(viewClass, viewOptions);
+
+                    view.appendChild(bindView);
+
+                    observer = function() {
+                        run.scheduleOnce('render', bindView, 'rerenderIfNeeded');
+                    };
+                }
+
+                // Observes the given property on the context and
+                // tells the Ember._HandlebarsBoundView to re-render. If property
+                // is an empty string, we are printing the current context
+                // object ({{this}}) so updating it is not our responsibility.
+                if (normalized.path !== '') {
+                    view.registerObserver(normalized.root, normalized.path, observer);
+                    if (childProperties) {
+                        for (i = 0; i &lt; childProperties.length; i++) {
+                            view.registerObserver(normalized.root, normalized.path + '.' + childProperties[i], observer);
+                        }
+                    }
+                }
+            } else {
+                // The object is not observable, so just render it out and
+                // be done with it.
+                data.buffer.push(handlebarsGetEscaped(currentContext, property, options));
+            }
+        }
+
+        function simpleBind(currentContext, property, options) {
+            var data = options.data,
+            view = data.view,
+            normalized, observer, pathRoot, output;
+
+            normalized = normalizePath(currentContext, property, data);
+            pathRoot = normalized.root;
+
+            // Set up observers for observable objects
+            if (pathRoot &amp;&amp; ('object' === typeof pathRoot)) {
+                if (data.insideGroup) {
+                    observer = function() {
+                        while (view._contextView) {
+                            view = view._contextView;
+                        }
+                        run.once(view, 'rerender');
+                    };
+
+                    output = handlebarsGetEscaped(currentContext, property, options);
+
+                    data.buffer.push(output);
+                } else {
+                    var bindView = new SimpleHandlebarsView(
+                    property, currentContext, !options.hash.unescaped, options.data
+                    );
+
+                    bindView._parentView = view;
+                    view.appendChild(bindView);
+
+                    observer = function() {
+                        run.scheduleOnce('render', bindView, 'rerender');
+                    };
+                }
+
+                // Observes the given property on the context and
+                // tells the Ember._HandlebarsBoundView to re-render. If property
+                // is an empty string, we are printing the current context
+                // object ({{this}}) so updating it is not our responsibility.
+                if (normalized.path !== '') {
+                    view.registerObserver(normalized.root, normalized.path, observer);
+                }
+            } else {
+                // The object is not observable, so just render it out and
+                // be done with it.
+                output = handlebarsGetEscaped(currentContext, property, options);
+                data.buffer.push(output);
+            }
+        }
+
+        function shouldDisplayIfHelperContent(result) {
+            var truthy = result &amp;&amp; get(result, 'isTruthy');
+            if (typeof truthy === 'boolean') {
+                return truthy;
+            }
+
+            if (isArray(result)) {
+                return get(result, 'length') !== 0;
+            } else {
+                return !!result;
+            }
+        }
+
+        /**
+              '_triageMustache' is used internally select between a binding, helper, or component for
+              the given context. Until this point, it would be hard to determine if the
+              mustache is a property reference or a regular helper reference. This triage
+              helper resolves that.
+
+              This would not be typically invoked by directly.
+
+              @private
+              @method _triageMustache
+              @for Ember.Handlebars.helpers
+              @param {String} property Property/helperID to triage
+              @param {Object} options hash of template/rendering options
+              @return {String} HTML string
+            */
+        function _triageMustacheHelper(property, options) {
+            Ember.assert(&quot;You cannot pass more than one argument to the _triageMustache helper&quot;, arguments.length &lt;= 2);
+
+            var helper = EmberHandlebars.resolveHelper(options.data.view.container, property);
+            if (helper) {
+                return helper.call(this, options);
+            }
+
+            return helpers.bind.call(this, property, options);
+        }
+
+        /**
+              Used to lookup/resolve handlebars helpers. The lookup order is:
+
+              * Look for a registered helper
+              * If a dash exists in the name:
+                * Look for a helper registed in the container
+                * Use Ember.ComponentLookup to find an Ember.Component that resolves
+                  to the given name
+
+              @private
+              @method resolveHelper
+              @param {Container} container
+              @param {String} name the name of the helper to lookup
+              @return {Handlebars Helper}
+            */
+        function resolveHelper(container, name) {
+            if (helpers[name]) {
+                return helpers[name];
+            }
+
+            if (!container || name.indexOf('-') === -1) {
+                return;
+            }
+
+            var helper = container.lookup('helper:' + name);
+            if (!helper) {
+                var componentLookup = container.lookup('component-lookup:main');
+                Ember.assert(&quot;Could not find 'component-lookup:main' on the provided container, which is necessary for performing component lookups&quot;, componentLookup);
+
+                var Component = componentLookup.lookupFactory(name, container);
+                if (Component) {
+                    helper = EmberHandlebars.makeViewHelper(Component);
+                    container.register('helper:' + name, helper);
+                }
+            }
+            return helper;
+        }
+
+
+        /**
+              `bind` can be used to display a value, then update that value if it
+              changes. For example, if you wanted to print the `title` property of
+              `content`:
+
+              ```handlebars
+              {{bind &quot;content.title&quot;}}
+              ```
+
+              This will return the `title` property as a string, then create a new observer
+              at the specified path. If it changes, it will update the value in DOM. Note
+              that if you need to support IE7 and IE8 you must modify the model objects
+              properties using `Ember.get()` and `Ember.set()` for this to work as it
+              relies on Ember's KVO system. For all other browsers this will be handled for
+              you automatically.
+
+              @private
+              @method bind
+              @for Ember.Handlebars.helpers
+              @param {String} property Property to bind
+              @param {Function} fn Context to provide for rendering
+              @return {String} HTML string
+            */
+        function bindHelper(property, options) {
+            Ember.assert(&quot;You cannot pass more than one argument to the bind helper&quot;, arguments.length &lt;= 2);
+
+            var context = (options.contexts &amp;&amp; options.contexts.length) ? options.contexts[0] : this;
+
+            if (!options.fn) {
+                return simpleBind(context, property, options);
+            }
+
+            options.helperName = 'bind';
+
+            return bind.call(context, property, options, false, exists);
+        }
+
+        /**
+              Use the `boundIf` helper to create a conditional that re-evaluates
+              whenever the truthiness of the bound value changes.
+
+              ```handlebars
+              {{#boundIf &quot;content.shouldDisplayTitle&quot;}}
+                {{content.title}}
+              {{/boundIf}}
+              ```
+
+              @private
+              @method boundIf
+              @for Ember.Handlebars.helpers
+              @param {String} property Property to bind
+              @param {Function} fn Context to provide for rendering
+              @return {String} HTML string
+            */
+        function boundIfHelper(property, fn) {
+            var context = (fn.contexts &amp;&amp; fn.contexts.length) ? fn.contexts[0] : this;
+
+            fn.helperName = fn.helperName || 'boundIf';
+
+            return bind.call(context, property, fn, true, shouldDisplayIfHelperContent, shouldDisplayIfHelperContent, ['isTruthy', 'length']);
+        }
+
+
+        /**
+              @private
+
+              Use the `unboundIf` helper to create a conditional that evaluates once.
+
+              ```handlebars
+              {{#unboundIf &quot;content.shouldDisplayTitle&quot;}}
+                {{content.title}}
+              {{/unboundIf}}
+              ```
+
+              @method unboundIf
+              @for Ember.Handlebars.helpers
+              @param {String} property Property to bind
+              @param {Function} fn Context to provide for rendering
+              @return {String} HTML string
+              @since 1.4.0
+            */
+        function unboundIfHelper(property, fn) {
+            var context = (fn.contexts &amp;&amp; fn.contexts.length) ? fn.contexts[0] : this,
+            data = fn.data,
+            template = fn.fn,
+            inverse = fn.inverse,
+            normalized, propertyValue, result;
+
+            normalized = normalizePath(context, property, data);
+            propertyValue = handlebarsGet(context, property, fn);
+
+            if (!shouldDisplayIfHelperContent(propertyValue)) {
+                template = inverse;
+            }
+
+            template(context, {
+                data: data 
+            });
+        }
+
+        /**
+              Use the `{{with}}` helper when you want to scope context. Take the following code as an example:
+
+              ```handlebars
+              &lt;h5&gt;{{user.name}}&lt;/h5&gt;
+
+              &lt;div class=&quot;role&quot;&gt;
+                &lt;h6&gt;{{user.role.label}}&lt;/h6&gt;
+                &lt;span class=&quot;role-id&quot;&gt;{{user.role.id}}&lt;/span&gt;
+
+                &lt;p class=&quot;role-desc&quot;&gt;{{user.role.description}}&lt;/p&gt;
+              &lt;/div&gt;
+              ```
+
+              `{{with}}` can be our best friend in these cases,
+              instead of writing `user.role.*` over and over, we use `{{#with user.role}}`.
+              Now the context within the `{{#with}} .. {{/with}}` block is `user.role` so you can do the following:
+
+              ```handlebars
+              &lt;h5&gt;{{user.name}}&lt;/h5&gt;
+
+              &lt;div class=&quot;role&quot;&gt;
+                {{#with user.role}}
+                  &lt;h6&gt;{{label}}&lt;/h6&gt;
+                  &lt;span class=&quot;role-id&quot;&gt;{{id}}&lt;/span&gt;
+
+                  &lt;p class=&quot;role-desc&quot;&gt;{{description}}&lt;/p&gt;
+                {{/with}}
+              &lt;/div&gt;
+              ```
+
+              ### `as` operator
+
+              This operator aliases the scope to a new name. It's helpful for semantic clarity and to retain
+              default scope or to reference from another `{{with}}` block.
+
+              ```handlebars
+              // posts might not be
+              {{#with user.posts as blogPosts}}
+                &lt;div class=&quot;notice&quot;&gt;
+                  There are {{blogPosts.length}} blog posts written by {{user.name}}.
+                &lt;/div&gt;
+
+                {{#each post in blogPosts}}
+                  &lt;li&gt;{{post.title}}&lt;/li&gt;
+                {{/each}}
+              {{/with}}
+              ```
+
+              Without the `as` operator, it would be impossible to reference `user.name` in the example above.
+
+              NOTE: The alias should not reuse a name from the bound property path.
+              For example: `{{#with foo.bar as foo}}` is not supported because it attempts to alias using
+              the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`.
+
+              ### `controller` option
+
+              Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of
+              the specified controller with the new context as its content.
+
+              This is very similar to using an `itemController` option with the `{{each}}` helper.
+
+              ```handlebars
+              {{#with users.posts controller='userBlogPosts'}}
+                {{!- The current context is wrapped in our controller instance }}
+              {{/with}}
+              ```
+
+              In the above example, the template provided to the `{{with}}` block is now wrapped in the
+              `userBlogPost` controller, which provides a very elegant way to decorate the context with custom
+              functions/properties.
+
+              @method with
+              @for Ember.Handlebars.helpers
+              @param {Function} context
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        function withHelper(context, options) {
+            var bindContext, preserveContext, controller, helperName = 'with';
+
+            if (arguments.length === 4) {
+                var keywordName, path, rootPath, normalized, contextPath;
+
+                Ember.assert(&quot;If you pass more than one argument to the with helper, it must be in the form #with foo as bar&quot;, arguments[1] === &quot;as&quot;);
+                options = arguments[3];
+                keywordName = arguments[2];
+                path = arguments[0];
+
+                if (path) {
+                    helperName += ' ' + path + ' as ' + keywordName;
+                }
+
+                Ember.assert(&quot;You must pass a block to the with helper&quot;, options.fn &amp;&amp; options.fn !== Handlebars.VM.noop);
+
+                var localizedOptions = o_create(options);
+                localizedOptions.data = o_create(options.data);
+                localizedOptions.data.keywords = o_create(options.data.keywords || {});
+
+                if (isGlobalPath(path)) {
+                    contextPath = path;
+                } else {
+                    normalized = normalizePath(this, path, options.data);
+                    path = normalized.path;
+                    rootPath = normalized.root;
+
+                    // This is a workaround for the fact that you cannot bind separate objects
+                    // together. When we implement that functionality, we should use it here.
+                    var contextKey = jQuery.expando + guidFor(rootPath);
+                    localizedOptions.data.keywords[contextKey] = rootPath;
+                    // if the path is '' (&quot;this&quot;), just bind directly to the current context
+                    contextPath = path ? contextKey + '.' + path : contextKey;
+                }
+
+                localizedOptions.hash.keywordName = keywordName;
+                localizedOptions.hash.keywordPath = contextPath;
+
+                bindContext = this;
+                context = contextPath;
+                options = localizedOptions;
+                preserveContext = true;
+            } else {
+                Ember.assert(&quot;You must pass exactly one argument to the with helper&quot;, arguments.length === 2);
+                Ember.assert(&quot;You must pass a block to the with helper&quot;, options.fn &amp;&amp; options.fn !== Handlebars.VM.noop);
+
+                helperName += ' ' + context;
+                bindContext = options.contexts[0];
+                preserveContext = false;
+            }
+
+            options.helperName = helperName;
+            options.isWithHelper = true;
+
+            return bind.call(bindContext, context, options, preserveContext, exists);
+        }
+        /**
+              See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf)
+              and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf)
+
+              @method if
+              @for Ember.Handlebars.helpers
+              @param {Function} context
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        function ifHelper(context, options) {
+            Ember.assert(&quot;You must pass exactly one argument to the if helper&quot;, arguments.length === 2);
+            Ember.assert(&quot;You must pass a block to the if helper&quot;, options.fn &amp;&amp; options.fn !== Handlebars.VM.noop);
+
+            options.helperName = options.helperName || ('if ' + context);
+
+            if (options.data.isUnbound) {
+                return helpers.unboundIf.call(options.contexts[0], context, options);
+            } else {
+                return helpers.boundIf.call(options.contexts[0], context, options);
+            }
+        }
+
+        /**
+              @method unless
+              @for Ember.Handlebars.helpers
+              @param {Function} context
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        function unlessHelper(context, options) {
+            Ember.assert(&quot;You must pass exactly one argument to the unless helper&quot;, arguments.length === 2);
+            Ember.assert(&quot;You must pass a block to the unless helper&quot;, options.fn &amp;&amp; options.fn !== Handlebars.VM.noop);
+
+            var fn = options.fn, inverse = options.inverse, helperName = 'unless';
+
+            if (context) {
+                helperName += ' ' + context;
+            }
+
+            options.fn = inverse;
+            options.inverse = fn;
+
+            options.helperName = options.helperName || helperName;
+
+            if (options.data.isUnbound) {
+                return helpers.unboundIf.call(options.contexts[0], context, options);
+            } else {
+                return helpers.boundIf.call(options.contexts[0], context, options);
+            }
+        }
+
+        /**
+              `bind-attr` allows you to create a binding between DOM element attributes and
+              Ember objects. For example:
+
+              ```handlebars
+              &lt;img {{bind-attr src=&quot;imageUrl&quot; alt=&quot;imageTitle&quot;}}&gt;
+              ```
+
+              The above handlebars template will fill the `&lt;img&gt;`'s `src` attribute will
+              the value of the property referenced with `&quot;imageUrl&quot;` and its `alt`
+              attribute with the value of the property referenced with `&quot;imageTitle&quot;`.
+
+              If the rendering context of this template is the following object:
+
+              ```javascript
+              {
+                imageUrl: 'http://lolcats.info/haz-a-funny',
+                imageTitle: 'A humorous image of a cat'
+              }
+              ```
+
+              The resulting HTML output will be:
+
+              ```html
+              &lt;img src=&quot;http://lolcats.info/haz-a-funny&quot; alt=&quot;A humorous image of a cat&quot;&gt;
+              ```
+
+              `bind-attr` cannot redeclare existing DOM element attributes. The use of `src`
+              in the following `bind-attr` example will be ignored and the hard coded value
+              of `src=&quot;/failwhale.gif&quot;` will take precedence:
+
+              ```handlebars
+              &lt;img src=&quot;/failwhale.gif&quot; {{bind-attr src=&quot;imageUrl&quot; alt=&quot;imageTitle&quot;}}&gt;
+              ```
+
+              ### `bind-attr` and the `class` attribute
+
+              `bind-attr` supports a special syntax for handling a number of cases unique
+              to the `class` DOM element attribute. The `class` attribute combines
+              multiple discrete values into a single attribute as a space-delimited
+              list of strings. Each string can be:
+
+              * a string return value of an object's property.
+              * a boolean return value of an object's property
+              * a hard-coded value
+
+              A string return value works identically to other uses of `bind-attr`. The
+              return value of the property will become the value of the attribute. For
+              example, the following view and template:
+
+              ```javascript
+                AView = View.extend({
+                  someProperty: function() {
+                    return &quot;aValue&quot;;
+                  }.property()
+                })
+              ```
+
+              ```handlebars
+              &lt;img {{bind-attr class=&quot;view.someProperty}}&gt;
+              ```
+
+              Result in the following rendered output:
+
+              ```html
+              &lt;img class=&quot;aValue&quot;&gt;
+              ```
+
+              A boolean return value will insert a specified class name if the property
+              returns `true` and remove the class name if the property returns `false`.
+
+              A class name is provided via the syntax
+              `somePropertyName:class-name-if-true`.
+
+              ```javascript
+              AView = View.extend({
+                someBool: true
+              })
+              ```
+
+              ```handlebars
+              &lt;img {{bind-attr class=&quot;view.someBool:class-name-if-true&quot;}}&gt;
+              ```
+
+              Result in the following rendered output:
+
+              ```html
+              &lt;img class=&quot;class-name-if-true&quot;&gt;
+              ```
+
+              An additional section of the binding can be provided if you want to
+              replace the existing class instead of removing it when the boolean
+              value changes:
+
+              ```handlebars
+              &lt;img {{bind-attr class=&quot;view.someBool:class-name-if-true:class-name-if-false&quot;}}&gt;
+              ```
+
+              A hard-coded value can be used by prepending `:` to the desired
+              class name: `:class-name-to-always-apply`.
+
+              ```handlebars
+              &lt;img {{bind-attr class=&quot;:class-name-to-always-apply&quot;}}&gt;
+              ```
+
+              Results in the following rendered output:
+
+              ```html
+              &lt;img class=&quot;class-name-to-always-apply&quot;&gt;
+              ```
+
+              All three strategies - string return value, boolean return value, and
+              hard-coded value – can be combined in a single declaration:
+
+              ```handlebars
+              &lt;img {{bind-attr class=&quot;:class-name-to-always-apply view.someBool:class-name-if-true view.someProperty&quot;}}&gt;
+              ```
+
+              @method bind-attr
+              @for Ember.Handlebars.helpers
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        function bindAttrHelper(options) {
+            var attrs = options.hash;
+
+            Ember.assert(&quot;You must specify at least one hash argument to bind-attr&quot;, !!keys(attrs).length);
+
+            var view = options.data.view;
+            var ret = [];
+
+            // we relied on the behavior of calling without
+            // context to mean this === window, but when running
+            // &quot;use strict&quot;, it's possible for this to === undefined;
+            var ctx = this || window;
+
+            // Generate a unique id for this element. This will be added as a
+            // data attribute to the element so it can be looked up when
+            // the bound property changes.
+            var dataId = uuid();
+
+            // Handle classes differently, as we can bind multiple classes
+            var classBindings = attrs['class'];
+            if (classBindings != null) {
+                var classResults = bindClasses(ctx, classBindings, view, dataId, options);
+
+                ret.push('class=&quot;' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '&quot;');
+                delete attrs['class'];
+            }
+
+            var attrKeys = keys(attrs);
+
+            // For each attribute passed, create an observer and emit the
+            // current value of the property as an attribute.
+            forEach.call(attrKeys, function(attr) {
+                var path = attrs[attr],
+                normalized;
+
+                Ember.assert(fmt(&quot;You must provide an expression as the value of bound attribute. You specified: %@=%@&quot;, [attr, path]), typeof path === 'string');
+
+                normalized = normalizePath(ctx, path, options.data);
+
+                var value = (path === 'this') ? normalized.root : handlebarsGet(ctx, path, options),
+                type = typeOf(value);
+
+                Ember.assert(fmt(&quot;Attributes must be numbers, strings or booleans, not %@&quot;, [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean');
+
+                var observer;
+
+                observer = function observer() {
+                    var result = handlebarsGet(ctx, path, options);
+
+                    Ember.assert(fmt(&quot;Attributes must be numbers, strings or booleans, not %@&quot;, [result]),
+                    result === null || result === undefined || typeof result === 'number' ||
+                    typeof result === 'string' || typeof result === 'boolean');
+
+                    var elem = view.$(&quot;[data-bindattr-&quot; + dataId + &quot;='&quot; + dataId + &quot;']&quot;);
+
+                    // If we aren't able to find the element, it means the element
+                    // to which we were bound has been removed from the view.
+                    // In that case, we can assume the template has been re-rendered
+                    // and we need to clean up the observer.
+                    if (!elem || elem.length === 0) {
+                        removeObserver(normalized.root, normalized.path, observer);
+                        return;
+                    }
+
+                    View.applyAttributeBindings(elem, attr, result);
+                };
+
+                // Add an observer to the view for when the property changes.
+                // When the observer fires, find the element using the
+                // unique data id and update the attribute to the new value.
+                // Note: don't add observer when path is 'this' or path
+                // is whole keyword e.g. {{#each x in list}} ... {{bind-attr attr=&quot;x&quot;}}
+                if (path !== 'this' &amp;&amp; !(normalized.isKeyword &amp;&amp; normalized.path === '' )) {
+                    view.registerObserver(normalized.root, normalized.path, observer);
+                }
+
+                // if this changes, also change the logic in ember-views/lib/views/view.js
+                if ((type === 'string' || (type === 'number' &amp;&amp; !isNaN(value)))) {
+                    ret.push(attr + '=&quot;' + Handlebars.Utils.escapeExpression(value) + '&quot;');
+                } else if (value &amp;&amp; type === 'boolean') {
+                    // The developer controls the attr name, so it should always be safe
+                    ret.push(attr + '=&quot;' + attr + '&quot;');
+                }
+            }, this);
+
+            // Add the unique identifier
+            // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG
+            ret.push('data-bindattr-' + dataId + '=&quot;' + dataId + '&quot;');
+            return new SafeString(ret.join(' '));
+        }
+
+        /**
+              See `bind-attr`
+
+              @method bindAttr
+              @for Ember.Handlebars.helpers
+              @deprecated
+              @param {Function} context
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        function bindAttrHelperDeprecated() {
+            Ember.warn(&quot;The 'bindAttr' view helper is deprecated in favor of 'bind-attr'&quot;);
+            return helpers['bind-attr'].apply(this, arguments);
+        }
+
+        /**
+              Helper that, given a space-separated string of property paths and a context,
+              returns an array of class names. Calling this method also has the side
+              effect of setting up observers at those property paths, such that if they
+              change, the correct class name will be reapplied to the DOM element.
+
+              For example, if you pass the string &quot;fooBar&quot;, it will first look up the
+              &quot;fooBar&quot; value of the context. If that value is true, it will add the
+              &quot;foo-bar&quot; class to the current element (i.e., the dasherized form of
+              &quot;fooBar&quot;). If the value is a string, it will add that string as the class.
+              Otherwise, it will not add any new class name.
+
+              @private
+              @method bindClasses
+              @for Ember.Handlebars
+              @param {Ember.Object} context The context from which to lookup properties
+              @param {String} classBindings A string, space-separated, of class bindings
+                to use
+              @param {View} view The view in which observers should look for the
+                element to update
+              @param {Srting} bindAttrId Optional bindAttr id used to lookup elements
+              @return {Array} An array of class names to add
+            */
+        function bindClasses(context, classBindings, view, bindAttrId, options) {
+            var ret = [], newClass, value, elem;
+
+            // Helper method to retrieve the property from the context and
+            // determine which class string to return, based on whether it is
+            // a Boolean or not.
+            var classStringForPath = function(root, parsedPath, options) {
+                var val,
+                path = parsedPath.path;
+
+                if (path === 'this') {
+                    val = root;
+                } else if (path === '') {
+                    val = true;
+                } else {
+                    val = handlebarsGet(root, path, options);
+                }
+
+                return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
+            };
+
+            // For each property passed, loop through and setup
+            // an observer.
+            forEach.call(classBindings.split(' '), function(binding) {
+
+                // Variable in which the old class value is saved. The observer function
+                // closes over this variable, so it knows which string to remove when
+                // the property changes.
+                var oldClass;
+
+                var observer;
+
+                var parsedPath = View._parsePropertyPath(binding),
+                path = parsedPath.path,
+                pathRoot = context,
+                normalized;
+
+                if (path !== '' &amp;&amp; path !== 'this') {
+                    normalized = normalizePath(context, path, options.data);
+
+                    pathRoot = normalized.root;
+                    path = normalized.path;
+                }
+
+                // Set up an observer on the context. If the property changes, toggle the
+                // class name.
+                observer = function() {
+                    // Get the current value of the property
+                    newClass = classStringForPath(context, parsedPath, options);
+                    elem = bindAttrId ? view.$(&quot;[data-bindattr-&quot; + bindAttrId + &quot;='&quot; + bindAttrId + &quot;']&quot;) : view.$();
+
+                    // If we can't find the element anymore, a parent template has been
+                    // re-rendered and we've been nuked. Remove the observer.
+                    if (!elem || elem.length === 0) {
+                        removeObserver(pathRoot, path, observer);
+                    } else {
+                        // If we had previously added a class to the element, remove it.
+                        if (oldClass) {
+                            elem.removeClass(oldClass);
+                        }
+
+                        // If necessary, add a new class. Make sure we keep track of it so
+                        // it can be removed in the future.
+                        if (newClass) {
+                            elem.addClass(newClass);
+                            oldClass = newClass;
+                        } else {
+                            oldClass = null;
+                        }
+                    }
+                };
+
+                if (path !== '' &amp;&amp; path !== 'this') {
+                    view.registerObserver(pathRoot, path, observer);
+                }
+
+                // We've already setup the observer; now we just need to figure out the
+                // correct behavior right now on the first pass through.
+                value = classStringForPath(context, parsedPath, options);
+
+                if (value) {
+                    ret.push(value);
+
+                    // Make sure we save the current value so that it can be removed if the
+                    // observer fires.
+                    oldClass = value;
+                }
+            });
+
+            return ret;
+        }
+
+        __exports__.bind = bind;
+        __exports__._triageMustacheHelper = _triageMustacheHelper;
+        __exports__.resolveHelper = resolveHelper;
+        __exports__.bindHelper = bindHelper;
+        __exports__.boundIfHelper = boundIfHelper;
+        __exports__.unboundIfHelper = unboundIfHelper;
+        __exports__.withHelper = withHelper;
+        __exports__.ifHelper = ifHelper;
+        __exports__.unlessHelper = unlessHelper;
+        __exports__.bindAttrHelper = bindAttrHelper;
+        __exports__.bindAttrHelperDeprecated = bindAttrHelperDeprecated;
+        __exports__.bindClasses = bindClasses;
+    });
+    define(&quot;ember-handlebars/helpers/collection&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-handlebars-compiler&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-handlebars/helpers/view&quot;, &quot;ember-metal/computed&quot;, &quot;ember-views/views/collection_view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert, Ember.deprecate
+        var inspect = __dependency2__.inspect;
+
+        // var emberAssert = Ember.assert;
+        // emberDeprecate = Ember.deprecate;
+
+        var EmberHandlebars = __dependency3__[&quot;default&quot;];
+        var helpers = EmberHandlebars.helpers;
+
+        var fmt = __dependency4__.fmt;
+        var get = __dependency5__.get;
+        var handlebarsGet = __dependency6__.handlebarsGet;
+        var ViewHelper = __dependency7__.ViewHelper;
+        var computed = __dependency8__.computed;
+        var CollectionView = __dependency9__[&quot;default&quot;];
+
+        var alias = computed.alias;
+        /**
+              `{{collection}}` is a `Ember.Handlebars` helper for adding instances of
+              `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html)
+               for additional information on how a `CollectionView` functions.
+
+              `{{collection}}`'s primary use is as a block helper with a `contentBinding`
+              option pointing towards an `Ember.Array`-compatible object. An `Ember.View`
+              instance will be created for each item in its `content` property. Each view
+              will have its own `content` property set to the appropriate item in the
+              collection.
+
+              The provided block will be applied as the template for each item's view.
+
+              Given an empty `&lt;body&gt;` the following template:
+
+              ```handlebars
+              {{#collection contentBinding=&quot;App.items&quot;}}
+                Hi {{view.content.name}}
+              {{/collection}}
+              ```
+
+              And the following application code
+
+              ```javascript
+              App = Ember.Application.create()
+              App.items = [
+                Ember.Object.create({name: 'Dave'}),
+                Ember.Object.create({name: 'Mary'}),
+                Ember.Object.create({name: 'Sara'})
+              ]
+              ```
+
+              Will result in the HTML structure below
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Hi Dave&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Hi Mary&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Hi Sara&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ### Blockless use in a collection
+
+              If you provide an `itemViewClass` option that has its own `template` you can
+              omit the block.
+
+              The following template:
+
+              ```handlebars
+              {{collection contentBinding=&quot;App.items&quot; itemViewClass=&quot;App.AnItemView&quot;}}
+              ```
+
+              And application code
+
+              ```javascript
+              App = Ember.Application.create();
+              App.items = [
+                Ember.Object.create({name: 'Dave'}),
+                Ember.Object.create({name: 'Mary'}),
+                Ember.Object.create({name: 'Sara'})
+              ];
+
+              App.AnItemView = Ember.View.extend({
+                template: Ember.Handlebars.compile(&quot;Greetings {{view.content.name}}&quot;)
+              });
+              ```
+
+              Will result in the HTML structure below
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Greetings Dave&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Greetings Mary&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Greetings Sara&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ### Specifying a CollectionView subclass
+
+              By default the `{{collection}}` helper will create an instance of
+              `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to
+              the helper by passing it as the first argument:
+
+              ```handlebars
+              {{#collection App.MyCustomCollectionClass contentBinding=&quot;App.items&quot;}}
+                Hi {{view.content.name}}
+              {{/collection}}
+              ```
+
+              ### Forwarded `item.*`-named Options
+
+              As with the `{{view}}`, helper options passed to the `{{collection}}` will be
+              set on the resulting `Ember.CollectionView` as properties. Additionally,
+              options prefixed with `item` will be applied to the views rendered for each
+              item (note the camelcasing):
+
+              ```handlebars
+              {{#collection contentBinding=&quot;App.items&quot;
+                            itemTagName=&quot;p&quot;
+                            itemClassNames=&quot;greeting&quot;}}
+                Howdy {{view.content.name}}
+              {{/collection}}
+              ```
+
+              Will result in the following HTML structure:
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;p class=&quot;ember-view greeting&quot;&gt;Howdy Dave&lt;/p&gt;
+                &lt;p class=&quot;ember-view greeting&quot;&gt;Howdy Mary&lt;/p&gt;
+                &lt;p class=&quot;ember-view greeting&quot;&gt;Howdy Sara&lt;/p&gt;
+              &lt;/div&gt;
+              ```
+
+              @method collection
+              @for Ember.Handlebars.helpers
+              @param {String} path
+              @param {Hash} options
+              @return {String} HTML string
+              @deprecated Use `{{each}}` helper instead.
+            */
+        function collectionHelper(path, options) {
+            Ember.deprecate(&quot;Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.&quot;, path !== 'collection');
+
+            // If no path is provided, treat path param as options.
+            if (path &amp;&amp; path.data &amp;&amp; path.data.isRenderData) {
+                options = path;
+                path = undefined;
+                Ember.assert(&quot;You cannot pass more than one argument to the collection helper&quot;, arguments.length === 1);
+            } else {
+                Ember.assert(&quot;You cannot pass more than one argument to the collection helper&quot;, arguments.length === 2);
+            }
+
+            var fn = options.fn;
+            var data = options.data;
+            var inverse = options.inverse;
+            var view = options.data.view;
+
+
+            var controller, container;
+            // If passed a path string, convert that into an object.
+            // Otherwise, just default to the standard class.
+            var collectionClass;
+            if (path) {
+                controller = data.keywords.controller;
+                container = controller &amp;&amp; controller.container;
+                collectionClass = handlebarsGet(this, path, options) || container.lookupFactory('view:' + path);
+                Ember.assert(fmt(&quot;%@ #collection: Could not find collection class %@&quot;, [data.view, path]), !!collectionClass);
+            } else {
+                collectionClass = CollectionView;
+            }
+
+            var hash = options.hash, itemHash = {}, match;
+
+            // Extract item view class if provided else default to the standard class
+            var collectionPrototype = collectionClass.proto(), itemViewClass;
+
+            if (hash.itemView) {
+                controller = data.keywords.controller;
+                Ember.assert('You specified an itemView, but the current context has no ' +
+                'container to look the itemView up in. This probably means ' +
+                'that you created a view manually, instead of through the ' +
+                'container. Instead, use container.lookup(&quot;view:viewName&quot;), ' +
+                'which will properly instantiate your view.',
+                controller &amp;&amp; controller.container);
+                container = controller.container;
+                itemViewClass = container.lookupFactory('view:' + hash.itemView);
+                Ember.assert('You specified the itemView ' + hash.itemView + &quot;, but it was &quot; +
+                &quot;not found at &quot; + container.describe(&quot;view:&quot; + hash.itemView) +
+                &quot; (and it was not registered in the container)&quot;, !!itemViewClass);
+            } else if (hash.itemViewClass) {
+                itemViewClass = handlebarsGet(collectionPrototype, hash.itemViewClass, options);
+            } else {
+                itemViewClass = collectionPrototype.itemViewClass;
+            }
+
+            Ember.assert(fmt(&quot;%@ #collection: Could not find itemViewClass %@&quot;, [data.view, itemViewClass]), !!itemViewClass);
+
+            delete hash.itemViewClass;
+            delete hash.itemView;
+
+            // Go through options passed to the {{collection}} helper and extract options
+            // that configure item views instead of the collection itself.
+            for (var prop in hash) {
+                if (hash.hasOwnProperty(prop)) {
+                    match = prop.match(/^item(.)(.*)$/);
+
+                    if (match &amp;&amp; prop !== 'itemController') {
+                        // Convert itemShouldFoo -&gt; shouldFoo
+                        itemHash[match[1].toLowerCase() + match[2]] = hash[prop];
+                        // Delete from hash as this will end up getting passed to the
+                        // {{view}} helper method.
+                        delete hash[prop];
+                    }
+                }
+            }
+
+            if (fn) {
+                itemHash.template = fn;
+                delete options.fn;
+            }
+
+            var emptyViewClass;
+            if (inverse &amp;&amp; inverse !== EmberHandlebars.VM.noop) {
+                emptyViewClass = get(collectionPrototype, 'emptyViewClass');
+                emptyViewClass = emptyViewClass.extend({
+                    template: inverse,
+                    tagName: itemHash.tagName
+                });
+            } else if (hash.emptyViewClass) {
+                emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options);
+            }
+            if (emptyViewClass) {
+                hash.emptyView = emptyViewClass;
+            }
+
+            if (hash.keyword) {
+                itemHash._context = this;
+            } else {
+                itemHash._context = alias('content');
+            }
+
+            var viewOptions = ViewHelper.propertiesFromHTMLOptions({
+                data: data,
+                hash: itemHash 
+            }, this);
+            hash.itemViewClass = itemViewClass.extend(viewOptions);
+
+            options.helperName = options.helperName || 'collection';
+
+            return helpers.view.call(this, collectionClass, options);
+        }
+
+        __exports__[&quot;default&quot;] = collectionHelper;
+    });
+    define(&quot;ember-handlebars/helpers/debug&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/logger&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-handlebars/ext&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        /*jshint debug:true*/
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.FEATURES,
+        var inspect = __dependency2__.inspect;
+        var Logger = __dependency3__[&quot;default&quot;];
+
+        var get = __dependency4__.get;
+        var normalizePath = __dependency5__.normalizePath;
+        var handlebarsGet = __dependency5__.handlebarsGet;
+
+        var a_slice = [].slice;
+
+        /**
+              `log` allows you to output the value of variables in the current rendering
+              context. `log` also accepts primitive types such as strings or numbers.
+
+              ```handlebars
+              {{log &quot;myVariable:&quot; myVariable }}
+              ```
+
+              @method log
+              @for Ember.Handlebars.helpers
+              @param {String} property
+            */
+        function logHelper() {
+            var params = a_slice.call(arguments, 0, -1),
+            options = arguments[arguments.length - 1],
+            logger = Logger.log,
+            values = [],
+            allowPrimitives = true;
+
+            for (var i = 0; i &lt; params.length; i++) {
+                var type = options.types[i];
+
+                if (type === 'ID' || !allowPrimitives) {
+                    var context = (options.contexts &amp;&amp; options.contexts[i]) || this,
+                    normalized = normalizePath(context, params[i], options.data);
+
+                    if (normalized.path === 'this') {
+                        values.push(normalized.root);
+                    } else {
+                        values.push(handlebarsGet(normalized.root, normalized.path, options));
+                    }
+                } else {
+                    values.push(params[i]);
+                }
+            }
+
+            logger.apply(logger, values);
+        }
+
+        /**
+              Execute the `debugger` statement in the current context.
+
+              ```handlebars
+              {{debugger}}
+              ```
+
+              Before invoking the `debugger` statement, there
+              are a few helpful variables defined in the
+              body of this helper that you can inspect while
+              debugging that describe how and where this
+              helper was invoked:
+
+              - templateContext: this is most likely a controller
+                from which this template looks up / displays properties
+              - typeOfTemplateContext: a string description of
+                what the templateContext is
+
+              For example, if you're wondering why a value `{{foo}}`
+              isn't rendering as expected within a template, you
+              could place a `{{debugger}}` statement, and when
+              the `debugger;` breakpoint is hit, you can inspect
+              `templateContext`, determine if it's the object you
+              expect, and/or evaluate expressions in the console
+              to perform property lookups on the `templateContext`:
+
+              ```
+                &gt; templateContext.get('foo') // -&gt; &quot;&lt;value of {{foo}}&gt;&quot;
+              ```
+
+              @method debugger
+              @for Ember.Handlebars.helpers
+              @param {String} property
+            */
+        function debuggerHelper(options) {
+
+            // These are helpful values you can inspect while debugging.
+            var templateContext = this;
+            var typeOfTemplateContext = inspect(templateContext);
+            Ember.Logger.info('Use `this` to access the context of the calling template.');
+
+            debugger;
+        }
+
+        __exports__.logHelper = logHelper;
+        __exports__.debuggerHelper = debuggerHelper;
+    });
+    define(&quot;ember-handlebars/helpers/each&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-handlebars-compiler&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/views/collection_view&quot;, &quot;ember-metal/binding&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;ember-runtime/controllers/array_controller&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;ember-runtime/copy&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/events&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/observer&quot;, &quot;ember-handlebars/views/metamorph_view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
+        &quot;use strict&quot;;
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert;, Ember.K
+        // var emberAssert = Ember.assert,
+        var K = Ember.K;
+
+        var EmberHandlebars = __dependency2__[&quot;default&quot;];
+        var helpers = EmberHandlebars.helpers;
+
+        var fmt = __dependency3__.fmt;
+        var get = __dependency4__.get;
+        var set = __dependency5__.set;
+        var CollectionView = __dependency6__[&quot;default&quot;];
+        var Binding = __dependency7__.Binding;
+        var ControllerMixin = __dependency8__[&quot;default&quot;];
+        var ArrayController = __dependency9__[&quot;default&quot;];
+        var EmberArray = __dependency10__[&quot;default&quot;];
+        var copy = __dependency11__[&quot;default&quot;];
+        var run = __dependency12__[&quot;default&quot;];
+        var on = __dependency13__.on;
+        var handlebarsGet = __dependency14__.handlebarsGet;
+        var computed = __dependency15__.computed;
+
+        var addObserver = __dependency16__.addObserver;
+        var removeObserver = __dependency16__.removeObserver;
+        var addBeforeObserver = __dependency16__.addBeforeObserver;
+        var removeBeforeObserver = __dependency16__.removeBeforeObserver;
+
+        var _Metamorph = __dependency17__._Metamorph;
+        var _MetamorphView = __dependency17__._MetamorphView;
+
+        var EachView = CollectionView.extend(_Metamorph, {
+
+            init: function() {
+                var itemController = get(this, 'itemController');
+                var binding;
+
+                if (itemController) {
+                    var controller = get(this, 'controller.container').lookupFactory('controller:array').create({
+                        _isVirtual: true,
+                        parentController: get(this, 'controller'),
+                        itemController: itemController,
+                        target: get(this, 'controller'),
+                        _eachView: this
+                    });
+
+                    this.disableContentObservers(function() {
+                        set(this, 'content', controller);
+                        binding = new Binding('content', '_eachView.dataSource').oneWay();
+                        binding.connect(controller);
+                    });
+
+                    set(this, '_arrayController', controller);
+                } else {
+                    this.disableContentObservers(function() {
+                        binding = new Binding('content', 'dataSource').oneWay();
+                        binding.connect(this);
+                    });
+                }
+
+                return this._super();
+            },
+
+            _assertArrayLike: function(content) {
+                Ember.assert(fmt(&quot;The value that #each loops over must be an Array. You &quot; +
+                &quot;passed %@, but it should have been an ArrayController&quot;,
+                [content.constructor]),
+                !ControllerMixin.detect(content) ||
+                (content &amp;&amp; content.isGenerated) ||
+                content instanceof ArrayController);
+                Ember.assert(fmt(&quot;The value that #each loops over must be an Array. You passed %@&quot;, [(ControllerMixin.detect(content) &amp;&amp; content.get('model') !== undefined) ? fmt(&quot;'%@' (wrapped in %@)&quot;, [content.get('model'), content]) : content]), EmberArray.detect(content));
+            },
+
+            disableContentObservers: function(callback) {
+                removeBeforeObserver(this, 'content', null, '_contentWillChange');
+                removeObserver(this, 'content', null, '_contentDidChange');
+
+                callback.call(this);
+
+                addBeforeObserver(this, 'content', null, '_contentWillChange');
+                addObserver(this, 'content', null, '_contentDidChange');
+            },
+
+            itemViewClass: _MetamorphView,
+            emptyViewClass: _MetamorphView,
+
+            createChildView: function(view, attrs) {
+                view = this._super(view, attrs);
+
+                // At the moment, if a container view subclass wants
+                // to insert keywords, it is responsible for cloning
+                // the keywords hash. This will be fixed momentarily.
+                var keyword = get(this, 'keyword');
+                var content = get(view, 'content');
+
+                if (keyword) {
+                    var data = get(view, 'templateData');
+
+                    data = copy(data);
+                    data.keywords = view.cloneKeywords();
+                    set(view, 'templateData', data);
+
+                    // In this case, we do not bind, because the `content` of
+                    // a #each item cannot change.
+                    data.keywords[keyword] = content;
+                }
+
+                // If {{#each}} is looping over an array of controllers,
+                // point each child view at their respective controller.
+                if (content &amp;&amp; content.isController) {
+                    set(view, 'controller', content);
+                }
+
+                return view;
+            },
+
+            destroy: function() {
+                if (!this._super()) {
+                    return;
+                }
+
+                var arrayController = get(this, '_arrayController');
+
+                if (arrayController) {
+                    arrayController.destroy();
+                }
+
+                return this;
+            }
+        });
+
+        // Defeatureify doesn't seem to like nested functions that need to be removed
+        function _addMetamorphCheck() {
+            EachView.reopen({
+                _checkMetamorph: on('didInsertElement', function() {
+                    Ember.assert(&quot;The metamorph tags, &quot; +
+                    this.morph.start + &quot; and &quot; + this.morph.end +
+                    &quot;, have different parents.\nThe browser has fixed your template to output valid HTML (for example, check that you have properly closed all tags and have used a TBODY tag when creating a table with '{{#each}}')&quot;,
+                    document.getElementById( this.morph.start ).parentNode ===
+                    document.getElementById( this.morph.end ).parentNode
+                    );
+                })
+            });
+        }
+
+        // until ember-debug is es6ed
+        var runInDebug = function(f) {
+            f();
+        };
+        runInDebug( function() {
+            _addMetamorphCheck();
+        });
+
+        var GroupedEach = EmberHandlebars.GroupedEach = function(context, path, options) {
+            var self = this,
+            normalized = EmberHandlebars.normalizePath(context, path, options.data);
+
+            this.context = context;
+            this.path = path;
+            this.options = options;
+            this.template = options.fn;
+            this.containingView = options.data.view;
+            this.normalizedRoot = normalized.root;
+            this.normalizedPath = normalized.path;
+            this.content = this.lookupContent();
+
+            this.addContentObservers();
+            this.addArrayObservers();
+
+            this.containingView.on('willClearRender', function() {
+                self.destroy();
+            });
+        };
+
+        GroupedEach.prototype = {
+            contentWillChange: function() {
+                this.removeArrayObservers();
+            },
+
+            contentDidChange: function() {
+                this.content = this.lookupContent();
+                this.addArrayObservers();
+                this.rerenderContainingView();
+            },
+
+            contentArrayWillChange: K,
+
+            contentArrayDidChange: function() {
+                this.rerenderContainingView();
+            },
+
+            lookupContent: function() {
+                return handlebarsGet(this.normalizedRoot, this.normalizedPath, this.options);
+            },
+
+            addArrayObservers: function() {
+                if (!this.content) {
+                    return;
+                }
+
+                this.content.addArrayObserver(this, {
+                    willChange: 'contentArrayWillChange',
+                    didChange: 'contentArrayDidChange'
+                });
+            },
+
+            removeArrayObservers: function() {
+                if (!this.content) {
+                    return;
+                }
+
+                this.content.removeArrayObserver(this, {
+                    willChange: 'contentArrayWillChange',
+                    didChange: 'contentArrayDidChange'
+                });
+            },
+
+            addContentObservers: function() {
+                addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange);
+                addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange);
+            },
+
+            removeContentObservers: function() {
+                removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange);
+                removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange);
+            },
+
+            render: function() {
+                if (!this.content) {
+                    return;
+                }
+
+                var content = this.content,
+                contentLength = get(content, 'length'),
+                options = this.options,
+                data = options.data,
+                template = this.template;
+
+                data.insideEach = true;
+                for (var i = 0; i &lt; contentLength; i++) {
+                    var context = content.objectAt(i);
+                    options.data.keywords[options.hash.keyword] = context;
+                    template(context, {
+                        data: data 
+                    });
+                }
+            },
+
+            rerenderContainingView: function() {
+                var self = this;
+                run.scheduleOnce('render', this, function() {
+                    // It's possible it's been destroyed after we enqueued a re-render call.
+                    if (!self.destroyed) {
+                        self.containingView.rerender();
+                    }
+                });
+            },
+
+            destroy: function() {
+                this.removeContentObservers();
+                if (this.content) {
+                    this.removeArrayObservers();
+                }
+                this.destroyed = true;
+            }
+        };
+
+        /**
+              The `{{#each}}` helper loops over elements in a collection, rendering its
+              block once for each item. It is an extension of the base Handlebars `{{#each}}`
+              helper:
+
+              ```javascript
+              Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
+              ```
+
+              ```handlebars
+              {{#each Developers}}
+                {{name}}
+              {{/each}}
+              ```
+
+              `{{each}}` supports an alternative syntax with element naming:
+
+              ```handlebars
+              {{#each person in Developers}}
+                {{person.name}}
+              {{/each}}
+              ```
+
+              When looping over objects that do not have properties, `{{this}}` can be used
+              to render the object:
+
+              ```javascript
+              DeveloperNames = ['Yehuda', 'Tom', 'Paul']
+              ```
+
+              ```handlebars
+              {{#each DeveloperNames}}
+                {{this}}
+              {{/each}}
+              ```
+              ### {{else}} condition
+              `{{#each}}` can have a matching `{{else}}`. The contents of this block will render
+              if the collection is empty.
+
+              ```
+              {{#each person in Developers}}
+                {{person.name}}
+              {{else}}
+                &lt;p&gt;Sorry, nobody is available for this task.&lt;/p&gt;
+              {{/each}}
+              ```
+              ### Specifying a View class for items
+              If you provide an `itemViewClass` option that references a view class
+              with its own `template` you can omit the block.
+
+              The following template:
+
+              ```handlebars
+              {{#view App.MyView }}
+                {{each view.items itemViewClass=&quot;App.AnItemView&quot;}}
+              {{/view}}
+              ```
+
+              And application code
+
+              ```javascript
+              App = Ember.Application.create({
+                MyView: Ember.View.extend({
+                  items: [
+                    Ember.Object.create({name: 'Dave'}),
+                    Ember.Object.create({name: 'Mary'}),
+                    Ember.Object.create({name: 'Sara'})
+                  ]
+                })
+              });
+
+              App.AnItemView = Ember.View.extend({
+                template: Ember.Handlebars.compile(&quot;Greetings {{name}}&quot;)
+              });
+              ```
+
+              Will result in the HTML structure below
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Greetings Dave&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Greetings Mary&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Greetings Sara&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              If an `itemViewClass` is defined on the helper, and therefore the helper is not
+              being used as a block, an `emptyViewClass` can also be provided optionally.
+              The `emptyViewClass` will match the behavior of the `{{else}}` condition
+              described above. That is, the `emptyViewClass` will render if the collection
+              is empty.
+
+              ### Representing each item with a Controller.
+              By default the controller lookup within an `{{#each}}` block will be
+              the controller of the template where the `{{#each}}` was used. If each
+              item needs to be presented by a custom controller you can provide a
+              `itemController` option which references a controller by lookup name.
+              Each item in the loop will be wrapped in an instance of this controller
+              and the item itself will be set to the `model` property of that controller.
+
+              This is useful in cases where properties of model objects need transformation
+              or synthesis for display:
+
+              ```javascript
+              App.DeveloperController = Ember.ObjectController.extend({
+                isAvailableForHire: function() {
+                  return !this.get('model.isEmployed') &amp;&amp; this.get('model.isSeekingWork');
+                }.property('isEmployed', 'isSeekingWork')
+              })
+              ```
+
+              ```handlebars
+              {{#each person in developers itemController=&quot;developer&quot;}}
+                {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}}
+              {{/each}}
+              ```
+
+              Each itemController will receive a reference to the current controller as
+              a `parentController` property.
+
+              ### (Experimental) Grouped Each
+
+              When used in conjunction with the experimental [group helper](https://github.com/emberjs/group-helper),
+              you can inform Handlebars to re-render an entire group of items instead of
+              re-rendering them one at a time (in the event that they are changed en masse
+              or an item is added/removed).
+
+              ```handlebars
+              {{#group}}
+                {{#each people}}
+                  {{firstName}} {{lastName}}
+                {{/each}}
+              {{/group}}
+              ```
+
+              This can be faster than the normal way that Handlebars re-renders items
+              in some cases.
+
+              If for some reason you have a group with more than one `#each`, you can make
+              one of the collections be updated in normal (non-grouped) fashion by setting
+              the option `groupedRows=true` (counter-intuitive, I know).
+
+              For example,
+
+              ```handlebars
+              {{dealershipName}}
+
+              {{#group}}
+                {{#each dealers}}
+                  {{firstName}} {{lastName}}
+                {{/each}}
+
+                {{#each car in cars groupedRows=true}}
+                  {{car.make}} {{car.model}} {{car.color}}
+                {{/each}}
+              {{/group}}
+              ```
+              Any change to `dealershipName` or the `dealers` collection will cause the
+              entire group to be re-rendered. However, changes to the `cars` collection
+              will be re-rendered individually (as normal).
+
+              Note that `group` behavior is also disabled by specifying an `itemViewClass`.
+
+              @method each
+              @for Ember.Handlebars.helpers
+              @param [name] {String} name for item (used with `in`)
+              @param [path] {String} path
+              @param [options] {Object} Handlebars key/value pairs of options
+              @param [options.itemViewClass] {String} a path to a view class used for each item
+              @param [options.itemController] {String} name of a controller to be created for each item
+              @param [options.groupedRows] {boolean} enable normal item-by-item rendering when inside a `#group` helper
+            */
+        function eachHelper(path, options) {
+            var ctx, helperName = 'each';
+
+            if (arguments.length === 4) {
+                Ember.assert(&quot;If you pass more than one argument to the each helper, it must be in the form #each foo in bar&quot;, arguments[1] === &quot;in&quot;);
+
+                var keywordName = arguments[0];
+
+
+                options = arguments[3];
+                path = arguments[2];
+
+                helperName += ' ' + keywordName + ' in ' + path;
+
+                if (path === '') {
+                    path = &quot;this&quot;;
+                }
+
+                options.hash.keyword = keywordName;
+
+            } else if (arguments.length === 1) {
+                options = path;
+                path = 'this';
+            } else {
+                helperName += ' ' + path;
+            }
+
+            options.hash.dataSourceBinding = path;
+            // Set up emptyView as a metamorph with no tag
+            //options.hash.emptyViewClass = Ember._MetamorphView;
+
+            // can't rely on this default behavior when use strict
+            ctx = this || window;
+
+            options.helperName = options.helperName || helperName;
+
+            if (options.data.insideGroup &amp;&amp; !options.hash.groupedRows &amp;&amp; !options.hash.itemViewClass) {
+                new GroupedEach(ctx, path, options).render();
+            } else {
+                // ES6TODO: figure out how to do this without global lookup.
+                return helpers.collection.call(ctx, 'Ember.Handlebars.EachView', options);
+            }
+        }
+
+        __exports__.EachView = EachView;
+        __exports__.GroupedEach = GroupedEach;
+        __exports__.eachHelper = eachHelper;
+    });
+    define(&quot;ember-handlebars/helpers/loc&quot;,
+    [&quot;ember-runtime/system/string&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var loc = __dependency1__.loc;
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        // ES6TODO:
+        // Pretty sure this can be expressed as
+        // var locHelper EmberStringUtils.loc ?
+
+        /**
+              Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the
+              provided string.
+
+              This is a convenient way to localize text. For example:
+
+              ```html
+              &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;home&quot;&gt;
+                {{loc &quot;welcome&quot;}}
+              &lt;/script&gt;
+              ```
+
+              Take note that `&quot;welcome&quot;` is a string and not an object
+              reference.
+
+              See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to 
+              set up localized string references.
+
+              @method loc
+              @for Ember.Handlebars.helpers
+              @param {String} str The string to format
+              @see {Ember.String#loc}
+            */
+        __exports__[&quot;default&quot;] = function locHelper(str) {
+            return loc(str);
+        }
+    });
+    define(&quot;ember-handlebars/helpers/partial&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-handlebars/helpers/binding&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        // var emberAssert = Ember.assert;
+
+        var isNone = __dependency2__.isNone;
+        var handlebarsGet = __dependency3__.handlebarsGet;
+        var bind = __dependency4__.bind;
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        /**
+              The `partial` helper renders another template without
+              changing the template context:
+
+              ```handlebars
+              {{foo}}
+              {{partial &quot;nav&quot;}}
+              ```
+
+              The above example template will render a template named
+              &quot;_nav&quot;, which has the same context as the parent template
+              it's rendered into, so if the &quot;_nav&quot; template also referenced
+              `{{foo}}`, it would print the same thing as the `{{foo}}`
+              in the above example.
+
+              If a &quot;_nav&quot; template isn't found, the `partial` helper will
+              fall back to a template named &quot;nav&quot;.
+
+              ## Bound template names
+
+              The parameter supplied to `partial` can also be a path
+              to a property containing a template name, e.g.:
+
+              ```handlebars
+              {{partial someTemplateName}}
+              ```
+
+              The above example will look up the value of `someTemplateName`
+              on the template context (e.g. a controller) and use that
+              value as the name of the template to render. If the resolved
+              value is falsy, nothing will be rendered. If `someTemplateName`
+              changes, the partial will be re-rendered using the new template
+              name.
+
+              ## Setting the partial's context with `with`
+
+              The `partial` helper can be used in conjunction with the `with`
+              helper to set a context that will be used by the partial:
+
+              ```handlebars
+              {{#with currentUser}}
+                {{partial &quot;user_info&quot;}}
+              {{/with}}
+              ```
+
+              @method partial
+              @for Ember.Handlebars.helpers
+              @param {String} partialName the name of the template to render minus the leading underscore
+            */
+
+        __exports__[&quot;default&quot;] = function partialHelper(name, options) {
+
+            var context = (options.contexts &amp;&amp; options.contexts.length) ? options.contexts[0] : this;
+
+            options.helperName = options.helperName || 'partial';
+
+            if (options.types[0] === &quot;ID&quot;) {
+                // Helper was passed a property path; we need to
+                // create a binding that will re-render whenever
+                // this property changes.
+                options.fn = function(context, fnOptions) {
+                    var partialName = handlebarsGet(context, name, fnOptions);
+                    renderPartial(context, partialName, fnOptions);
+                };
+
+                return bind.call(context, name, options, true, exists);
+            } else {
+                // Render the partial right into parent template.
+                renderPartial(context, name, options);
+            }
+        }
+
+        function exists(value) {
+            return !isNone(value);
+        }
+
+        function renderPartial(context, name, options) {
+            var nameParts = name.split(&quot;/&quot;);
+            var lastPart = nameParts[nameParts.length - 1];
+
+            nameParts[nameParts.length - 1] = &quot;_&quot; + lastPart;
+
+            var view = options.data.view;
+            var underscoredName = nameParts.join(&quot;/&quot;);
+            var template = view.templateForName(underscoredName);
+            var deprecatedTemplate = !template &amp;&amp; view.templateForName(name);
+
+            Ember.assert(&quot;Unable to find partial with name '&quot; + name + &quot;'.&quot;, template || deprecatedTemplate);
+
+            template = template || deprecatedTemplate;
+
+            template(context, {
+                data: options.data 
+            });
+        }
+    });
+    define(&quot;ember-handlebars/helpers/shared&quot;,
+    [&quot;ember-handlebars/ext&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var handlebarsGet = __dependency1__.handlebarsGet;
+
+        __exports__[&quot;default&quot;] = function resolvePaths(options) {
+            var ret = [],
+            contexts = options.contexts,
+            roots = options.roots,
+            data = options.data;
+
+            for (var i = 0, l = contexts.length; i &lt; l; i++) {
+                ret.push(handlebarsGet(roots[i], contexts[i], {
+                    data: data 
+                }));
+            }
+
+            return ret;
+        }
+    });
+    define(&quot;ember-handlebars/helpers/template&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-handlebars-compiler&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // var emberDeprecate = Ember.deprecate;
+
+        var EmberHandlebars = __dependency2__[&quot;default&quot;];
+        var helpers = EmberHandlebars.helpers;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        /**
+              `template` allows you to render a template from inside another template.
+              This allows you to re-use the same template in multiple places. For example:
+
+              ```html
+              &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;logged_in_user&quot;&gt;
+                {{#with loggedInUser}}
+                  Last Login: {{lastLogin}}
+                  User Info: {{template &quot;user_info&quot;}}
+                {{/with}}
+              &lt;/script&gt;
+              ```
+
+              ```html
+              &lt;script type=&quot;text/x-handlebars&quot; data-template-name=&quot;user_info&quot;&gt;
+                Name: &lt;em&gt;{{name}}&lt;/em&gt;
+                Karma: &lt;em&gt;{{karma}}&lt;/em&gt;
+              &lt;/script&gt;
+              ```
+
+              ```handlebars
+              {{#if isUser}}
+                {{template &quot;user_info&quot;}}
+              {{else}}
+                {{template &quot;unlogged_user_info&quot;}}
+              {{/if}}
+              ```
+
+              This helper looks for templates in the global `Ember.TEMPLATES` hash. If you
+              add `&lt;script&gt;` tags to your page with the `data-template-name` attribute set,
+              they will be compiled and placed in this hash automatically.
+
+              You can also manually register templates by adding them to the hash:
+
+              ```javascript
+              Ember.TEMPLATES[&quot;my_cool_template&quot;] = Ember.Handlebars.compile('&lt;b&gt;{{user}}&lt;/b&gt;');
+              ```
+
+              @deprecated
+              @method template
+              @for Ember.Handlebars.helpers
+              @param {String} templateName the template to render
+            */
+        __exports__[&quot;default&quot;] = function templateHelper(name, options) {
+            Ember.deprecate(&quot;The `template` helper has been deprecated in favor of the `partial` helper. Please use `partial` instead, which will work the same way.&quot;);
+
+            options.helperName = options.helperName || 'template';
+
+            return helpers.partial.apply(this, arguments);
+        }
+    });
+    define(&quot;ember-handlebars/helpers/unbound&quot;,
+    [&quot;ember-handlebars-compiler&quot;, &quot;ember-handlebars/helpers/binding&quot;, &quot;ember-handlebars/ext&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        /*globals Handlebars */
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var EmberHandlebars = __dependency1__[&quot;default&quot;];
+        var helpers = EmberHandlebars.helpers;
+
+        var resolveHelper = __dependency2__.resolveHelper;
+        var handlebarsGet = __dependency3__.handlebarsGet;
+
+        var slice = [].slice;
+
+        /**
+              `unbound` allows you to output a property without binding. *Important:* The
+              output will not be updated if the property changes. Use with caution.
+
+              ```handlebars
+              &lt;div&gt;{{unbound somePropertyThatDoesntChange}}&lt;/div&gt;
+              ```
+
+              `unbound` can also be used in conjunction with a bound helper to
+              render it in its unbound form:
+
+              ```handlebars
+              &lt;div&gt;{{unbound helperName somePropertyThatDoesntChange}}&lt;/div&gt;
+              ```
+
+              @method unbound
+              @for Ember.Handlebars.helpers
+              @param {String} property
+              @return {String} HTML string
+            */
+        __exports__[&quot;default&quot;] = function unboundHelper(property, fn) {
+            var options = arguments[arguments.length - 1],
+            container = options.data.view.container,
+            helper, context, out, ctx;
+
+            ctx = this;
+            if (arguments.length &gt; 2) {
+                // Unbound helper call.
+                options.data.isUnbound = true;
+                helper = resolveHelper(container, property) || helpers.helperMissing;
+                out = helper.apply(ctx, slice.call(arguments, 1));
+                delete options.data.isUnbound;
+                return out;
+            }
+
+            context = (fn.contexts &amp;&amp; fn.contexts.length) ? fn.contexts[0] : ctx;
+            return handlebarsGet(context, property, fn);
+        }
+    });
+    define(&quot;ember-handlebars/helpers/view&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-views/views/view&quot;, &quot;ember-metal/binding&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-runtime/system/string&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
+        &quot;use strict&quot;;
+        /*globals Handlebars */
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.warn, Ember.assert
+        // var emberWarn = Ember.warn, emberAssert = Ember.assert;
+
+        var EmberObject = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var IS_BINDING = __dependency5__.IS_BINDING;
+        var jQuery = __dependency6__[&quot;default&quot;];
+        var View = __dependency7__[&quot;default&quot;];
+        var isGlobalPath = __dependency8__.isGlobalPath;
+        var normalizePath = __dependency9__.normalizePath;
+        var handlebarsGet = __dependency9__.handlebarsGet;
+        var EmberString = __dependency10__[&quot;default&quot;];
+
+
+        var LOWERCASE_A_Z = /^[a-z]/,
+        VIEW_PREFIX = /^view\./;
+
+        function makeBindings(thisContext, options) {
+            var hash = options.hash,
+            hashType = options.hashTypes;
+
+            for (var prop in hash) {
+                if (hashType[prop] === 'ID') {
+
+                    var value = hash[prop];
+
+                    if (IS_BINDING.test(prop)) {
+                        Ember.warn(&quot;You're attempting to render a view by passing &quot; + prop + &quot;=&quot; + value + &quot; to a view helper, but this syntax is ambiguous. You should either surround &quot; + value + &quot; in quotes or remove `Binding` from &quot; + prop + &quot;.&quot;);
+                    } else {
+                        hash[prop + 'Binding'] = value;
+                        hashType[prop + 'Binding'] = 'STRING';
+                        delete hash[prop];
+                        delete hashType[prop];
+                    }
+                }
+            }
+
+            if (hash.hasOwnProperty('idBinding')) {
+                // id can't be bound, so just perform one-time lookup.
+                hash.id = handlebarsGet(thisContext, hash.idBinding, options);
+                hashType.id = 'STRING';
+                delete hash.idBinding;
+                delete hashType.idBinding;
+            }
+        }
+
+        var ViewHelper = EmberObject.create({
+
+            propertiesFromHTMLOptions: function(options) {
+                var hash = options.hash, data = options.data;
+                var extensions = {},
+                classes = hash['class'],
+                dup = false;
+
+                if (hash.id) {
+                    extensions.elementId = hash.id;
+                    dup = true;
+                }
+
+                if (hash.tag) {
+                    extensions.tagName = hash.tag;
+                    dup = true;
+                }
+
+                if (classes) {
+                    classes = classes.split(' ');
+                    extensions.classNames = classes;
+                    dup = true;
+                }
+
+                if (hash.classBinding) {
+                    extensions.classNameBindings = hash.classBinding.split(' ');
+                    dup = true;
+                }
+
+                if (hash.classNameBindings) {
+                    if (extensions.classNameBindings === undefined) 
+                        extensions.classNameBindings = [];
+                    extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' '));
+                    dup = true;
+                }
+
+                if (hash.attributeBindings) {
+                    Ember.assert(&quot;Setting 'attributeBindings' via Handlebars is not allowed. Please subclass Ember.View and set it there instead.&quot;);
+                    extensions.attributeBindings = null;
+                    dup = true;
+                }
+
+                if (dup) {
+                    hash = jQuery.extend({}, hash);
+                    delete hash.id;
+                    delete hash.tag;
+                    delete hash['class'];
+                    delete hash.classBinding;
+                }
+
+                // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings
+                // as well as class name bindings. If the bindings are local, make them relative to the current context
+                // instead of the view.
+                var path;
+
+                // Evaluate the context of regular attribute bindings:
+                for (var prop in hash) {
+                    if (!hash.hasOwnProperty(prop)) {
+                        continue;
+                    }
+
+                    // Test if the property ends in &quot;Binding&quot;
+                    if (IS_BINDING.test(prop) &amp;&amp; typeof hash[prop] === 'string') {
+                        path = this.contextualizeBindingPath(hash[prop], data);
+                        if (path) {
+                            hash[prop] = path;
+                        }
+                    }
+                }
+
+                // Evaluate the context of class name bindings:
+                if (extensions.classNameBindings) {
+                    for (var b in extensions.classNameBindings) {
+                        var full = extensions.classNameBindings[b];
+                        if (typeof full === 'string') {
+                            // Contextualize the path of classNameBinding so this:
+                            //
+                            //     classNameBinding=&quot;isGreen:green&quot;
+                            //
+                            // is converted to this:
+                            //
+                            //     classNameBinding=&quot;_parentView.context.isGreen:green&quot;
+                            var parsedPath = View._parsePropertyPath(full);
+                            path = this.contextualizeBindingPath(parsedPath.path, data);
+                            if (path) {
+                                extensions.classNameBindings[b] = path + parsedPath.classNames;
+                            }
+                        }
+                    }
+                }
+
+                return jQuery.extend(hash, extensions);
+            },
+
+            // Transform bindings from the current context to a context that can be evaluated within the view.
+            // Returns null if the path shouldn't be changed.
+            //
+            // TODO: consider the addition of a prefix that would allow this method to return `path`.
+            contextualizeBindingPath: function(path, data) {
+                var normalized = normalizePath(null, path, data);
+                if (normalized.isKeyword) {
+                    return 'templateData.keywords.' + path;
+                } else if (isGlobalPath(path)) {
+                    return null;
+                } else if (path === 'this' || path === '') {
+                    return '_parentView.context';
+                } else {
+                    return '_parentView.context.' + path;
+                }
+            },
+
+            helper: function(thisContext, path, options) {
+                var data = options.data,
+                fn = options.fn,
+                newView;
+
+                makeBindings(thisContext, options);
+
+                if ('string' === typeof path) {
+                    var lookup;
+                    // TODO: this is a lame conditional, this should likely change
+                    // but something along these lines will likely need to be added
+                    // as deprecation warnings
+                    //
+                    if (options.types[0] === 'STRING' &amp;&amp; LOWERCASE_A_Z.test(path) &amp;&amp; !VIEW_PREFIX.test(path)) {
+                        lookup = path;
+                    } else {
+                        newView = handlebarsGet(thisContext, path, options);
+                        if (typeof newView === 'string') {
+                            lookup = newView;
+                        }
+                    }
+
+                    if (lookup) {
+                        Ember.assert(&quot;View requires a container&quot;, !!data.view.container);
+                        newView = data.view.container.lookupFactory('view:' + lookup);
+                    }
+
+                    Ember.assert(&quot;Unable to find view at path '&quot; + path + &quot;'&quot;, !!newView);
+                } else {
+                    newView = path;
+                }
+
+                Ember.assert(EmberString.fmt('You must pass a view to the #view helper, not %@ (%@)', [path, newView]), View.detect(newView) || View.detectInstance(newView));
+
+                var viewOptions = this.propertiesFromHTMLOptions(options, thisContext);
+                var currentView = data.view;
+                viewOptions.templateData = data;
+                var newViewProto = newView.proto ? newView.proto() : newView;
+
+                if (fn) {
+                    Ember.assert(&quot;You cannot provide a template block if you also specified a templateName&quot;, !get(viewOptions, 'templateName') &amp;&amp; !get(newViewProto, 'templateName'));
+                    viewOptions.template = fn;
+                }
+
+                // We only want to override the `_context` computed property if there is
+                // no specified controller. See View#_context for more information.
+                if (!newViewProto.controller &amp;&amp; !newViewProto.controllerBinding &amp;&amp; !viewOptions.controller &amp;&amp; !viewOptions.controllerBinding) {
+                    viewOptions._context = thisContext;
+                }
+
+                // for instrumentation
+                if (options.helperName) {
+                    viewOptions.helperName = options.helperName;
+                }
+
+                currentView.appendChild(newView, viewOptions);
+            }
+        });
+        __exports__.ViewHelper = ViewHelper;
+        /**
+              `{{view}}` inserts a new instance of an `Ember.View` into a template passing its
+              options to the `Ember.View`'s `create` method and using the supplied block as
+              the view's own template.
+
+              An empty `&lt;body&gt;` and the following template:
+
+              ```handlebars
+              A span:
+              {{#view tagName=&quot;span&quot;}}
+                hello.
+              {{/view}}
+              ```
+
+              Will result in HTML structure:
+
+              ```html
+              &lt;body&gt;
+                &lt;!-- Note: the handlebars template script
+                     also results in a rendered Ember.View
+                     which is the outer &lt;div&gt; here --&gt;
+
+                &lt;div class=&quot;ember-view&quot;&gt;
+                  A span:
+                  &lt;span id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;
+                    Hello.
+                  &lt;/span&gt;
+                &lt;/div&gt;
+              &lt;/body&gt;
+              ```
+
+              ### `parentView` setting
+
+              The `parentView` property of the new `Ember.View` instance created through
+              `{{view}}` will be set to the `Ember.View` instance of the template where
+              `{{view}}` was called.
+
+              ```javascript
+              aView = Ember.View.create({
+                template: Ember.Handlebars.compile(&quot;{{#view}} my parent: {{parentView.elementId}} {{/view}}&quot;)
+              });
+
+              aView.appendTo('body');
+              ```
+
+              Will result in HTML structure:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;
+                &lt;div id=&quot;ember2&quot; class=&quot;ember-view&quot;&gt;
+                  my parent: ember1
+                &lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ### Setting CSS id and class attributes
+
+              The HTML `id` attribute can be set on the `{{view}}`'s resulting element with
+              the `id` option. This option will _not_ be passed to `Ember.View.create`.
+
+              ```handlebars
+              {{#view tagName=&quot;span&quot; id=&quot;a-custom-id&quot;}}
+                hello.
+              {{/view}}
+              ```
+
+              Results in the following HTML structure:
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;span id=&quot;a-custom-id&quot; class=&quot;ember-view&quot;&gt;
+                  hello.
+                &lt;/span&gt;
+              &lt;/div&gt;
+              ```
+
+              The HTML `class` attribute can be set on the `{{view}}`'s resulting element
+              with the `class` or `classNameBindings` options. The `class` option will
+              directly set the CSS `class` attribute and will not be passed to
+              `Ember.View.create`. `classNameBindings` will be passed to `create` and use
+              `Ember.View`'s class name binding functionality:
+
+              ```handlebars
+              {{#view tagName=&quot;span&quot; class=&quot;a-custom-class&quot;}}
+                hello.
+              {{/view}}
+              ```
+
+              Results in the following HTML structure:
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;span id=&quot;ember2&quot; class=&quot;ember-view a-custom-class&quot;&gt;
+                  hello.
+                &lt;/span&gt;
+              &lt;/div&gt;
+              ```
+
+              ### Supplying a different view class
+
+              `{{view}}` can take an optional first argument before its supplied options to
+              specify a path to a custom view class.
+
+              ```handlebars
+              {{#view &quot;MyApp.CustomView&quot;}}
+                hello.
+              {{/view}}
+              ```
+
+              The first argument can also be a relative path accessible from the current
+              context.
+
+              ```javascript
+              MyApp = Ember.Application.create({});
+              MyApp.OuterView = Ember.View.extend({
+                innerViewClass: Ember.View.extend({
+                  classNames: ['a-custom-view-class-as-property']
+                }),
+                template: Ember.Handlebars.compile('{{#view &quot;view.innerViewClass&quot;}} hi {{/view}}')
+              });
+
+              MyApp.OuterView.create().appendTo('body');
+              ```
+
+              Will result in the following HTML:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;
+                &lt;div id=&quot;ember2&quot; class=&quot;ember-view a-custom-view-class-as-property&quot;&gt;
+                  hi
+                &lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ### Blockless use
+
+              If you supply a custom `Ember.View` subclass that specifies its own template
+              or provide a `templateName` option to `{{view}}` it can be used without
+              supplying a block. Attempts to use both a `templateName` option and supply a
+              block will throw an error.
+
+              ```handlebars
+              {{view &quot;MyApp.ViewWithATemplateDefined&quot;}}
+              ```
+
+              ### `viewName` property
+
+              You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance
+              will be referenced as a property of its parent view by this name.
+
+              ```javascript
+              aView = Ember.View.create({
+                template: Ember.Handlebars.compile('{{#view viewName=&quot;aChildByName&quot;}} hi {{/view}}')
+              });
+
+              aView.appendTo('body');
+              aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper
+              ```
+
+              @method view
+              @for Ember.Handlebars.helpers
+              @param {String} path
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        function viewHelper(path, options) {
+            Ember.assert(&quot;The view helper only takes a single argument&quot;, arguments.length &lt;= 2);
+
+            // If no path is provided, treat path param as options
+            // and get an instance of the registered `view:toplevel`
+            if (path &amp;&amp; path.data &amp;&amp; path.data.isRenderData) {
+                options = path;
+                Ember.assert('{{view}} helper requires parent view to have a container but none was found. This usually happens when you are manually-managing views.', !!options.data.view.container);
+                path = options.data.view.container.lookupFactory('view:toplevel');
+            }
+
+            options.helperName = options.helperName || 'view';
+
+            return ViewHelper.helper(this, path, options);
+        }
+
+        __exports__.viewHelper = viewHelper;
+    });
+    define(&quot;ember-handlebars/helpers/yield&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // var emberAssert = Ember.assert;
+
+        var get = __dependency2__.get;
+
+        /**
+              `{{yield}}` denotes an area of a template that will be rendered inside
+              of another template. It has two main uses:
+
+              ### Use with `layout`
+              When used in a Handlebars template that is assigned to an `Ember.View`
+              instance's `layout` property Ember will render the layout template first,
+              inserting the view's own rendered output at the `{{yield}}` location.
+
+              An empty `&lt;body&gt;` and the following application code:
+
+              ```javascript
+              AView = Ember.View.extend({
+                classNames: ['a-view-with-layout'],
+                layout: Ember.Handlebars.compile('&lt;div class=&quot;wrapper&quot;&gt;{{yield}}&lt;/div&gt;'),
+                template: Ember.Handlebars.compile('&lt;span&gt;I am wrapped&lt;/span&gt;')
+              });
+
+              aView = AView.create();
+              aView.appendTo('body');
+              ```
+
+              Will result in the following HTML output:
+
+              ```html
+              &lt;body&gt;
+                &lt;div class='ember-view a-view-with-layout'&gt;
+                  &lt;div class=&quot;wrapper&quot;&gt;
+                    &lt;span&gt;I am wrapped&lt;/span&gt;
+                  &lt;/div&gt;
+                &lt;/div&gt;
+              &lt;/body&gt;
+              ```
+
+              The `yield` helper cannot be used outside of a template assigned to an
+              `Ember.View`'s `layout` property and will throw an error if attempted.
+
+              ```javascript
+              BView = Ember.View.extend({
+                classNames: ['a-view-with-layout'],
+                template: Ember.Handlebars.compile('{{yield}}')
+              });
+
+              bView = BView.create();
+              bView.appendTo('body');
+
+              // throws
+              // Uncaught Error: assertion failed:
+              // You called yield in a template that was not a layout
+              ```
+
+              ### Use with Ember.Component
+              When designing components `{{yield}}` is used to denote where, inside the component's
+              template, an optional block passed to the component should render:
+
+              ```handlebars
+              &lt;!-- application.hbs --&gt;
+              {{#labeled-textfield value=someProperty}}
+                First name:
+              {{/labeled-textfield}}
+              ```
+
+              ```handlebars
+              &lt;!-- components/labeled-textfield.hbs --&gt;
+              &lt;label&gt;
+                {{yield}} {{input value=value}}
+              &lt;/label&gt;
+              ```
+
+              Result:
+
+              ```html
+              &lt;label&gt;
+                First name: &lt;input type=&quot;text&quot; /&gt;
+              &lt;/label&gt;
+              ```
+
+              @method yield
+              @for Ember.Handlebars.helpers
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        __exports__[&quot;default&quot;] = function yieldHelper(options) {
+            var view = options.data.view;
+
+            while (view &amp;&amp; !get(view, 'layout')) {
+                if (view._contextView) {
+                    view = view._contextView;
+                } else {
+                    view = get(view, '_parentView');
+                }
+            }
+
+            Ember.assert(&quot;You called yield in a template that was not a layout&quot;, !!view);
+
+            view._yield(this, options);
+        }
+    });
+    define(&quot;ember-handlebars/loader&quot;,
+    [&quot;ember-handlebars/component_lookup&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-metal/error&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-handlebars-compiler&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        /*globals Handlebars */
+
+        var ComponentLookup = __dependency1__[&quot;default&quot;];
+        var jQuery = __dependency2__[&quot;default&quot;];
+        var EmberError = __dependency3__[&quot;default&quot;];
+        var onLoad = __dependency4__.onLoad;
+
+        var EmberHandlebars = __dependency5__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        /**
+              Find templates stored in the head tag as script tags and make them available
+              to `Ember.CoreView` in the global `Ember.TEMPLATES` object. This will be run
+              as as jQuery DOM-ready callback.
+
+              Script tags with `text/x-handlebars` will be compiled
+              with Ember's Handlebars and are suitable for use as a view's template.
+              Those with type `text/x-raw-handlebars` will be compiled with regular
+              Handlebars and are suitable for use in views' computed properties.
+
+              @private
+              @method bootstrap
+              @for Ember.Handlebars
+              @static
+              @param ctx
+            */
+        function bootstrap(ctx) {
+            var selectors = 'script[type=&quot;text/x-handlebars&quot;], script[type=&quot;text/x-raw-handlebars&quot;]';
+
+            jQuery(selectors, ctx)
+            .each(function() {
+                // Get a reference to the script tag
+                var script = jQuery(this);
+
+                var compile = (script.attr('type') === 'text/x-raw-handlebars') ?
+                jQuery.proxy(Handlebars.compile, Handlebars) :
+                jQuery.proxy(EmberHandlebars.compile, EmberHandlebars),
+                // Get the name of the script, used by Ember.View's templateName property.
+                // First look for data-template-name attribute, then fall back to its
+                // id if no name is found.
+                templateName = script.attr('data-template-name') || script.attr('id') || 'application',
+                template = compile(script.html());
+
+                // Check if template of same name already exists
+                if (Ember.TEMPLATES[templateName] !== undefined) {
+                    throw new EmberError('Template named &quot;' + templateName + '&quot; already exists.');
+                }
+
+                // For templates which have a name, we save them and then remove them from the DOM
+                Ember.TEMPLATES[templateName] = template;
+
+                // Remove script tag from DOM
+                script.remove();
+            });
+        }
+
+        function _bootstrap() {
+            bootstrap( jQuery(document) );
+        }
+
+        function registerComponentLookup(container) {
+            container.register('component-lookup:main', ComponentLookup);
+        }
+
+        /*
+              We tie this to application.load to ensure that we've at least
+              attempted to bootstrap at the point that the application is loaded.
+
+              We also tie this to document ready since we're guaranteed that all
+              the inline templates are present at this point.
+
+              There's no harm to running this twice, since we remove the templates
+              from the DOM after processing.
+            */
+
+        onLoad('Ember.Application', function(Application) {
+            Application.initializer({
+                name: 'domTemplates',
+                initialize: _bootstrap
+            });
+
+            Application.initializer({
+                name: 'registerComponentLookup',
+                after: 'domTemplates',
+                initialize: registerComponentLookup
+            });
+        });
+
+        __exports__[&quot;default&quot;] = bootstrap;
+    });
+    define(&quot;ember-handlebars/string&quot;,
+    [&quot;ember-runtime/system/string&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        // required so we can extend this object.
+        var EmberStringUtils = __dependency1__[&quot;default&quot;];
+
+        /**
+              Mark a string as safe for unescaped output with Handlebars. If you
+              return HTML from a Handlebars helper, use this function to
+              ensure Handlebars does not escape the HTML.
+
+              ```javascript
+              Ember.String.htmlSafe('&lt;div&gt;someString&lt;/div&gt;')
+              ```
+
+              @method htmlSafe
+              @for Ember.String
+              @static
+              @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
+            */
+        function htmlSafe(str) {
+            return new Handlebars.SafeString(str);
+        }
+
+        EmberStringUtils.htmlSafe = htmlSafe;
+        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
+
+            /**
+                    Mark a string as being safe for unescaped output with Handlebars.
+
+                    ```javascript
+                    '&lt;div&gt;someString&lt;/div&gt;'.htmlSafe()
+                    ```
+
+                    See [Ember.String.htmlSafe](/api/classes/Ember.String.html#method_htmlSafe).
+
+                    @method htmlSafe
+                    @for String
+                    @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars
+                  */
+            String.prototype.htmlSafe = function() {
+                return htmlSafe(this);
+            };
+        }
+
+        __exports__[&quot;default&quot;] = htmlSafe;
+    });
+    define(&quot;ember-handlebars/views/handlebars_bound_view&quot;,
+    [&quot;ember-handlebars-compiler&quot;, &quot;ember-metal/core&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/computed&quot;, &quot;ember-views/views/view&quot;, &quot;ember-views/views/states&quot;, &quot;ember-handlebars/views/metamorph_view&quot;, &quot;ember-handlebars/ext&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
+        &quot;use strict&quot;;
+        /*globals Handlebars, Metamorph:true */
+        /*jshint newcap:false*/
+
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var EmberHandlebars = __dependency1__[&quot;default&quot;];
+        // EmberHandlebars.SafeString;
+        var SafeString = EmberHandlebars.SafeString;
+
+        var Ember = __dependency2__[&quot;default&quot;];
+        // Ember.K
+        var K = Ember.K;
+
+        var Metamorph = requireModule('metamorph');
+
+        var EmberError = __dependency3__[&quot;default&quot;];
+        var get = __dependency4__.get;
+        var set = __dependency5__.set;
+        var merge = __dependency6__[&quot;default&quot;];
+        var run = __dependency7__[&quot;default&quot;];
+        var computed = __dependency8__.computed;
+        var View = __dependency9__[&quot;default&quot;];
+        var cloneStates = __dependency10__.cloneStates;
+        var states = __dependency10__.states;
+        var viewStates = states;
+
+        var _MetamorphView = __dependency11__[&quot;default&quot;];
+        var handlebarsGet = __dependency12__.handlebarsGet;
+
+        function SimpleHandlebarsView(path, pathRoot, isEscaped, templateData) {
+            this.path = path;
+            this.pathRoot = pathRoot;
+            this.isEscaped = isEscaped;
+            this.templateData = templateData;
+
+            this._lastNormalizedValue = undefined;
+            this.morph = Metamorph();
+            this.state = 'preRender';
+            this.updateId = null;
+            this._parentView = null;
+            this.buffer = null;
+        }
+
+        SimpleHandlebarsView.prototype = {
+            isVirtual: true,
+            isView: true,
+
+            destroy: function () {
+                if (this.updateId) {
+                    run.cancel(this.updateId);
+                    this.updateId = null;
+                }
+                if (this._parentView) {
+                    this._parentView.removeChild(this);
+                }
+                this.morph = null;
+                this.state = 'destroyed';
+            },
+
+            propertyWillChange: K,
+
+            propertyDidChange: K,
+
+            normalizedValue: function() {
+                var path = this.path;
+                var pathRoot = this.pathRoot;
+                var result, templateData;
+
+                // Use the pathRoot as the result if no path is provided. This
+                // happens if the path is `this`, which gets normalized into
+                // a `pathRoot` of the current Handlebars context and a path
+                // of `''`.
+                if (path === '') {
+                    result = pathRoot;
+                } else {
+                    templateData = this.templateData;
+                    result = handlebarsGet(pathRoot, path, {
+                        data: templateData 
+                    });
+                }
+
+                return result;
+            },
+
+            renderToBuffer: function(buffer) {
+                var string = '';
+
+                string += this.morph.startTag();
+                string += this.render();
+                string += this.morph.endTag();
+
+                buffer.push(string);
+            },
+
+            render: function(value) {
+                // If not invoked via a triple-mustache ({{{foo}}}), escape
+                // the content of the template.
+                var escape = this.isEscaped;
+                var result = value || this.normalizedValue();
+                this._lastNormalizedValue = result;
+                if (result === null || result === undefined) {
+                    result = &quot;&quot;;
+                } else if (!(result instanceof SafeString)) {
+                    result = String(result);
+                }
+
+                if (escape) {
+                    result = Handlebars.Utils.escapeExpression(result);
+                }
+                return result;
+            },
+
+            rerender: function() {
+                switch (this.state) {
+                case 'preRender':
+                case 'destroyed':
+                    break;
+                case 'inBuffer':
+                    throw new EmberError(&quot;Something you did tried to replace an {{expression}} before it was inserted into the DOM.&quot;);
+                case 'hasElement':
+                case 'inDOM':
+                    this.updateId = run.scheduleOnce('render', this, 'update');
+                    break;
+                }
+
+                return this;
+            },
+
+            update: function () {
+                this.updateId = null;
+                var value = this.normalizedValue();
+                if (value !== this._lastNormalizedValue) {
+                    this.morph.html(this.render(value));
+                }
+            },
+
+            _transitionTo: function(state) {
+                this.state = state;
+            }
+        };
+
+        states = cloneStates(viewStates);
+
+        merge(states._default, {
+            rerenderIfNeeded: K
+        });
+
+        merge(states.inDOM, {
+            rerenderIfNeeded: function(view) {
+                if (view.normalizedValue() !== view._lastNormalizedValue) {
+                    view.rerender();
+                }
+            }
+        });
+
+        /**
+              `Ember._HandlebarsBoundView` is a private view created by the Handlebars
+              `{{bind}}` helpers that is used to keep track of bound properties.
+
+              Every time a property is bound using a `{{mustache}}`, an anonymous subclass
+              of `Ember._HandlebarsBoundView` is created with the appropriate sub-template
+              and context set up. When the associated property changes, just the template
+              for this view will re-render.
+
+              @class _HandlebarsBoundView
+              @namespace Ember
+              @extends Ember._MetamorphView
+              @private
+            */
+        var _HandlebarsBoundView = _MetamorphView.extend({
+            instrumentName: 'boundHandlebars',
+
+            _states: states,
+
+            /**
+                    The function used to determine if the `displayTemplate` or
+                    `inverseTemplate` should be rendered. This should be a function that takes
+                    a value and returns a Boolean.
+
+                    @property shouldDisplayFunc
+                    @type Function
+                    @default null
+                  */
+            shouldDisplayFunc: null,
+
+            /**
+                    Whether the template rendered by this view gets passed the context object
+                    of its parent template, or gets passed the value of retrieving `path`
+                    from the `pathRoot`.
+
+                    For example, this is true when using the `{{#if}}` helper, because the
+                    template inside the helper should look up properties relative to the same
+                    object as outside the block. This would be `false` when used with `{{#with
+                    foo}}` because the template should receive the object found by evaluating
+                    `foo`.
+
+                    @property preserveContext
+                    @type Boolean
+                    @default false
+                  */
+            preserveContext: false,
+
+            /**
+                    If `preserveContext` is true, this is the object that will be used
+                    to render the template.
+
+                    @property previousContext
+                    @type Object
+                  */
+            previousContext: null,
+
+            /**
+                    The template to render when `shouldDisplayFunc` evaluates to `true`.
+
+                    @property displayTemplate
+                    @type Function
+                    @default null
+                  */
+            displayTemplate: null,
+
+            /**
+                    The template to render when `shouldDisplayFunc` evaluates to `false`.
+
+                    @property inverseTemplate
+                    @type Function
+                    @default null
+                  */
+            inverseTemplate: null,
+
+
+            /**
+                    The path to look up on `pathRoot` that is passed to
+                    `shouldDisplayFunc` to determine which template to render.
+
+                    In addition, if `preserveContext` is `false,` the object at this path will
+                    be passed to the template when rendering.
+
+                    @property path
+                    @type String
+                    @default null
+                  */
+            path: null,
+
+            /**
+                    The object from which the `path` will be looked up. Sometimes this is the
+                    same as the `previousContext`, but in cases where this view has been
+                    generated for paths that start with a keyword such as `view` or
+                    `controller`, the path root will be that resolved object.
+
+                    @property pathRoot
+                    @type Object
+                  */
+            pathRoot: null,
+
+            normalizedValue: function() {
+                var path = get(this, 'path'),
+                pathRoot = get(this, 'pathRoot'),
+                valueNormalizer = get(this, 'valueNormalizerFunc'),
+                result, templateData;
+
+                // Use the pathRoot as the result if no path is provided. This
+                // happens if the path is `this`, which gets normalized into
+                // a `pathRoot` of the current Handlebars context and a path
+                // of `''`.
+                if (path === '') {
+                    result = pathRoot;
+                } else {
+                    templateData = get(this, 'templateData');
+                    result = handlebarsGet(pathRoot, path, {
+                        data: templateData 
+                    });
+                }
+
+                return valueNormalizer ? valueNormalizer(result) : result;
+            },
+
+            rerenderIfNeeded: function() {
+                this.currentState.rerenderIfNeeded(this);
+            },
+
+            /**
+                    Determines which template to invoke, sets up the correct state based on
+                    that logic, then invokes the default `Ember.View` `render` implementation.
+
+                    This method will first look up the `path` key on `pathRoot`,
+                    then pass that value to the `shouldDisplayFunc` function. If that returns
+                    `true,` the `displayTemplate` function will be rendered to DOM. Otherwise,
+                    `inverseTemplate`, if specified, will be rendered.
+
+                    For example, if this `Ember._HandlebarsBoundView` represented the `{{#with
+                    foo}}` helper, it would look up the `foo` property of its context, and
+                    `shouldDisplayFunc` would always return true. The object found by looking
+                    up `foo` would be passed to `displayTemplate`.
+
+                    @method render
+                    @param {Ember.RenderBuffer} buffer
+                  */
+            render: function(buffer) {
+                // If not invoked via a triple-mustache ({{{foo}}}), escape
+                // the content of the template.
+                var escape = get(this, 'isEscaped');
+
+                var shouldDisplay = get(this, 'shouldDisplayFunc'),
+                preserveContext = get(this, 'preserveContext'),
+                context = get(this, 'previousContext');
+
+                var inverseTemplate = get(this, 'inverseTemplate'),
+                displayTemplate = get(this, 'displayTemplate');
+
+                var result = this.normalizedValue();
+                this._lastNormalizedValue = result;
+
+                // First, test the conditional to see if we should
+                // render the template or not.
+                if (shouldDisplay(result)) {
+                    set(this, 'template', displayTemplate);
+
+                    // If we are preserving the context (for example, if this
+                    // is an #if block, call the template with the same object.
+                    if (preserveContext) {
+                        set(this, '_context', context);
+                    } else {
+                        // Otherwise, determine if this is a block bind or not.
+                        // If so, pass the specified object to the template
+                        if (displayTemplate) {
+                            set(this, '_context', result);
+                        } else {
+                            // This is not a bind block, just push the result of the
+                            // expression to the render context and return.
+                            if (result === null || result === undefined) {
+                                result = &quot;&quot;;
+                            } else if (!(result instanceof SafeString)) {
+                                result = String(result);
+                            }
+
+                            if (escape) {
+                                result = Handlebars.Utils.escapeExpression(result);
+                            }
+                            buffer.push(result);
+                            return;
+                        }
+                    }
+                } else if (inverseTemplate) {
+                    set(this, 'template', inverseTemplate);
+
+                    if (preserveContext) {
+                        set(this, '_context', context);
+                    } else {
+                        set(this, '_context', result);
+                    }
+                } else {
+                    set(this, 'template', function() {
+                        return '';
+                    });
+                }
+
+                return this._super(buffer);
+            }
+        });
+
+        __exports__._HandlebarsBoundView = _HandlebarsBoundView;
+        __exports__.SimpleHandlebarsView = SimpleHandlebarsView;
+    });
+    define(&quot;ember-handlebars/views/metamorph_view&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/views/core_view&quot;, &quot;ember-views/views/view&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/run_loop&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        /* global Metamorph:true */
+
+        /*jshint newcap:false*/
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.deprecate
+        // var emberDeprecate = Ember.deprecate;
+
+        var get = __dependency2__.get;
+        var set = __dependency3__[&quot;default&quot;];
+
+        var CoreView = __dependency4__[&quot;default&quot;];
+        var View = __dependency5__[&quot;default&quot;];
+        var Mixin = __dependency6__.Mixin;
+        var run = __dependency7__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-handlebars
+            */
+
+        var Metamorph = requireModule('metamorph');
+
+        function notifyMutationListeners() {
+            run.once(View, 'notifyMutationListeners');
+        }
+
+        // DOMManager should just abstract dom manipulation between jquery and metamorph
+        var DOMManager = {
+            remove: function(view) {
+                view.morph.remove();
+                notifyMutationListeners();
+            },
+
+            prepend: function(view, html) {
+                view.morph.prepend(html);
+                notifyMutationListeners();
+            },
+
+            after: function(view, html) {
+                view.morph.after(html);
+                notifyMutationListeners();
+            },
+
+            html: function(view, html) {
+                view.morph.html(html);
+                notifyMutationListeners();
+            },
+
+            // This is messed up.
+            replace: function(view) {
+                var morph = view.morph;
+
+                view._transitionTo('preRender');
+
+                run.schedule('render', this, function renderMetamorphView() {
+                    if (view.isDestroying) {
+                        return;
+                    }
+
+                    view.clearRenderedChildren();
+                    var buffer = view.renderToBuffer();
+
+                    view.invokeRecursively(function(view) {
+                        view.propertyWillChange('element');
+                    });
+                    view.triggerRecursively('willInsertElement');
+
+                    morph.replaceWith(buffer.string());
+                    view._transitionTo('inDOM');
+
+                    view.invokeRecursively(function(view) {
+                        view.propertyDidChange('element');
+                    });
+                    view.triggerRecursively('didInsertElement');
+
+                    notifyMutationListeners();
+                });
+            },
+
+            empty: function(view) {
+                view.morph.html(&quot;&quot;);
+                notifyMutationListeners();
+            }
+        };
+
+        // The `morph` and `outerHTML` properties are internal only
+        // and not observable.
+
+        /**
+              @class _Metamorph
+              @namespace Ember
+              @private
+            */
+        var _Metamorph = Mixin.create({
+            isVirtual: true,
+            tagName: '',
+
+            instrumentName: 'metamorph',
+
+            init: function() {
+                this._super();
+                this.morph = Metamorph();
+                Ember.deprecate('Supplying a tagName to Metamorph views is unreliable and is deprecated. You may be setting the tagName on a Handlebars helper that creates a Metamorph.', !this.tagName);
+            },
+
+            beforeRender: function(buffer) {
+                buffer.push(this.morph.startTag());
+                buffer.pushOpeningTag();
+            },
+
+            afterRender: function(buffer) {
+                buffer.pushClosingTag();
+                buffer.push(this.morph.endTag());
+            },
+
+            createElement: function() {
+                var buffer = this.renderToBuffer();
+                this.outerHTML = buffer.string();
+                this.clearBuffer();
+            },
+
+            domManager: DOMManager
+        });
+        __exports__._Metamorph = _Metamorph;
+        var _wrapMap = Metamorph._wrapMap;
+        __exports__._wrapMap = _wrapMap;
+        /**
+              @class _MetamorphView
+              @namespace Ember
+              @extends Ember.View
+              @uses Ember._Metamorph
+              @private
+            */
+        var _MetamorphView = View.extend(_Metamorph);
+        __exports__._MetamorphView = _MetamorphView;
+        /**
+              @class _SimpleMetamorphView
+              @namespace Ember
+              @extends Ember.CoreView
+              @uses Ember._Metamorph
+              @private
+            */
+        var _SimpleMetamorphView = CoreView.extend(_Metamorph);
+        __exports__._SimpleMetamorphView = _SimpleMetamorphView;
+        __exports__[&quot;default&quot;] = View.extend(_Metamorph);
+    });
+    define(&quot;ember-metal&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/instrumentation&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/logger&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/events&quot;, &quot;ember-metal/observer_set&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/map&quot;, &quot;ember-metal/get_properties&quot;, &quot;ember-metal/set_properties&quot;, &quot;ember-metal/watch_key&quot;, &quot;ember-metal/chains&quot;, &quot;ember-metal/watch_path&quot;, &quot;ember-metal/watching&quot;, &quot;ember-metal/expand_properties&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/computed_macros&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/binding&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/libraries&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/is_empty&quot;, &quot;ember-metal/is_blank&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __dependency29__, __dependency30__, __dependency31__, __dependency32__, __dependency33__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            Ember Metal
+
+            @module ember
+            @submodule ember-metal
+            */
+
+        // BEGIN IMPORTS
+        var Ember = __dependency1__[&quot;default&quot;];
+        var merge = __dependency2__[&quot;default&quot;];
+        var instrument = __dependency3__.instrument;
+        var subscribe = __dependency3__.subscribe;
+        var unsubscribe = __dependency3__.unsubscribe;
+        var reset = __dependency3__.reset;
+        var generateGuid = __dependency4__.generateGuid;
+        var GUID_KEY = __dependency4__.GUID_KEY;
+        var GUID_PREFIX = __dependency4__.GUID_PREFIX;
+        var guidFor = __dependency4__.guidFor;
+        var META_DESC = __dependency4__.META_DESC;
+        var EMPTY_META = __dependency4__.EMPTY_META;
+        var meta = __dependency4__.meta;
+        var getMeta = __dependency4__.getMeta;
+        var setMeta = __dependency4__.setMeta;
+        var metaPath = __dependency4__.metaPath;
+        var inspect = __dependency4__.inspect;
+        var typeOf = __dependency4__.typeOf;
+        var tryCatchFinally = __dependency4__.tryCatchFinally;
+        var isArray = __dependency4__.isArray;
+        var makeArray = __dependency4__.makeArray;
+        var canInvoke = __dependency4__.canInvoke;
+        var tryInvoke = __dependency4__.tryInvoke;
+        var tryFinally = __dependency4__.tryFinally;
+        var wrap = __dependency4__.wrap;
+        var apply = __dependency4__.apply;
+        var applyStr = __dependency4__.applyStr;
+        var EmberError = __dependency5__[&quot;default&quot;];
+        var EnumerableUtils = __dependency6__[&quot;default&quot;];
+
+        var create = __dependency7__.create;
+        var platform = __dependency7__.platform;
+        var map = __dependency8__.map;
+        var forEach = __dependency8__.forEach;
+        var filter = __dependency8__.filter;
+        var indexOf = __dependency8__.indexOf;
+        var Logger = __dependency9__[&quot;default&quot;];
+
+        var get = __dependency10__.get;
+        var getWithDefault = __dependency10__.getWithDefault;
+        var normalizeTuple = __dependency10__.normalizeTuple;
+        var _getPath = __dependency10__._getPath;
+
+        var on = __dependency11__.on;
+        var addListener = __dependency11__.addListener;
+        var removeListener = __dependency11__.removeListener;
+        var suspendListener = __dependency11__.suspendListener;
+        var suspendListeners = __dependency11__.suspendListeners;
+        var sendEvent = __dependency11__.sendEvent;
+        var hasListeners = __dependency11__.hasListeners;
+        var watchedEvents = __dependency11__.watchedEvents;
+        var listenersFor = __dependency11__.listenersFor;
+        var listenersDiff = __dependency11__.listenersDiff;
+        var listenersUnion = __dependency11__.listenersUnion;
+
+        var ObserverSet = __dependency12__[&quot;default&quot;];
+
+        var propertyWillChange = __dependency13__.propertyWillChange;
+        var propertyDidChange = __dependency13__.propertyDidChange;
+        var overrideChains = __dependency13__.overrideChains;
+        var beginPropertyChanges = __dependency13__.beginPropertyChanges;
+        var endPropertyChanges = __dependency13__.endPropertyChanges;
+        var changeProperties = __dependency13__.changeProperties;
+
+        var Descriptor = __dependency14__.Descriptor;
+        var defineProperty = __dependency14__.defineProperty;
+        var set = __dependency15__.set;
+        var trySet = __dependency15__.trySet;
+
+        var OrderedSet = __dependency16__.OrderedSet;
+        var Map = __dependency16__.Map;
+        var MapWithDefault = __dependency16__.MapWithDefault;
+        var getProperties = __dependency17__[&quot;default&quot;];
+        var setProperties = __dependency18__[&quot;default&quot;];
+        var watchKey = __dependency19__.watchKey;
+        var unwatchKey = __dependency19__.unwatchKey;
+        var flushPendingChains = __dependency20__.flushPendingChains;
+        var removeChainWatcher = __dependency20__.removeChainWatcher;
+        var ChainNode = __dependency20__.ChainNode;
+        var finishChains = __dependency20__.finishChains;
+        var watchPath = __dependency21__.watchPath;
+        var unwatchPath = __dependency21__.unwatchPath;
+        var watch = __dependency22__.watch;
+        var isWatching = __dependency22__.isWatching;
+        var unwatch = __dependency22__.unwatch;
+        var rewatch = __dependency22__.rewatch;
+        var destroy = __dependency22__.destroy;
+        var expandProperties = __dependency23__[&quot;default&quot;];
+        var ComputedProperty = __dependency24__.ComputedProperty;
+        var computed = __dependency24__.computed;
+        var cacheFor = __dependency24__.cacheFor;
+
+        // side effect of defining the computed.* macros
+
+        var addObserver = __dependency26__.addObserver;
+        var observersFor = __dependency26__.observersFor;
+        var removeObserver = __dependency26__.removeObserver;
+        var addBeforeObserver = __dependency26__.addBeforeObserver;
+        var _suspendBeforeObserver = __dependency26__._suspendBeforeObserver;
+        var _suspendObserver = __dependency26__._suspendObserver;
+        var _suspendBeforeObservers = __dependency26__._suspendBeforeObservers;
+        var _suspendObservers = __dependency26__._suspendObservers;
+        var beforeObserversFor = __dependency26__.beforeObserversFor;
+        var removeBeforeObserver = __dependency26__.removeBeforeObserver;
+        var IS_BINDING = __dependency27__.IS_BINDING;
+        var mixin = __dependency27__.mixin;
+        var Mixin = __dependency27__.Mixin;
+        var required = __dependency27__.required;
+        var aliasMethod = __dependency27__.aliasMethod;
+        var observer = __dependency27__.observer;
+        var immediateObserver = __dependency27__.immediateObserver;
+        var beforeObserver = __dependency27__.beforeObserver;
+        var Binding = __dependency28__.Binding;
+        var isGlobalPath = __dependency28__.isGlobalPath;
+        var bind = __dependency28__.bind;
+        var oneWay = __dependency28__.oneWay;
+        var run = __dependency29__[&quot;default&quot;];
+        var libraries = __dependency30__[&quot;default&quot;];
+        var isNone = __dependency31__.isNone;
+        var none = __dependency31__.none;
+        var isEmpty = __dependency32__.isEmpty;
+        var empty = __dependency32__.empty;
+        var isBlank = __dependency33__[&quot;default&quot;];
+        // END IMPORTS
+
+        // BEGIN EXPORTS
+        var EmberInstrumentation = Ember.Instrumentation = {};
+        EmberInstrumentation.instrument = instrument;
+        EmberInstrumentation.subscribe = subscribe;
+        EmberInstrumentation.unsubscribe = unsubscribe;
+        EmberInstrumentation.reset = reset;
+
+        Ember.instrument = instrument;
+        Ember.subscribe = subscribe;
+
+        Ember.generateGuid = generateGuid;
+        Ember.GUID_KEY = GUID_KEY;
+        Ember.GUID_PREFIX = GUID_PREFIX;
+        Ember.create = create;
+        Ember.platform = platform;
+
+        var EmberArrayPolyfills = Ember.ArrayPolyfills = {};
+
+        EmberArrayPolyfills.map = map;
+        EmberArrayPolyfills.forEach = forEach;
+        EmberArrayPolyfills.filter = filter;
+        EmberArrayPolyfills.indexOf = indexOf;
+
+        Ember.Error = EmberError;
+        Ember.guidFor = guidFor;
+        Ember.META_DESC = META_DESC;
+        Ember.EMPTY_META = EMPTY_META;
+        Ember.meta = meta;
+        Ember.getMeta = getMeta;
+        Ember.setMeta = setMeta;
+        Ember.metaPath = metaPath;
+        Ember.inspect = inspect;
+        Ember.typeOf = typeOf;
+        Ember.tryCatchFinally = tryCatchFinally;
+        Ember.isArray = isArray;
+        Ember.makeArray = makeArray;
+        Ember.canInvoke = canInvoke;
+        Ember.tryInvoke = tryInvoke;
+        Ember.tryFinally = tryFinally;
+        Ember.wrap = wrap;
+        Ember.apply = apply;
+        Ember.applyStr = applyStr;
+
+        Ember.Logger = Logger;
+
+        Ember.get = get;
+        Ember.getWithDefault = getWithDefault;
+        Ember.normalizeTuple = normalizeTuple;
+        Ember._getPath = _getPath;
+
+        Ember.EnumerableUtils = EnumerableUtils;
+
+        Ember.on = on;
+        Ember.addListener = addListener;
+        Ember.removeListener = removeListener;
+        Ember._suspendListener = suspendListener;
+        Ember._suspendListeners = suspendListeners;
+        Ember.sendEvent = sendEvent;
+        Ember.hasListeners = hasListeners;
+        Ember.watchedEvents = watchedEvents;
+        Ember.listenersFor = listenersFor;
+        Ember.listenersDiff = listenersDiff;
+        Ember.listenersUnion = listenersUnion;
+
+        Ember._ObserverSet = ObserverSet;
+
+        Ember.propertyWillChange = propertyWillChange;
+        Ember.propertyDidChange = propertyDidChange;
+        Ember.overrideChains = overrideChains;
+        Ember.beginPropertyChanges = beginPropertyChanges;
+        Ember.endPropertyChanges = endPropertyChanges;
+        Ember.changeProperties = changeProperties;
+
+        Ember.Descriptor = Descriptor;
+        Ember.defineProperty = defineProperty;
+
+        Ember.set = set;
+        Ember.trySet = trySet;
+
+        Ember.OrderedSet = OrderedSet;
+        Ember.Map = Map;
+        Ember.MapWithDefault = MapWithDefault;
+
+        Ember.getProperties = getProperties;
+        Ember.setProperties = setProperties;
+
+        Ember.watchKey = watchKey;
+        Ember.unwatchKey = unwatchKey;
+
+        Ember.flushPendingChains = flushPendingChains;
+        Ember.removeChainWatcher = removeChainWatcher;
+        Ember._ChainNode = ChainNode;
+        Ember.finishChains = finishChains;
+
+        Ember.watchPath = watchPath;
+        Ember.unwatchPath = unwatchPath;
+
+        Ember.watch = watch;
+        Ember.isWatching = isWatching;
+        Ember.unwatch = unwatch;
+        Ember.rewatch = rewatch;
+        Ember.destroy = destroy;
+
+        Ember.expandProperties = expandProperties;
+
+        Ember.ComputedProperty = ComputedProperty;
+        Ember.computed = computed;
+        Ember.cacheFor = cacheFor;
+
+        Ember.addObserver = addObserver;
+        Ember.observersFor = observersFor;
+        Ember.removeObserver = removeObserver;
+        Ember.addBeforeObserver = addBeforeObserver;
+        Ember._suspendBeforeObserver = _suspendBeforeObserver;
+        Ember._suspendBeforeObservers = _suspendBeforeObservers;
+        Ember._suspendObserver = _suspendObserver;
+        Ember._suspendObservers = _suspendObservers;
+        Ember.beforeObserversFor = beforeObserversFor;
+        Ember.removeBeforeObserver = removeBeforeObserver;
+
+        Ember.IS_BINDING = IS_BINDING;
+        Ember.required = required;
+        Ember.aliasMethod = aliasMethod;
+        Ember.observer = observer;
+        Ember.immediateObserver = immediateObserver;
+        Ember.beforeObserver = beforeObserver;
+        Ember.mixin = mixin;
+        Ember.Mixin = Mixin;
+
+        Ember.oneWay = oneWay;
+        Ember.bind = bind;
+        Ember.Binding = Binding;
+        Ember.isGlobalPath = isGlobalPath;
+
+        Ember.run = run;
+
+        Ember.libraries = libraries;
+        Ember.libraries.registerCoreLibrary('Ember', Ember.VERSION);
+
+        Ember.isNone = isNone;
+        Ember.none = none;
+
+        Ember.isEmpty = isEmpty;
+        Ember.empty = empty;
+
+        Ember.isBlank = isBlank;
+
+        Ember.merge = merge;
+
+        /**
+              A function may be assigned to `Ember.onerror` to be called when Ember
+              internals encounter an error. This is useful for specialized error handling
+              and reporting code.
+
+              ```javascript
+              Ember.onerror = function(error) {
+                Em.$.ajax('/report-error', 'POST', {
+                  stack: error.stack,
+                  otherInformation: 'whatever app state you want to provide'
+                });
+              };
+              ```
+
+              Internally, `Ember.onerror` is used as Backburner's error handler.
+
+              @event onerror
+              @for Ember
+              @param {Exception} error the error object
+            */
+        Ember.onerror = null;
+        // END EXPORTS
+
+        // do this for side-effects of updating Ember.assert, warn, etc when
+        // ember-debug is present
+        if (Ember.__loader.registry['ember-debug']) {
+            requireModule('ember-debug');
+        }
+
+        __exports__[&quot;default&quot;] = Ember;
+    });
+    define(&quot;ember-metal/alias&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/dependent_keys&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var EmberError = __dependency3__[&quot;default&quot;];
+        var Descriptor = __dependency4__.Descriptor;
+        var defineProperty = __dependency4__.defineProperty;
+        var ComputedProperty = __dependency5__.ComputedProperty;
+        var create = __dependency6__.create;
+        var meta = __dependency7__.meta;
+        var inspect = __dependency7__.inspect;
+        var addDependentKeys = __dependency8__.addDependentKeys;
+        var removeDependentKeys = __dependency8__.removeDependentKeys;
+
+        function alias(altKey) {
+            return new AliasedProperty(altKey);
+        }
+
+        __exports__.alias = alias;
+        function AliasedProperty(altKey) {
+            this.altKey = altKey;
+            this._dependentKeys = [ altKey ];
+        }
+
+        __exports__.AliasedProperty = AliasedProperty;
+        AliasedProperty.prototype = create(Descriptor.prototype);
+
+        AliasedProperty.prototype.get = function AliasedProperty_get(obj, keyName) {
+            return get(obj, this.altKey);
+        };
+
+        AliasedProperty.prototype.set = function AliasedProperty_set(obj, keyName, value) {
+            return set(obj, this.altKey, value);
+        };
+
+        AliasedProperty.prototype.willWatch = function(obj, keyName) {
+            addDependentKeys(this, obj, keyName, meta(obj));
+        };
+
+        AliasedProperty.prototype.didUnwatch = function(obj, keyName) {
+            removeDependentKeys(this, obj, keyName, meta(obj));
+        };
+
+        AliasedProperty.prototype.setup = function(obj, keyName) {
+            var m = meta(obj);
+            if (m.watching[keyName]) {
+                addDependentKeys(this, obj, keyName, m);
+            }
+        };
+
+        AliasedProperty.prototype.teardown = function(obj, keyName) {
+            var m = meta(obj);
+            if (m.watching[keyName]) {
+                removeDependentKeys(this, obj, keyName, m);
+            }
+        };
+
+        AliasedProperty.prototype.readOnly = function() {
+            this.set = AliasedProperty_readOnlySet;
+            return this;
+        };
+
+        function AliasedProperty_readOnlySet(obj, keyName, value) {
+            throw new EmberError('Cannot set read-only property &quot;' + keyName + '&quot; on object: ' + inspect(obj));
+        }
+
+        AliasedProperty.prototype.oneWay = function() {
+            this.set = AliasedProperty_oneWaySet;
+            return this;
+        };
+
+        function AliasedProperty_oneWaySet(obj, keyName, value) {
+            defineProperty(obj, keyName, null);
+            return set(obj, keyName, value);
+        }
+
+        // Backwards compatibility with Ember Data
+        AliasedProperty.prototype._meta = undefined;
+        AliasedProperty.prototype.meta = ComputedProperty.prototype.meta;
+    });
+    define(&quot;ember-metal/array&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember-metal
+            */
+
+        var ArrayPrototype = Array.prototype;
+
+        // Testing this is not ideal, but we want to use native functions
+        // if available, but not to use versions created by libraries like Prototype
+        var isNativeFunc = function(func) {
+            // This should probably work in all browsers likely to have ES5 array methods
+            return func &amp;&amp; Function.prototype.toString.call(func).indexOf('[native code]') &gt; -1;
+        };
+
+        // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map
+        var map = isNativeFunc(ArrayPrototype.map) ? ArrayPrototype.map : function(fun /*, thisp */
+        ) {
+            //&quot;use strict&quot;;
+
+            if (this === void 0 || this === null) {
+                throw new TypeError();
+            }
+
+            var t = Object(this);
+            var len = t.length &gt;&gt;&gt; 0;
+            if (typeof fun !== &quot;function&quot;) {
+                throw new TypeError();
+            }
+
+            var res = new Array(len);
+            var thisp = arguments[1];
+            for (var i = 0; i &lt; len; i++) {
+                if (i in t) {
+                    res[i] = fun.call(thisp, t[i], i, t);
+                }
+            }
+
+            return res;
+        };
+
+        // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach
+        var forEach = isNativeFunc(ArrayPrototype.forEach) ? ArrayPrototype.forEach : function(fun /*, thisp */
+        ) {
+            //&quot;use strict&quot;;
+
+            if (this === void 0 || this === null) {
+                throw new TypeError();
+            }
+
+            var t = Object(this);
+            var len = t.length &gt;&gt;&gt; 0;
+            if (typeof fun !== &quot;function&quot;) {
+                throw new TypeError();
+            }
+
+            var thisp = arguments[1];
+            for (var i = 0; i &lt; len; i++) {
+                if (i in t) {
+                    fun.call(thisp, t[i], i, t);
+                }
+            }
+        };
+
+        var indexOf = isNativeFunc(ArrayPrototype.indexOf) ? ArrayPrototype.indexOf : function (obj, fromIndex) {
+            if (fromIndex === null || fromIndex === undefined) {
+                fromIndex = 0;
+            } else if (fromIndex &lt; 0) {
+                fromIndex = Math.max(0, this.length + fromIndex);
+            }
+            for (var i = fromIndex, j = this.length; i &lt; j; i++) {
+                if (this[i] === obj) {
+                    return i;
+                }
+            }
+            return -1;
+        };
+
+        var filter = isNativeFunc(ArrayPrototype.filter) ? ArrayPrototype.filter : function (fn, context) {
+            var i,
+            value,
+            result = [],
+            length = this.length;
+
+            for (i = 0; i &lt; length; i++) {
+                if (this.hasOwnProperty(i)) {
+                    value = this[i];
+                    if (fn.call(context, value, i, this)) {
+                        result.push(value);
+                    }
+                }
+            }
+            return result;
+        };
+
+
+        if (Ember.SHIM_ES5) {
+            if (!ArrayPrototype.map) {
+                ArrayPrototype.map = map;
+            }
+
+            if (!ArrayPrototype.forEach) {
+                ArrayPrototype.forEach = forEach;
+            }
+
+            if (!ArrayPrototype.filter) {
+                ArrayPrototype.filter = filter;
+            }
+
+            if (!ArrayPrototype.indexOf) {
+                ArrayPrototype.indexOf = indexOf;
+            }
+        }
+
+        /**
+              Array polyfills to support ES5 features in older browsers.
+
+              @namespace Ember
+              @property ArrayPolyfills
+            */
+        __exports__.map = map;
+        __exports__.forEach = forEach;
+        __exports__.filter = filter;
+        __exports__.indexOf = indexOf;
+    });
+    define(&quot;ember-metal/binding&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/map&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/run_loop&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.Logger, Ember.LOG_BINDINGS, assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var trySet = __dependency3__.trySet;
+        var guidFor = __dependency4__.guidFor;
+        var Map = __dependency5__.Map;
+        var addObserver = __dependency6__.addObserver;
+        var removeObserver = __dependency6__.removeObserver;
+        var _suspendObserver = __dependency6__._suspendObserver;
+        var run = __dependency7__[&quot;default&quot;];
+
+        // ES6TODO: where is Ember.lookup defined?
+        /**
+            @module ember-metal
+            */
+
+        // ..........................................................
+        // CONSTANTS
+        //
+
+        /**
+              Debug parameter you can turn on. This will log all bindings that fire to
+              the console. This should be disabled in production code. Note that you
+              can also enable this from the console or temporarily.
+
+              @property LOG_BINDINGS
+              @for Ember
+              @type Boolean
+              @default false
+            */
+        Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS;
+
+        var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
+
+        /**
+              Returns true if the provided path is global (e.g., `MyApp.fooController.bar`)
+              instead of local (`foo.bar.baz`).
+
+              @method isGlobalPath
+              @for Ember
+              @private
+              @param {String} path
+              @return Boolean
+            */
+        function isGlobalPath(path) {
+            return IS_GLOBAL.test(path);
+        }
+
+        function getWithGlobals(obj, path) {
+            return get(isGlobalPath(path) ? Ember.lookup : obj, path);
+        }
+
+        // ..........................................................
+        // BINDING
+        //
+
+        function Binding(toPath, fromPath) {
+            this._direction = 'fwd';
+            this._from = fromPath;
+            this._to = toPath;
+            this._directionMap = Map.create();
+            this._readyToSync = undefined;
+            this._oneWay = undefined;
+        }
+
+        /**
+            @class Binding
+            @namespace Ember
+            */
+
+        Binding.prototype = {
+            /**
+                    This copies the Binding so it can be connected to another object.
+
+                    @method copy
+                    @return {Ember.Binding} `this`
+                  */
+            copy: function () {
+                var copy = new Binding(this._to, this._from);
+                if (this._oneWay) {
+                    copy._oneWay = true;
+                }
+                return copy;
+            },
+
+            // ..........................................................
+            // CONFIG
+            //
+
+            /**
+                    This will set `from` property path to the specified value. It will not
+                    attempt to resolve this property path to an actual object until you
+                    connect the binding.
+
+                    The binding will search for the property path starting at the root object
+                    you pass when you `connect()` the binding. It follows the same rules as
+                    `get()` - see that method for more information.
+
+                    @method from
+                    @param {String} path the property path to connect to
+                    @return {Ember.Binding} `this`
+                  */
+            from: function(path) {
+                this._from = path;
+                return this;
+            },
+
+            /**
+                    This will set the `to` property path to the specified value. It will not
+                    attempt to resolve this property path to an actual object until you
+                    connect the binding.
+
+                    The binding will search for the property path starting at the root object
+                    you pass when you `connect()` the binding. It follows the same rules as
+                    `get()` - see that method for more information.
+
+                    @method to
+                    @param {String|Tuple} path A property path or tuple
+                    @return {Ember.Binding} `this`
+                  */
+            to: function(path) {
+                this._to = path;
+                return this;
+            },
+
+            /**
+                    Configures the binding as one way. A one-way binding will relay changes
+                    on the `from` side to the `to` side, but not the other way around. This
+                    means that if you change the `to` side directly, the `from` side may have
+                    a different value.
+
+                    @method oneWay
+                    @return {Ember.Binding} `this`
+                  */
+            oneWay: function() {
+                this._oneWay = true;
+                return this;
+            },
+
+            /**
+                    @method toString
+                    @return {String} string representation of binding
+                  */
+            toString: function() {
+                var oneWay = this._oneWay ? '[oneWay]' : '';
+                return &quot;Ember.Binding&lt;&quot; + guidFor(this) + &quot;&gt;(&quot; + this._from + &quot; -&gt; &quot; + this._to + &quot;)&quot; + oneWay;
+            },
+
+            // ..........................................................
+            // CONNECT AND SYNC
+            //
+
+            /**
+                    Attempts to connect this binding instance so that it can receive and relay
+                    changes. This method will raise an exception if you have not set the
+                    from/to properties yet.
+
+                    @method connect
+                    @param {Object} obj The root object for this binding.
+                    @return {Ember.Binding} `this`
+                  */
+            connect: function(obj) {
+                Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);
+
+                var fromPath = this._from, toPath = this._to;
+                trySet(obj, toPath, getWithGlobals(obj, fromPath));
+
+                // add an observer on the object to be notified when the binding should be updated
+                addObserver(obj, fromPath, this, this.fromDidChange);
+
+                // if the binding is a two-way binding, also set up an observer on the target
+                if (!this._oneWay) {
+                    addObserver(obj, toPath, this, this.toDidChange);
+                }
+
+                this._readyToSync = true;
+
+                return this;
+            },
+
+            /**
+                    Disconnects the binding instance. Changes will no longer be relayed. You
+                    will not usually need to call this method.
+
+                    @method disconnect
+                    @param {Object} obj The root object you passed when connecting the binding.
+                    @return {Ember.Binding} `this`
+                  */
+            disconnect: function(obj) {
+                Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj);
+
+                var twoWay = !this._oneWay;
+
+                // remove an observer on the object so we're no longer notified of
+                // changes that should update bindings.
+                removeObserver(obj, this._from, this, this.fromDidChange);
+
+                // if the binding is two-way, remove the observer from the target as well
+                if (twoWay) {
+                    removeObserver(obj, this._to, this, this.toDidChange);
+                }
+
+                this._readyToSync = false; // disable scheduled syncs...
+                return this;
+            },
+
+            // ..........................................................
+            // PRIVATE
+            //
+
+            /* called when the from side changes */
+            fromDidChange: function(target) {
+                this._scheduleSync(target, 'fwd');
+            },
+
+            /* called when the to side changes */
+            toDidChange: function(target) {
+                this._scheduleSync(target, 'back');
+            },
+
+            _scheduleSync: function(obj, dir) {
+                var directionMap = this._directionMap;
+                var existingDir = directionMap.get(obj);
+
+                // if we haven't scheduled the binding yet, schedule it
+                if (!existingDir) {
+                    run.schedule('sync', this, this._sync, obj);
+                    directionMap.set(obj, dir);
+                }
+
+                // If both a 'back' and 'fwd' sync have been scheduled on the same object,
+                // default to a 'fwd' sync so that it remains deterministic.
+                if (existingDir === 'back' &amp;&amp; dir === 'fwd') {
+                    directionMap.set(obj, 'fwd');
+                }
+            },
+
+            _sync: function(obj) {
+                var log = Ember.LOG_BINDINGS;
+
+                // don't synchronize destroyed objects or disconnected bindings
+                if (obj.isDestroyed || !this._readyToSync) {
+                    return;
+                }
+
+                // get the direction of the binding for the object we are
+                // synchronizing from
+                var directionMap = this._directionMap;
+                var direction = directionMap.get(obj);
+
+                var fromPath = this._from, toPath = this._to;
+
+                directionMap.remove(obj);
+
+                // if we're synchronizing from the remote object...
+                if (direction === 'fwd') {
+                    var fromValue = getWithGlobals(obj, this._from);
+                    if (log) {
+                        Ember.Logger.log(' ', this.toString(), '-&gt;', fromValue, obj);
+                    }
+                    if (this._oneWay) {
+                        trySet(obj, toPath, fromValue);
+                    } else {
+                        _suspendObserver(obj, toPath, this, this.toDidChange, function () {
+                            trySet(obj, toPath, fromValue);
+                        });
+                    }
+                    // if we're synchronizing *to* the remote object
+                } else if (direction === 'back') {
+                    var toValue = get(obj, this._to);
+                    if (log) {
+                        Ember.Logger.log(' ', this.toString(), '&lt;-', toValue, obj);
+                    }
+                    _suspendObserver(obj, fromPath, this, this.fromDidChange, function () {
+                        trySet(isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue);
+                    });
+                }
+            }
+
+        };
+
+        function mixinProperties(to, from) {
+            for (var key in from) {
+                if (from.hasOwnProperty(key)) {
+                    to[key] = from[key];
+                }
+            }
+        }
+
+        mixinProperties(Binding, {
+
+            /*
+                    See `Ember.Binding.from`.
+
+                    @method from
+                    @static
+                  */
+            from: function() {
+                var C = this, binding = new C();
+                return binding.from.apply(binding, arguments);
+            },
+
+            /*
+                    See `Ember.Binding.to`.
+
+                    @method to
+                    @static
+                  */
+            to: function() {
+                var C = this, binding = new C();
+                return binding.to.apply(binding, arguments);
+            },
+
+            /**
+                    Creates a new Binding instance and makes it apply in a single direction.
+                    A one-way binding will relay changes on the `from` side object (supplied
+                    as the `from` argument) the `to` side, but not the other way around.
+                    This means that if you change the &quot;to&quot; side directly, the &quot;from&quot; side may have
+                    a different value.
+
+                    See `Binding.oneWay`.
+
+                    @method oneWay
+                    @param {String} from from path.
+                    @param {Boolean} [flag] (Optional) passing nothing here will make the
+                      binding `oneWay`. You can instead pass `false` to disable `oneWay`, making the
+                      binding two way again.
+                    @return {Ember.Binding} `this`
+                  */
+            oneWay: function(from, flag) {
+                var C = this, binding = new C(null, from);
+                return binding.oneWay(flag);
+            }
+
+        });
+        /**
+              An `Ember.Binding` connects the properties of two objects so that whenever
+              the value of one property changes, the other property will be changed also.
+
+              ## Automatic Creation of Bindings with `/^*Binding/`-named Properties
+
+              You do not usually create Binding objects directly but instead describe
+              bindings in your class or object definition using automatic binding
+              detection.
+
+              Properties ending in a `Binding` suffix will be converted to `Ember.Binding`
+              instances. The value of this property should be a string representing a path
+              to another object or a custom binding instanced created using Binding helpers
+              (see &quot;One Way Bindings&quot;):
+
+              ```
+              valueBinding: &quot;MyApp.someController.title&quot;
+              ```
+
+              This will create a binding from `MyApp.someController.title` to the `value`
+              property of your object instance automatically. Now the two values will be
+              kept in sync.
+
+              ## One Way Bindings
+
+              One especially useful binding customization you can use is the `oneWay()`
+              helper. This helper tells Ember that you are only interested in
+              receiving changes on the object you are binding from. For example, if you
+              are binding to a preference and you want to be notified if the preference
+              has changed, but your object will not be changing the preference itself, you
+              could do:
+
+              ```
+              bigTitlesBinding: Ember.Binding.oneWay(&quot;MyApp.preferencesController.bigTitles&quot;)
+              ```
+
+              This way if the value of `MyApp.preferencesController.bigTitles` changes the
+              `bigTitles` property of your object will change also. However, if you
+              change the value of your `bigTitles` property, it will not update the
+              `preferencesController`.
+
+              One way bindings are almost twice as fast to setup and twice as fast to
+              execute because the binding only has to worry about changes to one side.
+
+              You should consider using one way bindings anytime you have an object that
+              may be created frequently and you do not intend to change a property; only
+              to monitor it for changes (such as in the example above).
+
+              ## Adding Bindings Manually
+
+              All of the examples above show you how to configure a custom binding, but the
+              result of these customizations will be a binding template, not a fully active
+              Binding instance. The binding will actually become active only when you
+              instantiate the object the binding belongs to. It is useful however, to
+              understand what actually happens when the binding is activated.
+
+              For a binding to function it must have at least a `from` property and a `to`
+              property. The `from` property path points to the object/key that you want to
+              bind from while the `to` path points to the object/key you want to bind to.
+
+              When you define a custom binding, you are usually describing the property
+              you want to bind from (such as `MyApp.someController.value` in the examples
+              above). When your object is created, it will automatically assign the value
+              you want to bind `to` based on the name of your binding key. In the
+              examples above, during init, Ember objects will effectively call
+              something like this on your binding:
+
+              ```javascript
+              binding = Ember.Binding.from(this.valueBinding).to(&quot;value&quot;);
+              ```
+
+              This creates a new binding instance based on the template you provide, and
+              sets the to path to the `value` property of the new object. Now that the
+              binding is fully configured with a `from` and a `to`, it simply needs to be
+              connected to become active. This is done through the `connect()` method:
+
+              ```javascript
+              binding.connect(this);
+              ```
+
+              Note that when you connect a binding you pass the object you want it to be
+              connected to. This object will be used as the root for both the from and
+              to side of the binding when inspecting relative paths. This allows the
+              binding to be automatically inherited by subclassed objects as well.
+
+              Now that the binding is connected, it will observe both the from and to side
+              and relay changes.
+
+              If you ever needed to do so (you almost never will, but it is useful to
+              understand this anyway), you could manually create an active binding by
+              using the `Ember.bind()` helper method. (This is the same method used by
+              to setup your bindings on objects):
+
+              ```javascript
+              Ember.bind(MyApp.anotherObject, &quot;value&quot;, &quot;MyApp.someController.value&quot;);
+              ```
+
+              Both of these code fragments have the same effect as doing the most friendly
+              form of binding creation like so:
+
+              ```javascript
+              MyApp.anotherObject = Ember.Object.create({
+                valueBinding: &quot;MyApp.someController.value&quot;,
+
+                // OTHER CODE FOR THIS OBJECT...
+              });
+              ```
+
+              Ember's built in binding creation method makes it easy to automatically
+              create bindings for you. You should always use the highest-level APIs
+              available, even if you understand how it works underneath.
+
+              @class Binding
+              @namespace Ember
+              @since Ember 0.9
+            */
+        // Ember.Binding = Binding; ES6TODO: where to put this?
+
+
+        /**
+              Global helper method to create a new binding. Just pass the root object
+              along with a `to` and `from` path to create and connect the binding.
+
+              @method bind
+              @for Ember
+              @param {Object} obj The root object of the transform.
+              @param {String} to The path to the 'to' side of the binding.
+                Must be relative to obj.
+              @param {String} from The path to the 'from' side of the binding.
+                Must be relative to obj or a global path.
+              @return {Ember.Binding} binding instance
+            */
+        function bind(obj, to, from) {
+            return new Binding(to, from).connect(obj);
+        }
+
+        __exports__.bind = bind; /**
+              @method oneWay
+              @for Ember
+              @param {Object} obj The root object of the transform.
+              @param {String} to The path to the 'to' side of the binding.
+                Must be relative to obj.
+              @param {String} from The path to the 'from' side of the binding.
+                Must be relative to obj or a global path.
+              @return {Ember.Binding} binding instance
+            */
+        function oneWay(obj, to, from) {
+            return new Binding(to, from).oneWay().connect(obj);
+        }
+
+        __exports__.oneWay = oneWay;
+        __exports__.Binding = Binding;
+        __exports__.isGlobalPath = isGlobalPath;
+    });
+    define(&quot;ember-metal/chains&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/watch_key&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // warn, assert, etc;
+        var get = __dependency2__.get;
+        var normalizeTuple = __dependency2__.normalizeTuple;
+        var meta = __dependency3__.meta;
+        var META_KEY = __dependency3__.META_KEY;
+        var forEach = __dependency4__.forEach;
+        var watchKey = __dependency5__.watchKey;
+        var unwatchKey = __dependency5__.unwatchKey;
+
+        var metaFor = meta,
+        warn = Ember.warn,
+        FIRST_KEY = /^([^\.]+)/;
+
+        function firstKey(path) {
+            return path.match(FIRST_KEY)[0];
+        }
+
+        var pendingQueue = [];
+
+        // attempts to add the pendingQueue chains again. If some of them end up
+        // back in the queue and reschedule is true, schedules a timeout to try
+        // again.
+        function flushPendingChains() {
+            if (pendingQueue.length === 0) {
+                return;
+            }
+            // nothing to do
+
+            var queue = pendingQueue;
+            pendingQueue = [];
+
+            forEach.call(queue, function(q) {
+                q[0].add(q[1]);
+            });
+
+            warn('Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos', pendingQueue.length === 0);
+        }
+
+        __exports__.flushPendingChains = flushPendingChains;
+        function addChainWatcher(obj, keyName, node) {
+            if (!obj || ('object' !== typeof obj)) {
+                return;
+            }
+            // nothing to do
+
+            var m = metaFor(obj), nodes = m.chainWatchers;
+
+            if (!m.hasOwnProperty('chainWatchers')) {
+                nodes = m.chainWatchers = {};
+            }
+
+            if (!nodes[keyName]) {
+                nodes[keyName] = [];
+            }
+            nodes[keyName].push(node);
+            watchKey(obj, keyName, m);
+        }
+
+        function removeChainWatcher(obj, keyName, node) {
+            if (!obj || 'object' !== typeof obj) {
+                return;
+            }
+            // nothing to do
+
+            var m = obj[META_KEY];
+            if (m &amp;&amp; !m.hasOwnProperty('chainWatchers')) {
+                return;
+            }
+            // nothing to do
+
+            var nodes = m &amp;&amp; m.chainWatchers;
+
+            if (nodes &amp;&amp; nodes[keyName]) {
+                nodes = nodes[keyName];
+                for (var i = 0, l = nodes.length; i &lt; l; i++) {
+                    if (nodes[i] === node) {
+                        nodes.splice(i, 1);
+                        break;
+                    }
+                }
+            }
+            unwatchKey(obj, keyName, m);
+        }
+
+        // A ChainNode watches a single key on an object. If you provide a starting
+        // value for the key then the node won't actually watch it. For a root node
+        // pass null for parent and key and object for value.
+        function ChainNode(parent, key, value) {
+            this._parent = parent;
+            this._key = key;
+
+            // _watching is true when calling get(this._parent, this._key) will
+            // return the value of this node.
+            //
+            // It is false for the root of a chain (because we have no parent)
+            // and for global paths (because the parent node is the object with
+            // the observer on it)
+            this._watching = value === undefined;
+
+            this._value = value;
+            this._paths = {};
+            if (this._watching) {
+                this._object = parent.value();
+                if (this._object) {
+                    addChainWatcher(this._object, this._key, this);
+                }
+            }
+
+            // Special-case: the EachProxy relies on immediate evaluation to
+            // establish its observers.
+            //
+            // TODO: Replace this with an efficient callback that the EachProxy
+            // can implement.
+            if (this._parent &amp;&amp; this._parent._key === '@each') {
+                this.value();
+            }
+        }
+
+        var ChainNodePrototype = ChainNode.prototype;
+
+        function lazyGet(obj, key) {
+            if (!obj) 
+                return undefined;
+
+            var meta = obj[META_KEY];
+            // check if object meant only to be a prototype
+            if (meta &amp;&amp; meta.proto === obj) 
+                return undefined;
+
+            if (key === &quot;@each&quot;) 
+                return get(obj, key);
+
+            // if a CP only return cached value
+            var desc = meta &amp;&amp; meta.descs[key];
+            if (desc &amp;&amp; desc._cacheable) {
+                if (key in meta.cache) {
+                    return meta.cache[key];
+                } else {
+                    return undefined;
+                }
+            }
+
+            return get(obj, key);
+        }
+
+        ChainNodePrototype.value = function() {
+            if (this._value === undefined &amp;&amp; this._watching) {
+                var obj = this._parent.value();
+                this._value = lazyGet(obj, this._key);
+            }
+            return this._value;
+        };
+
+        ChainNodePrototype.destroy = function() {
+            if (this._watching) {
+                var obj = this._object;
+                if (obj) {
+                    removeChainWatcher(obj, this._key, this);
+                }
+                this._watching = false; // so future calls do nothing
+            }
+        };
+
+        // copies a top level object only
+        ChainNodePrototype.copy = function(obj) {
+            var ret = new ChainNode(null, null, obj),
+            paths = this._paths, path;
+            for (path in paths) {
+                if (paths[path] &lt;= 0) {
+                    continue;
+                }
+                // this check will also catch non-number vals.
+                ret.add(path);
+            }
+            return ret;
+        };
+
+        // called on the root node of a chain to setup watchers on the specified
+        // path.
+        ChainNodePrototype.add = function(path) {
+            var obj, tuple, key, src, paths;
+
+            paths = this._paths;
+            paths[path] = (paths[path] || 0) + 1;
+
+            obj = this.value();
+            tuple = normalizeTuple(obj, path);
+
+            // the path was a local path
+            if (tuple[0] &amp;&amp; tuple[0] === obj) {
+                path = tuple[1];
+                key = firstKey(path);
+                path = path.slice(key.length + 1);
+
+                // global path, but object does not exist yet.
+                // put into a queue and try to connect later.
+            } else if (!tuple[0]) {
+                pendingQueue.push([this, path]);
+                tuple.length = 0;
+                return;
+
+                // global path, and object already exists
+            } else {
+                src = tuple[0];
+                key = path.slice(0, 0 - (tuple[1].length + 1));
+                path = tuple[1];
+            }
+
+            tuple.length = 0;
+            this.chain(key, path, src);
+        };
+
+        // called on the root node of a chain to teardown watcher on the specified
+        // path
+        ChainNodePrototype.remove = function(path) {
+            var obj, tuple, key, src, paths;
+
+            paths = this._paths;
+            if (paths[path] &gt; 0) {
+                paths[path]--;
+            }
+
+            obj = this.value();
+            tuple = normalizeTuple(obj, path);
+            if (tuple[0] === obj) {
+                path = tuple[1];
+                key = firstKey(path);
+                path = path.slice(key.length + 1);
+            } else {
+                src = tuple[0];
+                key = path.slice(0, 0 - (tuple[1].length + 1));
+                path = tuple[1];
+            }
+
+            tuple.length = 0;
+            this.unchain(key, path);
+        };
+
+        ChainNodePrototype.count = 0;
+
+        ChainNodePrototype.chain = function(key, path, src) {
+            var chains = this._chains, node;
+            if (!chains) {
+                chains = this._chains = {};
+            }
+
+            node = chains[key];
+            if (!node) {
+                node = chains[key] = new ChainNode(this, key, src);
+            }
+            node.count++; // count chains...
+
+            // chain rest of path if there is one
+            if (path) {
+                key = firstKey(path);
+                path = path.slice(key.length + 1);
+                node.chain(key, path); // NOTE: no src means it will observe changes...
+            }
+        };
+
+        ChainNodePrototype.unchain = function(key, path) {
+            var chains = this._chains, node = chains[key];
+
+            // unchain rest of path first...
+            if (path &amp;&amp; path.length &gt; 1) {
+                key = firstKey(path);
+                path = path.slice(key.length + 1);
+                node.unchain(key, path);
+            }
+
+            // delete node if needed.
+            node.count--;
+            if (node.count &lt;= 0) {
+                delete chains[node._key];
+                node.destroy();
+            }
+
+        };
+
+        ChainNodePrototype.willChange = function(events) {
+            var chains = this._chains;
+            if (chains) {
+                for (var key in chains) {
+                    if (!chains.hasOwnProperty(key)) {
+                        continue;
+                    }
+                    chains[key].willChange(events);
+                }
+            }
+
+            if (this._parent) {
+                this._parent.chainWillChange(this, this._key, 1, events);
+            }
+        };
+
+        ChainNodePrototype.chainWillChange = function(chain, path, depth, events) {
+            if (this._key) {
+                path = this._key + '.' + path;
+            }
+
+            if (this._parent) {
+                this._parent.chainWillChange(this, path, depth + 1, events);
+            } else {
+                if (depth &gt; 1) {
+                    events.push(this.value(), path);
+                }
+                path = 'this.' + path;
+                if (this._paths[path] &gt; 0) {
+                    events.push(this.value(), path);
+                }
+            }
+        };
+
+        ChainNodePrototype.chainDidChange = function(chain, path, depth, events) {
+            if (this._key) {
+                path = this._key + '.' + path;
+            }
+            if (this._parent) {
+                this._parent.chainDidChange(this, path, depth + 1, events);
+            } else {
+                if (depth &gt; 1) {
+                    events.push(this.value(), path);
+                }
+                path = 'this.' + path;
+                if (this._paths[path] &gt; 0) {
+                    events.push(this.value(), path);
+                }
+            }
+        };
+
+        ChainNodePrototype.didChange = function(events) {
+            // invalidate my own value first.
+            if (this._watching) {
+                var obj = this._parent.value();
+                if (obj !== this._object) {
+                    removeChainWatcher(this._object, this._key, this);
+                    this._object = obj;
+                    addChainWatcher(obj, this._key, this);
+                }
+                this._value = undefined;
+
+                // Special-case: the EachProxy relies on immediate evaluation to
+                // establish its observers.
+                if (this._parent &amp;&amp; this._parent._key === '@each')
+                    this.value();
+            }
+
+            // then notify chains...
+            var chains = this._chains;
+            if (chains) {
+                for (var key in chains) {
+                    if (!chains.hasOwnProperty(key)) {
+                        continue;
+                    }
+                    chains[key].didChange(events);
+                }
+            }
+
+            // if no events are passed in then we only care about the above wiring update
+            if (events === null) {
+                return;
+            }
+
+            // and finally tell parent about my path changing...
+            if (this._parent) {
+                this._parent.chainDidChange(this, this._key, 1, events);
+            }
+        };
+
+        function finishChains(obj) {
+            // We only create meta if we really have to
+            var m = obj[META_KEY], chains = m &amp;&amp; m.chains;
+            if (chains) {
+                if (chains.value() !== obj) {
+                    metaFor(obj).chains = chains = chains.copy(obj);
+                } else {
+                    chains.didChange(null);
+                }
+            }
+        }
+
+        __exports__.finishChains = finishChains;
+        __exports__.removeChainWatcher = removeChainWatcher;
+        __exports__.ChainNode = ChainNode;
+    });
+    define(&quot;ember-metal/computed&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/expand_properties&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/dependent_keys&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var meta = __dependency4__.meta;
+        var META_KEY = __dependency4__.META_KEY;
+        var inspect = __dependency4__.inspect;
+        var expandProperties = __dependency5__[&quot;default&quot;];
+        var EmberError = __dependency6__[&quot;default&quot;];
+        var Descriptor = __dependency7__.Descriptor;
+        var defineProperty = __dependency7__.defineProperty;
+        var propertyWillChange = __dependency8__.propertyWillChange;
+        var propertyDidChange = __dependency8__.propertyDidChange;
+        var addDependentKeys = __dependency9__.addDependentKeys;
+        var removeDependentKeys = __dependency9__.removeDependentKeys;
+
+        /**
+            @module ember-metal
+            */
+
+        Ember.warn(&quot;The CP_DEFAULT_CACHEABLE flag has been removed and computed properties are always cached by default. Use `volatile` if you don't want caching.&quot;, Ember.ENV.CP_DEFAULT_CACHEABLE !== false);
+
+
+        var metaFor = meta,
+        a_slice = [].slice;
+
+        function UNDEFINED() {}
+
+        // ..........................................................
+        // COMPUTED PROPERTY
+        //
+
+        /**
+              A computed property transforms an objects function into a property.
+
+              By default the function backing the computed property will only be called
+              once and the result will be cached. You can specify various properties
+              that your computed property is dependent on. This will force the cached
+              result to be recomputed if the dependencies are modified.
+
+              In the following example we declare a computed property (by calling
+              `.property()` on the fullName function) and setup the properties
+              dependencies (depending on firstName and lastName). The fullName function
+              will be called once (regardless of how many times it is accessed) as long
+              as it's dependencies have not been changed. Once firstName or lastName are updated
+              any future calls (or anything bound) to fullName will incorporate the new
+              values.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                // these will be supplied by `create`
+                firstName: null,
+                lastName: null,
+
+                fullName: function() {
+                  var firstName = this.get('firstName');
+                  var lastName = this.get('lastName');
+
+                 return firstName + ' ' + lastName;
+                }.property('firstName', 'lastName')
+              });
+
+              var tom = Person.create({
+                firstName: 'Tom',
+                lastName: 'Dale'
+              });
+
+              tom.get('fullName') // 'Tom Dale'
+              ```
+
+              You can also define what Ember should do when setting a computed property.
+              If you try to set a computed property, it will be invoked with the key and
+              value you want to set it to. You can also accept the previous value as the
+              third parameter.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                // these will be supplied by `create`
+                firstName: null,
+                lastName: null,
+
+                fullName: function(key, value, oldValue) {
+                  // getter
+                  if (arguments.length === 1) {
+                    var firstName = this.get('firstName');
+                    var lastName = this.get('lastName');
+
+                    return firstName + ' ' + lastName;
+
+                  // setter
+                  } else {
+                    var name = value.split(' ');
+
+                    this.set('firstName', name[0]);
+                    this.set('lastName', name[1]);
+
+                    return value;
+                  }
+                }.property('firstName', 'lastName')
+              });
+
+              var person = Person.create();
+
+              person.set('fullName', 'Peter Wagenet');
+              person.get('firstName'); // 'Peter'
+              person.get('lastName');  // 'Wagenet'
+              ```
+
+              @class ComputedProperty
+              @namespace Ember
+              @extends Ember.Descriptor
+              @constructor
+            */
+        function ComputedProperty(func, opts) {
+            func.__ember_arity__ = func.length;
+            this.func = func;
+
+            this._cacheable = (opts &amp;&amp; opts.cacheable !== undefined) ? opts.cacheable : true;
+            this._dependentKeys = opts &amp;&amp; opts.dependentKeys;
+            this._readOnly = opts &amp;&amp; (opts.readOnly !== undefined || !!opts.readOnly) || false;
+        }
+
+        ComputedProperty.prototype = new Descriptor();
+
+        var ComputedPropertyPrototype = ComputedProperty.prototype;
+        ComputedPropertyPrototype._dependentKeys = undefined;
+        ComputedPropertyPrototype._suspended = undefined;
+        ComputedPropertyPrototype._meta = undefined;
+
+        /**
+              Properties are cacheable by default. Computed property will automatically
+              cache the return value of your function until one of the dependent keys changes.
+
+              Call `volatile()` to set it into non-cached mode. When in this mode
+              the computed property will not automatically cache the return value.
+
+              However, if a property is properly observable, there is no reason to disable
+              caching.
+
+              @method cacheable
+              @param {Boolean} aFlag optional set to `false` to disable caching
+              @return {Ember.ComputedProperty} this
+              @chainable
+            */
+        ComputedPropertyPrototype.cacheable = function(aFlag) {
+            this._cacheable = aFlag !== false;
+            return this;
+        };
+
+        /**
+              Call on a computed property to set it into non-cached mode. When in this
+              mode the computed property will not automatically cache the return value.
+
+              ```javascript
+              var outsideService = Ember.Object.extend({
+                value: function() {
+                  return OutsideService.getValue();
+                }.property().volatile()
+              }).create();
+              ```
+
+              @method volatile
+              @return {Ember.ComputedProperty} this
+              @chainable
+            */
+        ComputedPropertyPrototype[&quot;volatile&quot;] = function() {
+            return this.cacheable(false);
+        };
+
+        /**
+              Call on a computed property to set it into read-only mode. When in this
+              mode the computed property will throw an error when set.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                guid: function() {
+                  return 'guid-guid-guid';
+                }.property().readOnly()
+              });
+
+              var person = Person.create();
+
+              person.set('guid', 'new-guid'); // will throw an exception
+              ```
+
+              @method readOnly
+              @return {Ember.ComputedProperty} this
+              @chainable
+            */
+        ComputedPropertyPrototype.readOnly = function(readOnly) {
+            this._readOnly = readOnly === undefined || !!readOnly;
+            return this;
+        };
+
+        /**
+              Sets the dependent keys on this computed property. Pass any number of
+              arguments containing key paths that this computed property depends on.
+
+              ```javascript
+              var President = Ember.Object.extend({
+                fullName: computed(function() {
+                  return this.get('firstName') + ' ' + this.get('lastName');
+
+                  // Tell Ember that this computed property depends on firstName
+                  // and lastName
+                }).property('firstName', 'lastName')
+              });
+
+              var president = President.create({
+                firstName: 'Barack',
+                lastName: 'Obama'
+              });
+
+              president.get('fullName'); // 'Barack Obama'
+              ```
+
+              @method property
+              @param {String} path* zero or more property paths
+              @return {Ember.ComputedProperty} this
+              @chainable
+            */
+        ComputedPropertyPrototype.property = function() {
+            var args;
+
+            var addArg = function (property) {
+                args.push(property);
+            };
+
+            args = [];
+            for (var i = 0, l = arguments.length; i &lt; l; i++) {
+                expandProperties(arguments[i], addArg);
+            }
+
+            this._dependentKeys = args;
+            return this;
+        };
+
+        /**
+              In some cases, you may want to annotate computed properties with additional
+              metadata about how they function or what values they operate on. For example,
+              computed property functions may close over variables that are then no longer
+              available for introspection.
+
+              You can pass a hash of these values to a computed property like this:
+
+              ```
+              person: function() {
+                var personId = this.get('personId');
+                return App.Person.create({ id: personId });
+              }.property().meta({ type: App.Person })
+              ```
+
+              The hash that you pass to the `meta()` function will be saved on the
+              computed property descriptor under the `_meta` key. Ember runtime
+              exposes a public API for retrieving these values from classes,
+              via the `metaForProperty()` function.
+
+              @method meta
+              @param {Hash} meta
+              @chainable
+            */
+
+        ComputedPropertyPrototype.meta = function(meta) {
+            if (arguments.length === 0) {
+                return this._meta || {};
+            } else {
+                this._meta = meta;
+                return this;
+            }
+        };
+
+        /* impl descriptor API */
+        ComputedPropertyPrototype.didChange = function(obj, keyName) {
+            // _suspended is set via a CP.set to ensure we don't clear
+            // the cached value set by the setter
+            if (this._cacheable &amp;&amp; this._suspended !== obj) {
+                var meta = metaFor(obj);
+                if (meta.cache[keyName] !== undefined) {
+                    meta.cache[keyName] = undefined;
+                    removeDependentKeys(this, obj, keyName, meta);
+                }
+            }
+        };
+
+        function finishChains(chainNodes)
+        {
+            for (var i = 0, l = chainNodes.length; i &lt; l; i++) {
+                chainNodes[i].didChange(null);
+            }
+        }
+
+        /**
+              Access the value of the function backing the computed property.
+              If this property has already been cached, return the cached result.
+              Otherwise, call the function passing the property name as an argument.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                fullName: function(keyName) {
+                  // the keyName parameter is 'fullName' in this case.
+                  return this.get('firstName') + ' ' + this.get('lastName');
+                }.property('firstName', 'lastName')
+              });
+
+
+              var tom = Person.create({
+                firstName: 'Tom',
+                lastName: 'Dale'
+              });
+
+              tom.get('fullName') // 'Tom Dale'
+              ```
+
+              @method get
+              @param {String} keyName The key being accessed.
+              @return {Object} The return value of the function backing the CP.
+            */
+        ComputedPropertyPrototype.get = function(obj, keyName) {
+            var ret, cache, meta, chainNodes;
+            if (this._cacheable) {
+                meta = metaFor(obj);
+                cache = meta.cache;
+
+                var result = cache[keyName];
+
+                if (result === UNDEFINED) {
+                    return undefined;
+                } else if (result !== undefined) {
+                    return result;
+                }
+
+                ret = this.func.call(obj, keyName);
+                if (ret === undefined) {
+                    cache[keyName] = UNDEFINED;
+                } else {
+                    cache[keyName] = ret;
+                }
+
+                chainNodes = meta.chainWatchers &amp;&amp; meta.chainWatchers[keyName];
+                if (chainNodes) {
+                    finishChains(chainNodes);
+                }
+                addDependentKeys(this, obj, keyName, meta);
+            } else {
+                ret = this.func.call(obj, keyName);
+            }
+            return ret;
+        };
+
+        /**
+              Set the value of a computed property. If the function that backs your
+              computed property does not accept arguments then the default action for
+              setting would be to define the property on the current object, and set
+              the value of the property to the value being set.
+
+              Generally speaking if you intend for your computed property to be set
+              your backing function should accept either two or three arguments.
+
+              @method set
+              @param {String} keyName The key being accessed.
+              @param {Object} newValue The new value being assigned.
+              @param {String} oldValue The old value being replaced.
+              @return {Object} The return value of the function backing the CP.
+            */
+        ComputedPropertyPrototype.set = function(obj, keyName, value) {
+            var cacheable = this._cacheable,
+            func = this.func,
+            meta = metaFor(obj, cacheable),
+            oldSuspended = this._suspended,
+            hadCachedValue = false,
+            cache = meta.cache,
+            funcArgLength, cachedValue, ret;
+
+            if (this._readOnly) {
+                throw new EmberError('Cannot set read-only property &quot;' + keyName + '&quot; on object: ' + inspect(obj));
+            }
+
+            this._suspended = obj;
+
+            try {
+
+                if (cacheable &amp;&amp; cache[keyName] !== undefined) {
+                    if (cache[keyName] !== UNDEFINED) {
+                        cachedValue = cache[keyName];
+                    }
+
+                    hadCachedValue = true;
+                }
+
+                // Check if the CP has been wrapped. If it has, use the
+                // length from the wrapped function.
+
+                funcArgLength = func.wrappedFunction ? func.wrappedFunction.__ember_arity__ : func.__ember_arity__;
+
+                // For backwards-compatibility with computed properties
+                // that check for arguments.length === 2 to determine if
+                // they are being get or set, only pass the old cached
+                // value if the computed property opts into a third
+                // argument.
+                if (funcArgLength === 3) {
+                    ret = func.call(obj, keyName, value, cachedValue);
+                } else if (funcArgLength === 2) {
+                    ret = func.call(obj, keyName, value);
+                } else {
+                    defineProperty(obj, keyName, null, cachedValue);
+                    set(obj, keyName, value);
+                    return;
+                }
+
+                if (hadCachedValue &amp;&amp; cachedValue === ret) {
+                    return;
+                }
+
+                var watched = meta.watching[keyName];
+                if (watched) {
+                    propertyWillChange(obj, keyName);
+                }
+
+                if (hadCachedValue) {
+                    cache[keyName] = undefined;
+                }
+
+                if (cacheable) {
+                    if (!hadCachedValue) {
+                        addDependentKeys(this, obj, keyName, meta);
+                    }
+                    if (ret === undefined) {
+                        cache[keyName] = UNDEFINED;
+                    } else {
+                        cache[keyName] = ret;
+                    }
+                }
+
+                if (watched) {
+                    propertyDidChange(obj, keyName);
+                }
+            } finally {
+                this._suspended = oldSuspended;
+            }
+            return ret;
+        };
+
+        /* called before property is overridden */
+        ComputedPropertyPrototype.teardown = function(obj, keyName) {
+            var meta = metaFor(obj);
+
+            if (keyName in meta.cache) {
+                removeDependentKeys(this, obj, keyName, meta);
+            }
+
+            if (this._cacheable) {
+                delete meta.cache[keyName];
+            }
+
+            return null; // no value to restore
+        };
+
+
+        /**
+              This helper returns a new property descriptor that wraps the passed
+              computed property function. You can use this helper to define properties
+              with mixins or via `Ember.defineProperty()`.
+
+              The function you pass will be used to both get and set property values.
+              The function should accept two parameters, key and value. If value is not
+              undefined you should set the value first. In either case return the
+              current value of the property.
+
+              @method computed
+              @for Ember
+              @param {Function} func The computed property function.
+              @return {Ember.ComputedProperty} property descriptor instance
+            */
+        function computed(func) {
+            var args;
+
+            if (arguments.length &gt; 1) {
+                args = a_slice.call(arguments);
+                func = args.pop();
+            }
+
+            if (typeof func !== &quot;function&quot;) {
+                throw new EmberError(&quot;Computed Property declared without a property function&quot;);
+            }
+
+            var cp = new ComputedProperty(func);
+
+            if (args) {
+                cp.property.apply(cp, args);
+            }
+
+            return cp;
+        }
+
+        /**
+              Returns the cached value for a property, if one exists.
+              This can be useful for peeking at the value of a computed
+              property that is generated lazily, without accidentally causing
+              it to be created.
+
+              @method cacheFor
+              @for Ember
+              @param {Object} obj the object whose property you want to check
+              @param {String} key the name of the property whose cached value you want
+                to return
+              @return {Object} the cached value
+            */
+        function cacheFor(obj, key) {
+            var meta = obj[META_KEY],
+            cache = meta &amp;&amp; meta.cache,
+            ret = cache &amp;&amp; cache[key];
+
+            if (ret === UNDEFINED) {
+                return undefined;
+            }
+            return ret;
+        }
+
+        cacheFor.set = function(cache, key, value) {
+            if (value === undefined) {
+                cache[key] = UNDEFINED;
+            } else {
+                cache[key] = value;
+            }
+        };
+
+        cacheFor.get = function(cache, key) {
+            var ret = cache[key];
+            if (ret === UNDEFINED) {
+                return undefined;
+            }
+            return ret;
+        };
+
+        cacheFor.remove = function(cache, key) {
+            cache[key] = undefined;
+        };
+
+        __exports__.ComputedProperty = ComputedProperty;
+        __exports__.computed = computed;
+        __exports__.cacheFor = cacheFor;
+    });
+    define(&quot;ember-metal/computed_macros&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/is_empty&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/alias&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var computed = __dependency4__.computed;
+        var isEmpty = __dependency5__[&quot;default&quot;];
+        var isNone = __dependency6__.isNone;
+        var alias = __dependency7__.alias;
+
+        /**
+            @module ember-metal
+            */
+
+        var a_slice = [].slice;
+
+        function getProperties(self, propertyNames) {
+            var ret = {};
+            for (var i = 0; i &lt; propertyNames.length; i++) {
+                ret[propertyNames[i]] = get(self, propertyNames[i]);
+            }
+            return ret;
+        }
+
+        function registerComputed(name, macro) {
+            computed[name] = function(dependentKey) {
+                var args = a_slice.call(arguments);
+                return computed(dependentKey, function() {
+                    return macro.apply(this, args);
+                });
+            };
+        }
+
+        function registerComputedWithProperties(name, macro) {
+            computed[name] = function() {
+                var properties = a_slice.call(arguments);
+
+                var computedFunc = computed(function() {
+                    return macro.apply(this, [getProperties(this, properties)]);
+                });
+
+                return computedFunc.property.apply(computedFunc, properties);
+            };
+        }
+
+        /**
+              A computed property that returns true if the value of the dependent
+              property is null, an empty string, empty array, or empty function.
+
+              Example
+
+              ```javascript
+              var ToDoList = Ember.Object.extend({
+                done: Ember.computed.empty('todos')
+              });
+
+              var todoList = ToDoList.create({
+                todos: ['Unit Test', 'Documentation', 'Release']
+              });
+
+              todoList.get('done'); // false
+              todoList.get('todos').clear();
+              todoList.get('done'); // true
+              ```
+
+              @since 1.6.0
+              @method computed.empty
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which negate
+              the original value for property
+            */
+        computed.empty = function (dependentKey) {
+            return computed(dependentKey + '.length', function () {
+                return isEmpty(get(this, dependentKey));
+            });
+        };
+
+        /**
+              A computed property that returns true if the value of the dependent
+              property is NOT null, an empty string, empty array, or empty function.
+
+              Note: When using `computed.notEmpty` to watch an array make sure to
+              use the `array.[]` syntax so the computed can subscribe to transitions
+              from empty to non-empty states.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                hasStuff: Ember.computed.notEmpty('backpack.[]')
+              });
+
+              var hamster = Hamster.create({ backpack: ['Food', 'Sleeping Bag', 'Tent'] });
+
+              hamster.get('hasStuff');         // true
+              hamster.get('backpack').clear(); // []
+              hamster.get('hasStuff');         // false
+              ```
+
+              @method computed.notEmpty
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which returns true if
+              original value for property is not empty.
+            */
+        registerComputed('notEmpty', function(dependentKey) {
+            return !isEmpty(get(this, dependentKey));
+        });
+
+        /**
+              A computed property that returns true if the value of the dependent
+              property is null or undefined. This avoids errors from JSLint complaining
+              about use of ==, which can be technically confusing.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                isHungry: Ember.computed.none('food')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('isHungry'); // true
+              hamster.set('food', 'Banana');
+              hamster.get('isHungry'); // false
+              hamster.set('food', null);
+              hamster.get('isHungry'); // true
+              ```
+
+              @method computed.none
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which
+              returns true if original value for property is null or undefined.
+            */
+        registerComputed('none', function(dependentKey) {
+            return isNone(get(this, dependentKey));
+        });
+
+        /**
+              A computed property that returns the inverse boolean value
+              of the original value for the dependent property.
+
+              Example
+
+              ```javascript
+              var User = Ember.Object.extend({
+                isAnonymous: Ember.computed.not('loggedIn')
+              });
+
+              var user = User.create({loggedIn: false});
+
+              user.get('isAnonymous'); // true
+              user.set('loggedIn', true);
+              user.get('isAnonymous'); // false
+              ```
+
+              @method computed.not
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which returns
+              inverse of the original value for property
+            */
+        registerComputed('not', function(dependentKey) {
+            return !get(this, dependentKey);
+        });
+
+        /**
+              A computed property that converts the provided dependent property
+              into a boolean value.
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                hasBananas: Ember.computed.bool('numBananas')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('hasBananas'); // false
+              hamster.set('numBananas', 0);
+              hamster.get('hasBananas'); // false
+              hamster.set('numBananas', 1);
+              hamster.get('hasBananas'); // true
+              hamster.set('numBananas', null);
+              hamster.get('hasBananas'); // false
+              ```
+
+              @method computed.bool
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which converts
+              to boolean the original value for property
+            */
+        registerComputed('bool', function(dependentKey) {
+            return !!get(this, dependentKey);
+        });
+
+        /**
+              A computed property which matches the original value for the
+              dependent property against a given RegExp, returning `true`
+              if they values matches the RegExp and `false` if it does not.
+
+              Example
+
+              ```javascript
+              var User = Ember.Object.extend({
+                hasValidEmail: Ember.computed.match('email', /^.+@.+\..+$/)
+              });
+
+              var user = User.create({loggedIn: false});
+
+              user.get('hasValidEmail'); // false
+              user.set('email', '');
+              user.get('hasValidEmail'); // false
+              user.set('email', 'ember_hamster@example.com');
+              user.get('hasValidEmail'); // true
+              ```
+
+              @method computed.match
+              @for Ember
+              @param {String} dependentKey
+              @param {RegExp} regexp
+              @return {Ember.ComputedProperty} computed property which match
+              the original value for property against a given RegExp
+            */
+        registerComputed('match', function(dependentKey, regexp) {
+            var value = get(this, dependentKey);
+            return typeof value === 'string' ? regexp.test(value) : false;
+        });
+
+        /**
+              A computed property that returns true if the provided dependent property
+              is equal to the given value.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                napTime: Ember.computed.equal('state', 'sleepy')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('napTime'); // false
+              hamster.set('state', 'sleepy');
+              hamster.get('napTime'); // true
+              hamster.set('state', 'hungry');
+              hamster.get('napTime'); // false
+              ```
+
+              @method computed.equal
+              @for Ember
+              @param {String} dependentKey
+              @param {String|Number|Object} value
+              @return {Ember.ComputedProperty} computed property which returns true if
+              the original value for property is equal to the given value.
+            */
+        registerComputed('equal', function(dependentKey, value) {
+            return get(this, dependentKey) === value;
+        });
+
+        /**
+              A computed property that returns true if the provied dependent property
+              is greater than the provided value.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                hasTooManyBananas: Ember.computed.gt('numBananas', 10)
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('hasTooManyBananas'); // false
+              hamster.set('numBananas', 3);
+              hamster.get('hasTooManyBananas'); // false
+              hamster.set('numBananas', 11);
+              hamster.get('hasTooManyBananas'); // true
+              ```
+
+              @method computed.gt
+              @for Ember
+              @param {String} dependentKey
+              @param {Number} value
+              @return {Ember.ComputedProperty} computed property which returns true if
+              the original value for property is greater then given value.
+            */
+        registerComputed('gt', function(dependentKey, value) {
+            return get(this, dependentKey) &gt; value;
+        });
+
+        /**
+              A computed property that returns true if the provided dependent property
+              is greater than or equal to the provided value.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                hasTooManyBananas: Ember.computed.gte('numBananas', 10)
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('hasTooManyBananas'); // false
+              hamster.set('numBananas', 3);
+              hamster.get('hasTooManyBananas'); // false
+              hamster.set('numBananas', 10);
+              hamster.get('hasTooManyBananas'); // true
+              ```
+
+              @method computed.gte
+              @for Ember
+              @param {String} dependentKey
+              @param {Number} value
+              @return {Ember.ComputedProperty} computed property which returns true if
+              the original value for property is greater or equal then given value.
+            */
+        registerComputed('gte', function(dependentKey, value) {
+            return get(this, dependentKey) &gt;= value;
+        });
+
+        /**
+              A computed property that returns true if the provided dependent property
+              is less than the provided value.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                needsMoreBananas: Ember.computed.lt('numBananas', 3)
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('needsMoreBananas'); // true
+              hamster.set('numBananas', 3);
+              hamster.get('needsMoreBananas'); // false
+              hamster.set('numBananas', 2);
+              hamster.get('needsMoreBananas'); // true
+              ```
+
+              @method computed.lt
+              @for Ember
+              @param {String} dependentKey
+              @param {Number} value
+              @return {Ember.ComputedProperty} computed property which returns true if
+              the original value for property is less then given value.
+            */
+        registerComputed('lt', function(dependentKey, value) {
+            return get(this, dependentKey) &lt; value;
+        });
+
+        /**
+              A computed property that returns true if the provided dependent property
+              is less than or equal to the provided value.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                needsMoreBananas: Ember.computed.lte('numBananas', 3)
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('needsMoreBananas'); // true
+              hamster.set('numBananas', 5);
+              hamster.get('needsMoreBananas'); // false
+              hamster.set('numBananas', 3);
+              hamster.get('needsMoreBananas'); // true
+              ```
+
+              @method computed.lte
+              @for Ember
+              @param {String} dependentKey
+              @param {Number} value
+              @return {Ember.ComputedProperty} computed property which returns true if
+              the original value for property is less or equal then given value.
+            */
+        registerComputed('lte', function(dependentKey, value) {
+            return get(this, dependentKey) &lt;= value;
+        });
+
+        /**
+              A computed property that performs a logical `and` on the
+              original values for the provided dependent properties.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                readyForCamp: Ember.computed.and('hasTent', 'hasBackpack')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('readyForCamp'); // false
+              hamster.set('hasTent', true);
+              hamster.get('readyForCamp'); // false
+              hamster.set('hasBackpack', true);
+              hamster.get('readyForCamp'); // true
+              ```
+
+              @method computed.and
+              @for Ember
+              @param {String} dependentKey*
+              @return {Ember.ComputedProperty} computed property which performs
+              a logical `and` on the values of all the original values for properties.
+            */
+        registerComputedWithProperties('and', function(properties) {
+            for (var key in properties) {
+                if (properties.hasOwnProperty(key) &amp;&amp; !properties[key]) {
+                    return false;
+                }
+            }
+            return true;
+        });
+
+        /**
+              A computed property which performs a logical `or` on the
+              original values for the provided dependent properties.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                readyForRain: Ember.computed.or('hasJacket', 'hasUmbrella')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('readyForRain'); // false
+              hamster.set('hasJacket', true);
+              hamster.get('readyForRain'); // true
+              ```
+
+              @method computed.or
+              @for Ember
+              @param {String} dependentKey*
+              @return {Ember.ComputedProperty} computed property which performs
+              a logical `or` on the values of all the original values for properties.
+            */
+        registerComputedWithProperties('or', function(properties) {
+            for (var key in properties) {
+                if (properties.hasOwnProperty(key) &amp;&amp; properties[key]) {
+                    return true;
+                }
+            }
+            return false;
+        });
+
+        /**
+              A computed property that returns the first truthy value
+              from a list of dependent properties.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                hasClothes: Ember.computed.any('hat', 'shirt')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('hasClothes'); // null
+              hamster.set('shirt', 'Hawaiian Shirt');
+              hamster.get('hasClothes'); // 'Hawaiian Shirt'
+              ```
+
+              @method computed.any
+              @for Ember
+              @param {String} dependentKey*
+              @return {Ember.ComputedProperty} computed property which returns
+              the first truthy value of given list of properties.
+            */
+        registerComputedWithProperties('any', function(properties) {
+            for (var key in properties) {
+                if (properties.hasOwnProperty(key) &amp;&amp; properties[key]) {
+                    return properties[key];
+                }
+            }
+            return null;
+        });
+
+        /**
+              A computed property that returns the array of values
+              for the provided dependent properties.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                clothes: Ember.computed.collect('hat', 'shirt')
+              });
+
+              var hamster = Hamster.create();
+
+              hamster.get('clothes'); // [null, null]
+              hamster.set('hat', 'Camp Hat');
+              hamster.set('shirt', 'Camp Shirt');
+              hamster.get('clothes'); // ['Camp Hat', 'Camp Shirt']
+              ```
+
+              @method computed.collect
+              @for Ember
+              @param {String} dependentKey*
+              @return {Ember.ComputedProperty} computed property which maps
+              values of all passed properties in to an array.
+            */
+        registerComputedWithProperties('collect', function(properties) {
+            var res = [];
+            for (var key in properties) {
+                if (properties.hasOwnProperty(key)) {
+                    if (isNone(properties[key])) {
+                        res.push(null);
+                    } else {
+                        res.push(properties[key]);
+                    }
+                }
+            }
+            return res;
+        });
+
+        /**
+              Creates a new property that is an alias for another property
+              on an object. Calls to `get` or `set` this property behave as
+              though they were called on the original property.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                name: 'Alex Matchneer',
+                nomen: Ember.computed.alias('name')
+              });
+
+              var alex = Person.create();
+
+              alex.get('nomen'); // 'Alex Matchneer'
+              alex.get('name');  // 'Alex Matchneer'
+
+              alex.set('nomen', '@machty');
+              alex.get('name');  // '@machty'
+              ```
+
+              @method computed.alias
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which creates an
+              alias to the original value for property.
+            */
+        computed.alias = alias;
+
+        /**
+              Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
+              data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
+              not mutate the upstream property, rather causes the current property to
+              become the value set. This causes the downstream property to permanently
+              diverge from the upstream property.
+
+              Example
+
+              ```javascript
+              var User = Ember.Object.extend({
+                firstName: null,
+                lastName: null,
+                nickName: Ember.computed.oneWay('firstName')
+              });
+
+              var teddy = User.create({
+                firstName: 'Teddy',
+                lastName:  'Zeenny'
+              });
+
+              teddy.get('nickName');              // 'Teddy'
+              teddy.set('nickName', 'TeddyBear'); // 'TeddyBear'
+              teddy.get('firstName');             // 'Teddy'
+              ```
+
+              @method computed.oneWay
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which creates a
+              one way computed property to the original value for property.
+            */
+        computed.oneWay = function(dependentKey) {
+            return alias(dependentKey).oneWay();
+        };
+
+
+        /**
+                This is a more semantically meaningful alias of `computed.oneWay`,
+                whose name is somewhat ambiguous as to which direction the data flows.
+
+                @method computed.reads
+                @for Ember
+                @param {String} dependentKey
+                @return {Ember.ComputedProperty} computed property which creates a
+                  one way computed property to the original value for property.
+               */
+        computed.reads = computed.oneWay;
+
+
+        /**
+              Where `computed.oneWay` provides oneWay bindings, `computed.readOnly` provides
+              a readOnly one way binding. Very often when using `computed.oneWay` one does
+              not also want changes to propogate back up, as they will replace the value.
+
+              This prevents the reverse flow, and also throws an exception when it occurs.
+
+              Example
+
+              ```javascript
+              var User = Ember.Object.extend({
+                firstName: null,
+                lastName: null,
+                nickName: Ember.computed.readOnly('firstName')
+              });
+
+              var teddy = User.create({
+                firstName: 'Teddy',
+                lastName:  'Zeenny'
+              });
+
+              teddy.get('nickName');              // 'Teddy'
+              teddy.set('nickName', 'TeddyBear'); // throws Exception
+              // throw new Ember.Error('Cannot Set: nickName on: &lt;User:ember27288&gt;' );`
+              teddy.get('firstName');             // 'Teddy'
+              ```
+
+              @method computed.readOnly
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which creates a
+              one way computed property to the original value for property.
+              @since 1.5.0
+            */
+        computed.readOnly = function(dependentKey) {
+            return alias(dependentKey).readOnly();
+        };
+        /**
+              A computed property that acts like a standard getter and setter,
+              but returns the value at the provided `defaultPath` if the
+              property itself has not been set to a value
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                wishList: Ember.computed.defaultTo('favoriteFood')
+              });
+
+              var hamster = Hamster.create({ favoriteFood: 'Banana' });
+
+              hamster.get('wishList');                     // 'Banana'
+              hamster.set('wishList', 'More Unit Tests');
+              hamster.get('wishList');                     // 'More Unit Tests'
+              hamster.get('favoriteFood');                 // 'Banana'
+              ```
+
+              @method computed.defaultTo
+              @for Ember
+              @param {String} defaultPath
+              @return {Ember.ComputedProperty} computed property which acts like
+              a standard getter and setter, but defaults to the value from `defaultPath`.
+            */
+        // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed
+        computed.defaultTo = function(defaultPath) {
+            return computed(function(key, newValue, cachedValue) {
+                if (arguments.length === 1) {
+                    return get(this, defaultPath);
+                }
+                return newValue != null ? newValue : get(this, defaultPath);
+            });
+        };
+
+        /**
+              Creates a new property that is an alias for another property
+              on an object. Calls to `get` or `set` this property behave as
+              though they were called on the original property, but also
+              print a deprecation warning.
+
+              @method computed.deprecatingAlias
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computed property which creates an
+              alias with a deprecation to the original value for property.
+            */
+        computed.deprecatingAlias = function(dependentKey) {
+            return computed(dependentKey, function(key, value) {
+                Ember.deprecate('Usage of `' + key + '` is deprecated, use `' + dependentKey + '` instead.');
+
+                if (arguments.length &gt; 1) {
+                    set(this, dependentKey, value);
+                    return value;
+                } else {
+                    return get(this, dependentKey);
+                }
+            });
+        };
+    });
+    define(&quot;ember-metal/core&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        /*globals Ember:true,Em:true,ENV,EmberENV,MetamorphENV:true */
+
+        /**
+            @module ember
+            @submodule ember-metal
+            */
+
+        /**
+              All Ember methods and functions are defined inside of this namespace. You
+              generally should not add new properties to this namespace as it may be
+              overwritten by future versions of Ember.
+
+              You can also use the shorthand `Em` instead of `Ember`.
+
+              Ember-Runtime is a framework that provides core functions for Ember including
+              cross-platform functions, support for property observing and objects. Its
+              focus is on small size and performance. You can use this in place of or
+              along-side other cross-platform libraries such as jQuery.
+
+              The core Runtime framework is based on the jQuery API with a number of
+              performance optimizations.
+
+              @class Ember
+              @static
+              @version 1.7.0-beta.4+pre.4b6ff143
+            */
+
+        if ('undefined' === typeof Ember) {
+            // Create core object. Make it act like an instance of Ember.Namespace so that
+            // objects assigned to it are given a sane string representation.
+            Ember = {};
+        }
+
+        // Default imports, exports and lookup to the global object;
+        var imports = Ember.imports = Ember.imports || this;
+        var exports = Ember.exports = Ember.exports || this;
+        var lookup = Ember.lookup = Ember.lookup || this;
+
+        // aliases needed to keep minifiers from removing the global context
+        exports.Em = exports.Ember = Ember;
+
+        // Make sure these are set whether Ember was already defined or not
+
+        Ember.isNamespace = true;
+
+        Ember.toString = function() {
+            return &quot;Ember&quot;;
+        };
+
+
+        /**
+              @property VERSION
+              @type String
+              @default '1.7.0-beta.4+pre.4b6ff143'
+              @static
+            */
+        Ember.VERSION = '1.7.0-beta.4+pre.4b6ff143';
+
+        /**
+              Standard environmental variables. You can define these in a global `EmberENV`
+              variable before loading Ember to control various configuration settings.
+
+              For backwards compatibility with earlier versions of Ember the global `ENV`
+              variable will be used if `EmberENV` is not defined.
+
+              @property ENV
+              @type Hash
+            */
+
+        if (Ember.ENV) {
+            // do nothing if Ember.ENV is already setup
+        } else if ('undefined' !== typeof EmberENV) {
+            Ember.ENV = EmberENV;
+        } else if ('undefined' !== typeof ENV) {
+            Ember.ENV = ENV;
+        } else {
+            Ember.ENV = {};
+        }
+
+        Ember.config = Ember.config || {};
+
+        // We disable the RANGE API by default for performance reasons
+        if ('undefined' === typeof Ember.ENV.DISABLE_RANGE_API) {
+            Ember.ENV.DISABLE_RANGE_API = true;
+        }
+
+        if (&quot;undefined&quot; === typeof MetamorphENV) {
+            exports.MetamorphENV = {};
+        }
+
+        MetamorphENV.DISABLE_RANGE_API = Ember.ENV.DISABLE_RANGE_API;
+
+        /**
+              Hash of enabled Canary features. Add to before creating your application.
+
+              You can also define `ENV.FEATURES` if you need to enable features flagged at runtime.
+
+              @class FEATURES
+              @namespace Ember
+              @static
+              @since 1.1.0
+            */
+
+        Ember.FEATURES = Ember.ENV.FEATURES || {};
+
+        /**
+              Test that a feature is enabled. Parsed by Ember's build tools to leave
+              experimental features out of beta/stable builds.
+
+              You can define the following configuration options:
+
+              * `ENV.ENABLE_ALL_FEATURES` - force all features to be enabled.
+              * `ENV.ENABLE_OPTIONAL_FEATURES` - enable any features that have not been explicitly
+                enabled/disabled.
+
+              @method isEnabled
+              @param {String} feature
+              @return {Boolean}
+              @for Ember.FEATURES
+              @since 1.1.0
+            */
+
+        Ember.FEATURES.isEnabled = function(feature) {
+            var featureValue = Ember.FEATURES[feature];
+
+            if (Ember.ENV.ENABLE_ALL_FEATURES) {
+                return true;
+            } else if (featureValue === true || featureValue === false || featureValue === undefined) {
+                return featureValue;
+            } else if (Ember.ENV.ENABLE_OPTIONAL_FEATURES) {
+                return true;
+            } else {
+                return false;
+            }
+        };
+
+        // ..........................................................
+        // BOOTSTRAP
+        //
+
+        /**
+              Determines whether Ember should enhance some built-in object prototypes to
+              provide a more friendly API. If enabled, a few methods will be added to
+              `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced,
+              which is the one that causes most trouble for people.
+
+              In general we recommend leaving this option set to true since it rarely
+              conflicts with other code. If you need to turn it off however, you can
+              define an `ENV.EXTEND_PROTOTYPES` config to disable it.
+
+              @property EXTEND_PROTOTYPES
+              @type Boolean
+              @default true
+              @for Ember
+            */
+        Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;
+
+        if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
+            Ember.EXTEND_PROTOTYPES = true;
+        }
+
+        /**
+              Determines whether Ember logs a full stack trace during deprecation warnings
+
+              @property LOG_STACKTRACE_ON_DEPRECATION
+              @type Boolean
+              @default true
+            */
+        Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false);
+
+        /**
+              Determines whether Ember should add ECMAScript 5 shims to older browsers.
+
+              @property SHIM_ES5
+              @type Boolean
+              @default Ember.EXTEND_PROTOTYPES
+            */
+        Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES;
+
+        /**
+              Determines whether Ember logs info about version of used libraries
+
+              @property LOG_VERSION
+              @type Boolean
+              @default true
+            */
+        Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true;
+
+        /**
+              Empty function. Useful for some operations. Always returns `this`.
+
+              @method K
+              @private
+              @return {Object}
+            */
+        var K = function() {
+            return this;
+        };
+        var K = K;
+        __exports__.K = K;
+        Ember.K = K;
+        //TODO: ES6 GLOBL TODO
+
+        // Stub out the methods defined by the ember-debug package in case it's not loaded
+
+        if ('undefined' === typeof Ember.assert) {
+            Ember.assert = Ember.K;
+        }
+        if ('undefined' === typeof Ember.warn) {
+            Ember.warn = Ember.K;
+        }
+        if ('undefined' === typeof Ember.debug) {
+            Ember.debug = Ember.K;
+        }
+        if ('undefined' === typeof Ember.runInDebug) {
+            Ember.runInDebug = Ember.K;
+        }
+        if ('undefined' === typeof Ember.deprecate) {
+            Ember.deprecate = Ember.K;
+        }
+        if ('undefined' === typeof Ember.deprecateFunc) {
+            Ember.deprecateFunc = function(_, func) {
+                return func;
+            };
+        }
+
+        __exports__[&quot;default&quot;] = Ember;
+    });
+    define(&quot;ember-metal/dependent_keys&quot;,
+    [&quot;ember-metal/platform&quot;, &quot;ember-metal/watching&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var create = __dependency1__.create;
+        var watch = __dependency2__.watch;
+        var unwatch = __dependency2__.unwatch;
+
+        /**
+            @module ember-metal
+            */
+
+        var o_create = create;
+
+        // ..........................................................
+        // DEPENDENT KEYS
+        //
+
+        // data structure:
+        //  meta.deps = {
+        //    'depKey': {
+        //      'keyName': count,
+        //    }
+        //  }
+
+        /*
+              This function returns a map of unique dependencies for a
+              given object and key.
+            */
+        function keysForDep(depsMeta, depKey) {
+            var keys = depsMeta[depKey];
+            if (!keys) {
+                // if there are no dependencies yet for a the given key
+                // create a new empty list of dependencies for the key
+                keys = depsMeta[depKey] = {};
+            } else if (!depsMeta.hasOwnProperty(depKey)) {
+                // otherwise if the dependency list is inherited from
+                // a superclass, clone the hash
+                keys = depsMeta[depKey] = o_create(keys);
+            }
+            return keys;
+        }
+
+        function metaForDeps(meta) {
+            return keysForDep(meta, 'deps');
+        }
+
+        function addDependentKeys(desc, obj, keyName, meta) {
+            // the descriptor has a list of dependent keys, so
+            // add all of its dependent keys.
+            var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
+            if (!depKeys) 
+                return;
+
+            depsMeta = metaForDeps(meta);
+
+            for (idx = 0, len = depKeys.length; idx &lt; len; idx++) {
+                depKey = depKeys[idx];
+                // Lookup keys meta for depKey
+                keys = keysForDep(depsMeta, depKey);
+                // Increment the number of times depKey depends on keyName.
+                keys[keyName] = (keys[keyName] || 0) + 1;
+                // Watch the depKey
+                watch(obj, depKey, meta);
+            }
+        }
+
+        __exports__.addDependentKeys = addDependentKeys;
+        function removeDependentKeys(desc, obj, keyName, meta) {
+            // the descriptor has a list of dependent keys, so
+            // remove all of its dependent keys.
+            var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys;
+            if (!depKeys) 
+                return;
+
+            depsMeta = metaForDeps(meta);
+
+            for (idx = 0, len = depKeys.length; idx &lt; len; idx++) {
+                depKey = depKeys[idx];
+                // Lookup keys meta for depKey
+                keys = keysForDep(depsMeta, depKey);
+                // Decrement the number of times depKey depends on keyName.
+                keys[keyName] = (keys[keyName] || 0) - 1;
+                // Unwatch the depKey
+                unwatch(obj, depKey, meta);
+            }
+        }
+        __exports__.removeDependentKeys = removeDependentKeys;
+    });
+    define(&quot;ember-metal/enumerable_utils&quot;,
+    [&quot;ember-metal/array&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var _filter = __dependency1__.filter;
+        var a_forEach = __dependency1__.forEach;
+        var _indexOf = __dependency1__.indexOf;
+        var _map = __dependency1__.map;
+
+        var splice = Array.prototype.splice;
+
+        /**
+             * Defines some convenience methods for working with Enumerables.
+             * `Ember.EnumerableUtils` uses `Ember.ArrayPolyfills` when necessary.
+             *
+             * @class EnumerableUtils
+             * @namespace Ember
+             * @static
+             * */
+
+        /**
+             * Calls the map function on the passed object with a specified callback. This
+             * uses `Ember.ArrayPolyfill`'s-map method when necessary.
+             *
+             * @method map
+             * @param {Object} obj The object that should be mapped
+             * @param {Function} callback The callback to execute
+             * @param {Object} thisArg Value to use as this when executing *callback*
+             *
+             * @return {Array} An array of mapped values.
+             */
+        function map(obj, callback, thisArg) {
+            return obj.map ? obj.map.call(obj, callback, thisArg) : _map.call(obj, callback, thisArg);
+        }
+
+        __exports__.map = map; /**
+             * Calls the forEach function on the passed object with a specified callback. This
+             * uses `Ember.ArrayPolyfill`'s-forEach method when necessary.
+             *
+             * @method forEach
+             * @param {Object} obj The object to call forEach on
+             * @param {Function} callback The callback to execute
+             * @param {Object} thisArg Value to use as this when executing *callback*
+             *
+             */
+        function forEach(obj, callback, thisArg) {
+            return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : a_forEach.call(obj, callback, thisArg);
+        }
+
+        __exports__.forEach = forEach; /**
+             * Calls the filter function on the passed object with a specified callback. This
+             * uses `Ember.ArrayPolyfill`'s-filter method when necessary.
+             *
+             * @method filter
+             * @param {Object} obj The object to call filter on
+             * @param {Function} callback The callback to execute
+             * @param {Object} thisArg Value to use as this when executing *callback*
+             *
+             * @return {Array} An array containing the filtered values
+             * @since 1.4.0
+             */
+        function filter(obj, callback, thisArg) {
+            return obj.filter ? obj.filter.call(obj, callback, thisArg) : _filter.call(obj, callback, thisArg);
+        }
+
+        __exports__.filter = filter; /**
+             * Calls the indexOf function on the passed object with a specified callback. This
+             * uses `Ember.ArrayPolyfill`'s-indexOf method when necessary.
+             *
+             * @method indexOf
+             * @param {Object} obj The object to call indexOn on
+             * @param {Function} callback The callback to execute
+             * @param {Object} index The index to start searching from
+             *
+             */
+        function indexOf(obj, element, index) {
+            return obj.indexOf ? obj.indexOf.call(obj, element, index) : _indexOf.call(obj, element, index);
+        }
+
+        __exports__.indexOf = indexOf; /**
+             * Returns an array of indexes of the first occurrences of the passed elements
+             * on the passed object.
+             *
+             * ```javascript
+             *  var array = [1, 2, 3, 4, 5];
+             *  Ember.EnumerableUtils.indexesOf(array, [2, 5]); // [1, 4]
+             *
+             *  var fubar = &quot;Fubarr&quot;;
+             *  Ember.EnumerableUtils.indexesOf(fubar, ['b', 'r']); // [2, 4]
+             * ```
+             *
+             * @method indexesOf
+             * @param {Object} obj The object to check for element indexes
+             * @param {Array} elements The elements to search for on *obj*
+             *
+             * @return {Array} An array of indexes.
+             *
+             */
+        function indexesOf(obj, elements) {
+            return elements === undefined ? [] : map(elements, function(item) {
+                return indexOf(obj, item);
+            });
+        }
+
+        __exports__.indexesOf = indexesOf; /**
+             * Adds an object to an array. If the array already includes the object this
+             * method has no effect.
+             *
+             * @method addObject
+             * @param {Array} array The array the passed item should be added to
+             * @param {Object} item The item to add to the passed array
+             *
+             * @return 'undefined'
+             */
+        function addObject(array, item) {
+            var index = indexOf(array, item);
+            if (index === -1) {
+                array.push(item);
+            }
+        }
+
+        __exports__.addObject = addObject; /**
+             * Removes an object from an array. If the array does not contain the passed
+             * object this method has no effect.
+             *
+             * @method removeObject
+             * @param {Array} array The array to remove the item from.
+             * @param {Object} item The item to remove from the passed array.
+             *
+             * @return 'undefined'
+             */
+        function removeObject(array, item) {
+            var index = indexOf(array, item);
+            if (index !== -1) {
+                array.splice(index, 1);
+            }
+        }
+
+        __exports__.removeObject = removeObject;
+        function _replace(array, idx, amt, objects) {
+            var args = [].concat(objects), chunk, ret = [],
+            // https://code.google.com/p/chromium/issues/detail?id=56588
+            size = 60000, start = idx, ends = amt, count;
+
+            while (args.length) {
+                count = ends &gt; size ? size : ends;
+                if (count &lt;= 0) {
+                    count = 0;
+                }
+
+                chunk = args.splice(0, size);
+                chunk = [start, count].concat(chunk);
+
+                start += size;
+                ends -= count;
+
+                ret = ret.concat(splice.apply(array, chunk));
+            }
+            return ret;
+        }
+
+        __exports__._replace = _replace; /**
+             * Replaces objects in an array with the passed objects.
+             *
+             * ```javascript
+             *   var array = [1,2,3];
+             *   Ember.EnumerableUtils.replace(array, 1, 2, [4, 5]); // [1, 4, 5]
+             *
+             *   var array = [1,2,3];
+             *   Ember.EnumerableUtils.replace(array, 1, 1, [4, 5]); // [1, 4, 5, 3]
+             *
+             *   var array = [1,2,3];
+             *   Ember.EnumerableUtils.replace(array, 10, 1, [4, 5]); // [1, 2, 3, 4, 5]
+             * ```
+             *
+             * @method replace
+             * @param {Array} array The array the objects should be inserted into.
+             * @param {Number} idx Starting index in the array to replace. If *idx* &gt;=
+             * length, then append to the end of the array.
+             * @param {Number} amt Number of elements that should be removed from the array,
+             * starting at *idx*
+             * @param {Array} objects An array of zero or more objects that should be
+             * inserted into the array at *idx*
+             *
+             * @return {Array} The modified array.
+             */
+        function replace(array, idx, amt, objects) {
+            if (array.replace) {
+                return array.replace(idx, amt, objects);
+            } else {
+                return _replace(array, idx, amt, objects);
+            }
+        }
+
+        __exports__.replace = replace; /**
+             * Calculates the intersection of two arrays. This method returns a new array
+             * filled with the records that the two passed arrays share with each other.
+             * If there is no intersection, an empty array will be returned.
+             *
+             * ```javascript
+             * var array1 = [1, 2, 3, 4, 5];
+             * var array2 = [1, 3, 5, 6, 7];
+             *
+             * Ember.EnumerableUtils.intersection(array1, array2); // [1, 3, 5]
+             *
+             * var array1 = [1, 2, 3];
+             * var array2 = [4, 5, 6];
+             *
+             * Ember.EnumerableUtils.intersection(array1, array2); // []
+             * ```
+             *
+             * @method intersection
+             * @param {Array} array1 The first array
+             * @param {Array} array2 The second array
+             *
+             * @return {Array} The intersection of the two passed arrays.
+             */
+        function intersection(array1, array2) {
+            var result = [];
+            forEach(array1, function(element) {
+                if (indexOf(array2, element) &gt;= 0) {
+                    result.push(element);
+                }
+            });
+
+            return result;
+        }
+
+        __exports__.intersection = intersection; // TODO: this only exists to maintain the existing api, as we move forward it
+        // should only be part of the &quot;global build&quot; via some shim
+        __exports__[&quot;default&quot;] = {
+            _replace: _replace,
+            addObject: addObject,
+            filter: filter,
+            forEach: forEach,
+            indexOf: indexOf,
+            indexesOf: indexesOf,
+            intersection: intersection,
+            map: map,
+            removeObject: removeObject,
+            replace: replace
+        };
+    });
+    define(&quot;ember-metal/error&quot;,
+    [&quot;ember-metal/platform&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var create = __dependency1__.create;
+
+        var errorProps = [
+        'description',
+        'fileName',
+        'lineNumber',
+        'message',
+        'name',
+        'number',
+        'stack'
+        ];
+
+        /**
+              A subclass of the JavaScript Error object for use in Ember.
+
+              @class Error
+              @namespace Ember
+              @extends Error
+              @constructor
+            */
+        function EmberError() {
+            var tmp = Error.apply(this, arguments);
+
+            // Adds a `stack` property to the given error object that will yield the
+            // stack trace at the time captureStackTrace was called.
+            // When collecting the stack trace all frames above the topmost call
+            // to this function, including that call, will be left out of the
+            // stack trace.
+            // This is useful because we can hide Ember implementation details
+            // that are not very helpful for the user.
+            if (Error.captureStackTrace) {
+                Error.captureStackTrace(this, Ember.Error);
+            }
+            // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
+            for (var idx = 0; idx &lt; errorProps.length; idx++) {
+                this[errorProps[idx]] = tmp[errorProps[idx]];
+            }
+        }
+
+        EmberError.prototype = create(Error.prototype);
+
+        __exports__[&quot;default&quot;] = EmberError;
+    });
+    define(&quot;ember-metal/events&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/platform&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember-metal
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        var meta = __dependency2__.meta;
+        var META_KEY = __dependency2__.META_KEY;
+        var tryFinally = __dependency2__.tryFinally;
+        var apply = __dependency2__.apply;
+        var applyStr = __dependency2__.applyStr;
+        var create = __dependency3__.create;
+
+        var a_slice = [].slice,
+        metaFor = meta,
+        /* listener flags */
+        ONCE = 1, SUSPENDED = 2;
+
+
+        /*
+              The event system uses a series of nested hashes to store listeners on an
+              object. When a listener is registered, or when an event arrives, these
+              hashes are consulted to determine which target and action pair to invoke.
+
+              The hashes are stored in the object's meta hash, and look like this:
+
+                  // Object's meta hash
+                  {
+                    listeners: {       // variable name: `listenerSet`
+                      &quot;foo:changed&quot;: [ // variable name: `actions`
+                        target, method, flags
+                      ]
+                    }
+                  }
+
+            */
+
+        function indexOf(array, target, method) {
+            var index = -1;
+            // hashes are added to the end of the event array
+            // so it makes sense to start searching at the end
+            // of the array and search in reverse
+            for (var i = array.length - 3 ; i &gt;= 0; i -= 3) {
+                if (target === array[i] &amp;&amp; method === array[i + 1]) {
+                    index = i;
+                    break;
+                }
+            }
+            return index;
+        }
+
+        function actionsFor(obj, eventName) {
+            var meta = metaFor(obj, true),
+            actions;
+
+            if (!meta.listeners) {
+                meta.listeners = {};
+            }
+
+            if (!meta.hasOwnProperty('listeners')) {
+                // setup inherited copy of the listeners object
+                meta.listeners = create(meta.listeners);
+            }
+
+            actions = meta.listeners[eventName];
+
+            // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype
+            if (actions &amp;&amp; !meta.listeners.hasOwnProperty(eventName)) {
+                actions = meta.listeners[eventName] = meta.listeners[eventName].slice();
+            } else if (!actions) {
+                actions = meta.listeners[eventName] = [];
+            }
+
+            return actions;
+        }
+
+        function listenersUnion(obj, eventName, otherActions) {
+            var meta = obj[META_KEY],
+            actions = meta &amp;&amp; meta.listeners &amp;&amp; meta.listeners[eventName];
+
+            if (!actions) {
+                return;
+            }
+            for (var i = actions.length - 3; i &gt;= 0; i -= 3) {
+                var target = actions[i],
+                method = actions[i + 1],
+                flags = actions[i + 2],
+                actionIndex = indexOf(otherActions, target, method);
+
+                if (actionIndex === -1) {
+                    otherActions.push(target, method, flags);
+                }
+            }
+        }
+
+        __exports__.listenersUnion = listenersUnion;
+        function listenersDiff(obj, eventName, otherActions) {
+            var meta = obj[META_KEY],
+            actions = meta &amp;&amp; meta.listeners &amp;&amp; meta.listeners[eventName],
+            diffActions = [];
+
+            if (!actions) {
+                return;
+            }
+            for (var i = actions.length - 3; i &gt;= 0; i -= 3) {
+                var target = actions[i],
+                method = actions[i + 1],
+                flags = actions[i + 2],
+                actionIndex = indexOf(otherActions, target, method);
+
+                if (actionIndex !== -1) {
+                    continue;
+                }
+
+                otherActions.push(target, method, flags);
+                diffActions.push(target, method, flags);
+            }
+
+            return diffActions;
+        }
+
+        __exports__.listenersDiff = listenersDiff; /**
+              Add an event listener
+
+              @method addListener
+              @for Ember
+              @param obj
+              @param {String} eventName
+              @param {Object|Function} targetOrMethod A target object or a function
+              @param {Function|String} method A function or the name of a function to be called on `target`
+              @param {Boolean} once A flag whether a function should only be called once
+            */
+        function addListener(obj, eventName, target, method, once) {
+            Ember.assert(&quot;You must pass at least an object and event name to Ember.addListener&quot;, !!obj &amp;&amp; !!eventName);
+
+            if (!method &amp;&amp; 'function' === typeof target) {
+                method = target;
+                target = null;
+            }
+
+            var actions = actionsFor(obj, eventName),
+            actionIndex = indexOf(actions, target, method),
+            flags = 0;
+
+            if (once) 
+                flags |= ONCE;
+
+            if (actionIndex !== -1) {
+                return;
+            }
+
+            actions.push(target, method, flags);
+
+            if ('function' === typeof obj.didAddListener) {
+                obj.didAddListener(eventName, target, method);
+            }
+        }
+
+        __exports__.addListener = addListener; /**
+              Remove an event listener
+
+              Arguments should match those passed to `Ember.addListener`.
+
+              @method removeListener
+              @for Ember
+              @param obj
+              @param {String} eventName
+              @param {Object|Function} targetOrMethod A target object or a function
+              @param {Function|String} method A function or the name of a function to be called on `target`
+            */
+        function removeListener(obj, eventName, target, method) {
+            Ember.assert(&quot;You must pass at least an object and event name to Ember.removeListener&quot;, !!obj &amp;&amp; !!eventName);
+
+            if (!method &amp;&amp; 'function' === typeof target) {
+                method = target;
+                target = null;
+            }
+
+            function _removeListener(target, method) {
+                var actions = actionsFor(obj, eventName),
+                actionIndex = indexOf(actions, target, method);
+
+                // action doesn't exist, give up silently
+                if (actionIndex === -1) {
+                    return;
+                }
+
+                actions.splice(actionIndex, 3);
+
+                if ('function' === typeof obj.didRemoveListener) {
+                    obj.didRemoveListener(eventName, target, method);
+                }
+            }
+
+            if (method) {
+                _removeListener(target, method);
+            } else {
+                var meta = obj[META_KEY],
+                actions = meta &amp;&amp; meta.listeners &amp;&amp; meta.listeners[eventName];
+
+                if (!actions) {
+                    return;
+                }
+                for (var i = actions.length - 3; i &gt;= 0; i -= 3) {
+                    _removeListener(actions[i], actions[i + 1]);
+                }
+            }
+        }
+
+        /**
+              Suspend listener during callback.
+
+              This should only be used by the target of the event listener
+              when it is taking an action that would cause the event, e.g.
+              an object might suspend its property change listener while it is
+              setting that property.
+
+              @method suspendListener
+              @for Ember
+
+              @private
+              @param obj
+              @param {String} eventName
+              @param {Object|Function} targetOrMethod A target object or a function
+              @param {Function|String} method A function or the name of a function to be called on `target`
+              @param {Function} callback
+            */
+        function suspendListener(obj, eventName, target, method, callback) {
+            if (!method &amp;&amp; 'function' === typeof target) {
+                method = target;
+                target = null;
+            }
+
+            var actions = actionsFor(obj, eventName),
+            actionIndex = indexOf(actions, target, method);
+
+            if (actionIndex !== -1) {
+                actions[actionIndex + 2] |= SUSPENDED; // mark the action as suspended
+            }
+
+            function tryable() {
+                return callback.call(target);
+            }
+            function finalizer() {
+                if (actionIndex !== -1) {
+                    actions[actionIndex + 2] &amp;= ~SUSPENDED;
+                }
+            }
+
+            return tryFinally(tryable, finalizer);
+        }
+
+        __exports__.suspendListener = suspendListener; /**
+              Suspends multiple listeners during a callback.
+
+              @method suspendListeners
+              @for Ember
+
+              @private
+              @param obj
+              @param {Array} eventName Array of event names
+              @param {Object|Function} targetOrMethod A target object or a function
+              @param {Function|String} method A function or the name of a function to be called on `target`
+              @param {Function} callback
+            */
+        function suspendListeners(obj, eventNames, target, method, callback) {
+            if (!method &amp;&amp; 'function' === typeof target) {
+                method = target;
+                target = null;
+            }
+
+            var suspendedActions = [],
+            actionsList = [],
+            eventName, actions, i, l;
+
+            for (i = 0, l = eventNames.length; i &lt; l; i++) {
+                eventName = eventNames[i];
+                actions = actionsFor(obj, eventName);
+                var actionIndex = indexOf(actions, target, method);
+
+                if (actionIndex !== -1) {
+                    actions[actionIndex + 2] |= SUSPENDED;
+                    suspendedActions.push(actionIndex);
+                    actionsList.push(actions);
+                }
+            }
+
+            function tryable() {
+                return callback.call(target);
+            }
+
+            function finalizer() {
+                for (var i = 0, l = suspendedActions.length; i &lt; l; i++) {
+                    var actionIndex = suspendedActions[i];
+                    actionsList[i][actionIndex + 2] &amp;= ~SUSPENDED;
+                }
+            }
+
+            return tryFinally(tryable, finalizer);
+        }
+
+        __exports__.suspendListeners = suspendListeners; /**
+              Return a list of currently watched events
+
+              @private
+              @method watchedEvents
+              @for Ember
+              @param obj
+            */
+        function watchedEvents(obj) {
+            var listeners = obj[META_KEY].listeners, ret = [];
+
+            if (listeners) {
+                for (var eventName in listeners) {
+                    if (listeners[eventName]) {
+                        ret.push(eventName);
+                    }
+                }
+            }
+            return ret;
+        }
+
+        __exports__.watchedEvents = watchedEvents; /**
+              Send an event. The execution of suspended listeners
+              is skipped, and once listeners are removed. A listener without
+              a target is executed on the passed object. If an array of actions
+              is not passed, the actions stored on the passed object are invoked.
+
+              @method sendEvent
+              @for Ember
+              @param obj
+              @param {String} eventName
+              @param {Array} params Optional parameters for each listener.
+              @param {Array} actions Optional array of actions (listeners).
+              @return true
+            */
+        function sendEvent(obj, eventName, params, actions) {
+            // first give object a chance to handle it
+            if (obj !== Ember &amp;&amp; 'function' === typeof obj.sendEvent) {
+                obj.sendEvent(eventName, params);
+            }
+
+            if (!actions) {
+                var meta = obj[META_KEY];
+                actions = meta &amp;&amp; meta.listeners &amp;&amp; meta.listeners[eventName];
+            }
+
+            if (!actions) {
+                return;
+            }
+
+            for (var i = actions.length - 3; i &gt;= 0; i -= 3) {
+                // looping in reverse for once listeners
+                var target = actions[i], method = actions[i + 1], flags = actions[i + 2];
+                if (!method) {
+                    continue;
+                }
+                if (flags &amp; SUSPENDED) {
+                    continue;
+                }
+                if (flags &amp; ONCE) {
+                    removeListener(obj, eventName, target, method);
+                }
+                if (!target) {
+                    target = obj;
+                }
+                if ('string' === typeof method) {
+                    if (params) {
+                        applyStr(target, method, params);
+                    } else {
+                        target[method]();
+                    }
+                } else {
+                    if (params) {
+                        apply(target, method, params);
+                    } else {
+                        method.call(target);
+                    }
+                }
+            }
+            return true;
+        }
+
+        __exports__.sendEvent = sendEvent; /**
+              @private
+              @method hasListeners
+              @for Ember
+              @param obj
+              @param {String} eventName
+            */
+        function hasListeners(obj, eventName) {
+            var meta = obj[META_KEY],
+            actions = meta &amp;&amp; meta.listeners &amp;&amp; meta.listeners[eventName];
+
+            return !!(actions &amp;&amp; actions.length);
+        }
+
+        __exports__.hasListeners = hasListeners; /**
+              @private
+              @method listenersFor
+              @for Ember
+              @param obj
+              @param {String} eventName
+            */
+        function listenersFor(obj, eventName) {
+            var ret = [];
+            var meta = obj[META_KEY],
+            actions = meta &amp;&amp; meta.listeners &amp;&amp; meta.listeners[eventName];
+
+            if (!actions) {
+                return ret;
+            }
+
+            for (var i = 0, l = actions.length; i &lt; l; i += 3) {
+                var target = actions[i],
+                method = actions[i + 1];
+                ret.push([target, method]);
+            }
+
+            return ret;
+        }
+
+        __exports__.listenersFor = listenersFor; /**
+              Define a property as a function that should be executed when
+              a specified event or events are triggered.
+
+
+              ``` javascript
+              var Job = Ember.Object.extend({
+                logCompleted: Ember.on('completed', function() {
+                  console.log('Job completed!');
+                })
+              });
+
+              var job = Job.create();
+
+              Ember.sendEvent(job, 'completed'); // Logs 'Job completed!'
+             ```
+
+              @method on
+              @for Ember
+              @param {String} eventNames*
+              @param {Function} func
+              @return func
+            */
+        function on() {
+            var func = a_slice.call(arguments, -1)[0],
+            events = a_slice.call(arguments, 0, -1);
+            func.__ember_listens__ = events;
+            return func;
+        }
+
+        __exports__.on = on;
+        __exports__.removeListener = removeListener;
+    });
+    define(&quot;ember-metal/expand_properties&quot;,
+    [&quot;ember-metal/error&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var EmberError = __dependency1__[&quot;default&quot;];
+        var forEach = __dependency2__.forEach;
+
+        /**
+              @module ember-metal
+              */
+
+        var BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/;
+
+        /**
+              Expands `pattern`, invoking `callback` for each expansion.
+
+              The only pattern supported is brace-expansion, anything else will be passed
+              once to `callback` directly. Brace expansion can only appear at the end of a
+              pattern, for an example see the last call below.
+
+              Example
+              ```js
+              function echo(arg){ console.log(arg); }
+
+              Ember.expandProperties('foo.bar', echo);        //=&gt; 'foo.bar'
+              Ember.expandProperties('{foo,bar}', echo);      //=&gt; 'foo', 'bar'
+              Ember.expandProperties('foo.{bar,baz}', echo);  //=&gt; 'foo.bar', 'foo.baz'
+              Ember.expandProperties('{foo,bar}.baz', echo);  //=&gt; '{foo,bar}.baz'
+              ```
+
+              @method
+              @private
+              @param {string} pattern The property pattern to expand.
+              @param {function} callback The callback to invoke.  It is invoked once per
+              expansion, and is passed the expansion.
+              */
+        __exports__[&quot;default&quot;] = function expandProperties(pattern, callback) {
+            var match, prefix, list;
+
+            if (pattern.indexOf(' ') &gt; -1) {
+                throw new EmberError('Brace expanded properties cannot contain spaces, ' + 
+                'e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`');
+            }
+
+            if (match = BRACE_EXPANSION.exec(pattern)) {
+                prefix = match[1];
+                list = match[2];
+
+                forEach(list.split(','), function (suffix) {
+                    callback(prefix + suffix);
+                });
+            } else {
+                callback(pattern);
+            }
+        }
+    });
+    define(&quot;ember-metal/get_properties&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var typeOf = __dependency2__.typeOf;
+
+        /**
+              To get multiple properties at once, call `Ember.getProperties`
+              with an object followed by a list of strings or an array:
+
+              ```javascript
+              Ember.getProperties(record, 'firstName', 'lastName', 'zipCode');
+              // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
+              ```
+
+              is equivalent to:
+
+              ```javascript
+              Ember.getProperties(record, ['firstName', 'lastName', 'zipCode']);
+              // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
+              ```
+
+              @method getProperties
+              @param obj
+              @param {String...|Array} list of keys to get
+              @return {Hash}
+            */
+        __exports__[&quot;default&quot;] = function getProperties(obj) {
+            var ret = {},
+            propertyNames = arguments,
+            i = 1;
+
+            if (arguments.length === 2 &amp;&amp; typeOf(arguments[1]) === 'array') {
+                i = 0;
+                propertyNames = arguments[1];
+            }
+            for (var len = propertyNames.length; i &lt; len; i++) {
+                ret[propertyNames[i]] = get(obj, propertyNames[i]);
+            }
+            return ret;
+        }
+    });
+    define(&quot;ember-metal/instrumentation&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var tryCatchFinally = __dependency2__.tryCatchFinally;
+
+        /**
+              The purpose of the Ember Instrumentation module is
+              to provide efficient, general-purpose instrumentation
+              for Ember.
+
+              Subscribe to a listener by using `Ember.subscribe`:
+
+              ```javascript
+              Ember.subscribe(&quot;render&quot;, {
+                before: function(name, timestamp, payload) {
+
+                },
+
+                after: function(name, timestamp, payload) {
+
+                }
+              });
+              ```
+
+              If you return a value from the `before` callback, that same
+              value will be passed as a fourth parameter to the `after`
+              callback.
+
+              Instrument a block of code by using `Ember.instrument`:
+
+              ```javascript
+              Ember.instrument(&quot;render.handlebars&quot;, payload, function() {
+                // rendering logic
+              }, binding);
+              ```
+
+              Event names passed to `Ember.instrument` are namespaced
+              by periods, from more general to more specific. Subscribers
+              can listen for events by whatever level of granularity they
+              are interested in.
+
+              In the above example, the event is `render.handlebars`,
+              and the subscriber listened for all events beginning with
+              `render`. It would receive callbacks for events named
+              `render`, `render.handlebars`, `render.container`, or
+              even `render.handlebars.layout`.
+
+              @class Instrumentation
+              @namespace Ember
+              @static
+            */
+        var subscribers = [], cache = {};
+
+        var populateListeners = function(name) {
+            var listeners = [], subscriber;
+
+            for (var i = 0, l = subscribers.length; i &lt; l; i++) {
+                subscriber = subscribers[i];
+                if (subscriber.regex.test(name)) {
+                    listeners.push(subscriber.object);
+                }
+            }
+
+            cache[name] = listeners;
+            return listeners;
+        };
+
+        var time = (function() {
+            var perf = 'undefined' !== typeof window ? window.performance || {}
+            : {};
+            var fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow;
+            // fn.bind will be available in all the browsers that support the advanced window.performance... ;-)
+            return fn ? fn.bind(perf) : function() {
+                return + new Date();
+            };
+        })();
+
+        /**
+              Notifies event's subscribers, calls `before` and `after` hooks.
+
+              @method instrument
+              @namespace Ember.Instrumentation
+
+              @param {String} [name] Namespaced event name.
+              @param {Object} payload
+              @param {Function} callback Function that you're instrumenting.
+              @param {Object} binding Context that instrument function is called with.
+            */
+        function instrument(name, payload, callback, binding) {
+            var listeners = cache[name], timeName, ret;
+
+            // ES6TODO: Docs. What is this?
+            if (Ember.STRUCTURED_PROFILE) {
+                timeName = name + &quot;: &quot; + payload.object;
+                console.time(timeName);
+            }
+
+            if (!listeners) {
+                listeners = populateListeners(name);
+            }
+
+            if (listeners.length === 0) {
+                ret = callback.call(binding);
+                if (Ember.STRUCTURED_PROFILE) {
+                    console.timeEnd(timeName);
+                }
+                return ret;
+            }
+
+            var beforeValues = [], listener, i, l;
+
+            function tryable() {
+                for (i = 0, l = listeners.length; i &lt; l; i++) {
+                    listener = listeners[i];
+                    beforeValues[i] = listener.before(name, time(), payload);
+                }
+
+                return callback.call(binding);
+            }
+
+            function catchable(e) {
+                payload = payload || {};
+                payload.exception = e;
+            }
+
+            function finalizer() {
+                for (i = 0, l = listeners.length; i &lt; l; i++) {
+                    listener = listeners[i];
+                    listener.after(name, time(), payload, beforeValues[i]);
+                }
+
+                if (Ember.STRUCTURED_PROFILE) {
+                    console.timeEnd(timeName);
+                }
+            }
+
+            return tryCatchFinally(tryable, catchable, finalizer);
+        }
+
+        __exports__.instrument = instrument; /**
+              Subscribes to a particular event or instrumented block of code.
+
+              @method subscribe
+              @namespace Ember.Instrumentation
+
+              @param {String} [pattern] Namespaced event name.
+              @param {Object} [object] Before and After hooks.
+
+              @return {Subscriber}
+            */
+        function subscribe(pattern, object) {
+            var paths = pattern.split(&quot;.&quot;), path, regex = [];
+
+            for (var i = 0, l = paths.length; i &lt; l; i++) {
+                path = paths[i];
+                if (path === &quot;*&quot;) {
+                    regex.push(&quot;[^\\.]*&quot;);
+                } else {
+                    regex.push(path);
+                }
+            }
+
+            regex = regex.join(&quot;\\.&quot;);
+            regex = regex + &quot;(\\..*)?&quot;;
+
+            var subscriber = {
+                pattern: pattern,
+                regex: new RegExp(&quot;^&quot; + regex + &quot;$&quot;),
+                object: object
+            };
+
+            subscribers.push(subscriber);
+            cache = {};
+
+            return subscriber;
+        }
+
+        __exports__.subscribe = subscribe; /**
+              Unsubscribes from a particular event or instrumented block of code.
+
+              @method unsubscribe
+              @namespace Ember.Instrumentation
+
+              @param {Object} [subscriber]
+            */
+        function unsubscribe(subscriber) {
+            var index;
+
+            for (var i = 0, l = subscribers.length; i &lt; l; i++) {
+                if (subscribers[i] === subscriber) {
+                    index = i;
+                }
+            }
+
+            subscribers.splice(index, 1);
+            cache = {};
+        }
+
+        __exports__.unsubscribe = unsubscribe; /**
+              Resets `Ember.Instrumentation` by flushing list of subscribers.
+
+              @method reset
+              @namespace Ember.Instrumentation
+            */
+        function reset() {
+            subscribers = [];
+            cache = {};
+        }
+
+        __exports__.reset = reset;
+    });
+    define(&quot;ember-metal/is_blank&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/is_empty&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // deprecateFunc
+        var isEmpty = __dependency2__[&quot;default&quot;];
+
+        /**
+              A value is blank if it is empty or a whitespace string.
+
+              ```javascript
+              Ember.isBlank();                // true
+              Ember.isBlank(null);            // true
+              Ember.isBlank(undefined);       // true
+              Ember.isBlank('');              // true
+              Ember.isBlank([]);              // true
+              Ember.isBlank('\n\t');          // true
+              Ember.isBlank('  ');            // true
+              Ember.isBlank({});              // false
+              Ember.isBlank('\n\t Hello');    // false
+              Ember.isBlank('Hello world');   // false
+              Ember.isBlank([1,2,3]);         // false
+              ```
+
+              @method isBlank
+              @for Ember
+              @param {Object} obj Value to test
+              @return {Boolean}
+              @since 1.5.0
+              */
+        __exports__[&quot;default&quot;] = function isBlank(obj) {
+            return isEmpty(obj) || (typeof obj === 'string' &amp;&amp; obj.match(/\S/) === null);
+        }
+    });
+    define(&quot;ember-metal/is_empty&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/is_none&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // deprecateFunc
+        var get = __dependency2__.get;
+        var isNone = __dependency3__[&quot;default&quot;];
+
+        /**
+              Verifies that a value is `null` or an empty string, empty array,
+              or empty function.
+
+              Constrains the rules on `Ember.isNone` by returning false for empty
+              string and empty arrays.
+
+              ```javascript
+              Ember.isEmpty();                // true
+              Ember.isEmpty(null);            // true
+              Ember.isEmpty(undefined);       // true
+              Ember.isEmpty('');              // true
+              Ember.isEmpty([]);              // true
+              Ember.isEmpty('Adam Hawkins');  // false
+              Ember.isEmpty([0,1,2]);         // false
+              ```
+
+              @method isEmpty
+              @for Ember
+              @param {Object} obj Value to test
+              @return {Boolean}
+            */
+        function isEmpty(obj) {
+            return isNone(obj) || (obj.length === 0 &amp;&amp; typeof obj !== 'function') || (typeof obj === 'object' &amp;&amp; get(obj, 'length') === 0);
+        }
+
+        var empty = Ember.deprecateFunc(&quot;Ember.empty is deprecated. Please use Ember.isEmpty instead.&quot;, isEmpty);
+        __exports__.empty = empty;
+        __exports__[&quot;default&quot;] = isEmpty;
+        __exports__.isEmpty = isEmpty;
+        __exports__.empty = empty;
+    });
+    define(&quot;ember-metal/is_none&quot;,
+    [&quot;ember-metal/core&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // deprecateFunc
+
+        /**
+              Returns true if the passed value is null or undefined. This avoids errors
+              from JSLint complaining about use of ==, which can be technically
+              confusing.
+
+              ```javascript
+              Ember.isNone();              // true
+              Ember.isNone(null);          // true
+              Ember.isNone(undefined);     // true
+              Ember.isNone('');            // false
+              Ember.isNone([]);            // false
+              Ember.isNone(function() {});  // false
+              ```
+
+              @method isNone
+              @for Ember
+              @param {Object} obj Value to test
+              @return {Boolean}
+            */
+        function isNone(obj) {
+            return obj === null || obj === undefined;
+        }
+
+        var none = Ember.deprecateFunc(&quot;Ember.none is deprecated. Please use Ember.isNone instead.&quot;, isNone);
+        __exports__.none = none;
+        __exports__[&quot;default&quot;] = isNone;
+        __exports__.isNone = isNone;
+    });
+    define(&quot;ember-metal/libraries&quot;,
+    [&quot;ember-metal/enumerable_utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        // Provides a way to register library versions with ember.
+        var forEach = __dependency1__.forEach;
+        var indexOf = __dependency1__.indexOf;
+
+        var libraries = function() {
+            var _libraries = [];
+            var coreLibIndex = 0;
+
+            var getLibrary = function(name) {
+                for (var i = 0; i &lt; _libraries.length; i++) {
+                    if (_libraries[i].name === name) {
+                        return _libraries[i];
+                    }
+                }
+            };
+
+            _libraries.register = function(name, version) {
+                if (!getLibrary(name)) {
+                    _libraries.push({
+                        name: name,
+                        version: version
+                    });
+                }
+            };
+
+            _libraries.registerCoreLibrary = function(name, version) {
+                if (!getLibrary(name)) {
+                    _libraries.splice(coreLibIndex++, 0, {
+                        name: name,
+                        version: version
+                    });
+                }
+            };
+
+            _libraries.deRegister = function(name) {
+                var lib = getLibrary(name);
+                if (lib) 
+                    _libraries.splice(indexOf(_libraries, lib), 1);
+            };
+
+            _libraries.each = function (callback) {
+                forEach(_libraries, function(lib) {
+                    callback(lib.name, lib.version);
+                });
+            };
+
+            return _libraries;
+        }();
+
+        __exports__[&quot;default&quot;] = libraries;
+    });
+    define(&quot;ember-metal/logger&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var EmberError = __dependency2__[&quot;default&quot;];
+
+        function consoleMethod(name) {
+            var consoleObj, logToConsole;
+            if (Ember.imports.console) {
+                consoleObj = Ember.imports.console;
+            } else if (typeof console !== 'undefined') {
+                consoleObj = console;
+            }
+
+            var method = typeof consoleObj === 'object' ? consoleObj[name] : null;
+
+            if (method) {
+                // Older IE doesn't support apply, but Chrome needs it
+                if (typeof method.apply === 'function') {
+                    logToConsole = function() {
+                        method.apply(consoleObj, arguments);
+                    };
+                    logToConsole.displayName = 'console.' + name;
+                    return logToConsole;
+                } else {
+                    return function() {
+                        var message = Array.prototype.join.call(arguments, ', ');
+                        method(message);
+                    };
+                }
+            }
+        }
+
+        function assertPolyfill(test, message) {
+            if (!test) {
+                try {
+                    // attempt to preserve the stack
+                    throw new EmberError(&quot;assertion failed: &quot; + message);
+                } catch (error) {
+                    setTimeout(function() {
+                        throw error;
+                    }, 0);
+                }
+            }
+        }
+
+        /**
+              Inside Ember-Metal, simply uses the methods from `imports.console`.
+              Override this to provide more robust logging functionality.
+
+              @class Logger
+              @namespace Ember
+            */
+        __exports__[&quot;default&quot;] = {
+            /**
+                   Logs the arguments to the console.
+                   You can pass as many arguments as you want and they will be joined together with a space.
+
+                    ```javascript
+                    var foo = 1;
+                    Ember.Logger.log('log value of foo:', foo);
+                    // &quot;log value of foo: 1&quot; will be printed to the console
+                    ```
+
+                   @method log
+                   @for Ember.Logger
+                   @param {*} arguments
+                  */
+            log: consoleMethod('log') || Ember.K,
+
+            /**
+                   Prints the arguments to the console with a warning icon.
+                   You can pass as many arguments as you want and they will be joined together with a space.
+
+                    ```javascript
+                    Ember.Logger.warn('Something happened!');
+                    // &quot;Something happened!&quot; will be printed to the console with a warning icon.
+                    ```
+
+                   @method warn
+                   @for Ember.Logger
+                   @param {*} arguments
+                  */
+            warn: consoleMethod('warn') || Ember.K,
+
+            /**
+                   Prints the arguments to the console with an error icon, red text and a stack trace.
+                   You can pass as many arguments as you want and they will be joined together with a space.
+
+                    ```javascript
+                    Ember.Logger.error('Danger! Danger!');
+                    // &quot;Danger! Danger!&quot; will be printed to the console in red text.
+                    ```
+
+                   @method error
+                   @for Ember.Logger
+                   @param {*} arguments
+                  */
+            error: consoleMethod('error') || Ember.K,
+
+            /**
+                   Logs the arguments to the console.
+                   You can pass as many arguments as you want and they will be joined together with a space.
+
+                    ```javascript
+                    var foo = 1;
+                    Ember.Logger.info('log value of foo:', foo);
+                    // &quot;log value of foo: 1&quot; will be printed to the console
+                    ```
+
+                   @method info
+                   @for Ember.Logger
+                   @param {*} arguments
+                  */
+            info: consoleMethod('info') || Ember.K,
+
+            /**
+                   Logs the arguments to the console in blue text.
+                   You can pass as many arguments as you want and they will be joined together with a space.
+
+                    ```javascript
+                    var foo = 1;
+                    Ember.Logger.debug('log value of foo:', foo);
+                    // &quot;log value of foo: 1&quot; will be printed to the console
+                    ```
+
+                   @method debug
+                   @for Ember.Logger
+                   @param {*} arguments
+                  */
+            debug: consoleMethod('debug') || consoleMethod('info') || Ember.K,
+
+            /**
+                   If the value passed into `Ember.Logger.assert` is not truthy it will throw an error with a stack trace.
+
+                    ```javascript
+                    Ember.Logger.assert(true); // undefined
+                    Ember.Logger.assert(true === false); // Throws an Assertion failed error.
+                    ```
+
+                   @method assert
+                   @for Ember.Logger
+                   @param {Boolean} bool Value to test
+                  */
+            assert: consoleMethod('assert') || assertPolyfill
+        };
+    });
+    define(&quot;ember-metal/map&quot;,
+    [&quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/platform&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember-metal
+            */
+
+        /*
+              JavaScript (before ES6) does not have a Map implementation. Objects,
+              which are often used as dictionaries, may only have Strings as keys.
+
+              Because Ember has a way to get a unique identifier for every object
+              via `Ember.guidFor`, we can implement a performant Map with arbitrary
+              keys. Because it is commonly used in low-level bookkeeping, Map is
+              implemented as a pure JavaScript object for performance.
+
+              This implementation follows the current iteration of the ES6 proposal for
+              maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
+              with two exceptions. First, because we need our implementation to be pleasant
+              on older browsers, we do not use the `delete` name (using `remove` instead).
+              Second, as we do not have the luxury of in-VM iteration, we implement a
+              forEach method for iteration.
+
+              Map is mocked out to look like an Ember object, so you can do
+              `Ember.Map.create()` for symmetry with other Ember classes.
+            */
+
+        var set = __dependency1__.set;
+        var guidFor = __dependency2__.guidFor;
+        var indexOf = __dependency3__.indexOf;
+        var create = __dependency4__.create;
+
+        function copy(obj) {
+            var output = {};
+
+            for (var prop in obj) {
+                if (obj.hasOwnProperty(prop)) {
+                    output[prop] = obj[prop];
+                }
+            }
+
+            return output;
+        }
+
+        function copyMap(original, newObject) {
+            var keys = original.keys.copy(),
+            values = copy(original.values);
+
+            newObject.keys = keys;
+            newObject.values = values;
+            newObject.length = original.length;
+
+            return newObject;
+        }
+
+        /**
+              This class is used internally by Ember and Ember Data.
+              Please do not use it at this time. We plan to clean it up
+              and add many tests soon.
+
+              @class OrderedSet
+              @namespace Ember
+              @constructor
+              @private
+            */
+        function OrderedSet() {
+            this.clear();
+        }
+
+        /**
+              @method create
+              @static
+              @return {Ember.OrderedSet}
+            */
+        OrderedSet.create = function() {
+            return new OrderedSet();
+        };
+
+
+        OrderedSet.prototype = {
+            /**
+                    @method clear
+                  */
+            clear: function() {
+                this.presenceSet = {};
+                this.list = [];
+            },
+
+            /**
+                    @method add
+                    @param obj
+                  */
+            add: function(obj) {
+                var guid = guidFor(obj),
+                presenceSet = this.presenceSet,
+                list = this.list;
+
+                if (guid in presenceSet) {
+                    return;
+                }
+
+                presenceSet[guid] = true;
+                list.push(obj);
+            },
+
+            /**
+                    @method remove
+                    @param obj
+                  */
+            remove: function(obj) {
+                var guid = guidFor(obj),
+                presenceSet = this.presenceSet,
+                list = this.list;
+
+                delete presenceSet[guid];
+
+                var index = indexOf.call(list, obj);
+                if (index &gt; -1) {
+                    list.splice(index, 1);
+                }
+            },
+
+            /**
+                    @method isEmpty
+                    @return {Boolean}
+                  */
+            isEmpty: function() {
+                return this.list.length === 0;
+            },
+
+            /**
+                    @method has
+                    @param obj
+                    @return {Boolean}
+                  */
+            has: function(obj) {
+                var guid = guidFor(obj),
+                presenceSet = this.presenceSet;
+
+                return guid in presenceSet;
+            },
+
+            /**
+                    @method forEach
+                    @param {Function} fn
+                    @param self
+                  */
+            forEach: function(fn, self) {
+                // allow mutation during iteration
+                var list = this.toArray();
+
+                for (var i = 0, j = list.length; i &lt; j; i++) {
+                    fn.call(self, list[i]);
+                }
+            },
+
+            /**
+                    @method toArray
+                    @return {Array}
+                  */
+            toArray: function() {
+                return this.list.slice();
+            },
+
+            /**
+                    @method copy
+                    @return {Ember.OrderedSet}
+                  */
+            copy: function() {
+                var set = new OrderedSet();
+
+                set.presenceSet = copy(this.presenceSet);
+                set.list = this.toArray();
+
+                return set;
+            }
+        };
+
+        /**
+              A Map stores values indexed by keys. Unlike JavaScript's
+              default Objects, the keys of a Map can be any JavaScript
+              object.
+
+              Internally, a Map has two data structures:
+
+              1. `keys`: an OrderedSet of all of the existing keys
+              2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`
+
+              When a key/value pair is added for the first time, we
+              add the key to the `keys` OrderedSet, and create or
+              replace an entry in `values`. When an entry is deleted,
+              we delete its entry in `keys` and `values`.
+
+              @class Map
+              @namespace Ember
+              @private
+              @constructor
+            */
+        function Map() {
+            this.keys = OrderedSet.create();
+            this.values = {};
+        }
+
+        Ember.Map = Map;
+
+        /**
+              @method create
+              @static
+            */
+        Map.create = function() {
+            return new Map();
+        };
+
+        Map.prototype = {
+            /**
+                    This property will change as the number of objects in the map changes.
+
+                    @property length
+                    @type number
+                    @default 0
+                  */
+            length: 0,
+
+            /**
+                    Retrieve the value associated with a given key.
+
+                    @method get
+                    @param {*} key
+                    @return {*} the value associated with the key, or `undefined`
+                  */
+            get: function(key) {
+                var values = this.values,
+                guid = guidFor(key);
+
+                return values[guid];
+            },
+
+            /**
+                    Adds a value to the map. If a value for the given key has already been
+                    provided, the new value will replace the old value.
+
+                    @method set
+                    @param {*} key
+                    @param {*} value
+                  */
+            set: function(key, value) {
+                var keys = this.keys,
+                values = this.values,
+                guid = guidFor(key);
+
+                keys.add(key);
+                values[guid] = value;
+                set(this, 'length', keys.list.length);
+            },
+
+            /**
+                    Removes a value from the map for an associated key.
+
+                    @method remove
+                    @param {*} key
+                    @return {Boolean} true if an item was removed, false otherwise
+                  */
+            remove: function(key) {
+                // don't use ES6 &quot;delete&quot; because it will be annoying
+                // to use in browsers that are not ES6 friendly;
+                var keys = this.keys,
+                values = this.values,
+                guid = guidFor(key);
+
+                if (values.hasOwnProperty(guid)) {
+                    keys.remove(key);
+                    delete values[guid];
+                    set(this, 'length', keys.list.length);
+                    return true;
+                } else {
+                    return false;
+                }
+            },
+
+            /**
+                    Check whether a key is present.
+
+                    @method has
+                    @param {*} key
+                    @return {Boolean} true if the item was present, false otherwise
+                  */
+            has: function(key) {
+                var values = this.values,
+                guid = guidFor(key);
+
+                return values.hasOwnProperty(guid);
+            },
+
+            /**
+                    Iterate over all the keys and values. Calls the function once
+                    for each key, passing in the key and value, in that order.
+
+                    The keys are guaranteed to be iterated over in insertion order.
+
+                    @method forEach
+                    @param {Function} callback
+                    @param {*} self if passed, the `this` value inside the
+                      callback. By default, `this` is the map.
+                  */
+            forEach: function(callback, self) {
+                var keys = this.keys,
+                values = this.values;
+
+                keys.forEach(function(key) {
+                    var guid = guidFor(key);
+                    callback.call(self, key, values[guid]);
+                });
+            },
+
+            /**
+                    @method copy
+                    @return {Ember.Map}
+                  */
+            copy: function() {
+                return copyMap(this, new Map());
+            }
+        };
+
+        /**
+              @class MapWithDefault
+              @namespace Ember
+              @extends Ember.Map
+              @private
+              @constructor
+              @param [options]
+                @param {*} [options.defaultValue]
+            */
+        function MapWithDefault(options) {
+            Map.call(this);
+            this.defaultValue = options.defaultValue;
+        }
+
+        /**
+              @method create
+              @static
+              @param [options]
+                @param {*} [options.defaultValue]
+              @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
+                `Ember.MapWithDefault` otherwise returns `Ember.Map`
+            */
+        MapWithDefault.create = function(options) {
+            if (options) {
+                return new MapWithDefault(options);
+            } else {
+                return new Map();
+            }
+        };
+
+        MapWithDefault.prototype = create(Map.prototype);
+
+        /**
+              Retrieve the value associated with a given key.
+
+              @method get
+              @param {*} key
+              @return {*} the value associated with the key, or the default value
+            */
+        MapWithDefault.prototype.get = function(key) {
+            var hasValue = this.has(key);
+
+            if (hasValue) {
+                return Map.prototype.get.call(this, key);
+            } else {
+                var defaultValue = this.defaultValue(key);
+                this.set(key, defaultValue);
+                return defaultValue;
+            }
+        };
+
+        /**
+              @method copy
+              @return {Ember.MapWithDefault}
+            */
+        MapWithDefault.prototype.copy = function() {
+            return copyMap(this, new MapWithDefault({
+                defaultValue: this.defaultValue
+            }));
+        };
+
+        __exports__.OrderedSet = OrderedSet;
+        __exports__.Map = Map;
+        __exports__.MapWithDefault = MapWithDefault;
+    });
+    define(&quot;ember-metal/merge&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        /**
+              Merge the contents of two objects together into the first object.
+
+              ```javascript
+              Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'}
+              var a = {first: 'Yehuda'}, b = {last: 'Katz'};
+              Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'}
+              ```
+
+              @method merge
+              @for Ember
+              @param {Object} original The object to merge into
+              @param {Object} updates The object to copy properties from
+              @return {Object}
+            */
+        __exports__[&quot;default&quot;] = function merge(original, updates) {
+            for (var prop in updates) {
+                if (!updates.hasOwnProperty(prop)) {
+                    continue;
+                }
+                original[prop] = updates[prop];
+            }
+            return original;
+        }
+    });
+    define(&quot;ember-metal/mixin&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/expand_properties&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/binding&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-metal
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // warn, assert, wrap, et;
+        var merge = __dependency2__[&quot;default&quot;];
+        var map = __dependency3__.map;
+        var indexOf = __dependency3__.indexOf;
+        var forEach = __dependency3__.forEach;
+        var create = __dependency4__.create;
+        var guidFor = __dependency5__.guidFor;
+        var meta = __dependency5__.meta;
+        var META_KEY = __dependency5__.META_KEY;
+        var wrap = __dependency5__.wrap;
+        var makeArray = __dependency5__.makeArray;
+        var apply = __dependency5__.apply;
+        var expandProperties = __dependency6__[&quot;default&quot;];
+        var Descriptor = __dependency7__.Descriptor;
+        var defineProperty = __dependency7__.defineProperty;
+        var ComputedProperty = __dependency8__.ComputedProperty;
+        var Binding = __dependency9__.Binding;
+        var addObserver = __dependency10__.addObserver;
+        var removeObserver = __dependency10__.removeObserver;
+        var addBeforeObserver = __dependency10__.addBeforeObserver;
+        var removeBeforeObserver = __dependency10__.removeBeforeObserver;
+        var addListener = __dependency11__.addListener;
+        var removeListener = __dependency11__.removeListener;
+
+        var REQUIRED,
+        a_map = map,
+        a_indexOf = indexOf,
+        a_forEach = forEach,
+        a_slice = [].slice,
+        o_create = create,
+        metaFor = meta;
+
+        function superFunction() {
+            var ret, func = this.__nextSuper;
+            if (func) {
+                this.__nextSuper = null;
+                ret = apply(this, func, arguments);
+                this.__nextSuper = func;
+            }
+            return ret;
+        }
+
+        function mixinsMeta(obj) {
+            var m = metaFor(obj, true), ret = m.mixins;
+            if (!ret) {
+                ret = m.mixins = {};
+            } else if (!m.hasOwnProperty('mixins')) {
+                ret = m.mixins = o_create(ret);
+            }
+            return ret;
+        }
+
+        function initMixin(mixin, args) {
+            if (args &amp;&amp; args.length &gt; 0) {
+                mixin.mixins = a_map.call(args, function(x) {
+                    if (x instanceof Mixin) {
+                        return x;
+                    }
+
+                    // Note: Manually setup a primitive mixin here. This is the only
+                    // way to actually get a primitive mixin. This way normal creation
+                    // of mixins will give you combined mixins...
+                    var mixin = new Mixin();
+                    mixin.properties = x;
+                    return mixin;
+                });
+            }
+            return mixin;
+        }
+
+        function isMethod(obj) {
+            return 'function' === typeof obj &amp;&amp;
+            obj.isMethod !== false &amp;&amp;
+            obj !== Boolean &amp;&amp; obj !== Object &amp;&amp; obj !== Number &amp;&amp; obj !== Array &amp;&amp; obj !== Date &amp;&amp; obj !== String;
+        }
+
+        var CONTINUE = {};
+
+        function mixinProperties(mixinsMeta, mixin) {
+            var guid;
+
+            if (mixin instanceof Mixin) {
+                guid = guidFor(mixin);
+                if (mixinsMeta[guid]) {
+                    return CONTINUE;
+                }
+                mixinsMeta[guid] = mixin;
+                return mixin.properties;
+            } else {
+                return mixin; // apply anonymous mixin properties
+            }
+        }
+
+        function concatenatedMixinProperties(concatProp, props, values, base) {
+            var concats;
+
+            // reset before adding each new mixin to pickup concats from previous
+            concats = values[concatProp] || base[concatProp];
+            if (props[concatProp]) {
+                concats = concats ? concats.concat(props[concatProp]) : props[concatProp];
+            }
+
+            return concats;
+        }
+
+        function giveDescriptorSuper(meta, key, property, values, descs) {
+            var superProperty;
+
+            // Computed properties override methods, and do not call super to them
+            if (values[key] === undefined) {
+                // Find the original descriptor in a parent mixin
+                superProperty = descs[key];
+            }
+
+            // If we didn't find the original descriptor in a parent mixin, find
+            // it on the original object.
+            superProperty = superProperty || meta.descs[key];
+
+            if (!superProperty || !(superProperty instanceof ComputedProperty)) {
+                return property;
+            }
+
+            // Since multiple mixins may inherit from the same parent, we need
+            // to clone the computed property so that other mixins do not receive
+            // the wrapped version.
+            property = o_create(property);
+            property.func = wrap(property.func, superProperty.func);
+
+            return property;
+        }
+
+        function giveMethodSuper(obj, key, method, values, descs) {
+            var superMethod;
+
+            // Methods overwrite computed properties, and do not call super to them.
+            if (descs[key] === undefined) {
+                // Find the original method in a parent mixin
+                superMethod = values[key];
+            }
+
+            // If we didn't find the original value in a parent mixin, find it in
+            // the original object
+            superMethod = superMethod || obj[key];
+
+            // Only wrap the new method if the original method was a function
+            if ('function' !== typeof superMethod) {
+                return method;
+            }
+
+            return wrap(method, superMethod);
+        }
+
+        function applyConcatenatedProperties(obj, key, value, values) {
+            var baseValue = values[key] || obj[key];
+
+            if (baseValue) {
+                if ('function' === typeof baseValue.concat) {
+                    return baseValue.concat(value);
+                } else {
+                    return makeArray(baseValue).concat(value);
+                }
+            } else {
+                return makeArray(value);
+            }
+        }
+
+        function applyMergedProperties(obj, key, value, values) {
+            var baseValue = values[key] || obj[key];
+
+            if (!baseValue) {
+                return value;
+            }
+
+            var newBase = merge({}, baseValue),
+            hasFunction = false;
+
+            for (var prop in value) {
+                if (!value.hasOwnProperty(prop)) {
+                    continue;
+                }
+
+                var propValue = value[prop];
+                if (isMethod(propValue)) {
+                    // TODO: support for Computed Properties, etc?
+                    hasFunction = true;
+                    newBase[prop] = giveMethodSuper(obj, prop, propValue, baseValue, {});
+                } else {
+                    newBase[prop] = propValue;
+                }
+            }
+
+            if (hasFunction) {
+                newBase._super = superFunction;
+            }
+
+            return newBase;
+        }
+
+        function addNormalizedProperty(base, key, value, meta, descs, values, concats, mergings) {
+            if (value instanceof Descriptor) {
+                if (value === REQUIRED &amp;&amp; descs[key]) {
+                    return CONTINUE;
+                }
+
+                // Wrap descriptor function to implement
+                // __nextSuper() if needed
+                if (value.func) {
+                    value = giveDescriptorSuper(meta, key, value, values, descs);
+                }
+
+                descs[key] = value;
+                values[key] = undefined;
+            } else {
+                if ((concats &amp;&amp; a_indexOf.call(concats, key) &gt;= 0) ||
+                key === 'concatenatedProperties' ||
+                key === 'mergedProperties') {
+                    value = applyConcatenatedProperties(base, key, value, values);
+                } else if ((mergings &amp;&amp; a_indexOf.call(mergings, key) &gt;= 0)) {
+                    value = applyMergedProperties(base, key, value, values);
+                } else if (isMethod(value)) {
+                    value = giveMethodSuper(base, key, value, values, descs);
+                }
+
+                descs[key] = undefined;
+                values[key] = value;
+            }
+        }
+
+        function mergeMixins(mixins, m, descs, values, base, keys) {
+            var mixin, props, key, concats, mergings, meta;
+
+            function removeKeys(keyName) {
+                delete descs[keyName];
+                delete values[keyName];
+            }
+
+            for (var i = 0, l = mixins.length; i &lt; l; i++) {
+                mixin = mixins[i];
+                Ember.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(mixin),
+                typeof mixin === 'object' &amp;&amp; mixin !== null &amp;&amp; Object.prototype.toString.call(mixin) !== '[object Array]');
+
+                props = mixinProperties(m, mixin);
+                if (props === CONTINUE) {
+                    continue;
+                }
+
+                if (props) {
+                    meta = metaFor(base);
+                    if (base.willMergeMixin) {
+                        base.willMergeMixin(props);
+                    }
+                    concats = concatenatedMixinProperties('concatenatedProperties', props, values, base);
+                    mergings = concatenatedMixinProperties('mergedProperties', props, values, base);
+
+                    for (key in props) {
+                        if (!props.hasOwnProperty(key)) {
+                            continue;
+                        }
+                        keys.push(key);
+                        addNormalizedProperty(base, key, props[key], meta, descs, values, concats, mergings);
+                    }
+
+                    // manually copy toString() because some JS engines do not enumerate it
+                    if (props.hasOwnProperty('toString')) {
+                        base.toString = props.toString;
+                    }
+                } else if (mixin.mixins) {
+                    mergeMixins(mixin.mixins, m, descs, values, base, keys);
+                    if (mixin._without) {
+                        a_forEach.call(mixin._without, removeKeys);
+                    }
+                }
+            }
+        }
+
+        var IS_BINDING = /^.+Binding$/;
+
+        function detectBinding(obj, key, value, m) {
+            if (IS_BINDING.test(key)) {
+                var bindings = m.bindings;
+                if (!bindings) {
+                    bindings = m.bindings = {};
+                } else if (!m.hasOwnProperty('bindings')) {
+                    bindings = m.bindings = o_create(m.bindings);
+                }
+                bindings[key] = value;
+            }
+        }
+
+        function connectBindings(obj, m) {
+            // TODO Mixin.apply(instance) should disconnect binding if exists
+            var bindings = m.bindings, key, binding, to;
+            if (bindings) {
+                for (key in bindings) {
+                    binding = bindings[key];
+                    if (binding) {
+                        to = key.slice(0, -7); // strip Binding off end
+                        if (binding instanceof Binding) {
+                            binding = binding.copy(); // copy prototypes' instance
+                            binding.to(to);
+                        } else {
+                            // binding is string path
+                            binding = new Binding(to, binding);
+                        }
+                        binding.connect(obj);
+                        obj[key] = binding;
+                    }
+                }
+                // mark as applied
+                m.bindings = {};
+            }
+        }
+
+        function finishPartial(obj, m) {
+            connectBindings(obj, m || metaFor(obj));
+            return obj;
+        }
+
+        function followAlias(obj, desc, m, descs, values) {
+            var altKey = desc.methodName, value;
+            if (descs[altKey] || values[altKey]) {
+                value = values[altKey];
+                desc = descs[altKey];
+            } else if (m.descs[altKey]) {
+                desc = m.descs[altKey];
+                value = undefined;
+            } else {
+                desc = undefined;
+                value = obj[altKey];
+            }
+
+            return {
+                desc: desc,
+                value: value 
+            };
+        }
+
+        function updateObserversAndListeners(obj, key, observerOrListener, pathsKey, updateMethod) {
+            var paths = observerOrListener[pathsKey];
+
+            if (paths) {
+                for (var i = 0, l = paths.length; i &lt; l; i++) {
+                    updateMethod(obj, paths[i], null, key);
+                }
+            }
+        }
+
+        function replaceObserversAndListeners(obj, key, observerOrListener) {
+            var prev = obj[key];
+
+            if ('function' === typeof prev) {
+                updateObserversAndListeners(obj, key, prev, '__ember_observesBefore__', removeBeforeObserver);
+                updateObserversAndListeners(obj, key, prev, '__ember_observes__', removeObserver);
+                updateObserversAndListeners(obj, key, prev, '__ember_listens__', removeListener);
+            }
+
+            if ('function' === typeof observerOrListener) {
+                updateObserversAndListeners(obj, key, observerOrListener, '__ember_observesBefore__', addBeforeObserver);
+                updateObserversAndListeners(obj, key, observerOrListener, '__ember_observes__', addObserver);
+                updateObserversAndListeners(obj, key, observerOrListener, '__ember_listens__', addListener);
+            }
+        }
+
+        function applyMixin(obj, mixins, partial) {
+            var descs = {}, values = {}, m = metaFor(obj),
+            key, value, desc, keys = [];
+
+            obj._super = superFunction;
+
+            // Go through all mixins and hashes passed in, and:
+            //
+            // * Handle concatenated properties
+            // * Handle merged properties
+            // * Set up _super wrapping if necessary
+            // * Set up computed property descriptors
+            // * Copying `toString` in broken browsers
+            mergeMixins(mixins, mixinsMeta(obj), descs, values, obj, keys);
+
+            for (var i = 0, l = keys.length; i &lt; l; i++) {
+                key = keys[i];
+                if (key === 'constructor' || !values.hasOwnProperty(key)) {
+                    continue;
+                }
+
+                desc = descs[key];
+                value = values[key];
+
+                if (desc === REQUIRED) {
+                    continue;
+                }
+
+                while (desc &amp;&amp; desc instanceof Alias) {
+                    var followed = followAlias(obj, desc, m, descs, values);
+                    desc = followed.desc;
+                    value = followed.value;
+                }
+
+                if (desc === undefined &amp;&amp; value === undefined) {
+                    continue;
+                }
+
+                replaceObserversAndListeners(obj, key, value);
+                detectBinding(obj, key, value, m);
+                defineProperty(obj, key, desc, value, m);
+            }
+
+            if (!partial) {
+                // don't apply to prototype
+                finishPartial(obj, m);
+            }
+
+            return obj;
+        }
+
+        /**
+              @method mixin
+              @for Ember
+              @param obj
+              @param mixins*
+              @return obj
+            */
+        function mixin(obj) {
+            var args = a_slice.call(arguments, 1);
+            applyMixin(obj, args, false);
+            return obj;
+        }
+
+        __exports__.mixin = mixin; /**
+              The `Ember.Mixin` class allows you to create mixins, whose properties can be
+              added to other classes. For instance,
+
+              ```javascript
+              App.Editable = Ember.Mixin.create({
+                edit: function() {
+                  console.log('starting to edit');
+                  this.set('isEditing', true);
+                },
+                isEditing: false
+              });
+
+              // Mix mixins into classes by passing them as the first arguments to
+              // .extend.
+              App.CommentView = Ember.View.extend(App.Editable, {
+                template: Ember.Handlebars.compile('{{#if view.isEditing}}...{{else}}...{{/if}}')
+              });
+
+              commentView = App.CommentView.create();
+              commentView.edit(); // outputs 'starting to edit'
+              ```
+
+              Note that Mixins are created with `Ember.Mixin.create`, not
+              `Ember.Mixin.extend`.
+
+              Note that mixins extend a constructor's prototype so arrays and object literals
+              defined as properties will be shared amongst objects that implement the mixin.
+              If you want to define a property in a mixin that is not shared, you can define
+              it either as a computed property or have it be created on initialization of the object.
+
+              ```javascript
+              //filters array will be shared amongst any object implementing mixin
+              App.Filterable = Ember.Mixin.create({
+                filters: Ember.A()
+              });
+
+              //filters will be a separate  array for every object implementing the mixin
+              App.Filterable = Ember.Mixin.create({
+                filters: Ember.computed(function(){return Ember.A();})
+              });
+
+              //filters will be created as a separate array during the object's initialization
+              App.Filterable = Ember.Mixin.create({
+                init: function() {
+                  this._super();
+                  this.set(&quot;filters&quot;, Ember.A());
+                }
+              });
+              ```
+
+              @class Mixin
+              @namespace Ember
+            */
+        __exports__[&quot;default&quot;] = Mixin;
+        function Mixin() {
+            return initMixin(this, arguments);
+        }
+        Mixin.prototype = {
+            properties: null,
+            mixins: null,
+            ownerConstructor: null
+        };
+
+        Mixin._apply = applyMixin;
+
+        Mixin.applyPartial = function(obj) {
+            var args = a_slice.call(arguments, 1);
+            return applyMixin(obj, args, true);
+        };
+
+        Mixin.finishPartial = finishPartial;
+
+        // ES6TODO: this relies on a global state?
+        Ember.anyUnprocessedMixins = false;
+
+        /**
+              @method create
+              @static
+              @param arguments*
+            */
+        Mixin.create = function() {
+            // ES6TODO: this relies on a global state?
+            Ember.anyUnprocessedMixins = true;
+            var M = this;
+            return initMixin(new M(), arguments);
+        };
+
+        var MixinPrototype = Mixin.prototype;
+
+        /**
+              @method reopen
+              @param arguments*
+            */
+        MixinPrototype.reopen = function() {
+            var mixin, tmp;
+
+            if (this.properties) {
+                mixin = Mixin.create();
+                mixin.properties = this.properties;
+                delete this.properties;
+                this.mixins = [mixin];
+            } else if (!this.mixins) {
+                this.mixins = [];
+            }
+
+            var len = arguments.length, mixins = this.mixins, idx;
+
+            for (idx = 0; idx &lt; len; idx++) {
+                mixin = arguments[idx];
+                Ember.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(mixin),
+                typeof mixin === 'object' &amp;&amp; mixin !== null &amp;&amp; Object.prototype.toString.call(mixin) !== '[object Array]');
+
+                if (mixin instanceof Mixin) {
+                    mixins.push(mixin);
+                } else {
+                    tmp = Mixin.create();
+                    tmp.properties = mixin;
+                    mixins.push(tmp);
+                }
+            }
+
+            return this;
+        };
+
+        /**
+              @method apply
+              @param obj
+              @return applied object
+            */
+        MixinPrototype.apply = function(obj) {
+            return applyMixin(obj, [this], false);
+        };
+
+        MixinPrototype.applyPartial = function(obj) {
+            return applyMixin(obj, [this], true);
+        };
+
+        function _detect(curMixin, targetMixin, seen) {
+            var guid = guidFor(curMixin);
+
+            if (seen[guid]) {
+                return false;
+            }
+            seen[guid] = true;
+
+            if (curMixin === targetMixin) {
+                return true;
+            }
+            var mixins = curMixin.mixins, loc = mixins ? mixins.length : 0;
+            while (--loc &gt;= 0) {
+                if (_detect(mixins[loc], targetMixin, seen)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+              @method detect
+              @param obj
+              @return {Boolean}
+            */
+        MixinPrototype.detect = function(obj) {
+            if (!obj) {
+                return false;
+            }
+            if (obj instanceof Mixin) {
+                return _detect(obj, this, {});
+            }
+            var m = obj[META_KEY],
+            mixins = m &amp;&amp; m.mixins;
+            if (mixins) {
+                return !!mixins[guidFor(this)];
+            }
+            return false;
+        };
+
+        MixinPrototype.without = function() {
+            var ret = new Mixin(this);
+            ret._without = a_slice.call(arguments);
+            return ret;
+        };
+
+        function _keys(ret, mixin, seen) {
+            if (seen[guidFor(mixin)]) {
+                return;
+            }
+            seen[guidFor(mixin)] = true;
+
+            if (mixin.properties) {
+                var props = mixin.properties;
+                for (var key in props) {
+                    if (props.hasOwnProperty(key)) {
+                        ret[key] = true;
+                    }
+                }
+            } else if (mixin.mixins) {
+                a_forEach.call(mixin.mixins, function(x) {
+                    _keys(ret, x, seen);
+                });
+            }
+        }
+
+        MixinPrototype.keys = function() {
+            var keys = {}, seen = {}, ret = [];
+            _keys(keys, this, seen);
+            for (var key in keys) {
+                if (keys.hasOwnProperty(key)) {
+                    ret.push(key);
+                }
+            }
+            return ret;
+        };
+
+        // returns the mixins currently applied to the specified object
+        // TODO: Make Ember.mixin
+        Mixin.mixins = function(obj) {
+            var m = obj[META_KEY],
+            mixins = m &amp;&amp; m.mixins, ret = [];
+
+            if (!mixins) {
+                return ret;
+            }
+
+            for (var key in mixins) {
+                var mixin = mixins[key];
+
+                // skip primitive mixins since these are always anonymous
+                if (!mixin.properties) {
+                    ret.push(mixin);
+                }
+            }
+
+            return ret;
+        };
+
+        REQUIRED = new Descriptor();
+        REQUIRED.toString = function() {
+            return '(Required Property)';
+        };
+
+        /**
+              Denotes a required property for a mixin
+
+              @method required
+              @for Ember
+            */
+        function required() {
+            return REQUIRED;
+        }
+
+        __exports__.required = required;
+        function Alias(methodName) {
+            this.methodName = methodName;
+        }
+
+        Alias.prototype = new Descriptor();
+
+        /**
+              Makes a method available via an additional name.
+
+              ```javascript
+              App.Person = Ember.Object.extend({
+                name: function() {
+                  return 'Tomhuda Katzdale';
+                },
+                moniker: Ember.aliasMethod('name')
+              });
+
+              var goodGuy = App.Person.create();
+              
+              goodGuy.name();    // 'Tomhuda Katzdale'
+              goodGuy.moniker(); // 'Tomhuda Katzdale'
+              ```
+
+              @method aliasMethod
+              @for Ember
+              @param {String} methodName name of the method to alias
+              @return {Ember.Descriptor}
+            */
+        function aliasMethod(methodName) {
+            return new Alias(methodName);
+        }
+
+        __exports__.aliasMethod = aliasMethod; // ..........................................................
+        // OBSERVER HELPER
+        //
+
+        /**
+              Specify a method that observes property changes.
+
+              ```javascript
+              Ember.Object.extend({
+                valueObserver: Ember.observer('value', function() {
+                  // Executes whenever the &quot;value&quot; property changes
+                })
+              });
+              ```
+
+              In the future this method may become asynchronous. If you want to ensure
+              synchronous behavior, use `immediateObserver`.
+
+              Also available as `Function.prototype.observes` if prototype extensions are
+              enabled.
+
+              @method observer
+              @for Ember
+              @param {String} propertyNames*
+              @param {Function} func
+              @return func
+            */
+        function observer() {
+            var func = a_slice.call(arguments, -1)[0];
+            var paths;
+
+            var addWatchedProperty = function (path) {
+                paths.push(path);
+            };
+            var _paths = a_slice.call(arguments, 0, -1);
+
+            if (typeof func !== &quot;function&quot;) {
+                // revert to old, soft-deprecated argument ordering
+
+                func = arguments[0];
+                _paths = a_slice.call(arguments, 1);
+            }
+
+            paths = [];
+
+            for (var i = 0; i &lt; _paths.length; ++i) {
+                expandProperties(_paths[i], addWatchedProperty);
+            }
+
+            if (typeof func !== &quot;function&quot;) {
+                throw new Ember.Error(&quot;Ember.observer called without a function&quot;);
+            }
+
+            func.__ember_observes__ = paths;
+            return func;
+        }
+
+        __exports__.observer = observer; /**
+              Specify a method that observes property changes.
+
+              ```javascript
+              Ember.Object.extend({
+                valueObserver: Ember.immediateObserver('value', function() {
+                  // Executes whenever the &quot;value&quot; property changes
+                })
+              });
+              ```
+
+              In the future, `Ember.observer` may become asynchronous. In this event,
+              `Ember.immediateObserver` will maintain the synchronous behavior.
+
+              Also available as `Function.prototype.observesImmediately` if prototype extensions are
+              enabled.
+
+              @method immediateObserver
+              @for Ember
+              @param {String} propertyNames*
+              @param {Function} func
+              @return func
+            */
+        function immediateObserver() {
+            for (var i = 0, l = arguments.length; i &lt; l; i++) {
+                var arg = arguments[i];
+                Ember.assert(&quot;Immediate observers must observe internal properties only, not properties on other objects.&quot;, typeof arg !== &quot;string&quot; || arg.indexOf('.') === -1);
+            }
+
+            return observer.apply(this, arguments);
+        }
+
+        __exports__.immediateObserver = immediateObserver; /**
+              When observers fire, they are called with the arguments `obj`, `keyName`.
+
+              Note, `@each.property` observer is called per each add or replace of an element
+              and it's not called with a specific enumeration item.
+
+              A `beforeObserver` fires before a property changes.
+
+              A `beforeObserver` is an alternative form of `.observesBefore()`.
+
+              ```javascript
+              App.PersonView = Ember.View.extend({
+                friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],
+
+                valueWillChange: Ember.beforeObserver('content.value', function(obj, keyName) {
+                  this.changingFrom = obj.get(keyName);
+                }),
+
+                valueDidChange: Ember.observer('content.value', function(obj, keyName) {
+                    // only run if updating a value already in the DOM
+                    if (this.get('state') === 'inDOM') {
+                      var color = obj.get(keyName) &gt; this.changingFrom ? 'green' : 'red';
+                      // logic
+                    }
+                }),
+
+                friendsDidChange: Ember.observer('friends.@each.name', function(obj, keyName) {
+                  // some logic
+                  // obj.get(keyName) returns friends array
+                })
+              });
+              ```
+
+              Also available as `Function.prototype.observesBefore` if prototype extensions are
+              enabled.
+
+              @method beforeObserver
+              @for Ember
+              @param {String} propertyNames*
+              @param {Function} func
+              @return func
+            */
+        function beforeObserver() {
+            var func = a_slice.call(arguments, -1)[0];
+            var paths;
+
+            var addWatchedProperty = function(path) {
+                paths.push(path);
+            };
+
+            var _paths = a_slice.call(arguments, 0, -1);
+
+            if (typeof func !== &quot;function&quot;) {
+                // revert to old, soft-deprecated argument ordering
+
+                func = arguments[0];
+                _paths = a_slice.call(arguments, 1);
+            }
+
+            paths = [];
+
+            for (var i = 0; i &lt; _paths.length; ++i) {
+                expandProperties(_paths[i], addWatchedProperty);
+            }
+
+            if (typeof func !== &quot;function&quot;) {
+                throw new Ember.Error(&quot;Ember.beforeObserver called without a function&quot;);
+            }
+
+            func.__ember_observesBefore__ = paths;
+            return func;
+        }
+
+        __exports__.beforeObserver = beforeObserver;
+        __exports__.IS_BINDING = IS_BINDING;
+        __exports__.Mixin = Mixin;
+    });
+    define(&quot;ember-metal/observer&quot;,
+    [&quot;ember-metal/watching&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var watch = __dependency1__.watch;
+        var unwatch = __dependency1__.unwatch;
+        var map = __dependency2__.map;
+        var listenersFor = __dependency3__.listenersFor;
+        var addListener = __dependency3__.addListener;
+        var removeListener = __dependency3__.removeListener;
+        var suspendListeners = __dependency3__.suspendListeners;
+        var suspendListener = __dependency3__.suspendListener;
+        /**
+            @module ember-metal
+            */
+
+        var AFTER_OBSERVERS = ':change';
+        var BEFORE_OBSERVERS = ':before';
+
+        function changeEvent(keyName) {
+            return keyName + AFTER_OBSERVERS;
+        }
+
+        function beforeEvent(keyName) {
+            return keyName + BEFORE_OBSERVERS;
+        }
+
+        /**
+              @method addObserver
+              @for Ember
+              @param obj
+              @param {String} path
+              @param {Object|Function} targetOrMethod
+              @param {Function|String} [method]
+            */
+        function addObserver(obj, _path, target, method) {
+            addListener(obj, changeEvent(_path), target, method);
+            watch(obj, _path);
+
+            return this;
+        }
+
+        __exports__.addObserver = addObserver;
+        function observersFor(obj, path) {
+            return listenersFor(obj, changeEvent(path));
+        }
+
+        __exports__.observersFor = observersFor; /**
+              @method removeObserver
+              @for Ember
+              @param obj
+              @param {String} path
+              @param {Object|Function} targetOrMethod
+              @param {Function|String} [method]
+            */
+        function removeObserver(obj, _path, target, method) {
+            unwatch(obj, _path);
+            removeListener(obj, changeEvent(_path), target, method);
+
+            return this;
+        }
+
+        __exports__.removeObserver = removeObserver; /**
+              @method addBeforeObserver
+              @for Ember
+              @param obj
+              @param {String} path
+              @param {Object|Function} targetOrMethod
+              @param {Function|String} [method]
+            */
+        function addBeforeObserver(obj, _path, target, method) {
+            addListener(obj, beforeEvent(_path), target, method);
+            watch(obj, _path);
+
+            return this;
+        }
+
+        __exports__.addBeforeObserver = addBeforeObserver; // Suspend observer during callback.
+        //
+        // This should only be used by the target of the observer
+        // while it is setting the observed path.
+        function _suspendBeforeObserver(obj, path, target, method, callback) {
+            return suspendListener(obj, beforeEvent(path), target, method, callback);
+        }
+
+        __exports__._suspendBeforeObserver = _suspendBeforeObserver;
+        function _suspendObserver(obj, path, target, method, callback) {
+            return suspendListener(obj, changeEvent(path), target, method, callback);
+        }
+
+        __exports__._suspendObserver = _suspendObserver;
+        function _suspendBeforeObservers(obj, paths, target, method, callback) {
+            var events = map.call(paths, beforeEvent);
+            return suspendListeners(obj, events, target, method, callback);
+        }
+
+        __exports__._suspendBeforeObservers = _suspendBeforeObservers;
+        function _suspendObservers(obj, paths, target, method, callback) {
+            var events = map.call(paths, changeEvent);
+            return suspendListeners(obj, events, target, method, callback);
+        }
+
+        __exports__._suspendObservers = _suspendObservers;
+        function beforeObserversFor(obj, path) {
+            return listenersFor(obj, beforeEvent(path));
+        }
+
+        __exports__.beforeObserversFor = beforeObserversFor; /**
+              @method removeBeforeObserver
+              @for Ember
+              @param obj
+              @param {String} path
+              @param {Object|Function} targetOrMethod
+              @param {Function|String} [method]
+            */
+        function removeBeforeObserver(obj, _path, target, method) {
+            unwatch(obj, _path);
+            removeListener(obj, beforeEvent(_path), target, method);
+
+            return this;
+        }
+
+        __exports__.removeBeforeObserver = removeBeforeObserver;
+    });
+    define(&quot;ember-metal/observer_set&quot;,
+    [&quot;ember-metal/utils&quot;, &quot;ember-metal/events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var guidFor = __dependency1__.guidFor;
+        var sendEvent = __dependency2__.sendEvent;
+
+        /*
+              this.observerSet = {
+                [senderGuid]: { // variable name: `keySet`
+                  [keyName]: listIndex
+                }
+              },
+              this.observers = [
+                {
+                  sender: obj,
+                  keyName: keyName,
+                  eventName: eventName,
+                  listeners: [
+                    [target, method, flags]
+                  ]
+                },
+                ...
+              ]
+            */
+        __exports__[&quot;default&quot;] = ObserverSet;
+        function ObserverSet() {
+            this.clear();
+        }
+
+
+        ObserverSet.prototype.add = function(sender, keyName, eventName) {
+            var observerSet = this.observerSet,
+            observers = this.observers,
+            senderGuid = guidFor(sender),
+            keySet = observerSet[senderGuid],
+            index;
+
+            if (!keySet) {
+                observerSet[senderGuid] = keySet = {};
+            }
+            index = keySet[keyName];
+            if (index === undefined) {
+                index = observers.push({
+                    sender: sender,
+                    keyName: keyName,
+                    eventName: eventName,
+                    listeners: []
+                }) - 1;
+                keySet[keyName] = index;
+            }
+            return observers[index].listeners;
+        };
+
+        ObserverSet.prototype.flush = function() {
+            var observers = this.observers, i, len, observer, sender;
+            this.clear();
+            for (i = 0, len = observers.length; i &lt; len; ++i) {
+                observer = observers[i];
+                sender = observer.sender;
+                if (sender.isDestroying || sender.isDestroyed) {
+                    continue;
+                }
+                sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners);
+            }
+        };
+
+        ObserverSet.prototype.clear = function() {
+            this.observerSet = {};
+            this.observers = [];
+        };
+    });
+    define(&quot;ember-metal/platform&quot;,
+    [&quot;ember-metal/core&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        /*globals Node */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+
+        /**
+            @module ember-metal
+            */
+
+        /**
+              Platform specific methods and feature detectors needed by the framework.
+
+              @class platform
+              @namespace Ember
+              @static
+            */
+        // TODO remove this
+        var platform = {};
+
+        /**
+              Identical to `Object.create()`. Implements if not available natively.
+
+              @method create
+              @for Ember
+            */
+        var create = Object.create;
+
+        // IE8 has Object.create but it couldn't treat property descriptors.
+        if (create) {
+            if (create({
+                a: 1
+            }, {
+                a: {
+                    value: 2
+                }
+            }).a !== 2) {
+                create = null;
+            }
+        }
+
+        // STUB_OBJECT_CREATE allows us to override other libraries that stub
+        // Object.create different than we would prefer
+        if (!create || Ember.ENV.STUB_OBJECT_CREATE) {
+            var K = function() {};
+
+            create = function(obj, props) {
+                K.prototype = obj;
+                obj = new K();
+                if (props) {
+                    K.prototype = obj;
+                    for (var prop in props) {
+                        K.prototype[prop] = props[prop].value;
+                    }
+                    obj = new K();
+                }
+                K.prototype = null;
+
+                return obj;
+            };
+
+            create.isSimulated = true;
+        }
+
+        var defineProperty = Object.defineProperty;
+        var canRedefineProperties, canDefinePropertyOnDOM;
+
+        // Catch IE8 where Object.defineProperty exists but only works on DOM elements
+        if (defineProperty) {
+            try {
+                defineProperty({}, 'a', {
+                    get: function() {}
+                });
+            } catch (e) {
+                defineProperty = null;
+            }
+        }
+
+        if (defineProperty) {
+            // Detects a bug in Android &lt;3.2 where you cannot redefine a property using
+            // Object.defineProperty once accessors have already been set.
+            canRedefineProperties = (function() {
+                var obj = {};
+
+                defineProperty(obj, 'a', {
+                    configurable: true,
+                    enumerable: true,
+                    get: function() {},
+                    set: function() {}
+                });
+
+                defineProperty(obj, 'a', {
+                    configurable: true,
+                    enumerable: true,
+                    writable: true,
+                    value: true
+                });
+
+                return obj.a === true;
+            })();
+
+            // This is for Safari 5.0, which supports Object.defineProperty, but not
+            // on DOM nodes.
+            canDefinePropertyOnDOM = (function() {
+                try {
+                    defineProperty(document.createElement('div'), 'definePropertyOnDOM', {});
+                    return true;
+                } catch (e) {}
+
+                return false;
+            })();
+
+            if (!canRedefineProperties) {
+                defineProperty = null;
+            } else if (!canDefinePropertyOnDOM) {
+                defineProperty = function(obj, keyName, desc) {
+                    var isNode;
+
+                    if (typeof Node === &quot;object&quot;) {
+                        isNode = obj instanceof Node;
+                    } else {
+                        isNode = typeof obj === &quot;object&quot; &amp;&amp; typeof obj.nodeType === &quot;number&quot; &amp;&amp; typeof obj.nodeName === &quot;string&quot;;
+                    }
+
+                    if (isNode) {
+                        // TODO: Should we have a warning here?
+                        return (obj[keyName] = desc.value);
+                    } else {
+                        return Object.defineProperty(obj, keyName, desc);
+                    }
+                };
+            }
+        }
+
+        /**
+            @class platform
+            @namespace Ember
+            */
+
+        /**
+              Identical to `Object.defineProperty()`. Implements as much functionality
+              as possible if not available natively.
+
+              @method defineProperty
+              @param {Object} obj The object to modify
+              @param {String} keyName property name to modify
+              @param {Object} desc descriptor hash
+              @return {void}
+            */
+        platform.defineProperty = defineProperty;
+
+        /**
+              Set to true if the platform supports native getters and setters.
+
+              @property hasPropertyAccessors
+              @final
+            */
+        platform.hasPropertyAccessors = true;
+
+        if (!platform.defineProperty) {
+            platform.hasPropertyAccessors = false;
+
+            platform.defineProperty = function(obj, keyName, desc) {
+                if (!desc.get) {
+                    obj[keyName] = desc.value;
+                }
+            };
+
+            platform.defineProperty.isSimulated = true;
+        }
+
+        if (Ember.ENV.MANDATORY_SETTER &amp;&amp; !platform.hasPropertyAccessors) {
+            Ember.ENV.MANDATORY_SETTER = false;
+        }
+
+        __exports__.create = create;
+        __exports__.platform = platform;
+    });
+    define(&quot;ember-metal/properties&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember-metal
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var META_KEY = __dependency2__.META_KEY;
+        var meta = __dependency2__.meta;
+        var platform = __dependency3__.platform;
+        var overrideChains = __dependency4__.overrideChains;
+        var get = __dependency5__.get;
+        var set = __dependency6__.set;
+
+        var metaFor = meta,
+        objectDefineProperty = platform.defineProperty;
+
+        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
+
+        // ..........................................................
+        // DESCRIPTOR
+        //
+
+        /**
+              Objects of this type can implement an interface to respond to requests to
+              get and set. The default implementation handles simple properties.
+
+              You generally won't need to create or subclass this directly.
+
+              @class Descriptor
+              @namespace Ember
+              @private
+              @constructor
+            */
+        function Descriptor() {}
+
+        __exports__.Descriptor = Descriptor; // ..........................................................
+        // DEFINING PROPERTIES API
+        //
+
+        var MANDATORY_SETTER_FUNCTION = Ember.MANDATORY_SETTER_FUNCTION = function(value) {
+            Ember.assert(&quot;You must use Ember.set() to access this property (of &quot; + this + &quot;)&quot;, false);
+        };
+
+        var DEFAULT_GETTER_FUNCTION = Ember.DEFAULT_GETTER_FUNCTION = function DEFAULT_GETTER_FUNCTION(name) {
+            return function() {
+                var meta = this[META_KEY];
+                return meta &amp;&amp; meta.values[name];
+            };
+        };
+
+        /**
+              NOTE: This is a low-level method used by other parts of the API. You almost
+              never want to call this method directly. Instead you should use
+              `Ember.mixin()` to define new properties.
+
+              Defines a property on an object. This method works much like the ES5
+              `Object.defineProperty()` method except that it can also accept computed
+              properties and other special descriptors.
+
+              Normally this method takes only three parameters. However if you pass an
+              instance of `Ember.Descriptor` as the third param then you can pass an
+              optional value as the fourth parameter. This is often more efficient than
+              creating new descriptor hashes for each property.
+
+              ## Examples
+
+              ```javascript
+              // ES5 compatible mode
+              Ember.defineProperty(contact, 'firstName', {
+                writable: true,
+                configurable: false,
+                enumerable: true,
+                value: 'Charles'
+              });
+
+              // define a simple property
+              Ember.defineProperty(contact, 'lastName', undefined, 'Jolley');
+
+              // define a computed property
+              Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
+                return this.firstName+' '+this.lastName;
+              }).property('firstName', 'lastName'));
+              ```
+
+              @private
+              @method defineProperty
+              @for Ember
+              @param {Object} obj the object to define this property on. This may be a prototype.
+              @param {String} keyName the name of the property
+              @param {Ember.Descriptor} [desc] an instance of `Ember.Descriptor` (typically a
+                computed property) or an ES5 descriptor.
+                You must provide this or `data` but not both.
+              @param {*} [data] something other than a descriptor, that will
+                become the explicit value of this property.
+            */
+        function defineProperty(obj, keyName, desc, data, meta) {
+            var descs, existingDesc, watching, value;
+
+            if (!meta) 
+                meta = metaFor(obj);
+            descs = meta.descs;
+            existingDesc = meta.descs[keyName];
+            watching = meta.watching[keyName] &gt; 0;
+
+            if (existingDesc instanceof Descriptor) {
+                existingDesc.teardown(obj, keyName);
+            }
+
+            if (desc instanceof Descriptor) {
+                value = desc;
+
+                descs[keyName] = desc;
+                if (MANDATORY_SETTER &amp;&amp; watching) {
+                    objectDefineProperty(obj, keyName, {
+                        configurable: true,
+                        enumerable: true,
+                        writable: true,
+                        value: undefined // make enumerable
+                    });
+                } else {
+                    obj[keyName] = undefined; // make enumerable
+                }
+                if (desc.setup) {
+                    desc.setup(obj, keyName);
+                }
+            } else {
+                descs[keyName] = undefined; // shadow descriptor in proto
+                if (desc == null) {
+                    value = data;
+
+                    if (MANDATORY_SETTER &amp;&amp; watching) {
+                        meta.values[keyName] = data;
+                        objectDefineProperty(obj, keyName, {
+                            configurable: true,
+                            enumerable: true,
+                            set: MANDATORY_SETTER_FUNCTION,
+                            get: DEFAULT_GETTER_FUNCTION(keyName)
+                        });
+                    } else {
+                        obj[keyName] = data;
+                    }
+                } else {
+                    value = desc;
+
+                    // compatibility with ES5
+                    objectDefineProperty(obj, keyName, desc);
+                }
+            }
+
+            // if key is being watched, override chains that
+            // were initialized with the prototype
+            if (watching) {
+                overrideChains(obj, keyName, meta);
+            }
+
+            // The `value` passed to the `didDefineProperty` hook is
+            // either the descriptor or data, whichever was passed.
+            if (obj.didDefineProperty) {
+                obj.didDefineProperty(obj, keyName, value);
+            }
+
+            return this;
+        }
+
+        __exports__.defineProperty = defineProperty; /**
+              Used internally to allow changing properties in a backwards compatible way, and print a helpful
+              deprecation warning.
+
+              @method deprecateProperty
+              @param {Object} object The object to add the deprecated property to.
+              @param {String} deprecatedKey The property to add (and print deprecation warnings upon accessing).
+              @param {String} newKey The property that will be aliased.
+              @private
+            */
+
+        function deprecateProperty(object, deprecatedKey, newKey) {
+            function deprecate() {
+                Ember.deprecate('Usage of `' + deprecatedKey + '` is deprecated, use `' + newKey + '` instead.');
+            }
+
+            if (platform.hasPropertyAccessors) {
+                defineProperty(object, deprecatedKey, {
+                    configurable: true,
+                    enumerable: false,
+                    set: function(value) {
+                        deprecate();
+                        set(object, newKey, value);
+                    },
+                    get: function() {
+                        deprecate();
+                        return get(object, newKey);
+                    }
+                });
+            }
+        }
+
+        __exports__.deprecateProperty = deprecateProperty;
+    });
+    define(&quot;ember-metal/property_events&quot;,
+    [&quot;ember-metal/utils&quot;, &quot;ember-metal/events&quot;, &quot;ember-metal/observer_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var META_KEY = __dependency1__.META_KEY;
+        var guidFor = __dependency1__.guidFor;
+        var tryFinally = __dependency1__.tryFinally;
+        var sendEvent = __dependency2__.sendEvent;
+        var listenersUnion = __dependency2__.listenersUnion;
+        var listenersDiff = __dependency2__.listenersDiff;
+        var ObserverSet = __dependency3__[&quot;default&quot;];
+
+        var beforeObserverSet = new ObserverSet();
+        var observerSet = new ObserverSet();
+        var deferred = 0;
+
+        // ..........................................................
+        // PROPERTY CHANGES
+        //
+
+        /**
+              This function is called just before an object property is about to change.
+              It will notify any before observers and prepare caches among other things.
+
+              Normally you will not need to call this method directly but if for some
+              reason you can't directly watch a property you can invoke this method
+              manually along with `Ember.propertyDidChange()` which you should call just
+              after the property value changes.
+
+              @method propertyWillChange
+              @for Ember
+              @param {Object} obj The object with the property that will change
+              @param {String} keyName The property key (or path) that will change.
+              @return {void}
+            */
+        function propertyWillChange(obj, keyName) {
+            var m = obj[META_KEY],
+            watching = (m &amp;&amp; m.watching[keyName] &gt; 0) || keyName === 'length',
+            proto = m &amp;&amp; m.proto,
+            desc = m &amp;&amp; m.descs[keyName];
+
+            if (!watching) {
+                return;
+            }
+            if (proto === obj) {
+                return;
+            }
+            if (desc &amp;&amp; desc.willChange) {
+                desc.willChange(obj, keyName);
+            }
+            dependentKeysWillChange(obj, keyName, m);
+            chainsWillChange(obj, keyName, m);
+            notifyBeforeObservers(obj, keyName);
+        }
+
+        /**
+              This function is called just after an object property has changed.
+              It will notify any observers and clear caches among other things.
+
+              Normally you will not need to call this method directly but if for some
+              reason you can't directly watch a property you can invoke this method
+              manually along with `Ember.propertyWillChange()` which you should call just
+              before the property value changes.
+
+              @method propertyDidChange
+              @for Ember
+              @param {Object} obj The object with the property that will change
+              @param {String} keyName The property key (or path) that will change.
+              @return {void}
+            */
+        function propertyDidChange(obj, keyName) {
+            var m = obj[META_KEY],
+            watching = (m &amp;&amp; m.watching[keyName] &gt; 0) || keyName === 'length',
+            proto = m &amp;&amp; m.proto,
+            desc = m &amp;&amp; m.descs[keyName];
+
+            if (proto === obj) {
+                return;
+            }
+
+            // shouldn't this mean that we're watching this key?
+            if (desc &amp;&amp; desc.didChange) {
+                desc.didChange(obj, keyName);
+            }
+            if (!watching &amp;&amp; keyName !== 'length') {
+                return;
+            }
+
+            dependentKeysDidChange(obj, keyName, m);
+            chainsDidChange(obj, keyName, m, false);
+            notifyObservers(obj, keyName);
+        }
+
+        var WILL_SEEN, DID_SEEN;
+
+        // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...)
+        function dependentKeysWillChange(obj, depKey, meta) {
+            if (obj.isDestroying) {
+                return;
+            }
+
+            var seen = WILL_SEEN, top = !seen;
+            if (top) {
+                seen = WILL_SEEN = {};
+            }
+            iterDeps(propertyWillChange, obj, depKey, seen, meta);
+            if (top) {
+                WILL_SEEN = null;
+            }
+        }
+
+        // called whenever a property has just changed to update dependent keys
+        function dependentKeysDidChange(obj, depKey, meta) {
+            if (obj.isDestroying) {
+                return;
+            }
+
+            var seen = DID_SEEN, top = !seen;
+            if (top) {
+                seen = DID_SEEN = {};
+            }
+            iterDeps(propertyDidChange, obj, depKey, seen, meta);
+            if (top) {
+                DID_SEEN = null;
+            }
+        }
+
+        function iterDeps(method, obj, depKey, seen, meta) {
+            var guid = guidFor(obj);
+            if (!seen[guid]) 
+                seen[guid] = {};
+            if (seen[guid][depKey]) 
+                return;
+            seen[guid][depKey] = true;
+
+            var deps = meta.deps;
+            deps = deps &amp;&amp; deps[depKey];
+            if (deps) {
+                for (var key in deps) {
+                    var desc = meta.descs[key];
+                    if (desc &amp;&amp; desc._suspended === obj) 
+                        continue;
+                    method(obj, key);
+                }
+            }
+        }
+
+        function chainsWillChange(obj, keyName, m) {
+            if (!(m.hasOwnProperty('chainWatchers') &amp;&amp;
+            m.chainWatchers[keyName])) {
+                return;
+            }
+
+            var nodes = m.chainWatchers[keyName],
+            events = [],
+            i, l;
+
+            for (i = 0, l = nodes.length; i &lt; l; i++) {
+                nodes[i].willChange(events);
+            }
+
+            for (i = 0, l = events.length; i &lt; l; i += 2) {
+                propertyWillChange(events[i], events[i + 1]);
+            }
+        }
+
+        function chainsDidChange(obj, keyName, m, suppressEvents) {
+            if (!(m &amp;&amp; m.hasOwnProperty('chainWatchers') &amp;&amp;
+            m.chainWatchers[keyName])) {
+                return;
+            }
+
+            var nodes = m.chainWatchers[keyName],
+            events = suppressEvents ? null : [],
+            i, l;
+
+            for (i = 0, l = nodes.length; i &lt; l; i++) {
+                nodes[i].didChange(events);
+            }
+
+            if (suppressEvents) {
+                return;
+            }
+
+            for (i = 0, l = events.length; i &lt; l; i += 2) {
+                propertyDidChange(events[i], events[i + 1]);
+            }
+        }
+
+        function overrideChains(obj, keyName, m) {
+            chainsDidChange(obj, keyName, m, true);
+        }
+
+        /**
+              @method beginPropertyChanges
+              @chainable
+              @private
+            */
+        function beginPropertyChanges() {
+            deferred++;
+        }
+
+        /**
+              @method endPropertyChanges
+              @private
+            */
+        function endPropertyChanges() {
+            deferred--;
+            if (deferred &lt;= 0) {
+                beforeObserverSet.clear();
+                observerSet.flush();
+            }
+        }
+
+        /**
+              Make a series of property changes together in an
+              exception-safe way.
+
+              ```javascript
+              Ember.changeProperties(function() {
+                obj1.set('foo', mayBlowUpWhenSet);
+                obj2.set('bar', baz);
+              });
+              ```
+
+              @method changeProperties
+              @param {Function} callback
+              @param [binding]
+            */
+        function changeProperties(cb, binding) {
+            beginPropertyChanges();
+            tryFinally(cb, endPropertyChanges, binding);
+        }
+
+        function notifyBeforeObservers(obj, keyName) {
+            if (obj.isDestroying) {
+                return;
+            }
+
+            var eventName = keyName + ':before', listeners, diff;
+            if (deferred) {
+                listeners = beforeObserverSet.add(obj, keyName, eventName);
+                diff = listenersDiff(obj, eventName, listeners);
+                sendEvent(obj, eventName, [obj, keyName], diff);
+            } else {
+                sendEvent(obj, eventName, [obj, keyName]);
+            }
+        }
+
+        function notifyObservers(obj, keyName) {
+            if (obj.isDestroying) {
+                return;
+            }
+
+            var eventName = keyName + ':change', listeners;
+            if (deferred) {
+                listeners = observerSet.add(obj, keyName, eventName);
+                listenersUnion(obj, eventName, listeners);
+            } else {
+                sendEvent(obj, eventName, [obj, keyName]);
+            }
+        }
+
+        __exports__.propertyWillChange = propertyWillChange;
+        __exports__.propertyDidChange = propertyDidChange;
+        __exports__.overrideChains = overrideChains;
+        __exports__.beginPropertyChanges = beginPropertyChanges;
+        __exports__.endPropertyChanges = endPropertyChanges;
+        __exports__.changeProperties = changeProperties;
+    });
+    define(&quot;ember-metal/property_get&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember-metal
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var META_KEY = __dependency2__.META_KEY;
+        var EmberError = __dependency3__[&quot;default&quot;];
+
+        var get;
+
+        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
+
+        var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.]/;
+        var HAS_THIS = 'this.';
+        var FIRST_KEY = /^([^\.]+)/;
+
+        // ..........................................................
+        // GET AND SET
+        //
+        // If we are on a platform that supports accessors we can use those.
+        // Otherwise simulate accessors by looking up the property directly on the
+        // object.
+
+        /**
+              Gets the value of a property on an object. If the property is computed,
+              the function will be invoked. If the property is not defined but the
+              object implements the `unknownProperty` method then that will be invoked.
+
+              If you plan to run on IE8 and older browsers then you should use this
+              method anytime you want to retrieve a property on an object that you don't
+              know for sure is private. (Properties beginning with an underscore '_'
+              are considered private.)
+
+              On all newer browsers, you only need to use this method to retrieve
+              properties if the property might not be defined on the object and you want
+              to respect the `unknownProperty` handler. Otherwise you can ignore this
+              method.
+
+              Note that if the object itself is `undefined`, this method will throw
+              an error.
+
+              @method get
+              @for Ember
+              @param {Object} obj The object to retrieve from.
+              @param {String} keyName The property key to retrieve
+              @return {Object} the property value or `null`.
+            */
+        var get = function get(obj, keyName) {
+            // Helpers that operate with 'this' within an #each
+            if (keyName === '') {
+                return obj;
+            }
+
+            if (!keyName &amp;&amp; 'string' === typeof obj) {
+                keyName = obj;
+                obj = null;
+            }
+
+            Ember.assert(&quot;Cannot call get with &quot; + keyName + &quot; key.&quot;, !!keyName);
+            Ember.assert(&quot;Cannot call get with '&quot; + keyName + &quot;' on an undefined object.&quot;, obj !== undefined);
+
+            if (obj === null) {
+                return _getPath(obj, keyName);
+            }
+
+            var meta = obj[META_KEY], desc = meta &amp;&amp; meta.descs[keyName], ret;
+
+            if (desc === undefined &amp;&amp; keyName.indexOf('.') !== -1) {
+                return _getPath(obj, keyName);
+            }
+
+            if (desc) {
+                return desc.get(obj, keyName);
+            } else {
+                if (MANDATORY_SETTER &amp;&amp; meta &amp;&amp; meta.watching[keyName] &gt; 0) {
+                    ret = meta.values[keyName];
+                } else {
+                    ret = obj[keyName];
+                }
+
+                if (ret === undefined &amp;&amp;
+                'object' === typeof obj &amp;&amp; !(keyName in obj) &amp;&amp; 'function' === typeof obj.unknownProperty) {
+                    return obj.unknownProperty(keyName);
+                }
+
+                return ret;
+            }
+        };
+
+        // Currently used only by Ember Data tests
+        if (Ember.config.overrideAccessors) {
+            Ember.get = get;
+            Ember.config.overrideAccessors();
+            get = Ember.get;
+        }
+
+        /**
+              Normalizes a target/path pair to reflect that actual target/path that should
+              be observed, etc. This takes into account passing in global property
+              paths (i.e. a path beginning with a captial letter not defined on the
+              target).
+
+              @private
+              @method normalizeTuple
+              @for Ember
+              @param {Object} target The current target. May be `null`.
+              @param {String} path A path on the target or a global property path.
+              @return {Array} a temporary array with the normalized target/path pair.
+            */
+        function normalizeTuple(target, path) {
+            var hasThis = path.indexOf(HAS_THIS) === 0,
+            isGlobal = !hasThis &amp;&amp; IS_GLOBAL_PATH.test(path),
+            key;
+
+            if (!target || isGlobal) 
+                target = Ember.lookup;
+            if (hasThis) 
+                path = path.slice(5);
+
+            if (target === Ember.lookup) {
+                key = path.match(FIRST_KEY)[0];
+                target = get(target, key);
+                path = path.slice(key.length + 1);
+            }
+
+            // must return some kind of path to be valid else other things will break.
+            if (!path || path.length === 0) 
+                throw new EmberError('Path cannot be empty');
+
+            return [ target, path ];
+        }
+
+        function _getPath(root, path) {
+            var hasThis, parts, tuple, idx, len;
+
+            // If there is no root and path is a key name, return that
+            // property from the global object.
+            // E.g. get('Ember') -&gt; Ember
+            if (root === null &amp;&amp; path.indexOf('.') === -1) {
+                return get(Ember.lookup, path);
+            }
+
+            // detect complicated paths and normalize them
+            hasThis = path.indexOf(HAS_THIS) === 0;
+
+            if (!root || hasThis) {
+                tuple = normalizeTuple(root, path);
+                root = tuple[0];
+                path = tuple[1];
+                tuple.length = 0;
+            }
+
+            parts = path.split(&quot;.&quot;);
+            len = parts.length;
+            for (idx = 0; root != null &amp;&amp; idx &lt; len; idx++) {
+                root = get(root, parts[idx], true);
+                if (root &amp;&amp; root.isDestroyed) {
+                    return undefined;
+                }
+            }
+            return root;
+        }
+
+        function getWithDefault(root, key, defaultValue) {
+            var value = get(root, key);
+
+            if (value === undefined) {
+                return defaultValue;
+            }
+            return value;
+        }
+
+        __exports__.getWithDefault = getWithDefault;
+        __exports__[&quot;default&quot;] = get;
+        __exports__.get = get;
+        __exports__.normalizeTuple = normalizeTuple;
+        __exports__._getPath = _getPath;
+    });
+    define(&quot;ember-metal/property_set&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var getPath = __dependency2__._getPath;
+        var META_KEY = __dependency3__.META_KEY;
+        var propertyWillChange = __dependency4__.propertyWillChange;
+        var propertyDidChange = __dependency4__.propertyDidChange;
+        var defineProperty = __dependency5__.defineProperty;
+        var EmberError = __dependency6__[&quot;default&quot;];
+
+        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
+        var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/;
+
+        /**
+              Sets the value of a property on an object, respecting computed properties
+              and notifying observers and other listeners of the change. If the
+              property is not defined but the object implements the `setUnknownProperty`
+              method then that will be invoked as well.
+
+              @method set
+              @for Ember
+              @param {Object} obj The object to modify.
+              @param {String} keyName The property key to set
+              @param {Object} value The value to set
+              @return {Object} the passed value.
+            */
+        var set = function set(obj, keyName, value, tolerant) {
+            if (typeof obj === 'string') {
+                Ember.assert(&quot;Path '&quot; + obj + &quot;' must be global if no obj is given.&quot;, IS_GLOBAL.test(obj));
+                value = keyName;
+                keyName = obj;
+                obj = null;
+            }
+
+            Ember.assert(&quot;Cannot call set with &quot; + keyName + &quot; key.&quot;, !!keyName);
+
+            if (!obj) {
+                return setPath(obj, keyName, value, tolerant);
+            }
+
+            var meta = obj[META_KEY], desc = meta &amp;&amp; meta.descs[keyName],
+            isUnknown, currentValue;
+
+            if (desc === undefined &amp;&amp; keyName.indexOf('.') !== -1) {
+                return setPath(obj, keyName, value, tolerant);
+            }
+
+            Ember.assert(&quot;You need to provide an object and key to `set`.&quot;, !!obj &amp;&amp; keyName !== undefined);
+            Ember.assert('calling set on destroyed object', !obj.isDestroyed);
+
+            if (desc !== undefined) {
+                desc.set(obj, keyName, value);
+            } else {
+
+                if (typeof obj === 'object' &amp;&amp; obj !== null &amp;&amp; value !== undefined &amp;&amp; obj[keyName] === value) {
+                    return value;
+                }
+
+                isUnknown = 'object' === typeof obj &amp;&amp; !(keyName in obj);
+
+                // setUnknownProperty is called if `obj` is an object,
+                // the property does not already exist, and the
+                // `setUnknownProperty` method exists on the object
+                if (isUnknown &amp;&amp; 'function' === typeof obj.setUnknownProperty) {
+                    obj.setUnknownProperty(keyName, value);
+                } else if (meta &amp;&amp; meta.watching[keyName] &gt; 0) {
+                    if (MANDATORY_SETTER) {
+                        currentValue = meta.values[keyName];
+                    } else {
+                        currentValue = obj[keyName];
+                    }
+                    // only trigger a change if the value has changed
+                    if (value !== currentValue) {
+                        propertyWillChange(obj, keyName);
+                        if (MANDATORY_SETTER) {
+                            if ((currentValue === undefined &amp;&amp; !(keyName in obj)) || !obj.propertyIsEnumerable(keyName)) {
+                                defineProperty(obj, keyName, null, value); // setup mandatory setter
+                            } else {
+                                meta.values[keyName] = value;
+                            }
+                        } else {
+                            obj[keyName] = value;
+                        }
+                        propertyDidChange(obj, keyName);
+                    }
+                } else {
+                    obj[keyName] = value;
+                }
+            }
+            return value;
+        };
+
+        // Currently used only by Ember Data tests
+        // ES6TODO: Verify still true
+        if (Ember.config.overrideAccessors) {
+            Ember.set = set;
+            Ember.config.overrideAccessors();
+            set = Ember.set;
+        }
+
+        function setPath(root, path, value, tolerant) {
+            var keyName;
+
+            // get the last part of the path
+            keyName = path.slice(path.lastIndexOf('.') + 1);
+
+            // get the first part of the part
+            path = (path === keyName) ? keyName : path.slice(0, path.length - (keyName.length + 1));
+
+            // unless the path is this, look up the first part to
+            // get the root
+            if (path !== 'this') {
+                root = getPath(root, path);
+            }
+
+            if (!keyName || keyName.length === 0) {
+                throw new EmberError('Property set failed: You passed an empty path');
+            }
+
+            if (!root) {
+                if (tolerant) {
+                    return;
+                } else {
+                    throw new EmberError('Property set failed: object in path &quot;' + path + '&quot; could not be found or was destroyed.');
+                }
+            }
+
+            return set(root, keyName, value);
+        }
+
+        /**
+              Error-tolerant form of `Ember.set`. Will not blow up if any part of the
+              chain is `undefined`, `null`, or destroyed.
+
+              This is primarily used when syncing bindings, which may try to update after
+              an object has been destroyed.
+
+              @method trySet
+              @for Ember
+              @param {Object} obj The object to modify.
+              @param {String} path The property path to set
+              @param {Object} value The value to set
+            */
+        function trySet(root, path, value) {
+            return set(root, path, value, true);
+        }
+
+        __exports__.trySet = trySet;
+        __exports__.set = set;
+    });
+    define(&quot;ember-metal/run_loop&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/property_events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var apply = __dependency2__.apply;
+        var indexOf = __dependency3__.indexOf;
+        var beginPropertyChanges = __dependency4__.beginPropertyChanges;
+        var endPropertyChanges = __dependency4__.endPropertyChanges;
+
+        function onBegin(current) {
+            run.currentRunLoop = current;
+        }
+
+        function onEnd(current, next) {
+            run.currentRunLoop = next;
+        }
+
+        // ES6TODO: should Backburner become es6?
+        var Backburner = requireModule('backburner').Backburner;
+        var backburner = new Backburner(['sync', 'actions', 'destroy'], {
+            sync: {
+                before: beginPropertyChanges,
+                after: endPropertyChanges
+            },
+            defaultQueue: 'actions',
+            onBegin: onBegin,
+            onEnd: onEnd,
+            onErrorTarget: Ember,
+            onErrorMethod: 'onerror'
+        });
+        var slice = [].slice;
+        var concat = [].concat;
+
+        // ..........................................................
+        // run - this is ideally the only public API the dev sees
+        //
+
+        /**
+              Runs the passed target and method inside of a RunLoop, ensuring any
+              deferred actions including bindings and views updates are flushed at the
+              end.
+
+              Normally you should not need to invoke this method yourself. However if
+              you are implementing raw event handlers when interfacing with other
+              libraries or plugins, you should probably wrap all of your code inside this
+              call.
+
+              ```javascript
+              run(function() {
+                // code to be execute within a RunLoop
+              });
+              ```
+
+              @class run
+              @namespace Ember
+              @static
+              @constructor
+              @param {Object} [target] target of method to call
+              @param {Function|String} method Method to invoke.
+                May be a function or a string. If you pass a string
+                then it will be looked up on the passed target.
+              @param {Object} [args*] Any additional arguments you wish to pass to the method.
+              @return {Object} return value from invoking the passed function.
+            */
+        __exports__[&quot;default&quot;] = run;
+        function run() {
+            return apply(backburner, backburner.run, arguments);
+        }
+
+        /**
+              If no run-loop is present, it creates a new one. If a run loop is
+              present it will queue itself to run on the existing run-loops action
+              queue.
+
+              Please note: This is not for normal usage, and should be used sparingly.
+
+              If invoked when not within a run loop:
+
+              ```javascript
+              run.join(function() {
+                // creates a new run-loop
+              });
+              ```
+
+              Alternatively, if called within an existing run loop:
+
+              ```javascript
+              run(function() {
+                // creates a new run-loop
+                run.join(function() {
+                  // joins with the existing run-loop, and queues for invocation on
+                  // the existing run-loops action queue.
+                });
+              });
+              ```
+
+              @method join
+              @namespace Ember
+              @param {Object} [target] target of method to call
+              @param {Function|String} method Method to invoke.
+                May be a function or a string. If you pass a string
+                then it will be looked up on the passed target.
+              @param {Object} [args*] Any additional arguments you wish to pass to the method.
+              @return {Object} Return value from invoking the passed function. Please note,
+              when called within an existing loop, no return value is possible.
+            */
+        run.join = function(target, method /* args */
+        ) {
+            if (!run.currentRunLoop) {
+                return apply(Ember, run, arguments);
+            }
+
+            var args = slice.call(arguments);
+            args.unshift('actions');
+            apply(run, run.schedule, args);
+        };
+
+        /**
+              Provides a useful utility for when integrating with non-Ember libraries
+              that provide asynchronous callbacks.
+
+              Ember utilizes a run-loop to batch and coalesce changes. This works by
+              marking the start and end of Ember-related Javascript execution.
+
+              When using events such as a View's click handler, Ember wraps the event
+              handler in a run-loop, but when integrating with non-Ember libraries this
+              can be tedious.
+
+              For example, the following is rather verbose but is the correct way to combine
+              third-party events and Ember code.
+
+              ```javascript
+              var that = this;
+              jQuery(window).on('resize', function(){
+                run(function(){
+                  that.handleResize();
+                });
+              });
+              ```
+
+              To reduce the boilerplate, the following can be used to construct a
+              run-loop-wrapped callback handler.
+
+              ```javascript
+              jQuery(window).on('resize', run.bind(this, this.handleResize));
+              ```
+
+              @method bind
+              @namespace Ember
+              @param {Object} [target] target of method to call
+              @param {Function|String} method Method to invoke.
+                May be a function or a string. If you pass a string
+                then it will be looked up on the passed target.
+              @param {Object} [args*] Any additional arguments you wish to pass to the method.
+              @return {Object} return value from invoking the passed function. Please note,
+              when called within an existing loop, no return value is possible.
+              @since 1.4.0
+            */
+        run.bind = function(target, method /* args*/
+        ) {
+            var args = slice.call(arguments);
+            return function() {
+                return apply(run, run.join, args.concat(slice.call(arguments)));
+            };
+        };
+
+        run.backburner = backburner;
+        run.currentRunLoop = null;
+        run.queues = backburner.queueNames;
+
+        /**
+              Begins a new RunLoop. Any deferred actions invoked after the begin will
+              be buffered until you invoke a matching call to `run.end()`. This is
+              a lower-level way to use a RunLoop instead of using `run()`.
+
+              ```javascript
+              run.begin();
+              // code to be execute within a RunLoop
+              run.end();
+              ```
+
+              @method begin
+              @return {void}
+            */
+        run.begin = function() {
+            backburner.begin();
+        };
+
+        /**
+              Ends a RunLoop. This must be called sometime after you call
+              `run.begin()` to flush any deferred actions. This is a lower-level way
+              to use a RunLoop instead of using `run()`.
+
+              ```javascript
+              run.begin();
+              // code to be execute within a RunLoop
+              run.end();
+              ```
+
+              @method end
+              @return {void}
+            */
+        run.end = function() {
+            backburner.end();
+        };
+
+        /**
+              Array of named queues. This array determines the order in which queues
+              are flushed at the end of the RunLoop. You can define your own queues by
+              simply adding the queue name to this array. Normally you should not need
+              to inspect or modify this property.
+
+              @property queues
+              @type Array
+              @default ['sync', 'actions', 'destroy']
+            */
+
+        /**
+              Adds the passed target/method and any optional arguments to the named
+              queue to be executed at the end of the RunLoop. If you have not already
+              started a RunLoop when calling this method one will be started for you
+              automatically.
+
+              At the end of a RunLoop, any methods scheduled in this way will be invoked.
+              Methods will be invoked in an order matching the named queues defined in
+              the `run.queues` property.
+
+              ```javascript
+              run.schedule('sync', this, function() {
+                // this will be executed in the first RunLoop queue, when bindings are synced
+                console.log(&quot;scheduled on sync queue&quot;);
+              });
+
+              run.schedule('actions', this, function() {
+                // this will be executed in the 'actions' queue, after bindings have synced.
+                console.log(&quot;scheduled on actions queue&quot;);
+              });
+
+              // Note the functions will be run in order based on the run queues order.
+              // Output would be:
+              //   scheduled on sync queue
+              //   scheduled on actions queue
+              ```
+
+              @method schedule
+              @param {String} queue The name of the queue to schedule against.
+                Default queues are 'sync' and 'actions'
+              @param {Object} [target] target object to use as the context when invoking a method.
+              @param {String|Function} method The method to invoke. If you pass a string it
+                will be resolved on the target object at the time the scheduled item is
+                invoked allowing you to change the target function.
+              @param {Object} [arguments*] Optional arguments to be passed to the queued method.
+              @return {void}
+            */
+        run.schedule = function(queue, target, method) {
+            checkAutoRun();
+            apply(backburner, backburner.schedule, arguments);
+        };
+
+        // Used by global test teardown
+        run.hasScheduledTimers = function() {
+            return backburner.hasTimers();
+        };
+
+        // Used by global test teardown
+        run.cancelTimers = function () {
+            backburner.cancelTimers();
+        };
+
+        /**
+              Immediately flushes any events scheduled in the 'sync' queue. Bindings
+              use this queue so this method is a useful way to immediately force all
+              bindings in the application to sync.
+
+              You should call this method anytime you need any changed state to propagate
+              throughout the app immediately without repainting the UI (which happens
+              in the later 'render' queue added by the `ember-views` package).
+
+              ```javascript
+              run.sync();
+              ```
+
+              @method sync
+              @return {void}
+            */
+        run.sync = function() {
+            if (backburner.currentInstance) {
+                backburner.currentInstance.queues.sync.flush();
+            }
+        };
+
+        /**
+              Invokes the passed target/method and optional arguments after a specified
+              period if time. The last parameter of this method must always be a number
+              of milliseconds.
+
+              You should use this method whenever you need to run some action after a
+              period of time instead of using `setTimeout()`. This method will ensure that
+              items that expire during the same script execution cycle all execute
+              together, which is often more efficient than using a real setTimeout.
+
+              ```javascript
+              run.later(myContext, function() {
+                // code here will execute within a RunLoop in about 500ms with this == myContext
+              }, 500);
+              ```
+
+              @method later
+              @param {Object} [target] target of method to invoke
+              @param {Function|String} method The method to invoke.
+                If you pass a string it will be resolved on the
+                target at the time the method is invoked.
+              @param {Object} [args*] Optional arguments to pass to the timeout.
+              @param {Number} wait Number of milliseconds to wait.
+              @return {String} a string you can use to cancel the timer in
+                `run.cancel` later.
+            */
+        run.later = function(target, method) {
+            return apply(backburner, backburner.later, arguments);
+        };
+
+        /**
+              Schedule a function to run one time during the current RunLoop. This is equivalent
+              to calling `scheduleOnce` with the &quot;actions&quot; queue.
+
+              @method once
+              @param {Object} [target] The target of the method to invoke.
+              @param {Function|String} method The method to invoke.
+                If you pass a string it will be resolved on the
+                target at the time the method is invoked.
+              @param {Object} [args*] Optional arguments to pass to the timeout.
+              @return {Object} Timer information for use in cancelling, see `run.cancel`.
+            */
+        run.once = function(target, method) {
+            checkAutoRun();
+            var args = slice.call(arguments);
+            args.unshift('actions');
+            return apply(backburner, backburner.scheduleOnce, args);
+        };
+
+        /**
+              Schedules a function to run one time in a given queue of the current RunLoop.
+              Calling this method with the same queue/target/method combination will have
+              no effect (past the initial call).
+
+              Note that although you can pass optional arguments these will not be
+              considered when looking for duplicates. New arguments will replace previous
+              calls.
+
+              ```javascript
+              run(function() {
+                var sayHi = function() { console.log('hi'); }
+                run.scheduleOnce('afterRender', myContext, sayHi);
+                run.scheduleOnce('afterRender', myContext, sayHi);
+                // sayHi will only be executed once, in the afterRender queue of the RunLoop
+              });
+              ```
+
+              Also note that passing an anonymous function to `run.scheduleOnce` will
+              not prevent additional calls with an identical anonymous function from
+              scheduling the items multiple times, e.g.:
+
+              ```javascript
+              function scheduleIt() {
+                run.scheduleOnce('actions', myContext, function() { console.log(&quot;Closure&quot;); });
+              }
+              scheduleIt();
+              scheduleIt();
+              // &quot;Closure&quot; will print twice, even though we're using `run.scheduleOnce`,
+              // because the function we pass to it is anonymous and won't match the
+              // previously scheduled operation.
+              ```
+
+              Available queues, and their order, can be found at `run.queues`
+
+              @method scheduleOnce
+              @param {String} [queue] The name of the queue to schedule against. Default queues are 'sync' and 'actions'.
+              @param {Object} [target] The target of the method to invoke.
+              @param {Function|String} method The method to invoke.
+                If you pass a string it will be resolved on the
+                target at the time the method is invoked.
+              @param {Object} [args*] Optional arguments to pass to the timeout.
+              @return {Object} Timer information for use in cancelling, see `run.cancel`.
+            */
+        run.scheduleOnce = function(queue, target, method) {
+            checkAutoRun();
+            return apply(backburner, backburner.scheduleOnce, arguments);
+        };
+
+        /**
+              Schedules an item to run from within a separate run loop, after
+              control has been returned to the system. This is equivalent to calling
+              `run.later` with a wait time of 1ms.
+
+              ```javascript
+              run.next(myContext, function() {
+                // code to be executed in the next run loop,
+                // which will be scheduled after the current one
+              });
+              ```
+
+              Multiple operations scheduled with `run.next` will coalesce
+              into the same later run loop, along with any other operations
+              scheduled by `run.later` that expire right around the same
+              time that `run.next` operations will fire.
+
+              Note that there are often alternatives to using `run.next`.
+              For instance, if you'd like to schedule an operation to happen
+              after all DOM element operations have completed within the current
+              run loop, you can make use of the `afterRender` run loop queue (added
+              by the `ember-views` package, along with the preceding `render` queue
+              where all the DOM element operations happen). Example:
+
+              ```javascript
+              App.MyCollectionView = Ember.CollectionView.extend({
+                didInsertElement: function() {
+                  run.scheduleOnce('afterRender', this, 'processChildElements');
+                },
+                processChildElements: function() {
+                  // ... do something with collectionView's child view
+                  // elements after they've finished rendering, which
+                  // can't be done within the CollectionView's
+                  // `didInsertElement` hook because that gets run
+                  // before the child elements have been added to the DOM.
+                }
+              });
+              ```
+
+              One benefit of the above approach compared to using `run.next` is
+              that you will be able to perform DOM/CSS operations before unprocessed
+              elements are rendered to the screen, which may prevent flickering or
+              other artifacts caused by delaying processing until after rendering.
+
+              The other major benefit to the above approach is that `run.next`
+              introduces an element of non-determinism, which can make things much
+              harder to test, due to its reliance on `setTimeout`; it's much harder
+              to guarantee the order of scheduled operations when they are scheduled
+              outside of the current run loop, i.e. with `run.next`.
+
+              @method next
+              @param {Object} [target] target of method to invoke
+              @param {Function|String} method The method to invoke.
+                If you pass a string it will be resolved on the
+                target at the time the method is invoked.
+              @param {Object} [args*] Optional arguments to pass to the timeout.
+              @return {Object} Timer information for use in cancelling, see `run.cancel`.
+            */
+        run.next = function() {
+            var args = slice.call(arguments);
+            args.push(1);
+            return apply(backburner, backburner.later, args);
+        };
+
+        /**
+              Cancels a scheduled item. Must be a value returned by `run.later()`,
+              `run.once()`, `run.next()`, `run.debounce()`, or
+              `run.throttle()`.
+
+              ```javascript
+              var runNext = run.next(myContext, function() {
+                // will not be executed
+              });
+              run.cancel(runNext);
+
+              var runLater = run.later(myContext, function() {
+                // will not be executed
+              }, 500);
+              run.cancel(runLater);
+
+              var runOnce = run.once(myContext, function() {
+                // will not be executed
+              });
+              run.cancel(runOnce);
+
+              var throttle = run.throttle(myContext, function() {
+                // will not be executed
+              }, 1, false);
+              run.cancel(throttle);
+
+              var debounce = run.debounce(myContext, function() {
+                // will not be executed
+              }, 1);
+              run.cancel(debounce);
+
+              var debounceImmediate = run.debounce(myContext, function() {
+                // will be executed since we passed in true (immediate)
+              }, 100, true);
+              // the 100ms delay until this method can be called again will be cancelled
+              run.cancel(debounceImmediate);
+              ```
+
+              @method cancel
+              @param {Object} timer Timer object to cancel
+              @return {Boolean} true if cancelled or false/undefined if it wasn't found
+            */
+        run.cancel = function(timer) {
+            return backburner.cancel(timer);
+        };
+
+        /**
+              Delay calling the target method until the debounce period has elapsed
+              with no additional debounce calls. If `debounce` is called again before
+              the specified time has elapsed, the timer is reset and the entire period
+              must pass again before the target method is called.
+
+              This method should be used when an event may be called multiple times
+              but the action should only be called once when the event is done firing.
+              A common example is for scroll events where you only want updates to
+              happen once scrolling has ceased.
+
+              ```javascript
+                var myFunc = function() { console.log(this.name + ' ran.'); };
+                var myContext = {name: 'debounce'};
+
+                run.debounce(myContext, myFunc, 150);
+
+                // less than 150ms passes
+
+                run.debounce(myContext, myFunc, 150);
+
+                // 150ms passes
+                // myFunc is invoked with context myContext
+                // console logs 'debounce ran.' one time.
+              ```
+
+              Immediate allows you to run the function immediately, but debounce
+              other calls for this function until the wait time has elapsed. If
+              `debounce` is called again before the specified time has elapsed,
+              the timer is reset and the entire period must pass again before
+              the method can be called again.
+
+              ```javascript
+                var myFunc = function() { console.log(this.name + ' ran.'); };
+                var myContext = {name: 'debounce'};
+
+                run.debounce(myContext, myFunc, 150, true);
+
+                // console logs 'debounce ran.' one time immediately.
+                // 100ms passes
+
+                run.debounce(myContext, myFunc, 150, true);
+
+                // 150ms passes and nothing else is logged to the console and
+                // the debouncee is no longer being watched
+
+                run.debounce(myContext, myFunc, 150, true);
+
+                // console logs 'debounce ran.' one time immediately.
+                // 150ms passes and nothing else is logged to the console and
+                // the debouncee is no longer being watched
+
+              ```
+
+              @method debounce
+              @param {Object} [target] target of method to invoke
+              @param {Function|String} method The method to invoke.
+                May be a function or a string. If you pass a string
+                then it will be looked up on the passed target.
+              @param {Object} [args*] Optional arguments to pass to the timeout.
+              @param {Number} wait Number of milliseconds to wait.
+              @param {Boolean} immediate Trigger the function on the leading instead
+                of the trailing edge of the wait interval. Defaults to false.
+              @return {Array} Timer information for use in cancelling, see `run.cancel`.
+            */
+        run.debounce = function() {
+            return apply(backburner, backburner.debounce, arguments);
+        };
+
+        /**
+              Ensure that the target method is never called more frequently than
+              the specified spacing period. The target method is called immediately.
+
+              ```javascript
+                var myFunc = function() { console.log(this.name + ' ran.'); };
+                var myContext = {name: 'throttle'};
+
+                run.throttle(myContext, myFunc, 150);
+                // myFunc is invoked with context myContext
+                // console logs 'throttle ran.'
+
+                // 50ms passes
+                run.throttle(myContext, myFunc, 150);
+
+                // 50ms passes
+                run.throttle(myContext, myFunc, 150);
+
+                // 150ms passes
+                run.throttle(myContext, myFunc, 150);
+                // myFunc is invoked with context myContext
+                // console logs 'throttle ran.'
+              ```
+
+              @method throttle
+              @param {Object} [target] target of method to invoke
+              @param {Function|String} method The method to invoke.
+                May be a function or a string. If you pass a string
+                then it will be looked up on the passed target.
+              @param {Object} [args*] Optional arguments to pass to the timeout.
+              @param {Number} spacing Number of milliseconds to space out requests.
+              @param {Boolean} immediate Trigger the function on the leading instead
+                of the trailing edge of the wait interval. Defaults to true.
+              @return {Array} Timer information for use in cancelling, see `run.cancel`.
+            */
+        run.throttle = function() {
+            return apply(backburner, backburner.throttle, arguments);
+        };
+
+        // Make sure it's not an autorun during testing
+        function checkAutoRun() {
+            if (!run.currentRunLoop) {
+                Ember.assert(&quot;You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an run&quot;, !Ember.testing);
+            }
+        }
+
+        /**
+              Add a new named queue after the specified queue.
+
+              The queue to add will only be added once.
+
+              @method _addQueue
+              @param {String} name the name of the queue to add.
+              @param {String} after the name of the queue to add after.
+              @private
+            */
+        run._addQueue = function(name, after) {
+            if (indexOf.call(run.queues, name) === -1) {
+                run.queues.splice(indexOf.call(run.queues, after) + 1, 0, name);
+            }
+        };
+    });
+    define(&quot;ember-metal/set_properties&quot;,
+    [&quot;ember-metal/property_events&quot;, &quot;ember-metal/property_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var changeProperties = __dependency1__.changeProperties;
+        var set = __dependency2__.set;
+
+        /**
+              Set a list of properties on an object. These properties are set inside
+              a single `beginPropertyChanges` and `endPropertyChanges` batch, so
+              observers will be buffered.
+
+              ```javascript
+              var anObject = Ember.Object.create();
+
+              anObject.setProperties({
+                firstName: 'Stanley',
+                lastName: 'Stuart',
+                age: 21
+              });
+              ```
+
+              @method setProperties
+              @param self
+              @param {Object} hash
+              @return self
+            */
+        __exports__[&quot;default&quot;] = function setProperties(self, hash) {
+            changeProperties(function() {
+                for (var prop in hash) {
+                    if (hash.hasOwnProperty(prop)) {
+                        set(self, prop, hash[prop]);
+                    }
+                }
+            });
+            return self;
+        }
+    });
+    define(&quot;ember-metal/utils&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/array&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var platform = __dependency2__.platform;
+        var create = __dependency2__.create;
+
+        var forEach = __dependency3__.forEach;
+
+        /**
+            @module ember-metal
+            */
+
+        /**
+              Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from
+              jQuery master. We'll just bootstrap our own uuid now.
+
+              @private
+              @return {Number} the uuid
+            */
+        var _uuid = 0;
+
+        function uuid() {
+            return ++_uuid;
+        }
+
+        __exports__.uuid = uuid; /**
+              Prefix used for guids through out Ember.
+              @private
+              @property GUID_PREFIX
+              @for Ember
+              @type String
+              @final
+            */
+        var GUID_PREFIX = 'ember';
+
+        var o_defineProperty = platform.defineProperty;
+        var o_create = create;
+        // Used for guid generation...
+        var numberCache = [];
+        var stringCache = {};
+        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
+
+        /**
+              A unique key used to assign guids and other private metadata to objects.
+              If you inspect an object in your browser debugger you will often see these.
+              They can be safely ignored.
+
+              On browsers that support it, these properties are added with enumeration
+              disabled so they won't show up when you iterate over your properties.
+
+              @private
+              @property GUID_KEY
+              @for Ember
+              @type String
+              @final
+            */
+        var GUID_KEY = '__ember' + ( + new Date());
+
+        var GUID_DESC = {
+            writable: false,
+            configurable: false,
+            enumerable: false,
+            value: null
+        };
+
+        /**
+              Generates a new guid, optionally saving the guid to the object that you
+              pass in. You will rarely need to use this method. Instead you should
+              call `Ember.guidFor(obj)`, which return an existing guid if available.
+
+              @private
+              @method generateGuid
+              @for Ember
+              @param {Object} [obj] Object the guid will be used for. If passed in, the guid will
+                be saved on the object and reused whenever you pass the same object
+                again.
+
+                If no object is passed, just generate a new guid.
+              @param {String} [prefix] Prefix to place in front of the guid. Useful when you want to
+                separate the guid into separate namespaces.
+              @return {String} the guid
+            */
+        function generateGuid(obj, prefix) {
+            if (!prefix) 
+                prefix = GUID_PREFIX;
+            var ret = (prefix + uuid());
+            if (obj) {
+                if (obj[GUID_KEY] === null) {
+                    obj[GUID_KEY] = ret;
+                } else {
+                    GUID_DESC.value = ret;
+                    o_defineProperty(obj, GUID_KEY, GUID_DESC);
+                }
+            }
+            return ret;
+        }
+
+        __exports__.generateGuid = generateGuid; /**
+              Returns a unique id for the object. If the object does not yet have a guid,
+              one will be assigned to it. You can call this on any object,
+              `Ember.Object`-based or not, but be aware that it will add a `_guid`
+              property.
+
+              You can also use this method on DOM Element objects.
+
+              @private
+              @method guidFor
+              @for Ember
+              @param {Object} obj any object, string, number, Element, or primitive
+              @return {String} the unique guid for this instance.
+            */
+        function guidFor(obj) {
+
+            // special cases where we don't want to add a key to object
+            if (obj === undefined) 
+                return &quot;(undefined)&quot;;
+            if (obj === null) 
+                return &quot;(null)&quot;;
+
+            var ret;
+            var type = typeof obj;
+
+            // Don't allow prototype changes to String etc. to change the guidFor
+            switch (type) {
+            case 'number':
+                ret = numberCache[obj];
+                if (!ret) 
+                    ret = numberCache[obj] = 'nu' + obj;
+                return ret;
+
+            case 'string':
+                ret = stringCache[obj];
+                if (!ret) 
+                    ret = stringCache[obj] = 'st' + uuid();
+                return ret;
+
+            case 'boolean':
+                return obj ? '(true)' : '(false)';
+
+            default:
+                if (obj[GUID_KEY]) 
+                    return obj[GUID_KEY];
+                if (obj === Object) 
+                    return '(Object)';
+                if (obj === Array) 
+                    return '(Array)';
+                ret = 'ember' + uuid();
+
+                if (obj[GUID_KEY] === null) {
+                    obj[GUID_KEY] = ret;
+                } else {
+                    GUID_DESC.value = ret;
+                    o_defineProperty(obj, GUID_KEY, GUID_DESC);
+                }
+                return ret;
+            }
+        }
+
+        __exports__.guidFor = guidFor; // ..........................................................
+        // META
+        //
+
+        var META_DESC = {
+            writable: true,
+            configurable: false,
+            enumerable: false,
+            value: null
+        };
+
+        /**
+              The key used to store meta information on object for property observing.
+
+              @property META_KEY
+              @for Ember
+              @private
+              @final
+              @type String
+            */
+        var META_KEY = '__ember_meta__';
+
+        var isDefinePropertySimulated = platform.defineProperty.isSimulated;
+
+        function Meta(obj) {
+            this.descs = {};
+            this.watching = {};
+            this.cache = {};
+            this.cacheMeta = {};
+            this.source = obj;
+        }
+
+        Meta.prototype = {
+            descs: null,
+            deps: null,
+            watching: null,
+            listeners: null,
+            cache: null,
+            cacheMeta: null,
+            source: null,
+            mixins: null,
+            bindings: null,
+            chains: null,
+            chainWatchers: null,
+            values: null,
+            proto: null
+        };
+
+        if (isDefinePropertySimulated) {
+            // on platforms that don't support enumerable false
+            // make meta fail jQuery.isPlainObject() to hide from
+            // jQuery.extend() by having a property that fails
+            // hasOwnProperty check.
+            Meta.prototype.__preventPlainObject__ = true;
+
+            // Without non-enumerable properties, meta objects will be output in JSON
+            // unless explicitly suppressed
+            Meta.prototype.toJSON = function () {};
+        }
+
+        // Placeholder for non-writable metas.
+        var EMPTY_META = new Meta(null);
+
+        if (MANDATORY_SETTER) {
+            EMPTY_META.values = {};
+        }
+
+        /**
+              Retrieves the meta hash for an object. If `writable` is true ensures the
+              hash is writable for this object as well.
+
+              The meta object contains information about computed property descriptors as
+              well as any watched properties and other information. You generally will
+              not access this information directly but instead work with higher level
+              methods that manipulate this hash indirectly.
+
+              @method meta
+              @for Ember
+              @private
+
+              @param {Object} obj The object to retrieve meta for
+              @param {Boolean} [writable=true] Pass `false` if you do not intend to modify
+                the meta hash, allowing the method to avoid making an unnecessary copy.
+              @return {Object} the meta hash for an object
+            */
+        function meta(obj, writable) {
+
+            var ret = obj[META_KEY];
+            if (writable === false) 
+                return ret || EMPTY_META;
+
+            if (!ret) {
+                if (!isDefinePropertySimulated) 
+                    o_defineProperty(obj, META_KEY, META_DESC);
+
+                ret = new Meta(obj);
+
+                if (MANDATORY_SETTER) {
+                    ret.values = {};
+                }
+
+                obj[META_KEY] = ret;
+
+                // make sure we don't accidentally try to create constructor like desc
+                ret.descs.constructor = null;
+
+            } else if (ret.source !== obj) {
+                if (!isDefinePropertySimulated) 
+                    o_defineProperty(obj, META_KEY, META_DESC);
+
+                    ret = o_create(ret);
+                    ret.descs = o_create(ret.descs);
+                    ret.watching = o_create(ret.watching);
+                    ret.cache = {};
+                    ret.cacheMeta = {};
+                    ret.source = obj;
+
+                    if (MANDATORY_SETTER) {
+                        ret.values = o_create(ret.values);
+                    }
+
+                    obj[META_KEY] = ret;
+            }
+            return ret;
+        }
+
+        function getMeta(obj, property) {
+            var _meta = meta(obj, false);
+            return _meta[property];
+        }
+
+        __exports__.getMeta = getMeta;
+        function setMeta(obj, property, value) {
+            var _meta = meta(obj, true);
+            _meta[property] = value;
+            return value;
+        }
+
+        __exports__.setMeta = setMeta; /**
+              @deprecated
+              @private
+
+              In order to store defaults for a class, a prototype may need to create
+              a default meta object, which will be inherited by any objects instantiated
+              from the class's constructor.
+
+              However, the properties of that meta object are only shallow-cloned,
+              so if a property is a hash (like the event system's `listeners` hash),
+              it will by default be shared across all instances of that class.
+
+              This method allows extensions to deeply clone a series of nested hashes or
+              other complex objects. For instance, the event system might pass
+              `['listeners', 'foo:change', 'ember157']` to `prepareMetaPath`, which will
+              walk down the keys provided.
+
+              For each key, if the key does not exist, it is created. If it already
+              exists and it was inherited from its constructor, the constructor's
+              key is cloned.
+
+              You can also pass false for `writable`, which will simply return
+              undefined if `prepareMetaPath` discovers any part of the path that
+              shared or undefined.
+
+              @method metaPath
+              @for Ember
+              @param {Object} obj The object whose meta we are examining
+              @param {Array} path An array of keys to walk down
+              @param {Boolean} writable whether or not to create a new meta
+                (or meta property) if one does not already exist or if it's
+                shared with its constructor
+            */
+        function metaPath(obj, path, writable) {
+            Ember.deprecate(&quot;Ember.metaPath is deprecated and will be removed from future releases.&quot;);
+            var _meta = meta(obj, writable), keyName, value;
+
+            for (var i = 0, l = path.length; i &lt; l; i++) {
+                keyName = path[i];
+                value = _meta[keyName];
+
+                if (!value) {
+                    if (!writable) {
+                        return undefined;
+                    }
+                    value = _meta[keyName] = {
+                        __ember_source__: obj 
+                    };
+                } else if (value.__ember_source__ !== obj) {
+                    if (!writable) {
+                        return undefined;
+                    }
+                    value = _meta[keyName] = o_create(value);
+                    value.__ember_source__ = obj;
+                }
+
+                _meta = value;
+            }
+
+            return value;
+        }
+
+        __exports__.metaPath = metaPath; /**
+              Wraps the passed function so that `this._super` will point to the superFunc
+              when the function is invoked. This is the primitive we use to implement
+              calls to super.
+
+              @private
+              @method wrap
+              @for Ember
+              @param {Function} func The function to call
+              @param {Function} superFunc The super function.
+              @return {Function} wrapped function.
+            */
+        function wrap(func, superFunc) {
+            function superWrapper() {
+                var ret, sup = this &amp;&amp; this.__nextSuper;
+                if (this) {
+                    this.__nextSuper = superFunc;
+                }
+                ret = apply(this, func, arguments);
+                if (this) {
+                    this.__nextSuper = sup;
+                }
+                return ret;
+            }
+
+            superWrapper.wrappedFunction = func;
+            superWrapper.wrappedFunction.__ember_arity__ = func.length;
+            superWrapper.__ember_observes__ = func.__ember_observes__;
+            superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
+            superWrapper.__ember_listens__ = func.__ember_listens__;
+
+            return superWrapper;
+        }
+
+        __exports__.wrap = wrap;
+        var EmberArray;
+
+        /**
+              Returns true if the passed object is an array or Array-like.
+
+              Ember Array Protocol:
+
+                - the object has an objectAt property
+                - the object is a native Array
+                - the object is an Object, and has a length property
+
+              Unlike `Ember.typeOf` this method returns true even if the passed object is
+              not formally array but appears to be array-like (i.e. implements `Ember.Array`)
+
+              ```javascript
+              Ember.isArray();                                          // false
+              Ember.isArray([]);                                        // true
+              Ember.isArray(Ember.ArrayProxy.create({ content: [] }));  // true
+              ```
+
+              @method isArray
+              @for Ember
+              @param {Object} obj The object to test
+              @return {Boolean} true if the passed object is an array or Array-like
+            */
+        // ES6TODO: Move up to runtime? This is only use in ember-metal by concatenatedProperties
+        function isArray(obj) {
+            var modulePath, type;
+
+            if (typeof EmberArray === &quot;undefined&quot;) {
+                modulePath = 'ember-runtime/mixins/array';
+                if (Ember.__loader.registry[modulePath]) {
+                    EmberArray = Ember.__loader.require(modulePath)['default'];
+                }
+            }
+
+            if (!obj || obj.setInterval) {
+                return false;
+            }
+            if (Array.isArray &amp;&amp; Array.isArray(obj)) {
+                return true;
+            }
+            if (EmberArray &amp;&amp; EmberArray.detect(obj)) {
+                return true;
+            }
+
+            type = typeOf(obj);
+            if ('array' === type) {
+                return true;
+            }
+            if ((obj.length !== undefined) &amp;&amp; 'object' === type) {
+                return true;
+            }
+            return false;
+        }
+
+        /**
+              Forces the passed object to be part of an array. If the object is already
+              an array or array-like, returns the object. Otherwise adds the object to
+              an array. If obj is `null` or `undefined`, returns an empty array.
+
+              ```javascript
+              Ember.makeArray();            // []
+              Ember.makeArray(null);        // []
+              Ember.makeArray(undefined);   // []
+              Ember.makeArray('lindsay');   // ['lindsay']
+              Ember.makeArray([1, 2, 42]);  // [1, 2, 42]
+
+              var controller = Ember.ArrayProxy.create({ content: [] });
+
+              Ember.makeArray(controller) === controller;  // true
+              ```
+
+              @method makeArray
+              @for Ember
+              @param {Object} obj the object
+              @return {Array}
+            */
+        function makeArray(obj) {
+            if (obj === null || obj === undefined) {
+                return [];
+            }
+            return isArray(obj) ? obj : [obj];
+        }
+
+        __exports__.makeArray = makeArray; /**
+              Checks to see if the `methodName` exists on the `obj`.
+
+              ```javascript
+              var foo = { bar: Ember.K, baz: null };
+
+              Ember.canInvoke(foo, 'bar'); // true
+              Ember.canInvoke(foo, 'baz'); // false
+              Ember.canInvoke(foo, 'bat'); // false
+              ```
+
+              @method canInvoke
+              @for Ember
+              @param {Object} obj The object to check for the method
+              @param {String} methodName The method name to check for
+              @return {Boolean}
+            */
+        function canInvoke(obj, methodName) {
+            return !!(obj &amp;&amp; typeof obj[methodName] === 'function');
+        }
+
+        /**
+              Checks to see if the `methodName` exists on the `obj`,
+              and if it does, invokes it with the arguments passed.
+
+              ```javascript
+              var d = new Date('03/15/2013');
+
+              Ember.tryInvoke(d, 'getTime');              // 1363320000000
+              Ember.tryInvoke(d, 'setFullYear', [2014]);  // 1394856000000
+              Ember.tryInvoke(d, 'noSuchMethod', [2014]); // undefined
+              ```
+
+              @method tryInvoke
+              @for Ember
+              @param {Object} obj The object to check for the method
+              @param {String} methodName The method name to check for
+              @param {Array} [args] The arguments to pass to the method
+              @return {*} the return value of the invoked method or undefined if it cannot be invoked
+            */
+        function tryInvoke(obj, methodName, args) {
+            if (canInvoke(obj, methodName)) {
+                return args ? applyStr(obj, methodName, args) : applyStr(obj, methodName);
+            }
+        }
+
+        __exports__.tryInvoke = tryInvoke; // https://github.com/emberjs/ember.js/pull/1617
+        var needsFinallyFix = (function() {
+            var count = 0;
+            try {
+                try {} finally {
+                    count++;
+                    throw new Error('needsFinallyFixTest');
+                }
+            } catch (e) {}
+
+            return count !== 1;
+        })();
+
+        /**
+              Provides try/finally functionality, while working
+              around Safari's double finally bug.
+
+              ```javascript
+              var tryable = function() {
+                someResource.lock();
+                runCallback(); // May throw error.
+              };
+
+              var finalizer = function() {
+                someResource.unlock();
+              };
+
+              Ember.tryFinally(tryable, finalizer);
+              ```
+
+              @method tryFinally
+              @for Ember
+              @param {Function} tryable The function to run the try callback
+              @param {Function} finalizer The function to run the finally callback
+              @param {Object} [binding] The optional calling object. Defaults to 'this'
+              @return {*} The return value is the that of the finalizer,
+              unless that value is undefined, in which case it is the return value
+              of the tryable
+            */
+
+        var tryFinally;
+        if (needsFinallyFix) {
+            tryFinally = function(tryable, finalizer, binding) {
+                var result, finalResult, finalError;
+
+                binding = binding || this;
+
+                try {
+                    result = tryable.call(binding);
+                } finally {
+                    try {
+                        finalResult = finalizer.call(binding);
+                    } catch (e) {
+                        finalError = e;
+                    }
+                }
+
+                if (finalError) {
+                    throw finalError;
+                }
+
+                return (finalResult === undefined) ? result : finalResult;
+            };
+        } else {
+            tryFinally = function(tryable, finalizer, binding) {
+                var result, finalResult;
+
+                binding = binding || this;
+
+                try {
+                    result = tryable.call(binding);
+                } finally {
+                    finalResult = finalizer.call(binding);
+                }
+
+                return (finalResult === undefined) ? result : finalResult;
+            };
+        }
+
+        /**
+              Provides try/catch/finally functionality, while working
+              around Safari's double finally bug.
+
+              ```javascript
+              var tryable = function() {
+                for (i = 0, l = listeners.length; i &lt; l; i++) {
+                  listener = listeners[i];
+                  beforeValues[i] = listener.before(name, time(), payload);
+                }
+
+                return callback.call(binding);
+              };
+
+              var catchable = function(e) {
+                payload = payload || {};
+                payload.exception = e;
+              };
+
+              var finalizer = function() {
+                for (i = 0, l = listeners.length; i &lt; l; i++) {
+                  listener = listeners[i];
+                  listener.after(name, time(), payload, beforeValues[i]);
+                }
+              };
+
+              Ember.tryCatchFinally(tryable, catchable, finalizer);
+              ```
+
+              @method tryCatchFinally
+              @for Ember
+              @param {Function} tryable The function to run the try callback
+              @param {Function} catchable The function to run the catchable callback
+              @param {Function} finalizer The function to run the finally callback
+              @param {Object} [binding] The optional calling object. Defaults to 'this'
+              @return {*} The return value is the that of the finalizer,
+              unless that value is undefined, in which case it is the return value
+              of the tryable.
+            */
+        var tryCatchFinally;
+        if (needsFinallyFix) {
+            tryCatchFinally = function(tryable, catchable, finalizer, binding) {
+                var result, finalResult, finalError;
+
+                binding = binding || this;
+
+                try {
+                    result = tryable.call(binding);
+                } catch (error) {
+                    result = catchable.call(binding, error);
+                } finally {
+                    try {
+                        finalResult = finalizer.call(binding);
+                    } catch (e) {
+                        finalError = e;
+                    }
+                }
+
+                if (finalError) {
+                    throw finalError;
+                }
+
+                return (finalResult === undefined) ? result : finalResult;
+            };
+        } else {
+            tryCatchFinally = function(tryable, catchable, finalizer, binding) {
+                var result, finalResult;
+
+                binding = binding || this;
+
+                try {
+                    result = tryable.call(binding);
+                } catch (error) {
+                    result = catchable.call(binding, error);
+                } finally {
+                    finalResult = finalizer.call(binding);
+                }
+
+                return (finalResult === undefined) ? result : finalResult;
+            };
+        }
+
+        // ........................................
+        // TYPING &amp; ARRAY MESSAGING
+        //
+
+        var TYPE_MAP = {};
+        var t = &quot;Boolean Number String Function Array Date RegExp Object&quot;.split(&quot; &quot;);
+        forEach.call(t, function(name) {
+            TYPE_MAP[ &quot;[object &quot; + name + &quot;]&quot; ] = name.toLowerCase();
+        });
+
+        var toString = Object.prototype.toString;
+
+        var EmberObject;
+
+        /**
+              Returns a consistent type for the passed item.
+
+              Use this instead of the built-in `typeof` to get the type of an item.
+              It will return the same result across all browsers and includes a bit
+              more detail. Here is what will be returned:
+
+                  | Return Value  | Meaning                                              |
+                  |---------------|------------------------------------------------------|
+                  | 'string'      | String primitive or String object.                   |
+                  | 'number'      | Number primitive or Number object.                   |
+                  | 'boolean'     | Boolean primitive or Boolean object.                 |
+                  | 'null'        | Null value                                           |
+                  | 'undefined'   | Undefined value                                      |
+                  | 'function'    | A function                                           |
+                  | 'array'       | An instance of Array                                 |
+                  | 'regexp'      | An instance of RegExp                                |
+                  | 'date'        | An instance of Date                                  |
+                  | 'class'       | An Ember class (created using Ember.Object.extend()) |
+                  | 'instance'    | An Ember object instance                             |
+                  | 'error'       | An instance of the Error object                      |
+                  | 'object'      | A JavaScript object not inheriting from Ember.Object |
+
+              Examples:
+
+              ```javascript
+              Ember.typeOf();                       // 'undefined'
+              Ember.typeOf(null);                   // 'null'
+              Ember.typeOf(undefined);              // 'undefined'
+              Ember.typeOf('michael');              // 'string'
+              Ember.typeOf(new String('michael'));  // 'string'
+              Ember.typeOf(101);                    // 'number'
+              Ember.typeOf(new Number(101));        // 'number'
+              Ember.typeOf(true);                   // 'boolean'
+              Ember.typeOf(new Boolean(true));      // 'boolean'
+              Ember.typeOf(Ember.makeArray);        // 'function'
+              Ember.typeOf([1, 2, 90]);             // 'array'
+              Ember.typeOf(/abc/);                  // 'regexp'
+              Ember.typeOf(new Date());             // 'date'
+              Ember.typeOf(Ember.Object.extend());  // 'class'
+              Ember.typeOf(Ember.Object.create());  // 'instance'
+              Ember.typeOf(new Error('teamocil'));  // 'error'
+
+              // 'normal' JavaScript object
+              Ember.typeOf({ a: 'b' });             // 'object'
+              ```
+
+              @method typeOf
+              @for Ember
+              @param {Object} item the item to check
+              @return {String} the type
+            */
+        function typeOf(item) {
+            var ret, modulePath;
+
+            // ES6TODO: Depends on Ember.Object which is defined in runtime.
+            if (typeof EmberObject === &quot;undefined&quot;) {
+                modulePath = 'ember-runtime/system/object';
+                if (Ember.__loader.registry[modulePath]) {
+                    EmberObject = Ember.__loader.require(modulePath)['default'];
+                }
+            }
+
+            ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object';
+
+            if (ret === 'function') {
+                if (EmberObject &amp;&amp; EmberObject.detect(item)) 
+                    ret = 'class';
+            } else if (ret === 'object') {
+                if (item instanceof Error) 
+                    ret = 'error';
+                else if (EmberObject &amp;&amp; item instanceof EmberObject) 
+                    ret = 'instance';
+                else if (item instanceof Date) 
+                    ret = 'date';
+            }
+
+            return ret;
+        }
+
+        /**
+              Convenience method to inspect an object. This method will attempt to
+              convert the object into a useful string description.
+
+              It is a pretty simple implementation. If you want something more robust,
+              use something like JSDump: https://github.com/NV/jsDump
+
+              @method inspect
+              @for Ember
+              @param {Object} obj The object you want to inspect.
+              @return {String} A description of the object
+              @since 1.4.0
+            */
+        function inspect(obj) {
+            var type = typeOf(obj);
+            if (type === 'array') {
+                return '[' + obj + ']';
+            }
+            if (type !== 'object') {
+                return obj + '';
+            }
+
+            var v, ret = [];
+            for (var key in obj) {
+                if (obj.hasOwnProperty(key)) {
+                    v = obj[key];
+                    if (v === 'toString') {
+                        continue;
+                    }
+                    // ignore useless items
+                    if (typeOf(v) === 'function') {
+                        v = &quot;function() { ... }&quot;;
+                    }
+                    ret.push(key + &quot;: &quot; + v);
+                }
+            }
+            return &quot;{&quot; + ret.join(&quot;, &quot;) + &quot;}&quot;;
+        }
+
+        __exports__.inspect = inspect; // The following functions are intentionally minified to keep the functions
+        // below Chrome's function body size inlining limit of 600 chars.
+
+        function apply(t /* target */
+        , m /* method */
+        , a /* args */
+        ) {
+            var l = a &amp;&amp; a.length;
+            if (!a || !l) {
+                return m.call(t);
+            }
+            switch (l) {
+            case 1:
+                return m.call(t, a[0]);
+            case 2:
+                return m.call(t, a[0], a[1]);
+            case 3:
+                return m.call(t, a[0], a[1], a[2]);
+            case 4:
+                return m.call(t, a[0], a[1], a[2], a[3]);
+            case 5:
+                return m.call(t, a[0], a[1], a[2], a[3], a[4]);
+            default:
+                return m.apply(t, a);
+            }
+        }
+
+        __exports__.apply = apply;
+        function applyStr(t /* target */
+        , m /* method */
+        , a /* args */
+        ) {
+            var l = a &amp;&amp; a.length;
+            if (!a || !l) {
+                return t[m]();
+            }
+            switch (l) {
+            case 1:
+                return t[m](a[0]);
+            case 2:
+                return t[m](a[0], a[1]);
+            case 3:
+                return t[m](a[0], a[1], a[2]);
+            case 4:
+                return t[m](a[0], a[1], a[2], a[3]);
+            case 5:
+                return t[m](a[0], a[1], a[2], a[3], a[4]);
+            default:
+                return t[m].apply(t, a);
+            }
+        }
+
+        __exports__.applyStr = applyStr;
+        __exports__.GUID_KEY = GUID_KEY;
+        __exports__.GUID_PREFIX = GUID_PREFIX;
+        __exports__.META_DESC = META_DESC;
+        __exports__.EMPTY_META = EMPTY_META;
+        __exports__.META_KEY = META_KEY;
+        __exports__.meta = meta;
+        __exports__.typeOf = typeOf;
+        __exports__.tryCatchFinally = tryCatchFinally;
+        __exports__.isArray = isArray;
+        __exports__.canInvoke = canInvoke;
+        __exports__.tryFinally = tryFinally;
+    });
+    define(&quot;ember-metal/watch_key&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/platform&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var meta = __dependency2__.meta;
+        var typeOf = __dependency2__.typeOf;
+        var platform = __dependency3__.platform;
+
+        var metaFor = meta; // utils.js
+        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
+        var o_defineProperty = platform.defineProperty;
+
+        function watchKey(obj, keyName, meta) {
+            // can't watch length on Array - it is special...
+            if (keyName === 'length' &amp;&amp; typeOf(obj) === 'array') {
+                return;
+            }
+
+            var m = meta || metaFor(obj), watching = m.watching;
+
+            // activate watching first time
+            if (!watching[keyName]) {
+                watching[keyName] = 1;
+
+                var desc = m.descs[keyName];
+                if (desc &amp;&amp; desc.willWatch) {
+                    desc.willWatch(obj, keyName);
+                }
+
+                if ('function' === typeof obj.willWatchProperty) {
+                    obj.willWatchProperty(keyName);
+                }
+
+                if (MANDATORY_SETTER &amp;&amp; keyName in obj) {
+                    m.values[keyName] = obj[keyName];
+                    o_defineProperty(obj, keyName, {
+                        configurable: true,
+                        enumerable: obj.propertyIsEnumerable(keyName),
+                        set: Ember.MANDATORY_SETTER_FUNCTION,
+                        get: Ember.DEFAULT_GETTER_FUNCTION(keyName)
+                    });
+                }
+            } else {
+                watching[keyName] = (watching[keyName] || 0) + 1;
+            }
+        }
+
+        __exports__.watchKey = watchKey;
+        function unwatchKey(obj, keyName, meta) {
+            var m = meta || metaFor(obj), watching = m.watching;
+
+            if (watching[keyName] === 1) {
+                watching[keyName] = 0;
+
+                var desc = m.descs[keyName];
+                if (desc &amp;&amp; desc.didUnwatch) {
+                    desc.didUnwatch(obj, keyName);
+                }
+
+                if ('function' === typeof obj.didUnwatchProperty) {
+                    obj.didUnwatchProperty(keyName);
+                }
+
+                if (MANDATORY_SETTER &amp;&amp; keyName in obj) {
+                    o_defineProperty(obj, keyName, {
+                        configurable: true,
+                        enumerable: obj.propertyIsEnumerable(keyName),
+                        set: function(val) {
+                            // redefine to set as enumerable
+                            o_defineProperty(obj, keyName, {
+                                configurable: true,
+                                writable: true,
+                                enumerable: true,
+                                value: val
+                            });
+                            delete m.values[keyName];
+                        },
+                        get: Ember.DEFAULT_GETTER_FUNCTION(keyName)
+                    });
+                }
+            } else if (watching[keyName] &gt; 1) {
+                watching[keyName]--;
+            }
+        }
+
+        __exports__.unwatchKey = unwatchKey;
+    });
+    define(&quot;ember-metal/watch_path&quot;,
+    [&quot;ember-metal/utils&quot;, &quot;ember-metal/chains&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var meta = __dependency1__.meta;
+        var typeOf = __dependency1__.typeOf;
+        var ChainNode = __dependency2__.ChainNode;
+
+        var metaFor = meta;
+
+        // get the chains for the current object. If the current object has
+        // chains inherited from the proto they will be cloned and reconfigured for
+        // the current object.
+        function chainsFor(obj, meta) {
+            var m = meta || metaFor(obj), ret = m.chains;
+            if (!ret) {
+                ret = m.chains = new ChainNode(null, null, obj);
+            } else if (ret.value() !== obj) {
+                ret = m.chains = ret.copy(obj);
+            }
+            return ret;
+        }
+
+        function watchPath(obj, keyPath, meta) {
+            // can't watch length on Array - it is special...
+            if (keyPath === 'length' &amp;&amp; typeOf(obj) === 'array') {
+                return;
+            }
+
+            var m = meta || metaFor(obj), watching = m.watching;
+
+            if (!watching[keyPath]) {
+                // activate watching first time
+                watching[keyPath] = 1;
+                chainsFor(obj, m).add(keyPath);
+            } else {
+                watching[keyPath] = (watching[keyPath] || 0) + 1;
+            }
+        }
+
+        __exports__.watchPath = watchPath;
+        function unwatchPath(obj, keyPath, meta) {
+            var m = meta || metaFor(obj), watching = m.watching;
+
+            if (watching[keyPath] === 1) {
+                watching[keyPath] = 0;
+                chainsFor(obj, m).remove(keyPath);
+            } else if (watching[keyPath] &gt; 1) {
+                watching[keyPath]--;
+            }
+        }
+
+        __exports__.unwatchPath = unwatchPath;
+    });
+    define(&quot;ember-metal/watching&quot;,
+    [&quot;ember-metal/utils&quot;, &quot;ember-metal/chains&quot;, &quot;ember-metal/watch_key&quot;, &quot;ember-metal/watch_path&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember-metal
+            */
+
+        var meta = __dependency1__.meta;
+        var META_KEY = __dependency1__.META_KEY;
+        var GUID_KEY = __dependency1__.GUID_KEY;
+        var typeOf = __dependency1__.typeOf;
+        var generateGuid = __dependency1__.generateGuid;
+        var removeChainWatcher = __dependency2__.removeChainWatcher;
+        var flushPendingChains = __dependency2__.flushPendingChains;
+        var watchKey = __dependency3__.watchKey;
+        var unwatchKey = __dependency3__.unwatchKey;
+        var watchPath = __dependency4__.watchPath;
+        var unwatchPath = __dependency4__.unwatchPath;
+
+        var metaFor = meta; // utils.js
+
+        // returns true if the passed path is just a keyName
+        function isKeyName(path) {
+            return path.indexOf('.') === -1;
+        }
+
+        /**
+              Starts watching a property on an object. Whenever the property changes,
+              invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the
+              primitive used by observers and dependent keys; usually you will never call
+              this method directly but instead use higher level methods like
+              `Ember.addObserver()`
+
+              @private
+              @method watch
+              @for Ember
+              @param obj
+              @param {String} keyName
+            */
+        function watch(obj, _keyPath, m) {
+            // can't watch length on Array - it is special...
+            if (_keyPath === 'length' &amp;&amp; typeOf(obj) === 'array') {
+                return;
+            }
+
+            if (isKeyName(_keyPath)) {
+                watchKey(obj, _keyPath, m);
+            } else {
+                watchPath(obj, _keyPath, m);
+            }
+        }
+
+        __exports__.watch = watch;
+
+        function isWatching(obj, key) {
+            var meta = obj[META_KEY];
+            return (meta &amp;&amp; meta.watching[key]) &gt; 0;
+        }
+
+        __exports__.isWatching = isWatching;
+        watch.flushPending = flushPendingChains;
+
+        function unwatch(obj, _keyPath, m) {
+            // can't watch length on Array - it is special...
+            if (_keyPath === 'length' &amp;&amp; typeOf(obj) === 'array') {
+                return;
+            }
+
+            if (isKeyName(_keyPath)) {
+                unwatchKey(obj, _keyPath, m);
+            } else {
+                unwatchPath(obj, _keyPath, m);
+            }
+        }
+
+        __exports__.unwatch = unwatch; /**
+              Call on an object when you first beget it from another object. This will
+              setup any chained watchers on the object instance as needed. This method is
+              safe to call multiple times.
+
+              @private
+              @method rewatch
+              @for Ember
+              @param obj
+            */
+        function rewatch(obj) {
+            var m = obj[META_KEY], chains = m &amp;&amp; m.chains;
+
+            // make sure the object has its own guid.
+            if (GUID_KEY in obj &amp;&amp; !obj.hasOwnProperty(GUID_KEY)) {
+                generateGuid(obj);
+            }
+
+            // make sure any chained watchers update.
+            if (chains &amp;&amp; chains.value() !== obj) {
+                m.chains = chains.copy(obj);
+            }
+        }
+
+        __exports__.rewatch = rewatch;
+        var NODE_STACK = [];
+
+        /**
+              Tears down the meta on an object so that it can be garbage collected.
+              Multiple calls will have no effect.
+
+              @method destroy
+              @for Ember
+              @param {Object} obj  the object to destroy
+              @return {void}
+            */
+        function destroy(obj) {
+            var meta = obj[META_KEY], node, nodes, key, nodeObject;
+            if (meta) {
+                obj[META_KEY] = null;
+                // remove chainWatchers to remove circular references that would prevent GC
+                node = meta.chains;
+                if (node) {
+                    NODE_STACK.push(node);
+                    // process tree
+                    while (NODE_STACK.length &gt; 0) {
+                        node = NODE_STACK.pop();
+                        // push children
+                        nodes = node._chains;
+                        if (nodes) {
+                            for (key in nodes) {
+                                if (nodes.hasOwnProperty(key)) {
+                                    NODE_STACK.push(nodes[key]);
+                                }
+                            }
+                        }
+                        // remove chainWatcher in node object
+                        if (node._watching) {
+                            nodeObject = node._object;
+                            if (nodeObject) {
+                                removeChainWatcher(nodeObject, node._key, node);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        __exports__.destroy = destroy;
+    });
+    define(&quot;ember-routing-handlebars&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-handlebars&quot;, &quot;ember-routing/system/router&quot;, &quot;ember-routing-handlebars/helpers/shared&quot;, &quot;ember-routing-handlebars/helpers/link_to&quot;, &quot;ember-routing-handlebars/helpers/outlet&quot;, &quot;ember-routing-handlebars/helpers/render&quot;, &quot;ember-routing-handlebars/helpers/action&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            Ember Routing Handlebars
+
+            @module ember
+            @submodule ember-routing-handlebars
+            @requires ember-views
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var EmberHandlebars = __dependency2__[&quot;default&quot;];
+        var Router = __dependency3__[&quot;default&quot;];
+
+        var resolvePaths = __dependency4__.resolvePaths;
+        var resolveParams = __dependency4__.resolveParams;
+
+        var deprecatedLinkToHelper = __dependency5__.deprecatedLinkToHelper;
+        var linkToHelper = __dependency5__.linkToHelper;
+        var LinkView = __dependency5__.LinkView;
+
+        var outletHelper = __dependency6__.outletHelper;
+        var OutletView = __dependency6__.OutletView;
+
+        var renderHelper = __dependency7__[&quot;default&quot;];
+
+        var ActionHelper = __dependency8__.ActionHelper;
+        var actionHelper = __dependency8__.actionHelper;
+
+        Router.resolveParams = resolveParams;
+        Router.resolvePaths = resolvePaths;
+
+        Ember.LinkView = LinkView;
+        EmberHandlebars.ActionHelper = ActionHelper;
+        EmberHandlebars.OutletView = OutletView;
+
+        EmberHandlebars.registerHelper('render', renderHelper);
+        EmberHandlebars.registerHelper('action', actionHelper);
+        EmberHandlebars.registerHelper('outlet', outletHelper);
+        EmberHandlebars.registerHelper('link-to', linkToHelper);
+        EmberHandlebars.registerHelper('linkTo', deprecatedLinkToHelper);
+
+        __exports__[&quot;default&quot;] = Ember;
+    });
+    define(&quot;ember-routing-handlebars/helpers/action&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-views/system/utils&quot;, &quot;ember-routing/system/router&quot;, &quot;ember-handlebars&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-handlebars/helpers/view&quot;, &quot;ember-routing-handlebars/helpers/shared&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Handlebars, uuid, FEATURES, assert, deprecate
+        var get = __dependency2__.get;
+        var forEach = __dependency3__.forEach;
+        var uuid = __dependency4__.uuid;
+        var run = __dependency5__[&quot;default&quot;];
+
+        var isSimpleClick = __dependency6__.isSimpleClick;
+        var EmberRouter = __dependency7__[&quot;default&quot;];
+
+        var EmberHandlebars = __dependency8__[&quot;default&quot;];
+        var handlebarsGet = __dependency9__.handlebarsGet;
+        var viewHelper = __dependency10__.viewHelper;
+        var resolveParams = __dependency11__.resolveParams;
+        var resolvePath = __dependency11__.resolvePath;
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        var SafeString = EmberHandlebars.SafeString;
+        var a_slice = Array.prototype.slice;
+
+        function args(options, actionName) {
+            var ret = [];
+            if (actionName) {
+                ret.push(actionName);
+            }
+
+            var types = options.options.types.slice(1),
+            data = options.options.data;
+
+            return ret.concat(resolveParams(options.context, options.params, {
+                types: types,
+                data: data 
+            }));
+        }
+
+        var ActionHelper = {
+            registeredActions: {}
+        };
+
+        __exports__.ActionHelper = ActionHelper;
+
+        var keys = [&quot;alt&quot;, &quot;shift&quot;, &quot;meta&quot;, &quot;ctrl&quot;];
+
+        var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/;
+
+        var isAllowedEvent = function(event, allowedKeys) {
+            if (typeof allowedKeys === &quot;undefined&quot;) {
+                if (POINTER_EVENT_TYPE_REGEX.test(event.type)) {
+                    return isSimpleClick(event);
+                } else {
+                    allowedKeys = '';
+                }
+            }
+
+            if (allowedKeys.indexOf(&quot;any&quot;) &gt;= 0) {
+                return true;
+            }
+
+            var allowed = true;
+
+            forEach.call(keys, function(key) {
+                if (event[key + &quot;Key&quot;] &amp;&amp; allowedKeys.indexOf(key) === -1) {
+                    allowed = false;
+                }
+            });
+
+            return allowed;
+        };
+
+        ActionHelper.registerAction = function(actionNameOrPath, options, allowedKeys) {
+            var actionId = uuid();
+
+            ActionHelper.registeredActions[actionId] = {
+                eventName: options.eventName,
+                handler: function handleRegisteredAction(event) {
+                    if (!isAllowedEvent(event, allowedKeys)) {
+                        return true;
+                    }
+
+                    if (options.preventDefault !== false) {
+                        event.preventDefault();
+                    }
+
+                    if (options.bubbles === false) {
+                        event.stopPropagation();
+                    }
+
+                    var target = options.target,
+                    parameters = options.parameters,
+                    actionName;
+
+                    if (target.target) {
+                        target = handlebarsGet(target.root, target.target, target.options);
+                    } else {
+                        target = target.root;
+                    }
+
+                    if (options.boundProperty) {
+                        actionName = resolveParams(parameters.context, [actionNameOrPath], {
+                            types: ['ID'],
+                            data: parameters.options.data 
+                        })[0];
+
+                        if (typeof actionName === 'undefined' || typeof actionName === 'function') {
+                            Ember.assert(&quot;You specified a quoteless path to the {{action}} helper '&quot; + actionNameOrPath + &quot;' which did not resolve to an actionName. Perhaps you meant to use a quoted actionName? (e.g. {{action '&quot; + actionNameOrPath + &quot;'}}).&quot;, true);
+                            actionName = actionNameOrPath;
+                        }
+                    }
+
+                    if (!actionName) {
+                        actionName = actionNameOrPath;
+                    }
+
+                    run(function runRegisteredAction() {
+                        if (target.send) {
+                            target.send.apply(target, args(parameters, actionName));
+                        } else {
+                            Ember.assert(&quot;The action '&quot; + actionName + &quot;' did not exist on &quot; + target, typeof target[actionName] === 'function');
+                            target[actionName].apply(target, args(parameters));
+                        }
+                    });
+                }
+            };
+
+            options.view.on('willClearRender', function() {
+                delete ActionHelper.registeredActions[actionId];
+            });
+
+            return actionId;
+        };
+
+        /**
+              The `{{action}}` helper registers an HTML element within a template for DOM
+              event handling and forwards that interaction to the templates's controller
+              or supplied `target` option (see 'Specifying a Target').
+
+              If the controller does not implement the event, the event is sent
+              to the current route, and it bubbles up the route hierarchy from there.
+
+              User interaction with that element will invoke the supplied action name on
+              the appropriate target. Specifying a non-quoted action name will result in
+              a bound property lookup at the time the event will be triggered.
+
+              Given the following application Handlebars template on the page
+
+              ```handlebars
+              &lt;div {{action 'anActionName'}}&gt;
+                click me
+              &lt;/div&gt;
+              ```
+
+              And application code
+
+              ```javascript
+              App.ApplicationController = Ember.Controller.extend({
+                actions: {
+                  anActionName: function() {
+                  }
+                }
+              });
+              ```
+
+              Will result in the following rendered HTML
+
+              ```html
+              &lt;div class=&quot;ember-view&quot;&gt;
+                &lt;div data-ember-action=&quot;1&quot;&gt;
+                  click me
+                &lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              Clicking &quot;click me&quot; will trigger the `anActionName` action of the
+              `App.ApplicationController`. In this case, no additional parameters will be passed.
+
+              If you provide additional parameters to the helper:
+
+              ```handlebars
+              &lt;button {{action 'edit' post}}&gt;Edit&lt;/button&gt;
+              ```
+
+              Those parameters will be passed along as arguments to the JavaScript
+              function implementing the action.
+
+              ### Event Propagation
+
+              Events triggered through the action helper will automatically have
+              `.preventDefault()` called on them. You do not need to do so in your event
+              handlers. If you need to allow event propagation (to handle file inputs for
+              example) you can supply the `preventDefault=false` option to the `{{action}}` helper:
+
+              ```handlebars
+              &lt;div {{action &quot;sayHello&quot; preventDefault=false}}&gt;
+                &lt;input type=&quot;file&quot; /&gt;
+                &lt;input type=&quot;checkbox&quot; /&gt;
+              &lt;/div&gt;
+              ```
+
+              To disable bubbling, pass `bubbles=false` to the helper:
+
+              ```handlebars
+              &lt;button {{action 'edit' post bubbles=false}}&gt;Edit&lt;/button&gt;
+              ```
+
+              If you need the default handler to trigger you should either register your
+              own event handler, or use event methods on your view class. See [Ember.View](/api/classes/Ember.View.html)
+              'Responding to Browser Events' for more information.
+
+              ### Specifying DOM event type
+
+              By default the `{{action}}` helper registers for DOM `click` events. You can
+              supply an `on` option to the helper to specify a different DOM event name:
+
+              ```handlebars
+              &lt;div {{action &quot;anActionName&quot; on=&quot;doubleClick&quot;}}&gt;
+                click me
+              &lt;/div&gt;
+              ```
+
+              See `Ember.View` 'Responding to Browser Events' for a list of
+              acceptable DOM event names.
+
+              NOTE: Because `{{action}}` depends on Ember's event dispatch system it will
+              only function if an `Ember.EventDispatcher` instance is available. An
+              `Ember.EventDispatcher` instance will be created when a new `Ember.Application`
+              is created. Having an instance of `Ember.Application` will satisfy this
+              requirement.
+
+              ### Specifying whitelisted modifier keys
+
+              By default the `{{action}}` helper will ignore click event with pressed modifier
+              keys. You can supply an `allowedKeys` option to specify which keys should not be ignored.
+
+              ```handlebars
+              &lt;div {{action &quot;anActionName&quot; allowedKeys=&quot;alt&quot;}}&gt;
+                click me
+              &lt;/div&gt;
+              ```
+
+              This way the `{{action}}` will fire when clicking with the alt key pressed down.
+
+              Alternatively, supply &quot;any&quot; to the `allowedKeys` option to accept any combination of modifier keys.
+
+              ```handlebars
+              &lt;div {{action &quot;anActionName&quot; allowedKeys=&quot;any&quot;}}&gt;
+                click me with any key pressed
+              &lt;/div&gt;
+              ```
+
+              ### Specifying a Target
+
+              There are several possible target objects for `{{action}}` helpers:
+
+              In a typical Ember application, where views are managed through use of the
+              `{{outlet}}` helper, actions will bubble to the current controller, then
+              to the current route, and then up the route hierarchy.
+
+              Alternatively, a `target` option can be provided to the helper to change
+              which object will receive the method call. This option must be a path
+              to an object, accessible in the current context:
+
+              ```handlebars
+              {{! the application template }}
+              &lt;div {{action &quot;anActionName&quot; target=view}}&gt;
+                click me
+              &lt;/div&gt;
+              ```
+
+              ```javascript
+              App.ApplicationView = Ember.View.extend({
+                actions: {
+                  anActionName: function(){}
+                }
+              });
+
+              ```
+
+              ### Additional Parameters
+
+              You may specify additional parameters to the `{{action}}` helper. These
+              parameters are passed along as the arguments to the JavaScript function
+              implementing the action.
+
+              ```handlebars
+              {{#each person in people}}
+                &lt;div {{action &quot;edit&quot; person}}&gt;
+                  click me
+                &lt;/div&gt;
+              {{/each}}
+              ```
+
+              Clicking &quot;click me&quot; will trigger the `edit` method on the current controller
+              with the value of `person` as a parameter.
+
+              @method action
+              @for Ember.Handlebars.helpers
+              @param {String} actionName
+              @param {Object} [context]*
+              @param {Hash} options
+            */
+        function actionHelper(actionName) {
+            var options = arguments[arguments.length - 1],
+            contexts = a_slice.call(arguments, 1, -1);
+
+            var hash = options.hash,
+            controller = options.data.keywords.controller;
+
+            // create a hash to pass along to registerAction
+            var action = {
+                eventName: hash.on || &quot;click&quot;,
+                parameters: {
+                    context: this,
+                    options: options,
+                    params: contexts
+                },
+                view: options.data.view,
+                bubbles: hash.bubbles,
+                preventDefault: hash.preventDefault,
+                target: {
+                    options: options 
+                },
+                boundProperty: options.types[0] === &quot;ID&quot;
+            };
+
+            if (hash.target) {
+                action.target.root = this;
+                action.target.target = hash.target;
+            } else if (controller) {
+                action.target.root = controller;
+            }
+
+            var actionId = ActionHelper.registerAction(actionName, action, hash.allowedKeys);
+            return new SafeString('data-ember-action=&quot;' + actionId + '&quot;');
+        }
+
+        __exports__.actionHelper = actionHelper;
+    });
+    define(&quot;ember-routing-handlebars/helpers/link_to&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/computed&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/keys&quot;, &quot;ember-views/system/utils&quot;, &quot;ember-views/views/component&quot;, &quot;ember-handlebars&quot;, &quot;ember-handlebars/helpers/view&quot;, &quot;ember-routing/system/router&quot;, &quot;ember-routing-handlebars/helpers/shared&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES, Logger, Handlebars, warn, assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var merge = __dependency4__[&quot;default&quot;];
+        var run = __dependency5__[&quot;default&quot;];
+        var computed = __dependency6__.computed;
+
+        var onLoad = __dependency7__.onLoad;
+        var fmt = __dependency8__.fmt;
+        var EmberObject = __dependency9__[&quot;default&quot;];
+        var keys = __dependency10__[&quot;default&quot;];
+        var isSimpleClick = __dependency11__.isSimpleClick;
+        var EmberComponent = __dependency12__[&quot;default&quot;];
+        var EmberHandlebars = __dependency13__[&quot;default&quot;];
+        var viewHelper = __dependency14__.viewHelper;
+        var EmberRouter = __dependency15__[&quot;default&quot;];
+        var resolveParams = __dependency16__.resolveParams;
+        var resolvePaths = __dependency16__.resolvePaths;
+        var routeArgs = __dependency16__.routeArgs;
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        var slice = [].slice;
+
+        requireModule('ember-handlebars');
+
+        var numberOfContextsAcceptedByHandler = function(handler, handlerInfos) {
+            var req = 0;
+            for (var i = 0, l = handlerInfos.length; i &lt; l; i++) {
+                req = req + handlerInfos[i].names.length;
+                if (handlerInfos[i].handler === handler)
+                    break;
+            }
+
+            return req;
+        };
+
+        var QueryParams = EmberObject.extend({
+            values: null
+        });
+
+        function getResolvedPaths(options) {
+
+            var types = options.options.types,
+            data = options.options.data;
+
+            return resolvePaths(options.context, options.params, {
+                types: types,
+                data: data 
+            });
+        }
+
+        /**
+              `Ember.LinkView` renders an element whose `click` event triggers a
+              transition of the application's instance of `Ember.Router` to
+              a supplied route by name.
+
+              Instances of `LinkView` will most likely be created through
+              the `link-to` Handlebars helper, but properties of this class
+              can be overridden to customize application-wide behavior.
+
+              @class LinkView
+              @namespace Ember
+              @extends Ember.View
+              @see {Handlebars.helpers.link-to}
+            **/
+        var LinkView = Ember.LinkView = EmberComponent.extend({
+            tagName: 'a',
+            currentWhen: null,
+
+            /**
+                    Sets the `title` attribute of the `LinkView`'s HTML element.
+
+                    @property title
+                    @default null
+                  **/
+            title: null,
+
+            /**
+                    Sets the `rel` attribute of the `LinkView`'s HTML element.
+
+                    @property rel
+                    @default null
+                  **/
+            rel: null,
+
+            /**
+                    The CSS class to apply to `LinkView`'s element when its `active`
+                    property is `true`.
+
+                    @property activeClass
+                    @type String
+                    @default active
+                  **/
+            activeClass: 'active',
+
+            /**
+                    The CSS class to apply to `LinkView`'s element when its `loading`
+                    property is `true`.
+
+                    @property loadingClass
+                    @type String
+                    @default loading
+                  **/
+            loadingClass: 'loading',
+
+            /**
+                    The CSS class to apply to a `LinkView`'s element when its `disabled`
+                    property is `true`.
+
+                    @property disabledClass
+                    @type String
+                    @default disabled
+                  **/
+            disabledClass: 'disabled',
+            _isDisabled: false,
+
+            /**
+                    Determines whether the `LinkView` will trigger routing via
+                    the `replaceWith` routing strategy.
+
+                    @property replace
+                    @type Boolean
+                    @default false
+                  **/
+            replace: false,
+
+            /**
+                    By default the `{{link-to}}` helper will bind to the `href` and
+                    `title` attributes. It's discourage that you override these defaults,
+                    however you can push onto the array if needed.
+
+                    @property attributeBindings
+                    @type Array | String
+                    @default ['href', 'title', 'rel']
+                   **/
+            attributeBindings: ['href', 'title', 'rel'],
+
+            /**
+                    By default the `{{link-to}}` helper will bind to the `active`, `loading`, and
+                    `disabled` classes. It is discouraged to override these directly.
+
+                    @property classNameBindings
+                    @type Array
+                    @default ['active', 'loading', 'disabled']
+                   **/
+            classNameBindings: ['active', 'loading', 'disabled'],
+
+            /**
+                    By default the `{{link-to}}` helper responds to the `click` event. You
+                    can override this globally by setting this property to your custom
+                    event name.
+
+                    This is particularly useful on mobile when one wants to avoid the 300ms
+                    click delay using some sort of custom `tap` event.
+
+                    @property eventName
+                    @type String
+                    @default click
+                  */
+            eventName: 'click',
+
+            // this is doc'ed here so it shows up in the events
+            // section of the API documentation, which is where
+            // people will likely go looking for it.
+            /**
+                    Triggers the `LinkView`'s routing behavior. If
+                    `eventName` is changed to a value other than `click`
+                    the routing behavior will trigger on that custom event
+                    instead.
+
+                    @event click
+                  **/
+
+            /**
+                    An overridable method called when LinkView objects are instantiated.
+
+                    Example:
+
+                    ```javascript
+                    App.MyLinkView = Ember.LinkView.extend({
+                      init: function() {
+                        this._super();
+                        Ember.Logger.log('Event is ' + this.get('eventName'));
+                      }
+                    });
+                    ```
+
+                    NOTE: If you do override `init` for a framework class like `Ember.View` or
+                    `Ember.ArrayController`, be sure to call `this._super()` in your
+                    `init` declaration! If you don't, Ember may not have an opportunity to
+                    do important setup work, and you'll see strange behavior in your
+                    application.
+
+                    @method init
+                  */
+            init: function() {
+                this._super.apply(this, arguments);
+
+                // Map desired event name to invoke function
+                var eventName = get(this, 'eventName');
+                this.on(eventName, this, this._invoke);
+            },
+
+            /**
+                    This method is invoked by observers installed during `init` that fire
+                    whenever the params change
+
+                    @private
+                    @method _paramsChanged
+                    @since 1.3.0
+                   */
+            _paramsChanged: function() {
+                this.notifyPropertyChange('resolvedParams');
+            },
+
+            /**
+                   This is called to setup observers that will trigger a rerender.
+
+                   @private
+                   @method _setupPathObservers
+                   @since 1.3.0
+                  **/
+            _setupPathObservers: function() {
+                var helperParameters = this.parameters,
+                linkTextPath = helperParameters.options.linkTextPath,
+                paths = getResolvedPaths(helperParameters),
+                length = paths.length,
+                path, i, normalizedPath;
+
+                if (linkTextPath) {
+                    normalizedPath = getNormalizedPath(linkTextPath, helperParameters);
+                    this.registerObserver(normalizedPath.root, normalizedPath.path, this, this.rerender);
+                }
+
+                for (i = 0; i &lt; length; i++) {
+                    path = paths[i];
+                    if (null === path) {
+                        // A literal value was provided, not a path, so nothing to observe.
+                        continue;
+                    }
+
+                    normalizedPath = getNormalizedPath(path, helperParameters);
+                    this.registerObserver(normalizedPath.root, normalizedPath.path, this, this._paramsChanged);
+                }
+
+                var queryParamsObject = this.queryParamsObject;
+                if (queryParamsObject) {
+                    var values = queryParamsObject.values;
+
+                    // Install observers for all of the hash options
+                    // provided in the (query-params) subexpression.
+                    for (var k in values) {
+                        if (!values.hasOwnProperty(k)) {
+                            continue;
+                        }
+
+                        if (queryParamsObject.types[k] === 'ID') {
+                            normalizedPath = getNormalizedPath(values[k], helperParameters);
+                            this.registerObserver(normalizedPath.root, normalizedPath.path, this, this._paramsChanged);
+                        }
+                    }
+                }
+            },
+
+            afterRender: function() {
+                this._super.apply(this, arguments);
+                this._setupPathObservers();
+            },
+
+            /**
+
+                    Accessed as a classname binding to apply the `LinkView`'s `disabledClass`
+                    CSS `class` to the element when the link is disabled.
+
+                    When `true` interactions with the element will not trigger route changes.
+                    @property disabled
+                  */
+            disabled: computed(function computeLinkViewDisabled(key, value) {
+                if (value !== undefined) {
+                    this.set('_isDisabled', value);
+                }
+
+                return value ? get(this, 'disabledClass') : false;
+            }),
+
+            /**
+                    Accessed as a classname binding to apply the `LinkView`'s `activeClass`
+                    CSS `class` to the element when the link is active.
+
+                    A `LinkView` is considered active when its `currentWhen` property is `true`
+                    or the application's current route is the route the `LinkView` would trigger
+                    transitions into.
+
+                    @property active
+                  **/
+            active: computed('loadedParams', function computeLinkViewActive() {
+                if (get(this, 'loading')) {
+                    return false;
+                }
+
+                var router = get(this, 'router'),
+                loadedParams = get(this, 'loadedParams'),
+                contexts = loadedParams.models,
+                currentWhen = this.currentWhen || loadedParams.targetRouteName,
+                handlers = router.router.recognizer.handlersFor(currentWhen),
+                leafName = handlers[handlers.length-1].handler,
+                maximumContexts = numberOfContextsAcceptedByHandler(currentWhen, handlers);
+
+                // NOTE: any ugliness in the calculation of activeness is largely
+                // due to the fact that we support automatic normalizing of
+                // `resource` -&gt; `resource.index`, even though there might be
+                // dynamic segments / query params defined on `resource.index`
+                // which complicates (and makes somewhat ambiguous) the calculation
+                // of activeness for links that link to `resource` instead of
+                // directly to `resource.index`.
+
+                // if we don't have enough contexts revert back to full route name
+                // this is because the leaf route will use one of the contexts
+                if (contexts.length &gt; maximumContexts) {
+                    currentWhen = leafName;
+                }
+
+                var args = routeArgs(currentWhen, contexts, null);
+                var isActive = router.isActive.apply(router, args);
+                if (!isActive) {
+                    return false;
+                }
+
+
+                if (!this.currentWhen &amp;&amp; leafName === loadedParams.targetRouteName) {
+                    var visibleQueryParams = {};
+                    merge(visibleQueryParams, loadedParams.queryParams);
+                    router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
+                    isActive = shallowEqual(visibleQueryParams, router.router.state.queryParams);
+                }
+
+
+                if (isActive) {
+                    return get(this, 'activeClass');
+                }
+            }),
+
+            /**
+                    Accessed as a classname binding to apply the `LinkView`'s `loadingClass`
+                    CSS `class` to the element when the link is loading.
+
+                    A `LinkView` is considered loading when it has at least one
+                    parameter whose value is currently null or undefined. During
+                    this time, clicking the link will perform no transition and
+                    emit a warning that the link is still in a loading state.
+
+                    @property loading
+                  **/
+            loading: computed('loadedParams', function computeLinkViewLoading() {
+                if (!get(this, 'loadedParams')) {
+                    return get(this, 'loadingClass');
+                }
+            }),
+
+            /**
+                    Returns the application's main router from the container.
+
+                    @private
+                    @property router
+                  **/
+            router: computed(function() {
+                return get(this, 'controller').container.lookup('router:main');
+            }),
+
+            /**
+                    Event handler that invokes the link, activating the associated route.
+
+                    @private
+                    @method _invoke
+                    @param {Event} event
+                  */
+            _invoke: function(event) {
+                if (!isSimpleClick(event)) {
+                    return true;
+                }
+
+                if (this.preventDefault !== false) {
+
+                    event.preventDefault();
+
+                }
+
+                if (this.bubbles === false) {
+                    event.stopPropagation();
+                }
+
+                if (get(this, '_isDisabled')) {
+                    return false;
+                }
+
+                if (get(this, 'loading')) {
+                    Ember.Logger.warn(&quot;This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid.&quot;);
+                    return false;
+                }
+
+                var router = get(this, 'router'),
+                loadedParams = get(this, 'loadedParams');
+
+                var transition = router._doTransition(loadedParams.targetRouteName, loadedParams.models, loadedParams.queryParams);
+                if (get(this, 'replace')) {
+                    transition.method('replace');
+                }
+
+                // Schedule eager URL update, but after we've given the transition
+                // a chance to synchronously redirect.
+                // We need to always generate the URL instead of using the href because
+                // the href will include any rootURL set, but the router expects a URL
+                // without it! Note that we don't use the first level router because it
+                // calls location.formatURL(), which also would add the rootURL!
+                var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, transition.state.queryParams);
+                var url = router.router.generate.apply(router.router, args);
+
+                run.scheduleOnce('routerTransitions', this, this._eagerUpdateUrl, transition, url);
+            },
+
+            /**
+                    @private
+                    @method _eagerUpdateUrl
+                    @param transition
+                    @param href
+                   */
+            _eagerUpdateUrl: function(transition, href) {
+                if (!transition.isActive || !transition.urlMethod) {
+                    // transition was aborted, already ran to completion,
+                    // or it has a null url-updated method.
+                    return;
+                }
+
+                if (href.indexOf('#') === 0) {
+                    href = href.slice(1);
+                }
+
+                // Re-use the routerjs hooks set up by the Ember router.
+                var routerjs = get(this, 'router.router');
+                if (transition.urlMethod === 'update') {
+                    routerjs.updateURL(href);
+                } else if (transition.urlMethod === 'replace') {
+                    routerjs.replaceURL(href);
+                }
+
+                // Prevent later update url refire.
+                transition.method(null);
+            },
+
+            /**
+                    Computed property that returns an array of the
+                    resolved parameters passed to the `link-to` helper,
+                    e.g.:
+
+                    ```hbs
+                    {{link-to a b '123' c}}
+                    ```
+
+                    will generate a `resolvedParams` of:
+
+                    ```js
+                    [aObject, bObject, '123', cObject]
+                    ```
+
+                    @private
+                    @property
+                    @return {Array}
+                   */
+            resolvedParams: computed('router.url', function() {
+                var parameters = this.parameters,
+                options = parameters.options,
+                types = options.types,
+                data = options.data,
+                targetRouteName, models;
+
+                var onlyQueryParamsSupplied = (parameters.params.length === 0);
+                if (onlyQueryParamsSupplied) {
+                    var appController = this.container.lookup('controller:application');
+                    targetRouteName = get(appController, 'currentRouteName');
+                    models = [];
+                } else {
+                    models = resolveParams(parameters.context, parameters.params, {
+                        types: types,
+                        data: data 
+                    });
+                    targetRouteName = models.shift();
+                }
+
+                var suppliedQueryParams = getResolvedQueryParams(this, targetRouteName);
+
+                return {
+                    targetRouteName: targetRouteName,
+                    models: models,
+                    queryParams: suppliedQueryParams
+                };
+            }),
+
+            /**
+                    Computed property that returns the current route name,
+                    dynamic segments, and query params. Returns falsy if
+                    for null/undefined params to indicate that the link view
+                    is still in a loading state.
+
+                    @private
+                    @property
+                    @return {Array} An array with the route name and any dynamic segments
+                  **/
+            loadedParams: computed('resolvedParams', function computeLinkViewRouteArgs() {
+                var resolvedParams = get(this, 'resolvedParams'),
+                router = get(this, 'router'),
+                namedRoute = resolvedParams.targetRouteName;
+
+                if (!namedRoute) {
+                    return;
+                }
+
+                Ember.assert(fmt(&quot;The attempt to link-to route '%@' failed. &quot; +
+                &quot;The router did not find '%@' in its possible routes: '%@'&quot;,
+                [namedRoute, namedRoute, keys(router.router.recognizer.names).join(&quot;', '&quot;)]),
+                router.hasRoute(namedRoute));
+
+                if (!paramsAreLoaded(resolvedParams.models)) {
+                    return;
+                }
+
+                return resolvedParams;
+            }),
+
+            queryParamsObject: null,
+
+            /**
+                    Sets the element's `href` attribute to the url for
+                    the `LinkView`'s targeted route.
+
+                    If the `LinkView`'s `tagName` is changed to a value other
+                    than `a`, this property will be ignored.
+
+                    @property href
+                  **/
+            href: computed('loadedParams', function computeLinkViewHref() {
+                if (get(this, 'tagName') !== 'a') {
+                    return;
+                }
+
+                var router = get(this, 'router'),
+                loadedParams = get(this, 'loadedParams');
+
+                if (!loadedParams) {
+                    return get(this, 'loadingHref');
+                }
+
+                var visibleQueryParams = {};
+
+                merge(visibleQueryParams, loadedParams.queryParams);
+                router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
+
+
+                var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams);
+                var result = router.generate.apply(router, args);
+                return result;
+            }),
+
+            /**
+                    The default href value to use while a link-to is loading.
+                    Only applies when tagName is 'a'
+
+                    @property loadingHref
+                    @type String
+                    @default #
+                  */
+            loadingHref: '#'
+        });
+
+        LinkView.toString = function() {
+            return &quot;LinkView&quot;;
+        };
+
+
+        /**
+              The `{{link-to}}` helper renders a link to the supplied
+              `routeName` passing an optionally supplied model to the
+              route as its `model` context of the route. The block
+              for `{{link-to}}` becomes the innerHTML of the rendered
+              element:
+
+              ```handlebars
+              {{#link-to 'photoGallery'}}
+                Great Hamster Photos
+              {{/link-to}}
+              ```
+
+              ```html
+              &lt;a href=&quot;/hamster-photos&quot;&gt;
+                Great Hamster Photos
+              &lt;/a&gt;
+              ```
+
+              ### Supplying a tagName
+              By default `{{link-to}}` renders an `&lt;a&gt;` element. This can
+              be overridden for a single use of `{{link-to}}` by supplying
+              a `tagName` option:
+
+              ```handlebars
+              {{#link-to 'photoGallery' tagName=&quot;li&quot;}}
+                Great Hamster Photos
+              {{/link-to}}
+              ```
+
+              ```html
+              &lt;li&gt;
+                Great Hamster Photos
+              &lt;/li&gt;
+              ```
+
+              To override this option for your entire application, see
+              &quot;Overriding Application-wide Defaults&quot;.
+
+              ### Disabling the `link-to` helper
+              By default `{{link-to}}` is enabled.
+              any passed value to `disabled` helper property will disable the `link-to` helper.
+
+              static use: the `disabled` option:
+
+              ```handlebars
+              {{#link-to 'photoGallery' disabled=true}}
+                Great Hamster Photos
+              {{/link-to}}
+              ```
+
+              dynamic use: the `disabledWhen` option:
+
+              ```handlebars
+              {{#link-to 'photoGallery' disabledWhen=controller.someProperty}}
+                Great Hamster Photos
+              {{/link-to}}
+              ```
+
+              any passed value to `disabled` will disable it except `undefined`.
+              to ensure that only `true` disable the `link-to` helper you can
+              override the global behaviour of `Ember.LinkView`.
+
+              ```javascript
+              Ember.LinkView.reopen({
+                disabled: Ember.computed(function(key, value) {
+                  if (value !== undefined) {
+                    this.set('_isDisabled', value === true);
+                  }
+                  return value === true ? get(this, 'disabledClass') : false;
+                })
+              });
+              ```
+
+              see &quot;Overriding Application-wide Defaults&quot; for more.
+
+              ### Handling `href`
+              `{{link-to}}` will use your application's Router to
+              fill the element's `href` property with a url that
+              matches the path to the supplied `routeName` for your
+              routers's configured `Location` scheme, which defaults
+              to Ember.HashLocation.
+
+              ### Handling current route
+              `{{link-to}}` will apply a CSS class name of 'active'
+              when the application's current route matches
+              the supplied routeName. For example, if the application's
+              current route is 'photoGallery.recent' the following
+              use of `{{link-to}}`:
+
+              ```handlebars
+              {{#link-to 'photoGallery.recent'}}
+                Great Hamster Photos from the last week
+              {{/link-to}}
+              ```
+
+              will result in
+
+              ```html
+              &lt;a href=&quot;/hamster-photos/this-week&quot; class=&quot;active&quot;&gt;
+                Great Hamster Photos
+              &lt;/a&gt;
+              ```
+
+              The CSS class name used for active classes can be customized
+              for a single use of `{{link-to}}` by passing an `activeClass`
+              option:
+
+              ```handlebars
+              {{#link-to 'photoGallery.recent' activeClass=&quot;current-url&quot;}}
+                Great Hamster Photos from the last week
+              {{/link-to}}
+              ```
+
+              ```html
+              &lt;a href=&quot;/hamster-photos/this-week&quot; class=&quot;current-url&quot;&gt;
+                Great Hamster Photos
+              &lt;/a&gt;
+              ```
+
+              To override this option for your entire application, see
+              &quot;Overriding Application-wide Defaults&quot;.
+
+              ### Supplying a model
+              An optional model argument can be used for routes whose
+              paths contain dynamic segments. This argument will become
+              the model context of the linked route:
+
+              ```javascript
+              App.Router.map(function() {
+                this.resource(&quot;photoGallery&quot;, {path: &quot;hamster-photos/:photo_id&quot;});
+              });
+              ```
+
+              ```handlebars
+              {{#link-to 'photoGallery' aPhoto}}
+                {{aPhoto.title}}
+              {{/link-to}}
+              ```
+
+              ```html
+              &lt;a href=&quot;/hamster-photos/42&quot;&gt;
+                Tomster
+              &lt;/a&gt;
+              ```
+
+              ### Supplying multiple models
+              For deep-linking to route paths that contain multiple
+              dynamic segments, multiple model arguments can be used.
+              As the router transitions through the route path, each
+              supplied model argument will become the context for the
+              route with the dynamic segments:
+
+              ```javascript
+              App.Router.map(function() {
+                this.resource(&quot;photoGallery&quot;, {path: &quot;hamster-photos/:photo_id&quot;}, function() {
+                  this.route(&quot;comment&quot;, {path: &quot;comments/:comment_id&quot;});
+                });
+              });
+              ```
+              This argument will become the model context of the linked route:
+
+              ```handlebars
+              {{#link-to 'photoGallery.comment' aPhoto comment}}
+                {{comment.body}}
+              {{/link-to}}
+              ```
+
+              ```html
+              &lt;a href=&quot;/hamster-photos/42/comment/718&quot;&gt;
+                A+++ would snuggle again.
+              &lt;/a&gt;
+              ```
+
+              ### Supplying an explicit dynamic segment value
+              If you don't have a model object available to pass to `{{link-to}}`,
+              an optional string or integer argument can be passed for routes whose
+              paths contain dynamic segments. This argument will become the value
+              of the dynamic segment:
+
+              ```javascript
+              App.Router.map(function() {
+                this.resource(&quot;photoGallery&quot;, {path: &quot;hamster-photos/:photo_id&quot;});
+              });
+              ```
+
+              ```handlebars
+              {{#link-to 'photoGallery' aPhotoId}}
+                {{aPhoto.title}}
+              {{/link-to}}
+              ```
+
+              ```html
+              &lt;a href=&quot;/hamster-photos/42&quot;&gt;
+                Tomster
+              &lt;/a&gt;
+              ```
+
+              When transitioning into the linked route, the `model` hook will
+              be triggered with parameters including this passed identifier.
+
+              ### Allowing Default Action
+
+             By default the `{{link-to}}` helper prevents the default browser action
+             by calling `preventDefault()` as this sort of action bubbling is normally
+             handled internally and we do not want to take the browser to a new URL (for
+             example).
+
+             If you need to override this behavior specify `preventDefault=false` in
+             your template:
+
+              ```handlebars
+              {{#link-to 'photoGallery' aPhotoId preventDefault=false}}
+                {{aPhotoId.title}}
+              {{/link-to}}
+              ```
+
+              ### Overriding attributes
+              You can override any given property of the Ember.LinkView
+              that is generated by the `{{link-to}}` helper by passing
+              key/value pairs, like so:
+
+              ```handlebars
+              {{#link-to  aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}}
+                Uh-mazing!
+              {{/link-to}}
+              ```
+
+              See [Ember.LinkView](/api/classes/Ember.LinkView.html) for a
+              complete list of overrideable properties. Be sure to also
+              check out inherited properties of `LinkView`.
+
+              ### Overriding Application-wide Defaults
+              ``{{link-to}}`` creates an instance of Ember.LinkView
+              for rendering. To override options for your entire
+              application, reopen Ember.LinkView and supply the
+              desired values:
+
+              ``` javascript
+              Ember.LinkView.reopen({
+                activeClass: &quot;is-active&quot;,
+                tagName: 'li'
+              })
+              ```
+
+              It is also possible to override the default event in
+              this manner:
+
+              ``` javascript
+              Ember.LinkView.reopen({
+                eventName: 'customEventName'
+              });
+              ```
+
+              @method link-to
+              @for Ember.Handlebars.helpers
+              @param {String} routeName
+              @param {Object} [context]*
+              @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkView
+              @return {String} HTML string
+              @see {Ember.LinkView}
+            */
+        function linkToHelper(name) {
+            var options = slice.call(arguments, -1)[0],
+            params = slice.call(arguments, 0, -1),
+            hash = options.hash;
+
+            Ember.assert(&quot;You must provide one or more parameters to the link-to helper.&quot;, params.length);
+
+            if (params[params.length - 1] instanceof QueryParams) {
+                hash.queryParamsObject = params.pop();
+            }
+
+            hash.disabledBinding = hash.disabledWhen;
+
+            if (!options.fn) {
+                var linkTitle = params.shift();
+                var linkType = options.types.shift();
+                var context = this;
+                if (linkType === 'ID') {
+                    options.linkTextPath = linkTitle;
+                    options.fn = function() {
+                        return EmberHandlebars.getEscaped(context, linkTitle, options);
+                    };
+                } else {
+                    options.fn = function() {
+                        return linkTitle;
+                    };
+                }
+            }
+
+            hash.parameters = {
+                context: this,
+                options: options,
+                params: params
+            };
+
+            options.helperName = options.helperName || 'link-to';
+
+            return viewHelper.call(this, LinkView, options);
+        }
+
+
+
+        EmberHandlebars.registerHelper('query-params', function queryParamsHelper(options) {
+            Ember.assert(fmt(&quot;The `query-params` helper only accepts hash parameters, e.g. (query-params queryParamPropertyName='%@') as opposed to just (query-params '%@')&quot;, [options, options]), arguments.length === 1);
+
+            return QueryParams.create({
+                values: options.hash,
+                types: options.hashTypes
+            });
+        });
+
+
+        /**
+              See [link-to](/api/classes/Ember.Handlebars.helpers.html#method_link-to)
+
+              @method linkTo
+              @for Ember.Handlebars.helpers
+              @deprecated
+              @param {String} routeName
+              @param {Object} [context]*
+              @return {String} HTML string
+            */
+        function deprecatedLinkToHelper() {
+            Ember.warn(&quot;The 'linkTo' view helper is deprecated in favor of 'link-to'&quot;);
+            return linkToHelper.apply(this, arguments);
+        }
+
+        function getResolvedQueryParams(linkView, targetRouteName) {
+            var helperParameters = linkView.parameters,
+            queryParamsObject = linkView.queryParamsObject,
+            resolvedQueryParams = {};
+
+            if (!queryParamsObject) {
+                return resolvedQueryParams;
+            }
+            var rawParams = queryParamsObject.values;
+
+            for (var key in rawParams) {
+                if (!rawParams.hasOwnProperty(key)) {
+                    continue;
+                }
+
+                var value = rawParams[key],
+                type = queryParamsObject.types[key];
+
+                if (type === 'ID') {
+                    var normalizedPath = getNormalizedPath(value, helperParameters);
+                    value = EmberHandlebars.get(normalizedPath.root, normalizedPath.path, helperParameters.options);
+                }
+                resolvedQueryParams[key] = value;
+            }
+            return resolvedQueryParams;
+        }
+
+        function getNormalizedPath(path, helperParameters) {
+            return EmberHandlebars.normalizePath(helperParameters.context, path, helperParameters.options.data);
+        }
+
+        function paramsAreLoaded(params) {
+            for (var i = 0, len = params.length; i &lt; len; ++i) {
+                var param = params[i];
+                if (param === null || typeof param === 'undefined') {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        function shallowEqual(a, b) {
+            var k;
+            for (k in a) {
+                if (a.hasOwnProperty(k) &amp;&amp; a[k] !== b[k]) {
+                    return false;
+                }
+            }
+            for (k in b) {
+                if (b.hasOwnProperty(k) &amp;&amp; a[k] !== b[k]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        __exports__.LinkView = LinkView;
+        __exports__.deprecatedLinkToHelper = deprecatedLinkToHelper;
+        __exports__.linkToHelper = linkToHelper;
+    });
+    define(&quot;ember-routing-handlebars/helpers/outlet&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-views/views/container_view&quot;, &quot;ember-handlebars/views/metamorph_view&quot;, &quot;ember-handlebars/helpers/view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var onLoad = __dependency4__.onLoad;
+        var ContainerView = __dependency5__[&quot;default&quot;];
+        var _Metamorph = __dependency6__._Metamorph;
+        var viewHelper = __dependency7__.viewHelper;
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              @module ember
+              @submodule ember-routing
+              */
+
+        var OutletView = ContainerView.extend(_Metamorph);
+        __exports__.OutletView = OutletView;
+        /**
+              The `outlet` helper is a placeholder that the router will fill in with
+              the appropriate template based on the current state of the application.
+
+              ``` handlebars
+              {{outlet}}
+              ```
+
+              By default, a template based on Ember's naming conventions will be rendered
+              into the `outlet` (e.g. `App.PostsRoute` will render the `posts` template).
+
+              You can render a different template by using the `render()` method in the
+              route's `renderTemplate` hook. The following will render the `favoritePost`
+              template into the `outlet`.
+
+              ``` javascript
+              App.PostsRoute = Ember.Route.extend({
+                renderTemplate: function() {
+                  this.render('favoritePost');
+                }
+              });
+              ```
+
+              You can create custom named outlets for more control.
+
+              ``` handlebars
+              {{outlet 'favoritePost'}}
+              {{outlet 'posts'}}
+              ```
+
+              Then you can define what template is rendered into each outlet in your
+              route.
+
+
+              ``` javascript
+              App.PostsRoute = Ember.Route.extend({
+                renderTemplate: function() {
+                  this.render('favoritePost', { outlet: 'favoritePost' });
+                  this.render('posts', { outlet: 'posts' });
+                }
+              });
+              ```
+
+              You can specify the view that the outlet uses to contain and manage the
+              templates rendered into it.
+
+              ``` handlebars
+              {{outlet view='sectionContainer'}}
+              ```
+
+              ``` javascript
+              App.SectionContainer = Ember.ContainerView.extend({
+                tagName: 'section',
+                classNames: ['special']
+              });
+              ```
+
+              @method outlet
+              @for Ember.Handlebars.helpers
+              @param {String} property the property on the controller
+                that holds the view for this outlet
+              @return {String} HTML string
+            */
+        function outletHelper(property, options) {
+            var outletSource;
+            var container;
+            var viewName;
+            var viewClass;
+            var viewFullName;
+
+            if (property &amp;&amp; property.data &amp;&amp; property.data.isRenderData) {
+                options = property;
+                property = 'main';
+            }
+
+            container = options.data.view.container;
+
+            outletSource = options.data.view;
+            while (!outletSource.get('template.isTop')) {
+                outletSource = outletSource.get('_parentView');
+            }
+
+            // provide controller override
+            viewName = options.hash.view;
+
+            if (viewName) {
+                viewFullName = 'view:' + viewName;
+                Ember.assert(&quot;Using a quoteless view parameter with {{outlet}} is not supported. Please update to quoted usage '{{outlet \&quot;&quot; + viewName + &quot;\&quot;}}.&quot;, options.hashTypes.view !== 'ID');
+                Ember.assert(&quot;The view name you supplied '&quot; + viewName + &quot;' did not resolve to a view.&quot;, container.has(viewFullName));
+            }
+
+            viewClass = viewName ? container.lookupFactory(viewFullName) : options.hash.viewClass || OutletView;
+
+            options.data.view.set('outletSource', outletSource);
+            options.hash.currentViewBinding = '_view.outletSource._outlets.' + property;
+
+            options.helperName = options.helperName || 'outlet';
+
+            return viewHelper.call(this, viewClass, options);
+        }
+
+        __exports__.outletHelper = outletHelper;
+    });
+    define(&quot;ember-routing-handlebars/helpers/render&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-routing/system/generate_controller&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-handlebars/helpers/view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // assert, deprecate
+        var EmberError = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var camelize = __dependency5__.camelize;
+        var generateControllerFactory = __dependency6__.generateControllerFactory;
+        var generateController = __dependency6__[&quot;default&quot;];
+        var handlebarsGet = __dependency7__.handlebarsGet;
+        var viewHelper = __dependency8__.viewHelper;
+
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              Calling ``{{render}}`` from within a template will insert another
+              template that matches the provided name. The inserted template will
+              access its properties on its own controller (rather than the controller
+              of the parent template).
+
+              If a view class with the same name exists, the view class also will be used.
+
+              Note: A given controller may only be used *once* in your app in this manner.
+              A singleton instance of the controller will be created for you.
+
+              Example:
+
+              ```javascript
+              App.NavigationController = Ember.Controller.extend({
+                who: &quot;world&quot;
+              });
+              ```
+
+              ```handlebars
+              &lt;!-- navigation.hbs --&gt;
+              Hello, {{who}}.
+              ```
+
+              ```handelbars
+              &lt;!-- application.hbs --&gt;
+              &lt;h1&gt;My great app&lt;/h1&gt;
+              {{render &quot;navigation&quot;}}
+              ```
+
+              ```html
+              &lt;h1&gt;My great app&lt;/h1&gt;
+              &lt;div class='ember-view'&gt;
+                Hello, world.
+              &lt;/div&gt;
+              ```
+
+              Optionally you may provide a second argument: a property path
+              that will be bound to the `model` property of the controller.
+
+              If a `model` property path is specified, then a new instance of the
+              controller will be created and `{{render}}` can be used multiple times
+              with the same name.
+
+             For example if you had this `author` template.
+
+             ```handlebars
+            &lt;div class=&quot;author&quot;&gt;
+            Written by {{firstName}} {{lastName}}.
+            Total Posts: {{postCount}}
+            &lt;/div&gt;
+            ```
+
+            You could render it inside the `post` template using the `render` helper.
+
+            ```handlebars
+            &lt;div class=&quot;post&quot;&gt;
+            &lt;h1&gt;{{title}}&lt;/h1&gt;
+            &lt;div&gt;{{body}}&lt;/div&gt;
+            {{render &quot;author&quot; author}}
+            &lt;/div&gt;
+             ```
+
+              @method render
+              @for Ember.Handlebars.helpers
+              @param {String} name
+              @param {Object?} contextString
+              @param {Hash} options
+              @return {String} HTML string
+            */
+        __exports__[&quot;default&quot;] = function renderHelper(name, contextString, options) {
+            var length = arguments.length;
+
+            var contextProvided = length === 3,
+            container, router, controller, view, context, lookupOptions;
+
+            container = (options || contextString).data.keywords.controller.container;
+            router = container.lookup('router:main');
+
+            if (length === 2) {
+                // use the singleton controller
+                options = contextString;
+                contextString = undefined;
+                Ember.assert(&quot;You can only use the {{render}} helper once without a model object as its second argument, as in {{render \&quot;post\&quot; post}}.&quot;, !router || !router._lookupActiveView(name));
+            } else if (length === 3) {
+                // create a new controller
+                context = handlebarsGet(options.contexts[1], contextString, options);
+            } else {
+                throw new EmberError(&quot;You must pass a templateName to render&quot;);
+            }
+
+            Ember.deprecate(&quot;Using a quoteless parameter with {{render}} is deprecated. Please update to quoted usage '{{render \&quot;&quot; + name + &quot;\&quot;}}.&quot;, options.types[0] !== 'ID');
+
+            // # legacy namespace
+            name = name.replace(/\//g, '.');
+            // \ legacy slash as namespace support
+
+
+            view = container.lookup('view:' + name) || container.lookup('view:default');
+
+            // provide controller override
+            var controllerName = options.hash.controller || name;
+            var controllerFullName = 'controller:' + controllerName;
+
+            if (options.hash.controller) {
+                Ember.assert(&quot;The controller name you supplied '&quot; + controllerName + &quot;' did not resolve to a controller.&quot;, container.has(controllerFullName));
+            }
+
+            var parentController = options.data.keywords.controller;
+
+            // choose name
+            if (length &gt; 2) {
+                var factory = container.lookupFactory(controllerFullName) ||
+                generateControllerFactory(container, controllerName, context);
+
+                controller = factory.create({
+                    model: context,
+                    parentController: parentController,
+                    target: parentController
+                });
+
+                view.one('willDestroyElement', function() {
+                    controller.destroy();
+                });
+            } else {
+                controller = container.lookup(controllerFullName) ||
+                generateController(container, controllerName);
+
+                controller.setProperties({
+                    target: parentController,
+                    parentController: parentController
+                });
+            }
+
+            var root = options.contexts[1];
+
+            if (root) {
+                view.registerObserver(root, contextString, function() {
+                    controller.set('model', handlebarsGet(root, contextString, options));
+                });
+            }
+
+            options.hash.viewName = camelize(name);
+
+            var templateName = 'template:' + name;
+            Ember.assert(&quot;You used `{{render '&quot; + name + &quot;'}}`, but '&quot; + name + &quot;' can not be found as either a template or a view.&quot;, container.has(&quot;view:&quot; + name) || container.has(templateName) || options.fn);
+            options.hash.template = container.lookup(templateName);
+
+            options.hash.controller = controller;
+
+            if (router &amp;&amp; !context) {
+                router._connectActiveView(name, view);
+            }
+
+            options.helperName = options.helperName || ('render &quot;' + name + '&quot;');
+
+            viewHelper.call(this, view, options);
+        }
+    });
+    define(&quot;ember-routing-handlebars/helpers/shared&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/array&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;ember-handlebars/ext&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var map = __dependency2__.map;
+        var ControllerMixin = __dependency3__[&quot;default&quot;];
+        var handlebarsResolve = __dependency4__.resolveParams;
+        var handlebarsGet = __dependency4__.handlebarsGet;
+        var typeOf = __dependency5__.typeOf;
+        var get = __dependency1__.get;
+
+        function routeArgs(targetRouteName, models, queryParams) {
+            var args = [];
+            if (typeOf(targetRouteName) === 'string') {
+                args.push('' + targetRouteName);
+            }
+            args.push.apply(args, models);
+            args.push({
+                queryParams: queryParams 
+            });
+            return args;
+        }
+
+        __exports__.routeArgs = routeArgs;
+        function getActiveTargetName(router) {
+            var handlerInfos = router.activeTransition ?
+            router.activeTransition.state.handlerInfos :
+            router.state.handlerInfos;
+            return handlerInfos[handlerInfos.length - 1].name;
+        }
+
+        __exports__.getActiveTargetName = getActiveTargetName;
+        function resolveParams(context, params, options) {
+            return map.call(resolvePaths(context, params, options), function(path, i) {
+                if (null === path) {
+                    // Param was string/number, not a path, so just return raw string/number.
+                    return params[i];
+                } else {
+                    return handlebarsGet(context, path, options);
+                }
+            });
+        }
+
+        __exports__.resolveParams = resolveParams;
+        function stashParamNames(router, handlerInfos) {
+            if (handlerInfos._namesStashed) {
+                return;
+            }
+
+            // This helper exists because router.js/route-recognizer.js awkwardly
+            // keeps separate a handlerInfo's list of parameter names depending
+            // on whether a URL transition or named transition is happening.
+            // Hopefully we can remove this in the future.
+            var targetRouteName = handlerInfos[handlerInfos.length-1].name;
+            var recogHandlers = router.router.recognizer.handlersFor(targetRouteName);
+            var dynamicParent = null;
+
+            for (var i = 0, len = handlerInfos.length; i &lt; len; ++i) {
+                var handlerInfo = handlerInfos[i];
+                var names = recogHandlers[i].names;
+
+                if (names.length) {
+                    dynamicParent = handlerInfo;
+                }
+
+                handlerInfo._names = names;
+
+                var route = handlerInfo.handler;
+                route._stashNames(handlerInfo, dynamicParent);
+            }
+
+            handlerInfos._namesStashed = true;
+        }
+
+        __exports__.stashParamNames = stashParamNames;
+        function resolvePaths(context, params, options) {
+            var resolved = handlebarsResolve(context, params, options),
+            types = options.types;
+
+            return map.call(resolved, function(object, i) {
+                if (types[i] === 'ID') {
+                    return unwrap(object, params[i]);
+                } else {
+                    return null;
+                }
+            });
+
+            function unwrap(object, path) {
+                if (path === 'controller') {
+                    return path;
+                }
+
+                if (ControllerMixin.detect(object)) {
+                    return unwrap(get(object, 'model'), path ? path + '.model' : 'model');
+                } else {
+                    return path;
+                }
+            }
+        }
+
+        __exports__.resolvePaths = resolvePaths;
+    });
+    define(&quot;ember-routing&quot;,
+    [&quot;ember-handlebars&quot;, &quot;ember-metal/core&quot;, &quot;ember-routing/ext/run_loop&quot;, &quot;ember-routing/ext/controller&quot;, &quot;ember-routing/ext/view&quot;, &quot;ember-routing/location/api&quot;, &quot;ember-routing/location/none_location&quot;, &quot;ember-routing/location/hash_location&quot;, &quot;ember-routing/location/history_location&quot;, &quot;ember-routing/location/auto_location&quot;, &quot;ember-routing/system/generate_controller&quot;, &quot;ember-routing/system/controller_for&quot;, &quot;ember-routing/system/dsl&quot;, &quot;ember-routing/system/router&quot;, &quot;ember-routing/system/route&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            Ember Routing
+
+            @module ember
+            @submodule ember-routing
+            @requires ember-views
+            */
+
+        var EmberHandlebars = __dependency1__[&quot;default&quot;];
+        var Ember = __dependency2__[&quot;default&quot;];
+
+        // ES6TODO: Cleanup modules with side-effects below
+
+        var EmberLocation = __dependency6__[&quot;default&quot;];
+        var NoneLocation = __dependency7__[&quot;default&quot;];
+        var HashLocation = __dependency8__[&quot;default&quot;];
+        var HistoryLocation = __dependency9__[&quot;default&quot;];
+        var AutoLocation = __dependency10__[&quot;default&quot;];
+
+        var generateControllerFactory = __dependency11__.generateControllerFactory;
+        var generateController = __dependency11__[&quot;default&quot;];
+        var controllerFor = __dependency12__[&quot;default&quot;];
+        var RouterDSL = __dependency13__[&quot;default&quot;];
+        var Router = __dependency14__[&quot;default&quot;];
+        var Route = __dependency15__[&quot;default&quot;];
+
+        Ember.Location = EmberLocation;
+        Ember.AutoLocation = AutoLocation;
+        Ember.HashLocation = HashLocation;
+        Ember.HistoryLocation = HistoryLocation;
+        Ember.NoneLocation = NoneLocation;
+
+        Ember.controllerFor = controllerFor;
+        Ember.generateControllerFactory = generateControllerFactory;
+        Ember.generateController = generateController;
+        Ember.RouterDSL = RouterDSL;
+        Ember.Router = Router;
+        Ember.Route = Route;
+
+        __exports__[&quot;default&quot;] = Ember;
+    });
+    define(&quot;ember-routing/ext/controller&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES, deprecate
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var computed = __dependency4__.computed;
+        var typeOf = __dependency5__.typeOf;
+        var meta = __dependency5__.meta;
+        var merge = __dependency6__[&quot;default&quot;];
+        var map = __dependency7__.map;
+
+        var ControllerMixin = __dependency8__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        ControllerMixin.reopen({
+            /**
+                    Transition the application into another route. The route may
+                    be either a single route or route path:
+
+                    ```javascript
+                    aController.transitionToRoute('blogPosts');
+                    aController.transitionToRoute('blogPosts.recentEntries');
+                    ```
+
+                    Optionally supply a model for the route in question. The model
+                    will be serialized into the URL using the `serialize` hook of
+                    the route:
+
+                    ```javascript
+                    aController.transitionToRoute('blogPost', aPost);
+                    ```
+
+                    If a literal is passed (such as a number or a string), it will
+                    be treated as an identifier instead. In this case, the `model`
+                    hook of the route will be triggered:
+
+                    ```javascript
+                    aController.transitionToRoute('blogPost', 1);
+                    ```
+
+                    Multiple models will be applied last to first recursively up the
+                    resource tree.
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.resource('blogPost', {path:':blogPostId'}, function(){
+                        this.resource('blogComment', {path: ':blogCommentId'});
+                      });
+                    });
+
+                    aController.transitionToRoute('blogComment', aPost, aComment);
+                    aController.transitionToRoute('blogComment', 1, 13);
+                    ```
+
+                    It is also possible to pass a URL (a string that starts with a
+                    `/`). This is intended for testing and debugging purposes and
+                    should rarely be used in production code.
+
+                    ```javascript
+                    aController.transitionToRoute('/');
+                    aController.transitionToRoute('/blog/post/1/comment/13');
+                    ```
+
+                    See also [replaceRoute](/api/classes/Ember.ControllerMixin.html#method_replaceRoute).
+
+                    @param {String} name the name of the route or a URL
+                    @param {...Object} models the model(s) or identifier(s) to be used
+                    while transitioning to the route.
+                    @for Ember.ControllerMixin
+                    @method transitionToRoute
+                  */
+            transitionToRoute: function() {
+                // target may be either another controller or a router
+                var target = get(this, 'target');
+                var method = target.transitionToRoute || target.transitionTo;
+                return method.apply(target, arguments);
+            },
+
+            /**
+                    @deprecated
+                    @for Ember.ControllerMixin
+                    @method transitionTo
+                  */
+            transitionTo: function() {
+                Ember.deprecate(&quot;transitionTo is deprecated. Please use transitionToRoute.&quot;);
+                return this.transitionToRoute.apply(this, arguments);
+            },
+
+            /**
+                    Transition into another route while replacing the current URL, if possible.
+                    This will replace the current history entry instead of adding a new one.
+                    Beside that, it is identical to `transitionToRoute` in all other respects.
+
+                    ```javascript
+                    aController.replaceRoute('blogPosts');
+                    aController.replaceRoute('blogPosts.recentEntries');
+                    ```
+
+                    Optionally supply a model for the route in question. The model
+                    will be serialized into the URL using the `serialize` hook of
+                    the route:
+
+                    ```javascript
+                    aController.replaceRoute('blogPost', aPost);
+                    ```
+
+                    If a literal is passed (such as a number or a string), it will
+                    be treated as an identifier instead. In this case, the `model`
+                    hook of the route will be triggered:
+
+                    ```javascript
+                    aController.replaceRoute('blogPost', 1);
+                    ```
+
+                    Multiple models will be applied last to first recursively up the
+                    resource tree.
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.resource('blogPost', {path:':blogPostId'}, function(){
+                        this.resource('blogComment', {path: ':blogCommentId'});
+                      });
+                    });
+
+                    aController.replaceRoute('blogComment', aPost, aComment);
+                    aController.replaceRoute('blogComment', 1, 13);
+                    ```
+
+                    It is also possible to pass a URL (a string that starts with a
+                    `/`). This is intended for testing and debugging purposes and
+                    should rarely be used in production code.
+
+                    ```javascript
+                    aController.replaceRoute('/');
+                    aController.replaceRoute('/blog/post/1/comment/13');
+                    ```
+
+                    @param {String} name the name of the route or a URL
+                    @param {...Object} models the model(s) or identifier(s) to be used
+                    while transitioning to the route.
+                    @for Ember.ControllerMixin
+                    @method replaceRoute
+                  */
+            replaceRoute: function() {
+                // target may be either another controller or a router
+                var target = get(this, 'target');
+                var method = target.replaceRoute || target.replaceWith;
+                return method.apply(target, arguments);
+            },
+
+            /**
+                    @deprecated
+                    @for Ember.ControllerMixin
+                    @method replaceWith
+                  */
+            replaceWith: function() {
+                Ember.deprecate(&quot;replaceWith is deprecated. Please use replaceRoute.&quot;);
+                return this.replaceRoute.apply(this, arguments);
+            }
+        });
+
+        var ALL_PERIODS_REGEX = /\./g;
+
+
+        ControllerMixin.reopen({
+            init: function() {
+                this._super.apply(this, arguments);
+                listenForQueryParamChanges(this);
+            },
+
+            concatenatedProperties: ['queryParams', '_pCacheMeta'],
+            queryParams: null,
+
+            _qpDelegate: null,
+            _normalizedQueryParams: computed(function() {
+                var m = meta(this);
+                if (m.proto !== this) {
+                    return get(m.proto, '_normalizedQueryParams');
+                }
+
+                var queryParams = this.queryParams;
+                if (queryParams._qpMap) {
+                    return queryParams._qpMap;
+                }
+
+                var qpMap = queryParams._qpMap = {};
+
+                for (var i = 0, len = queryParams.length; i &lt; len; ++i) {
+                    accumulateQueryParamDescriptors(queryParams[i], qpMap);
+                }
+
+                return qpMap;
+            }),
+
+            _cacheMeta: computed(function() {
+                var m = meta(this);
+                if (m.proto !== this) {
+                    return get(m.proto, '_cacheMeta');
+                }
+
+                var cacheMeta = {};
+                var qpMap = get(this, '_normalizedQueryParams');
+                for (var prop in qpMap) {
+                    if (!qpMap.hasOwnProperty(prop)) {
+                        continue;
+                    }
+
+                    var qp = qpMap[prop];
+                    var scope = qp.scope;
+                    var parts;
+
+                    if (scope === 'controller') {
+                        parts = [];
+                    }
+
+                    cacheMeta[prop] = {
+                        parts: parts,
+                        // provided by route if 'model' scope
+                        values: null,
+                        // provided by route
+                        scope: scope,
+                        prefix: &quot;&quot;,
+                        def: get(this, prop)
+                    };
+                }
+
+                return cacheMeta;
+            }),
+
+            _updateCacheParams: function(params) {
+                var cacheMeta = get(this, '_cacheMeta');
+                for (var prop in cacheMeta) {
+                    if (!cacheMeta.hasOwnProperty(prop)) {
+                        continue;
+                    }
+                    var propMeta = cacheMeta[prop];
+                    propMeta.values = params;
+
+                    var cacheKey = this._calculateCacheKey(propMeta.prefix, propMeta.parts, propMeta.values);
+                    var cache = this._bucketCache;
+                    var value = cache.lookup(cacheKey, prop, propMeta.def);
+
+                    set(this, prop, value);
+                }
+            },
+
+            _qpChanged: function(controller, _prop) {
+                var prop = _prop.substr(0, _prop.length-3);
+                var cacheMeta = get(controller, '_cacheMeta');
+                var propCache = cacheMeta[prop];
+                var cacheKey = controller._calculateCacheKey(propCache.prefix || &quot;&quot;, propCache.parts, propCache.values);
+                var value = get(controller, prop);
+
+                // 1. Update model-dep cache
+                controller._bucketCache.stash(cacheKey, prop, value);
+
+                // 2. Notify a delegate (e.g. to fire a qp transition)
+                var delegate = controller._qpDelegate;
+                if (delegate) {
+                    delegate(controller, prop);
+                }
+            },
+
+            _calculateCacheKey: function(prefix, _parts, values) {
+                var parts = _parts || [], suffixes = &quot;&quot;;
+                for (var i = 0, len = parts.length; i &lt; len; ++i) {
+                    var part = parts[i];
+                    var value = get(values, part);
+                    suffixes += &quot;::&quot; + part + &quot;:&quot; + value;
+                }
+                return prefix + suffixes.replace(ALL_PERIODS_REGEX, '-');
+            }
+        });
+
+
+        function accumulateQueryParamDescriptors(_desc, accum) {
+            var desc = _desc, tmp;
+            if (typeOf(desc) === 'string') {
+                tmp = {};
+                tmp[desc] = {
+                    as: null 
+                };
+                desc = tmp;
+            }
+
+            for (var key in desc) {
+                if (!desc.hasOwnProperty(key)) {
+                    return;
+                }
+
+                var singleDesc = desc[key];
+                if (typeOf(singleDesc) === 'string') {
+                    singleDesc = {
+                        as: singleDesc 
+                    };
+                }
+
+                tmp = accum[key] || {
+                    as: null,
+                    scope: 'model' 
+                };
+                merge(tmp, singleDesc);
+
+                accum[key] = tmp;
+            }
+        }
+
+        function listenForQueryParamChanges(controller) {
+            var qpMap = get(controller, '_normalizedQueryParams');
+            for (var prop in qpMap) {
+                if (!qpMap.hasOwnProperty(prop)) {
+                    continue;
+                }
+                controller.addObserver(prop + '.[]', controller, controller._qpChanged);
+            }
+        }
+
+
+        __exports__[&quot;default&quot;] = ControllerMixin;
+    });
+    define(&quot;ember-routing/ext/run_loop&quot;,
+    [&quot;ember-metal/run_loop&quot;],
+    function(__dependency1__) {
+        &quot;use strict&quot;;
+        var run = __dependency1__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        // Add a new named queue after the 'actions' queue (where RSVP promises
+        // resolve), which is used in router transitions to prevent unnecessary
+        // loading state entry if all context promises resolve on the
+        // 'actions' queue first.
+
+        var queues = run.queues;
+        run._addQueue('routerTransitions', 'actions');
+    });
+    define(&quot;ember-routing/ext/view&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-views/views/view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var run = __dependency3__[&quot;default&quot;];
+        var EmberView = __dependency4__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        EmberView.reopen({
+
+            /**
+                    Sets the private `_outlets` object on the view.
+
+                    @method init
+                   */
+            init: function() {
+                set(this, '_outlets', {});
+                this._super();
+            },
+
+            /**
+                    Manually fill any of a view's `{{outlet}}` areas with the
+                    supplied view.
+
+                    Example
+
+                    ```javascript
+                    var MyView = Ember.View.extend({
+                      template: Ember.Handlebars.compile('Child view: {{outlet &quot;main&quot;}} ')
+                    });
+                    var myView = MyView.create();
+                    myView.appendTo('body');
+                    // The html for myView now looks like:
+                    // &lt;div id=&quot;ember228&quot; class=&quot;ember-view&quot;&gt;Child view: &lt;/div&gt;
+
+                    var FooView = Ember.View.extend({
+                      template: Ember.Handlebars.compile('&lt;h1&gt;Foo&lt;/h1&gt; ')
+                    });
+                    var fooView = FooView.create();
+                    myView.connectOutlet('main', fooView);
+                    // The html for myView now looks like:
+                    // &lt;div id=&quot;ember228&quot; class=&quot;ember-view&quot;&gt;Child view:
+                    //   &lt;div id=&quot;ember234&quot; class=&quot;ember-view&quot;&gt;&lt;h1&gt;Foo&lt;/h1&gt; &lt;/div&gt;
+                    // &lt;/div&gt;
+                    ```
+                    @method connectOutlet
+                    @param  {String} outletName A unique name for the outlet
+                    @param  {Object} view       An Ember.View
+                   */
+            connectOutlet: function(outletName, view) {
+                if (this._pendingDisconnections) {
+                    delete this._pendingDisconnections[outletName];
+                }
+
+                if (this._hasEquivalentView(outletName, view)) {
+                    view.destroy();
+                    return;
+                }
+
+                var outlets = get(this, '_outlets');
+                var container = get(this, 'container');
+                var router = container &amp;&amp; container.lookup('router:main');
+                var renderedName = get(view, 'renderedName');
+
+                set(outlets, outletName, view);
+
+                if (router &amp;&amp; renderedName) {
+                    router._connectActiveView(renderedName, view);
+                }
+            },
+
+            /**
+                    Determines if the view has already been created by checking if
+                    the view has the same constructor, template, and context as the
+                    view in the `_outlets` object.
+
+                    @private
+                    @method _hasEquivalentView
+                    @param  {String} outletName The name of the outlet we are checking
+                    @param  {Object} view       An Ember.View
+                    @return {Boolean}
+                   */
+            _hasEquivalentView: function(outletName, view) {
+                var existingView = get(this, '_outlets.' + outletName);
+                return existingView &amp;&amp;
+                existingView.constructor === view.constructor &amp;&amp;
+                existingView.get('template') === view.get('template') &amp;&amp;
+                existingView.get('context') === view.get('context');
+            },
+
+            /**
+                    Removes an outlet from the view.
+
+                    Example
+
+                    ```javascript
+                    var MyView = Ember.View.extend({
+                      template: Ember.Handlebars.compile('Child view: {{outlet &quot;main&quot;}} ')
+                    });
+                    var myView = MyView.create();
+                    myView.appendTo('body');
+                    // myView's html:
+                    // &lt;div id=&quot;ember228&quot; class=&quot;ember-view&quot;&gt;Child view: &lt;/div&gt;
+
+                    var FooView = Ember.View.extend({
+                      template: Ember.Handlebars.compile('&lt;h1&gt;Foo&lt;/h1&gt; ')
+                    });
+                    var fooView = FooView.create();
+                    myView.connectOutlet('main', fooView);
+                    // myView's html:
+                    // &lt;div id=&quot;ember228&quot; class=&quot;ember-view&quot;&gt;Child view:
+                    //   &lt;div id=&quot;ember234&quot; class=&quot;ember-view&quot;&gt;&lt;h1&gt;Foo&lt;/h1&gt; &lt;/div&gt;
+                    // &lt;/div&gt;
+
+                    myView.disconnectOutlet('main');
+                    // myView's html:
+                    // &lt;div id=&quot;ember228&quot; class=&quot;ember-view&quot;&gt;Child view: &lt;/div&gt;
+                    ```
+
+                    @method disconnectOutlet
+                    @param  {String} outletName The name of the outlet to be removed
+                   */
+            disconnectOutlet: function(outletName) {
+                if (!this._pendingDisconnections) {
+                    this._pendingDisconnections = {};
+                }
+                this._pendingDisconnections[outletName] = true;
+                run.once(this, '_finishDisconnections');
+            },
+
+            /**
+                    Gets an outlet that is pending disconnection and then
+                    nullifys the object on the `_outlet` object.
+
+                    @private
+                    @method _finishDisconnections
+                   */
+            _finishDisconnections: function() {
+                if (this.isDestroyed) 
+                    return; // _outlets will be gone anyway
+                var outlets = get(this, '_outlets');
+                var pendingDisconnections = this._pendingDisconnections;
+                this._pendingDisconnections = null;
+
+                for (var outletName in pendingDisconnections) {
+                    set(outlets, outletName, null);
+                }
+            }
+        });
+
+        __exports__[&quot;default&quot;] = EmberView;
+    });
+    define(&quot;ember-routing/location/api&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // deprecate, assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              Ember.Location returns an instance of the correct implementation of
+              the `location` API.
+
+              ## Implementations
+
+              You can pass an implementation name (`hash`, `history`, `none`) to force a
+              particular implementation to be used in your application.
+
+              ### HashLocation
+
+              Using `HashLocation` results in URLs with a `#` (hash sign) separating the
+              server side URL portion of the URL from the portion that is used by Ember.
+              This relies upon the `hashchange` event existing in the browser.
+
+              Example:
+
+              ```javascript
+              App.Router.map(function() {
+                this.resource('posts', function() {
+                  this.route('new');
+                });
+              });
+
+              App.Router.reopen({
+                location: 'hash'
+              });
+              ```
+
+              This will result in a posts.new url of `/#/posts/new`.
+
+              ### HistoryLocation
+
+              Using `HistoryLocation` results in URLs that are indistinguishable from a
+              standard URL. This relies upon the browser's `history` API.
+
+              Example:
+
+              ```javascript
+              App.Router.map(function() {
+                this.resource('posts', function() {
+                  this.route('new');
+                });
+              });
+
+              App.Router.reopen({
+                location: 'history'
+              });
+              ```
+
+              This will result in a posts.new url of `/posts/new`.
+
+              Keep in mind that your server must serve the Ember app at all the routes you
+              define.
+
+              ### AutoLocation
+
+              Using `AutoLocation`, the router will use the best Location class supported by
+              the browser it is running in.
+
+              Browsers that support the `history` API will use `HistoryLocation`, those that
+              do not, but still support the `hashchange` event will use `HashLocation`, and
+              in the rare case neither is supported will use `NoneLocation`.
+
+              Example:
+
+              ```javascript
+              App.Router.map(function() {
+                this.resource('posts', function() {
+                  this.route('new');
+                });
+              });
+
+              App.Router.reopen({
+                location: 'auto'
+              });
+              ```
+
+              This will result in a posts.new url of `/posts/new` for modern browsers that
+              support the `history` api or `/#/posts/new` for older ones, like Internet
+              Explorer 9 and below.
+
+              When a user visits a link to your application, they will be automatically
+              upgraded or downgraded to the appropriate `Location` class, with the URL
+              transformed accordingly, if needed.
+
+              Keep in mind that since some of your users will use `HistoryLocation`, your
+              server must serve the Ember app at all the routes you define.
+
+              ### NoneLocation
+
+              Using `NoneLocation` causes Ember to not store the applications URL state
+              in the actual URL. This is generally used for testing purposes, and is one
+              of the changes made when calling `App.setupForTesting()`.
+
+              ## Location API
+
+              Each location implementation must provide the following methods:
+
+              * implementation: returns the string name used to reference the implementation.
+              * getURL: returns the current URL.
+              * setURL(path): sets the current URL.
+              * replaceURL(path): replace the current URL (optional).
+              * onUpdateURL(callback): triggers the callback when the URL changes.
+              * formatURL(url): formats `url` to be placed into `href` attribute.
+
+              Calling setURL or replaceURL will not trigger onUpdateURL callbacks.
+
+              @class Location
+              @namespace Ember
+              @static
+            */
+        __exports__[&quot;default&quot;] = {
+            /**
+                   This is deprecated in favor of using the container to lookup the location
+                   implementation as desired.
+
+                   For example:
+
+                   ```javascript
+                   // Given a location registered as follows:
+                   container.register('location:history-test', HistoryTestLocation);
+
+                   // You could create a new instance via:
+                   container.lookup('location:history-test');
+                   ```
+
+                    @method create
+                    @param {Object} options
+                    @return {Object} an instance of an implementation of the `location` API
+                    @deprecated Use the container to lookup the location implementation that you
+                    need.
+                  */
+            create: function(options) {
+                var implementation = options &amp;&amp; options.implementation;
+                Ember.assert(&quot;Ember.Location.create: you must specify a 'implementation' option&quot;, !!implementation);
+
+                var implementationClass = this.implementations[implementation];
+                Ember.assert(&quot;Ember.Location.create: &quot; + implementation + &quot; is not a valid implementation&quot;, !!implementationClass);
+
+                return implementationClass.create.apply(implementationClass, arguments);
+            },
+
+            /**
+                   This is deprecated in favor of using the container to register the
+                   location implementation as desired.
+
+                   Example:
+
+                   ```javascript
+                   Application.initializer({
+                    name: &quot;history-test-location&quot;,
+
+                    initialize: function(container, application) {
+                      application.register('location:history-test', HistoryTestLocation);
+                    }
+                   });
+                   ```
+
+                   @method registerImplementation
+                   @param {String} name
+                   @param {Object} implementation of the `location` API
+                   @deprecated Register your custom location implementation with the
+                   container directly.
+                  */
+            registerImplementation: function(name, implementation) {
+                Ember.deprecate('Using the Ember.Location.registerImplementation is no longer supported. Register your custom location implementation with the container instead.', false);
+
+                this.implementations[name] = implementation;
+            },
+
+            implementations: {},
+            _location: window.location,
+
+            /**
+                    Returns the current `location.hash` by parsing location.href since browsers
+                    inconsistently URL-decode `location.hash`.
+
+                    https://bugzilla.mozilla.org/show_bug.cgi?id=483304
+
+                    @private
+                    @method getHash
+                    @since 1.4.0
+                  */
+            _getHash: function () {
+                // AutoLocation has it at _location, HashLocation at .location.
+                // Being nice and not changing
+                var href = (this._location || this.location).href;
+                var hashIndex = href.indexOf('#');
+
+                if (hashIndex === -1) {
+                    return '';
+                } else {
+                    return href.substr(hashIndex);
+                }
+            }
+        };
+    });
+    define(&quot;ember-routing/location/auto_location&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-routing/location/api&quot;, &quot;ember-routing/location/history_location&quot;, &quot;ember-routing/location/hash_location&quot;, &quot;ember-routing/location/none_location&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+
+        var EmberLocation = __dependency4__[&quot;default&quot;];
+        var HistoryLocation = __dependency5__[&quot;default&quot;];
+        var HashLocation = __dependency6__[&quot;default&quot;];
+        var NoneLocation = __dependency7__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              Ember.AutoLocation will select the best location option based off browser
+              support with the priority order: history, hash, none.
+
+              Clean pushState paths accessed by hashchange-only browsers will be redirected
+              to the hash-equivalent and vice versa so future transitions are consistent.
+
+              Keep in mind that since some of your users will use `HistoryLocation`, your
+              server must serve the Ember app at all the routes you define.
+
+              @class AutoLocation
+              @namespace Ember
+              @static
+            */
+        __exports__[&quot;default&quot;] = {
+
+            /**
+                    @private
+
+                    This property is used by router:main to know whether to cancel the routing
+                    setup process, which is needed while we redirect the browser.
+
+                    @since 1.5.1
+                    @property cancelRouterSetup
+                    @default false
+                  */
+            cancelRouterSetup: false,
+
+            /**
+                    @private
+
+                    Will be pre-pended to path upon state change.
+
+                    @since 1.5.1
+                    @property rootURL
+                    @default '/'
+                  */
+            rootURL: '/',
+
+            /**
+                    @private
+
+                    Attached for mocking in tests
+
+                    @since 1.5.1
+                    @property _window
+                    @default window
+                  */
+            _window: window,
+
+            /**
+                    @private
+
+                    Attached for mocking in tests
+
+                    @property location
+                    @default window.location
+                  */
+            _location: window.location,
+
+            /**
+                    @private
+
+                    Attached for mocking in tests
+
+                    @since 1.5.1
+                    @property _history
+                    @default window.history
+                  */
+            _history: window.history,
+
+            /**
+                    @private
+
+                    Attached for mocking in tests
+
+                    @since 1.5.1
+                    @property _HistoryLocation
+                    @default Ember.HistoryLocation
+                  */
+            _HistoryLocation: HistoryLocation,
+
+            /**
+                    @private
+
+                    Attached for mocking in tests
+
+                    @since 1.5.1
+                    @property _HashLocation
+                    @default Ember.HashLocation
+                  */
+            _HashLocation: HashLocation,
+
+            /**
+                    @private
+
+                    Attached for mocking in tests
+
+                    @since 1.5.1
+                    @property _NoneLocation
+                    @default Ember.NoneLocation
+                  */
+            _NoneLocation: NoneLocation,
+
+            /**
+                    @private
+
+                    Returns location.origin or builds it if device doesn't support it.
+
+                    @method _getOrigin
+                  */
+            _getOrigin: function () {
+                var location = this._location;
+                var origin = location.origin;
+
+                // Older browsers, especially IE, don't have origin
+                if (!origin) {
+                    origin = location.protocol + '//' + location.hostname;
+
+                    if (location.port) {
+                        origin += ':' + location.port;
+                    }
+                }
+
+                return origin;
+            },
+
+            /**
+                    @private
+
+                    We assume that if the history object has a pushState method, the host should
+                    support HistoryLocation.
+
+                    @method _getSupportsHistory
+                  */
+            _getSupportsHistory: function () {
+                // Boosted from Modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
+                // The stock browser on Android 2.2 &amp; 2.3 returns positive on history support
+                // Unfortunately support is really buggy and there is no clean way to detect
+                // these bugs, so we fall back to a user agent sniff :(
+                var userAgent = this._window.navigator.userAgent;
+
+                // We only want Android 2, stock browser, and not Chrome which identifies
+                // itself as 'Mobile Safari' as well
+                if (userAgent.indexOf('Android 2') !== -1 &amp;&amp;
+                userAgent.indexOf('Mobile Safari') !== -1 &amp;&amp;
+                userAgent.indexOf('Chrome') === -1) {
+                    return false;
+                }
+
+                return !!(this._history &amp;&amp; 'pushState' in this._history);
+            },
+
+            /**
+                    @private
+
+                    IE8 running in IE7 compatibility mode gives false positive, so we must also
+                    check documentMode.
+
+                    @method _getSupportsHashChange
+                  */
+            _getSupportsHashChange: function () {
+                var _window = this._window;
+                var documentMode = _window.document.documentMode;
+
+                return ('onhashchange' in _window &amp;&amp; (documentMode === undefined || documentMode &gt; 7 ));
+            },
+
+            /**
+                    @private
+
+                    Redirects the browser using location.replace, prepending the locatin.origin
+                    to prevent phishing attempts
+
+                    @method _replacePath
+                  */
+            _replacePath: function (path) {
+                this._location.replace(this._getOrigin() + path);
+            },
+
+            /**
+                    @since 1.5.1
+                    @private
+                    @method _getRootURL
+                  */
+            _getRootURL: function () {
+                return this.rootURL;
+            },
+
+            /**
+                    @private
+
+                    Returns the current `location.pathname`, normalized for IE inconsistencies.
+
+                    @method _getPath
+                  */
+            _getPath: function () {
+                var pathname = this._location.pathname;
+                // Various versions of IE/Opera don't always return a leading slash
+                if (pathname.charAt(0) !== '/') {
+                    pathname = '/' + pathname;
+                }
+
+                return pathname;
+            },
+
+            /**
+                    @private
+
+                    Returns normalized location.hash as an alias to Ember.Location._getHash
+
+                    @since 1.5.1
+                    @method _getHash
+                  */
+            _getHash: EmberLocation._getHash,
+
+            /**
+                    @private
+
+                    Returns location.search
+
+                    @since 1.5.1
+                    @method _getQuery
+                  */
+            _getQuery: function () {
+                return this._location.search;
+            },
+
+            /**
+                    @private
+
+                    Returns the full pathname including query and hash
+
+                    @method _getFullPath
+                  */
+            _getFullPath: function () {
+                return this._getPath() + this._getQuery() + this._getHash();
+            },
+
+            /**
+                    @private
+
+                    Returns the current path as it should appear for HistoryLocation supported
+                    browsers. This may very well differ from the real current path (e.g. if it
+                    starts off as a hashed URL)
+
+                    @method _getHistoryPath
+                  */
+            _getHistoryPath: function () {
+                var rootURL = this._getRootURL();
+                var path = this._getPath();
+                var hash = this._getHash();
+                var query = this._getQuery();
+                var rootURLIndex = path.indexOf(rootURL);
+                var routeHash, hashParts;
+
+                Ember.assert('Path ' + path + ' does not start with the provided rootURL ' + rootURL, rootURLIndex === 0);
+
+                // By convention, Ember.js routes using HashLocation are required to start
+                // with `#/`. Anything else should NOT be considered a route and should
+                // be passed straight through, without transformation.
+                if (hash.substr(0, 2) === '#/') {
+                    // There could be extra hash segments after the route
+                    hashParts = hash.substr(1).split('#');
+                    // The first one is always the route url
+                    routeHash = hashParts.shift();
+
+                    // If the path already has a trailing slash, remove the one
+                    // from the hashed route so we don't double up.
+                    if (path.slice(-1) === '/') {
+                        routeHash = routeHash.substr(1);
+                    }
+
+                    // This is the &quot;expected&quot; final order
+                    path += routeHash;
+                    path += query;
+
+                    if (hashParts.length) {
+                        path += '#' + hashParts.join('#');
+                    }
+                } else {
+                    path += query;
+                    path += hash;
+                }
+
+                return path;
+            },
+
+            /**
+                    @private
+
+                    Returns the current path as it should appear for HashLocation supported
+                    browsers. This may very well differ from the real current path.
+
+                    @method _getHashPath
+                  */
+            _getHashPath: function () {
+                var rootURL = this._getRootURL();
+                var path = rootURL;
+                var historyPath = this._getHistoryPath();
+                var routePath = historyPath.substr(rootURL.length);
+
+                if (routePath !== '') {
+                    if (routePath.charAt(0) !== '/') {
+                        routePath = '/' + routePath;
+                    }
+
+                    path += '#' + routePath;
+                }
+
+                return path;
+            },
+
+            /**
+                    Selects the best location option based off browser support and returns an
+                    instance of that Location class.
+
+                    @see Ember.AutoLocation
+                    @method create
+                  */
+            create: function (options) {
+                if (options &amp;&amp; options.rootURL) {
+                    Ember.assert('rootURL must end with a trailing forward slash e.g. &quot;/app/&quot;', options.rootURL.charAt(options.rootURL.length-1) === '/');
+                    this.rootURL = options.rootURL;
+                }
+
+                var historyPath, hashPath;
+                var cancelRouterSetup = false;
+                var implementationClass = this._NoneLocation;
+                var currentPath = this._getFullPath();
+
+                if (this._getSupportsHistory()) {
+                    historyPath = this._getHistoryPath();
+
+                    // Since we support history paths, let's be sure we're using them else
+                    // switch the location over to it.
+                    if (currentPath === historyPath) {
+                        implementationClass = this._HistoryLocation;
+                    } else {
+                        cancelRouterSetup = true;
+                        this._replacePath(historyPath);
+                    }
+
+                } else if (this._getSupportsHashChange()) {
+                    hashPath = this._getHashPath();
+
+                    // Be sure we're using a hashed path, otherwise let's switch over it to so
+                    // we start off clean and consistent. We'll count an index path with no
+                    // hash as &quot;good enough&quot; as well.
+                    if (currentPath === hashPath || (currentPath === '/' &amp;&amp; hashPath === '/#/')) {
+                        implementationClass = this._HashLocation;
+                    } else {
+                        // Our URL isn't in the expected hash-supported format, so we want to
+                        // cancel the router setup and replace the URL to start off clean
+                        cancelRouterSetup = true;
+                        this._replacePath(hashPath);
+                    }
+                }
+
+                var implementation = implementationClass.create.apply(implementationClass, arguments);
+
+                if (cancelRouterSetup) {
+                    set(implementation, 'cancelRouterSetup', true);
+                }
+
+                return implementation;
+            }
+        };
+    });
+    define(&quot;ember-routing/location/hash_location&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-routing/location/api&quot;, &quot;ember-views/system/jquery&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var run = __dependency3__[&quot;default&quot;];
+        var guidFor = __dependency4__.guidFor;
+
+        var EmberObject = __dependency5__[&quot;default&quot;];
+        var EmberLocation = __dependency6__[&quot;default&quot;];
+        var jQuery = __dependency7__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              `Ember.HashLocation` implements the location API using the browser's
+              hash. At present, it relies on a `hashchange` event existing in the
+              browser.
+
+              @class HashLocation
+              @namespace Ember
+              @extends Ember.Object
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            implementation: 'hash',
+
+            init: function() {
+                set(this, 'location', get(this, '_location') || window.location);
+            },
+
+            /**
+                    @private
+
+                    Returns normalized location.hash
+
+                    @since 1.5.1
+                    @method getHash
+                  */
+            getHash: EmberLocation._getHash,
+
+            /**
+                    Returns the current `location.hash`, minus the '#' at the front.
+
+                    @private
+                    @method getURL
+                  */
+            getURL: function() {
+                return this.getHash().substr(1);
+            },
+
+            /**
+                    Set the `location.hash` and remembers what was set. This prevents
+                    `onUpdateURL` callbacks from triggering when the hash was set by
+                    `HashLocation`.
+
+                    @private
+                    @method setURL
+                    @param path {String}
+                  */
+            setURL: function(path) {
+                get(this, 'location').hash = path;
+                set(this, 'lastSetURL', path);
+            },
+
+            /**
+                    Uses location.replace to update the url without a page reload
+                    or history modification.
+
+                    @private
+                    @method replaceURL
+                    @param path {String}
+                  */
+            replaceURL: function(path) {
+                get(this, 'location').replace('#' + path);
+                set(this, 'lastSetURL', path);
+            },
+
+            /**
+                    Register a callback to be invoked when the hash changes. These
+                    callbacks will execute when the user presses the back or forward
+                    button, but not after `setURL` is invoked.
+
+                    @private
+                    @method onUpdateURL
+                    @param callback {Function}
+                  */
+            onUpdateURL: function(callback) {
+                var self = this;
+                var guid = guidFor(this);
+
+                jQuery(window).on('hashchange.ember-location-' + guid, function() {
+                    run(function() {
+                        var path = self.getURL();
+                        if (get(self, 'lastSetURL') === path) {
+                            return;
+                        }
+
+                        set(self, 'lastSetURL', null);
+
+                        callback(path);
+                    });
+                });
+            },
+
+            /**
+                    Given a URL, formats it to be placed into the page as part
+                    of an element's `href` attribute.
+
+                    This is used, for example, when using the {{action}} helper
+                    to generate a URL based on an event.
+
+                    @private
+                    @method formatURL
+                    @param url {String}
+                  */
+            formatURL: function(url) {
+                return '#' + url;
+            },
+
+            /**
+                    Cleans up the HashLocation event listener.
+
+                    @private
+                    @method willDestroy
+                  */
+            willDestroy: function() {
+                var guid = guidFor(this);
+
+                jQuery(window).off('hashchange.ember-location-' + guid);
+            }
+        });
+    });
+    define(&quot;ember-routing/location/history_location&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-views/system/jquery&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var guidFor = __dependency4__.guidFor;
+
+        var EmberObject = __dependency5__[&quot;default&quot;];
+        var jQuery = __dependency6__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        var popstateFired = false;
+        var supportsHistoryState = window.history &amp;&amp; 'state' in window.history;
+
+        /**
+              Ember.HistoryLocation implements the location API using the browser's
+              history.pushState API.
+
+              @class HistoryLocation
+              @namespace Ember
+              @extends Ember.Object
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            implementation: 'history',
+
+            init: function() {
+                set(this, 'location', get(this, 'location') || window.location);
+                set(this, 'baseURL', jQuery('base').attr('href') || '');
+            },
+
+            /**
+                    Used to set state on first call to setURL
+
+                    @private
+                    @method initState
+                  */
+            initState: function() {
+                set(this, 'history', get(this, 'history') || window.history);
+                this.replaceState(this.formatURL(this.getURL()));
+            },
+
+            /**
+                    Will be pre-pended to path upon state change
+
+                    @property rootURL
+                    @default '/'
+                  */
+            rootURL: '/',
+
+            /**
+                    Returns the current `location.pathname` without `rootURL` or `baseURL`
+
+                    @private
+                    @method getURL
+                    @return url {String}
+                  */
+            getURL: function() {
+                var rootURL = get(this, 'rootURL');
+                var location = get(this, 'location');
+                var path = location.pathname;
+                var baseURL = get(this, 'baseURL');
+
+                rootURL = rootURL.replace(/\/$/, '');
+                baseURL = baseURL.replace(/\/$/, '');
+
+                var url = path.replace(baseURL, '').replace(rootURL, '');
+
+
+                var search = location.search || '';
+                url += search;
+
+
+                return url;
+            },
+
+            /**
+                    Uses `history.pushState` to update the url without a page reload.
+
+                    @private
+                    @method setURL
+                    @param path {String}
+                  */
+            setURL: function(path) {
+                var state = this.getState();
+                path = this.formatURL(path);
+
+                if (!state || state.path !== path) {
+                    this.pushState(path);
+                }
+            },
+
+            /**
+                    Uses `history.replaceState` to update the url without a page reload
+                    or history modification.
+
+                    @private
+                    @method replaceURL
+                    @param path {String}
+                  */
+            replaceURL: function(path) {
+                var state = this.getState();
+                path = this.formatURL(path);
+
+                if (!state || state.path !== path) {
+                    this.replaceState(path);
+                }
+            },
+
+            /**
+                   Get the current `history.state`. Checks for if a polyfill is
+                   required and if so fetches this._historyState. The state returned
+                   from getState may be null if an iframe has changed a window's
+                   history.
+
+                   @private
+                   @method getState
+                   @return state {Object}
+                  */
+            getState: function() {
+                return supportsHistoryState ? get(this, 'history').state : this._historyState;
+            },
+
+            /**
+                   Pushes a new state.
+
+                   @private
+                   @method pushState
+                   @param path {String}
+                  */
+            pushState: function(path) {
+                var state = {
+                    path: path 
+                };
+
+                get(this, 'history').pushState(state, null, path);
+
+                // store state if browser doesn't support `history.state`
+                if (!supportsHistoryState) {
+                    this._historyState = state;
+                }
+
+                // used for webkit workaround
+                this._previousURL = this.getURL();
+            },
+
+            /**
+                   Replaces the current state.
+
+                   @private
+                   @method replaceState
+                   @param path {String}
+                  */
+            replaceState: function(path) {
+                var state = {
+                    path: path 
+                };
+
+                get(this, 'history').replaceState(state, null, path);
+
+                // store state if browser doesn't support `history.state`
+                if (!supportsHistoryState) {
+                    this._historyState = state;
+                }
+
+                // used for webkit workaround
+                this._previousURL = this.getURL();
+            },
+
+            /**
+                    Register a callback to be invoked whenever the browser
+                    history changes, including using forward and back buttons.
+
+                    @private
+                    @method onUpdateURL
+                    @param callback {Function}
+                  */
+            onUpdateURL: function(callback) {
+                var guid = guidFor(this);
+                var self = this;
+
+                jQuery(window).on('popstate.ember-location-' + guid, function(e) {
+                    // Ignore initial page load popstate event in Chrome
+                    if (!popstateFired) {
+                        popstateFired = true;
+                        if (self.getURL() === self._previousURL) {
+                            return;
+                        }
+                    }
+                    callback(self.getURL());
+                });
+            },
+
+            /**
+                    Used when using `{{action}}` helper.  The url is always appended to the rootURL.
+
+                    @private
+                    @method formatURL
+                    @param url {String}
+                    @return formatted url {String}
+                  */
+            formatURL: function(url) {
+                var rootURL = get(this, 'rootURL');
+                var baseURL = get(this, 'baseURL');
+
+                if (url !== '') {
+                    rootURL = rootURL.replace(/\/$/, '');
+                    baseURL = baseURL.replace(/\/$/, '');
+                } else if (baseURL.match(/^\//) &amp;&amp; rootURL.match(/^\//)) {
+                    baseURL = baseURL.replace(/\/$/, '');
+                }
+
+                return baseURL + rootURL + url;
+            },
+
+            /**
+                    Cleans up the HistoryLocation event listener.
+
+                    @private
+                    @method willDestroy
+                  */
+            willDestroy: function() {
+                var guid = guidFor(this);
+
+                jQuery(window).off('popstate.ember-location-' + guid);
+            }
+        });
+    });
+    define(&quot;ember-routing/location/none_location&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var EmberObject = __dependency3__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              Ember.NoneLocation does not interact with the browser. It is useful for
+              testing, or when you need to manage state with your Router, but temporarily
+              don't want it to muck with the URL (for example when you embed your
+              application in a larger page).
+
+              @class NoneLocation
+              @namespace Ember
+              @extends Ember.Object
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            implementation: 'none',
+            path: '',
+
+            /**
+                    Returns the current path.
+
+                    @private
+                    @method getURL
+                    @return {String} path
+                  */
+            getURL: function() {
+                return get(this, 'path');
+            },
+
+            /**
+                    Set the path and remembers what was set. Using this method
+                    to change the path will not invoke the `updateURL` callback.
+
+                    @private
+                    @method setURL
+                    @param path {String}
+                  */
+            setURL: function(path) {
+                set(this, 'path', path);
+            },
+
+            /**
+                    Register a callback to be invoked when the path changes. These
+                    callbacks will execute when the user presses the back or forward
+                    button, but not after `setURL` is invoked.
+
+                    @private
+                    @method onUpdateURL
+                    @param callback {Function}
+                  */
+            onUpdateURL: function(callback) {
+                this.updateCallback = callback;
+            },
+
+            /**
+                    Sets the path and calls the `updateURL` callback.
+
+                    @private
+                    @method handleURL
+                    @param callback {Function}
+                  */
+            handleURL: function(url) {
+                set(this, 'path', url);
+                this.updateCallback(url);
+            },
+
+            /**
+                    Given a URL, formats it to be placed into the page as part
+                    of an element's `href` attribute.
+
+                    This is used, for example, when using the {{action}} helper
+                    to generate a URL based on an event.
+
+                    @private
+                    @method formatURL
+                    @param url {String}
+                    @return {String} url
+                  */
+            formatURL: function(url) {
+                // The return value is not overly meaningful, but we do not want to throw
+                // errors when test code renders templates containing {{action href=true}}
+                // helpers.
+                return url;
+            }
+        });
+    });
+    define(&quot;ember-routing/system/cache&quot;,
+    [&quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var EmberObject = __dependency1__[&quot;default&quot;];
+
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+            init: function() {
+                this.cache = {};
+            },
+            has: function(bucketKey) {
+                return bucketKey in this.cache;
+            },
+            stash: function(bucketKey, key, value) {
+                var bucket = this.cache[bucketKey];
+                if (!bucket) {
+                    bucket = this.cache[bucketKey] = {};
+                }
+                bucket[key] = value;
+            },
+            lookup: function(bucketKey, prop, defaultValue) {
+                var cache = this.cache;
+                if (!(bucketKey in cache)) {
+                    return defaultValue;
+                }
+                var bucket = cache[bucketKey];
+                if (prop in bucket) {
+                    return bucket[prop];
+                } else {
+                    return defaultValue;
+                }
+            },
+            cache: null
+        });
+    });
+    define(&quot;ember-routing/system/controller_for&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+
+              Finds a controller instance.
+
+              @for Ember
+              @method controllerFor
+              @private
+            */
+        __exports__[&quot;default&quot;] = function controllerFor(container, controllerName, lookupOptions) {
+            return container.lookup('controller:' + controllerName, lookupOptions);
+        }
+    });
+    define(&quot;ember-routing/system/dsl&quot;,
+    [&quot;ember-metal/core&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES, assert
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        function DSL(name) {
+            this.parent = name;
+            this.matches = [];
+        }
+        __exports__[&quot;default&quot;] = DSL;
+
+        DSL.prototype = {
+            route: function(name, options, callback) {
+                if (arguments.length === 2 &amp;&amp; typeof options === 'function') {
+                    callback = options;
+                    options = {};
+                }
+
+                if (arguments.length === 1) {
+                    options = {};
+                }
+
+                var type = options.resetNamespace === true ? 'resource' : 'route';
+                Ember.assert(&quot;'basic' cannot be used as a &quot; + type + &quot; name.&quot;, name !== 'basic');
+
+
+                if (typeof options.path !== 'string') {
+                    options.path = &quot;/&quot; + name;
+                }
+
+                if (canNest(this) &amp;&amp; options.resetNamespace !== true) {
+                    name = this.parent + &quot;.&quot; + name;
+                }
+
+                if (callback) {
+                    var dsl = new DSL(name);
+                    route(dsl, 'loading');
+                    route(dsl, 'error', {
+                        path: &quot;/_unused_dummy_error_path_route_&quot; + name + &quot;/:error&quot; 
+                    });
+
+                    if (callback) {
+                        callback.call(dsl);
+                    }
+
+                    this.push(options.path, name, dsl.generate());
+                } else {
+                    this.push(options.path, name, null);
+                }
+
+            },
+
+            push: function(url, name, callback) {
+                var parts = name.split('.');
+                if (url === &quot;&quot; || url === &quot;/&quot; || parts[parts.length-1] === &quot;index&quot;) {
+                    this.explicitIndex = true;
+                }
+
+                this.matches.push([url, name, callback]);
+            },
+
+            resource: function(name, options, callback) {
+                if (arguments.length === 2 &amp;&amp; typeof options === 'function') {
+                    callback = options;
+                    options = {};
+                }
+
+                if (arguments.length === 1) {
+                    options = {};
+                }
+
+                options.resetNamespace = true;
+                this.route(name, options, callback);
+            },
+
+            generate: function() {
+                var dslMatches = this.matches;
+
+                if (!this.explicitIndex) {
+                    route(this, &quot;index&quot;, {
+                        path: &quot;/&quot; 
+                    });
+                }
+
+                return function(match) {
+                    for (var i = 0, l = dslMatches.length; i &lt; l; i++) {
+                        var dslMatch = dslMatches[i];
+                        var matchObj = match(dslMatch[0]).to(dslMatch[1], dslMatch[2]);
+                    }
+                };
+            }
+        };
+
+        function canNest(dsl) {
+            return dsl.parent &amp;&amp; dsl.parent !== 'application';
+        }
+
+        function route(dsl, name, options) {
+            Ember.assert(&quot;You must use `this.resource` to nest&quot;, typeof options !== 'function');
+
+            options = options || {};
+
+            if (typeof options.path !== 'string') {
+                options.path = &quot;/&quot; + name;
+            }
+
+            if (canNest(dsl) &amp;&amp; options.resetNamespace !== true) {
+                name = dsl.parent + &quot;.&quot; + name;
+            }
+
+            dsl.push(options.path, name, null);
+        }
+
+        DSL.map = function(callback) {
+            var dsl = new DSL();
+            callback.call(dsl);
+            return dsl;
+        };
+    });
+    define(&quot;ember-routing/system/generate_controller&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Logger
+        var get = __dependency2__.get;
+        var isArray = __dependency3__.isArray;
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              Generates a controller factory
+
+              The type of the generated controller factory is derived
+              from the context. If the context is an array an array controller
+              is generated, if an object, an object controller otherwise, a basic
+              controller is generated.
+
+              You can customize your generated controllers by defining
+              `App.ObjectController` or `App.ArrayController`.
+
+              @for Ember
+              @method generateControllerFactory
+              @private
+            */
+
+        function generateControllerFactory(container, controllerName, context) {
+            var Factory, fullName, instance, name, factoryName, controllerType;
+
+            if (context &amp;&amp; isArray(context)) {
+                controllerType = 'array';
+            } else if (context) {
+                controllerType = 'object';
+            } else {
+                controllerType = 'basic';
+            }
+
+            factoryName = 'controller:' + controllerType;
+
+            Factory = container.lookupFactory(factoryName).extend({
+                isGenerated: true,
+                toString: function() {
+                    return &quot;(generated &quot; + controllerName + &quot; controller)&quot;;
+                }
+            });
+
+            fullName = 'controller:' + controllerName;
+
+            container.register(fullName, Factory);
+
+            return Factory;
+        }
+
+        __exports__.generateControllerFactory = generateControllerFactory; /**
+              Generates and instantiates a controller.
+
+              The type of the generated controller factory is derived
+              from the context. If the context is an array an array controller
+              is generated, if an object, an object controller otherwise, a basic
+              controller is generated.
+
+              @for Ember
+              @method generateController
+              @private
+              @since 1.3.0
+            */
+        __exports__[&quot;default&quot;] = function generateController(container, controllerName, context) {
+            generateControllerFactory(container, controllerName, context);
+            var fullName = 'controller:' + controllerName;
+            var instance = container.lookup(fullName);
+
+            if (get(instance, 'namespace.LOG_ACTIVE_GENERATION')) {
+                Ember.Logger.info(&quot;generated -&gt; &quot; + fullName, {
+                    fullName: fullName 
+                });
+            }
+
+            return instance;
+        }
+    });
+    define(&quot;ember-routing/system/route&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/get_properties&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-runtime/keys&quot;, &quot;ember-runtime/copy&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/mixins/action_handler&quot;, &quot;ember-routing/system/generate_controller&quot;, &quot;ember-routing-handlebars/helpers/shared&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES, K, A, deprecate, assert, Logger
+        var EmberError = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var getProperties = __dependency5__[&quot;default&quot;];
+        var forEach = __dependency6__.forEach;
+        var replace = __dependency6__.replace;
+        var isNone = __dependency7__.isNone;
+        var computed = __dependency8__.computed;
+        var merge = __dependency9__[&quot;default&quot;];
+        var isArray = __dependency10__.isArray;
+        var typeOf = __dependency10__.typeOf;
+        var run = __dependency11__[&quot;default&quot;];
+        var keys = __dependency12__[&quot;default&quot;];
+        var copy = __dependency13__[&quot;default&quot;];
+        var classify = __dependency14__.classify;
+        var fmt = __dependency14__.fmt;
+        var EmberObject = __dependency15__[&quot;default&quot;];
+        var ActionHandler = __dependency16__[&quot;default&quot;];
+        var generateController = __dependency17__[&quot;default&quot;];
+        var stashParamNames = __dependency18__.stashParamNames;
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        /**
+              The `Ember.Route` class is used to define individual routes. Refer to
+              the [routing guide](http://emberjs.com/guides/routing/) for documentation.
+
+              @class Route
+              @namespace Ember
+              @extends Ember.Object
+              @uses Ember.ActionHandler
+            */
+        var Route = EmberObject.extend(ActionHandler, {
+
+            /**
+                    @private
+
+                    @method exit
+                  */
+            exit: function() {
+                this.deactivate();
+                this.teardownViews();
+            },
+
+            /**
+                    @private
+
+                    @method reset
+                  */
+            reset: function(isExiting, transition) {
+
+                var controller = this.controller;
+                controller._qpDelegate = get(this, '_qp.states.inactive');
+                this.resetController(this.controller, isExiting, transition);
+
+            },
+
+            /**
+                    @private
+
+                    @method enter
+                  */
+            enter: function() {
+                this.activate();
+            },
+
+            /**
+                    The name of the view to use by default when rendering this routes template.
+
+                    When rendering a template, the route will, by default, determine the
+                    template and view to use from the name of the route itself. If you need to
+                    define a specific view, set this property.
+
+                    This is useful when multiple routes would benefit from using the same view
+                    because it doesn't require a custom `renderTemplate` method. For example,
+                    the following routes will all render using the `App.PostsListView` view:
+
+                    ```js
+                    var PostsList = Ember.Route.extend({
+                      viewName: 'postsList'
+                    });
+
+                    App.PostsIndexRoute = PostsList.extend();
+                    App.PostsArchivedRoute = PostsList.extend();
+                    ```
+
+                    @property viewName
+                    @type String
+                    @default null
+                    @since 1.4.0
+                  */
+            viewName: null,
+
+            /**
+                    The name of the template to use by default when rendering this routes
+                    template.
+
+                    This is similar with `viewName`, but is useful when you just want a custom
+                    template without a view.
+
+                    ```js
+                    var PostsList = Ember.Route.extend({
+                      templateName: 'posts/list'
+                    });
+
+                    App.PostsIndexRoute = PostsList.extend();
+                    App.PostsArchivedRoute = PostsList.extend();
+                    ```
+
+                    @property templateName
+                    @type String
+                    @default null
+                    @since 1.4.0
+                  */
+            templateName: null,
+
+            /**
+                    The name of the controller to associate with this route.
+
+                    By default, Ember will lookup a route's controller that matches the name
+                    of the route (i.e. `App.PostController` for `App.PostRoute`). However,
+                    if you would like to define a specific controller to use, you can do so
+                    using this property.
+
+                    This is useful in many ways, as the controller specified will be:
+
+                    * passed to the `setupController` method.
+                    * used as the controller for the view being rendered by the route.
+                    * returned from a call to `controllerFor` for the route.
+
+                    @property controllerName
+                    @type String
+                    @default null
+                    @since 1.4.0
+                  */
+            controllerName: null,
+
+            /**
+                    The `willTransition` action is fired at the beginning of any
+                    attempted transition with a `Transition` object as the sole
+                    argument. This action can be used for aborting, redirecting,
+                    or decorating the transition from the currently active routes.
+
+                    A good example is preventing navigation when a form is
+                    half-filled out:
+
+                    ```js
+                    App.ContactFormRoute = Ember.Route.extend({
+                      actions: {
+                        willTransition: function(transition) {
+                          if (this.controller.get('userHasEnteredData')) {
+                            this.controller.displayNavigationConfirm();
+                            transition.abort();
+                          }
+                        }
+                      }
+                    });
+                    ```
+
+                    You can also redirect elsewhere by calling
+                    `this.transitionTo('elsewhere')` from within `willTransition`.
+                    Note that `willTransition` will not be fired for the
+                    redirecting `transitionTo`, since `willTransition` doesn't
+                    fire when there is already a transition underway. If you want
+                    subsequent `willTransition` actions to fire for the redirecting
+                    transition, you must first explicitly call
+                    `transition.abort()`.
+
+                    @event willTransition
+                    @param {Transition} transition
+                  */
+
+            /**
+                    The `didTransition` action is fired after a transition has
+                    successfully been completed. This occurs after the normal model
+                    hooks (`beforeModel`, `model`, `afterModel`, `setupController`)
+                    have resolved. The `didTransition` action has no arguments,
+                    however, it can be useful for tracking page views or resetting
+                    state on the controller.
+
+                    ```js
+                    App.LoginRoute = Ember.Route.extend({
+                      actions: {
+                        didTransition: function() {
+                          this.controller.get('errors.base').clear();
+                          return true; // Bubble the didTransition event
+                        }
+                      }
+                    });
+                    ```
+
+                    @event didTransition
+                    @since 1.2.0
+                  */
+
+            /**
+                    The `loading` action is fired on the route when a route's `model`
+                    hook returns a promise that is not already resolved. The current
+                    `Transition` object is the first parameter and the route that
+                    triggered the loading event is the second parameter.
+
+                    ```js
+                    App.ApplicationRoute = Ember.Route.extend({
+                      actions: {
+                        loading: function(transition, route) {
+                          var view = Ember.View.create({
+                            classNames: ['app-loading']
+                          })
+                          .append();
+
+                          this.router.one('didTransition', function () {
+                            view.destroy();
+                          });
+                          return true; // Bubble the loading event
+                        }
+                      }
+                    });
+                    ```
+
+                    @event loading
+                    @param {Transition} transition
+                    @param {Ember.Route} route The route that triggered the loading event
+                    @since 1.2.0
+                  */
+
+            /**
+                    When attempting to transition into a route, any of the hooks
+                    may return a promise that rejects, at which point an `error`
+                    action will be fired on the partially-entered routes, allowing
+                    for per-route error handling logic, or shared error handling
+                    logic defined on a parent route.
+
+                    Here is an example of an error handler that will be invoked
+                    for rejected promises from the various hooks on the route,
+                    as well as any unhandled errors from child routes:
+
+                    ```js
+                    App.AdminRoute = Ember.Route.extend({
+                      beforeModel: function() {
+                        return Ember.RSVP.reject(&quot;bad things!&quot;);
+                      },
+
+                      actions: {
+                        error: function(error, transition) {
+                          // Assuming we got here due to the error in `beforeModel`,
+                          // we can expect that error === &quot;bad things!&quot;,
+                          // but a promise model rejecting would also
+                          // call this hook, as would any errors encountered
+                          // in `afterModel`.
+
+                          // The `error` hook is also provided the failed
+                          // `transition`, which can be stored and later
+                          // `.retry()`d if desired.
+
+                          this.transitionTo('login');
+                        }
+                      }
+                    });
+                    ```
+
+                    `error` actions that bubble up all the way to `ApplicationRoute`
+                    will fire a default error handler that logs the error. You can
+                    specify your own global default error handler by overriding the
+                    `error` handler on `ApplicationRoute`:
+
+                    ```js
+                    App.ApplicationRoute = Ember.Route.extend({
+                      actions: {
+                        error: function(error, transition) {
+                          this.controllerFor('banner').displayError(error.message);
+                        }
+                      }
+                    });
+                    ```
+                    @event error
+                    @param {Error} error
+                    @param {Transition} transition
+                  */
+
+            /**
+                    The controller associated with this route.
+
+                    Example
+
+                    ```javascript
+                    App.FormRoute = Ember.Route.extend({
+                      actions: {
+                        willTransition: function(transition) {
+                          if (this.controller.get('userHasEnteredData') &amp;&amp;
+                              !confirm(&quot;Are you sure you want to abandon progress?&quot;)) {
+                            transition.abort();
+                          } else {
+                            // Bubble the `willTransition` action so that
+                            // parent routes can decide whether or not to abort.
+                            return true;
+                          }
+                        }
+                      }
+                    });
+                    ```
+
+                    @property controller
+                    @type Ember.Controller
+                    @since 1.6.0
+                  */
+
+            _actions: {
+
+                queryParamsDidChange: function(changed, totalPresent, removed) {
+
+                    var totalChanged = keys(changed).concat(keys(removed));
+                    for (var i = 0, len = totalChanged.length; i &lt; len; ++i) {
+                        var urlKey = totalChanged[i],
+                        options = get(this.queryParams, urlKey) || {};
+                        if (get(options, 'refreshModel')) {
+                            this.refresh();
+                        }
+                    }
+                    return true;
+
+                },
+
+                finalizeQueryParamChange: function(params, finalParams, transition) {
+
+                    if (this.routeName !== 'application') {
+                        return true;
+                    }
+
+                    // Transition object is absent for intermediate transitions.
+                    if (!transition) {
+                        return;
+                    }
+
+                    var handlerInfos = transition.state.handlerInfos;
+                    var router = this.router;
+                    var qpMeta = router._queryParamsFor(handlerInfos[handlerInfos.length-1].name);
+                    var changes = router._qpUpdates;
+                    var replaceUrl;
+
+                    stashParamNames(router, handlerInfos);
+
+                    for (var i = 0, len = qpMeta.qps.length; i &lt; len; ++i) {
+                        var qp = qpMeta.qps[i];
+                        var route = qp.route;
+                        var controller = route.controller;
+                        var presentKey = qp.urlKey in params &amp;&amp; qp.urlKey;
+
+                        // Do a reverse lookup to see if the changed query
+                        // param URL key corresponds to a QP property on
+                        // this controller.
+                        var value, svalue;
+                        if (changes &amp;&amp; qp.urlKey in changes) {
+                            // Controller overrode this value in setupController
+                            value = get(controller, qp.prop);
+                            svalue = route.serializeQueryParam(value, qp.urlKey, qp.type);
+                        } else {
+                            if (presentKey) {
+                                svalue = params[presentKey];
+                                value = route.deserializeQueryParam(svalue, qp.urlKey, qp.type);
+                            } else {
+                                // No QP provided; use default value.
+                                svalue = qp.sdef;
+                                value = qp.def;
+                                if (isArray(value)) {
+                                    value = Ember.A(value.slice());
+                                }
+                            }
+                        }
+
+                        controller._qpDelegate = get(this, '_qp.states.inactive');
+
+                        var thisQueryParamChanged = (svalue !== qp.svalue);
+                        if (thisQueryParamChanged) {
+                            var options = get(route, 'queryParams.' + qp.urlKey) || {};
+
+                            if (transition.queryParamsOnly &amp;&amp; replaceUrl !== false) {
+                                var replaceConfigValue = get(options, 'replace');
+                                if (replaceConfigValue) {
+                                    replaceUrl = true;
+                                } else if (replaceConfigValue === false) {
+                                    // Explicit pushState wins over any other replaceStates.
+                                    replaceUrl = false;
+                                }
+                            }
+
+                            set(controller, qp.prop, value);
+                        }
+
+                        // Stash current serialized value of controller.
+                        qp.svalue = svalue;
+
+                        var thisQueryParamHasDefaultValue = (qp.sdef === svalue);
+                        if (!thisQueryParamHasDefaultValue) {
+                            finalParams.push({
+                                value: svalue,
+                                visible: true,
+                                key: presentKey || qp.urlKey
+                            });
+                        }
+                    }
+
+                    if (replaceUrl) {
+                        transition.method('replace');
+                    }
+
+                    forEach(qpMeta.qps, function(qp) {
+                        var routeQpMeta = get(qp.route, '_qp');
+                        var finalizedController = qp.route.controller;
+                        finalizedController._qpDelegate = get(routeQpMeta, 'states.active');
+                    });
+                    router._qpUpdates = null;
+
+                }
+            },
+
+            /**
+                    @deprecated
+
+                    Please use `actions` instead.
+                    @method events
+                  */
+            events: null,
+
+            mergedProperties: ['events'],
+
+            /**
+                    This hook is executed when the router completely exits this route. It is
+                    not executed when the model for the route changes.
+
+                    @method deactivate
+                  */
+            deactivate: Ember.K,
+
+            /**
+                    This hook is executed when the router enters the route. It is not executed
+                    when the model for the route changes.
+
+                    @method activate
+                  */
+            activate: Ember.K,
+
+            /**
+                    Transition the application into another route. The route may
+                    be either a single route or route path:
+
+                    ```javascript
+                    this.transitionTo('blogPosts');
+                    this.transitionTo('blogPosts.recentEntries');
+                    ```
+
+                    Optionally supply a model for the route in question. The model
+                    will be serialized into the URL using the `serialize` hook of
+                    the route:
+
+                    ```javascript
+                    this.transitionTo('blogPost', aPost);
+                    ```
+
+                    If a literal is passed (such as a number or a string), it will
+                    be treated as an identifier instead. In this case, the `model`
+                    hook of the route will be triggered:
+
+                    ```javascript
+                    this.transitionTo('blogPost', 1);
+                    ```
+
+                    Multiple models will be applied last to first recursively up the
+                    resource tree.
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.resource('blogPost', {path:':blogPostId'}, function(){
+                        this.resource('blogComment', {path: ':blogCommentId'});
+                      });
+                    });
+
+                    this.transitionTo('blogComment', aPost, aComment);
+                    this.transitionTo('blogComment', 1, 13);
+                    ```
+
+                    It is also possible to pass a URL (a string that starts with a
+                    `/`). This is intended for testing and debugging purposes and
+                    should rarely be used in production code.
+
+                    ```javascript
+                    this.transitionTo('/');
+                    this.transitionTo('/blog/post/1/comment/13');
+                    ```
+
+                    See also 'replaceWith'.
+
+                    Simple Transition Example
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.route(&quot;index&quot;);
+                      this.route(&quot;secret&quot;);
+                      this.route(&quot;fourOhFour&quot;, { path: &quot;*:&quot;});
+                    });
+
+                    App.IndexRoute = Ember.Route.extend({
+                      actions: {
+                        moveToSecret: function(context){
+                          if (authorized()){
+                            this.transitionTo('secret', context);
+                          }
+                            this.transitionTo('fourOhFour');
+                        }
+                      }
+                    });
+                    ```
+
+                    Transition to a nested route
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.resource('articles', { path: '/articles' }, function() {
+                        this.route('new');
+                      });
+                    });
+
+                    App.IndexRoute = Ember.Route.extend({
+                      actions: {
+                        transitionToNewArticle: function() {
+                          this.transitionTo('articles.new');
+                        }
+                      }
+                    });
+                    ```
+
+                    Multiple Models Example
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.route(&quot;index&quot;);
+                      this.resource('breakfast', {path:':breakfastId'}, function(){
+                        this.resource('cereal', {path: ':cerealId'});
+                      });
+                    });
+
+                    App.IndexRoute = Ember.Route.extend({
+                      actions: {
+                        moveToChocolateCereal: function(){
+                          var cereal = { cerealId: &quot;ChocolateYumminess&quot;},
+                              breakfast = {breakfastId: &quot;CerealAndMilk&quot;};
+
+                          this.transitionTo('cereal', breakfast, cereal);
+                        }
+                      }
+                    });
+                    ```
+
+                    @method transitionTo
+                    @param {String} name the name of the route or a URL
+                    @param {...Object} models the model(s) or identifier(s) to be used while
+                      transitioning to the route.
+                    @return {Transition} the transition object associated with this
+                      attempted transition
+                  */
+            transitionTo: function(name, context) {
+                var router = this.router;
+                return router.transitionTo.apply(router, arguments);
+            },
+
+            /**
+                    Perform a synchronous transition into another route without attempting
+                    to resolve promises, update the URL, or abort any currently active
+                    asynchronous transitions (i.e. regular transitions caused by
+                    `transitionTo` or URL changes).
+
+                    This method is handy for performing intermediate transitions on the
+                    way to a final destination route, and is called internally by the
+                    default implementations of the `error` and `loading` handlers.
+
+                    @method intermediateTransitionTo
+                    @param {String} name the name of the route
+                    @param {...Object} models the model(s) to be used while transitioning
+                    to the route.
+                    @since 1.2.0
+                   */
+            intermediateTransitionTo: function() {
+                var router = this.router;
+                router.intermediateTransitionTo.apply(router, arguments);
+            },
+
+            /**
+                    Refresh the model on this route and any child routes, firing the
+                    `beforeModel`, `model`, and `afterModel` hooks in a similar fashion
+                    to how routes are entered when transitioning in from other route.
+                    The current route params (e.g. `article_id`) will be passed in
+                    to the respective model hooks, and if a different model is returned,
+                    `setupController` and associated route hooks will re-fire as well.
+
+                    An example usage of this method is re-querying the server for the
+                    latest information using the same parameters as when the route
+                    was first entered.
+
+                    Note that this will cause `model` hooks to fire even on routes
+                    that were provided a model object when the route was initially
+                    entered.
+
+                    @method refresh
+                    @return {Transition} the transition object associated with this
+                      attempted transition
+                    @since 1.4.0
+                   */
+            refresh: function() {
+                return this.router.router.refresh(this);
+            },
+
+            /**
+                    Transition into another route while replacing the current URL, if possible.
+                    This will replace the current history entry instead of adding a new one.
+                    Beside that, it is identical to `transitionTo` in all other respects. See
+                    'transitionTo' for additional information regarding multiple models.
+
+                    Example
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.route(&quot;index&quot;);
+                      this.route(&quot;secret&quot;);
+                    });
+
+                    App.SecretRoute = Ember.Route.extend({
+                      afterModel: function() {
+                        if (!authorized()){
+                          this.replaceWith('index');
+                        }
+                      }
+                    });
+                    ```
+
+                    @method replaceWith
+                    @param {String} name the name of the route or a URL
+                    @param {...Object} models the model(s) or identifier(s) to be used while
+                      transitioning to the route.
+                    @return {Transition} the transition object associated with this
+                      attempted transition
+                  */
+            replaceWith: function() {
+                var router = this.router;
+                return router.replaceWith.apply(router, arguments);
+            },
+
+            /**
+                    Sends an action to the router, which will delegate it to the currently
+                    active route hierarchy per the bubbling rules explained under `actions`.
+
+                    Example
+
+                    ```javascript
+                    App.Router.map(function() {
+                      this.route(&quot;index&quot;);
+                    });
+
+                    App.ApplicationRoute = Ember.Route.extend({
+                      actions: {
+                        track: function(arg) {
+                          console.log(arg, 'was clicked');
+                        }
+                      }
+                    });
+
+                    App.IndexRoute = Ember.Route.extend({
+                      actions: {
+                        trackIfDebug: function(arg) {
+                          if (debug) {
+                            this.send('track', arg);
+                          }
+                        }
+                      }
+                    });
+                    ```
+
+                    @method send
+                    @param {String} name the name of the action to trigger
+                    @param {...*} args
+                  */
+            send: function() {
+                return this.router.send.apply(this.router, arguments);
+            },
+
+            /**
+                    This hook is the entry point for router.js
+
+                    @private
+                    @method setup
+                  */
+            setup: function(context, transition) {
+                var controllerName = this.controllerName || this.routeName;
+                var controller = this.controllerFor(controllerName, true);
+
+                if (!controller) {
+                    controller = this.generateController(controllerName, context);
+                }
+
+                // Assign the route's controller so that it can more easily be
+                // referenced in action handlers
+                this.controller = controller;
+
+                if (this.setupControllers) {
+                    Ember.deprecate(&quot;Ember.Route.setupControllers is deprecated. Please use Ember.Route.setupController(controller, model) instead.&quot;);
+                    this.setupControllers(controller, context);
+                } else {
+
+                    var states = get(this, '_qp.states');
+                    if (transition) {
+                        // Update the model dep values used to calculate cache keys.
+                        controller._qpDelegate = states.changingKeys;
+                        controller._updateCacheParams(transition.params);
+                    }
+                    controller._qpDelegate = states.allowOverrides;
+
+                    this.setupController(controller, context, transition);
+                }
+
+                if (this.renderTemplates) {
+                    Ember.deprecate(&quot;Ember.Route.renderTemplates is deprecated. Please use Ember.Route.renderTemplate(controller, model) instead.&quot;);
+                    this.renderTemplates(context);
+                } else {
+                    this.renderTemplate(controller, context);
+                }
+            },
+
+            /**
+                    This hook is the first of the route entry validation hooks
+                    called when an attempt is made to transition into a route
+                    or one of its children. It is called before `model` and
+                    `afterModel`, and is appropriate for cases when:
+
+                    1) A decision can be made to redirect elsewhere without
+                       needing to resolve the model first.
+                    2) Any async operations need to occur first before the
+                       model is attempted to be resolved.
+
+                    This hook is provided the current `transition` attempt
+                    as a parameter, which can be used to `.abort()` the transition,
+                    save it for a later `.retry()`, or retrieve values set
+                    on it from a previous hook. You can also just call
+                    `this.transitionTo` to another route to implicitly
+                    abort the `transition`.
+
+                    You can return a promise from this hook to pause the
+                    transition until the promise resolves (or rejects). This could
+                    be useful, for instance, for retrieving async code from
+                    the server that is required to enter a route.
+
+                    ```js
+                    App.PostRoute = Ember.Route.extend({
+                      beforeModel: function(transition) {
+                        if (!App.Post) {
+                          return Ember.$.getScript('/models/post.js');
+                        }
+                      }
+                    });
+                    ```
+
+                    If `App.Post` doesn't exist in the above example,
+                    `beforeModel` will use jQuery's `getScript`, which
+                    returns a promise that resolves after the server has
+                    successfully retrieved and executed the code from the
+                    server. Note that if an error were to occur, it would
+                    be passed to the `error` hook on `Ember.Route`, but
+                    it's also possible to handle errors specific to
+                    `beforeModel` right from within the hook (to distinguish
+                    from the shared error handling behavior of the `error`
+                    hook):
+
+                    ```js
+                    App.PostRoute = Ember.Route.extend({
+                      beforeModel: function(transition) {
+                        if (!App.Post) {
+                          var self = this;
+                          return Ember.$.getScript('post.js').then(null, function(e) {
+                            self.transitionTo('help');
+
+                            // Note that the above transitionTo will implicitly
+                            // halt the transition. If you were to return
+                            // nothing from this promise reject handler,
+                            // according to promise semantics, that would
+                            // convert the reject into a resolve and the
+                            // transition would continue. To propagate the
+                            // error so that it'd be handled by the `error`
+                            // hook, you would have to either
+                            return Ember.RSVP.reject(e);
+                          });
+                        }
+                      }
+                    });
+                    ```
+
+                    @method beforeModel
+                    @param {Transition} transition
+                    @param {Object} queryParams the active query params for this route
+                    @return {Promise} if the value returned from this hook is
+                      a promise, the transition will pause until the transition
+                      resolves. Otherwise, non-promise return values are not
+                      utilized in any way.
+                  */
+            beforeModel: Ember.K,
+
+            /**
+                    This hook is called after this route's model has resolved.
+                    It follows identical async/promise semantics to `beforeModel`
+                    but is provided the route's resolved model in addition to
+                    the `transition`, and is therefore suited to performing
+                    logic that can only take place after the model has already
+                    resolved.
+
+                    ```js
+                    App.PostsRoute = Ember.Route.extend({
+                      afterModel: function(posts, transition) {
+                        if (posts.get('length') === 1) {
+                          this.transitionTo('post.show', posts.get('firstObject'));
+                        }
+                      }
+                    });
+                    ```
+
+                    Refer to documentation for `beforeModel` for a description
+                    of transition-pausing semantics when a promise is returned
+                    from this hook.
+
+                    @method afterModel
+                    @param {Object} resolvedModel the value returned from `model`,
+                      or its resolved value if it was a promise
+                    @param {Transition} transition
+                    @param {Object} queryParams the active query params for this handler
+                    @return {Promise} if the value returned from this hook is
+                      a promise, the transition will pause until the transition
+                      resolves. Otherwise, non-promise return values are not
+                      utilized in any way.
+                   */
+            afterModel: Ember.K,
+
+            /**
+                    A hook you can implement to optionally redirect to another route.
+
+                    If you call `this.transitionTo` from inside of this hook, this route
+                    will not be entered in favor of the other hook.
+
+                    `redirect` and `afterModel` behave very similarly and are
+                    called almost at the same time, but they have an important
+                    distinction in the case that, from one of these hooks, a
+                    redirect into a child route of this route occurs: redirects
+                    from `afterModel` essentially invalidate the current attempt
+                    to enter this route, and will result in this route's `beforeModel`,
+                    `model`, and `afterModel` hooks being fired again within
+                    the new, redirecting transition. Redirects that occur within
+                    the `redirect` hook, on the other hand, will _not_ cause
+                    these hooks to be fired again the second time around; in
+                    other words, by the time the `redirect` hook has been called,
+                    both the resolved model and attempted entry into this route
+                    are considered to be fully validated.
+
+                    @method redirect
+                    @param {Object} model the model for this route
+                  */
+            redirect: Ember.K,
+
+            /**
+                    Called when the context is changed by router.js.
+
+                    @private
+                    @method contextDidChange
+                  */
+            contextDidChange: function() {
+                this.currentModel = this.context;
+            },
+
+            /**
+                    A hook you can implement to convert the URL into the model for
+                    this route.
+
+                    ```js
+                    App.Router.map(function() {
+                      this.resource('post', {path: '/posts/:post_id'});
+                    });
+                    ```
+
+                    The model for the `post` route is `App.Post.find(params.post_id)`.
+
+                    By default, if your route has a dynamic segment ending in `_id`:
+
+                    * The model class is determined from the segment (`post_id`'s
+                      class is `App.Post`)
+                    * The find method is called on the model class with the value of
+                      the dynamic segment.
+
+                    Note that for routes with dynamic segments, this hook is only
+                    executed when entered via the URL. If the route is entered
+                    through a transition (e.g. when using the `link-to` Handlebars
+                    helper), then a model context is already provided and this hook
+                    is not called. Routes without dynamic segments will always
+                    execute the model hook.
+
+                    This hook follows the asynchronous/promise semantics
+                    described in the documentation for `beforeModel`. In particular,
+                    if a promise returned from `model` fails, the error will be
+                    handled by the `error` hook on `Ember.Route`.
+
+                    Example
+
+                    ```js
+                    App.PostRoute = Ember.Route.extend({
+                      model: function(params) {
+                        return App.Post.find(params.post_id);
+                      }
+                    });
+                    ```
+
+                    @method model
+                    @param {Object} params the parameters extracted from the URL
+                    @param {Transition} transition
+                    @param {Object} queryParams the query params for this route
+                    @return {Object|Promise} the model for this route. If
+                      a promise is returned, the transition will pause until
+                      the promise resolves, and the resolved value of the promise
+                      will be used as the model for this route.
+                  */
+            model: function(params, transition) {
+                var match, name, sawParams, value;
+
+                var queryParams;
+
+                queryParams = get(this, '_qp.map');
+
+
+                for (var prop in params) {
+                    if (prop === 'queryParams' || (queryParams &amp;&amp; prop in queryParams)) {
+                        continue;
+                    }
+
+                    if (match = prop.match(/^(.*)_id$/)) {
+                        name = match[1];
+                        value = params[prop];
+                    }
+                    sawParams = true;
+                }
+
+                if (!name &amp;&amp; sawParams) {
+                    return copy(params);
+                } else if (!name) {
+                    if (transition.resolveIndex !== transition.state.handlerInfos.length-1) {
+                        return;
+                    }
+
+                    var parentModel = transition.state.handlerInfos[transition.resolveIndex-1].context;
+
+                    return parentModel;
+                }
+
+                return this.findModel(name, value);
+            },
+
+            /**
+                    @private
+                    @method deserialize
+                    @param {Object} params the parameters extracted from the URL
+                    @param {Transition} transition
+                    @return {Object|Promise} the model for this route.
+
+                    Router.js hook.
+                   */
+            deserialize: function(params, transition) {
+
+                return this.model(this.paramsFor(this.routeName), transition);
+            },
+
+            /**
+
+                    @method findModel
+                    @param {String} type the model type
+                    @param {Object} value the value passed to find
+                  */
+            findModel: function() {
+                var store = get(this, 'store');
+                return store.find.apply(store, arguments);
+            },
+
+            /**
+                    Store property provides a hook for data persistence libraries to inject themselves.
+
+                    By default, this store property provides the exact same functionality previously
+                    in the model hook.
+
+                    Currently, the required interface is:
+
+                    `store.find(modelName, findArguments)`
+
+                    @method store
+                    @param {Object} store
+                  */
+            store: computed(function() {
+                var container = this.container;
+                var routeName = this.routeName;
+                var namespace = get(this, 'router.namespace');
+
+                return {
+                    find: function(name, value) {
+                        var modelClass = container.lookupFactory('model:' + name);
+
+                        Ember.assert(&quot;You used the dynamic segment &quot; + name + &quot;_id in your route &quot; +
+                        routeName + &quot;, but &quot; + namespace + &quot;.&quot; + classify(name) +
+                        &quot; did not exist and you did not override your route's `model` &quot; +
+                        &quot;hook.&quot;, modelClass);
+
+                        if (!modelClass) {
+                            return;
+                        }
+
+                        Ember.assert(classify(name) + ' has no method `find`.', typeof modelClass.find === 'function');
+
+                        return modelClass.find(value);
+                    }
+                };
+            }),
+
+            /**
+                    A hook you can implement to convert the route's model into parameters
+                    for the URL.
+
+                    ```js
+                    App.Router.map(function() {
+                      this.resource('post', {path: '/posts/:post_id'});
+                    });
+
+                    App.PostRoute = Ember.Route.extend({
+                      model: function(params) {
+                        // the server returns `{ id: 12 }`
+                        return jQuery.getJSON(&quot;/posts/&quot; + params.post_id);
+                      },
+
+                      serialize: function(model) {
+                        // this will make the URL `/posts/12`
+                        return { post_id: model.id };
+                      }
+                    });
+                    ```
+
+                    The default `serialize` method will insert the model's `id` into the
+                    route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
+                    If the route has multiple dynamic segments or does not contain '_id', `serialize`
+                    will return `Ember.getProperties(model, params)`
+
+                    This method is called when `transitionTo` is called with a context
+                    in order to populate the URL.
+
+                    @method serialize
+                    @param {Object} model the route's model
+                    @param {Array} params an Array of parameter names for the current
+                      route (in the example, `['post_id']`.
+                    @return {Object} the serialized parameters
+                  */
+            serialize: function(model, params) {
+                if (params.length &lt; 1) {
+                    return;
+                }
+                if (!model) {
+                    return;
+                }
+
+                var name = params[0], object = {};
+
+                if (/_id$/.test(name) &amp;&amp; params.length === 1) {
+                    object[name] = get(model, &quot;id&quot;);
+                } else {
+                    object = getProperties(model, params);
+                }
+
+                return object;
+            },
+
+            /**
+                    A hook you can use to setup the controller for the current route.
+
+                    This method is called with the controller for the current route and the
+                    model supplied by the `model` hook.
+
+                    By default, the `setupController` hook sets the `model` property of
+                    the controller to the `model`.
+
+                    If you implement the `setupController` hook in your Route, it will
+                    prevent this default behavior. If you want to preserve that behavior
+                    when implementing your `setupController` function, make sure to call
+                    `_super`:
+
+                    ```js
+                    App.PhotosRoute = Ember.Route.extend({
+                      model: function() {
+                        return App.Photo.find();
+                      },
+
+                      setupController: function (controller, model) {
+                        // Call _super for default behavior
+                        this._super(controller, model);
+                        // Implement your custom setup after
+                        this.controllerFor('application').set('showingPhotos', true);
+                      }
+                    });
+                    ```
+
+                    This means that your template will get a proxy for the model as its
+                    context, and you can act as though the model itself was the context.
+
+                    The provided controller will be one resolved based on the name
+                    of this route.
+
+                    If no explicit controller is defined, Ember will automatically create
+                    an appropriate controller for the model.
+
+                    * if the model is an `Ember.Array` (including record arrays from Ember
+                      Data), the controller is an `Ember.ArrayController`.
+                    * otherwise, the controller is an `Ember.ObjectController`.
+
+                    As an example, consider the router:
+
+                    ```js
+                    App.Router.map(function() {
+                      this.resource('post', {path: '/posts/:post_id'});
+                    });
+                    ```
+
+                    For the `post` route, a controller named `App.PostController` would
+                    be used if it is defined. If it is not defined, an `Ember.ObjectController`
+                    instance would be used.
+
+                    Example
+
+                    ```js
+                    App.PostRoute = Ember.Route.extend({
+                      setupController: function(controller, model) {
+                        controller.set('model', model);
+                      }
+                    });
+                    ```
+
+                    @method setupController
+                    @param {Controller} controller instance
+                    @param {Object} model
+                  */
+            setupController: function(controller, context, transition) {
+                if (controller &amp;&amp; (context !== undefined)) {
+                    set(controller, 'model', context);
+                }
+            },
+
+            /**
+                    Returns the controller for a particular route or name.
+
+                    The controller instance must already have been created, either through entering the
+                    associated route or using `generateController`.
+
+                    ```js
+                    App.PostRoute = Ember.Route.extend({
+                      setupController: function(controller, post) {
+                        this._super(controller, post);
+                        this.controllerFor('posts').set('currentPost', post);
+                      }
+                    });
+                    ```
+
+                    @method controllerFor
+                    @param {String} name the name of the route or controller
+                    @return {Ember.Controller}
+                  */
+            controllerFor: function(name, _skipAssert) {
+                var container = this.container;
+                var route = container.lookup('route:' + name);
+                var controller;
+
+                if (route &amp;&amp; route.controllerName) {
+                    name = route.controllerName;
+                }
+
+                controller = container.lookup('controller:' + name);
+
+                // NOTE: We're specifically checking that skipAssert is true, because according
+                //   to the old API the second parameter was model. We do not want people who
+                //   passed a model to skip the assertion.
+                Ember.assert(&quot;The controller named '&quot; + name + &quot;' could not be found. Make sure &quot; +
+                &quot;that this route exists and has already been entered at least &quot; +
+                &quot;once. If you are accessing a controller not associated with a &quot; +
+                &quot;route, make sure the controller class is explicitly defined.&quot;,
+                controller || _skipAssert === true);
+
+                return controller;
+            },
+
+            /**
+                    Generates a controller for a route.
+
+                    If the optional model is passed then the controller type is determined automatically,
+                    e.g., an ArrayController for arrays.
+
+                    Example
+
+                    ```js
+                    App.PostRoute = Ember.Route.extend({
+                      setupController: function(controller, post) {
+                        this._super(controller, post);
+                        this.generateController('posts', post);
+                      }
+                    });
+                    ```
+
+                    @method generateController
+                    @param {String} name the name of the controller
+                    @param {Object} model the model to infer the type of the controller (optional)
+                  */
+            generateController: function(name, model) {
+                var container = this.container;
+
+                model = model || this.modelFor(name);
+
+                return generateController(container, name, model);
+            },
+
+            /**
+                    Returns the model of a parent (or any ancestor) route
+                    in a route hierarchy.  During a transition, all routes
+                    must resolve a model object, and if a route
+                    needs access to a parent route's model in order to
+                    resolve a model (or just reuse the model from a parent),
+                    it can call `this.modelFor(theNameOfParentRoute)` to
+                    retrieve it.
+
+                    Example
+
+                    ```js
+                    App.Router.map(function() {
+                        this.resource('post', { path: '/post/:post_id' }, function() {
+                            this.resource('comments');
+                        });
+                    });
+
+                    App.CommentsRoute = Ember.Route.extend({
+                        afterModel: function() {
+                            this.set('post', this.modelFor('post'));
+                        }
+                    });
+                    ```
+
+                    @method modelFor
+                    @param {String} name the name of the route
+                    @return {Object} the model object
+                  */
+            modelFor: function(name) {
+                var route = this.container.lookup('route:' + name);
+                var transition = this.router ? this.router.router.activeTransition : null;
+
+                // If we are mid-transition, we want to try and look up
+                // resolved parent contexts on the current transitionEvent.
+                if (transition) {
+                    var modelLookupName = (route &amp;&amp; route.routeName) || name;
+                    if (transition.resolvedModels.hasOwnProperty(modelLookupName)) {
+                        return transition.resolvedModels[modelLookupName];
+                    }
+                }
+
+                return route &amp;&amp; route.currentModel;
+            },
+
+            /**
+                    A hook you can use to render the template for the current route.
+
+                    This method is called with the controller for the current route and the
+                    model supplied by the `model` hook. By default, it renders the route's
+                    template, configured with the controller for the route.
+
+                    This method can be overridden to set up and render additional or
+                    alternative templates.
+
+                    ```js
+                    App.PostsRoute = Ember.Route.extend({
+                      renderTemplate: function(controller, model) {
+                        var favController = this.controllerFor('favoritePost');
+
+                        // Render the `favoritePost` template into
+                        // the outlet `posts`, and display the `favoritePost`
+                        // controller.
+                        this.render('favoritePost', {
+                          outlet: 'posts',
+                          controller: favController
+                        });
+                      }
+                    });
+                    ```
+
+                    @method renderTemplate
+                    @param {Object} controller the route's controller
+                    @param {Object} model the route's model
+                  */
+            renderTemplate: function(controller, model) {
+                this.render();
+            },
+
+            /**
+                    `render` is used to render a template into a region of another template
+                    (indicated by an `{{outlet}}`). `render` is used both during the entry
+                    phase of routing (via the `renderTemplate` hook) and later in response to
+                    user interaction.
+
+                    For example, given the following minimal router and templates:
+
+                    ```js
+                    Router.map(function() {
+                      this.resource('photos');
+                    });
+                    ```
+
+                    ```handlebars
+                    &lt;!-- application.hbs --&gt;
+                    &lt;div class='something-in-the-app-hbs'&gt;
+                      {{outlet &quot;anOutletName&quot;}}
+                    &lt;/div&gt;
+                    ```
+
+                    ```handlebars
+                    &lt;!-- photos.hbs --&gt;
+                    &lt;h1&gt;Photos&lt;/h1&gt;
+                    ```
+
+                    You can render `photos.hbs` into the `&quot;anOutletName&quot;` outlet of
+                    `application.hbs` by calling `render`:
+
+                    ```js
+                    // posts route
+                    Ember.Route.extend({
+                      renderTemplate: function(){
+                        this.render('posts', {
+                          into: 'application',
+                          outlet: 'anOutletName'
+                        })
+                      }
+                    });
+                    ```
+
+                    `render` additionally allows you to supply which `view`, `controller`, and
+                    `model` objects should be loaded and associated with the rendered template.
+
+
+                    ```js
+                    // posts route
+                    Ember.Route.extend({
+                      renderTemplate: function(controller, model){
+                        this.render('posts', {    // the template to render, referenced by name
+                          into: 'application',    // the template to render into, referenced by name
+                          outlet: 'anOutletName', // the outlet inside `options.template` to render into.
+                          view: 'aViewName',      // the view to use for this template, referenced by name
+                          controller: 'someControllerName', // the controller to use for this template, referenced by name
+                          model: model            // the model to set on `options.controller`.
+                        })
+                      }
+                    });
+                    ```
+
+                    The string values provided for the template name, view, and controller
+                    will eventually pass through to the resolver for lookup. See
+                    Ember.Resolver for how these are mapped to JavaScript objects in your
+                    application.
+
+                    Not all options need to be passed to `render`. Default values will be used
+                    based on the name of the route specified in the router or the Route's
+                    `controllerName`, `viewName` and and `templateName` properties.
+
+                    For example:
+
+                    ```js
+                    // router
+                    Router.map(function() {
+                      this.route('index');
+                      this.resource('post', {path: '/posts/:post_id'});
+                    });
+                    ```
+
+                    ```js
+                    // post route
+                    PostRoute = App.Route.extend({
+                      renderTemplate: function() {
+                        this.render(); // all defaults apply
+                      }
+                    });
+                    ```
+
+                    The name of the `PostRoute`, defined by the router, is `post`.
+
+                    The following equivalent default options will be applied when
+                    the Route calls `render`:
+
+                    ```js
+                    //
+                    this.render('post', {  // the template name associated with 'post' Route
+                      into: 'application', // the parent route to 'post' Route
+                      outlet: 'main',      // {{outlet}} and {{outlet 'main' are synonymous}},
+                      view: 'post',        // the view associated with the 'post' Route
+                      controller: 'post',  // the controller associated with the 'post' Route
+                    })
+                    ```
+
+                    By default the controller's `model` will be the route's model, so it does not
+                    need to be passed unless you wish to change which model is being used.
+
+                    @method render
+                    @param {String} name the name of the template to render
+                    @param {Object} options the options
+                    @param {String} options.into the template to render into,
+                                    referenced by name. Defaults to the parent template
+                    @param {String} options.outlet the outlet inside `options.template` to render into.
+                                    Defaults to 'main'
+                    @param {String} options.controller the controller to use for this template,
+                                    referenced by name. Defaults to the Route's paired controller
+                    @param {String} options.model the model object to set on `options.controller`
+                                    Defaults to the return value of the Route's model hook
+                  */
+            render: function(name, options) {
+                Ember.assert(&quot;The name in the given arguments is undefined&quot;, arguments.length &gt; 0 ? !isNone(arguments[0]) : true);
+
+                var namePassed = typeof name === 'string' &amp;&amp; !!name;
+
+                if (typeof name === 'object' &amp;&amp; !options) {
+                    options = name;
+                    name = this.routeName;
+                }
+
+                options = options || {};
+                options.namePassed = namePassed;
+
+                var templateName;
+
+                if (name) {
+                    name = name.replace(/\//g, '.');
+                    templateName = name;
+                } else {
+                    name = this.routeName;
+                    templateName = this.templateName || name;
+                }
+
+                var viewName = options.view || namePassed &amp;&amp; name || this.viewName || name;
+
+                var container = this.container;
+                var view = container.lookup('view:' + viewName);
+                var template = view ? view.get('template') : null;
+
+                if (!template) {
+                    template = container.lookup('template:' + templateName);
+                }
+
+                if (!view &amp;&amp; !template) {
+                    Ember.assert(&quot;Could not find \&quot;&quot; + name + &quot;\&quot; template or view.&quot;, Ember.isEmpty(arguments[0]));
+                    if (get(this.router, 'namespace.LOG_VIEW_LOOKUPS')) {
+                        Ember.Logger.info(&quot;Could not find \&quot;&quot; + name + &quot;\&quot; template or view. Nothing will be rendered&quot;, {
+                            fullName: 'template:' + name 
+                        });
+                    }
+                    return;
+                }
+
+                options = normalizeOptions(this, name, template, options);
+                view = setupView(view, container, options);
+
+                if (options.outlet === 'main') {
+                    this.lastRenderedTemplate = name;
+                }
+
+                appendView(this, view, options);
+            },
+
+            /**
+                    Disconnects a view that has been rendered into an outlet.
+
+                    You may pass any or all of the following options to `disconnectOutlet`:
+
+                    * `outlet`: the name of the outlet to clear (default: 'main')
+                    * `parentView`: the name of the view containing the outlet to clear
+                       (default: the view rendered by the parent route)
+
+                    Example:
+
+                    ```js
+                    App.ApplicationRoute = App.Route.extend({
+                      actions: {
+                        showModal: function(evt) {
+                          this.render(evt.modalName, {
+                            outlet: 'modal',
+                            into: 'application'
+                          });
+                        },
+                        hideModal: function(evt) {
+                          this.disconnectOutlet({
+                            outlet: 'modal',
+                            parentView: 'application'
+                          });
+                        }
+                      }
+                    });
+                    ```
+
+                    Alternatively, you can pass the `outlet` name directly as a string.
+
+                    Example:
+
+                    ```js
+                    hideModal: function(evt) {
+                      this.disconnectOutlet('modal');
+                    }
+                    ```
+
+                    @method disconnectOutlet
+                    @param {Object|String} options the options hash or outlet name
+                  */
+            disconnectOutlet: function(options) {
+                if (!options || typeof options === &quot;string&quot;) {
+                    var outletName = options;
+                    options = {};
+                    options.outlet = outletName;
+                }
+                options.parentView = options.parentView ? options.parentView.replace(/\//g, '.') : parentTemplate(this);
+                options.outlet = options.outlet || 'main';
+
+                var parentView = this.router._lookupActiveView(options.parentView);
+                if (parentView) {
+                    parentView.disconnectOutlet(options.outlet);
+                }
+            },
+
+            willDestroy: function() {
+                this.teardownViews();
+            },
+
+            /**
+                    @private
+
+                    @method teardownViews
+                  */
+            teardownViews: function() {
+                // Tear down the top level view
+                if (this.teardownTopLevelView) {
+                    this.teardownTopLevelView();
+                }
+
+                // Tear down any outlets rendered with 'into'
+                var teardownOutletViews = this.teardownOutletViews || [];
+                forEach(teardownOutletViews, function(teardownOutletView) {
+                    teardownOutletView();
+                });
+
+                delete this.teardownTopLevelView;
+                delete this.teardownOutletViews;
+                delete this.lastRenderedTemplate;
+            }
+        });
+
+        var defaultQPMeta = {
+            qps: [],
+            map: {},
+            states: {}
+        };
+
+
+        Route.reopen({
+            /**
+                      Configuration hash for this route's queryParams. The possible
+                      configuration options and their defaults are as follows
+                      (assuming a query param whose URL key is `page`):
+
+                      ```js
+                      queryParams: {
+                        page: {
+                          // By default, controller query param properties don't
+                          // cause a full transition when they are changed, but
+                          // rather only cause the URL to update. Setting
+                          // `refreshModel` to true will cause an &quot;in-place&quot;
+                          // transition to occur, whereby the model hooks for
+                          // this route (and any child routes) will re-fire, allowing
+                          // you to reload models (e.g., from the server) using the
+                          // updated query param values.
+                          refreshModel: false,
+
+                          // By default, changes to controller query param properties
+                          // cause the URL to update via `pushState`, which means an
+                          // item will be added to the browser's history, allowing
+                          // you to use the back button to restore the app to the
+                          // previous state before the query param property was changed.
+                          // Setting `replace` to true will use `replaceState` (or its
+                          // hash location equivalent), which causes no browser history
+                          // item to be added. This options name and default value are
+                          // the same as the `link-to` helper's `replace` option.
+                          replace: false
+                        }
+                      }
+                      ```
+
+                      @property queryParams
+                      @for Ember.Route
+                      @type Hash
+                    */
+            queryParams: {},
+
+            _qp: computed(function() {
+                var controllerName = this.controllerName || this.routeName;
+                var fullName = this.container.normalize('controller:' + controllerName);
+                var controllerClass = this.container.lookupFactory(fullName);
+
+                if (!controllerClass) {
+                    return defaultQPMeta;
+                }
+
+                var controllerProto = controllerClass.proto();
+                var qpProps = get(controllerProto, '_normalizedQueryParams');
+                var cacheMeta = get(controllerProto, '_cacheMeta');
+
+                var qps = [], map = {}, self = this;
+                for (var propName in qpProps) {
+                    if (!qpProps.hasOwnProperty(propName)) {
+                        continue;
+                    }
+
+                    var desc = qpProps[propName],
+                    urlKey = desc.as || this.serializeQueryParamKey(propName),
+                    defaultValue = get(controllerProto, propName);
+
+                    if (isArray(defaultValue)) {
+                        defaultValue = Ember.A(defaultValue.slice());
+                    }
+
+                    var type = typeOf(defaultValue),
+                    defaultValueSerialized = this.serializeQueryParam(defaultValue, urlKey, type),
+                    fprop = controllerName + ':' + propName,
+                    qp = {
+                        def: defaultValue,
+                        sdef: defaultValueSerialized,
+                        type: type,
+                        urlKey: urlKey,
+                        prop: propName,
+                        fprop: fprop,
+                        ctrl: controllerName,
+                        cProto: controllerProto,
+                        svalue: defaultValueSerialized,
+                        cacheType: desc.scope,
+                        route: this,
+                        cacheMeta: cacheMeta[propName]
+                    };
+
+                    map[propName] = map[urlKey] = map[fprop] = qp;
+                    qps.push(qp);
+                }
+
+                return {
+                    qps: qps,
+                    map: map,
+                    states: {
+                        active: function(controller, prop) {
+                            return self._activeQPChanged(controller, map[prop]);
+                        },
+                        allowOverrides: function(controller, prop) {
+                            return self._updatingQPChanged(controller, map[prop]);
+                        },
+                        changingKeys: function(controller, prop) {
+                            return self._updateSerializedQPValue(controller, map[prop]);
+                        }
+                    }
+                };
+            }),
+
+            _names: null,
+            _stashNames: function(_handlerInfo, dynamicParent) {
+                var handlerInfo = _handlerInfo;
+                if (this._names) {
+                    return;
+                }
+                var names = this._names = handlerInfo._names;
+
+                if (!names.length) {
+                    handlerInfo = dynamicParent;
+                    names = handlerInfo &amp;&amp; handlerInfo._names || [];
+                }
+
+                var qps = get(this, '_qp.qps');
+                var len = qps.length;
+
+                var namePaths = new Array(names.length);
+                for (var a = 0, nlen = names.length; a &lt; nlen; ++a) {
+                    namePaths[a] = handlerInfo.name + '.' + names[a];
+                }
+
+                for (var i = 0; i &lt; len; ++i) {
+                    var qp = qps[i];
+                    var cacheMeta = qp.cacheMeta;
+                    if (cacheMeta.scope === 'model') {
+                        cacheMeta.parts = namePaths;
+                    }
+                    cacheMeta.prefix = qp.ctrl;
+                }
+            },
+
+            _updateSerializedQPValue: function(controller, qp) {
+                var value = get(controller, qp.prop);
+                qp.svalue = this.serializeQueryParam(value, qp.urlKey, qp.type);
+            },
+
+            _activeQPChanged: function(controller, qp) {
+                var value = get(controller, qp.prop);
+                this.router._queuedQPChanges[qp.fprop] = value;
+                run.once(this, this._fireQueryParamTransition);
+            },
+
+            //_inactiveQPChanged: function(controller, qp) {
+            //},
+
+            _updatingQPChanged: function(controller, qp) {
+                var router = this.router;
+                if (!router._qpUpdates) {
+                    router._qpUpdates = {};
+                }
+                router._qpUpdates[qp.urlKey] = true;
+            },
+
+            mergedProperties: ['queryParams'],
+
+            paramsFor: function(name) {
+                var route = this.container.lookup('route:' + name);
+
+                if (!route) {
+                    return {};
+                }
+
+                var transition = this.router.router.activeTransition;
+                var state = transition ? transition.state : this.router.router.state;
+                var params = {};
+
+                merge(params, state.params[name]);
+
+                if (!state.fullQueryParams) {
+                    state.fullQueryParams = {};
+                    merge(state.fullQueryParams, state.queryParams);
+
+                    var targetRouteName = state.handlerInfos[state.handlerInfos.length-1].name;
+                    this.router._deserializeQueryParams(targetRouteName, state.fullQueryParams);
+                }
+
+                var qpMeta = get(route, '_qp');
+
+                if (!qpMeta) {
+                    // No query params specified on the controller.
+                    return params;
+                }
+
+                // Copy over all the query params for this route/controller into params hash.
+                // TODO: is this correct? I think this won't do model dep state.
+                var qps = qpMeta.qps;
+                for (var i = 0, len = qps.length; i &lt; len; ++i) {
+                    // Put deserialized qp on params hash.
+                    var qp = qps[i];
+                    if (!(qp.prop in params)) {
+                        params[qp.prop] = state.fullQueryParams[qp.prop] || qp.def;
+                    }
+                }
+
+                return params;
+            },
+
+            serializeQueryParamKey: function(controllerPropertyName) {
+                return controllerPropertyName;
+            },
+
+            serializeQueryParam: function(value, urlKey, defaultValueType) {
+                // urlKey isn't used here, but anyone overriding
+                // can use it to provide serialization specific
+                // to a certain query param.
+                if (defaultValueType === 'array') {
+                    return JSON.stringify(value);
+                }
+                return '' + value;
+            },
+
+            deserializeQueryParam: function(value, urlKey, defaultValueType) {
+                // urlKey isn't used here, but anyone overriding
+                // can use it to provide deserialization specific
+                // to a certain query param.
+
+                // Use the defaultValueType of the default value (the initial value assigned to a
+                // controller query param property), to intelligently deserialize and cast.
+                if (defaultValueType === 'boolean') {
+                    return (value === 'true') ? true : false;
+                } else if (defaultValueType === 'number') {
+                    return (Number(value)).valueOf();
+                } else if (defaultValueType === 'array') {
+                    return Ember.A(JSON.parse(value));
+                }
+                return value;
+            },
+
+
+            _fireQueryParamTransition: function() {
+                this.transitionTo({
+                    queryParams: this.router._queuedQPChanges 
+                });
+                this.router._queuedQPChanges = {};
+            },
+
+            /**
+                      A hook you can use to reset controller values either when the model
+                      changes or the route is exiting.
+
+                      ```js
+                      App.ArticlesRoute = Ember.Route.extend({
+                        // ...
+
+                        resetController: function (controller, isExiting, transition) {
+                          if (isExiting) {
+                            controller.set('page', 1);
+                          }
+                        }
+                      });
+                      ```
+
+                      @method resetController
+                      @param {Controller} controller instance
+                      @param {Boolean} isExiting
+                      @param {Object} transition
+                    */
+            resetController: Ember.K
+        });
+
+
+        function parentRoute(route) {
+            var handlerInfo = handlerInfoFor(route, route.router.router.state.handlerInfos, -1);
+            return handlerInfo &amp;&amp; handlerInfo.handler;
+        }
+
+        function handlerInfoFor(route, handlerInfos, _offset) {
+            if (!handlerInfos) {
+                return;
+            }
+
+            var offset = _offset || 0, current;
+            for (var i = 0, l = handlerInfos.length; i &lt; l; i++) {
+                current = handlerInfos[i].handler;
+                if (current === route) {
+                    return handlerInfos[i + offset];
+                }
+            }
+        }
+
+        function parentTemplate(route) {
+            var parent = parentRoute(route), template;
+
+            if (!parent) {
+                return;
+            }
+
+            if (template = parent.lastRenderedTemplate) {
+                return template;
+            } else {
+                return parentTemplate(parent);
+            }
+        }
+
+        function normalizeOptions(route, name, template, options) {
+            options = options || {};
+            options.into = options.into ? options.into.replace(/\//g, '.') : parentTemplate(route);
+            options.outlet = options.outlet || 'main';
+            options.name = name;
+            options.template = template;
+            options.LOG_VIEW_LOOKUPS = get(route.router, 'namespace.LOG_VIEW_LOOKUPS');
+
+            Ember.assert(&quot;An outlet (&quot; + options.outlet + &quot;) was specified but was not found.&quot;, options.outlet === 'main' || options.into);
+
+            var controller = options.controller,
+            model = options.model,
+            namedController;
+
+            if (options.controller) {
+                controller = options.controller;
+            } else if (options.namePassed) {
+                controller = route.container.lookup('controller:' + name) || route.controllerName || route.routeName;
+            } else {
+                controller = route.controllerName || route.container.lookup('controller:' + name);
+            }
+
+            if (typeof controller === 'string') {
+                var controllerName = controller;
+                controller = route.container.lookup('controller:' + controllerName);
+                if (!controller) {
+                    throw new EmberError(&quot;You passed `controller: '&quot; + controllerName + &quot;'` into the `render` method, but no such controller could be found.&quot;);
+                }
+            }
+
+            if (model) {
+                controller.set('model', model);
+            }
+
+            options.controller = controller;
+
+            return options;
+        }
+
+        function setupView(view, container, options) {
+            if (view) {
+                if (options.LOG_VIEW_LOOKUPS) {
+                    Ember.Logger.info(&quot;Rendering &quot; + options.name + &quot; with &quot; + view, {
+                        fullName: 'view:' + options.name 
+                    });
+                }
+            } else {
+                var defaultView = options.into ? 'view:default' : 'view:toplevel';
+                view = container.lookup(defaultView);
+                if (options.LOG_VIEW_LOOKUPS) {
+                    Ember.Logger.info(&quot;Rendering &quot; + options.name + &quot; with default view &quot; + view, {
+                        fullName: 'view:' + options.name 
+                    });
+                }
+            }
+
+            if (!get(view, 'templateName')) {
+                set(view, 'template', options.template);
+
+                set(view, '_debugTemplateName', options.name);
+            }
+
+            set(view, 'renderedName', options.name);
+            set(view, 'controller', options.controller);
+
+            return view;
+        }
+
+        function appendView(route, view, options) {
+            if (options.into) {
+                var parentView = route.router._lookupActiveView(options.into);
+                var teardownOutletView = generateOutletTeardown(parentView, options.outlet);
+                if (!route.teardownOutletViews) {
+                    route.teardownOutletViews = [];
+                }
+                replace(route.teardownOutletViews, 0, 0, [teardownOutletView]);
+                parentView.connectOutlet(options.outlet, view);
+            } else {
+                var rootElement = get(route, 'router.namespace.rootElement');
+                // tear down view if one is already rendered
+                if (route.teardownTopLevelView) {
+                    route.teardownTopLevelView();
+                }
+                route.router._connectActiveView(options.name, view);
+                route.teardownTopLevelView = generateTopLevelTeardown(view);
+                view.appendTo(rootElement);
+            }
+        }
+
+        function generateTopLevelTeardown(view) {
+            return function() {
+                view.destroy();
+            };
+        }
+
+        function generateOutletTeardown(parentView, outlet) {
+            return function() {
+                parentView.disconnectOutlet(outlet);
+            };
+        }
+
+        __exports__[&quot;default&quot;] = Route;
+    });
+    define(&quot;ember-routing/system/router&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/mixins/evented&quot;, &quot;ember-routing/system/dsl&quot;, &quot;ember-views/views/view&quot;, &quot;ember-routing/location/api&quot;, &quot;ember-handlebars/views/metamorph_view&quot;, &quot;ember-routing-handlebars/helpers/shared&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // FEATURES, Logger, K, assert
+        var EmberError = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var defineProperty = __dependency5__.defineProperty;
+        var computed = __dependency6__.computed;
+        var merge = __dependency7__[&quot;default&quot;];
+        var run = __dependency8__[&quot;default&quot;];
+        var forEach = __dependency9__.forEach;
+
+        var fmt = __dependency10__.fmt;
+        var EmberObject = __dependency11__[&quot;default&quot;];
+        var Evented = __dependency12__[&quot;default&quot;];
+        var EmberRouterDSL = __dependency13__[&quot;default&quot;];
+        var EmberView = __dependency14__[&quot;default&quot;];
+        var EmberLocation = __dependency15__[&quot;default&quot;];
+        var _MetamorphView = __dependency16__[&quot;default&quot;];
+        var routeArgs = __dependency17__.routeArgs;
+        var getActiveTargetName = __dependency17__.getActiveTargetName;
+        var stashParamNames = __dependency17__.stashParamNames;
+
+        // requireModule(&quot;ember-handlebars&quot;);
+        // requireModule(&quot;ember-runtime&quot;);
+        // requireModule(&quot;ember-views&quot;);
+
+        /**
+            @module ember
+            @submodule ember-routing
+            */
+
+        // // side effect of loading some Ember globals, for now
+        // requireModule(&quot;ember-handlebars&quot;);
+        // requireModule(&quot;ember-runtime&quot;);
+        // requireModule(&quot;ember-views&quot;);
+
+        var Router = requireModule(&quot;router&quot;)['default'];
+        var Transition = requireModule(&quot;router/transition&quot;).Transition;
+
+        var slice = [].slice;
+
+        /**
+              The `Ember.Router` class manages the application state and URLs. Refer to
+              the [routing guide](http://emberjs.com/guides/routing/) for documentation.
+
+              @class Router
+              @namespace Ember
+              @extends Ember.Object
+            */
+        var EmberRouter = EmberObject.extend(Evented, {
+            /**
+                    The `location` property determines the type of URL's that your
+                    application will use.
+
+                    The following location types are currently available:
+
+                    * `hash`
+                    * `history`
+                    * `none`
+
+                    @property location
+                    @default 'hash'
+                    @see {Ember.Location}
+                  */
+            location: 'hash',
+
+            /**
+                   Represents the URL of the root of the application, often '/'. This prefix is
+                   assumed on all routes defined on this router.
+
+                   @property rootURL
+                   @default '/'
+                  */
+            rootURL: '/',
+
+            init: function() {
+                this.router = this.constructor.router || this.constructor.map(Ember.K);
+                this._activeViews = {};
+                this._setupLocation();
+                this._qpCache = {};
+                this._queuedQPChanges = {};
+
+                if (get(this, 'namespace.LOG_TRANSITIONS_INTERNAL')) {
+                    this.router.log = Ember.Logger.debug;
+                }
+            },
+
+            /**
+                    Represents the current URL.
+
+                    @method url
+                    @return {String} The current URL.
+                  */
+            url: computed(function() {
+                return get(this, 'location').getURL();
+            }),
+
+            /**
+                    Initializes the current router instance and sets up the change handling
+                    event listeners used by the instances `location` implementation.
+
+                    A property named `initialURL` will be used to determine the initial URL.
+                    If no value is found `/` will be used.
+
+                    @method startRouting
+                    @private
+                  */
+            startRouting: function() {
+                this.router = this.router || this.constructor.map(Ember.K);
+
+                var router = this.router;
+                var location = get(this, 'location');
+                var container = this.container;
+                var self = this;
+                var initialURL = get(this, 'initialURL');
+
+                // Allow the Location class to cancel the router setup while it refreshes
+                // the page
+                if (get(location, 'cancelRouterSetup')) {
+                    return;
+                }
+
+                this._setupRouter(router, location);
+
+                container.register('view:default', _MetamorphView);
+                container.register('view:toplevel', EmberView.extend());
+
+                location.onUpdateURL(function(url) {
+                    self.handleURL(url);
+                });
+
+                if (typeof initialURL === &quot;undefined&quot;) {
+                    initialURL = location.getURL();
+                }
+
+                this.handleURL(initialURL);
+            },
+
+            /**
+                    Handles updating the paths and notifying any listeners of the URL
+                    change.
+
+                    Triggers the router level `didTransition` hook.
+
+                    @method didTransition
+                    @private
+                    @since 1.2.0
+                  */
+            didTransition: function(infos) {
+                updatePaths(this);
+
+                this._cancelLoadingEvent();
+
+                this.notifyPropertyChange('url');
+
+                // Put this in the runloop so url will be accurate. Seems
+                // less surprising than didTransition being out of sync.
+                run.once(this, this.trigger, 'didTransition');
+
+                if (get(this, 'namespace').LOG_TRANSITIONS) {
+                    Ember.Logger.log(&quot;Transitioned into '&quot; + EmberRouter._routePath(infos) + &quot;'&quot;);
+                }
+            },
+
+            handleURL: function(url) {
+                return this._doURLTransition('handleURL', url);
+            },
+
+            _doURLTransition: function(routerJsMethod, url) {
+                var transition = this.router[routerJsMethod](url || '/');
+                listenForTransitionErrors(transition);
+                return transition;
+            },
+
+            transitionTo: function() {
+                var args = slice.call(arguments), queryParams;
+                if (resemblesURL(args[0])) {
+                    return this._doURLTransition('transitionTo', args[0]);
+                }
+
+                var possibleQueryParams = args[args.length-1];
+                if (possibleQueryParams &amp;&amp; possibleQueryParams.hasOwnProperty('queryParams')) {
+                    queryParams = args.pop().queryParams;
+                } else {
+                    queryParams = {};
+                }
+
+                var targetRouteName = args.shift();
+                return this._doTransition(targetRouteName, args, queryParams);
+            },
+
+            intermediateTransitionTo: function() {
+                this.router.intermediateTransitionTo.apply(this.router, arguments);
+
+                updatePaths(this);
+
+                var infos = this.router.currentHandlerInfos;
+                if (get(this, 'namespace').LOG_TRANSITIONS) {
+                    Ember.Logger.log(&quot;Intermediate-transitioned into '&quot; + EmberRouter._routePath(infos) + &quot;'&quot;);
+                }
+            },
+
+            replaceWith: function() {
+                return this.transitionTo.apply(this, arguments).method('replace');
+            },
+
+            generate: function() {
+                var url = this.router.generate.apply(this.router, arguments);
+                return this.location.formatURL(url);
+            },
+
+            /**
+                    Determines if the supplied route is currently active.
+
+                    @method isActive
+                    @param routeName
+                    @return {Boolean}
+                    @private
+                  */
+            isActive: function(routeName) {
+                var router = this.router;
+                return router.isActive.apply(router, arguments);
+            },
+
+            /**
+                    An alternative form of `isActive` that doesn't require
+                    manual concatenation of the arguments into a single
+                    array.
+
+                    @method isActive
+                    @param routeName
+                    @param models
+                    @param queryParams
+                    @return {Boolean}
+                    @private
+                  */
+            isActiveIntent: function(routeName, models, queryParams) {
+                var router = this.router;
+                return router.isActive.apply(router, arguments);
+            },
+
+            send: function(name, context) {
+                this.router.trigger.apply(this.router, arguments);
+            },
+
+            /**
+                    Does this router instance have the given route.
+
+                    @method hasRoute
+                    @return {Boolean}
+                    @private
+                  */
+            hasRoute: function(route) {
+                return this.router.hasRoute(route);
+            },
+
+            /**
+                    Resets the state of the router by clearing the current route
+                    handlers and deactivating them.
+
+                    @private
+                    @method reset
+                   */
+            reset: function() {
+                this.router.reset();
+            },
+
+            _lookupActiveView: function(templateName) {
+                var active = this._activeViews[templateName];
+                return active &amp;&amp; active[0];
+            },
+
+            _connectActiveView: function(templateName, view) {
+                var existing = this._activeViews[templateName];
+
+                if (existing) {
+                    existing[0].off('willDestroyElement', this, existing[1]);
+                }
+
+                function disconnectActiveView() {
+                    delete this._activeViews[templateName];
+                }
+
+                this._activeViews[templateName] = [view, disconnectActiveView];
+                view.one('willDestroyElement', this, disconnectActiveView);
+            },
+
+            _setupLocation: function() {
+                var location = get(this, 'location');
+                var rootURL = get(this, 'rootURL');
+
+                if (rootURL &amp;&amp; this.container &amp;&amp; !this.container.has('-location-setting:root-url')) {
+                    this.container.register('-location-setting:root-url', rootURL, {
+                        instantiate: false 
+                    });
+                }
+
+                if ('string' === typeof location &amp;&amp; this.container) {
+                    var resolvedLocation = this.container.lookup('location:' + location);
+
+                    if ('undefined' !== typeof resolvedLocation) {
+                        location = set(this, 'location', resolvedLocation);
+                    } else {
+                        // Allow for deprecated registration of custom location API's
+                        var options = {
+                            implementation: location
+                        };
+
+                        location = set(this, 'location', EmberLocation.create(options));
+                    }
+                }
+
+                if (rootURL &amp;&amp; typeof rootURL === 'string') {
+                    location.rootURL = rootURL;
+                }
+
+                // ensure that initState is called AFTER the rootURL is set on
+                // the location instance
+                if (typeof location.initState === 'function') {
+                    location.initState();
+                }
+            },
+
+            _getHandlerFunction: function() {
+                var seen = {}, container = this.container;
+                var DefaultRoute = container.lookupFactory('route:basic');
+                var self = this;
+
+                return function(name) {
+                    var routeName = 'route:' + name;
+                    var handler = container.lookup(routeName);
+
+                    if (seen[name]) {
+                        return handler;
+                    }
+
+                    seen[name] = true;
+
+                    if (!handler) {
+                        container.register(routeName, DefaultRoute.extend());
+                        handler = container.lookup(routeName);
+
+                        if (get(self, 'namespace.LOG_ACTIVE_GENERATION')) {
+                            Ember.Logger.info(&quot;generated -&gt; &quot; + routeName, {
+                                fullName: routeName 
+                            });
+                        }
+                    }
+
+                    handler.routeName = name;
+                    return handler;
+                };
+            },
+
+            _setupRouter: function(router, location) {
+                var lastURL, emberRouter = this;
+
+                router.getHandler = this._getHandlerFunction();
+
+                var doUpdateURL = function() {
+                    location.setURL(lastURL);
+                };
+
+                router.updateURL = function(path) {
+                    lastURL = path;
+                    run.once(doUpdateURL);
+                };
+
+                if (location.replaceURL) {
+                    var doReplaceURL = function() {
+                        location.replaceURL(lastURL);
+                    };
+
+                    router.replaceURL = function(path) {
+                        lastURL = path;
+                        run.once(doReplaceURL);
+                    };
+                }
+
+                router.didTransition = function(infos) {
+                    emberRouter.didTransition(infos);
+                };
+            },
+
+            _serializeQueryParams: function(targetRouteName, queryParams) {
+                var groupedByUrlKey = {};
+
+                forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
+                    var urlKey = qp.urlKey;
+                    if (!groupedByUrlKey[urlKey]) {
+                        groupedByUrlKey[urlKey] = [];
+                    }
+                    groupedByUrlKey[urlKey].push({
+                        qp: qp,
+                        value: value
+                    });
+                    delete queryParams[key];
+                });
+
+                for (var key in groupedByUrlKey) {
+                    var qps = groupedByUrlKey[key];
+                    if (qps.length &gt; 1) {
+                        var qp0 = qps[0].qp, qp1 = qps[1].qp;
+                        Ember.assert(fmt(&quot;You're not allowed to have more than one controller property map to the same query param key, but both `%@` and `%@` map to `%@`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `%@: { as: 'other-%@' }`&quot;, [qp0.fprop, qp1.fprop, qp0.urlKey, qp0.prop, qp0.prop]), false);
+                    }
+                    var qp = qps[0].qp;
+                    queryParams[qp.urlKey] = qp.route.serializeQueryParam(qps[0].value, qp.urlKey, qp.type);
+                }
+            },
+
+            _deserializeQueryParams: function(targetRouteName, queryParams) {
+                forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) {
+                    delete queryParams[key];
+                    queryParams[qp.prop] = qp.route.deserializeQueryParam(value, qp.urlKey, qp.type);
+                });
+            },
+
+            _pruneDefaultQueryParamValues: function(targetRouteName, queryParams) {
+                var qps = this._queryParamsFor(targetRouteName);
+                for (var key in queryParams) {
+                    var qp = qps.map[key];
+                    if (qp &amp;&amp; qp.sdef === queryParams[key]) {
+                        delete queryParams[key];
+                    }
+                }
+            },
+
+            _doTransition: function(_targetRouteName, models, _queryParams) {
+                var targetRouteName = _targetRouteName || getActiveTargetName(this.router);
+                Ember.assert(&quot;The route &quot; + targetRouteName + &quot; was not found&quot;, targetRouteName &amp;&amp; this.router.hasRoute(targetRouteName));
+
+                var queryParams = {};
+
+                merge(queryParams, _queryParams);
+                this._prepareQueryParams(targetRouteName, models, queryParams);
+
+
+                var transitionArgs = routeArgs(targetRouteName, models, queryParams);
+                var transitionPromise = this.router.transitionTo.apply(this.router, transitionArgs);
+
+                listenForTransitionErrors(transitionPromise);
+
+                return transitionPromise;
+            },
+
+            _prepareQueryParams: function(targetRouteName, models, queryParams) {
+                this._hydrateUnsuppliedQueryParams(targetRouteName, models, queryParams);
+                this._serializeQueryParams(targetRouteName, queryParams);
+                this._pruneDefaultQueryParamValues(targetRouteName, queryParams);
+            },
+
+            /**
+                    Returns a merged query params meta object for a given route.
+                    Useful for asking a route what its known query params are.
+                   */
+            _queryParamsFor: function(leafRouteName) {
+                if (this._qpCache[leafRouteName]) {
+                    return this._qpCache[leafRouteName];
+                }
+
+                var map = {}, qps = [], qpCache = this._qpCache[leafRouteName] = {
+                    map: map,
+                    qps: qps
+                };
+
+                var routerjs = this.router,
+                recogHandlerInfos = routerjs.recognizer.handlersFor(leafRouteName);
+
+                for (var i = 0, len = recogHandlerInfos.length; i &lt; len; ++i) {
+                    var recogHandler = recogHandlerInfos[i];
+                    var route = routerjs.getHandler(recogHandler.handler);
+                    var qpMeta = get(route, '_qp');
+
+                    if (!qpMeta) {
+                        continue;
+                    }
+
+                    merge(map, qpMeta.map);
+                    qps.push.apply(qps, qpMeta.qps);
+                }
+
+                return {
+                    qps: qps,
+                    map: map
+                };
+            },
+
+            /*
+                    becomeResolved: function(payload, resolvedContext) {
+                      var params = this.serialize(resolvedContext);
+
+                      if (payload) {
+                        this.stashResolvedModel(payload, resolvedContext);
+                        payload.params = payload.params || {};
+                        payload.params[this.name] = params;
+                      }
+
+                      return this.factory('resolved', {
+                        context: resolvedContext,
+                        name: this.name,
+                        handler: this.handler,
+                        params: params
+                      });
+                    },
+                  */
+
+            _hydrateUnsuppliedQueryParams: function(leafRouteName, contexts, queryParams) {
+                var state = calculatePostTransitionState(this, leafRouteName, contexts);
+                var handlerInfos = state.handlerInfos;
+                var appCache = this._bucketCache;
+
+                stashParamNames(this, handlerInfos);
+
+                for (var i = 0, len = handlerInfos.length; i &lt; len; ++i) {
+                    var route = handlerInfos[i].handler;
+                    var qpMeta = get(route, '_qp');
+
+                    for (var j = 0, qpLen = qpMeta.qps.length; j &lt; qpLen; ++j) {
+                        var qp = qpMeta.qps[j];
+                        var presentProp = qp.prop in queryParams &amp;&amp; qp.prop ||
+                        qp.fprop in queryParams &amp;&amp; qp.fprop;
+
+                        if (presentProp) {
+                            if (presentProp !== qp.fprop) {
+                                queryParams[qp.fprop] = queryParams[presentProp];
+                                delete queryParams[presentProp];
+                            }
+                        } else {
+                            var controllerProto = qp.cProto;
+                            var cacheMeta = get(controllerProto, '_cacheMeta');
+
+                            var cacheKey = controllerProto._calculateCacheKey(qp.ctrl, cacheMeta[qp.prop].parts, state.params);
+                            queryParams[qp.fprop] = appCache.lookup(cacheKey, qp.prop, qp.def);
+                        }
+                    }
+                }
+            },
+
+            _scheduleLoadingEvent: function(transition, originRoute) {
+                this._cancelLoadingEvent();
+                this._loadingStateTimer = run.scheduleOnce('routerTransitions', this, '_fireLoadingEvent', transition, originRoute);
+            },
+
+            _fireLoadingEvent: function(transition, originRoute) {
+                if (!this.router.activeTransition) {
+                    // Don't fire an event if we've since moved on from
+                    // the transition that put us in a loading state.
+                    return;
+                }
+
+                transition.trigger(true, 'loading', transition, originRoute);
+            },
+
+            _cancelLoadingEvent: function () {
+                if (this._loadingStateTimer) {
+                    run.cancel(this._loadingStateTimer);
+                }
+                this._loadingStateTimer = null;
+            }
+        });
+
+        /*
+              Helper function for iterating root-ward, starting
+              from (but not including) the provided `originRoute`.
+
+              Returns true if the last callback fired requested
+              to bubble upward.
+
+              @private
+             */
+        function forEachRouteAbove(originRoute, transition, callback) {
+            var handlerInfos = transition.state.handlerInfos;
+            var originRouteFound = false;
+            var handlerInfo, route;
+
+            for (var i = handlerInfos.length - 1; i &gt;= 0; --i) {
+                handlerInfo = handlerInfos[i];
+                route = handlerInfo.handler;
+
+                if (!originRouteFound) {
+                    if (originRoute === route) {
+                        originRouteFound = true;
+                    }
+                    continue;
+                }
+
+                if (callback(route, handlerInfos[i + 1].handler) !== true) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // These get invoked when an action bubbles above ApplicationRoute
+        // and are not meant to be overridable.
+        var defaultActionHandlers = {
+
+            willResolveModel: function(transition, originRoute) {
+                originRoute.router._scheduleLoadingEvent(transition, originRoute);
+            },
+
+            error: function(error, transition, originRoute) {
+                // Attempt to find an appropriate error substate to enter.
+                var router = originRoute.router;
+
+                var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) {
+                    var childErrorRouteName = findChildRouteName(route, childRoute, 'error');
+                    if (childErrorRouteName) {
+                        router.intermediateTransitionTo(childErrorRouteName, error);
+                        return;
+                    }
+                    return true;
+                });
+
+                if (tryTopLevel) {
+                    // Check for top-level error state to enter.
+                    if (routeHasBeenDefined(originRoute.router, 'application_error')) {
+                        router.intermediateTransitionTo('application_error', error);
+                        return;
+                    }
+                } else {
+                    // Don't fire an assertion if we found an error substate.
+                    return;
+                }
+
+                logError(error, 'Error while processing route: ' + transition.targetName);
+            },
+
+            loading: function(transition, originRoute) {
+                // Attempt to find an appropriate loading substate to enter.
+                var router = originRoute.router;
+
+                var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) {
+                    var childLoadingRouteName = findChildRouteName(route, childRoute, 'loading');
+
+                    if (childLoadingRouteName) {
+                        router.intermediateTransitionTo(childLoadingRouteName);
+                        return;
+                    }
+
+                    // Don't bubble above pivot route.
+                    if (transition.pivotHandler !== route) {
+                        return true;
+                    }
+                });
+
+                if (tryTopLevel) {
+                    // Check for top-level loading state to enter.
+                    if (routeHasBeenDefined(originRoute.router, 'application_loading')) {
+                        router.intermediateTransitionTo('application_loading');
+                        return;
+                    }
+                }
+            }
+        };
+
+        function logError(error, initialMessage) {
+            var errorArgs = [];
+
+            if (initialMessage) {
+                errorArgs.push(initialMessage);
+            }
+
+            if (error) {
+                if (error.message) {
+                    errorArgs.push(error.message);
+                }
+                if (error.stack) {
+                    errorArgs.push(error.stack);
+                }
+
+                if (typeof error === &quot;string&quot;) {
+                    errorArgs.push(error);
+                }
+            }
+
+            Ember.Logger.error.apply(this, errorArgs);
+        }
+
+        function findChildRouteName(parentRoute, originatingChildRoute, name) {
+            var router = parentRoute.router;
+            var childName;
+            var targetChildRouteName = originatingChildRoute.routeName.split('.').pop();
+            var namespace = parentRoute.routeName === 'application' ? '' : parentRoute.routeName + '.';
+
+
+            // Second, try general loading state, e.g. 'loading'
+            childName = namespace + name;
+            if (routeHasBeenDefined(router, childName)) {
+                return childName;
+            }
+        }
+
+        function routeHasBeenDefined(router, name) {
+            var container = router.container;
+            return router.hasRoute(name) &amp;&amp;
+            (container.has('template:' + name) || container.has('route:' + name));
+        }
+
+        function triggerEvent(handlerInfos, ignoreFailure, args) {
+            var name = args.shift();
+
+            if (!handlerInfos) {
+                if (ignoreFailure) {
+                    return;
+                }
+                throw new EmberError(&quot;Can't trigger action '&quot; + name + &quot;' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call `.send()` on the `Transition` object passed to the `model/beforeModel/afterModel` hooks.&quot;);
+            }
+
+            var eventWasHandled = false;
+            var handlerInfo, handler;
+
+            for (var i = handlerInfos.length - 1; i &gt;= 0; i--) {
+                handlerInfo = handlerInfos[i];
+                handler = handlerInfo.handler;
+
+                if (handler._actions &amp;&amp; handler._actions[name]) {
+                    if (handler._actions[name].apply(handler, args) === true) {
+                        eventWasHandled = true;
+                    } else {
+                        return;
+                    }
+                }
+            }
+
+            if (defaultActionHandlers[name]) {
+                defaultActionHandlers[name].apply(null, args);
+                return;
+            }
+
+            if (!eventWasHandled &amp;&amp; !ignoreFailure) {
+                throw new EmberError(&quot;Nothing handled the action '&quot; + name + &quot;'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.&quot;);
+            }
+        }
+
+        function calculatePostTransitionState(emberRouter, leafRouteName, contexts) {
+            var routerjs = emberRouter.router;
+            var state = routerjs.applyIntent(leafRouteName, contexts);
+            var handlerInfos = state.handlerInfos;
+            var params = state.params;
+
+            for (var i = 0, len = handlerInfos.length; i &lt; len; ++i) {
+                var handlerInfo = handlerInfos[i];
+                if (!handlerInfo.isResolved) {
+                    handlerInfo = handlerInfo.becomeResolved(null, handlerInfo.context);
+                }
+                params[handlerInfo.name] = handlerInfo.params;
+            }
+            return state;
+        }
+
+        function updatePaths(router) {
+            var appController = router.container.lookup('controller:application');
+
+            if (!appController) {
+                // appController might not exist when top-level loading/error
+                // substates have been entered since ApplicationRoute hasn't
+                // actually been entered at that point.
+                return;
+            }
+
+            var infos = router.router.currentHandlerInfos,
+            path = EmberRouter._routePath(infos);
+
+            if (!('currentPath' in appController)) {
+                defineProperty(appController, 'currentPath');
+            }
+
+            set(appController, 'currentPath', path);
+
+            if (!('currentRouteName' in appController)) {
+                defineProperty(appController, 'currentRouteName');
+            }
+
+            set(appController, 'currentRouteName', infos[infos.length - 1].name);
+        }
+
+        EmberRouter.reopenClass({
+            router: null,
+            map: function(callback) {
+                var router = this.router;
+                if (!router) {
+                    router = new Router();
+
+
+                    router._triggerWillChangeContext = Ember.K;
+                    router._triggerWillLeave = Ember.K;
+
+
+                    router.callbacks = [];
+                    router.triggerEvent = triggerEvent;
+                    this.reopenClass({
+                        router: router 
+                    });
+                }
+
+                var dsl = EmberRouterDSL.map(function() {
+                    this.resource('application', {
+                        path: &quot;/&quot; 
+                    }, function() {
+                        for (var i = 0; i &lt; router.callbacks.length; i++) {
+                            router.callbacks[i].call(this);
+                        }
+                        callback.call(this);
+                    });
+                });
+
+                router.callbacks.push(callback);
+                router.map(dsl.generate());
+                return router;
+            },
+
+            _routePath: function(handlerInfos) {
+                var path = [];
+
+                // We have to handle coalescing resource names that
+                // are prefixed with their parent's names, e.g.
+                // ['foo', 'foo.bar.baz'] =&gt; 'foo.bar.baz', not 'foo.foo.bar.baz'
+
+                function intersectionMatches(a1, a2) {
+                    for (var i = 0, len = a1.length; i &lt; len; ++i) {
+                        if (a1[i] !== a2[i]) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+
+                var name, nameParts, oldNameParts;
+                for (var i = 1, l = handlerInfos.length; i &lt; l; i++) {
+                    name = handlerInfos[i].name;
+                    nameParts = name.split(&quot;.&quot;);
+                    oldNameParts = slice.call(path);
+
+                    while (oldNameParts.length) {
+                        if (intersectionMatches(oldNameParts, nameParts)) {
+                            break;
+                        }
+                        oldNameParts.shift();
+                    }
+
+                    path.push.apply(path, nameParts.slice(oldNameParts.length));
+                }
+
+                return path.join(&quot;.&quot;);
+            }
+        });
+
+        function listenForTransitionErrors(transition) {
+            transition.then(null, function(error) {
+                if (!error || !error.name) {
+                    return;
+                }
+
+                if (error.name === &quot;UnrecognizedURLError&quot;) {
+                    Ember.assert(&quot;The URL '&quot; + error.message + &quot;' did not match any routes in your application&quot;);
+                } else if (error.name === 'TransitionAborted') {
+                    // just ignore TransitionAborted here
+                } else {
+                    logError(error);
+                }
+
+                return error;
+            }, 'Ember: Process errors from Router');
+        }
+
+        function resemblesURL(str) {
+            return typeof str === 'string' &amp;&amp; ( str === '' || str.charAt(0) === '/');
+        }
+
+        function forEachQueryParam(router, targetRouteName, queryParams, callback) {
+
+            var qpCache = router._queryParamsFor(targetRouteName),
+            qps = qpCache.qps;
+
+            for (var key in queryParams) {
+                if (!queryParams.hasOwnProperty(key)) {
+                    continue;
+                }
+                var value = queryParams[key],
+                qp = qpCache.map[key];
+
+                if (qp) {
+                    callback(key, value, qp);
+                }
+            }
+        }
+
+        __exports__[&quot;default&quot;] = EmberRouter;
+    });
+    define(&quot;ember-runtime&quot;,
+    [&quot;ember-metal&quot;, &quot;ember-runtime/core&quot;, &quot;ember-runtime/keys&quot;, &quot;ember-runtime/compare&quot;, &quot;ember-runtime/copy&quot;, &quot;ember-runtime/system/namespace&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/system/tracked_array&quot;, &quot;ember-runtime/system/subarray&quot;, &quot;ember-runtime/system/container&quot;, &quot;ember-runtime/system/application&quot;, &quot;ember-runtime/system/array_proxy&quot;, &quot;ember-runtime/system/object_proxy&quot;, &quot;ember-runtime/system/core_object&quot;, &quot;ember-runtime/system/each_proxy&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;ember-runtime/system/set&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/deferred&quot;, &quot;ember-runtime/system/lazy_load&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;ember-runtime/mixins/comparable&quot;, &quot;ember-runtime/mixins/copyable&quot;, &quot;ember-runtime/mixins/enumerable&quot;, &quot;ember-runtime/mixins/freezable&quot;, &quot;ember-runtime/mixins/observable&quot;, &quot;ember-runtime/mixins/action_handler&quot;, &quot;ember-runtime/mixins/deferred&quot;, &quot;ember-runtime/mixins/mutable_enumerable&quot;, &quot;ember-runtime/mixins/mutable_array&quot;, &quot;ember-runtime/mixins/target_action_support&quot;, &quot;ember-runtime/mixins/evented&quot;, &quot;ember-runtime/mixins/promise_proxy&quot;, &quot;ember-runtime/mixins/sortable&quot;, &quot;ember-runtime/computed/array_computed&quot;, &quot;ember-runtime/computed/reduce_computed&quot;, &quot;ember-runtime/computed/reduce_computed_macros&quot;, &quot;ember-runtime/controllers/array_controller&quot;, &quot;ember-runtime/controllers/object_controller&quot;, &quot;ember-runtime/controllers/controller&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;ember-runtime/ext/rsvp&quot;, &quot;ember-runtime/ext/string&quot;, &quot;ember-runtime/ext/function&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __dependency29__, __dependency30__, __dependency31__, __dependency32__, __dependency33__, __dependency34__, __dependency35__, __dependency36__, __dependency37__, __dependency38__, __dependency39__, __dependency40__, __dependency41__, __dependency42__, __dependency43__, __dependency44__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            Ember Runtime
+
+            @module ember
+            @submodule ember-runtime
+            @requires ember-metal
+            */
+
+        // BEGIN IMPORTS
+        var Ember = __dependency1__[&quot;default&quot;];
+        var isEqual = __dependency2__.isEqual;
+        var keys = __dependency3__[&quot;default&quot;];
+        var compare = __dependency4__[&quot;default&quot;];
+        var copy = __dependency5__[&quot;default&quot;];
+
+        var Namespace = __dependency6__[&quot;default&quot;];
+        var EmberObject = __dependency7__[&quot;default&quot;];
+        var TrackedArray = __dependency8__[&quot;default&quot;];
+        var SubArray = __dependency9__[&quot;default&quot;];
+        var Container = __dependency10__[&quot;default&quot;];
+        var Application = __dependency11__[&quot;default&quot;];
+        var ArrayProxy = __dependency12__[&quot;default&quot;];
+        var ObjectProxy = __dependency13__[&quot;default&quot;];
+        var CoreObject = __dependency14__[&quot;default&quot;];
+        var EachArray = __dependency15__.EachArray;
+        var EachProxy = __dependency15__.EachProxy;
+
+        var NativeArray = __dependency16__[&quot;default&quot;];
+        var Set = __dependency17__[&quot;default&quot;];
+        var EmberStringUtils = __dependency18__[&quot;default&quot;];
+        var Deferred = __dependency19__[&quot;default&quot;];
+        var onLoad = __dependency20__.onLoad;
+        var runLoadHooks = __dependency20__.runLoadHooks;
+
+        var EmberArray = __dependency21__[&quot;default&quot;];
+        var Comparable = __dependency22__[&quot;default&quot;];
+        var Copyable = __dependency23__[&quot;default&quot;];
+        var Enumerable = __dependency24__[&quot;default&quot;];
+        var Freezable = __dependency25__.Freezable;
+        var FROZEN_ERROR = __dependency25__.FROZEN_ERROR;
+
+        var Observable = __dependency26__[&quot;default&quot;];
+        var ActionHandler = __dependency27__[&quot;default&quot;];
+        var DeferredMixin = __dependency28__[&quot;default&quot;];
+        var MutableEnumerable = __dependency29__[&quot;default&quot;];
+        var MutableArray = __dependency30__[&quot;default&quot;];
+        var TargetActionSupport = __dependency31__[&quot;default&quot;];
+        var Evented = __dependency32__[&quot;default&quot;];
+        var PromiseProxyMixin = __dependency33__[&quot;default&quot;];
+        var SortableMixin = __dependency34__[&quot;default&quot;];
+        var arrayComputed = __dependency35__.arrayComputed;
+        var ArrayComputedProperty = __dependency35__.ArrayComputedProperty;
+
+        var reduceComputed = __dependency36__.reduceComputed;
+        var ReduceComputedProperty = __dependency36__.ReduceComputedProperty;
+
+        var sum = __dependency37__.sum;
+        var min = __dependency37__.min;
+        var max = __dependency37__.max;
+        var map = __dependency37__.map;
+        var sort = __dependency37__.sort;
+        var setDiff = __dependency37__.setDiff;
+        var mapBy = __dependency37__.mapBy;
+        var mapProperty = __dependency37__.mapProperty;
+        var filter = __dependency37__.filter;
+        var filterBy = __dependency37__.filterBy;
+        var filterProperty = __dependency37__.filterProperty;
+        var uniq = __dependency37__.uniq;
+        var union = __dependency37__.union;
+        var intersect = __dependency37__.intersect;
+
+        var ArrayController = __dependency38__[&quot;default&quot;];
+        var ObjectController = __dependency39__[&quot;default&quot;];
+        var Controller = __dependency40__[&quot;default&quot;];
+        var ControllerMixin = __dependency41__[&quot;default&quot;];
+
+        var RSVP = __dependency42__[&quot;default&quot;];
+        // just for side effect of extending Ember.RSVP
+        // just for side effect of extending String.prototype
+        // just for side effect of extending Function.prototype
+        // END IMPORTS
+
+        // BEGIN EXPORTS
+        Ember.compare = compare;
+        Ember.copy = copy;
+        Ember.isEqual = isEqual;
+        Ember.keys = keys;
+
+        Ember.Array = EmberArray;
+
+        Ember.Comparable = Comparable;
+        Ember.Copyable = Copyable;
+
+        Ember.SortableMixin = SortableMixin;
+
+        Ember.Freezable = Freezable;
+        Ember.FROZEN_ERROR = FROZEN_ERROR;
+
+        Ember.DeferredMixin = DeferredMixin;
+
+        Ember.MutableEnumerable = MutableEnumerable;
+        Ember.MutableArray = MutableArray;
+
+        Ember.TargetActionSupport = TargetActionSupport;
+        Ember.Evented = Evented;
+
+        Ember.PromiseProxyMixin = PromiseProxyMixin;
+
+        Ember.Observable = Observable;
+
+        Ember.arrayComputed = arrayComputed;
+        Ember.ArrayComputedProperty = ArrayComputedProperty;
+        Ember.reduceComputed = reduceComputed;
+        Ember.ReduceComputedProperty = ReduceComputedProperty;
+
+        // ES6TODO: this seems a less than ideal way/place to add properties to Ember.computed
+        var EmComputed = Ember.computed;
+
+        EmComputed.sum = sum;
+        EmComputed.min = min;
+        EmComputed.max = max;
+        EmComputed.map = map;
+        EmComputed.sort = sort;
+        EmComputed.setDiff = setDiff;
+        EmComputed.mapBy = mapBy;
+        EmComputed.mapProperty = mapProperty;
+        EmComputed.filter = filter;
+        EmComputed.filterBy = filterBy;
+        EmComputed.filterProperty = filterProperty;
+        EmComputed.uniq = uniq;
+        EmComputed.union = union;
+        EmComputed.intersect = intersect;
+
+        Ember.String = EmberStringUtils;
+        Ember.Object = EmberObject;
+        Ember.TrackedArray = TrackedArray;
+        Ember.SubArray = SubArray;
+        Ember.Container = Container;
+        Ember.Namespace = Namespace;
+        Ember.Enumerable = Enumerable;
+        Ember.ArrayProxy = ArrayProxy;
+        Ember.ObjectProxy = ObjectProxy;
+        Ember.ActionHandler = ActionHandler;
+        Ember.CoreObject = CoreObject;
+        Ember.EachArray = EachArray;
+        Ember.EachProxy = EachProxy;
+        Ember.NativeArray = NativeArray;
+        // ES6TODO: Currently we must rely on the global from ember-metal/core to avoid circular deps
+        // Ember.A = A;
+        Ember.Set = Set;
+        Ember.Deferred = Deferred;
+        Ember.onLoad = onLoad;
+        Ember.runLoadHooks = runLoadHooks;
+
+        Ember.ArrayController = ArrayController;
+        Ember.ObjectController = ObjectController;
+        Ember.Controller = Controller;
+        Ember.ControllerMixin = ControllerMixin;
+
+        Ember.RSVP = RSVP;
+        // END EXPORTS
+
+        __exports__[&quot;default&quot;] = Ember;
+    });
+    define(&quot;ember-runtime/compare&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/mixins/comparable&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // for Ember.ORDER_DEFINITION
+        var typeOf = __dependency2__.typeOf;
+        var Comparable = __dependency3__[&quot;default&quot;];
+
+        // Used by Ember.compare
+        Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [
+        'undefined',
+        'null',
+        'boolean',
+        'number',
+        'string',
+        'array',
+        'object',
+        'instance',
+        'function',
+        'class',
+        'date'
+        ];
+
+        /**
+             This will compare two javascript values of possibly different types.
+             It will tell you which one is greater than the other by returning:
+
+              - -1 if the first is smaller than the second,
+              - 0 if both are equal,
+              - 1 if the first is greater than the second.
+
+             The order is calculated based on `Ember.ORDER_DEFINITION`, if types are different.
+             In case they have the same type an appropriate comparison for this type is made.
+
+              ```javascript
+              Ember.compare('hello', 'hello');  // 0
+              Ember.compare('abc', 'dfg');      // -1
+              Ember.compare(2, 1);              // 1
+              ```
+
+             @method compare
+             @for Ember
+             @param {Object} v First value to compare
+             @param {Object} w Second value to compare
+             @return {Number} -1 if v &lt; w, 0 if v = w and 1 if v &gt; w.
+            */
+        __exports__[&quot;default&quot;] = function compare(v, w) {
+            if (v === w) {
+                return 0;
+            }
+
+            var type1 = typeOf(v);
+            var type2 = typeOf(w);
+
+            if (Comparable) {
+                if (type1 === 'instance' &amp;&amp; Comparable.detect(v.constructor)) {
+                    return v.constructor.compare(v, w);
+                }
+
+                if (type2 === 'instance' &amp;&amp; Comparable.detect(w.constructor)) {
+                    return 1 - w.constructor.compare(w, v);
+                }
+            }
+
+            // If we haven't yet generated a reverse-mapping of Ember.ORDER_DEFINITION,
+            // do so now.
+            var mapping = Ember.ORDER_DEFINITION_MAPPING;
+            if (!mapping) {
+                var order = Ember.ORDER_DEFINITION;
+                mapping = Ember.ORDER_DEFINITION_MAPPING = {};
+                var idx, len;
+                for (idx = 0, len = order.length; idx &lt; len; ++idx) {
+                    mapping[order[idx]] = idx;
+                }
+
+                // We no longer need Ember.ORDER_DEFINITION.
+                delete Ember.ORDER_DEFINITION;
+            }
+
+            var type1Index = mapping[type1];
+            var type2Index = mapping[type2];
+
+            if (type1Index &lt; type2Index) {
+                return -1;
+            }
+            if (type1Index &gt; type2Index) {
+                return 1;
+            }
+
+            // types are equal - so we have to check values now
+            switch (type1) {
+            case 'boolean':
+            case 'number':
+                if (v &lt; w) {
+                    return -1;
+                }
+                if (v &gt; w) {
+                    return 1;
+                }
+                return 0;
+
+            case 'string':
+                var comp = v.localeCompare(w);
+                if (comp &lt; 0) {
+                    return -1;
+                }
+                if (comp &gt; 0) {
+                    return 1;
+                }
+                return 0;
+
+            case 'array':
+                var vLen = v.length;
+                var wLen = w.length;
+                var l = Math.min(vLen, wLen);
+                var r = 0;
+                var i = 0;
+                while (r === 0 &amp;&amp; i &lt; l) {
+                    r = compare(v[i], w[i]);
+                    i++;
+                }
+                if (r !== 0) {
+                    return r;
+                }
+
+                // all elements are equal now
+                // shorter array should be ordered first
+                if (vLen &lt; wLen) {
+                    return -1;
+                }
+                if (vLen &gt; wLen) {
+                    return 1;
+                }
+                // arrays are equal now
+                return 0;
+
+            case 'instance':
+                if (Comparable &amp;&amp; Comparable.detect(v)) {
+                    return v.compare(v, w);
+                }
+                return 0;
+
+            case 'date':
+                var vNum = v.getTime();
+                var wNum = w.getTime();
+                if (vNum &lt; wNum) {
+                    return -1;
+                }
+                if (vNum &gt; wNum) {
+                    return 1;
+                }
+                return 0;
+
+            default:
+                return 0;
+            }
+        }
+    });
+    define(&quot;ember-runtime/computed/array_computed&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/computed/reduce_computed&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var reduceComputed = __dependency2__.reduceComputed;
+        var ReduceComputedProperty = __dependency2__.ReduceComputedProperty;
+        var forEach = __dependency3__.forEach;
+        var o_create = __dependency4__.create;
+        var addObserver = __dependency5__.addObserver;
+        var EmberError = __dependency6__[&quot;default&quot;];
+
+        var a_slice = [].slice;
+
+        function ArrayComputedProperty() {
+            var cp = this;
+
+            ReduceComputedProperty.apply(this, arguments);
+
+            this.func = (function(reduceFunc) {
+                return function (propertyName) {
+                    if (!cp._hasInstanceMeta(this, propertyName)) {
+                        // When we recompute an array computed property, we need already
+                        // retrieved arrays to be updated; we can't simply empty the cache and
+                        // hope the array is re-retrieved.
+                        forEach(cp._dependentKeys, function(dependentKey) {
+                            addObserver(this, dependentKey, function() {
+                                cp.recomputeOnce.call(this, propertyName);
+                            });
+                        }, this);
+                    }
+
+                    return reduceFunc.apply(this, arguments);
+                };
+            })(this.func);
+
+            return this;
+        }
+
+        ArrayComputedProperty.prototype = o_create(ReduceComputedProperty.prototype);
+        ArrayComputedProperty.prototype.initialValue = function () {
+            return Ember.A();
+        };
+        ArrayComputedProperty.prototype.resetValue = function (array) {
+            array.clear();
+            return array;
+        };
+
+        // This is a stopgap to keep the reference counts correct with lazy CPs.
+        ArrayComputedProperty.prototype.didChange = function (obj, keyName) {
+            return;
+        };
+
+        /**
+              Creates a computed property which operates on dependent arrays and
+              is updated with &quot;one at a time&quot; semantics. When items are added or
+              removed from the dependent array(s) an array computed only operates
+              on the change instead of re-evaluating the entire array. This should
+              return an array, if you'd like to use &quot;one at a time&quot; semantics and
+              compute some value other then an array look at
+              `Ember.reduceComputed`.
+
+              If there are more than one arguments the first arguments are
+              considered to be dependent property keys. The last argument is
+              required to be an options object. The options object can have the
+              following three properties.
+
+              `initialize` - An optional initialize function. Typically this will be used
+              to set up state on the instanceMeta object.
+
+              `removedItem` - A function that is called each time an element is
+              removed from the array.
+
+              `addedItem` - A function that is called each time an element is
+              added to the array.
+
+
+              The `initialize` function has the following signature:
+
+              ```javascript
+              function(array, changeMeta, instanceMeta)
+              ```
+
+              `array` - The initial value of the arrayComputed, an empty array.
+
+              `changeMeta` - An object which contains meta information about the
+              computed. It contains the following properties:
+
+                 - `property` the computed property
+                 - `propertyName` the name of the property on the object
+
+              `instanceMeta` - An object that can be used to store meta
+              information needed for calculating your computed. For example a
+              unique computed might use this to store the number of times a given
+              element is found in the dependent array.
+
+
+              The `removedItem` and `addedItem` functions both have the following signature:
+
+              ```javascript
+              function(accumulatedValue, item, changeMeta, instanceMeta)
+              ```
+
+              `accumulatedValue` - The value returned from the last time
+              `removedItem` or `addedItem` was called or an empty array.
+
+              `item` - the element added or removed from the array
+
+              `changeMeta` - An object which contains meta information about the
+              change. It contains the following properties:
+
+                - `property` the computed property
+                - `propertyName` the name of the property on the object
+                - `index` the index of the added or removed item
+                - `item` the added or removed item: this is exactly the same as
+                  the second arg
+                - `arrayChanged` the array that triggered the change. Can be
+                  useful when depending on multiple arrays.
+
+              For property changes triggered on an item property change (when
+              depKey is something like `someArray.@each.someProperty`),
+              `changeMeta` will also contain the following property:
+
+                - `previousValues` an object whose keys are the properties that changed on
+                the item, and whose values are the item's previous values.
+
+              `previousValues` is important Ember coalesces item property changes via
+              Ember.run.once. This means that by the time removedItem gets called, item has
+              the new values, but you may need the previous value (eg for sorting &amp;
+              filtering).
+
+              `instanceMeta` - An object that can be used to store meta
+              information needed for calculating your computed. For example a
+              unique computed might use this to store the number of times a given
+              element is found in the dependent array.
+
+              The `removedItem` and `addedItem` functions should return the accumulated
+              value. It is acceptable to not return anything (ie return undefined)
+              to invalidate the computation. This is generally not a good idea for
+              arrayComputed but it's used in eg max and min.
+
+              Example
+
+              ```javascript
+              Ember.computed.map = function(dependentKey, callback) {
+                var options = {
+                  addedItem: function(array, item, changeMeta, instanceMeta) {
+                    var mapped = callback(item);
+                    array.insertAt(changeMeta.index, mapped);
+                    return array;
+                  },
+                  removedItem: function(array, item, changeMeta, instanceMeta) {
+                    array.removeAt(changeMeta.index, 1);
+                    return array;
+                  }
+                };
+
+                return Ember.arrayComputed(dependentKey, options);
+              };
+              ```
+
+              @method arrayComputed
+              @for Ember
+              @param {String} [dependentKeys*]
+              @param {Object} options
+              @return {Ember.ComputedProperty}
+            */
+        function arrayComputed (options) {
+            var args;
+
+            if (arguments.length &gt; 1) {
+                args = a_slice.call(arguments, 0, -1);
+                options = a_slice.call(arguments, -1)[0];
+            }
+
+            if (typeof options !== &quot;object&quot;) {
+                throw new EmberError(&quot;Array Computed Property declared without an options hash&quot;);
+            }
+
+            var cp = new ArrayComputedProperty(options);
+
+            if (args) {
+                cp.property.apply(cp, args);
+            }
+
+            return cp;
+        }
+
+        __exports__.arrayComputed = arrayComputed;
+        __exports__.ArrayComputedProperty = ArrayComputedProperty;
+    });
+    define(&quot;ember-runtime/computed/reduce_computed&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/expand_properties&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/system/tracked_array&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-runtime/system/set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var e_get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var guidFor = __dependency4__.guidFor;
+        var metaFor = __dependency4__.meta;
+        var EmberError = __dependency5__[&quot;default&quot;];
+        var propertyWillChange = __dependency6__.propertyWillChange;
+        var propertyDidChange = __dependency6__.propertyDidChange;
+        var expandProperties = __dependency7__[&quot;default&quot;];
+        var addObserver = __dependency8__.addObserver;
+        var observersFor = __dependency8__.observersFor;
+        var removeObserver = __dependency8__.removeObserver;
+        var addBeforeObserver = __dependency8__.addBeforeObserver;
+        var removeBeforeObserver = __dependency8__.removeBeforeObserver;
+        var ComputedProperty = __dependency9__.ComputedProperty;
+        var cacheFor = __dependency9__.cacheFor;
+        var o_create = __dependency10__.create;
+        var forEach = __dependency11__.forEach;
+        var TrackedArray = __dependency12__[&quot;default&quot;];
+        var EmberArray = __dependency13__[&quot;default&quot;];
+        var run = __dependency14__[&quot;default&quot;];
+        var Set = __dependency15__[&quot;default&quot;];
+        var isArray = __dependency4__.isArray;
+
+        var cacheSet = cacheFor.set;
+        var cacheGet = cacheFor.get;
+        var cacheRemove = cacheFor.remove;
+        var a_slice = [].slice;
+        // Here we explicitly don't allow `@each.foo`; it would require some special
+        // testing, but there's no particular reason why it should be disallowed.
+        var eachPropertyPattern = /^(.*)\.@each\.(.*)/;
+        var doubleEachPropertyPattern = /(.*\.@each){2,}/;
+        var arrayBracketPattern = /\.\[\]$/;
+
+        function get(obj, key) {
+            if (key === '@this') {
+                return obj;
+            }
+
+            return e_get(obj, key);
+        }
+
+        /*
+              Tracks changes to dependent arrays, as well as to properties of items in
+              dependent arrays.
+
+              @class DependentArraysObserver
+            */
+        function DependentArraysObserver(callbacks, cp, instanceMeta, context, propertyName, sugarMeta) {
+            // user specified callbacks for `addedItem` and `removedItem`
+            this.callbacks = callbacks;
+
+            // the computed property: remember these are shared across instances
+            this.cp = cp;
+
+            // the ReduceComputedPropertyInstanceMeta this DependentArraysObserver is
+            // associated with
+            this.instanceMeta = instanceMeta;
+
+            // A map of array guids to dependentKeys, for the given context.  We track
+            // this because we want to set up the computed property potentially before the
+            // dependent array even exists, but when the array observer fires, we lack
+            // enough context to know what to update: we can recover that context by
+            // getting the dependentKey.
+            this.dependentKeysByGuid = {};
+
+            // a map of dependent array guids -&gt; TrackedArray instances.  We use
+            // this to lazily recompute indexes for item property observers.
+            this.trackedArraysByGuid = {};
+
+            // We suspend observers to ignore replacements from `reset` when totally
+            // recomputing.  Unfortunately we cannot properly suspend the observers
+            // because we only have the key; instead we make the observers no-ops
+            this.suspended = false;
+
+            // This is used to coalesce item changes from property observers within a
+            // single item.
+            this.changedItems = {};
+            // This is used to coalesce item changes for multiple items that depend on
+            // some shared state.
+            this.changedItemCount = 0;
+        }
+
+        function ItemPropertyObserverContext (dependentArray, index, trackedArray) {
+            Ember.assert(&quot;Internal error: trackedArray is null or undefined&quot;, trackedArray);
+
+            this.dependentArray = dependentArray;
+            this.index = index;
+            this.item = dependentArray.objectAt(index);
+            this.trackedArray = trackedArray;
+            this.beforeObserver = null;
+            this.observer = null;
+
+            this.destroyed = false;
+        }
+
+        DependentArraysObserver.prototype = {
+            setValue: function (newValue) {
+                this.instanceMeta.setValue(newValue, true);
+            },
+            getValue: function () {
+                return this.instanceMeta.getValue();
+            },
+
+            setupObservers: function (dependentArray, dependentKey) {
+                this.dependentKeysByGuid[guidFor(dependentArray)] = dependentKey;
+
+                dependentArray.addArrayObserver(this, {
+                    willChange: 'dependentArrayWillChange',
+                    didChange: 'dependentArrayDidChange'
+                });
+
+                if (this.cp._itemPropertyKeys[dependentKey]) {
+                    this.setupPropertyObservers(dependentKey, this.cp._itemPropertyKeys[dependentKey]);
+                }
+            },
+
+            teardownObservers: function (dependentArray, dependentKey) {
+                var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [];
+
+                delete this.dependentKeysByGuid[guidFor(dependentArray)];
+
+                this.teardownPropertyObservers(dependentKey, itemPropertyKeys);
+
+                dependentArray.removeArrayObserver(this, {
+                    willChange: 'dependentArrayWillChange',
+                    didChange: 'dependentArrayDidChange'
+                });
+            },
+
+            suspendArrayObservers: function (callback, binding) {
+                var oldSuspended = this.suspended;
+                this.suspended = true;
+                callback.call(binding);
+                this.suspended = oldSuspended;
+            },
+
+            setupPropertyObservers: function (dependentKey, itemPropertyKeys) {
+                var dependentArray = get(this.instanceMeta.context, dependentKey),
+                length = get(dependentArray, 'length'),
+                observerContexts = new Array(length);
+
+                this.resetTransformations(dependentKey, observerContexts);
+
+                forEach(dependentArray, function (item, index) {
+                    var observerContext = this.createPropertyObserverContext(dependentArray, index, this.trackedArraysByGuid[dependentKey]);
+                    observerContexts[index] = observerContext;
+
+                    forEach(itemPropertyKeys, function (propertyKey) {
+                        addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
+                        addObserver(item, propertyKey, this, observerContext.observer);
+                    }, this);
+                }, this);
+            },
+
+            teardownPropertyObservers: function (dependentKey, itemPropertyKeys) {
+                var dependentArrayObserver = this,
+                trackedArray = this.trackedArraysByGuid[dependentKey],
+                beforeObserver,
+                observer,
+                item;
+
+                if (!trackedArray) {
+                    return;
+                }
+
+                trackedArray.apply(function (observerContexts, offset, operation) {
+                    if (operation === TrackedArray.DELETE) {
+                        return;
+                    }
+
+                    forEach(observerContexts, function (observerContext) {
+                        observerContext.destroyed = true;
+                        beforeObserver = observerContext.beforeObserver;
+                        observer = observerContext.observer;
+                        item = observerContext.item;
+
+                        forEach(itemPropertyKeys, function (propertyKey) {
+                            removeBeforeObserver(item, propertyKey, dependentArrayObserver, beforeObserver);
+                            removeObserver(item, propertyKey, dependentArrayObserver, observer);
+                        });
+                    });
+                });
+            },
+
+            createPropertyObserverContext: function (dependentArray, index, trackedArray) {
+                var observerContext = new ItemPropertyObserverContext(dependentArray, index, trackedArray);
+
+                this.createPropertyObserver(observerContext);
+
+                return observerContext;
+            },
+
+            createPropertyObserver: function (observerContext) {
+                var dependentArrayObserver = this;
+
+                observerContext.beforeObserver = function (obj, keyName) {
+                    return dependentArrayObserver.itemPropertyWillChange(obj, keyName, observerContext.dependentArray, observerContext);
+                };
+                observerContext.observer = function (obj, keyName) {
+                    return dependentArrayObserver.itemPropertyDidChange(obj, keyName, observerContext.dependentArray, observerContext);
+                };
+            },
+
+            resetTransformations: function (dependentKey, observerContexts) {
+                this.trackedArraysByGuid[dependentKey] = new TrackedArray(observerContexts);
+            },
+
+            trackAdd: function (dependentKey, index, newItems) {
+                var trackedArray = this.trackedArraysByGuid[dependentKey];
+                if (trackedArray) {
+                    trackedArray.addItems(index, newItems);
+                }
+            },
+
+            trackRemove: function (dependentKey, index, removedCount) {
+                var trackedArray = this.trackedArraysByGuid[dependentKey];
+
+                if (trackedArray) {
+                    return trackedArray.removeItems(index, removedCount);
+                }
+
+                return [];
+            },
+
+            updateIndexes: function (trackedArray, array) {
+                var length = get(array, 'length');
+                // OPTIMIZE: we could stop updating once we hit the object whose observer
+                // fired; ie partially apply the transformations
+                trackedArray.apply(function (observerContexts, offset, operation, operationIndex) {
+                    // we don't even have observer contexts for removed items, even if we did,
+                    // they no longer have any index in the array
+                    if (operation === TrackedArray.DELETE) {
+                        return;
+                    }
+                    if (operationIndex === 0 &amp;&amp; operation === TrackedArray.RETAIN &amp;&amp; observerContexts.length === length &amp;&amp; offset === 0) {
+                        // If we update many items we don't want to walk the array each time: we
+                        // only need to update the indexes at most once per run loop.
+                        return;
+                    }
+
+                    forEach(observerContexts, function (context, index) {
+                        context.index = index + offset;
+                    });
+                });
+            },
+
+            dependentArrayWillChange: function (dependentArray, index, removedCount, addedCount) {
+                if (this.suspended) {
+                    return;
+                }
+
+                var removedItem = this.callbacks.removedItem;
+                var changeMeta;
+                var guid = guidFor(dependentArray);
+                var dependentKey = this.dependentKeysByGuid[guid];
+                var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [];
+                var length = get(dependentArray, 'length');
+                var normalizedIndex = normalizeIndex(index, length, 0);
+                var normalizedRemoveCount = normalizeRemoveCount(normalizedIndex, length, removedCount);
+                var item, itemIndex, sliceIndex, observerContexts;
+
+                observerContexts = this.trackRemove(dependentKey, normalizedIndex, normalizedRemoveCount);
+
+                function removeObservers(propertyKey) {
+                    observerContexts[sliceIndex].destroyed = true;
+                    removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver);
+                    removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer);
+                }
+
+                for (sliceIndex = normalizedRemoveCount - 1; sliceIndex &gt;= 0; --sliceIndex) {
+                    itemIndex = normalizedIndex + sliceIndex;
+                    if (itemIndex &gt;= length) {
+                        break;
+                    }
+
+                    item = dependentArray.objectAt(itemIndex);
+
+                    forEach(itemPropertyKeys, removeObservers, this);
+
+                    changeMeta = new ChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp, normalizedRemoveCount);
+                    this.setValue( removedItem.call(
+                    this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
+                }
+            },
+
+            dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) {
+                if (this.suspended) {
+                    return;
+                }
+
+                var addedItem = this.callbacks.addedItem;
+                var guid = guidFor(dependentArray);
+                var dependentKey = this.dependentKeysByGuid[guid];
+                var observerContexts = new Array(addedCount);
+                var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey];
+                var length = get(dependentArray, 'length');
+                var normalizedIndex = normalizeIndex(index, length, addedCount);
+                var changeMeta, observerContext;
+
+                forEach(dependentArray.slice(normalizedIndex, normalizedIndex + addedCount), function (item, sliceIndex) {
+                    if (itemPropertyKeys) {
+                        observerContext =
+                        observerContexts[sliceIndex] =
+                        this.createPropertyObserverContext(dependentArray, normalizedIndex + sliceIndex, this.trackedArraysByGuid[dependentKey]);
+                        forEach(itemPropertyKeys, function (propertyKey) {
+                            addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
+                            addObserver(item, propertyKey, this, observerContext.observer);
+                        }, this);
+                    }
+
+                    changeMeta = new ChangeMeta(dependentArray, item, normalizedIndex + sliceIndex, this.instanceMeta.propertyName, this.cp, addedCount);
+                    this.setValue( addedItem.call(
+                    this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
+                }, this);
+
+                this.trackAdd(dependentKey, normalizedIndex, observerContexts);
+            },
+
+            itemPropertyWillChange: function (obj, keyName, array, observerContext) {
+                var guid = guidFor(obj);
+
+                if (!this.changedItems[guid]) {
+                    this.changedItems[guid] = {
+                        array: array,
+                        observerContext: observerContext,
+                        obj: obj,
+                        previousValues: {}
+                    };
+                }
+                ++this.changedItemCount;
+
+                this.changedItems[guid].previousValues[keyName] = get(obj, keyName);
+            },
+
+            itemPropertyDidChange: function(obj, keyName, array, observerContext) {
+                if (--this.changedItemCount === 0) {
+                    this.flushChanges();
+                }
+            },
+
+            flushChanges: function() {
+                var changedItems = this.changedItems, key, c, changeMeta;
+
+                for (key in changedItems) {
+                    c = changedItems[key];
+                    if (c.observerContext.destroyed) {
+                        continue;
+                    }
+
+                    this.updateIndexes(c.observerContext.trackedArray, c.observerContext.dependentArray);
+
+                    changeMeta = new ChangeMeta(c.array, c.obj, c.observerContext.index, this.instanceMeta.propertyName, this.cp, changedItems.length, c.previousValues);
+                    this.setValue(
+                    this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
+                    this.setValue(
+                    this.callbacks.addedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta));
+                }
+                this.changedItems = {};
+            }
+        };
+
+        function normalizeIndex(index, length, newItemsOffset) {
+            if (index &lt; 0) {
+                return Math.max(0, length + index);
+            } else if (index &lt; length) {
+                return index;
+            } else /* index &gt; length */
+            {
+                return Math.min(length - newItemsOffset, index);
+            }
+        }
+
+        function normalizeRemoveCount(index, length, removedCount) {
+            return Math.min(removedCount, length - index);
+        }
+
+        function ChangeMeta(dependentArray, item, index, propertyName, property, changedCount, previousValues) {
+            this.arrayChanged = dependentArray;
+            this.index = index;
+            this.item = item;
+            this.propertyName = propertyName;
+            this.property = property;
+            this.changedCount = changedCount;
+
+            if (previousValues) {
+                // previous values only available for item property changes
+                this.previousValues = previousValues;
+            }
+        }
+
+        function addItems (dependentArray, callbacks, cp, propertyName, meta) {
+            forEach(dependentArray, function (item, index) {
+                meta.setValue( callbacks.addedItem.call(
+                this, meta.getValue(), item, new ChangeMeta(dependentArray, item, index, propertyName, cp, dependentArray.length), meta.sugarMeta));
+            }, this);
+        }
+
+        function reset(cp, propertyName) {
+            var callbacks = cp._callbacks(),
+            meta;
+
+            if (cp._hasInstanceMeta(this, propertyName)) {
+                meta = cp._instanceMeta(this, propertyName);
+                meta.setValue(cp.resetValue(meta.getValue()));
+            } else {
+                meta = cp._instanceMeta(this, propertyName);
+            }
+
+            if (cp.options.initialize) {
+                cp.options.initialize.call(this, meta.getValue(), {
+                    property: cp,
+                    propertyName: propertyName 
+                }, meta.sugarMeta);
+            }
+        }
+
+        function partiallyRecomputeFor(obj, dependentKey) {
+            if (arrayBracketPattern.test(dependentKey)) {
+                return false;
+            }
+
+            var value = get(obj, dependentKey);
+            return EmberArray.detect(value);
+        }
+
+        function ReduceComputedPropertyInstanceMeta(context, propertyName, initialValue) {
+            this.context = context;
+            this.propertyName = propertyName;
+            this.cache = metaFor(context).cache;
+
+            this.dependentArrays = {};
+            this.sugarMeta = {};
+
+            this.initialValue = initialValue;
+        }
+
+        ReduceComputedPropertyInstanceMeta.prototype = {
+            getValue: function () {
+                var value = cacheGet(this.cache, this.propertyName);
+                if (value !== undefined) {
+                    return value;
+                } else {
+                    return this.initialValue;
+                }
+            },
+
+            setValue: function(newValue, triggerObservers) {
+                // This lets sugars force a recomputation, handy for very simple
+                // implementations of eg max.
+                if (newValue === cacheGet(this.cache, this.propertyName)) {
+                    return;
+                }
+
+                if (triggerObservers) {
+                    propertyWillChange(this.context, this.propertyName);
+                }
+
+                if (newValue === undefined) {
+                    cacheRemove(this.cache, this.propertyName);
+                } else {
+                    cacheSet(this.cache, this.propertyName, newValue);
+                }
+
+                if (triggerObservers) {
+                    propertyDidChange(this.context, this.propertyName);
+                }
+            }
+        };
+
+        /**
+              A computed property whose dependent keys are arrays and which is updated with
+              &quot;one at a time&quot; semantics.
+
+              @class ReduceComputedProperty
+              @namespace Ember
+              @extends Ember.ComputedProperty
+              @constructor
+            */
+
+        __exports__.ReduceComputedProperty = ReduceComputedProperty;
+        // TODO: default export
+        function ReduceComputedProperty(options) {
+            var cp = this;
+
+            this.options = options;
+
+            this._dependentKeys = null;
+            // A map of dependentKey -&gt; [itemProperty, ...] that tracks what properties of
+            // items in the array we must track to update this property.
+            this._itemPropertyKeys = {};
+            this._previousItemPropertyKeys = {};
+
+            this.readOnly();
+            this.cacheable();
+
+            this.recomputeOnce = function(propertyName) {
+                // What we really want to do is coalesce by &lt;cp, propertyName&gt;.
+                // We need a form of `scheduleOnce` that accepts an arbitrary token to
+                // coalesce by, in addition to the target and method.
+                run.once(this, recompute, propertyName);
+            };
+            var recompute = function(propertyName) {
+                var dependentKeys = cp._dependentKeys,
+                meta = cp._instanceMeta(this, propertyName),
+                callbacks = cp._callbacks();
+
+                reset.call(this, cp, propertyName);
+
+                meta.dependentArraysObserver.suspendArrayObservers(function () {
+                    forEach(cp._dependentKeys, function (dependentKey) {
+                        Ember.assert(
+                        &quot;dependent array &quot; + dependentKey + &quot; must be an `Ember.Array`.  &quot; +
+                        &quot;If you are not extending arrays, you will need to wrap native arrays with `Ember.A`&quot;,
+                        !(isArray(get(this, dependentKey)) &amp;&amp; !EmberArray.detect(get(this, dependentKey))));
+
+                        if (!partiallyRecomputeFor(this, dependentKey)) {
+                            return;
+                        }
+
+                        var dependentArray = get(this, dependentKey),
+                        previousDependentArray = meta.dependentArrays[dependentKey];
+
+                        if (dependentArray === previousDependentArray) {
+                            // The array may be the same, but our item property keys may have
+                            // changed, so we set them up again.  We can't easily tell if they've
+                            // changed: the array may be the same object, but with different
+                            // contents.
+                            if (cp._previousItemPropertyKeys[dependentKey]) {
+                                delete cp._previousItemPropertyKeys[dependentKey];
+                                meta.dependentArraysObserver.setupPropertyObservers(dependentKey, cp._itemPropertyKeys[dependentKey]);
+                            }
+                        } else {
+                            meta.dependentArrays[dependentKey] = dependentArray;
+
+                            if (previousDependentArray) {
+                                meta.dependentArraysObserver.teardownObservers(previousDependentArray, dependentKey);
+                            }
+
+                            if (dependentArray) {
+                                meta.dependentArraysObserver.setupObservers(dependentArray, dependentKey);
+                            }
+                        }
+                    }, this);
+                }, this);
+
+                forEach(cp._dependentKeys, function(dependentKey) {
+                    if (!partiallyRecomputeFor(this, dependentKey)) {
+                        return;
+                    }
+
+                    var dependentArray = get(this, dependentKey);
+                    if (dependentArray) {
+                        addItems.call(this, dependentArray, callbacks, cp, propertyName, meta);
+                    }
+                }, this);
+            };
+
+
+            this.func = function (propertyName) {
+                Ember.assert(&quot;Computed reduce values require at least one dependent key&quot;, cp._dependentKeys);
+
+                recompute.call(this, propertyName);
+
+                return cp._instanceMeta(this, propertyName).getValue();
+            };
+        }
+
+        ReduceComputedProperty.prototype = o_create(ComputedProperty.prototype);
+
+        function defaultCallback(computedValue) {
+            return computedValue;
+        }
+
+        ReduceComputedProperty.prototype._callbacks = function () {
+            if (!this.callbacks) {
+                var options = this.options;
+                this.callbacks = {
+                    removedItem: options.removedItem || defaultCallback,
+                    addedItem: options.addedItem || defaultCallback
+                };
+            }
+            return this.callbacks;
+        };
+
+        ReduceComputedProperty.prototype._hasInstanceMeta = function (context, propertyName) {
+            return !!metaFor(context).cacheMeta[propertyName];
+        };
+
+        ReduceComputedProperty.prototype._instanceMeta = function (context, propertyName) {
+            var cacheMeta = metaFor(context).cacheMeta,
+            meta = cacheMeta[propertyName];
+
+            if (!meta) {
+                meta = cacheMeta[propertyName] = new ReduceComputedPropertyInstanceMeta(context, propertyName, this.initialValue());
+                meta.dependentArraysObserver = new DependentArraysObserver(this._callbacks(), this, meta, context, propertyName, meta.sugarMeta);
+            }
+
+            return meta;
+        };
+
+        ReduceComputedProperty.prototype.initialValue = function () {
+            if (typeof this.options.initialValue === 'function') {
+                return this.options.initialValue();
+            } else {
+                return this.options.initialValue;
+            }
+        };
+
+        ReduceComputedProperty.prototype.resetValue = function (value) {
+            return this.initialValue();
+        };
+
+        ReduceComputedProperty.prototype.itemPropertyKey = function (dependentArrayKey, itemPropertyKey) {
+            this._itemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey] || [];
+            this._itemPropertyKeys[dependentArrayKey].push(itemPropertyKey);
+        };
+
+        ReduceComputedProperty.prototype.clearItemPropertyKeys = function (dependentArrayKey) {
+            if (this._itemPropertyKeys[dependentArrayKey]) {
+                this._previousItemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey];
+                this._itemPropertyKeys[dependentArrayKey] = [];
+            }
+        };
+
+        ReduceComputedProperty.prototype.property = function () {
+            var cp = this,
+            args = a_slice.call(arguments),
+            propertyArgs = new Set(),
+            match,
+            dependentArrayKey,
+            itemPropertyKey;
+
+            forEach(args, function (dependentKey) {
+                if (doubleEachPropertyPattern.test(dependentKey)) {
+                    throw new EmberError(&quot;Nested @each properties not supported: &quot; + dependentKey);
+                } else if (match = eachPropertyPattern.exec(dependentKey)) {
+                    dependentArrayKey = match[1];
+
+                    var itemPropertyKeyPattern = match[2],
+                    addItemPropertyKey = function (itemPropertyKey) {
+                        cp.itemPropertyKey(dependentArrayKey, itemPropertyKey);
+                    };
+
+                    expandProperties(itemPropertyKeyPattern, addItemPropertyKey);
+                    propertyArgs.add(dependentArrayKey);
+                } else {
+                    propertyArgs.add(dependentKey);
+                }
+            });
+
+            return ComputedProperty.prototype.property.apply(this, propertyArgs.toArray());
+
+        };
+
+        /**
+              Creates a computed property which operates on dependent arrays and
+              is updated with &quot;one at a time&quot; semantics. When items are added or
+              removed from the dependent array(s) a reduce computed only operates
+              on the change instead of re-evaluating the entire array.
+
+              If there are more than one arguments the first arguments are
+              considered to be dependent property keys. The last argument is
+              required to be an options object. The options object can have the
+              following four properties:
+
+              `initialValue` - A value or function that will be used as the initial
+              value for the computed. If this property is a function the result of calling
+              the function will be used as the initial value. This property is required.
+
+              `initialize` - An optional initialize function. Typically this will be used
+              to set up state on the instanceMeta object.
+
+              `removedItem` - A function that is called each time an element is removed
+              from the array.
+
+              `addedItem` - A function that is called each time an element is added to
+              the array.
+
+
+              The `initialize` function has the following signature:
+
+              ```javascript
+              function(initialValue, changeMeta, instanceMeta)
+              ```
+
+              `initialValue` - The value of the `initialValue` property from the
+              options object.
+
+              `changeMeta` - An object which contains meta information about the
+              computed. It contains the following properties:
+
+                 - `property` the computed property
+                 - `propertyName` the name of the property on the object
+
+              `instanceMeta` - An object that can be used to store meta
+              information needed for calculating your computed. For example a
+              unique computed might use this to store the number of times a given
+              element is found in the dependent array.
+
+
+              The `removedItem` and `addedItem` functions both have the following signature:
+
+              ```javascript
+              function(accumulatedValue, item, changeMeta, instanceMeta)
+              ```
+
+              `accumulatedValue` - The value returned from the last time
+              `removedItem` or `addedItem` was called or `initialValue`.
+
+              `item` - the element added or removed from the array
+
+              `changeMeta` - An object which contains meta information about the
+              change. It contains the following properties:
+
+                - `property` the computed property
+                - `propertyName` the name of the property on the object
+                - `index` the index of the added or removed item
+                - `item` the added or removed item: this is exactly the same as
+                  the second arg
+                - `arrayChanged` the array that triggered the change. Can be
+                  useful when depending on multiple arrays.
+
+              For property changes triggered on an item property change (when
+              depKey is something like `someArray.@each.someProperty`),
+              `changeMeta` will also contain the following property:
+
+                - `previousValues` an object whose keys are the properties that changed on
+                the item, and whose values are the item's previous values.
+
+              `previousValues` is important Ember coalesces item property changes via
+              Ember.run.once. This means that by the time removedItem gets called, item has
+              the new values, but you may need the previous value (eg for sorting &amp;
+              filtering).
+
+              `instanceMeta` - An object that can be used to store meta
+              information needed for calculating your computed. For example a
+              unique computed might use this to store the number of times a given
+              element is found in the dependent array.
+
+              The `removedItem` and `addedItem` functions should return the accumulated
+              value. It is acceptable to not return anything (ie return undefined)
+              to invalidate the computation. This is generally not a good idea for
+              arrayComputed but it's used in eg max and min.
+
+              Note that observers will be fired if either of these functions return a value
+              that differs from the accumulated value.  When returning an object that
+              mutates in response to array changes, for example an array that maps
+              everything from some other array (see `Ember.computed.map`), it is usually
+              important that the *same* array be returned to avoid accidentally triggering observers.
+
+              Example
+
+              ```javascript
+              Ember.computed.max = function(dependentKey) {
+                return Ember.reduceComputed(dependentKey, {
+                  initialValue: -Infinity,
+
+                  addedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
+                    return Math.max(accumulatedValue, item);
+                  },
+
+                  removedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
+                    if (item &lt; accumulatedValue) {
+                      return accumulatedValue;
+                    }
+                  }
+                });
+              };
+              ```
+
+              Dependent keys may refer to `@this` to observe changes to the object itself,
+              which must be array-like, rather than a property of the object.  This is
+              mostly useful for array proxies, to ensure objects are retrieved via
+              `objectAtContent`.  This is how you could sort items by properties defined on an item controller.
+
+              Example
+
+              ```javascript
+              App.PeopleController = Ember.ArrayController.extend({
+                itemController: 'person',
+
+                sortedPeople: Ember.computed.sort('@this.@each.reversedName', function(personA, personB) {
+                  // `reversedName` isn't defined on Person, but we have access to it via
+                  // the item controller App.PersonController.  If we'd used
+                  // `content.@each.reversedName` above, we would be getting the objects
+                  // directly and not have access to `reversedName`.
+                  //
+                  var reversedNameA = get(personA, 'reversedName'),
+                      reversedNameB = get(personB, 'reversedName');
+
+                  return Ember.compare(reversedNameA, reversedNameB);
+                })
+              });
+
+              App.PersonController = Ember.ObjectController.extend({
+                reversedName: function() {
+                  return reverse(get(this, 'name'));
+                }.property('name')
+              });
+              ```
+
+              Dependent keys whose values are not arrays are treated as regular
+              dependencies: when they change, the computed property is completely
+              recalculated.  It is sometimes useful to have dependent arrays with similar
+              semantics.  Dependent keys which end in `.[]` do not use &quot;one at a time&quot;
+              semantics.  When an item is added or removed from such a dependency, the
+              computed property is completely recomputed.
+
+              When the computed property is completely recomputed, the `accumulatedValue`
+              is discarded, it starts with `initialValue` again, and each item is passed
+              to `addedItem` in turn.
+
+              Example
+
+              ```javascript
+              Ember.Object.extend({
+                // When `string` is changed, `computed` is completely recomputed.
+                string: 'a string',
+
+                // When an item is added to `array`, `addedItem` is called.
+                array: [],
+
+                // When an item is added to `anotherArray`, `computed` is completely
+                // recomputed.
+                anotherArray: [],
+
+                computed: Ember.reduceComputed('string', 'array', 'anotherArray.[]', {
+                  addedItem: addedItemCallback,
+                  removedItem: removedItemCallback
+                })
+              });
+              ```
+
+              @method reduceComputed
+              @for Ember
+              @param {String} [dependentKeys*]
+              @param {Object} options
+              @return {Ember.ComputedProperty}
+            */
+        function reduceComputed(options) {
+            var args;
+
+            if (arguments.length &gt; 1) {
+                args = a_slice.call(arguments, 0, -1);
+                options = a_slice.call(arguments, -1)[0];
+            }
+
+            if (typeof options !== &quot;object&quot;) {
+                throw new EmberError(&quot;Reduce Computed Property declared without an options hash&quot;);
+            }
+
+            if (!('initialValue' in options)) {
+                throw new EmberError(&quot;Reduce Computed Property declared without an initial value&quot;);
+            }
+
+            var cp = new ReduceComputedProperty(options);
+
+            if (args) {
+                cp.property.apply(cp, args);
+            }
+
+            return cp;
+        }
+
+        __exports__.reduceComputed = reduceComputed;
+    });
+    define(&quot;ember-runtime/computed/reduce_computed_macros&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/observer&quot;, &quot;ember-runtime/computed/array_computed&quot;, &quot;ember-runtime/computed/reduce_computed&quot;, &quot;ember-runtime/system/object_proxy&quot;, &quot;ember-runtime/system/subarray&quot;, &quot;ember-runtime/keys&quot;, &quot;ember-runtime/compare&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var merge = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var set = __dependency4__.set;
+        var isArray = __dependency5__.isArray;
+        var guidFor = __dependency5__.guidFor;
+        var EmberError = __dependency6__[&quot;default&quot;];
+        var forEach = __dependency7__.forEach;
+        var run = __dependency8__[&quot;default&quot;];
+        var addObserver = __dependency9__.addObserver;
+        var arrayComputed = __dependency10__.arrayComputed;
+        var reduceComputed = __dependency11__.reduceComputed;
+        var ObjectProxy = __dependency12__[&quot;default&quot;];
+        var SubArray = __dependency13__[&quot;default&quot;];
+        var keys = __dependency14__[&quot;default&quot;];
+        var compare = __dependency15__[&quot;default&quot;];
+
+        var a_slice = [].slice;
+
+        /**
+             A computed property that returns the sum of the value
+             in the dependent array.
+
+             @method computed.sum
+             @for Ember
+             @param {String} dependentKey
+             @return {Ember.ComputedProperty} computes the sum of all values in the dependentKey's array
+             @since 1.4.0
+            */
+
+        function sum(dependentKey) {
+            return reduceComputed(dependentKey, {
+                initialValue: 0,
+
+                addedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
+                    return accumulatedValue + item;
+                },
+
+                removedItem: function(accumulatedValue, item, changeMeta, instanceMeta) {
+                    return accumulatedValue - item;
+                }
+            });
+        }
+
+        __exports__.sum = sum; /**
+              A computed property that calculates the maximum value in the
+              dependent array. This will return `-Infinity` when the dependent
+              array is empty.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                childAges: Ember.computed.mapBy('children', 'age'),
+                maxChildAge: Ember.computed.max('childAges')
+              });
+
+              var lordByron = Person.create({ children: [] });
+
+              lordByron.get('maxChildAge'); // -Infinity
+              lordByron.get('children').pushObject({
+                name: 'Augusta Ada Byron', age: 7
+              });
+              lordByron.get('maxChildAge'); // 7
+              lordByron.get('children').pushObjects([{
+                name: 'Allegra Byron',
+                age: 5
+              }, {
+                name: 'Elizabeth Medora Leigh',
+                age: 8
+              }]);
+              lordByron.get('maxChildAge'); // 8
+              ```
+
+              @method computed.max
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
+            */
+        function max (dependentKey) {
+            return reduceComputed(dependentKey, {
+                initialValue: - Infinity,
+
+                addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
+                    return Math.max(accumulatedValue, item);
+                },
+
+                removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
+                    if (item &lt; accumulatedValue) {
+                        return accumulatedValue;
+                    }
+                }
+            });
+        }
+
+        __exports__.max = max; /**
+              A computed property that calculates the minimum value in the
+              dependent array. This will return `Infinity` when the dependent
+              array is empty.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                childAges: Ember.computed.mapBy('children', 'age'),
+                minChildAge: Ember.computed.min('childAges')
+              });
+
+              var lordByron = Person.create({ children: [] });
+
+              lordByron.get('minChildAge'); // Infinity
+              lordByron.get('children').pushObject({
+                name: 'Augusta Ada Byron', age: 7
+              });
+              lordByron.get('minChildAge'); // 7
+              lordByron.get('children').pushObjects([{
+                name: 'Allegra Byron',
+                age: 5
+              }, {
+                name: 'Elizabeth Medora Leigh',
+                age: 8
+              }]);
+              lordByron.get('minChildAge'); // 5
+              ```
+
+              @method computed.min
+              @for Ember
+              @param {String} dependentKey
+              @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
+            */
+        function min(dependentKey) {
+            return reduceComputed(dependentKey, {
+                initialValue: Infinity,
+
+                addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
+                    return Math.min(accumulatedValue, item);
+                },
+
+                removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
+                    if (item &gt; accumulatedValue) {
+                        return accumulatedValue;
+                    }
+                }
+            });
+        }
+
+        __exports__.min = min; /**
+              Returns an array mapped via the callback
+
+              The callback method you provide should have the following signature.
+              `item` is the current item in the iteration.
+
+              ```javascript
+              function(item);
+              ```
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                excitingChores: Ember.computed.map('chores', function(chore) {
+                  return chore.toUpperCase() + '!';
+                })
+              });
+
+              var hamster = Hamster.create({
+                chores: ['clean', 'write more unit tests']
+              });
+
+              hamster.get('excitingChores'); // ['CLEAN!', 'WRITE MORE UNIT TESTS!']
+              ```
+
+              @method computed.map
+              @for Ember
+              @param {String} dependentKey
+              @param {Function} callback
+              @return {Ember.ComputedProperty} an array mapped via the callback
+            */
+        function map(dependentKey, callback) {
+            var options = {
+                addedItem: function(array, item, changeMeta, instanceMeta) {
+                    var mapped = callback.call(this, item);
+                    array.insertAt(changeMeta.index, mapped);
+                    return array;
+                },
+                removedItem: function(array, item, changeMeta, instanceMeta) {
+                    array.removeAt(changeMeta.index, 1);
+                    return array;
+                }
+            };
+
+            return arrayComputed(dependentKey, options);
+        }
+
+        __exports__.map = map; /**
+              Returns an array mapped to the specified key.
+
+              ```javascript
+              var Person = Ember.Object.extend({
+                childAges: Ember.computed.mapBy('children', 'age')
+              });
+
+              var lordByron = Person.create({ children: [] });
+
+              lordByron.get('childAges'); // []
+              lordByron.get('children').pushObject({ name: 'Augusta Ada Byron', age: 7 });
+              lordByron.get('childAges'); // [7]
+              lordByron.get('children').pushObjects([{
+                name: 'Allegra Byron',
+                age: 5
+              }, {
+                name: 'Elizabeth Medora Leigh',
+                age: 8
+              }]);
+              lordByron.get('childAges'); // [7, 5, 8]
+              ```
+
+              @method computed.mapBy
+              @for Ember
+              @param {String} dependentKey
+              @param {String} propertyKey
+              @return {Ember.ComputedProperty} an array mapped to the specified key
+            */
+        function mapBy (dependentKey, propertyKey) {
+            var callback = function(item) {
+                return get(item, propertyKey);
+            };
+            return map(dependentKey + '.@each.' + propertyKey, callback);
+        }
+
+        __exports__.mapBy = mapBy; /**
+              @method computed.mapProperty
+              @for Ember
+              @deprecated Use `Ember.computed.mapBy` instead
+              @param dependentKey
+              @param propertyKey
+            */
+        var mapProperty = mapBy;
+        __exports__.mapProperty = mapProperty;
+        /**
+              Filters the array by the callback.
+
+              The callback method you provide should have the following signature.
+              `item` is the current item in the iteration.
+
+              ```javascript
+              function(item);
+              ```
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                remainingChores: Ember.computed.filter('chores', function(chore) {
+                  return !chore.done;
+                })
+              });
+
+              var hamster = Hamster.create({ 
+                chores: [
+                  { name: 'cook', done: true },
+                  { name: 'clean', done: true },
+                  { name: 'write more unit tests', done: false }
+                ] 
+              });
+
+              hamster.get('remainingChores'); // [{name: 'write more unit tests', done: false}]
+              ```
+
+              @method computed.filter
+              @for Ember
+              @param {String} dependentKey
+              @param {Function} callback
+              @return {Ember.ComputedProperty} the filtered array
+            */
+        function filter(dependentKey, callback) {
+            var options = {
+                initialize: function (array, changeMeta, instanceMeta) {
+                    instanceMeta.filteredArrayIndexes = new SubArray();
+                },
+
+                addedItem: function(array, item, changeMeta, instanceMeta) {
+                    var match = !!callback.call(this, item),
+                    filterIndex = instanceMeta.filteredArrayIndexes.addItem(changeMeta.index, match);
+
+                    if (match) {
+                        array.insertAt(filterIndex, item);
+                    }
+
+                    return array;
+                },
+
+                removedItem: function(array, item, changeMeta, instanceMeta) {
+                    var filterIndex = instanceMeta.filteredArrayIndexes.removeItem(changeMeta.index);
+
+                    if (filterIndex &gt; -1) {
+                        array.removeAt(filterIndex);
+                    }
+
+                    return array;
+                }
+            };
+
+            return arrayComputed(dependentKey, options);
+        }
+
+        __exports__.filter = filter; /**
+              Filters the array by the property and value
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                remainingChores: Ember.computed.filterBy('chores', 'done', false)
+              });
+
+              var hamster = Hamster.create({
+                chores: [
+                  { name: 'cook', done: true },
+                  { name: 'clean', done: true },
+                  { name: 'write more unit tests', done: false }
+                ]
+              });
+
+              hamster.get('remainingChores'); // [{ name: 'write more unit tests', done: false }]
+              ```
+
+              @method computed.filterBy
+              @for Ember
+              @param {String} dependentKey
+              @param {String} propertyKey
+              @param {*} value
+              @return {Ember.ComputedProperty} the filtered array
+            */
+        function filterBy (dependentKey, propertyKey, value) {
+            var callback;
+
+            if (arguments.length === 2) {
+                callback = function(item) {
+                    return get(item, propertyKey);
+                };
+            } else {
+                callback = function(item) {
+                    return get(item, propertyKey) === value;
+                };
+            }
+
+            return filter(dependentKey + '.@each.' + propertyKey, callback);
+        }
+
+        __exports__.filterBy = filterBy; /**
+              @method computed.filterProperty
+              @for Ember
+              @param dependentKey
+              @param propertyKey
+              @param value
+              @deprecated Use `Ember.computed.filterBy` instead
+            */
+        var filterProperty = filterBy;
+        __exports__.filterProperty = filterProperty;
+        /**
+              A computed property which returns a new array with all the unique
+              elements from one or more dependent arrays.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                uniqueFruits: Ember.computed.uniq('fruits')
+              });
+
+              var hamster = Hamster.create({
+                fruits: [
+                  'banana',
+                  'grape',
+                  'kale',
+                  'banana'
+                ]
+              });
+
+              hamster.get('uniqueFruits'); // ['banana', 'grape', 'kale']
+              ```
+
+              @method computed.uniq
+              @for Ember
+              @param {String} propertyKey*
+              @return {Ember.ComputedProperty} computes a new array with all the
+              unique elements from the dependent array
+            */
+        function uniq() {
+            var args = a_slice.call(arguments);
+            args.push({
+                initialize: function(array, changeMeta, instanceMeta) {
+                    instanceMeta.itemCounts = {};
+                },
+
+                addedItem: function(array, item, changeMeta, instanceMeta) {
+                    var guid = guidFor(item);
+
+                    if (!instanceMeta.itemCounts[guid]) {
+                        instanceMeta.itemCounts[guid] = 1;
+                    } else {
+                        ++instanceMeta.itemCounts[guid];
+                    }
+                    array.addObject(item);
+                    return array;
+                },
+                removedItem: function(array, item, _, instanceMeta) {
+                    var guid = guidFor(item),
+                    itemCounts = instanceMeta.itemCounts;
+
+                    if (--itemCounts[guid] === 0) {
+                        array.removeObject(item);
+                    }
+                    return array;
+                }
+            });
+            return arrayComputed.apply(null, args);
+        }
+
+        __exports__.uniq = uniq; /**
+              Alias for [Ember.computed.uniq](/api/#method_computed_uniq).
+
+              @method computed.union
+              @for Ember
+              @param {String} propertyKey*
+              @return {Ember.ComputedProperty} computes a new array with all the
+              unique elements from the dependent array
+            */
+        var union = uniq;
+        __exports__.union = union;
+        /**
+              A computed property which returns a new array with all the duplicated
+              elements from two or more dependent arrays.
+
+              Example
+
+              ```javascript
+              var obj = Ember.Object.createWithMixins({
+                adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
+                charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'],
+                friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
+              });
+
+              obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
+              ```
+
+              @method computed.intersect
+              @for Ember
+              @param {String} propertyKey*
+              @return {Ember.ComputedProperty} computes a new array with all the
+              duplicated elements from the dependent arrays
+            */
+        function intersect() {
+            var getDependentKeyGuids = function (changeMeta) {
+                return map(changeMeta.property._dependentKeys, function (dependentKey) {
+                    return guidFor(dependentKey);
+                });
+            };
+
+            var args = a_slice.call(arguments);
+            args.push({
+                initialize: function (array, changeMeta, instanceMeta) {
+                    instanceMeta.itemCounts = {};
+                },
+
+                addedItem: function(array, item, changeMeta, instanceMeta) {
+                    var itemGuid = guidFor(item),
+                    dependentGuids = getDependentKeyGuids(changeMeta),
+                    dependentGuid = guidFor(changeMeta.arrayChanged),
+                    numberOfDependentArrays = changeMeta.property._dependentKeys.length,
+                    itemCounts = instanceMeta.itemCounts;
+
+                    if (!itemCounts[itemGuid]) {
+                        itemCounts[itemGuid] = {};
+                    }
+                    if (itemCounts[itemGuid][dependentGuid] === undefined) {
+                        itemCounts[itemGuid][dependentGuid] = 0;
+                    }
+
+                    if (++itemCounts[itemGuid][dependentGuid] === 1 &amp;&amp;
+                    numberOfDependentArrays === keys(itemCounts[itemGuid]).length) {
+
+                        array.addObject(item);
+                    }
+                    return array;
+                },
+                removedItem: function(array, item, changeMeta, instanceMeta) {
+                    var itemGuid = guidFor(item),
+                    dependentGuids = getDependentKeyGuids(changeMeta),
+                    dependentGuid = guidFor(changeMeta.arrayChanged),
+                    numberOfDependentArrays = changeMeta.property._dependentKeys.length,
+                    numberOfArraysItemAppearsIn,
+                    itemCounts = instanceMeta.itemCounts;
+
+                    if (itemCounts[itemGuid][dependentGuid] === undefined) {
+                        itemCounts[itemGuid][dependentGuid] = 0;
+                    }
+                    if (--itemCounts[itemGuid][dependentGuid] === 0) {
+                        delete itemCounts[itemGuid][dependentGuid];
+                        numberOfArraysItemAppearsIn = keys(itemCounts[itemGuid]).length;
+
+                        if (numberOfArraysItemAppearsIn === 0) {
+                            delete itemCounts[itemGuid];
+                        }
+                        array.removeObject(item);
+                    }
+                    return array;
+                }
+            });
+            return arrayComputed.apply(null, args);
+        }
+
+        __exports__.intersect = intersect; /**
+              A computed property which returns a new array with all the
+              properties from the first dependent array that are not in the second
+              dependent array.
+
+              Example
+
+              ```javascript
+              var Hamster = Ember.Object.extend({
+                likes: ['banana', 'grape', 'kale'],
+                wants: Ember.computed.setDiff('likes', 'fruits')
+              });
+
+              var hamster = Hamster.create({
+                fruits: [
+                  'grape',
+                  'kale',
+                ]
+              });
+
+              hamster.get('wants'); // ['banana']
+              ```
+
+              @method computed.setDiff
+              @for Ember
+              @param {String} setAProperty
+              @param {String} setBProperty
+              @return {Ember.ComputedProperty} computes a new array with all the
+              items from the first dependent array that are not in the second
+              dependent array
+            */
+        function setDiff(setAProperty, setBProperty) {
+            if (arguments.length !== 2) {
+                throw new EmberError(&quot;setDiff requires exactly two dependent arrays.&quot;);
+            }
+            return arrayComputed(setAProperty, setBProperty, {
+                addedItem: function (array, item, changeMeta, instanceMeta) {
+                    var setA = get(this, setAProperty),
+                    setB = get(this, setBProperty);
+
+                    if (changeMeta.arrayChanged === setA) {
+                        if (!setB.contains(item)) {
+                            array.addObject(item);
+                        }
+                    } else {
+                        array.removeObject(item);
+                    }
+                    return array;
+                },
+
+                removedItem: function (array, item, changeMeta, instanceMeta) {
+                    var setA = get(this, setAProperty),
+                    setB = get(this, setBProperty);
+
+                    if (changeMeta.arrayChanged === setB) {
+                        if (setA.contains(item)) {
+                            array.addObject(item);
+                        }
+                    } else {
+                        array.removeObject(item);
+                    }
+                    return array;
+                }
+            });
+        }
+
+        __exports__.setDiff = setDiff;
+        function binarySearch(array, item, low, high) {
+            var mid, midItem, res, guidMid, guidItem;
+
+            if (arguments.length &lt; 4) {
+                high = get(array, 'length');
+            }
+            if (arguments.length &lt; 3) {
+                low = 0;
+            }
+
+            if (low === high) {
+                return low;
+            }
+
+            mid = low + Math.floor((high - low) / 2);
+            midItem = array.objectAt(mid);
+
+            guidMid = _guidFor(midItem);
+            guidItem = _guidFor(item);
+
+            if (guidMid === guidItem) {
+                return mid;
+            }
+
+            res = this.order(midItem, item);
+            if (res === 0) {
+                res = guidMid &lt; guidItem ? -1 : 1;
+            }
+
+
+            if (res &lt; 0) {
+                return this.binarySearch(array, item, mid + 1, high);
+            } else if (res &gt; 0) {
+                return this.binarySearch(array, item, low, mid);
+            }
+
+            return mid;
+
+            function _guidFor(item) {
+                if (SearchProxy.detectInstance(item)) {
+                    return guidFor(get(item, 'content'));
+                }
+                return guidFor(item);
+            }
+        }
+
+
+        var SearchProxy = ObjectProxy.extend();
+
+        /**
+              A computed property which returns a new array with all the
+              properties from the first dependent array sorted based on a property
+              or sort function.
+
+              The callback method you provide should have the following signature:
+
+              ```javascript
+              function(itemA, itemB);
+              ```
+
+              - `itemA` the first item to compare.
+              - `itemB` the second item to compare.
+
+              This function should return negative number (e.g. `-1`) when `itemA` should come before
+              `itemB`. It should return positive number (e.g. `1`) when `itemA` should come after
+              `itemB`. If the `itemA` and `itemB` are equal this function should return `0`.
+
+              Therefore, if this function is comparing some numeric values, simple `itemA - itemB` or
+              `itemA.get( 'foo' ) - itemB.get( 'foo' )` can be used instead of series of `if`.
+
+              Example
+
+              ```javascript
+              var ToDoList = Ember.Object.extend({
+                // using standard ascending sort
+                todosSorting: ['name'],
+                sortedTodos: Ember.computed.sort('todos', 'todosSorting'),
+
+                // using descending sort
+                todosSortingDesc: ['name:desc'],
+                sortedTodosDesc: Ember.computed.sort('todos', 'todosSortingDesc'),
+
+                // using a custom sort function
+                priorityTodos: Ember.computed.sort('todos', function(a, b){
+                  if (a.priority &gt; b.priority) {
+                    return 1;
+                  } else if (a.priority &lt; b.priority) {
+                    return -1;
+                  }
+
+                  return 0;
+                })
+              });
+
+              var todoList = ToDoList.create({todos: [
+                { name: 'Unit Test', priority: 2 },
+                { name: 'Documentation', priority: 3 },
+                { name: 'Release', priority: 1 }
+              ]});
+
+              todoList.get('sortedTodos');      // [{ name:'Documentation', priority:3 }, { name:'Release', priority:1 }, { name:'Unit Test', priority:2 }]
+              todoList.get('sortedTodosDesc');  // [{ name:'Unit Test', priority:2 }, { name:'Release', priority:1 }, { name:'Documentation', priority:3 }]
+              todoList.get('priorityTodos');    // [{ name:'Release', priority:1 }, { name:'Unit Test', priority:2 }, { name:'Documentation', priority:3 }]
+              ```
+
+              @method computed.sort
+              @for Ember
+              @param {String} dependentKey
+              @param {String or Function} sortDefinition a dependent key to an
+              array of sort properties (add `:desc` to the arrays sort properties to sort descending) or a function to use when sorting
+              @return {Ember.ComputedProperty} computes a new sorted array based
+              on the sort property array or callback function
+            */
+        function sort(itemsKey, sortDefinition) {
+            Ember.assert(&quot;Ember.computed.sort requires two arguments: an array key to sort and either a sort properties key or sort function&quot;, arguments.length === 2);
+
+            var initFn, sortPropertiesKey;
+
+            if (typeof sortDefinition === 'function') {
+                initFn = function (array, changeMeta, instanceMeta) {
+                    instanceMeta.order = sortDefinition;
+                    instanceMeta.binarySearch = binarySearch;
+                };
+            } else {
+                sortPropertiesKey = sortDefinition;
+                initFn = function (array, changeMeta, instanceMeta) {
+                    function setupSortProperties() {
+                        var sortPropertyDefinitions = get(this, sortPropertiesKey),
+                        sortProperty,
+                        sortProperties = instanceMeta.sortProperties = [],
+                        sortPropertyAscending = instanceMeta.sortPropertyAscending = {},
+                        idx,
+                        asc;
+
+                        Ember.assert(&quot;Cannot sort: '&quot; + sortPropertiesKey + &quot;' is not an array.&quot;, isArray(sortPropertyDefinitions));
+
+                        changeMeta.property.clearItemPropertyKeys(itemsKey);
+
+                        forEach(sortPropertyDefinitions, function (sortPropertyDefinition) {
+                            if ((idx = sortPropertyDefinition.indexOf(':')) !== -1) {
+                                sortProperty = sortPropertyDefinition.substring(0, idx);
+                                asc = sortPropertyDefinition.substring(idx + 1).toLowerCase() !== 'desc';
+                            } else {
+                                sortProperty = sortPropertyDefinition;
+                                asc = true;
+                            }
+
+                            sortProperties.push(sortProperty);
+                            sortPropertyAscending[sortProperty] = asc;
+                            changeMeta.property.itemPropertyKey(itemsKey, sortProperty);
+                        });
+
+                        sortPropertyDefinitions.addObserver('@each', this, updateSortPropertiesOnce);
+                    }
+
+                    function updateSortPropertiesOnce() {
+                        run.once(this, updateSortProperties, changeMeta.propertyName);
+                    }
+
+                    function updateSortProperties(propertyName) {
+                        setupSortProperties.call(this);
+                        changeMeta.property.recomputeOnce.call(this, propertyName);
+                    }
+
+                    addObserver(this, sortPropertiesKey, updateSortPropertiesOnce);
+
+                    setupSortProperties.call(this);
+
+
+                    instanceMeta.order = function (itemA, itemB) {
+                        var isProxy = itemB instanceof SearchProxy,
+                        sortProperty, result, asc;
+
+                        for (var i = 0; i &lt; this.sortProperties.length; ++i) {
+                            sortProperty = this.sortProperties[i];
+                            result = compare(get(itemA, sortProperty), isProxy ? itemB[sortProperty] : get(itemB, sortProperty));
+
+                            if (result !== 0) {
+                                asc = this.sortPropertyAscending[sortProperty];
+                                return asc ? result : (-1 * result);
+                            }
+                        }
+
+                        return 0;
+                    };
+
+                    instanceMeta.binarySearch = binarySearch;
+                };
+            }
+
+            return arrayComputed(itemsKey, {
+                initialize: initFn,
+
+                addedItem: function (array, item, changeMeta, instanceMeta) {
+                    var index = instanceMeta.binarySearch(array, item);
+                    array.insertAt(index, item);
+                    return array;
+                },
+
+                removedItem: function (array, item, changeMeta, instanceMeta) {
+                    var proxyProperties, index, searchItem;
+
+                    if (changeMeta.previousValues) {
+                        proxyProperties = merge({
+                            content: item 
+                        }, changeMeta.previousValues);
+
+                        searchItem = SearchProxy.create(proxyProperties);
+                    } else {
+                        searchItem = item;
+                    }
+
+                    index = instanceMeta.binarySearch(array, searchItem);
+                    array.removeAt(index);
+                    return array;
+                }
+            });
+        }
+
+        __exports__.sort = sort;
+    });
+    define(&quot;ember-runtime/controllers/array_controller&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/system/array_proxy&quot;, &quot;ember-runtime/mixins/sortable&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var forEach = __dependency4__.forEach;
+        var replace = __dependency4__.replace;
+        var ArrayProxy = __dependency5__[&quot;default&quot;];
+        var SortableMixin = __dependency6__[&quot;default&quot;];
+        var ControllerMixin = __dependency7__[&quot;default&quot;];
+        var computed = __dependency8__.computed;
+        var EmberError = __dependency9__[&quot;default&quot;];
+
+
+        /**
+              `Ember.ArrayController` provides a way for you to publish a collection of
+              objects so that you can easily bind to the collection from a Handlebars
+              `#each` helper, an `Ember.CollectionView`, or other controllers.
+
+              The advantage of using an `ArrayController` is that you only have to set up
+              your view bindings once; to change what's displayed, simply swap out the
+              `model` property on the controller.
+
+              For example, imagine you wanted to display a list of items fetched via an XHR
+              request. Create an `Ember.ArrayController` and set its `model` property:
+
+              ```javascript
+              MyApp.listController = Ember.ArrayController.create();
+
+              $.get('people.json', function(data) {
+                MyApp.listController.set('model', data);
+              });
+              ```
+
+              Then, create a view that binds to your new controller:
+
+              ```handlebars
+              {{#each MyApp.listController}}
+                {{firstName}} {{lastName}}
+              {{/each}}
+              ```
+
+              Although you are binding to the controller, the behavior of this controller
+              is to pass through any methods or properties to the underlying array. This
+              capability comes from `Ember.ArrayProxy`, which this class inherits from.
+
+              Sometimes you want to display computed properties within the body of an
+              `#each` helper that depend on the underlying items in `model`, but are not
+              present on those items.   To do this, set `itemController` to the name of a
+              controller (probably an `ObjectController`) that will wrap each individual item.
+
+              For example:
+
+              ```handlebars
+                {{#each post in controller}}
+                  &lt;li&gt;{{post.title}} ({{post.titleLength}} characters)&lt;/li&gt;
+                {{/each}}
+              ```
+
+              ```javascript
+              App.PostsController = Ember.ArrayController.extend({
+                itemController: 'post'
+              });
+
+              App.PostController = Ember.ObjectController.extend({
+                // the `title` property will be proxied to the underlying post.
+
+                titleLength: function() {
+                  return this.get('title').length;
+                }.property('title')
+              });
+              ```
+
+              In some cases it is helpful to return a different `itemController` depending
+              on the particular item.  Subclasses can do this by overriding
+              `lookupItemController`.
+
+              For example:
+
+              ```javascript
+              App.MyArrayController = Ember.ArrayController.extend({
+                lookupItemController: function( object ) {
+                  if (object.get('isSpecial')) {
+                    return &quot;special&quot;; // use App.SpecialController
+                  } else {
+                    return &quot;regular&quot;; // use App.RegularController
+                  }
+                }
+              });
+              ```
+
+              The itemController instances will have a `parentController` property set to
+              the `ArrayController` instance.
+
+              @class ArrayController
+              @namespace Ember
+              @extends Ember.ArrayProxy
+              @uses Ember.SortableMixin
+              @uses Ember.ControllerMixin
+            */
+
+        __exports__[&quot;default&quot;] = ArrayProxy.extend(ControllerMixin, SortableMixin, {
+
+            /**
+                    The controller used to wrap items, if any.
+
+                    @property itemController
+                    @type String
+                    @default null
+                  */
+            itemController: null,
+
+            /**
+                    Return the name of the controller to wrap items, or `null` if items should
+                    be returned directly.  The default implementation simply returns the
+                    `itemController` property, but subclasses can override this method to return
+                    different controllers for different objects.
+
+                    For example:
+
+                    ```javascript
+                    App.MyArrayController = Ember.ArrayController.extend({
+                      lookupItemController: function( object ) {
+                        if (object.get('isSpecial')) {
+                          return &quot;special&quot;; // use App.SpecialController
+                        } else {
+                          return &quot;regular&quot;; // use App.RegularController
+                        }
+                      }
+                    });
+                    ```
+
+                    @method lookupItemController
+                    @param {Object} object
+                    @return {String}
+                  */
+            lookupItemController: function(object) {
+                return get(this, 'itemController');
+            },
+
+            objectAtContent: function(idx) {
+                var length = get(this, 'length');
+                var arrangedContent = get(this, 'arrangedContent');
+                var object = arrangedContent &amp;&amp; arrangedContent.objectAt(idx);
+                var controllerClass;
+
+                if (idx &gt;= 0 &amp;&amp; idx &lt; length) {
+                    controllerClass = this.lookupItemController(object);
+                    if (controllerClass) {
+                        return this.controllerAt(idx, object, controllerClass);
+                    }
+                }
+
+                // When `controllerClass` is falsy, we have not opted in to using item
+                // controllers, so return the object directly.
+
+                // When the index is out of range, we want to return the &quot;out of range&quot;
+                // value, whatever that might be.  Rather than make assumptions
+                // (e.g. guessing `null` or `undefined`) we defer this to `arrangedContent`.
+                return object;
+            },
+
+            arrangedContentDidChange: function() {
+                this._super();
+                this._resetSubControllers();
+            },
+
+            arrayContentDidChange: function(idx, removedCnt, addedCnt) {
+                var subControllers = this._subControllers;
+
+                if (subControllers.length) {
+                    var subControllersToRemove = subControllers.slice(idx, idx + removedCnt);
+
+                    forEach(subControllersToRemove, function(subController) {
+                        if (subController) {
+                            subController.destroy();
+                        }
+                    });
+
+                    replace(subControllers, idx, removedCnt, new Array(addedCnt));
+                }
+
+                // The shadow array of subcontrollers must be updated before we trigger
+                // observers, otherwise observers will get the wrong subcontainer when
+                // calling `objectAt`
+                this._super(idx, removedCnt, addedCnt);
+            },
+
+            init: function() {
+                this._super();
+                this._subControllers = [];
+            },
+
+            model: computed(function () {
+                return Ember.A();
+            }),
+
+            /**
+                   * Flag to mark as being &quot;virtual&quot;. Used to keep this instance
+                   * from participating in the parentController hierarchy.
+                   *
+                   * @private
+                   * @property _isVirtual
+                   * @type Boolean
+                   */
+            _isVirtual: false,
+
+            controllerAt: function(idx, object, controllerClass) {
+                var fullName, subController, parentController;
+
+                var container = get(this, 'container');
+                var subControllers = this._subControllers;
+
+                if (subControllers.length &gt; idx) {
+                    subController = subControllers[idx];
+
+                    if (subController) {
+                        return subController;
+                    }
+                }
+
+                fullName = 'controller:' + controllerClass;
+
+                if (!container.has(fullName)) {
+                    throw new EmberError('Could not resolve itemController: &quot;' + controllerClass + '&quot;');
+                }
+
+                if (this._isVirtual) {
+                    parentController = get(this, 'parentController');
+                } else {
+                    parentController = this;
+                }
+
+                subController = container.lookupFactory(fullName).create({
+                    target: parentController,
+                    parentController: parentController,
+                    model: object
+                });
+
+                subControllers[idx] = subController;
+
+                return subController;
+            },
+
+            _subControllers: null,
+
+            _resetSubControllers: function() {
+                var controller;
+                var subControllers = this._subControllers;
+
+                if (subControllers.length) {
+                    for (var i = 0, length = subControllers.length; length &gt; i; i++) {
+                        controller = subControllers[i];
+                        if (controller) {
+                            controller.destroy();
+                        }
+                    }
+
+                    subControllers.length = 0;
+                }
+            },
+
+            willDestroy: function() {
+                this._resetSubControllers();
+                this._super();
+            }
+        });
+    });
+    define(&quot;ember-runtime/controllers/controller&quot;,
+    [&quot;ember-runtime/system/object&quot;, &quot;ember-runtime/mixins/controller&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var EmberObject = __dependency1__[&quot;default&quot;];
+        var Mixin = __dependency2__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        /**
+              @class Controller
+              @namespace Ember
+              @extends Ember.Object
+              @uses Ember.ControllerMixin
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend(Mixin);
+    });
+    define(&quot;ember-runtime/controllers/object_controller&quot;,
+    [&quot;ember-runtime/mixins/controller&quot;, &quot;ember-runtime/system/object_proxy&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var ControllerMixin = __dependency1__[&quot;default&quot;];
+        var ObjectProxy = __dependency2__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        /**
+              `Ember.ObjectController` is part of Ember's Controller layer. It is intended
+              to wrap a single object, proxying unhandled attempts to `get` and `set` to the underlying
+              model object, and to forward unhandled action attempts to its `target`.
+
+              `Ember.ObjectController` derives this functionality from its superclass
+              `Ember.ObjectProxy` and the `Ember.ControllerMixin` mixin.
+
+              @class ObjectController
+              @namespace Ember
+              @extends Ember.ObjectProxy
+              @uses Ember.ControllerMixin
+            **/
+        __exports__[&quot;default&quot;] = ObjectProxy.extend(ControllerMixin);
+    });
+    define(&quot;ember-runtime/copy&quot;,
+    [&quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/mixins/copyable&quot;, &quot;ember-metal/platform&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var indexOf = __dependency1__.indexOf;
+        var typeOf = __dependency2__.typeOf;
+        var EmberObject = __dependency3__[&quot;default&quot;];
+        var Copyable = __dependency4__[&quot;default&quot;];
+        var create = __dependency5__.create;
+
+        function _copy(obj, deep, seen, copies) {
+            var ret, loc, key;
+
+            // primitive data types are immutable, just return them.
+            if ('object' !== typeof obj || obj === null) 
+                return obj;
+
+            // avoid cyclical loops
+            if (deep &amp;&amp; (loc = indexOf(seen, obj)) &gt;= 0) 
+                return copies[loc];
+
+            Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof EmberObject) || (Copyable &amp;&amp; Copyable.detect(obj)));
+
+            // IMPORTANT: this specific test will detect a native array only. Any other
+            // object will need to implement Copyable.
+            if (typeOf(obj) === 'array') {
+                ret = obj.slice();
+                if (deep) {
+                    loc = ret.length;
+                    while (--loc &gt;= 0) 
+                        ret[loc] = _copy(ret[loc], deep, seen, copies);
+                }
+            } else if (Copyable &amp;&amp; Copyable.detect(obj)) {
+                ret = obj.copy(deep, seen, copies);
+            } else if (obj instanceof Date) {
+                ret = new Date(obj.getTime());
+            } else {
+                ret = {};
+                for (key in obj) {
+                    if (!obj.hasOwnProperty(key)) 
+                        continue;
+
+                        // Prevents browsers that don't respect non-enumerability from
+                        // copying internal Ember properties
+                        if (key.substring(0, 2) === '__') 
+                            continue;
+
+                            ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key];
+                }
+            }
+
+            if (deep) {
+                seen.push(obj);
+                copies.push(ret);
+            }
+
+            return ret;
+        }
+
+        /**
+              Creates a clone of the passed object. This function can take just about
+              any type of object and create a clone of it, including primitive values
+              (which are not actually cloned because they are immutable).
+
+              If the passed object implements the `clone()` method, then this function
+              will simply call that method and return the result.
+
+              @method copy
+              @for Ember
+              @param {Object} obj The object to clone
+              @param {Boolean} deep If true, a deep copy of the object is made
+              @return {Object} The cloned object
+            */
+        __exports__[&quot;default&quot;] = function copy(obj, deep) {
+            // fast paths
+            if ('object' !== typeof obj || obj === null) 
+                return obj; // can't copy primitives
+            if (Copyable &amp;&amp; Copyable.detect(obj)) 
+                return obj.copy(deep);
+            return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
+        }
+    });
+    define(&quot;ember-runtime/core&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        /**
+              Compares two objects, returning true if they are logically equal. This is
+              a deeper comparison than a simple triple equal. For sets it will compare the
+              internal objects. For any other object that implements `isEqual()` it will
+              respect that method.
+
+              ```javascript
+              Ember.isEqual('hello', 'hello');  // true
+              Ember.isEqual(1, 2);              // false
+              Ember.isEqual([4, 2], [4, 2]);    // false
+              ```
+
+              @method isEqual
+              @for Ember
+              @param {Object} a first object to compare
+              @param {Object} b second object to compare
+              @return {Boolean}
+            */
+        var isEqual = function isEqual(a, b) {
+            if (a &amp;&amp; 'function' === typeof a.isEqual) 
+                return a.isEqual(b);
+            if (a instanceof Date &amp;&amp; b instanceof Date) {
+                return a.getTime() === b.getTime();
+            }
+            return a === b;
+        };
+        __exports__.isEqual = isEqual;
+    });
+    define(&quot;ember-runtime/ext/function&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/expand_properties&quot;, &quot;ember-metal/computed&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.EXTEND_PROTOTYPES, Ember.assert
+        var expandProperties = __dependency2__[&quot;default&quot;];
+        var computed = __dependency3__.computed;
+
+        var a_slice = Array.prototype.slice;
+        var FunctionPrototype = Function.prototype;
+
+        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
+
+            /**
+                    The `property` extension of Javascript's Function prototype is available
+                    when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
+                    `true`, which is the default.
+
+                    Computed properties allow you to treat a function like a property:
+
+                    ```javascript
+                    MyApp.President = Ember.Object.extend({
+                      firstName: '',
+                      lastName:  '',
+
+                      fullName: function() {
+                        return this.get('firstName') + ' ' + this.get('lastName');
+
+                        // Call this flag to mark the function as a property
+                      }.property()
+                    });
+
+                    var president = MyApp.President.create({
+                      firstName: &quot;Barack&quot;,
+                      lastName: &quot;Obama&quot;
+                    });
+
+                    president.get('fullName');    // &quot;Barack Obama&quot;
+                    ```
+
+                    Treating a function like a property is useful because they can work with
+                    bindings, just like any other property.
+
+                    Many computed properties have dependencies on other properties. For
+                    example, in the above example, the `fullName` property depends on
+                    `firstName` and `lastName` to determine its value. You can tell Ember
+                    about these dependencies like this:
+
+                    ```javascript
+                    MyApp.President = Ember.Object.extend({
+                      firstName: '',
+                      lastName:  '',
+
+                      fullName: function() {
+                        return this.get('firstName') + ' ' + this.get('lastName');
+
+                        // Tell Ember.js that this computed property depends on firstName
+                        // and lastName
+                      }.property('firstName', 'lastName')
+                    });
+                    ```
+
+                    Make sure you list these dependencies so Ember knows when to update
+                    bindings that connect to a computed property. Changing a dependency
+                    will not immediately trigger an update of the computed property, but
+                    will instead clear the cache so that it is updated when the next `get`
+                    is called on the property.
+
+                    See [Ember.ComputedProperty](/api/classes/Ember.ComputedProperty.html), [Ember.computed](/api/#method_computed).
+
+                    @method property
+                    @for Function
+                  */
+            FunctionPrototype.property = function() {
+                var ret = computed(this);
+                // ComputedProperty.prototype.property expands properties; no need for us to
+                // do so here.
+                return ret.property.apply(ret, arguments);
+            };
+
+            /**
+                    The `observes` extension of Javascript's Function prototype is available
+                    when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
+                    true, which is the default.
+
+                    You can observe property changes simply by adding the `observes`
+                    call to the end of your method declarations in classes that you write.
+                    For example:
+
+                    ```javascript
+                    Ember.Object.extend({
+                      valueObserver: function() {
+                        // Executes whenever the &quot;value&quot; property changes
+                      }.observes('value')
+                    });
+                    ```
+
+                    In the future this method may become asynchronous. If you want to ensure
+                    synchronous behavior, use `observesImmediately`.
+
+                    See `Ember.observer`.
+
+                    @method observes
+                    @for Function
+                  */
+            FunctionPrototype.observes = function() {
+                var addWatchedProperty = function (obs) {
+                    watched.push(obs);
+                };
+                var watched = [];
+
+                for (var i = 0; i &lt; arguments.length; ++i) {
+                    expandProperties(arguments[i], addWatchedProperty);
+                }
+
+                this.__ember_observes__ = watched;
+
+                return this;
+            };
+
+            /**
+                    The `observesImmediately` extension of Javascript's Function prototype is
+                    available when `Ember.EXTEND_PROTOTYPES` or
+                    `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
+
+                    You can observe property changes simply by adding the `observesImmediately`
+                    call to the end of your method declarations in classes that you write.
+                    For example:
+
+                    ```javascript
+                    Ember.Object.extend({
+                      valueObserver: function() {
+                        // Executes immediately after the &quot;value&quot; property changes
+                      }.observesImmediately('value')
+                    });
+                    ```
+
+                    In the future, `observes` may become asynchronous. In this event,
+                    `observesImmediately` will maintain the synchronous behavior.
+
+                    See `Ember.immediateObserver`.
+
+                    @method observesImmediately
+                    @for Function
+                  */
+            FunctionPrototype.observesImmediately = function() {
+                for (var i = 0, l = arguments.length; i &lt; l; i++) {
+                    var arg = arguments[i];
+                    Ember.assert(&quot;Immediate observers must observe internal properties only, not properties on other objects.&quot;, arg.indexOf('.') === -1);
+                }
+
+                // observes handles property expansion
+                return this.observes.apply(this, arguments);
+            };
+
+            /**
+                    The `observesBefore` extension of Javascript's Function prototype is
+                    available when `Ember.EXTEND_PROTOTYPES` or
+                    `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default.
+
+                    You can get notified when a property change is about to happen by
+                    by adding the `observesBefore` call to the end of your method
+                    declarations in classes that you write. For example:
+
+                    ```javascript
+                    Ember.Object.extend({
+                      valueObserver: function() {
+                        // Executes whenever the &quot;value&quot; property is about to change
+                      }.observesBefore('value')
+                    });
+                    ```
+
+                    See `Ember.beforeObserver`.
+
+                    @method observesBefore
+                    @for Function
+                  */
+            FunctionPrototype.observesBefore = function() {
+                var addWatchedProperty = function (obs) {
+                    watched.push(obs);
+                };
+                var watched = [];
+
+                for (var i = 0; i &lt; arguments.length; ++i) {
+                    expandProperties(arguments[i], addWatchedProperty);
+                }
+
+                this.__ember_observesBefore__ = watched;
+
+                return this;
+            };
+
+            /**
+                    The `on` extension of Javascript's Function prototype is available
+                    when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is
+                    true, which is the default.
+
+                    You can listen for events simply by adding the `on` call to the end of
+                    your method declarations in classes or mixins that you write. For example:
+
+                    ```javascript
+                    Ember.Mixin.create({
+                      doSomethingWithElement: function() {
+                        // Executes whenever the &quot;didInsertElement&quot; event fires
+                      }.on('didInsertElement')
+                    });
+                    ```
+
+                    See `Ember.on`.
+
+                    @method on
+                    @for Function
+                  */
+            FunctionPrototype.on = function() {
+                var events = a_slice.call(arguments);
+                this.__ember_listens__ = events;
+                return this;
+            };
+        }
+    });
+    define(&quot;ember-runtime/ext/rsvp&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/logger&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        /* globals RSVP:true */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var Logger = __dependency2__[&quot;default&quot;];
+
+        var RSVP = requireModule(&quot;rsvp&quot;);
+        var Test, testModuleName = 'ember-testing/test';
+
+        RSVP.onerrorDefault = function(error) {
+            if (error instanceof Error) {
+                if (Ember.testing) {
+                    // ES6TODO: remove when possible
+                    if (!Test &amp;&amp; Ember.__loader.registry[testModuleName]) {
+                        Test = requireModule(testModuleName)['default'];
+                    }
+
+                    if (Test &amp;&amp; Test.adapter) {
+                        Test.adapter.exception(error);
+                    } else {
+                        throw error;
+                    }
+                } else if (Ember.onerror) {
+                    Ember.onerror(error);
+                } else {
+                    Logger.error(error.stack);
+                    Ember.assert(error, false);
+                }
+            }
+        };
+
+        RSVP.on('error', RSVP.onerrorDefault);
+
+        __exports__[&quot;default&quot;] = RSVP;
+    });
+    define(&quot;ember-runtime/ext/string&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/system/string&quot;],
+    function(__dependency1__, __dependency2__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.EXTEND_PROTOTYPES, Ember.assert, Ember.FEATURES
+        var fmt = __dependency2__.fmt;
+        var w = __dependency2__.w;
+        var loc = __dependency2__.loc;
+        var camelize = __dependency2__.camelize;
+        var decamelize = __dependency2__.decamelize;
+        var dasherize = __dependency2__.dasherize;
+        var underscore = __dependency2__.underscore;
+        var capitalize = __dependency2__.capitalize;
+        var classify = __dependency2__.classify;
+
+        var StringPrototype = String.prototype;
+
+        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
+
+            /**
+                    See [Ember.String.fmt](/api/classes/Ember.String.html#method_fmt).
+
+                    @method fmt
+                    @for String
+                  */
+            StringPrototype.fmt = function() {
+                return fmt(this, arguments);
+            };
+
+            /**
+                    See [Ember.String.w](/api/classes/Ember.String.html#method_w).
+
+                    @method w
+                    @for String
+                  */
+            StringPrototype.w = function() {
+                return w(this);
+            };
+
+            /**
+                    See [Ember.String.loc](/api/classes/Ember.String.html#method_loc).
+
+                    @method loc
+                    @for String
+                  */
+            StringPrototype.loc = function() {
+                return loc(this, arguments);
+            };
+
+            /**
+                    See [Ember.String.camelize](/api/classes/Ember.String.html#method_camelize).
+
+                    @method camelize
+                    @for String
+                  */
+            StringPrototype.camelize = function() {
+                return camelize(this);
+            };
+
+            /**
+                    See [Ember.String.decamelize](/api/classes/Ember.String.html#method_decamelize).
+
+                    @method decamelize
+                    @for String
+                  */
+            StringPrototype.decamelize = function() {
+                return decamelize(this);
+            };
+
+            /**
+                    See [Ember.String.dasherize](/api/classes/Ember.String.html#method_dasherize).
+
+                    @method dasherize
+                    @for String
+                  */
+            StringPrototype.dasherize = function() {
+                return dasherize(this);
+            };
+
+            /**
+                    See [Ember.String.underscore](/api/classes/Ember.String.html#method_underscore).
+
+                    @method underscore
+                    @for String
+                  */
+            StringPrototype.underscore = function() {
+                return underscore(this);
+            };
+
+            /**
+                    See [Ember.String.classify](/api/classes/Ember.String.html#method_classify).
+
+                    @method classify
+                    @for String
+                  */
+            StringPrototype.classify = function() {
+                return classify(this);
+            };
+
+            /**
+                    See [Ember.String.capitalize](/api/classes/Ember.String.html#method_capitalize).
+
+                    @method capitalize
+                    @for String
+                  */
+            StringPrototype.capitalize = function() {
+                return capitalize(this);
+            };
+        }
+    });
+    define(&quot;ember-runtime/keys&quot;,
+    [&quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/platform&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var EnumerableUtils = __dependency1__[&quot;default&quot;];
+        var create = __dependency2__.create;
+
+        /**
+              Returns all of the keys defined on an object or hash. This is useful
+              when inspecting objects for debugging. On browsers that support it, this
+              uses the native `Object.keys` implementation.
+
+              @method keys
+              @for Ember
+              @param {Object} obj
+              @return {Array} Array containing keys of obj
+            */
+        var keys = Object.keys;
+        if (!keys || create.isSimulated) {
+            var prototypeProperties = [
+            'constructor',
+            'hasOwnProperty',
+            'isPrototypeOf',
+            'propertyIsEnumerable',
+            'valueOf',
+            'toLocaleString',
+            'toString'
+            ],
+            pushPropertyName = function(obj, array, key) {
+                // Prevents browsers that don't respect non-enumerability from
+                // copying internal Ember properties
+                if (key.substring(0, 2) === '__') 
+                    return;
+                if (key === '_super') 
+                    return;
+                if (EnumerableUtils.indexOf(array, key) &gt;= 0) 
+                    return;
+                if (typeof obj.hasOwnProperty === 'function' &amp;&amp; !obj.hasOwnProperty(key)) 
+                    return;
+
+                array.push(key);
+            };
+
+            keys = function keys(obj) {
+                var ret = [], key;
+                for (key in obj) {
+                    pushPropertyName(obj, ret, key);
+                }
+
+                // IE8 doesn't enumerate property that named the same as prototype properties.
+                for (var i = 0, l = prototypeProperties.length; i &lt; l; i++) {
+                    key = prototypeProperties[i];
+
+                    pushPropertyName(obj, ret, key);
+                }
+
+                return ret;
+            };
+        }
+
+        __exports__[&quot;default&quot;] = keys;
+    });
+    define(&quot;ember-runtime/mixins/action_handler&quot;,
+    [&quot;ember-metal/merge&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+        var merge = __dependency1__[&quot;default&quot;];
+        var Mixin = __dependency2__.Mixin;
+        var get = __dependency3__.get;
+        var typeOf = __dependency4__.typeOf;
+
+        /**
+              The `Ember.ActionHandler` mixin implements support for moving an `actions`
+              property to an `_actions` property at extend time, and adding `_actions`
+              to the object's mergedProperties list.
+
+              `Ember.ActionHandler` is available on some familiar classes including
+              `Ember.Route`, `Ember.View`, `Ember.Component`, and controllers such as
+              `Ember.Controller` and `Ember.ObjectController`.
+              (Internally the mixin is used by `Ember.CoreView`, `Ember.ControllerMixin`,
+              and `Ember.Route` and available to the above classes through
+              inheritance.)
+
+              @class ActionHandler
+              @namespace Ember
+            */
+        var ActionHandler = Mixin.create({
+            mergedProperties: ['_actions'],
+
+            /**
+                    The collection of functions, keyed by name, available on this
+                    `ActionHandler` as action targets.
+
+                    These functions will be invoked when a matching `{{action}}` is triggered
+                    from within a template and the application's current route is this route.
+
+                    Actions can also be invoked from other parts of your application
+                    via `ActionHandler#send`.
+
+                    The `actions` hash will inherit action handlers from
+                    the `actions` hash defined on extended parent classes
+                    or mixins rather than just replace the entire hash, e.g.:
+
+                    ```js
+                    App.CanDisplayBanner = Ember.Mixin.create({
+                      actions: {
+                        displayBanner: function(msg) {
+                          // ...
+                        }
+                      }
+                    });
+
+                    App.WelcomeRoute = Ember.Route.extend(App.CanDisplayBanner, {
+                      actions: {
+                        playMusic: function() {
+                          // ...
+                        }
+                      }
+                    });
+
+                    // `WelcomeRoute`, when active, will be able to respond
+                    // to both actions, since the actions hash is merged rather
+                    // then replaced when extending mixins / parent classes.
+                    this.send('displayBanner');
+                    this.send('playMusic');
+                    ```
+
+                    Within a Controller, Route, View or Component's action handler,
+                    the value of the `this` context is the Controller, Route, View or
+                    Component object:
+
+                    ```js
+                    App.SongRoute = Ember.Route.extend({
+                      actions: {
+                        myAction: function() {
+                          this.controllerFor(&quot;song&quot;);
+                          this.transitionTo(&quot;other.route&quot;);
+                          ...
+                        }
+                      }
+                    });
+                    ```
+
+                    It is also possible to call `this._super()` from within an
+                    action handler if it overrides a handler defined on a parent
+                    class or mixin:
+
+                    Take for example the following routes:
+
+                    ```js
+                    App.DebugRoute = Ember.Mixin.create({
+                      actions: {
+                        debugRouteInformation: function() {
+                          console.debug(&quot;trololo&quot;);
+                        }
+                      }
+                    });
+
+                    App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, {
+                      actions: {
+                        debugRouteInformation: function() {
+                          // also call the debugRouteInformation of mixed in App.DebugRoute
+                          this._super();
+
+                          // show additional annoyance
+                          window.alert(...);
+                        }
+                      }
+                    });
+                    ```
+
+                    ## Bubbling
+
+                    By default, an action will stop bubbling once a handler defined
+                    on the `actions` hash handles it. To continue bubbling the action,
+                    you must return `true` from the handler:
+
+                    ```js
+                    App.Router.map(function() {
+                      this.resource(&quot;album&quot;, function() {
+                        this.route(&quot;song&quot;);
+                      });
+                    });
+
+                    App.AlbumRoute = Ember.Route.extend({
+                      actions: {
+                        startPlaying: function() {
+                        }
+                      }
+                    });
+
+                    App.AlbumSongRoute = Ember.Route.extend({
+                      actions: {
+                        startPlaying: function() {
+                          // ...
+
+                          if (actionShouldAlsoBeTriggeredOnParentRoute) {
+                            return true;
+                          }
+                        }
+                      }
+                    });
+                    ```
+
+                    @property actions
+                    @type Hash
+                    @default null
+                  */
+
+            /**
+                    Moves `actions` to `_actions` at extend time. Note that this currently
+                    modifies the mixin themselves, which is technically dubious but
+                    is practically of little consequence. This may change in the future.
+
+                    @private
+                    @method willMergeMixin
+                  */
+            willMergeMixin: function(props) {
+                var hashName;
+
+                if (!props._actions) {
+                    Ember.assert(&quot;'actions' should not be a function&quot;, typeof(props.actions) !== 'function');
+
+                    if (typeOf(props.actions) === 'object') {
+                        hashName = 'actions';
+                    } else if (typeOf(props.events) === 'object') {
+                        Ember.deprecate('Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object', false);
+                        hashName = 'events';
+                    }
+
+                    if (hashName) {
+                        props._actions = merge(props._actions || {}, props[hashName]);
+                    }
+
+                    delete props[hashName];
+                }
+            },
+
+            /**
+                    Triggers a named action on the `ActionHandler`. Any parameters
+                    supplied after the `actionName` string will be passed as arguments
+                    to the action target function.
+
+                    If the `ActionHandler` has its `target` property set, actions may
+                    bubble to the `target`. Bubbling happens when an `actionName` can
+                    not be found in the `ActionHandler`'s `actions` hash or if the
+                    action target function returns `true`.
+
+                    Example
+
+                    ```js
+                    App.WelcomeRoute = Ember.Route.extend({
+                      actions: {
+                        playTheme: function() {
+                           this.send('playMusic', 'theme.mp3');
+                        },
+                        playMusic: function(track) {
+                          // ...
+                        }
+                      }
+                    });
+                    ```
+
+                    @method send
+                    @param {String} actionName The action to trigger
+                    @param {*} context a context to send with the action
+                  */
+            send: function(actionName) {
+                var args = [].slice.call(arguments, 1), target;
+
+                if (this._actions &amp;&amp; this._actions[actionName]) {
+                    if (this._actions[actionName].apply(this, args) === true) {
+                        // handler returned true, so this action will bubble
+                    } else {
+                        return;
+                    }
+                } else if (!Ember.FEATURES.isEnabled('ember-routing-drop-deprecated-action-style') &amp;&amp; this.deprecatedSend &amp;&amp; this.deprecatedSendHandles &amp;&amp; this.deprecatedSendHandles(actionName)) {
+                    Ember.warn(&quot;The current default is deprecated but will prefer to handle actions directly on the controller instead of a similarly named action in the actions hash. To turn off this deprecated feature set: Ember.FEATURES['ember-routing-drop-deprecated-action-style'] = true&quot;);
+                    if (this.deprecatedSend.apply(this, [].slice.call(arguments)) === true) {
+                        // handler return true, so this action will bubble
+                    } else {
+                        return;
+                    }
+                }
+
+                if (target = get(this, 'target')) {
+                    Ember.assert(&quot;The `target` for &quot; + this + &quot; (&quot; + target + &quot;) does not have a `send` method&quot;, typeof target.send === 'function');
+                    target.send.apply(target, arguments);
+                }
+            }
+        });
+
+        __exports__[&quot;default&quot;] = ActionHandler;
+    });
+    define(&quot;ember-runtime/mixins/array&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-runtime/mixins/enumerable&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/events&quot;, &quot;ember-metal/watching&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        // ..........................................................
+        // HELPERS
+        //
+        var Ember = __dependency1__[&quot;default&quot;];
+        // ES6TODO: Ember.A
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var computed = __dependency4__.computed;
+        var cacheFor = __dependency4__.cacheFor;
+        var isNone = __dependency5__.isNone;
+        var none = __dependency5__.none;
+        var Enumerable = __dependency6__[&quot;default&quot;];
+        var map = __dependency7__.map;
+        var Mixin = __dependency8__.Mixin;
+        var required = __dependency8__.required;
+        var propertyWillChange = __dependency9__.propertyWillChange;
+        var propertyDidChange = __dependency9__.propertyDidChange;
+        var addListener = __dependency10__.addListener;
+        var removeListener = __dependency10__.removeListener;
+        var sendEvent = __dependency10__.sendEvent;
+        var hasListeners = __dependency10__.hasListeners;
+        var isWatching = __dependency11__.isWatching;
+
+        // ..........................................................
+        // ARRAY
+        //
+        /**
+              This mixin implements Observer-friendly Array-like behavior. It is not a
+              concrete implementation, but it can be used up by other classes that want
+              to appear like arrays.
+
+              For example, ArrayProxy and ArrayController are both concrete classes that can
+              be instantiated to implement array-like behavior. Both of these classes use
+              the Array Mixin by way of the MutableArray mixin, which allows observable
+              changes to be made to the underlying array.
+
+              Unlike `Ember.Enumerable,` this mixin defines methods specifically for
+              collections that provide index-ordered access to their contents. When you
+              are designing code that needs to accept any kind of Array-like object, you
+              should use these methods instead of Array primitives because these will
+              properly notify observers of changes to the array.
+
+              Although these methods are efficient, they do add a layer of indirection to
+              your application so it is a good idea to use them only when you need the
+              flexibility of using both true JavaScript arrays and &quot;virtual&quot; arrays such
+              as controllers and collections.
+
+              You can use the methods defined in this module to access and modify array
+              contents in a KVO-friendly way. You can also be notified whenever the
+              membership of an array changes by using `.observes('myArray.[]')`.
+
+              To support `Ember.Array` in your own class, you must override two
+              primitives to use it: `replace()` and `objectAt()`.
+
+              Note that the Ember.Array mixin also incorporates the `Ember.Enumerable`
+              mixin. All `Ember.Array`-like objects are also enumerable.
+
+              @class Array
+              @namespace Ember
+              @uses Ember.Enumerable
+              @since Ember 0.9.0
+            */
+        __exports__[&quot;default&quot;] = Mixin.create(Enumerable, {
+
+            /**
+                    Your array must support the `length` property. Your replace methods should
+                    set this property whenever it changes.
+
+                    @property {Number} length
+                  */
+            length: required(),
+
+            /**
+                    Returns the object at the given `index`. If the given `index` is negative
+                    or is greater or equal than the array length, returns `undefined`.
+
+                    This is one of the primitives you must implement to support `Ember.Array`.
+                    If your object supports retrieving the value of an array item using `get()`
+                    (i.e. `myArray.get(0)`), then you do not need to implement this method
+                    yourself.
+
+                    ```javascript
+                    var arr = ['a', 'b', 'c', 'd'];
+                    arr.objectAt(0);   // &quot;a&quot;
+                    arr.objectAt(3);   // &quot;d&quot;
+                    arr.objectAt(-1);  // undefined
+                    arr.objectAt(4);   // undefined
+                    arr.objectAt(5);   // undefined
+                    ```
+
+                    @method objectAt
+                    @param {Number} idx The index of the item to return.
+                    @return {*} item at index or undefined
+                  */
+            objectAt: function(idx) {
+                if ((idx &lt; 0) || (idx &gt;= get(this, 'length'))) 
+                    return undefined;
+                return get(this, idx);
+            },
+
+            /**
+                    This returns the objects at the specified indexes, using `objectAt`.
+
+                    ```javascript
+                    var arr = ['a', 'b', 'c', 'd'];
+                    arr.objectsAt([0, 1, 2]);  // [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]
+                    arr.objectsAt([2, 3, 4]);  // [&quot;c&quot;, &quot;d&quot;, undefined]
+                    ```
+
+                    @method objectsAt
+                    @param {Array} indexes An array of indexes of items to return.
+                    @return {Array}
+                   */
+            objectsAt: function(indexes) {
+                var self = this;
+                return map(indexes, function(idx) {
+                    return self.objectAt(idx);
+                });
+            },
+
+            // overrides Ember.Enumerable version
+            nextObject: function(idx) {
+                return this.objectAt(idx);
+            },
+
+            /**
+                    This is the handler for the special array content property. If you get
+                    this property, it will return this. If you set this property to a new
+                    array, it will replace the current content.
+
+                    This property overrides the default property defined in `Ember.Enumerable`.
+
+                    @property []
+                    @return this
+                  */
+            '[]': computed(function(key, value) {
+                if (value !== undefined) 
+                    this.replace(0, get(this, 'length'), value) ;
+                return this ;
+            }),
+
+            firstObject: computed(function() {
+                return this.objectAt(0);
+            }),
+
+            lastObject: computed(function() {
+                return this.objectAt(get(this, 'length')-1);
+            }),
+
+            // optimized version from Enumerable
+            contains: function(obj) {
+                return this.indexOf(obj) &gt;= 0;
+            },
+
+            // Add any extra methods to Ember.Array that are native to the built-in Array.
+            /**
+                    Returns a new array that is a slice of the receiver. This implementation
+                    uses the observable array methods to retrieve the objects for the new
+                    slice.
+
+                    ```javascript
+                    var arr = ['red', 'green', 'blue'];
+                    arr.slice(0);       // ['red', 'green', 'blue']
+                    arr.slice(0, 2);    // ['red', 'green']
+                    arr.slice(1, 100);  // ['green', 'blue']
+                    ```
+
+                    @method slice
+                    @param {Integer} beginIndex (Optional) index to begin slicing from.
+                    @param {Integer} endIndex (Optional) index to end the slice at (but not included).
+                    @return {Array} New array with specified slice
+                  */
+            slice: function(beginIndex, endIndex) {
+                var ret = Ember.A();
+                var length = get(this, 'length') ;
+                if (isNone(beginIndex)) 
+                    beginIndex = 0 ;
+                if (isNone(endIndex) || (endIndex &gt; length)) 
+                    endIndex = length ;
+
+                if (beginIndex &lt; 0) 
+                    beginIndex = length + beginIndex;
+                if (endIndex &lt; 0) 
+                    endIndex = length + endIndex;
+
+                while (beginIndex &lt; endIndex) {
+                    ret[ret.length] = this.objectAt(beginIndex++) ;
+                }
+                return ret ;
+            },
+
+            /**
+                    Returns the index of the given object's first occurrence.
+                    If no `startAt` argument is given, the starting location to
+                    search is 0. If it's negative, will count backward from
+                    the end of the array. Returns -1 if no match is found.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;a&quot;];
+                    arr.indexOf(&quot;a&quot;);       //  0
+                    arr.indexOf(&quot;z&quot;);       // -1
+                    arr.indexOf(&quot;a&quot;, 2);    //  4
+                    arr.indexOf(&quot;a&quot;, -1);   //  4
+                    arr.indexOf(&quot;b&quot;, 3);    // -1
+                    arr.indexOf(&quot;a&quot;, 100);  // -1
+                    ```
+
+                    @method indexOf
+                    @param {Object} object the item to search for
+                    @param {Number} startAt optional starting location to search, default 0
+                    @return {Number} index or -1 if not found
+                  */
+            indexOf: function(object, startAt) {
+                var idx, len = get(this, 'length');
+
+                if (startAt === undefined) 
+                    startAt = 0;
+                if (startAt &lt; 0) 
+                    startAt += len;
+
+                for (idx = startAt; idx &lt; len; idx++) {
+                    if (this.objectAt(idx) === object) 
+                        return idx;
+                }
+                return -1;
+            },
+
+            /**
+                    Returns the index of the given object's last occurrence.
+                    If no `startAt` argument is given, the search starts from
+                    the last position. If it's negative, will count backward
+                    from the end of the array. Returns -1 if no match is found.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;a&quot;];
+                    arr.lastIndexOf(&quot;a&quot;);       //  4
+                    arr.lastIndexOf(&quot;z&quot;);       // -1
+                    arr.lastIndexOf(&quot;a&quot;, 2);    //  0
+                    arr.lastIndexOf(&quot;a&quot;, -1);   //  4
+                    arr.lastIndexOf(&quot;b&quot;, 3);    //  1
+                    arr.lastIndexOf(&quot;a&quot;, 100);  //  4
+                    ```
+
+                    @method lastIndexOf
+                    @param {Object} object the item to search for
+                    @param {Number} startAt optional starting location to search, default 0
+                    @return {Number} index or -1 if not found
+                  */
+            lastIndexOf: function(object, startAt) {
+                var idx, len = get(this, 'length');
+
+                if (startAt === undefined || startAt &gt;= len) 
+                    startAt = len-1;
+                if (startAt &lt; 0) 
+                    startAt += len;
+
+                for (idx = startAt; idx &gt;= 0; idx--) {
+                    if (this.objectAt(idx) === object) 
+                        return idx;
+                }
+                return -1;
+            },
+
+            // ..........................................................
+            // ARRAY OBSERVERS
+            //
+
+            /**
+                    Adds an array observer to the receiving array. The array observer object
+                    normally must implement two methods:
+
+                    * `arrayWillChange(observedObj, start, removeCount, addCount)` - This method will be
+                      called just before the array is modified.
+                    * `arrayDidChange(observedObj, start, removeCount, addCount)` - This method will be
+                      called just after the array is modified.
+
+                    Both callbacks will be passed the observed object, starting index of the
+                    change as well a a count of the items to be removed and added. You can use
+                    these callbacks to optionally inspect the array during the change, clear
+                    caches, or do any other bookkeeping necessary.
+
+                    In addition to passing a target, you can also include an options hash
+                    which you can use to override the method names that will be invoked on the
+                    target.
+
+                    @method addArrayObserver
+                    @param {Object} target The observer object.
+                    @param {Hash} opts Optional hash of configuration options including
+                      `willChange` and `didChange` option.
+                    @return {Ember.Array} receiver
+                  */
+            addArrayObserver: function(target, opts) {
+                var willChange = (opts &amp;&amp; opts.willChange) || 'arrayWillChange',
+                didChange = (opts &amp;&amp; opts.didChange) || 'arrayDidChange';
+
+                var hasObservers = get(this, 'hasArrayObservers');
+                if (!hasObservers) 
+                    propertyWillChange(this, 'hasArrayObservers');
+                addListener(this, '@array:before', target, willChange);
+                addListener(this, '@array:change', target, didChange);
+                if (!hasObservers) 
+                    propertyDidChange(this, 'hasArrayObservers');
+                return this;
+            },
+
+            /**
+                    Removes an array observer from the object if the observer is current
+                    registered. Calling this method multiple times with the same object will
+                    have no effect.
+
+                    @method removeArrayObserver
+                    @param {Object} target The object observing the array.
+                    @param {Hash} opts Optional hash of configuration options including
+                      `willChange` and `didChange` option.
+                    @return {Ember.Array} receiver
+                  */
+            removeArrayObserver: function(target, opts) {
+                var willChange = (opts &amp;&amp; opts.willChange) || 'arrayWillChange',
+                didChange = (opts &amp;&amp; opts.didChange) || 'arrayDidChange';
+
+                var hasObservers = get(this, 'hasArrayObservers');
+                if (hasObservers) 
+                    propertyWillChange(this, 'hasArrayObservers');
+                removeListener(this, '@array:before', target, willChange);
+                removeListener(this, '@array:change', target, didChange);
+                if (hasObservers) 
+                    propertyDidChange(this, 'hasArrayObservers');
+                return this;
+            },
+
+            /**
+                    Becomes true whenever the array currently has observers watching changes
+                    on the array.
+
+                    @property {Boolean} hasArrayObservers
+                  */
+            hasArrayObservers: computed(function() {
+                return hasListeners(this, '@array:change') || hasListeners(this, '@array:before');
+            }),
+
+            /**
+                    If you are implementing an object that supports `Ember.Array`, call this
+                    method just before the array content changes to notify any observers and
+                    invalidate any related properties. Pass the starting index of the change
+                    as well as a delta of the amounts to change.
+
+                    @method arrayContentWillChange
+                    @param {Number} startIdx The starting index in the array that will change.
+                    @param {Number} removeAmt The number of items that will be removed. If you
+                      pass `null` assumes 0
+                    @param {Number} addAmt The number of items that will be added. If you
+                      pass `null` assumes 0.
+                    @return {Ember.Array} receiver
+                  */
+            arrayContentWillChange: function(startIdx, removeAmt, addAmt) {
+
+                // if no args are passed assume everything changes
+                if (startIdx === undefined) {
+                    startIdx = 0;
+                    removeAmt = addAmt = -1;
+                } else {
+                    if (removeAmt === undefined) 
+                        removeAmt =- 1;
+                    if (addAmt === undefined) 
+                        addAmt =- 1;
+                }
+
+                // Make sure the @each proxy is set up if anyone is observing @each
+                if (isWatching(this, '@each')) {
+                    get(this, '@each');
+                }
+
+                sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);
+
+                var removing, lim;
+                if (startIdx &gt;= 0 &amp;&amp; removeAmt &gt;= 0 &amp;&amp; get(this, 'hasEnumerableObservers')) {
+                    removing = [];
+                    lim = startIdx + removeAmt;
+                    for (var idx = startIdx; idx &lt; lim; idx++) 
+                        removing.push(this.objectAt(idx));
+                } else {
+                    removing = removeAmt;
+                }
+
+                this.enumerableContentWillChange(removing, addAmt);
+
+                return this;
+            },
+
+            /**
+                    If you are implementing an object that supports `Ember.Array`, call this
+                    method just after the array content changes to notify any observers and
+                    invalidate any related properties. Pass the starting index of the change
+                    as well as a delta of the amounts to change.
+
+                    @method arrayContentDidChange
+                    @param {Number} startIdx The starting index in the array that did change.
+                    @param {Number} removeAmt The number of items that were removed. If you
+                      pass `null` assumes 0
+                    @param {Number} addAmt The number of items that were added. If you
+                      pass `null` assumes 0.
+                    @return {Ember.Array} receiver
+                  */
+            arrayContentDidChange: function(startIdx, removeAmt, addAmt) {
+
+                // if no args are passed assume everything changes
+                if (startIdx === undefined) {
+                    startIdx = 0;
+                    removeAmt = addAmt = -1;
+                } else {
+                    if (removeAmt === undefined) 
+                        removeAmt =- 1;
+                    if (addAmt === undefined) 
+                        addAmt =- 1;
+                }
+
+                var adding, lim;
+                if (startIdx &gt;= 0 &amp;&amp; addAmt &gt;= 0 &amp;&amp; get(this, 'hasEnumerableObservers')) {
+                    adding = [];
+                    lim = startIdx + addAmt;
+                    for (var idx = startIdx; idx &lt; lim; idx++) 
+                        adding.push(this.objectAt(idx));
+                } else {
+                    adding = addAmt;
+                }
+
+                this.enumerableContentDidChange(removeAmt, adding);
+                sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);
+
+                var length = get(this, 'length'),
+                cachedFirst = cacheFor(this, 'firstObject'),
+                cachedLast = cacheFor(this, 'lastObject');
+                if (this.objectAt(0) !== cachedFirst) {
+                    propertyWillChange(this, 'firstObject');
+                    propertyDidChange(this, 'firstObject');
+                }
+                if (this.objectAt(length-1) !== cachedLast) {
+                    propertyWillChange(this, 'lastObject');
+                    propertyDidChange(this, 'lastObject');
+                }
+
+                return this;
+            },
+
+            // ..........................................................
+            // ENUMERATED PROPERTIES
+            //
+
+            /**
+                    Returns a special object that can be used to observe individual properties
+                    on the array. Just get an equivalent property on this object and it will
+                    return an enumerable that maps automatically to the named key on the
+                    member objects.
+
+                    If you merely want to watch for any items being added or removed to the array,
+                    use the `[]` property instead of `@each`.
+
+                    @property @each
+                  */
+            '@each': computed(function() {
+                if (!this.__each) {
+                    // ES6TODO: GRRRRR
+                    var EachProxy = requireModule('ember-runtime/system/each_proxy')['EachProxy'];
+
+                    this.__each = new EachProxy(this);
+                }
+
+                return this.__each;
+            })
+        });
+    });
+    define(&quot;ember-runtime/mixins/comparable&quot;,
+    [&quot;ember-metal/mixin&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var Mixin = __dependency1__.Mixin;
+        var required = __dependency1__.required;
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        /**
+              Implements some standard methods for comparing objects. Add this mixin to
+              any class you create that can compare its instances.
+
+              You should implement the `compare()` method.
+
+              @class Comparable
+              @namespace Ember
+              @since Ember 0.9
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+
+            /**
+                    Override to return the result of the comparison of the two parameters. The
+                    compare method should return:
+
+                    - `-1` if `a &lt; b`
+                    - `0` if `a == b`
+                    - `1` if `a &gt; b`
+
+                    Default implementation raises an exception.
+
+                    @method compare
+                    @param a {Object} the first object to compare
+                    @param b {Object} the second object to compare
+                    @return {Integer} the result of the comparison
+                  */
+            compare: required(Function)
+        });
+    });
+    define(&quot;ember-runtime/mixins/controller&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/computed&quot;, &quot;ember-runtime/mixins/action_handler&quot;, &quot;ember-runtime/mixins/controller_content_model_alias_deprecation&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert, Ember.deprecate
+        var get = __dependency2__.get;
+        var EmberObject = __dependency3__[&quot;default&quot;];
+        var Mixin = __dependency4__.Mixin;
+        var computed = __dependency5__.computed;
+        var ActionHandler = __dependency6__[&quot;default&quot;];
+        var ControllerContentModelAliasDeprecation = __dependency7__[&quot;default&quot;];
+
+        /**
+              `Ember.ControllerMixin` provides a standard interface for all classes that
+              compose Ember's controller layer: `Ember.Controller`,
+              `Ember.ArrayController`, and `Ember.ObjectController`.
+
+              @class ControllerMixin
+              @namespace Ember
+              @uses Ember.ActionHandler
+            */
+        __exports__[&quot;default&quot;] = Mixin.create(ActionHandler, ControllerContentModelAliasDeprecation, {
+            /* ducktype as a controller */
+            isController: true,
+
+            /**
+                    The object to which actions from the view should be sent.
+
+                    For example, when a Handlebars template uses the `{{action}}` helper,
+                    it will attempt to send the action to the view's controller's `target`.
+
+                    By default, the value of the target property is set to the router, and
+                    is injected when a controller is instantiated. This injection is defined
+                    in Ember.Application#buildContainer, and is applied as part of the
+                    applications initialization process. It can also be set after a controller
+                    has been instantiated, for instance when using the render helper in a
+                    template, or when a controller is used as an `itemController`. In most
+                    cases the `target` property will automatically be set to the logical
+                    consumer of actions for the controller.
+
+                    @property target
+                    @default null
+                  */
+            target: null,
+
+            container: null,
+
+            parentController: null,
+
+            store: null,
+
+            model: null,
+            content: computed.alias('model'),
+
+            deprecatedSendHandles: function(actionName) {
+                return !!this[actionName];
+            },
+
+            deprecatedSend: function(actionName) {
+                var args = [].slice.call(arguments, 1);
+                Ember.assert('' + this + &quot; has the action &quot; + actionName + &quot; but it is not a function&quot;, typeof this[actionName] === 'function');
+                Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object ( action: `' + actionName + '` on ' + this + ')', false);
+                this[actionName].apply(this, args);
+                return;
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/controller_content_model_alias_deprecation&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/mixin&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.deprecate
+        var get = __dependency2__.get;
+        var Mixin = __dependency3__.Mixin;
+
+        /**
+              The ControllerContentModelAliasDeprecation mixin is used to provide a useful
+              deprecation warning when specifying `content` directly on a `Ember.Controller`
+              (without also specifying `model`).
+
+              Ember versions prior to 1.7 used `model` as an alias of `content`, but due to
+              much confusion this alias was reversed (so `content` is now an alias of `model).
+
+              This change reduces many caveats with model/content, and also sets a
+              simple ground rule: Never set a controllers content, rather always set
+              it's model and ember will do the right thing.
+
+
+              `Ember.ControllerContentModelAliasDeprecation` is used internally by Ember in
+              `Ember.Controller`.
+
+              @class ControllerContentModelAliasDeprecation
+              @namespace Ember
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+            /**
+                    @private
+
+                    Moves `content` to `model`  at extend time if a `model` is not also specified.
+
+                    Note that this currently modifies the mixin themselves, which is technically
+                    dubious but is practically of little consequence. This may change in the
+                    future.
+
+                    @method willMergeMixin
+                    @since 1.4.0
+                  */
+            willMergeMixin: function(props) {
+                // Calling super is only OK here since we KNOW that
+                // there is another Mixin loaded first.
+                this._super.apply(this, arguments);
+
+                var modelSpecified = !!props.model;
+
+                if (props.content &amp;&amp; !modelSpecified) {
+                    props.model = props.content;
+                    delete props['content'];
+
+                    Ember.deprecate('Do not specify `content` on a Controller, use `model` instead.', false);
+                }
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/copyable&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/freezable&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var required = __dependency3__.required;
+        var Freezable = __dependency4__.Freezable;
+        var Mixin = __dependency3__.Mixin;
+        var fmt = __dependency5__.fmt;
+        var EmberError = __dependency6__[&quot;default&quot;];
+
+
+        /**
+              Implements some standard methods for copying an object. Add this mixin to
+              any object you create that can create a copy of itself. This mixin is
+              added automatically to the built-in array.
+
+              You should generally implement the `copy()` method to return a copy of the
+              receiver.
+
+              Note that `frozenCopy()` will only work if you also implement
+              `Ember.Freezable`.
+
+              @class Copyable
+              @namespace Ember
+              @since Ember 0.9
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+            /**
+                    Override to return a copy of the receiver. Default implementation raises
+                    an exception.
+
+                    @method copy
+                    @param {Boolean} deep if `true`, a deep copy of the object should be made
+                    @return {Object} copy of receiver
+                  */
+            copy: required(Function),
+
+            /**
+                    If the object implements `Ember.Freezable`, then this will return a new
+                    copy if the object is not frozen and the receiver if the object is frozen.
+
+                    Raises an exception if you try to call this method on a object that does
+                    not support freezing.
+
+                    You should use this method whenever you want a copy of a freezable object
+                    since a freezable object can simply return itself without actually
+                    consuming more memory.
+
+                    @method frozenCopy
+                    @return {Object} copy of receiver or receiver
+                  */
+            frozenCopy: function() {
+                if (Freezable &amp;&amp; Freezable.detect(this)) {
+                    return get(this, 'isFrozen') ? this : this.copy().freeze();
+                } else {
+                    throw new EmberError(fmt(&quot;%@ does not support freezing&quot;, [this]));
+                }
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/deferred&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-runtime/ext/rsvp&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.FEATURES, Ember.Test
+        var get = __dependency2__.get;
+        var Mixin = __dependency3__.Mixin;
+        var computed = __dependency4__.computed;
+        var run = __dependency5__[&quot;default&quot;];
+        var RSVP = __dependency6__[&quot;default&quot;];
+
+        var asyncStart = function() {
+            if (Ember.Test &amp;&amp; Ember.Test.adapter) {
+                Ember.Test.adapter.asyncStart();
+            }
+        };
+
+        var asyncEnd = function() {
+            if (Ember.Test &amp;&amp; Ember.Test.adapter) {
+                Ember.Test.adapter.asyncEnd();
+            }
+        };
+
+        RSVP.configure('async', function(callback, promise) {
+            var async = !run.currentRunLoop;
+
+            if (Ember.testing &amp;&amp; async) {
+                asyncStart();
+            }
+
+            run.backburner.schedule('actions', function() {
+                if (Ember.testing &amp;&amp; async) {
+                    asyncEnd();
+                }
+                callback(promise);
+            });
+        });
+
+        RSVP.Promise.prototype.fail = function(callback, label) {
+            Ember.deprecate('RSVP.Promise.fail has been renamed as RSVP.Promise.catch');
+            return this['catch'](callback, label);
+        };
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+
+        /**
+              @class Deferred
+              @namespace Ember
+             */
+        __exports__[&quot;default&quot;] = Mixin.create({
+            /**
+                    Add handlers to be called when the Deferred object is resolved or rejected.
+
+                    @method then
+                    @param {Function} resolve a callback function to be called when done
+                    @param {Function} reject  a callback function to be called when failed
+                  */
+            then: function(resolve, reject, label) {
+                var deferred, promise, entity;
+
+                entity = this;
+                deferred = get(this, '_deferred');
+                promise = deferred.promise;
+
+                function fulfillmentHandler(fulfillment) {
+                    if (fulfillment === promise) {
+                        return resolve(entity);
+                    } else {
+                        return resolve(fulfillment);
+                    }
+                }
+
+                return promise.then(resolve &amp;&amp; fulfillmentHandler, reject, label);
+            },
+
+            /**
+                    Resolve a Deferred object and call any `doneCallbacks` with the given args.
+
+                    @method resolve
+                  */
+            resolve: function(value) {
+                var deferred, promise;
+
+                deferred = get(this, '_deferred');
+                promise = deferred.promise;
+
+                if (value === this) {
+                    deferred.resolve(promise);
+                } else {
+                    deferred.resolve(value);
+                }
+            },
+
+            /**
+                    Reject a Deferred object and call any `failCallbacks` with the given args.
+
+                    @method reject
+                  */
+            reject: function(value) {
+                get(this, '_deferred').reject(value);
+            },
+
+            _deferred: computed(function() {
+                Ember.deprecate('Usage of Ember.DeferredMixin or Ember.Deferred is deprecated.', this._suppressDeferredDeprecation);
+
+                return RSVP.defer('Ember: DeferredMixin - ' + this);
+            })
+        });
+    });
+    define(&quot;ember-runtime/mixins/enumerable&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/events&quot;, &quot;ember-runtime/compare&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        // ..........................................................
+        // HELPERS
+        //
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var apply = __dependency4__.apply;
+        var Mixin = __dependency5__.Mixin;
+        var required = __dependency5__.required;
+        var aliasMethod = __dependency5__.aliasMethod;
+        var indexOf = __dependency6__.indexOf;
+        var computed = __dependency7__.computed;
+        var propertyWillChange = __dependency8__.propertyWillChange;
+        var propertyDidChange = __dependency8__.propertyDidChange;
+        var addListener = __dependency9__.addListener;
+        var removeListener = __dependency9__.removeListener;
+        var sendEvent = __dependency9__.sendEvent;
+        var hasListeners = __dependency9__.hasListeners;
+        var compare = __dependency10__[&quot;default&quot;];
+
+        var a_slice = Array.prototype.slice;
+
+        var contexts = [];
+
+        function popCtx() {
+            return contexts.length === 0 ? {} : contexts.pop();
+        }
+
+        function pushCtx(ctx) {
+            contexts.push(ctx);
+            return null;
+        }
+
+        function iter(key, value) {
+            var valueProvided = arguments.length === 2;
+
+            function i(item) {
+                var cur = get(item, key);
+                return valueProvided ? value === cur : !!cur;
+            }
+
+            return i;
+        }
+
+        /**
+              This mixin defines the common interface implemented by enumerable objects
+              in Ember. Most of these methods follow the standard Array iteration
+              API defined up to JavaScript 1.8 (excluding language-specific features that
+              cannot be emulated in older versions of JavaScript).
+
+              This mixin is applied automatically to the Array class on page load, so you
+              can use any of these methods on simple arrays. If Array already implements
+              one of these methods, the mixin will not override them.
+
+              ## Writing Your Own Enumerable
+
+              To make your own custom class enumerable, you need two items:
+
+              1. You must have a length property. This property should change whenever
+                 the number of items in your enumerable object changes. If you use this
+                 with an `Ember.Object` subclass, you should be sure to change the length
+                 property using `set().`
+
+              2. You must implement `nextObject().` See documentation.
+
+              Once you have these two methods implemented, apply the `Ember.Enumerable` mixin
+              to your class and you will be able to enumerate the contents of your object
+              like any other collection.
+
+              ## Using Ember Enumeration with Other Libraries
+
+              Many other libraries provide some kind of iterator or enumeration like
+              facility. This is often where the most common API conflicts occur.
+              Ember's API is designed to be as friendly as possible with other
+              libraries by implementing only methods that mostly correspond to the
+              JavaScript 1.8 API.
+
+              @class Enumerable
+              @namespace Ember
+              @since Ember 0.9
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+
+            /**
+                    Implement this method to make your class enumerable.
+
+                    This method will be call repeatedly during enumeration. The index value
+                    will always begin with 0 and increment monotonically. You don't have to
+                    rely on the index value to determine what object to return, but you should
+                    always check the value and start from the beginning when you see the
+                    requested index is 0.
+
+                    The `previousObject` is the object that was returned from the last call
+                    to `nextObject` for the current iteration. This is a useful way to
+                    manage iteration if you are tracing a linked list, for example.
+
+                    Finally the context parameter will always contain a hash you can use as
+                    a &quot;scratchpad&quot; to maintain any other state you need in order to iterate
+                    properly. The context object is reused and is not reset between
+                    iterations so make sure you setup the context with a fresh state whenever
+                    the index parameter is 0.
+
+                    Generally iterators will continue to call `nextObject` until the index
+                    reaches the your current length-1. If you run out of data before this
+                    time for some reason, you should simply return undefined.
+
+                    The default implementation of this method simply looks up the index.
+                    This works great on any Array-like objects.
+
+                    @method nextObject
+                    @param {Number} index the current index of the iteration
+                    @param {Object} previousObject the value returned by the last call to
+                      `nextObject`.
+                    @param {Object} context a context object you can use to maintain state.
+                    @return {Object} the next object in the iteration or undefined
+                  */
+            nextObject: required(Function),
+
+            /**
+                    Helper method returns the first object from a collection. This is usually
+                    used by bindings and other parts of the framework to extract a single
+                    object if the enumerable contains only one item.
+
+                    If you override this method, you should implement it so that it will
+                    always return the same value each time it is called. If your enumerable
+                    contains only one object, this method should always return that object.
+                    If your enumerable is empty, this method should return `undefined`.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
+                    arr.get('firstObject');  // &quot;a&quot;
+
+                    var arr = [];
+                    arr.get('firstObject');  // undefined
+                    ```
+
+                    @property firstObject
+                    @return {Object} the object or undefined
+                  */
+            firstObject: computed('[]', function() {
+                if (get(this, 'length') === 0) 
+                    return undefined ;
+
+                // handle generic enumerables
+                var context = popCtx(), ret;
+                ret = this.nextObject(0, null, context);
+                pushCtx(context);
+                return ret;
+            }),
+
+            /**
+                    Helper method returns the last object from a collection. If your enumerable
+                    contains only one object, this method should always return that object.
+                    If your enumerable is empty, this method should return `undefined`.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
+                    arr.get('lastObject');  // &quot;c&quot;
+
+                    var arr = [];
+                    arr.get('lastObject');  // undefined
+                    ```
+
+                    @property lastObject
+                    @return {Object} the last object or undefined
+                  */
+            lastObject: computed('[]', function() {
+                var len = get(this, 'length');
+                if (len === 0) 
+                    return undefined ;
+                var context = popCtx(), idx = 0, cur, last = null;
+                do {
+                    last = cur;
+                    cur = this.nextObject(idx++, last, context);
+                }
+                while (cur !== undefined);
+                pushCtx(context);
+                return last;
+            }),
+
+            /**
+                    Returns `true` if the passed object can be found in the receiver. The
+                    default version will iterate through the enumerable until the object
+                    is found. You may want to override this with a more efficient version.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
+                    arr.contains(&quot;a&quot;); // true
+                    arr.contains(&quot;z&quot;); // false
+                    ```
+
+                    @method contains
+                    @param {Object} obj The object to search for.
+                    @return {Boolean} `true` if object is found in enumerable.
+                  */
+            contains: function(obj) {
+                return this.find(function(item) {
+                    return item === obj;
+                }) !== undefined;
+            },
+
+            /**
+                    Iterates through the enumerable, calling the passed function on each
+                    item. This method corresponds to the `forEach()` method defined in
+                    JavaScript 1.6.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    @method forEach
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Object} receiver
+                  */
+            forEach: function(callback, target) {
+                if (typeof callback !== 'function') 
+                    throw new TypeError() ;
+                var len = get(this, 'length'), last = null, context = popCtx();
+
+                if (target === undefined) 
+                    target = null;
+
+                for (var idx = 0; idx &lt; len; idx++) {
+                    var next = this.nextObject(idx, last, context) ;
+                    callback.call(target, next, idx, this);
+                    last = next ;
+                }
+                last = null ;
+                context = pushCtx(context);
+                return this ;
+            },
+
+            /**
+                    Alias for `mapBy`
+
+                    @method getEach
+                    @param {String} key name of the property
+                    @return {Array} The mapped array.
+                  */
+            getEach: function(key) {
+                return this.mapBy(key);
+            },
+
+            /**
+                    Sets the value on the named property for each member. This is more
+                    efficient than using other methods defined on this helper. If the object
+                    implements Ember.Observable, the value will be changed to `set(),` otherwise
+                    it will be set directly. `null` objects are skipped.
+
+                    @method setEach
+                    @param {String} key The key to set
+                    @param {Object} value The object to set
+                    @return {Object} receiver
+                  */
+            setEach: function(key, value) {
+                return this.forEach(function(item) {
+                    set(item, key, value);
+                });
+            },
+
+            /**
+                    Maps all of the items in the enumeration to another value, returning
+                    a new array. This method corresponds to `map()` defined in JavaScript 1.6.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    It should return the mapped value.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    @method map
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Array} The mapped array.
+                  */
+            map: function(callback, target) {
+                var ret = Ember.A();
+                this.forEach(function(x, idx, i) {
+                    ret[idx] = callback.call(target, x, idx, i);
+                });
+                return ret ;
+            },
+
+            /**
+                    Similar to map, this specialized function returns the value of the named
+                    property on all items in the enumeration.
+
+                    @method mapBy
+                    @param {String} key name of the property
+                    @return {Array} The mapped array.
+                  */
+            mapBy: function(key) {
+                return this.map(function(next) {
+                    return get(next, key);
+                });
+            },
+
+            /**
+                    Similar to map, this specialized function returns the value of the named
+                    property on all items in the enumeration.
+
+                    @method mapProperty
+                    @param {String} key name of the property
+                    @return {Array} The mapped array.
+                    @deprecated Use `mapBy` instead
+                  */
+
+            mapProperty: aliasMethod('mapBy'),
+
+            /**
+                    Returns an array with all of the items in the enumeration that the passed
+                    function returns true for. This method corresponds to `filter()` defined in
+                    JavaScript 1.6.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    It should return the `true` to include the item in the results, `false`
+                    otherwise.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    @method filter
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Array} A filtered array.
+                  */
+            filter: function(callback, target) {
+                var ret = Ember.A();
+                this.forEach(function(x, idx, i) {
+                    if (callback.call(target, x, idx, i)) 
+                        ret.push(x);
+                });
+                return ret ;
+            },
+
+            /**
+                    Returns an array with all of the items in the enumeration where the passed
+                    function returns false for. This method is the inverse of filter().
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - *item* is the current item in the iteration.
+                    - *index* is the current index in the iteration
+                    - *enumerable* is the enumerable object itself.
+
+                    It should return the a falsey value to include the item in the results.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as &quot;this&quot; on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    @method reject
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Array} A rejected array.
+                   */
+            reject: function(callback, target) {
+                return this.filter(function() {
+                    return !(apply(target, callback, arguments));
+                });
+            },
+
+            /**
+                    Returns an array with just the items with the matched property. You
+                    can pass an optional second argument with the target value. Otherwise
+                    this will match any property that evaluates to `true`.
+
+                    @method filterBy
+                    @param {String} key the property to test
+                    @param {*} [value] optional value to test against.
+                    @return {Array} filtered array
+                  */
+            filterBy: function(key, value) {
+                return this.filter(apply(this, iter, arguments));
+            },
+
+            /**
+                    Returns an array with just the items with the matched property. You
+                    can pass an optional second argument with the target value. Otherwise
+                    this will match any property that evaluates to `true`.
+
+                    @method filterProperty
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Array} filtered array
+                    @deprecated Use `filterBy` instead
+                  */
+            filterProperty: aliasMethod('filterBy'),
+
+            /**
+                    Returns an array with the items that do not have truthy values for
+                    key.  You can pass an optional second argument with the target value.  Otherwise
+                    this will match any property that evaluates to false.
+
+                    @method rejectBy
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Array} rejected array
+                  */
+            rejectBy: function(key, value) {
+                var exactValue = function(item) {
+                    return get(item, key) === value;
+                },
+                hasValue = function(item) {
+                    return !!get(item, key);
+                },
+                use = (arguments.length === 2 ? exactValue : hasValue);
+
+                return this.reject(use);
+            },
+
+            /**
+                    Returns an array with the items that do not have truthy values for
+                    key.  You can pass an optional second argument with the target value.  Otherwise
+                    this will match any property that evaluates to false.
+
+                    @method rejectProperty
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Array} rejected array
+                    @deprecated Use `rejectBy` instead
+                  */
+            rejectProperty: aliasMethod('rejectBy'),
+
+            /**
+                    Returns the first item in the array for which the callback returns true.
+                    This method works similar to the `filter()` method defined in JavaScript 1.6
+                    except that it will stop working on the array once a match is found.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    It should return the `true` to include the item in the results, `false`
+                    otherwise.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    @method find
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Object} Found item or `undefined`.
+                  */
+            find: function(callback, target) {
+                var len = get(this, 'length') ;
+                if (target === undefined) 
+                    target = null;
+
+                var last = null, next, found = false, ret ;
+                var context = popCtx();
+                for (var idx = 0; idx &lt; len &amp;&amp; !found; idx++) {
+                    next = this.nextObject(idx, last, context) ;
+                    if (found = callback.call(target, next, idx, this)) 
+                        ret = next ;
+                    last = next ;
+                }
+                next = last = null ;
+                context = pushCtx(context);
+                return ret ;
+            },
+
+            /**
+                    Returns the first item with a property matching the passed value. You
+                    can pass an optional second argument with the target value. Otherwise
+                    this will match any property that evaluates to `true`.
+
+                    This method works much like the more generic `find()` method.
+
+                    @method findBy
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Object} found item or `undefined`
+                  */
+            findBy: function(key, value) {
+                return this.find(apply(this, iter, arguments));
+            },
+
+            /**
+                    Returns the first item with a property matching the passed value. You
+                    can pass an optional second argument with the target value. Otherwise
+                    this will match any property that evaluates to `true`.
+
+                    This method works much like the more generic `find()` method.
+
+                    @method findProperty
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Object} found item or `undefined`
+                    @deprecated Use `findBy` instead
+                  */
+            findProperty: aliasMethod('findBy'),
+
+            /**
+                    Returns `true` if the passed function returns true for every item in the
+                    enumeration. This corresponds with the `every()` method in JavaScript 1.6.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    It should return the `true` or `false`.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    Example Usage:
+
+                    ```javascript
+                    if (people.every(isEngineer)) { Paychecks.addBigBonus(); }
+                    ```
+
+                    @method every
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Boolean}
+                  */
+            every: function(callback, target) {
+                return !this.find(function(x, idx, i) {
+                    return !callback.call(target, x, idx, i);
+                });
+            },
+
+            /**
+                    @method everyBy
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @deprecated Use `isEvery` instead
+                    @return {Boolean}
+                  */
+            everyBy: aliasMethod('isEvery'),
+
+            /**
+                    @method everyProperty
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @deprecated Use `isEvery` instead
+                    @return {Boolean}
+                  */
+            everyProperty: aliasMethod('isEvery'),
+
+            /**
+                    Returns `true` if the passed property resolves to `true` for all items in
+                    the enumerable. This method is often simpler/faster than using a callback.
+
+                    @method isEvery
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Boolean}
+                    @since 1.3.0
+                  */
+            isEvery: function(key, value) {
+                return this.every(apply(this, iter, arguments));
+            },
+
+            /**
+                    Returns `true` if the passed function returns true for any item in the
+                    enumeration. This corresponds with the `some()` method in JavaScript 1.6.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    It should return the `true` to include the item in the results, `false`
+                    otherwise.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    Usage Example:
+
+                    ```javascript
+                    if (people.any(isManager)) { Paychecks.addBiggerBonus(); }
+                    ```
+
+                    @method any
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Boolean} `true` if the passed function returns `true` for any item
+                  */
+            any: function(callback, target) {
+                var len = get(this, 'length'),
+                context = popCtx(),
+                found = false,
+                last = null,
+                next, idx;
+
+                if (target === undefined) {
+                    target = null;
+                }
+
+                for (idx = 0; idx &lt; len &amp;&amp; !found; idx++) {
+                    next = this.nextObject(idx, last, context);
+                    found = callback.call(target, next, idx, this);
+                    last = next;
+                }
+
+                next = last = null;
+                context = pushCtx(context);
+                return found;
+            },
+
+            /**
+                    Returns `true` if the passed function returns true for any item in the
+                    enumeration. This corresponds with the `some()` method in JavaScript 1.6.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(item, index, enumerable);
+                    ```
+
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    It should return the `true` to include the item in the results, `false`
+                    otherwise.
+
+                    Note that in addition to a callback, you can also pass an optional target
+                    object that will be set as `this` on the context. This is a good way
+                    to give your iterator function access to the current object.
+
+                    Usage Example:
+
+                    ```javascript
+                    if (people.some(isManager)) { Paychecks.addBiggerBonus(); }
+                    ```
+
+                    @method some
+                    @param {Function} callback The callback to execute
+                    @param {Object} [target] The target object to use
+                    @return {Boolean} `true` if the passed function returns `true` for any item
+                    @deprecated Use `any` instead
+                  */
+            some: aliasMethod('any'),
+
+            /**
+                    Returns `true` if the passed property resolves to `true` for any item in
+                    the enumerable. This method is often simpler/faster than using a callback.
+
+                    @method isAny
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Boolean} `true` if the passed function returns `true` for any item
+                    @since 1.3.0
+                  */
+            isAny: function(key, value) {
+                return this.any(apply(this, iter, arguments));
+            },
+
+            /**
+                    @method anyBy
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Boolean} `true` if the passed function returns `true` for any item
+                    @deprecated Use `isAny` instead
+                  */
+            anyBy: aliasMethod('isAny'),
+
+            /**
+                    @method someProperty
+                    @param {String} key the property to test
+                    @param {String} [value] optional value to test against.
+                    @return {Boolean} `true` if the passed function returns `true` for any item
+                    @deprecated Use `isAny` instead
+                  */
+            someProperty: aliasMethod('isAny'),
+
+            /**
+                    This will combine the values of the enumerator into a single value. It
+                    is a useful way to collect a summary value from an enumeration. This
+                    corresponds to the `reduce()` method defined in JavaScript 1.8.
+
+                    The callback method you provide should have the following signature (all
+                    parameters are optional):
+
+                    ```javascript
+                    function(previousValue, item, index, enumerable);
+                    ```
+
+                    - `previousValue` is the value returned by the last call to the iterator.
+                    - `item` is the current item in the iteration.
+                    - `index` is the current index in the iteration.
+                    - `enumerable` is the enumerable object itself.
+
+                    Return the new cumulative value.
+
+                    In addition to the callback you can also pass an `initialValue`. An error
+                    will be raised if you do not pass an initial value and the enumerator is
+                    empty.
+
+                    Note that unlike the other methods, this method does not allow you to
+                    pass a target object to set as this for the callback. It's part of the
+                    spec. Sorry.
+
+                    @method reduce
+                    @param {Function} callback The callback to execute
+                    @param {Object} initialValue Initial value for the reduce
+                    @param {String} reducerProperty internal use only.
+                    @return {Object} The reduced value.
+                  */
+            reduce: function(callback, initialValue, reducerProperty) {
+                if (typeof callback !== &quot;function&quot;) {
+                    throw new TypeError();
+                }
+
+                var ret = initialValue;
+
+                this.forEach(function(item, i) {
+                    ret = callback(ret, item, i, this, reducerProperty);
+                }, this);
+
+                return ret;
+            },
+
+            /**
+                    Invokes the named method on every object in the receiver that
+                    implements it. This method corresponds to the implementation in
+                    Prototype 1.6.
+
+                    @method invoke
+                    @param {String} methodName the name of the method
+                    @param {Object...} args optional arguments to pass as well.
+                    @return {Array} return values from calling invoke.
+                  */
+            invoke: function(methodName) {
+                var args, ret = Ember.A();
+                if (arguments.length &gt; 1) 
+                    args = a_slice.call(arguments, 1);
+
+                this.forEach(function(x, idx) {
+                    var method = x &amp;&amp; x[methodName];
+                    if ('function' === typeof method) {
+                        ret[idx] = args ? apply(x, method, args) : x[methodName]();
+                    }
+                }, this);
+
+                return ret;
+            },
+
+            /**
+                    Simply converts the enumerable into a genuine array. The order is not
+                    guaranteed. Corresponds to the method implemented by Prototype.
+
+                    @method toArray
+                    @return {Array} the enumerable as an array.
+                  */
+            toArray: function() {
+                var ret = Ember.A();
+                this.forEach(function(o, idx) {
+                    ret[idx] = o;
+                });
+                return ret;
+            },
+
+            /**
+                    Returns a copy of the array with all null and undefined elements removed.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, null, &quot;c&quot;, undefined];
+                    arr.compact();  // [&quot;a&quot;, &quot;c&quot;]
+                    ```
+
+                    @method compact
+                    @return {Array} the array without null and undefined elements.
+                  */
+            compact: function() {
+                return this.filter(function(value) {
+                    return value != null;
+                });
+            },
+
+            /**
+                    Returns a new enumerable that excludes the passed value. The default
+                    implementation returns an array regardless of the receiver type unless
+                    the receiver does not contain the value.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;b&quot;, &quot;a&quot;, &quot;c&quot;];
+                    arr.without(&quot;a&quot;);  // [&quot;b&quot;, &quot;c&quot;]
+                    ```
+
+                    @method without
+                    @param {Object} value
+                    @return {Ember.Enumerable}
+                  */
+            without: function(value) {
+                if (!this.contains(value)) 
+                    return this; // nothing to do
+                var ret = Ember.A();
+                this.forEach(function(k) {
+                    if (k !== value) 
+                        ret[ret.length] = k;
+                }) ;
+                return ret ;
+            },
+
+            /**
+                    Returns a new enumerable that contains only unique values. The default
+                    implementation returns an array regardless of the receiver type.
+
+                    ```javascript
+                    var arr = [&quot;a&quot;, &quot;a&quot;, &quot;b&quot;, &quot;b&quot;];
+                    arr.uniq();  // [&quot;a&quot;, &quot;b&quot;]
+                    ```
+
+                    @method uniq
+                    @return {Ember.Enumerable}
+                  */
+            uniq: function() {
+                var ret = Ember.A();
+                this.forEach(function(k) {
+                    if (indexOf(ret, k) &lt; 0) 
+                        ret.push(k);
+                });
+                return ret;
+            },
+
+            /**
+                    This property will trigger anytime the enumerable's content changes.
+                    You can observe this property to be notified of changes to the enumerables
+                    content.
+
+                    For plain enumerables, this property is read only. `Array` overrides
+                    this method.
+
+                    @property []
+                    @type Array
+                    @return this
+                  */
+            '[]': computed(function(key, value) {
+                return this;
+            }),
+
+            // ..........................................................
+            // ENUMERABLE OBSERVERS
+            //
+
+            /**
+                    Registers an enumerable observer. Must implement `Ember.EnumerableObserver`
+                    mixin.
+
+                    @method addEnumerableObserver
+                    @param {Object} target
+                    @param {Hash} [opts]
+                    @return this
+                  */
+            addEnumerableObserver: function(target, opts) {
+                var willChange = (opts &amp;&amp; opts.willChange) || 'enumerableWillChange',
+                didChange = (opts &amp;&amp; opts.didChange) || 'enumerableDidChange';
+
+                var hasObservers = get(this, 'hasEnumerableObservers');
+                if (!hasObservers) 
+                    propertyWillChange(this, 'hasEnumerableObservers');
+                addListener(this, '@enumerable:before', target, willChange);
+                addListener(this, '@enumerable:change', target, didChange);
+                if (!hasObservers) 
+                    propertyDidChange(this, 'hasEnumerableObservers');
+                return this;
+            },
+
+            /**
+                    Removes a registered enumerable observer.
+
+                    @method removeEnumerableObserver
+                    @param {Object} target
+                    @param {Hash} [opts]
+                    @return this
+                  */
+            removeEnumerableObserver: function(target, opts) {
+                var willChange = (opts &amp;&amp; opts.willChange) || 'enumerableWillChange',
+                didChange = (opts &amp;&amp; opts.didChange) || 'enumerableDidChange';
+
+                var hasObservers = get(this, 'hasEnumerableObservers');
+                if (hasObservers) 
+                    propertyWillChange(this, 'hasEnumerableObservers');
+                removeListener(this, '@enumerable:before', target, willChange);
+                removeListener(this, '@enumerable:change', target, didChange);
+                if (hasObservers) 
+                    propertyDidChange(this, 'hasEnumerableObservers');
+                return this;
+            },
+
+            /**
+                    Becomes true whenever the array currently has observers watching changes
+                    on the array.
+
+                    @property hasEnumerableObservers
+                    @type Boolean
+                  */
+            hasEnumerableObservers: computed(function() {
+                return hasListeners(this, '@enumerable:change') || hasListeners(this, '@enumerable:before');
+            }),
+
+
+            /**
+                    Invoke this method just before the contents of your enumerable will
+                    change. You can either omit the parameters completely or pass the objects
+                    to be removed or added if available or just a count.
+
+                    @method enumerableContentWillChange
+                    @param {Ember.Enumerable|Number} removing An enumerable of the objects to
+                      be removed or the number of items to be removed.
+                    @param {Ember.Enumerable|Number} adding An enumerable of the objects to be
+                      added or the number of items to be added.
+                    @chainable
+                  */
+            enumerableContentWillChange: function(removing, adding) {
+
+                var removeCnt, addCnt, hasDelta;
+
+                if ('number' === typeof removing) 
+                    removeCnt = removing;
+                else if (removing) 
+                    removeCnt = get(removing, 'length');
+                else 
+                    removeCnt = removing = -1;
+
+                if ('number' === typeof adding) 
+                    addCnt = adding;
+                else if (adding) 
+                    addCnt = get(adding, 'length');
+                else 
+                    addCnt = adding = -1;
+
+                hasDelta = addCnt &lt; 0 || removeCnt &lt; 0 || addCnt - removeCnt !== 0;
+
+                if (removing === -1) 
+                    removing = null;
+                if (adding === -1) 
+                    adding = null;
+
+                propertyWillChange(this, '[]');
+                if (hasDelta) 
+                    propertyWillChange(this, 'length');
+                sendEvent(this, '@enumerable:before', [this, removing, adding]);
+
+                return this;
+            },
+
+            /**
+                    Invoke this method when the contents of your enumerable has changed.
+                    This will notify any observers watching for content changes. If you are
+                    implementing an ordered enumerable (such as an array), also pass the
+                    start and end values where the content changed so that it can be used to
+                    notify range observers.
+
+                    @method enumerableContentDidChange
+                    @param {Ember.Enumerable|Number} removing An enumerable of the objects to
+                      be removed or the number of items to be removed.
+                    @param {Ember.Enumerable|Number} adding  An enumerable of the objects to
+                      be added or the number of items to be added.
+                    @chainable
+                  */
+            enumerableContentDidChange: function(removing, adding) {
+                var removeCnt, addCnt, hasDelta;
+
+                if ('number' === typeof removing) 
+                    removeCnt = removing;
+                else if (removing) 
+                    removeCnt = get(removing, 'length');
+                else 
+                    removeCnt = removing = -1;
+
+                if ('number' === typeof adding) 
+                    addCnt = adding;
+                else if (adding) 
+                    addCnt = get(adding, 'length');
+                else 
+                    addCnt = adding = -1;
+
+                hasDelta = addCnt &lt; 0 || removeCnt &lt; 0 || addCnt - removeCnt !== 0;
+
+                if (removing === -1) 
+                    removing = null;
+                if (adding === -1) 
+                    adding = null;
+
+                sendEvent(this, '@enumerable:change', [this, removing, adding]);
+                if (hasDelta) 
+                    propertyDidChange(this, 'length');
+                propertyDidChange(this, '[]');
+
+                return this ;
+            },
+
+            /**
+                    Converts the enumerable into an array and sorts by the keys
+                    specified in the argument.
+
+                    You may provide multiple arguments to sort by multiple properties.
+
+                    @method sortBy
+                    @param {String} property name(s) to sort on
+                    @return {Array} The sorted array.
+                    @since 1.2.0
+                    */
+            sortBy: function() {
+                var sortKeys = arguments;
+                return this.toArray().sort(function(a, b) {
+                    for (var i = 0; i &lt; sortKeys.length; i++) {
+                        var key = sortKeys[i],
+                        propA = get(a, key),
+                        propB = get(b, key);
+                        // return 1 or -1 else continue to the next sortKey
+                        var compareValue = compare(propA, propB);
+                        if (compareValue) {
+                            return compareValue;
+                        }
+                    }
+                    return 0;
+                });
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/evented&quot;,
+    [&quot;ember-metal/mixin&quot;, &quot;ember-metal/events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Mixin = __dependency1__.Mixin;
+        var addListener = __dependency2__.addListener;
+        var removeListener = __dependency2__.removeListener;
+        var hasListeners = __dependency2__.hasListeners;
+        var sendEvent = __dependency2__.sendEvent;
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        /**
+              This mixin allows for Ember objects to subscribe to and emit events.
+
+              ```javascript
+              App.Person = Ember.Object.extend(Ember.Evented, {
+                greet: function() {
+                  // ...
+                  this.trigger('greet');
+                }
+              });
+
+              var person = App.Person.create();
+
+              person.on('greet', function() {
+                console.log('Our person has greeted');
+              });
+
+              person.greet();
+
+              // outputs: 'Our person has greeted'
+              ```
+
+              You can also chain multiple event subscriptions:
+
+              ```javascript
+              person.on('greet', function() {
+                console.log('Our person has greeted');
+              }).one('greet', function() {
+                console.log('Offer one-time special');
+              }).off('event', this, forgetThis);
+              ```
+
+              @class Evented
+              @namespace Ember
+             */
+        __exports__[&quot;default&quot;] = Mixin.create({
+
+            /**
+                   Subscribes to a named event with given function.
+
+                   ```javascript
+                   person.on('didLoad', function() {
+                     // fired once the person has loaded
+                   });
+                   ```
+
+                   An optional target can be passed in as the 2nd argument that will
+                   be set as the &quot;this&quot; for the callback. This is a good way to give your
+                   function access to the object triggering the event. When the target
+                   parameter is used the callback becomes the third argument.
+
+                   @method on
+                   @param {String} name The name of the event
+                   @param {Object} [target] The &quot;this&quot; binding for the callback
+                   @param {Function} method The callback to execute
+                   @return this
+                  */
+            on: function(name, target, method) {
+                addListener(this, name, target, method);
+                return this;
+            },
+
+            /**
+                    Subscribes a function to a named event and then cancels the subscription
+                    after the first time the event is triggered. It is good to use ``one`` when
+                    you only care about the first time an event has taken place.
+
+                    This function takes an optional 2nd argument that will become the &quot;this&quot;
+                    value for the callback. If this argument is passed then the 3rd argument
+                    becomes the function.
+
+                    @method one
+                    @param {String} name The name of the event
+                    @param {Object} [target] The &quot;this&quot; binding for the callback
+                    @param {Function} method The callback to execute
+                    @return this
+                  */
+            one: function(name, target, method) {
+                if (!method) {
+                    method = target;
+                    target = null;
+                }
+
+                addListener(this, name, target, method, true);
+                return this;
+            },
+
+            /**
+                    Triggers a named event for the object. Any additional arguments
+                    will be passed as parameters to the functions that are subscribed to the
+                    event.
+
+                    ```javascript
+                    person.on('didEat', function(food) {
+                      console.log('person ate some ' + food);
+                    });
+
+                    person.trigger('didEat', 'broccoli');
+
+                    // outputs: person ate some broccoli
+                    ```
+                    @method trigger
+                    @param {String} name The name of the event
+                    @param {Object...} args Optional arguments to pass on
+                  */
+            trigger: function(name) {
+                var length = arguments.length;
+                var args = new Array(length - 1);
+
+                for (var i = 1; i &lt; length; i++) {
+                    args[i - 1] = arguments[i];
+                }
+
+                sendEvent(this, name, args);
+            },
+
+            /**
+                    Cancels subscription for given name, target, and method.
+
+                    @method off
+                    @param {String} name The name of the event
+                    @param {Object} target The target of the subscription
+                    @param {Function} method The function of the subscription
+                    @return this
+                  */
+            off: function(name, target, method) {
+                removeListener(this, name, target, method);
+                return this;
+            },
+
+            /**
+                    Checks to see if object has any subscriptions for named event.
+
+                    @method has
+                    @param {String} name The name of the event
+                    @return {Boolean} does the object have a subscription for event
+                   */
+            has: function(name) {
+                return hasListeners(this, name);
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/freezable&quot;,
+    [&quot;ember-metal/mixin&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Mixin = __dependency1__.Mixin;
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+
+        /**
+              The `Ember.Freezable` mixin implements some basic methods for marking an
+              object as frozen. Once an object is frozen it should be read only. No changes
+              may be made the internal state of the object.
+
+              ## Enforcement
+
+              To fully support freezing in your subclass, you must include this mixin and
+              override any method that might alter any property on the object to instead
+              raise an exception. You can check the state of an object by checking the
+              `isFrozen` property.
+
+              Although future versions of JavaScript may support language-level freezing
+              object objects, that is not the case today. Even if an object is freezable,
+              it is still technically possible to modify the object, even though it could
+              break other parts of your application that do not expect a frozen object to
+              change. It is, therefore, very important that you always respect the
+              `isFrozen` property on all freezable objects.
+
+              ## Example Usage
+
+              The example below shows a simple object that implement the `Ember.Freezable`
+              protocol.
+
+              ```javascript
+              Contact = Ember.Object.extend(Ember.Freezable, {
+                firstName: null,
+                lastName: null,
+
+                // swaps the names
+                swapNames: function() {
+                  if (this.get('isFrozen')) throw Ember.FROZEN_ERROR;
+                  var tmp = this.get('firstName');
+                  this.set('firstName', this.get('lastName'));
+                  this.set('lastName', tmp);
+                  return this;
+                }
+
+              });
+
+              c = Contact.create({ firstName: &quot;John&quot;, lastName: &quot;Doe&quot; });
+              c.swapNames();  // returns c
+              c.freeze();
+              c.swapNames();  // EXCEPTION
+              ```
+
+              ## Copying
+
+              Usually the `Ember.Freezable` protocol is implemented in cooperation with the
+              `Ember.Copyable` protocol, which defines a `frozenCopy()` method that will
+              return a frozen object, if the object implements this method as well.
+
+              @class Freezable
+              @namespace Ember
+              @since Ember 0.9
+            */
+        var Freezable = Mixin.create({
+
+            /**
+                    Set to `true` when the object is frozen. Use this property to detect
+                    whether your object is frozen or not.
+
+                    @property isFrozen
+                    @type Boolean
+                  */
+            isFrozen: false,
+
+            /**
+                    Freezes the object. Once this method has been called the object should
+                    no longer allow any properties to be edited.
+
+                    @method freeze
+                    @return {Object} receiver
+                  */
+            freeze: function() {
+                if (get(this, 'isFrozen')) 
+                    return this;
+                set(this, 'isFrozen', true);
+                return this;
+            }
+
+        });
+        __exports__.Freezable = Freezable;
+        var FROZEN_ERROR = &quot;Frozen object cannot be modified.&quot;;
+        __exports__.FROZEN_ERROR = FROZEN_ERROR;
+    });
+    define(&quot;ember-runtime/mixins/mutable_array&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;ember-runtime/mixins/mutable_enumerable&quot;, &quot;ember-runtime/mixins/enumerable&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+
+        // require('ember-runtime/mixins/array');
+        // require('ember-runtime/mixins/mutable_enumerable');
+
+        // ..........................................................
+        // CONSTANTS
+        //
+
+        var OUT_OF_RANGE_EXCEPTION = &quot;Index out of range&quot;;
+        var EMPTY = [];
+
+        // ..........................................................
+        // HELPERS
+        //
+
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var isArray = __dependency3__.isArray;
+        var EmberError = __dependency4__[&quot;default&quot;];
+        var Mixin = __dependency5__.Mixin;
+        var required = __dependency5__.required;
+        var EmberArray = __dependency6__[&quot;default&quot;];
+        var MutableEnumerable = __dependency7__[&quot;default&quot;];
+        var Enumerable = __dependency8__[&quot;default&quot;];
+        /**
+              This mixin defines the API for modifying array-like objects. These methods
+              can be applied only to a collection that keeps its items in an ordered set.
+              It builds upon the Array mixin and adds methods to modify the array.
+              Concrete implementations of this class include ArrayProxy and ArrayController.
+
+              It is important to use the methods in this class to modify arrays so that
+              changes are observable. This allows the binding system in Ember to function
+              correctly.
+
+
+              Note that an Array can change even if it does not implement this mixin.
+              For example, one might implement a SparseArray that cannot be directly
+              modified, but if its underlying enumerable changes, it will change also.
+
+              @class MutableArray
+              @namespace Ember
+              @uses Ember.Array
+              @uses Ember.MutableEnumerable
+            */
+        __exports__[&quot;default&quot;] = Mixin.create(EmberArray, MutableEnumerable, {
+
+            /**
+                    __Required.__ You must implement this method to apply this mixin.
+
+                    This is one of the primitives you must implement to support `Ember.Array`.
+                    You should replace amt objects started at idx with the objects in the
+                    passed array. You should also call `this.enumerableContentDidChange()`
+
+                    @method replace
+                    @param {Number} idx Starting index in the array to replace. If
+                      idx &gt;= length, then append to the end of the array.
+                    @param {Number} amt Number of elements that should be removed from
+                      the array, starting at *idx*.
+                    @param {Array} objects An array of zero or more objects that should be
+                      inserted into the array at *idx*
+                  */
+            replace: required(),
+
+            /**
+                    Remove all elements from the array. This is useful if you
+                    want to reuse an existing array without having to recreate it.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;];
+                    color.length();   //  3
+                    colors.clear();   //  []
+                    colors.length();  //  0
+                    ```
+
+                    @method clear
+                    @return {Ember.Array} An empty Array.
+                  */
+            clear: function () {
+                var len = get(this, 'length');
+                if (len === 0) 
+                    return this;
+                this.replace(0, len, EMPTY);
+                return this;
+            },
+
+            /**
+                    This will use the primitive `replace()` method to insert an object at the
+                    specified index.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;];
+                    colors.insertAt(2, &quot;yellow&quot;);  // [&quot;red&quot;, &quot;green&quot;, &quot;yellow&quot;, &quot;blue&quot;]
+                    colors.insertAt(5, &quot;orange&quot;);  // Error: Index out of range
+                    ```
+
+                    @method insertAt
+                    @param {Number} idx index of insert the object at.
+                    @param {Object} object object to insert
+                    @return {Ember.Array} receiver
+                  */
+            insertAt: function(idx, object) {
+                if (idx &gt; get(this, 'length')) 
+                    throw new EmberError(OUT_OF_RANGE_EXCEPTION);
+                this.replace(idx, 0, [object]);
+                return this;
+            },
+
+            /**
+                    Remove an object at the specified index using the `replace()` primitive
+                    method. You can pass either a single index, or a start and a length.
+
+                    If you pass a start and length that is beyond the
+                    length this method will throw an `OUT_OF_RANGE_EXCEPTION`.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;, &quot;yellow&quot;, &quot;orange&quot;];
+                    colors.removeAt(0);     // [&quot;green&quot;, &quot;blue&quot;, &quot;yellow&quot;, &quot;orange&quot;]
+                    colors.removeAt(2, 2);  // [&quot;green&quot;, &quot;blue&quot;]
+                    colors.removeAt(4, 2);  // Error: Index out of range
+                    ```
+
+                    @method removeAt
+                    @param {Number} start index, start of range
+                    @param {Number} len length of passing range
+                    @return {Ember.Array} receiver
+                  */
+            removeAt: function(start, len) {
+                if ('number' === typeof start) {
+
+                    if ((start &lt; 0) || (start &gt;= get(this, 'length'))) {
+                        throw new EmberError(OUT_OF_RANGE_EXCEPTION);
+                    }
+
+                    // fast case
+                    if (len === undefined) 
+                        len = 1;
+                    this.replace(start, len, EMPTY);
+                }
+
+                return this;
+            },
+
+            /**
+                    Push the object onto the end of the array. Works just like `push()` but it
+                    is KVO-compliant.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;];
+                    colors.pushObject(&quot;black&quot;);     // [&quot;red&quot;, &quot;green&quot;, &quot;black&quot;]
+                    colors.pushObject([&quot;yellow&quot;]);  // [&quot;red&quot;, &quot;green&quot;, [&quot;yellow&quot;]]
+                    ```
+
+                    @method pushObject
+                    @param {*} obj object to push
+                    @return object same object passed as a param
+                  */
+            pushObject: function(obj) {
+                this.insertAt(get(this, 'length'), obj);
+                return obj;
+            },
+
+            /**
+                    Add the objects in the passed numerable to the end of the array. Defers
+                    notifying observers of the change until all objects are added.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;];
+                    colors.pushObjects([&quot;yellow&quot;, &quot;orange&quot;]);  // [&quot;red&quot;, &quot;yellow&quot;, &quot;orange&quot;]
+                    ```
+
+                    @method pushObjects
+                    @param {Ember.Enumerable} objects the objects to add
+                    @return {Ember.Array} receiver
+                  */
+            pushObjects: function(objects) {
+                if (!(Enumerable.detect(objects) || isArray(objects))) {
+                    throw new TypeError(&quot;Must pass Ember.Enumerable to Ember.MutableArray#pushObjects&quot;);
+                }
+                this.replace(get(this, 'length'), 0, objects);
+                return this;
+            },
+
+            /**
+                    Pop object from array or nil if none are left. Works just like `pop()` but
+                    it is KVO-compliant.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;];
+                    colors.popObject();   // &quot;blue&quot;
+                    console.log(colors);  // [&quot;red&quot;, &quot;green&quot;]
+                    ```
+
+                    @method popObject
+                    @return object
+                  */
+            popObject: function() {
+                var len = get(this, 'length');
+                if (len === 0) 
+                    return null;
+
+                var ret = this.objectAt(len-1);
+                this.removeAt(len-1, 1);
+                return ret;
+            },
+
+            /**
+                    Shift an object from start of array or nil if none are left. Works just
+                    like `shift()` but it is KVO-compliant.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;];
+                    colors.shiftObject();  // &quot;red&quot;
+                    console.log(colors);   // [&quot;green&quot;, &quot;blue&quot;]
+                    ```
+
+                    @method shiftObject
+                    @return object
+                  */
+            shiftObject: function() {
+                if (get(this, 'length') === 0) 
+                    return null;
+                var ret = this.objectAt(0);
+                this.removeAt(0);
+                return ret;
+            },
+
+            /**
+                    Unshift an object to start of array. Works just like `unshift()` but it is
+                    KVO-compliant.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;];
+                    colors.unshiftObject(&quot;yellow&quot;);    // [&quot;yellow&quot;, &quot;red&quot;]
+                    colors.unshiftObject([&quot;black&quot;]);   // [[&quot;black&quot;], &quot;yellow&quot;, &quot;red&quot;]
+                    ```
+
+                    @method unshiftObject
+                    @param {*} obj object to unshift
+                    @return object same object passed as a param
+                  */
+            unshiftObject: function(obj) {
+                this.insertAt(0, obj);
+                return obj;
+            },
+
+            /**
+                    Adds the named objects to the beginning of the array. Defers notifying
+                    observers until all objects have been added.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;];
+                    colors.unshiftObjects([&quot;black&quot;, &quot;white&quot;]);   // [&quot;black&quot;, &quot;white&quot;, &quot;red&quot;]
+                    colors.unshiftObjects(&quot;yellow&quot;); // Type Error: 'undefined' is not a function
+                    ```
+
+                    @method unshiftObjects
+                    @param {Ember.Enumerable} objects the objects to add
+                    @return {Ember.Array} receiver
+                  */
+            unshiftObjects: function(objects) {
+                this.replace(0, 0, objects);
+                return this;
+            },
+
+            /**
+                    Reverse objects in the array. Works just like `reverse()` but it is
+                    KVO-compliant.
+
+                    @method reverseObjects
+                    @return {Ember.Array} receiver
+                   */
+            reverseObjects: function() {
+                var len = get(this, 'length');
+                if (len === 0) 
+                    return this;
+                var objects = this.toArray().reverse();
+                this.replace(0, len, objects);
+                return this;
+            },
+
+            /**
+                    Replace all the the receiver's content with content of the argument.
+                    If argument is an empty array receiver will be cleared.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;];
+                    colors.setObjects([&quot;black&quot;, &quot;white&quot;]);  // [&quot;black&quot;, &quot;white&quot;]
+                    colors.setObjects([]);                  // []
+                    ```
+
+                    @method setObjects
+                    @param {Ember.Array} objects array whose content will be used for replacing
+                        the content of the receiver
+                    @return {Ember.Array} receiver with the new content
+                   */
+            setObjects: function(objects) {
+                if (objects.length === 0) 
+                    return this.clear();
+
+                var len = get(this, 'length');
+                this.replace(0, len, objects);
+                return this;
+            },
+
+            // ..........................................................
+            // IMPLEMENT Ember.MutableEnumerable
+            //
+
+            /**
+                    Remove all occurances of an object in the array.
+
+                    ```javascript
+                    var cities = [&quot;Chicago&quot;, &quot;Berlin&quot;, &quot;Lima&quot;, &quot;Chicago&quot;];
+                    cities.removeObject(&quot;Chicago&quot;);  // [&quot;Berlin&quot;, &quot;Lima&quot;]
+                    cities.removeObject(&quot;Lima&quot;);     // [&quot;Berlin&quot;]
+                    cities.removeObject(&quot;Tokyo&quot;)     // [&quot;Berlin&quot;]
+                    ```
+
+                    @method removeObject
+                    @param {*} obj object to remove
+                    @return {Ember.Array} receiver
+                  */
+            removeObject: function(obj) {
+                var loc = get(this, 'length') || 0;
+                while (--loc &gt;= 0) {
+                    var curObject = this.objectAt(loc);
+                    if (curObject === obj) 
+                        this.removeAt(loc);
+                }
+                return this;
+            },
+
+            /**
+                    Push the object onto the end of the array if it is not already
+                    present in the array.
+
+                    ```javascript
+                    var cities = [&quot;Chicago&quot;, &quot;Berlin&quot;];
+                    cities.addObject(&quot;Lima&quot;);    // [&quot;Chicago&quot;, &quot;Berlin&quot;, &quot;Lima&quot;]
+                    cities.addObject(&quot;Berlin&quot;);  // [&quot;Chicago&quot;, &quot;Berlin&quot;, &quot;Lima&quot;]
+                    ```
+
+                    @method addObject
+                    @param {*} obj object to add, if not already present
+                    @return {Ember.Array} receiver
+                  */
+            addObject: function(obj) {
+                if (!this.contains(obj)) 
+                    this.pushObject(obj);
+                return this;
+            }
+
+        });
+    });
+    define(&quot;ember-runtime/mixins/mutable_enumerable&quot;,
+    [&quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/mixins/enumerable&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/property_events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var forEach = __dependency1__.forEach;
+        var Enumerable = __dependency2__[&quot;default&quot;];
+        var Mixin = __dependency3__.Mixin;
+        var required = __dependency3__.required;
+        var beginPropertyChanges = __dependency4__.beginPropertyChanges;
+        var endPropertyChanges = __dependency4__.endPropertyChanges;
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        /**
+              This mixin defines the API for modifying generic enumerables. These methods
+              can be applied to an object regardless of whether it is ordered or
+              unordered.
+
+              Note that an Enumerable can change even if it does not implement this mixin.
+              For example, a MappedEnumerable cannot be directly modified but if its
+              underlying enumerable changes, it will change also.
+
+              ## Adding Objects
+
+              To add an object to an enumerable, use the `addObject()` method. This
+              method will only add the object to the enumerable if the object is not
+              already present and is of a type supported by the enumerable.
+
+              ```javascript
+              set.addObject(contact);
+              ```
+
+              ## Removing Objects
+
+              To remove an object from an enumerable, use the `removeObject()` method. This
+              will only remove the object if it is present in the enumerable, otherwise
+              this method has no effect.
+
+              ```javascript
+              set.removeObject(contact);
+              ```
+
+              ## Implementing In Your Own Code
+
+              If you are implementing an object and want to support this API, just include
+              this mixin in your class and implement the required methods. In your unit
+              tests, be sure to apply the Ember.MutableEnumerableTests to your object.
+
+              @class MutableEnumerable
+              @namespace Ember
+              @uses Ember.Enumerable
+            */
+        __exports__[&quot;default&quot;] = Mixin.create(Enumerable, {
+
+            /**
+                    __Required.__ You must implement this method to apply this mixin.
+
+                    Attempts to add the passed object to the receiver if the object is not
+                    already present in the collection. If the object is present, this method
+                    has no effect.
+
+                    If the passed object is of a type not supported by the receiver,
+                    then this method should raise an exception.
+
+                    @method addObject
+                    @param {Object} object The object to add to the enumerable.
+                    @return {Object} the passed object
+                  */
+            addObject: required(Function),
+
+            /**
+                    Adds each object in the passed enumerable to the receiver.
+
+                    @method addObjects
+                    @param {Ember.Enumerable} objects the objects to add.
+                    @return {Object} receiver
+                  */
+            addObjects: function(objects) {
+                beginPropertyChanges(this);
+                forEach(objects, function(obj) {
+                    this.addObject(obj);
+                }, this);
+                endPropertyChanges(this);
+                return this;
+            },
+
+            /**
+                    __Required.__ You must implement this method to apply this mixin.
+
+                    Attempts to remove the passed object from the receiver collection if the
+                    object is present in the collection. If the object is not present,
+                    this method has no effect.
+
+                    If the passed object is of a type not supported by the receiver,
+                    then this method should raise an exception.
+
+                    @method removeObject
+                    @param {Object} object The object to remove from the enumerable.
+                    @return {Object} the passed object
+                  */
+            removeObject: required(Function),
+
+
+            /**
+                    Removes each object in the passed enumerable from the receiver.
+
+                    @method removeObjects
+                    @param {Ember.Enumerable} objects the objects to remove
+                    @return {Object} receiver
+                  */
+            removeObjects: function(objects) {
+                beginPropertyChanges(this);
+                for (var i = objects.length - 1; i &gt;= 0; i--) {
+                    this.removeObject(objects[i]);
+                }
+                endPropertyChanges(this);
+                return this;
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/observable&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/get_properties&quot;, &quot;ember-metal/set_properties&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/events&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/is_none&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+
+        var get = __dependency2__.get;
+        var getWithDefault = __dependency2__.getWithDefault;
+        var set = __dependency3__.set;
+        var apply = __dependency4__.apply;
+        var getProperties = __dependency5__[&quot;default&quot;];
+        var setProperties = __dependency6__[&quot;default&quot;];
+        var Mixin = __dependency7__.Mixin;
+        var hasListeners = __dependency8__.hasListeners;
+        var beginPropertyChanges = __dependency9__.beginPropertyChanges;
+        var propertyWillChange = __dependency9__.propertyWillChange;
+        var propertyDidChange = __dependency9__.propertyDidChange;
+        var endPropertyChanges = __dependency9__.endPropertyChanges;
+        var addObserver = __dependency10__.addObserver;
+        var addBeforeObserver = __dependency10__.addBeforeObserver;
+        var removeObserver = __dependency10__.removeObserver;
+        var observersFor = __dependency10__.observersFor;
+        var cacheFor = __dependency11__.cacheFor;
+        var isNone = __dependency12__.isNone;
+
+
+        var slice = Array.prototype.slice;
+        /**
+              ## Overview
+
+              This mixin provides properties and property observing functionality, core
+              features of the Ember object model.
+
+              Properties and observers allow one object to observe changes to a
+              property on another object. This is one of the fundamental ways that
+              models, controllers and views communicate with each other in an Ember
+              application.
+
+              Any object that has this mixin applied can be used in observer
+              operations. That includes `Ember.Object` and most objects you will
+              interact with as you write your Ember application.
+
+              Note that you will not generally apply this mixin to classes yourself,
+              but you will use the features provided by this module frequently, so it
+              is important to understand how to use it.
+
+              ## Using `get()` and `set()`
+
+              Because of Ember's support for bindings and observers, you will always
+              access properties using the get method, and set properties using the
+              set method. This allows the observing objects to be notified and
+              computed properties to be handled properly.
+
+              More documentation about `get` and `set` are below.
+
+              ## Observing Property Changes
+
+              You typically observe property changes simply by adding the `observes`
+              call to the end of your method declarations in classes that you write.
+              For example:
+
+              ```javascript
+              Ember.Object.extend({
+                valueObserver: function() {
+                  // Executes whenever the &quot;value&quot; property changes
+                }.observes('value')
+              });
+              ```
+
+              Although this is the most common way to add an observer, this capability
+              is actually built into the `Ember.Object` class on top of two methods
+              defined in this mixin: `addObserver` and `removeObserver`. You can use
+              these two methods to add and remove observers yourself if you need to
+              do so at runtime.
+
+              To add an observer for a property, call:
+
+              ```javascript
+              object.addObserver('propertyKey', targetObject, targetAction)
+              ```
+
+              This will call the `targetAction` method on the `targetObject` whenever
+              the value of the `propertyKey` changes.
+
+              Note that if `propertyKey` is a computed property, the observer will be
+              called when any of the property dependencies are changed, even if the
+              resulting value of the computed property is unchanged. This is necessary
+              because computed properties are not computed until `get` is called.
+
+              @class Observable
+              @namespace Ember
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+
+            /**
+                    Retrieves the value of a property from the object.
+
+                    This method is usually similar to using `object[keyName]` or `object.keyName`,
+                    however it supports both computed properties and the unknownProperty
+                    handler.
+
+                    Because `get` unifies the syntax for accessing all these kinds
+                    of properties, it can make many refactorings easier, such as replacing a
+                    simple property with a computed property, or vice versa.
+
+                    ### Computed Properties
+
+                    Computed properties are methods defined with the `property` modifier
+                    declared at the end, such as:
+
+                    ```javascript
+                    fullName: function() {
+                      return this.get('firstName') + ' ' + this.get('lastName');
+                    }.property('firstName', 'lastName')
+                    ```
+
+                    When you call `get` on a computed property, the function will be
+                    called and the return value will be returned instead of the function
+                    itself.
+
+                    ### Unknown Properties
+
+                    Likewise, if you try to call `get` on a property whose value is
+                    `undefined`, the `unknownProperty()` method will be called on the object.
+                    If this method returns any value other than `undefined`, it will be returned
+                    instead. This allows you to implement &quot;virtual&quot; properties that are
+                    not defined upfront.
+
+                    @method get
+                    @param {String} keyName The property to retrieve
+                    @return {Object} The property value or undefined.
+                  */
+            get: function(keyName) {
+                return get(this, keyName);
+            },
+
+            /**
+                    To get multiple properties at once, call `getProperties`
+                    with a list of strings or an array:
+
+                    ```javascript
+                    record.getProperties('firstName', 'lastName', 'zipCode');
+                    // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
+                    ```
+
+                    is equivalent to:
+
+                    ```javascript
+                    record.getProperties(['firstName', 'lastName', 'zipCode']);
+                    // { firstName: 'John', lastName: 'Doe', zipCode: '10011' }
+                    ```
+
+                    @method getProperties
+                    @param {String...|Array} list of keys to get
+                    @return {Hash}
+                  */
+            getProperties: function() {
+                return apply(null, getProperties, [this].concat(slice.call(arguments)));
+            },
+
+            /**
+                    Sets the provided key or path to the value.
+
+                    This method is generally very similar to calling `object[key] = value` or
+                    `object.key = value`, except that it provides support for computed
+                    properties, the `setUnknownProperty()` method and property observers.
+
+                    ### Computed Properties
+
+                    If you try to set a value on a key that has a computed property handler
+                    defined (see the `get()` method for an example), then `set()` will call
+                    that method, passing both the value and key instead of simply changing
+                    the value itself. This is useful for those times when you need to
+                    implement a property that is composed of one or more member
+                    properties.
+
+                    ### Unknown Properties
+
+                    If you try to set a value on a key that is undefined in the target
+                    object, then the `setUnknownProperty()` handler will be called instead. This
+                    gives you an opportunity to implement complex &quot;virtual&quot; properties that
+                    are not predefined on the object. If `setUnknownProperty()` returns
+                    undefined, then `set()` will simply set the value on the object.
+
+                    ### Property Observers
+
+                    In addition to changing the property, `set()` will also register a property
+                    change with the object. Unless you have placed this call inside of a
+                    `beginPropertyChanges()` and `endPropertyChanges(),` any &quot;local&quot; observers
+                    (i.e. observer methods declared on the same object), will be called
+                    immediately. Any &quot;remote&quot; observers (i.e. observer methods declared on
+                    another object) will be placed in a queue and called at a later time in a
+                    coalesced manner.
+
+                    ### Chaining
+
+                    In addition to property changes, `set()` returns the value of the object
+                    itself so you can do chaining like this:
+
+                    ```javascript
+                    record.set('firstName', 'Charles').set('lastName', 'Jolley');
+                    ```
+
+                    @method set
+                    @param {String} keyName The property to set
+                    @param {Object} value The value to set or `null`.
+                    @return {Ember.Observable}
+                  */
+            set: function(keyName, value) {
+                set(this, keyName, value);
+                return this;
+            },
+
+
+            /**
+                    Sets a list of properties at once. These properties are set inside
+                    a single `beginPropertyChanges` and `endPropertyChanges` batch, so
+                    observers will be buffered.
+
+                    ```javascript
+                    record.setProperties({ firstName: 'Charles', lastName: 'Jolley' });
+                    ```
+
+                    @method setProperties
+                    @param {Hash} hash the hash of keys and values to set
+                    @return {Ember.Observable}
+                  */
+            setProperties: function(hash) {
+                return setProperties(this, hash);
+            },
+
+            /**
+                    Begins a grouping of property changes.
+
+                    You can use this method to group property changes so that notifications
+                    will not be sent until the changes are finished. If you plan to make a
+                    large number of changes to an object at one time, you should call this
+                    method at the beginning of the changes to begin deferring change
+                    notifications. When you are done making changes, call
+                    `endPropertyChanges()` to deliver the deferred change notifications and end
+                    deferring.
+
+                    @method beginPropertyChanges
+                    @return {Ember.Observable}
+                  */
+            beginPropertyChanges: function() {
+                beginPropertyChanges();
+                return this;
+            },
+
+            /**
+                    Ends a grouping of property changes.
+
+                    You can use this method to group property changes so that notifications
+                    will not be sent until the changes are finished. If you plan to make a
+                    large number of changes to an object at one time, you should call
+                    `beginPropertyChanges()` at the beginning of the changes to defer change
+                    notifications. When you are done making changes, call this method to
+                    deliver the deferred change notifications and end deferring.
+
+                    @method endPropertyChanges
+                    @return {Ember.Observable}
+                  */
+            endPropertyChanges: function() {
+                endPropertyChanges();
+                return this;
+            },
+
+            /**
+                    Notify the observer system that a property is about to change.
+
+                    Sometimes you need to change a value directly or indirectly without
+                    actually calling `get()` or `set()` on it. In this case, you can use this
+                    method and `propertyDidChange()` instead. Calling these two methods
+                    together will notify all observers that the property has potentially
+                    changed value.
+
+                    Note that you must always call `propertyWillChange` and `propertyDidChange`
+                    as a pair. If you do not, it may get the property change groups out of
+                    order and cause notifications to be delivered more often than you would
+                    like.
+
+                    @method propertyWillChange
+                    @param {String} keyName The property key that is about to change.
+                    @return {Ember.Observable}
+                  */
+            propertyWillChange: function(keyName) {
+                propertyWillChange(this, keyName);
+                return this;
+            },
+
+            /**
+                    Notify the observer system that a property has just changed.
+
+                    Sometimes you need to change a value directly or indirectly without
+                    actually calling `get()` or `set()` on it. In this case, you can use this
+                    method and `propertyWillChange()` instead. Calling these two methods
+                    together will notify all observers that the property has potentially
+                    changed value.
+
+                    Note that you must always call `propertyWillChange` and `propertyDidChange`
+                    as a pair. If you do not, it may get the property change groups out of
+                    order and cause notifications to be delivered more often than you would
+                    like.
+
+                    @method propertyDidChange
+                    @param {String} keyName The property key that has just changed.
+                    @return {Ember.Observable}
+                  */
+            propertyDidChange: function(keyName) {
+                propertyDidChange(this, keyName);
+                return this;
+            },
+
+            /**
+                    Convenience method to call `propertyWillChange` and `propertyDidChange` in
+                    succession.
+
+                    @method notifyPropertyChange
+                    @param {String} keyName The property key to be notified about.
+                    @return {Ember.Observable}
+                  */
+            notifyPropertyChange: function(keyName) {
+                this.propertyWillChange(keyName);
+                this.propertyDidChange(keyName);
+                return this;
+            },
+
+            addBeforeObserver: function(key, target, method) {
+                addBeforeObserver(this, key, target, method);
+            },
+
+            /**
+                    Adds an observer on a property.
+
+                    This is the core method used to register an observer for a property.
+
+                    Once you call this method, any time the key's value is set, your observer
+                    will be notified. Note that the observers are triggered any time the
+                    value is set, regardless of whether it has actually changed. Your
+                    observer should be prepared to handle that.
+
+                    You can also pass an optional context parameter to this method. The
+                    context will be passed to your observer method whenever it is triggered.
+                    Note that if you add the same target/method pair on a key multiple times
+                    with different context parameters, your observer will only be called once
+                    with the last context you passed.
+
+                    ### Observer Methods
+
+                    Observer methods you pass should generally have the following signature if
+                    you do not pass a `context` parameter:
+
+                    ```javascript
+                    fooDidChange: function(sender, key, value, rev) { };
+                    ```
+
+                    The sender is the object that changed. The key is the property that
+                    changes. The value property is currently reserved and unused. The rev
+                    is the last property revision of the object when it changed, which you can
+                    use to detect if the key value has really changed or not.
+
+                    If you pass a `context` parameter, the context will be passed before the
+                    revision like so:
+
+                    ```javascript
+                    fooDidChange: function(sender, key, value, context, rev) { };
+                    ```
+
+                    Usually you will not need the value, context or revision parameters at
+                    the end. In this case, it is common to write observer methods that take
+                    only a sender and key value as parameters or, if you aren't interested in
+                    any of these values, to write an observer that has no parameters at all.
+
+                    @method addObserver
+                    @param {String} key The key to observer
+                    @param {Object} target The target object to invoke
+                    @param {String|Function} method The method to invoke.
+                  */
+            addObserver: function(key, target, method) {
+                addObserver(this, key, target, method);
+            },
+
+            /**
+                    Remove an observer you have previously registered on this object. Pass
+                    the same key, target, and method you passed to `addObserver()` and your
+                    target will no longer receive notifications.
+
+                    @method removeObserver
+                    @param {String} key The key to observer
+                    @param {Object} target The target object to invoke
+                    @param {String|Function} method The method to invoke.
+                  */
+            removeObserver: function(key, target, method) {
+                removeObserver(this, key, target, method);
+            },
+
+            /**
+                    Returns `true` if the object currently has observers registered for a
+                    particular key. You can use this method to potentially defer performing
+                    an expensive action until someone begins observing a particular property
+                    on the object.
+
+                    @method hasObserverFor
+                    @param {String} key Key to check
+                    @return {Boolean}
+                  */
+            hasObserverFor: function(key) {
+                return hasListeners(this, key + ':change');
+            },
+
+            /**
+                    Retrieves the value of a property, or a default value in the case that the
+                    property returns `undefined`.
+
+                    ```javascript
+                    person.getWithDefault('lastName', 'Doe');
+                    ```
+
+                    @method getWithDefault
+                    @param {String} keyName The name of the property to retrieve
+                    @param {Object} defaultValue The value to return if the property value is undefined
+                    @return {Object} The property value or the defaultValue.
+                  */
+            getWithDefault: function(keyName, defaultValue) {
+                return getWithDefault(this, keyName, defaultValue);
+            },
+
+            /**
+                    Set the value of a property to the current value plus some amount.
+
+                    ```javascript
+                    person.incrementProperty('age');
+                    team.incrementProperty('score', 2);
+                    ```
+
+                    @method incrementProperty
+                    @param {String} keyName The name of the property to increment
+                    @param {Number} increment The amount to increment by. Defaults to 1
+                    @return {Number} The new property value
+                  */
+            incrementProperty: function(keyName, increment) {
+                if (isNone(increment)) {
+                    increment = 1;
+                }
+                Ember.assert(&quot;Must pass a numeric value to incrementProperty&quot;, (!isNaN(parseFloat(increment)) &amp;&amp; isFinite(increment)));
+                set(this, keyName, (parseFloat(get(this, keyName)) || 0) + increment);
+                return get(this, keyName);
+            },
+
+            /**
+                    Set the value of a property to the current value minus some amount.
+
+                    ```javascript
+                    player.decrementProperty('lives');
+                    orc.decrementProperty('health', 5);
+                    ```
+
+                    @method decrementProperty
+                    @param {String} keyName The name of the property to decrement
+                    @param {Number} decrement The amount to decrement by. Defaults to 1
+                    @return {Number} The new property value
+                  */
+            decrementProperty: function(keyName, decrement) {
+                if (isNone(decrement)) {
+                    decrement = 1;
+                }
+                Ember.assert(&quot;Must pass a numeric value to decrementProperty&quot;, (!isNaN(parseFloat(decrement)) &amp;&amp; isFinite(decrement)));
+                set(this, keyName, (get(this, keyName) || 0) - decrement);
+                return get(this, keyName);
+            },
+
+            /**
+                    Set the value of a boolean property to the opposite of it's
+                    current value.
+
+                    ```javascript
+                    starship.toggleProperty('warpDriveEngaged');
+                    ```
+
+                    @method toggleProperty
+                    @param {String} keyName The name of the property to toggle
+                    @return {Object} The new property value
+                  */
+            toggleProperty: function(keyName) {
+                set(this, keyName, !get(this, keyName));
+                return get(this, keyName);
+            },
+
+            /**
+                    Returns the cached value of a computed property, if it exists.
+                    This allows you to inspect the value of a computed property
+                    without accidentally invoking it if it is intended to be
+                    generated lazily.
+
+                    @method cacheFor
+                    @param {String} keyName
+                    @return {Object} The cached value of the computed property, if any
+                  */
+            cacheFor: function(keyName) {
+                return cacheFor(this, keyName);
+            },
+
+            // intended for debugging purposes
+            observersForKey: function(keyName) {
+                return observersFor(this, keyName);
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/promise_proxy&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var set = __dependency2__.set;
+        var computed = __dependency3__.computed;
+        var Mixin = __dependency4__.Mixin;
+        var EmberError = __dependency5__[&quot;default&quot;];
+
+        var not = computed.not;
+        var or = computed.or;
+
+        /**
+              @module ember
+              @submodule ember-runtime
+             */
+
+        function tap(proxy, promise) {
+            set(proxy, 'isFulfilled', false);
+            set(proxy, 'isRejected', false);
+
+            return promise.then(function(value) {
+                set(proxy, 'isFulfilled', true);
+                set(proxy, 'content', value);
+                return value;
+            }, function(reason) {
+                set(proxy, 'isRejected', true);
+                set(proxy, 'reason', reason);
+                throw reason;
+            }, &quot;Ember: PromiseProxy&quot;);
+        }
+
+        /**
+              A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware.
+
+              ```javascript
+              var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin);
+
+              var controller = ObjectPromiseController.create({
+                promise: $.getJSON('/some/remote/data.json')
+              });
+
+              controller.then(function(json){
+                 // the json
+              }, function(reason) {
+                 // the reason why you have no json
+              });
+              ```
+
+              the controller has bindable attributes which
+              track the promises life cycle
+
+              ```javascript
+              controller.get('isPending')   //=&gt; true
+              controller.get('isSettled')  //=&gt; false
+              controller.get('isRejected')  //=&gt; false
+              controller.get('isFulfilled') //=&gt; false
+              ```
+
+              When the the $.getJSON completes, and the promise is fulfilled
+              with json, the life cycle attributes will update accordingly.
+
+              ```javascript
+              controller.get('isPending')   //=&gt; false
+              controller.get('isSettled')   //=&gt; true
+              controller.get('isRejected')  //=&gt; false
+              controller.get('isFulfilled') //=&gt; true
+              ```
+
+              As the controller is an ObjectController, and the json now its content,
+              all the json properties will be available directly from the controller.
+
+              ```javascript
+              // Assuming the following json:
+              {
+                firstName: 'Stefan',
+                lastName: 'Penner'
+              }
+
+              // both properties will accessible on the controller
+              controller.get('firstName') //=&gt; 'Stefan'
+              controller.get('lastName')  //=&gt; 'Penner'
+              ```
+
+              If the controller is backing a template, the attributes are
+              bindable from within that template
+
+              ```handlebars
+              {{#if isPending}}
+                loading...
+              {{else}}
+                firstName: {{firstName}}
+                lastName: {{lastName}}
+              {{/if}}
+              ```
+              @class Ember.PromiseProxyMixin
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+            /**
+                    If the proxied promise is rejected this will contain the reason
+                    provided.
+
+                    @property reason
+                    @default null
+                  */
+            reason: null,
+
+            /**
+                    Once the proxied promise has settled this will become `false`.
+
+                    @property isPending
+                    @default true
+                  */
+            isPending: not('isSettled').readOnly(),
+
+            /**
+                    Once the proxied promise has settled this will become `true`.
+
+                    @property isSettled
+                    @default false
+                  */
+            isSettled: or('isRejected', 'isFulfilled').readOnly(),
+
+            /**
+                    Will become `true` if the proxied promise is rejected.
+
+                    @property isRejected
+                    @default false
+                  */
+            isRejected: false,
+
+            /**
+                    Will become `true` if the proxied promise is fulfilled.
+
+                    @property isFulfilled
+                    @default false
+                  */
+            isFulfilled: false,
+
+            /**
+                    The promise whose fulfillment value is being proxied by this object.
+
+                    This property must be specified upon creation, and should not be
+                    changed once created.
+
+                    Example:
+
+                    ```javascript
+                    Ember.ObjectController.extend(Ember.PromiseProxyMixin).create({
+                      promise: &lt;thenable&gt;
+                    });
+                    ```
+
+                    @property promise
+                  */
+            promise: computed(function(key, promise) {
+                if (arguments.length === 2) {
+                    return tap(this, promise);
+                } else {
+                    throw new EmberError(&quot;PromiseProxy's promise must be set&quot;);
+                }
+            }),
+
+            /**
+                    An alias to the proxied promise's `then`.
+
+                    See RSVP.Promise.then.
+
+                    @method then
+                    @param {Function} callback
+                    @return {RSVP.Promise}
+                  */
+            then: promiseAlias('then'),
+
+            /**
+                    An alias to the proxied promise's `catch`.
+
+                    See RSVP.Promise.catch.
+
+                    @method catch
+                    @param {Function} callback
+                    @return {RSVP.Promise}
+                    @since 1.3.0
+                  */
+            'catch': promiseAlias('catch'),
+
+            /**
+                    An alias to the proxied promise's `finally`.
+
+                    See RSVP.Promise.finally.
+
+                    @method finally
+                    @param {Function} callback
+                    @return {RSVP.Promise}
+                    @since 1.3.0
+                  */
+            'finally': promiseAlias('finally')
+        });
+
+        function promiseAlias(name) {
+            return function () {
+                var promise = get(this, 'promise');
+                return promise[name].apply(promise, arguments);
+            };
+        }
+    });
+    define(&quot;ember-runtime/mixins/sortable&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/mutable_enumerable&quot;, &quot;ember-runtime/compare&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/computed&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert, Ember.A
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var forEach = __dependency4__.forEach;
+        var Mixin = __dependency5__.Mixin;
+        var MutableEnumerable = __dependency6__[&quot;default&quot;];
+        var compare = __dependency7__[&quot;default&quot;];
+        var addObserver = __dependency8__.addObserver;
+        var removeObserver = __dependency8__.removeObserver;
+        var computed = __dependency9__.computed;
+        var beforeObserver = __dependency5__.beforeObserver;
+        var observer = __dependency5__.observer;
+        //ES6TODO: should we access these directly from their package or from how thier exposed in ember-metal?
+
+        /**
+              `Ember.SortableMixin` provides a standard interface for array proxies
+              to specify a sort order and maintain this sorting when objects are added,
+              removed, or updated without changing the implicit order of their underlying
+              modelarray:
+
+              ```javascript
+              songs = [
+                {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'},
+                {trackNumber: 2, title: 'Back in the U.S.S.R.'},
+                {trackNumber: 3, title: 'Glass Onion'},
+              ];
+
+              songsController = Ember.ArrayController.create({
+                model: songs,
+                sortProperties: ['trackNumber'],
+                sortAscending: true
+              });
+
+              songsController.get('firstObject');  // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
+
+              songsController.addObject({trackNumber: 1, title: 'Dear Prudence'});
+              songsController.get('firstObject');  // {trackNumber: 1, title: 'Dear Prudence'}
+              ```
+
+              If you add or remove the properties to sort by or change the sort direction the model
+              sort order will be automatically updated.
+
+              ```javascript
+              songsController.set('sortProperties', ['title']);
+              songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'}
+
+              songsController.toggleProperty('sortAscending');
+              songsController.get('firstObject'); // {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'}
+              ```
+
+              SortableMixin works by sorting the arrangedContent array, which is the array that
+              arrayProxy displays. Due to the fact that the underlying 'content' array is not changed, that
+              array will not display the sorted list:
+
+               ```javascript
+              songsController.get('content').get('firstObject'); // Returns the unsorted original content
+              songsController.get('firstObject'); // Returns the sorted content.
+              ```
+
+              Although the sorted content can also be accessed through the arrangedContent property,
+              it is preferable to use the proxied class and not the arrangedContent array directly.
+
+              @class SortableMixin
+              @namespace Ember
+              @uses Ember.MutableEnumerable
+            */
+        __exports__[&quot;default&quot;] = Mixin.create(MutableEnumerable, {
+
+            /**
+                    Specifies which properties dictate the arrangedContent's sort order.
+
+                    When specifying multiple properties the sorting will use properties
+                    from the `sortProperties` array prioritized from first to last.
+
+                    @property {Array} sortProperties
+                  */
+            sortProperties: null,
+
+            /**
+                    Specifies the arrangedContent's sort direction.
+                    Sorts the content in ascending order by default. Set to `false` to
+                    use descending order.
+
+                    @property {Boolean} sortAscending
+                    @default true
+                  */
+            sortAscending: true,
+
+            /**
+                    The function used to compare two values. You can override this if you
+                    want to do custom comparisons. Functions must be of the type expected by
+                    Array#sort, i.e.
+                      return 0 if the two parameters are equal,
+                      return a negative value if the first parameter is smaller than the second or
+                      return a positive value otherwise:
+
+                    ```javascript
+                    function(x,y) { // These are assumed to be integers
+                      if (x === y)
+                        return 0;
+                      return x &lt; y ? -1 : 1;
+                    }
+                    ```
+
+                    @property sortFunction
+                    @type {Function}
+                    @default Ember.compare
+                  */
+            sortFunction: compare,
+
+            orderBy: function(item1, item2) {
+                var result = 0,
+                sortProperties = get(this, 'sortProperties'),
+                sortAscending = get(this, 'sortAscending'),
+                sortFunction = get(this, 'sortFunction');
+
+                Ember.assert(&quot;you need to define `sortProperties`&quot;, !!sortProperties);
+
+                forEach(sortProperties, function(propertyName) {
+                    if (result === 0) {
+                        result = sortFunction.call(this, get(item1, propertyName), get(item2, propertyName));
+                        if ((result !== 0) &amp;&amp; !sortAscending) {
+                            result = (-1) * result;
+                        }
+                    }
+                }, this);
+
+                return result;
+            },
+
+            destroy: function() {
+                var content = get(this, 'content'),
+                sortProperties = get(this, 'sortProperties');
+
+                if (content &amp;&amp; sortProperties) {
+                    forEach(content, function(item) {
+                        forEach(sortProperties, function(sortProperty) {
+                            removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
+                        }, this);
+                    }, this);
+                }
+
+                return this._super();
+            },
+
+            isSorted: computed.notEmpty('sortProperties'),
+
+            /**
+                    Overrides the default arrangedContent from arrayProxy in order to sort by sortFunction.
+                    Also sets up observers for each sortProperty on each item in the content Array.
+
+                    @property arrangedContent
+                  */
+
+            arrangedContent: computed('content', 'sortProperties.@each', function(key, value) {
+                var content = get(this, 'content'),
+                isSorted = get(this, 'isSorted'),
+                sortProperties = get(this, 'sortProperties'),
+                self = this;
+
+                if (content &amp;&amp; isSorted) {
+                    content = content.slice();
+                    content.sort(function(item1, item2) {
+                        return self.orderBy(item1, item2);
+                    });
+                    forEach(content, function(item) {
+                        forEach(sortProperties, function(sortProperty) {
+                            addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
+                        }, this);
+                    }, this);
+                    return Ember.A(content);
+                }
+
+                return content;
+            }),
+
+            _contentWillChange: beforeObserver('content', function() {
+                var content = get(this, 'content'),
+                sortProperties = get(this, 'sortProperties');
+
+                if (content &amp;&amp; sortProperties) {
+                    forEach(content, function(item) {
+                        forEach(sortProperties, function(sortProperty) {
+                            removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
+                        }, this);
+                    }, this);
+                }
+
+                this._super();
+            }),
+
+            sortPropertiesWillChange: beforeObserver('sortProperties', function() {
+                this._lastSortAscending = undefined;
+            }),
+
+            sortPropertiesDidChange: observer('sortProperties', function() {
+                this._lastSortAscending = undefined;
+            }),
+
+            sortAscendingWillChange: beforeObserver('sortAscending', function() {
+                this._lastSortAscending = get(this, 'sortAscending');
+            }),
+
+            sortAscendingDidChange: observer('sortAscending', function() {
+                if (this._lastSortAscending !== undefined &amp;&amp; get(this, 'sortAscending') !== this._lastSortAscending) {
+                    var arrangedContent = get(this, 'arrangedContent');
+                    arrangedContent.reverseObjects();
+                }
+            }),
+
+            contentArrayWillChange: function(array, idx, removedCount, addedCount) {
+                var isSorted = get(this, 'isSorted');
+
+                if (isSorted) {
+                    var arrangedContent = get(this, 'arrangedContent');
+                    var removedObjects = array.slice(idx, idx + removedCount);
+                    var sortProperties = get(this, 'sortProperties');
+
+                    forEach(removedObjects, function(item) {
+                        arrangedContent.removeObject(item);
+
+                        forEach(sortProperties, function(sortProperty) {
+                            removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
+                        }, this);
+                    }, this);
+                }
+
+                return this._super(array, idx, removedCount, addedCount);
+            },
+
+            contentArrayDidChange: function(array, idx, removedCount, addedCount) {
+                var isSorted = get(this, 'isSorted'),
+                sortProperties = get(this, 'sortProperties');
+
+                if (isSorted) {
+                    var addedObjects = array.slice(idx, idx + addedCount);
+
+                    forEach(addedObjects, function(item) {
+                        this.insertItemSorted(item);
+
+                        forEach(sortProperties, function(sortProperty) {
+                            addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange');
+                        }, this);
+                    }, this);
+                }
+
+                return this._super(array, idx, removedCount, addedCount);
+            },
+
+            insertItemSorted: function(item) {
+                var arrangedContent = get(this, 'arrangedContent');
+                var length = get(arrangedContent, 'length');
+
+                var idx = this._binarySearch(item, 0, length);
+                arrangedContent.insertAt(idx, item);
+            },
+
+            contentItemSortPropertyDidChange: function(item) {
+                var arrangedContent = get(this, 'arrangedContent'),
+                oldIndex = arrangedContent.indexOf(item),
+                leftItem = arrangedContent.objectAt(oldIndex - 1),
+                rightItem = arrangedContent.objectAt(oldIndex + 1),
+                leftResult = leftItem &amp;&amp; this.orderBy(item, leftItem),
+                rightResult = rightItem &amp;&amp; this.orderBy(item, rightItem);
+
+                if (leftResult &lt; 0 || rightResult &gt; 0) {
+                    arrangedContent.removeObject(item);
+                    this.insertItemSorted(item);
+                }
+            },
+
+            _binarySearch: function(item, low, high) {
+                var mid, midItem, res, arrangedContent;
+
+                if (low === high) {
+                    return low;
+                }
+
+                arrangedContent = get(this, 'arrangedContent');
+
+                mid = low + Math.floor((high - low) / 2);
+                midItem = arrangedContent.objectAt(mid);
+
+                res = this.orderBy(midItem, item);
+
+                if (res &lt; 0) {
+                    return this._binarySearch(item, mid + 1, high);
+                } else if (res &gt; 0) {
+                    return this._binarySearch(item, low, mid);
+                }
+
+                return mid;
+            }
+        });
+    });
+    define(&quot;ember-runtime/mixins/target_action_support&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/computed&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.lookup, Ember.assert
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var typeOf = __dependency4__.typeOf;
+        var Mixin = __dependency5__.Mixin;
+        var computed = __dependency6__.computed;
+
+        /**
+            `Ember.TargetActionSupport` is a mixin that can be included in a class
+            to add a `triggerAction` method with semantics similar to the Handlebars
+            `{{action}}` helper. In normal Ember usage, the `{{action}}` helper is
+            usually the best choice. This mixin is most often useful when you are
+            doing more complex event handling in View objects.
+
+            See also `Ember.ViewTargetActionSupport`, which has
+            view-aware defaults for target and actionContext.
+
+            @class TargetActionSupport
+            @namespace Ember
+            @extends Ember.Mixin
+            */
+        var TargetActionSupport = Mixin.create({
+            target: null,
+            action: null,
+            actionContext: null,
+
+            targetObject: computed(function() {
+                var target = get(this, 'target');
+
+                if (typeOf(target) === &quot;string&quot;) {
+                    var value = get(this, target);
+                    if (value === undefined) {
+                        value = get(Ember.lookup, target);
+                    }
+                    return value;
+                } else {
+                    return target;
+                }
+            }).property('target'),
+
+            actionContextObject: computed(function() {
+                var actionContext = get(this, 'actionContext');
+
+                if (typeOf(actionContext) === &quot;string&quot;) {
+                    var value = get(this, actionContext);
+                    if (value === undefined) {
+                        value = get(Ember.lookup, actionContext);
+                    }
+                    return value;
+                } else {
+                    return actionContext;
+                }
+            }).property('actionContext'),
+
+            /**
+                  Send an `action` with an `actionContext` to a `target`. The action, actionContext
+                  and target will be retrieved from properties of the object. For example:
+
+                  ```javascript
+                  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
+                    target: Ember.computed.alias('controller'),
+                    action: 'save',
+                    actionContext: Ember.computed.alias('context'),
+                    click: function() {
+                      this.triggerAction(); // Sends the `save` action, along with the current context
+                                            // to the current controller
+                    }
+                  });
+                  ```
+
+                  The `target`, `action`, and `actionContext` can be provided as properties of
+                  an optional object argument to `triggerAction` as well.
+
+                  ```javascript
+                  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
+                    click: function() {
+                      this.triggerAction({
+                        action: 'save',
+                        target: this.get('controller'),
+                        actionContext: this.get('context')
+                      }); // Sends the `save` action, along with the current context
+                          // to the current controller
+                    }
+                  });
+                  ```
+
+                  The `actionContext` defaults to the object you are mixing `TargetActionSupport` into.
+                  But `target` and `action` must be specified either as properties or with the argument
+                  to `triggerAction`, or a combination:
+
+                  ```javascript
+                  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
+                    target: Ember.computed.alias('controller'),
+                    click: function() {
+                      this.triggerAction({
+                        action: 'save'
+                      }); // Sends the `save` action, along with a reference to `this`,
+                          // to the current controller
+                    }
+                  });
+                  ```
+
+                  @method triggerAction
+                  @param opts {Hash} (optional, with the optional keys action, target and/or actionContext)
+                  @return {Boolean} true if the action was sent successfully and did not return false
+                  */
+            triggerAction: function(opts) {
+                opts = opts || {};
+                var action = opts.action || get(this, 'action'),
+                target = opts.target || get(this, 'targetObject'),
+                actionContext = opts.actionContext;
+
+                function args(options, actionName) {
+                    var ret = [];
+                    if (actionName) {
+                        ret.push(actionName);
+                    }
+
+                    return ret.concat(options);
+                }
+
+                if (typeof actionContext === 'undefined') {
+                    actionContext = get(this, 'actionContextObject') || this;
+                }
+
+                if (target &amp;&amp; action) {
+                    var ret;
+
+                    if (target.send) {
+                        ret = target.send.apply(target, args(actionContext, action));
+                    } else {
+                        Ember.assert(&quot;The action '&quot; + action + &quot;' did not exist on &quot; + target, typeof target[action] === 'function');
+                        ret = target[action].apply(target, args(actionContext));
+                    }
+
+                    if (ret !== false) 
+                        ret = true;
+
+                    return ret;
+                } else {
+                    return false;
+                }
+            }
+        });
+
+        __exports__[&quot;default&quot;] = TargetActionSupport;
+    });
+    define(&quot;ember-runtime/system/application&quot;,
+    [&quot;ember-runtime/system/namespace&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var Namespace = __dependency1__[&quot;default&quot;];
+
+        __exports__[&quot;default&quot;] = Namespace.extend();
+    });
+    define(&quot;ember-runtime/system/array_proxy&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/error&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/mixins/mutable_array&quot;, &quot;ember-runtime/mixins/enumerable&quot;, &quot;ember-runtime/system/string&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.K, Ember.assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var isArray = __dependency4__.isArray;
+        var apply = __dependency4__.apply;
+        var computed = __dependency5__.computed;
+        var beforeObserver = __dependency6__.beforeObserver;
+        var observer = __dependency6__.observer;
+        var beginPropertyChanges = __dependency7__.beginPropertyChanges;
+        var endPropertyChanges = __dependency7__.endPropertyChanges;
+        var EmberError = __dependency8__[&quot;default&quot;];
+        var EmberObject = __dependency9__[&quot;default&quot;];
+        var MutableArray = __dependency10__[&quot;default&quot;];
+        var Enumerable = __dependency11__[&quot;default&quot;];
+        var fmt = __dependency12__.fmt;
+
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var OUT_OF_RANGE_EXCEPTION = &quot;Index out of range&quot;;
+        var EMPTY = [];
+        var alias = computed.alias;
+        var K = Ember.K;
+
+        /**
+              An ArrayProxy wraps any other object that implements `Ember.Array` and/or
+              `Ember.MutableArray,` forwarding all requests. This makes it very useful for
+              a number of binding use cases or other cases where being able to swap
+              out the underlying array is useful.
+
+              A simple example of usage:
+
+              ```javascript
+              var pets = ['dog', 'cat', 'fish'];
+              var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) });
+
+              ap.get('firstObject');                        // 'dog'
+              ap.set('content', ['amoeba', 'paramecium']);
+              ap.get('firstObject');                        // 'amoeba'
+              ```
+
+              This class can also be useful as a layer to transform the contents of
+              an array, as they are accessed. This can be done by overriding
+              `objectAtContent`:
+
+              ```javascript
+              var pets = ['dog', 'cat', 'fish'];
+              var ap = Ember.ArrayProxy.create({
+                  content: Ember.A(pets),
+                  objectAtContent: function(idx) {
+                      return this.get('content').objectAt(idx).toUpperCase();
+                  }
+              });
+
+              ap.get('firstObject'); // . 'DOG'
+              ```
+
+              @class ArrayProxy
+              @namespace Ember
+              @extends Ember.Object
+              @uses Ember.MutableArray
+            */
+        var ArrayProxy = EmberObject.extend(MutableArray, {
+
+            /**
+                    The content array. Must be an object that implements `Ember.Array` and/or
+                    `Ember.MutableArray.`
+
+                    @property content
+                    @type Ember.Array
+                  */
+            content: null,
+
+            /**
+                   The array that the proxy pretends to be. In the default `ArrayProxy`
+                   implementation, this and `content` are the same. Subclasses of `ArrayProxy`
+                   can override this property to provide things like sorting and filtering.
+
+                   @property arrangedContent
+                  */
+            arrangedContent: alias('content'),
+
+            /**
+                    Should actually retrieve the object at the specified index from the
+                    content. You can override this method in subclasses to transform the
+                    content item to something new.
+
+                    This method will only be called if content is non-`null`.
+
+                    @method objectAtContent
+                    @param {Number} idx The index to retrieve.
+                    @return {Object} the value or undefined if none found
+                  */
+            objectAtContent: function(idx) {
+                return get(this, 'arrangedContent').objectAt(idx);
+            },
+
+            /**
+                    Should actually replace the specified objects on the content array.
+                    You can override this method in subclasses to transform the content item
+                    into something new.
+
+                    This method will only be called if content is non-`null`.
+
+                    @method replaceContent
+                    @param {Number} idx The starting index
+                    @param {Number} amt The number of items to remove from the content.
+                    @param {Array} objects Optional array of objects to insert or null if no
+                      objects.
+                    @return {void}
+                  */
+            replaceContent: function(idx, amt, objects) {
+                get(this, 'content').replace(idx, amt, objects);
+            },
+
+            /**
+                    Invoked when the content property is about to change. Notifies observers that the
+                    entire array content will change.
+
+                    @private
+                    @method _contentWillChange
+                  */
+            _contentWillChange: beforeObserver('content', function() {
+                this._teardownContent();
+            }),
+
+            _teardownContent: function() {
+                var content = get(this, 'content');
+
+                if (content) {
+                    content.removeArrayObserver(this, {
+                        willChange: 'contentArrayWillChange',
+                        didChange: 'contentArrayDidChange'
+                    });
+                }
+            },
+
+            contentArrayWillChange: K,
+            contentArrayDidChange: K,
+
+            /**
+                    Invoked when the content property changes. Notifies observers that the
+                    entire array content has changed.
+
+                    @private
+                    @method _contentDidChange
+                  */
+            _contentDidChange: observer('content', function() {
+                var content = get(this, 'content');
+
+                Ember.assert(&quot;Can't set ArrayProxy's content to itself&quot;, content !== this);
+
+                this._setupContent();
+            }),
+
+            _setupContent: function() {
+                var content = get(this, 'content');
+
+                if (content) {
+                    Ember.assert(fmt('ArrayProxy expects an Array or ' +
+                    'Ember.ArrayProxy, but you passed %@', [typeof content]),
+                    isArray(content) || content.isDestroyed);
+
+                    content.addArrayObserver(this, {
+                        willChange: 'contentArrayWillChange',
+                        didChange: 'contentArrayDidChange'
+                    });
+                }
+            },
+
+            _arrangedContentWillChange: beforeObserver('arrangedContent', function() {
+                var arrangedContent = get(this, 'arrangedContent'),
+                len = arrangedContent ? get(arrangedContent, 'length') : 0;
+
+                this.arrangedContentArrayWillChange(this, 0, len, undefined);
+                this.arrangedContentWillChange(this);
+
+                this._teardownArrangedContent(arrangedContent);
+            }),
+
+            _arrangedContentDidChange: observer('arrangedContent', function() {
+                var arrangedContent = get(this, 'arrangedContent'),
+                len = arrangedContent ? get(arrangedContent, 'length') : 0;
+
+                Ember.assert(&quot;Can't set ArrayProxy's content to itself&quot;, arrangedContent !== this);
+
+                this._setupArrangedContent();
+
+                this.arrangedContentDidChange(this);
+                this.arrangedContentArrayDidChange(this, 0, undefined, len);
+            }),
+
+            _setupArrangedContent: function() {
+                var arrangedContent = get(this, 'arrangedContent');
+
+                if (arrangedContent) {
+                    Ember.assert(fmt('ArrayProxy expects an Array or ' +
+                    'Ember.ArrayProxy, but you passed %@', [typeof arrangedContent]),
+                    isArray(arrangedContent) || arrangedContent.isDestroyed);
+
+                    arrangedContent.addArrayObserver(this, {
+                        willChange: 'arrangedContentArrayWillChange',
+                        didChange: 'arrangedContentArrayDidChange'
+                    });
+                }
+            },
+
+            _teardownArrangedContent: function() {
+                var arrangedContent = get(this, 'arrangedContent');
+
+                if (arrangedContent) {
+                    arrangedContent.removeArrayObserver(this, {
+                        willChange: 'arrangedContentArrayWillChange',
+                        didChange: 'arrangedContentArrayDidChange'
+                    });
+                }
+            },
+
+            arrangedContentWillChange: K,
+            arrangedContentDidChange: K,
+
+            objectAt: function(idx) {
+                return get(this, 'content') &amp;&amp; this.objectAtContent(idx);
+            },
+
+            length: computed(function() {
+                var arrangedContent = get(this, 'arrangedContent');
+                return arrangedContent ? get(arrangedContent, 'length') : 0;
+                // No dependencies since Enumerable notifies length of change
+            }),
+
+            _replace: function(idx, amt, objects) {
+                var content = get(this, 'content');
+                Ember.assert('The content property of ' + this.constructor + ' should be set before modifying it', content);
+                if (content) 
+                    this.replaceContent(idx, amt, objects);
+                return this;
+            },
+
+            replace: function() {
+                if (get(this, 'arrangedContent') === get(this, 'content')) {
+                    apply(this, this._replace, arguments);
+                } else {
+                    throw new EmberError(&quot;Using replace on an arranged ArrayProxy is not allowed.&quot;);
+                }
+            },
+
+            _insertAt: function(idx, object) {
+                if (idx &gt; get(this, 'content.length')) 
+                    throw new EmberError(OUT_OF_RANGE_EXCEPTION);
+                this._replace(idx, 0, [object]);
+                return this;
+            },
+
+            insertAt: function(idx, object) {
+                if (get(this, 'arrangedContent') === get(this, 'content')) {
+                    return this._insertAt(idx, object);
+                } else {
+                    throw new EmberError(&quot;Using insertAt on an arranged ArrayProxy is not allowed.&quot;);
+                }
+            },
+
+            removeAt: function(start, len) {
+                if ('number' === typeof start) {
+                    var content = get(this, 'content'),
+                    arrangedContent = get(this, 'arrangedContent'),
+                    indices = [], i;
+
+                    if ((start &lt; 0) || (start &gt;= get(this, 'length'))) {
+                        throw new EmberError(OUT_OF_RANGE_EXCEPTION);
+                    }
+
+                    if (len === undefined) 
+                        len = 1;
+
+                    // Get a list of indices in original content to remove
+                    for (i = start; i &lt; start + len; i++) {
+                        // Use arrangedContent here so we avoid confusion with objects transformed by objectAtContent
+                        indices.push(content.indexOf(arrangedContent.objectAt(i)));
+                    }
+
+                    // Replace in reverse order since indices will change
+                    indices.sort(function(a, b) {
+                        return b - a;
+                    });
+
+                    beginPropertyChanges();
+                    for (i = 0; i &lt; indices.length; i++) {
+                        this._replace(indices[i], 1, EMPTY);
+                    }
+                    endPropertyChanges();
+                }
+
+                return this ;
+            },
+
+            pushObject: function(obj) {
+                this._insertAt(get(this, 'content.length'), obj) ;
+                return obj ;
+            },
+
+            pushObjects: function(objects) {
+                if (!(Enumerable.detect(objects) || isArray(objects))) {
+                    throw new TypeError(&quot;Must pass Ember.Enumerable to Ember.MutableArray#pushObjects&quot;);
+                }
+                this._replace(get(this, 'length'), 0, objects);
+                return this;
+            },
+
+            setObjects: function(objects) {
+                if (objects.length === 0) 
+                    return this.clear();
+
+                var len = get(this, 'length');
+                this._replace(0, len, objects);
+                return this;
+            },
+
+            unshiftObject: function(obj) {
+                this._insertAt(0, obj) ;
+                return obj ;
+            },
+
+            unshiftObjects: function(objects) {
+                this._replace(0, 0, objects);
+                return this;
+            },
+
+            slice: function() {
+                var arr = this.toArray();
+                return arr.slice.apply(arr, arguments);
+            },
+
+            arrangedContentArrayWillChange: function(item, idx, removedCnt, addedCnt) {
+                this.arrayContentWillChange(idx, removedCnt, addedCnt);
+            },
+
+            arrangedContentArrayDidChange: function(item, idx, removedCnt, addedCnt) {
+                this.arrayContentDidChange(idx, removedCnt, addedCnt);
+            },
+
+            init: function() {
+                this._super();
+                this._setupContent();
+                this._setupArrangedContent();
+            },
+
+            willDestroy: function() {
+                this._teardownArrangedContent();
+                this._teardownContent();
+            }
+        });
+
+        __exports__[&quot;default&quot;] = ArrayProxy;
+    });
+    define(&quot;ember-runtime/system/container&quot;,
+    [&quot;ember-metal/property_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var set = __dependency1__[&quot;default&quot;];
+
+        var Container = requireModule('container')[&quot;default&quot;];
+        Container.set = set;
+
+        __exports__[&quot;default&quot;] = Container;
+    });
+    define(&quot;ember-runtime/system/core_object&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/watching&quot;, &quot;ember-metal/chains&quot;, &quot;ember-metal/events&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/error&quot;, &quot;ember-runtime/keys&quot;, &quot;ember-runtime/mixins/action_handler&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/binding&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/run_loop&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+              @module ember
+              @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.ENV.MANDATORY_SETTER, Ember.assert, Ember.K, Ember.config
+
+        // NOTE: this object should never be included directly. Instead use `Ember.Object`.
+        // We only define this separately so that `Ember.Set` can depend on it.
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var guidFor = __dependency4__.guidFor;
+        var apply = __dependency4__.apply;
+        var o_create = __dependency5__.create;
+        var generateGuid = __dependency4__.generateGuid;
+        var GUID_KEY = __dependency4__.GUID_KEY;
+        var meta = __dependency4__.meta;
+        var META_KEY = __dependency4__.META_KEY;
+        var makeArray = __dependency4__.makeArray;
+        var rewatch = __dependency6__.rewatch;
+        var finishChains = __dependency7__.finishChains;
+        var sendEvent = __dependency8__.sendEvent;
+        var IS_BINDING = __dependency9__.IS_BINDING;
+        var Mixin = __dependency9__.Mixin;
+        var required = __dependency9__.required;
+        var indexOf = __dependency10__.indexOf;
+        var EmberError = __dependency11__[&quot;default&quot;];
+        var platform = __dependency5__.platform;
+        var keys = __dependency12__[&quot;default&quot;];
+        var ActionHandler = __dependency13__[&quot;default&quot;];
+        var defineProperty = __dependency14__.defineProperty;
+        var Binding = __dependency15__.Binding;
+        var ComputedProperty = __dependency16__.ComputedProperty;
+        var run = __dependency17__[&quot;default&quot;];
+        var destroy = __dependency6__.destroy;
+
+        var K = __dependency1__.K;
+        var o_defineProperty = platform.defineProperty;
+        var schedule = run.schedule;
+        var applyMixin = Mixin._apply;
+        var finishPartial = Mixin.finishPartial;
+        var reopen = Mixin.prototype.reopen;
+        var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
+        var hasCachedComputedProperties = false;
+
+        var undefinedDescriptor = {
+            configurable: true,
+            writable: true,
+            enumerable: false,
+            value: undefined
+        };
+
+        var nullDescriptor = {
+            configurable: true,
+            writable: true,
+            enumerable: false,
+            value: null
+        };
+
+        function makeCtor() {
+
+            // Note: avoid accessing any properties on the object since it makes the
+            // method a lot faster. This is glue code so we want it to be as fast as
+            // possible.
+
+            var wasApplied = false, initMixins, initProperties;
+
+            var Class = function() {
+                if (!wasApplied) {
+                    Class.proto(); // prepare prototype...
+                }
+                o_defineProperty(this, GUID_KEY, nullDescriptor);
+                o_defineProperty(this, '__nextSuper', undefinedDescriptor);
+                var m = meta(this), proto = m.proto;
+                m.proto = this;
+                if (initMixins) {
+                    // capture locally so we can clear the closed over variable
+                    var mixins = initMixins;
+                    initMixins = null;
+                    apply(this, this.reopen, mixins);
+                }
+                if (initProperties) {
+                    // capture locally so we can clear the closed over variable
+                    var props = initProperties;
+                    initProperties = null;
+
+                    var concatenatedProperties = this.concatenatedProperties;
+
+                    for (var i = 0, l = props.length; i &lt; l; i++) {
+                        var properties = props[i];
+
+                        Ember.assert(&quot;Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.&quot;, !(properties instanceof Mixin));
+
+                        if (typeof properties !== 'object' &amp;&amp; properties !== undefined) {
+                            throw new EmberError(&quot;Ember.Object.create only accepts objects.&quot;);
+                        }
+
+                        if (!properties) {
+                            continue;
+                        }
+
+                        var keyNames = keys(properties);
+
+                        for (var j = 0, ll = keyNames.length; j &lt; ll; j++) {
+                            var keyName = keyNames[j];
+                            if (!properties.hasOwnProperty(keyName)) {
+                                continue;
+                            }
+
+                            var value = properties[keyName];
+
+                            if (IS_BINDING.test(keyName)) {
+                                var bindings = m.bindings;
+                                if (!bindings) {
+                                    bindings = m.bindings = {};
+                                } else if (!m.hasOwnProperty('bindings')) {
+                                    bindings = m.bindings = o_create(m.bindings);
+                                }
+                                bindings[keyName] = value;
+                            }
+
+                            var desc = m.descs[keyName];
+
+                            Ember.assert(&quot;Ember.Object.create no longer supports defining computed properties. Define computed properties using extend() or reopen() before calling create().&quot;, !(value instanceof ComputedProperty));
+                            Ember.assert(&quot;Ember.Object.create no longer supports defining methods that call _super.&quot;, !(typeof value === 'function' &amp;&amp; value.toString().indexOf('._super') !== -1));
+                            Ember.assert(&quot;`actions` must be provided at extend time, not at create &quot; +
+                            &quot;time, when Ember.ActionHandler is used (i.e. views, &quot; +
+                            &quot;controllers &amp; routes).&quot;, !((keyName === 'actions') &amp;&amp; ActionHandler.detect(this)));
+
+                            if (concatenatedProperties &amp;&amp; indexOf(concatenatedProperties, keyName) &gt;= 0) {
+                                var baseValue = this[keyName];
+
+                                if (baseValue) {
+                                    if ('function' === typeof baseValue.concat) {
+                                        value = baseValue.concat(value);
+                                    } else {
+                                        value = makeArray(baseValue).concat(value);
+                                    }
+                                } else {
+                                    value = makeArray(value);
+                                }
+                            }
+
+                            if (desc) {
+                                desc.set(this, keyName, value);
+                            } else {
+                                if (typeof this.setUnknownProperty === 'function' &amp;&amp; !(keyName in this)) {
+                                    this.setUnknownProperty(keyName, value);
+                                } else if (MANDATORY_SETTER) {
+                                    defineProperty(this, keyName, null, value); // setup mandatory setter
+                                } else {
+                                    this[keyName] = value;
+                                }
+                            }
+                        }
+                    }
+                }
+                finishPartial(this, m);
+                apply(this, this.init, arguments);
+                m.proto = proto;
+                finishChains(this);
+                sendEvent(this, &quot;init&quot;);
+            };
+
+            Class.toString = Mixin.prototype.toString;
+            Class.willReopen = function() {
+                if (wasApplied) {
+                    Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin);
+                }
+
+                wasApplied = false;
+            };
+            Class._initMixins = function(args) {
+                initMixins = args;
+            };
+            Class._initProperties = function(args) {
+                initProperties = args;
+            };
+
+            Class.proto = function() {
+                var superclass = Class.superclass;
+                if (superclass) {
+                    superclass.proto();
+                }
+
+                if (!wasApplied) {
+                    wasApplied = true;
+                    Class.PrototypeMixin.applyPartial(Class.prototype);
+                    rewatch(Class.prototype);
+                }
+
+                return this.prototype;
+            };
+
+            return Class;
+
+        }
+
+        /**
+              @class CoreObject
+              @namespace Ember
+            */
+        var CoreObject = makeCtor();
+        CoreObject.toString = function() {
+            return &quot;Ember.CoreObject&quot;;
+        };
+
+        CoreObject.PrototypeMixin = Mixin.create({
+            reopen: function() {
+                applyMixin(this, arguments, true);
+                return this;
+            },
+
+            /**
+                    An overridable method called when objects are instantiated. By default,
+                    does nothing unless it is overridden during class definition.
+
+                    Example:
+
+                    ```javascript
+                    App.Person = Ember.Object.extend({
+                      init: function() {
+                        alert('Name is ' + this.get('name'));
+                      }
+                    });
+
+                    var steve = App.Person.create({
+                      name: &quot;Steve&quot;
+                    });
+
+                    // alerts 'Name is Steve'.
+                    ```
+
+                    NOTE: If you do override `init` for a framework class like `Ember.View` or
+                    `Ember.ArrayController`, be sure to call `this._super()` in your
+                    `init` declaration! If you don't, Ember may not have an opportunity to
+                    do important setup work, and you'll see strange behavior in your
+                    application.
+
+                    @method init
+                  */
+            init: function() {},
+
+            /**
+                    Defines the properties that will be concatenated from the superclass
+                    (instead of overridden).
+
+                    By default, when you extend an Ember class a property defined in
+                    the subclass overrides a property with the same name that is defined
+                    in the superclass. However, there are some cases where it is preferable
+                    to build up a property's value by combining the superclass' property
+                    value with the subclass' value. An example of this in use within Ember
+                    is the `classNames` property of `Ember.View`.
+
+                    Here is some sample code showing the difference between a concatenated
+                    property and a normal one:
+
+                    ```javascript
+                    App.BarView = Ember.View.extend({
+                      someNonConcatenatedProperty: ['bar'],
+                      classNames: ['bar']
+                    });
+
+                    App.FooBarView = App.BarView.extend({
+                      someNonConcatenatedProperty: ['foo'],
+                      classNames: ['foo']
+                    });
+
+                    var fooBarView = App.FooBarView.create();
+                    fooBarView.get('someNonConcatenatedProperty'); // ['foo']
+                    fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo']
+                    ```
+
+                    This behavior extends to object creation as well. Continuing the
+                    above example:
+
+                    ```javascript
+                    var view = App.FooBarView.create({
+                      someNonConcatenatedProperty: ['baz'],
+                      classNames: ['baz']
+                    })
+                    view.get('someNonConcatenatedProperty'); // ['baz']
+                    view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
+                    ```
+                    Adding a single property that is not an array will just add it in the array:
+
+                    ```javascript
+                    var view = App.FooBarView.create({
+                      classNames: 'baz'
+                    })
+                    view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz']
+                    ```
+
+                    Using the `concatenatedProperties` property, we can tell to Ember that mix
+                    the content of the properties.
+
+                    In `Ember.View` the `classNameBindings` and `attributeBindings` properties
+                    are also concatenated, in addition to `classNames`.
+
+                    This feature is available for you to use throughout the Ember object model,
+                    although typical app developers are likely to use it infrequently. Since
+                    it changes expectations about behavior of properties, you should properly
+                    document its usage in each individual concatenated property (to not
+                    mislead your users to think they can override the property in a subclass).
+
+                    @property concatenatedProperties
+                    @type Array
+                    @default null
+                  */
+            concatenatedProperties: null,
+
+            /**
+                    Destroyed object property flag.
+
+                    if this property is `true` the observers and bindings were already
+                    removed by the effect of calling the `destroy()` method.
+
+                    @property isDestroyed
+                    @default false
+                  */
+            isDestroyed: false,
+
+            /**
+                    Destruction scheduled flag. The `destroy()` method has been called.
+
+                    The object stays intact until the end of the run loop at which point
+                    the `isDestroyed` flag is set.
+
+                    @property isDestroying
+                    @default false
+                  */
+            isDestroying: false,
+
+            /**
+                    Destroys an object by setting the `isDestroyed` flag and removing its
+                    metadata, which effectively destroys observers and bindings.
+
+                    If you try to set a property on a destroyed object, an exception will be
+                    raised.
+
+                    Note that destruction is scheduled for the end of the run loop and does not
+                    happen immediately.  It will set an isDestroying flag immediately.
+
+                    @method destroy
+                    @return {Ember.Object} receiver
+                  */
+            destroy: function() {
+                if (this.isDestroying) {
+                    return;
+                }
+                this.isDestroying = true;
+
+                schedule('actions', this, this.willDestroy);
+                schedule('destroy', this, this._scheduledDestroy);
+                return this;
+            },
+
+            /**
+                    Override to implement teardown.
+
+                    @method willDestroy
+                   */
+            willDestroy: K,
+
+            /**
+                    Invoked by the run loop to actually destroy the object. This is
+                    scheduled for execution by the `destroy` method.
+
+                    @private
+                    @method _scheduledDestroy
+                  */
+            _scheduledDestroy: function() {
+                if (this.isDestroyed) {
+                    return;
+                }
+                destroy(this);
+                this.isDestroyed = true;
+            },
+
+            bind: function(to, from) {
+                if (!(from instanceof Binding)) {
+                    from = Binding.from(from);
+                }
+                from.to(to).connect(this);
+                return from;
+            },
+
+            /**
+                    Returns a string representation which attempts to provide more information
+                    than Javascript's `toString` typically does, in a generic way for all Ember
+                    objects.
+
+                    ```javascript
+                    App.Person = Em.Object.extend()
+                    person = App.Person.create()
+                    person.toString() //=&gt; &quot;&lt;App.Person:ember1024&gt;&quot;
+                    ```
+
+                    If the object's class is not defined on an Ember namespace, it will
+                    indicate it is a subclass of the registered superclass:
+
+                   ```javascript
+                    Student = App.Person.extend()
+                    student = Student.create()
+                    student.toString() //=&gt; &quot;&lt;(subclass of App.Person):ember1025&gt;&quot;
+                    ```
+
+                    If the method `toStringExtension` is defined, its return value will be
+                    included in the output.
+
+                    ```javascript
+                    App.Teacher = App.Person.extend({
+                      toStringExtension: function() {
+                        return this.get('fullName');
+                      }
+                    });
+                    teacher = App.Teacher.create()
+                    teacher.toString(); //=&gt; &quot;&lt;App.Teacher:ember1026:Tom Dale&gt;&quot;
+                    ```
+
+                    @method toString
+                    @return {String} string representation
+                  */
+            toString: function toString() {
+                var hasToStringExtension = typeof this.toStringExtension === 'function',
+                extension = hasToStringExtension ? &quot;:&quot; + this.toStringExtension() : '';
+                var ret = '&lt;' + this.constructor.toString() + ':' + guidFor(this) + extension + '&gt;';
+                this.toString = makeToString(ret);
+                return ret;
+            }
+        });
+
+        CoreObject.PrototypeMixin.ownerConstructor = CoreObject;
+
+        function makeToString(ret) {
+            return function() {
+                return ret;
+            };
+        }
+
+        if (Ember.config.overridePrototypeMixin) {
+            Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin);
+        }
+
+        CoreObject.__super__ = null;
+
+        var ClassMixin = Mixin.create({
+
+            ClassMixin: required(),
+
+            PrototypeMixin: required(),
+
+            isClass: true,
+
+            isMethod: false,
+
+            /**
+                    Creates a new subclass.
+
+                    ```javascript
+                    App.Person = Ember.Object.extend({
+                      say: function(thing) {
+                        alert(thing);
+                       }
+                    });
+                    ```
+
+                    This defines a new subclass of Ember.Object: `App.Person`. It contains one method: `say()`.
+
+                    You can also create a subclass from any existing class by calling its `extend()`  method. For example, you might want to create a subclass of Ember's built-in `Ember.View` class:
+
+                    ```javascript
+                    App.PersonView = Ember.View.extend({
+                      tagName: 'li',
+                      classNameBindings: ['isAdministrator']
+                    });
+                    ```
+
+                    When defining a subclass, you can override methods but still access the implementation of your parent class by calling the special `_super()` method:
+
+                    ```javascript
+                    App.Person = Ember.Object.extend({
+                      say: function(thing) {
+                        var name = this.get('name');
+                        alert(name + ' says: ' + thing);
+                      }
+                    });
+
+                    App.Soldier = App.Person.extend({
+                      say: function(thing) {
+                        this._super(thing + &quot;, sir!&quot;);
+                      },
+                      march: function(numberOfHours) {
+                        alert(this.get('name') + ' marches for ' + numberOfHours + ' hours.')
+                      }
+                    });
+
+                    var yehuda = App.Soldier.create({
+                      name: &quot;Yehuda Katz&quot;
+                    });
+
+                    yehuda.say(&quot;Yes&quot;);  // alerts &quot;Yehuda Katz says: Yes, sir!&quot;
+                    ```
+
+                    The `create()` on line #17 creates an *instance* of the `App.Soldier` class. The `extend()` on line #8 creates a *subclass* of `App.Person`. Any instance of the `App.Person` class will *not* have the `march()` method.
+
+                    You can also pass `Mixin` classes to add additional properties to the subclass.
+
+                    ```javascript
+                    App.Person = Ember.Object.extend({
+                      say: function(thing) {
+                        alert(this.get('name') + ' says: ' + thing);
+                      }
+                    });
+
+                    App.SingingMixin = Mixin.create({
+                      sing: function(thing){
+                        alert(this.get('name') + ' sings: la la la ' + thing);
+                      }
+                    });
+
+                    App.BroadwayStar = App.Person.extend(App.SingingMixin, {
+                      dance: function() {
+                        alert(this.get('name') + ' dances: tap tap tap tap ');
+                      }
+                    });
+                    ```
+
+                    The `App.BroadwayStar` class contains three methods: `say()`, `sing()`, and `dance()`.
+
+                    @method extend
+                    @static
+
+                    @param {Mixin} [mixins]* One or more Mixin classes
+                    @param {Object} [arguments]* Object containing values to use within the new class
+                  */
+            extend: function() {
+                var Class = makeCtor(), proto;
+                Class.ClassMixin = Mixin.create(this.ClassMixin);
+                Class.PrototypeMixin = Mixin.create(this.PrototypeMixin);
+
+                Class.ClassMixin.ownerConstructor = Class;
+                Class.PrototypeMixin.ownerConstructor = Class;
+
+                reopen.apply(Class.PrototypeMixin, arguments);
+
+                Class.superclass = this;
+                Class.__super__ = this.prototype;
+
+                proto = Class.prototype = o_create(this.prototype);
+                proto.constructor = Class;
+                generateGuid(proto);
+                meta(proto).proto = proto; // this will disable observers on prototype
+
+                Class.ClassMixin.apply(Class);
+                return Class;
+            },
+
+            /**
+                    Equivalent to doing `extend(arguments).create()`.
+                    If possible use the normal `create` method instead.
+
+                    @method createWithMixins
+                    @static
+                    @param [arguments]*
+                  */
+            createWithMixins: function() {
+                var C = this;
+                if (arguments.length &gt; 0) {
+                    this._initMixins(arguments);
+                }
+                return new C();
+            },
+
+            /**
+                    Creates an instance of a class. Accepts either no arguments, or an object
+                    containing values to initialize the newly instantiated object with.
+
+                    ```javascript
+                    App.Person = Ember.Object.extend({
+                      helloWorld: function() {
+                        alert(&quot;Hi, my name is &quot; + this.get('name'));
+                      }
+                    });
+
+                    var tom = App.Person.create({
+                      name: 'Tom Dale'
+                    });
+
+                    tom.helloWorld(); // alerts &quot;Hi, my name is Tom Dale&quot;.
+                    ```
+
+                    `create` will call the `init` function if defined during
+                    `Ember.AnyObject.extend`
+
+                    If no arguments are passed to `create`, it will not set values to the new
+                    instance during initialization:
+
+                    ```javascript
+                    var noName = App.Person.create();
+                    noName.helloWorld(); // alerts undefined
+                    ```
+
+                    NOTE: For performance reasons, you cannot declare methods or computed
+                    properties during `create`. You should instead declare methods and computed
+                    properties when using `extend` or use the `createWithMixins` shorthand.
+
+                    @method create
+                    @static
+                    @param [arguments]*
+                  */
+            create: function() {
+                var C = this;
+                if (arguments.length &gt; 0) {
+                    this._initProperties(arguments);
+                }
+                return new C();
+            },
+
+            /**
+                    Augments a constructor's prototype with additional
+                    properties and functions:
+
+                    ```javascript
+                    MyObject = Ember.Object.extend({
+                      name: 'an object'
+                    });
+
+                    o = MyObject.create();
+                    o.get('name'); // 'an object'
+
+                    MyObject.reopen({
+                      say: function(msg){
+                        console.log(msg);
+                      }
+                    })
+
+                    o2 = MyObject.create();
+                    o2.say(&quot;hello&quot;); // logs &quot;hello&quot;
+
+                    o.say(&quot;goodbye&quot;); // logs &quot;goodbye&quot;
+                    ```
+
+                    To add functions and properties to the constructor itself,
+                    see `reopenClass`
+
+                    @method reopen
+                  */
+            reopen: function() {
+                this.willReopen();
+                apply(this.PrototypeMixin, reopen, arguments);
+                return this;
+            },
+
+            /**
+                    Augments a constructor's own properties and functions:
+
+                    ```javascript
+                    MyObject = Ember.Object.extend({
+                      name: 'an object'
+                    });
+
+                    MyObject.reopenClass({
+                      canBuild: false
+                    });
+
+                    MyObject.canBuild; // false
+                    o = MyObject.create();
+                    ```
+
+                    In other words, this creates static properties and functions for the class. These are only available on the class
+                    and not on any instance of that class.
+
+                    ```javascript
+                    App.Person = Ember.Object.extend({
+                      name : &quot;&quot;,
+                      sayHello : function(){
+                        alert(&quot;Hello. My name is &quot; + this.get('name'));
+                      }
+                    });
+
+                    App.Person.reopenClass({
+                      species : &quot;Homo sapiens&quot;,
+                      createPerson: function(newPersonsName){
+                        return App.Person.create({
+                          name:newPersonsName
+                        });
+                      }
+                    });
+
+                    var tom = App.Person.create({
+                      name : &quot;Tom Dale&quot;
+                    });
+                    var yehuda = App.Person.createPerson(&quot;Yehuda Katz&quot;);
+
+                    tom.sayHello(); // &quot;Hello. My name is Tom Dale&quot;
+                    yehuda.sayHello(); // &quot;Hello. My name is Yehuda Katz&quot;
+                    alert(App.Person.species); // &quot;Homo sapiens&quot;
+                    ```
+
+                    Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda`
+                    variables. They are only valid on `App.Person`.
+
+                    To add functions and properties to instances of
+                    a constructor by extending the constructor's prototype
+                    see `reopen`
+
+                    @method reopenClass
+                  */
+            reopenClass: function() {
+                apply(this.ClassMixin, reopen, arguments);
+                applyMixin(this, arguments, false);
+                return this;
+            },
+
+            detect: function(obj) {
+                if ('function' !== typeof obj) {
+                    return false;
+                }
+                while (obj) {
+                    if (obj === this) {
+                        return true;
+                    }
+                    obj = obj.superclass;
+                }
+                return false;
+            },
+
+            detectInstance: function(obj) {
+                return obj instanceof this;
+            },
+
+            /**
+                    In some cases, you may want to annotate computed properties with additional
+                    metadata about how they function or what values they operate on. For
+                    example, computed property functions may close over variables that are then
+                    no longer available for introspection.
+
+                    You can pass a hash of these values to a computed property like this:
+
+                    ```javascript
+                    person: function() {
+                      var personId = this.get('personId');
+                      return App.Person.create({ id: personId });
+                    }.property().meta({ type: App.Person })
+                    ```
+
+                    Once you've done this, you can retrieve the values saved to the computed
+                    property from your class like this:
+
+                    ```javascript
+                    MyClass.metaForProperty('person');
+                    ```
+
+                    This will return the original hash that was passed to `meta()`.
+
+                    @method metaForProperty
+                    @param key {String} property name
+                  */
+            metaForProperty: function(key) {
+                var meta = this.proto()[META_KEY],
+                desc = meta &amp;&amp; meta.descs[key];
+
+                Ember.assert(&quot;metaForProperty() could not find a computed property with key '&quot; + key + &quot;'.&quot;, !!desc &amp;&amp; desc instanceof ComputedProperty);
+                return desc._meta || {};
+            },
+
+            _computedProperties: Ember.computed(function() {
+                hasCachedComputedProperties = true;
+                var proto = this.proto();
+                var descs = meta(proto).descs;
+                var property;
+                var properties = [];
+
+                for (var name in descs) {
+                    property = descs[name];
+
+                    if (property instanceof ComputedProperty) {
+                        properties.push({
+                            name: name,
+                            meta: property._meta
+                        });
+                    }
+                }
+                return properties;
+            }).readOnly(),
+
+            /**
+                    Iterate over each computed property for the class, passing its name
+                    and any associated metadata (see `metaForProperty`) to the callback.
+
+                    @method eachComputedProperty
+                    @param {Function} callback
+                    @param {Object} binding
+                  */
+            eachComputedProperty: function(callback, binding) {
+                var property, name;
+                var empty = {};
+
+                var properties = get(this, '_computedProperties');
+
+                for (var i = 0, length = properties.length; i &lt; length; i++) {
+                    property = properties[i];
+                    name = property.name;
+                    callback.call(binding || this, property.name, property.meta || empty);
+                }
+            }
+        });
+
+        ClassMixin.ownerConstructor = CoreObject;
+
+        if (Ember.config.overrideClassMixin) {
+            Ember.config.overrideClassMixin(ClassMixin);
+        }
+
+        CoreObject.ClassMixin = ClassMixin;
+
+        ClassMixin.apply(CoreObject);
+
+        CoreObject.reopen({
+            didDefineProperty: function(proto, key, value) {
+                if (hasCachedComputedProperties === false) {
+                    return;
+                }
+                if (value instanceof Ember.ComputedProperty) {
+                    var cache = Ember.meta(this.constructor).cache;
+
+                    if (cache._computedProperties !== undefined) {
+                        cache._computedProperties = undefined;
+                    }
+                }
+
+                this._super();
+            }
+        });
+
+
+        __exports__[&quot;default&quot;] = CoreObject;
+    });
+    define(&quot;ember-runtime/system/deferred&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/mixins/deferred&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var DeferredMixin = __dependency2__[&quot;default&quot;];
+        var get = __dependency3__.get;
+        var EmberObject = __dependency4__[&quot;default&quot;];
+
+        var Deferred = EmberObject.extend(DeferredMixin, {
+            init: function() {
+                Ember.deprecate('Usage of Ember.Deferred is deprecated.');
+                this._super();
+            }
+        });
+
+        Deferred.reopenClass({
+            promise: function(callback, binding) {
+                var deferred = Deferred.create();
+                callback.call(binding, deferred);
+                return deferred;
+            }
+        });
+
+        __exports__[&quot;default&quot;] = Deferred;
+    });
+    define(&quot;ember-runtime/system/each_proxy&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/array&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/events&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/property_events&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var guidFor = __dependency4__.guidFor;
+        var forEach = __dependency5__.forEach;
+        var indexOf = __dependency6__.indexOf;
+        var EmberArray = __dependency7__[&quot;default&quot;];
+        // ES6TODO: WAT? Circular dep?
+        var EmberObject = __dependency8__[&quot;default&quot;];
+        var computed = __dependency9__.computed;
+        var addObserver = __dependency10__.addObserver;
+        var addBeforeObserver = __dependency10__.addBeforeObserver;
+        var removeBeforeObserver = __dependency10__.removeBeforeObserver;
+        var removeObserver = __dependency10__.removeObserver;
+        var typeOf = __dependency4__.typeOf;
+        var watchedEvents = __dependency11__.watchedEvents;
+        var defineProperty = __dependency12__.defineProperty;
+        var beginPropertyChanges = __dependency13__.beginPropertyChanges;
+        var propertyDidChange = __dependency13__.propertyDidChange;
+        var propertyWillChange = __dependency13__.propertyWillChange;
+        var endPropertyChanges = __dependency13__.endPropertyChanges;
+        var changeProperties = __dependency13__.changeProperties;
+
+        var EachArray = EmberObject.extend(EmberArray, {
+
+            init: function(content, keyName, owner) {
+                this._super();
+                this._keyName = keyName;
+                this._owner = owner;
+                this._content = content;
+            },
+
+            objectAt: function(idx) {
+                var item = this._content.objectAt(idx);
+                return item &amp;&amp; get(item, this._keyName);
+            },
+
+            length: computed(function() {
+                var content = this._content;
+                return content ? get(content, 'length') : 0;
+            })
+        });
+
+        var IS_OBSERVER = /^.+:(before|change)$/;
+
+        function addObserverForContentKey(content, keyName, proxy, idx, loc) {
+            var objects = proxy._objects, guid;
+            if (!objects) 
+                objects = proxy._objects = {};
+
+            while (--loc &gt;= idx) {
+                var item = content.objectAt(loc);
+                if (item) {
+                    Ember.assert('When using @each to observe the array ' + content + ', the array must return an object', typeOf(item) === 'instance' || typeOf(item) === 'object');
+                    addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
+                    addObserver(item, keyName, proxy, 'contentKeyDidChange');
+
+                    // keep track of the index each item was found at so we can map
+                    // it back when the obj changes.
+                    guid = guidFor(item);
+                    if (!objects[guid]) 
+                        objects[guid] = [];
+                    objects[guid].push(loc);
+                }
+            }
+        }
+
+        function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
+            var objects = proxy._objects;
+            if (!objects) 
+                objects = proxy._objects = {};
+            var indicies, guid;
+
+            while (--loc &gt;= idx) {
+                var item = content.objectAt(loc);
+                if (item) {
+                    removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
+                    removeObserver(item, keyName, proxy, 'contentKeyDidChange');
+
+                    guid = guidFor(item);
+                    indicies = objects[guid];
+                    indicies[indexOf.call(indicies, loc)] = null;
+                }
+            }
+        }
+
+        /**
+              This is the object instance returned when you get the `@each` property on an
+              array. It uses the unknownProperty handler to automatically create
+              EachArray instances for property names.
+
+              @private
+              @class EachProxy
+              @namespace Ember
+              @extends Ember.Object
+            */
+        var EachProxy = EmberObject.extend({
+
+            init: function(content) {
+                this._super();
+                this._content = content;
+                content.addArrayObserver(this);
+
+                // in case someone is already observing some keys make sure they are
+                // added
+                forEach(watchedEvents(this), function(eventName) {
+                    this.didAddListener(eventName);
+                }, this);
+            },
+
+            /**
+                    You can directly access mapped properties by simply requesting them.
+                    The `unknownProperty` handler will generate an EachArray of each item.
+
+                    @method unknownProperty
+                    @param keyName {String}
+                    @param value {*}
+                  */
+            unknownProperty: function(keyName, value) {
+                var ret;
+                ret = new EachArray(this._content, keyName, this);
+                defineProperty(this, keyName, null, ret);
+                this.beginObservingContentKey(keyName);
+                return ret;
+            },
+
+            // ..........................................................
+            // ARRAY CHANGES
+            // Invokes whenever the content array itself changes.
+
+            arrayWillChange: function(content, idx, removedCnt, addedCnt) {
+                var keys = this._keys, key, lim;
+
+                lim = removedCnt &gt; 0 ? idx + removedCnt : -1;
+                beginPropertyChanges(this);
+
+                for (key in keys) {
+                    if (!keys.hasOwnProperty(key)) {
+                        continue;
+                    }
+
+                    if (lim &gt; 0) {
+                        removeObserverForContentKey(content, key, this, idx, lim);
+                    }
+
+                    propertyWillChange(this, key);
+                }
+
+                propertyWillChange(this._content, '@each');
+                endPropertyChanges(this);
+            },
+
+            arrayDidChange: function(content, idx, removedCnt, addedCnt) {
+                var keys = this._keys, lim;
+
+                lim = addedCnt &gt; 0 ? idx + addedCnt : -1;
+                changeProperties(function() {
+                    for (var key in keys) {
+                        if (!keys.hasOwnProperty(key)) {
+                            continue;
+                        }
+
+                        if (lim &gt; 0) {
+                            addObserverForContentKey(content, key, this, idx, lim);
+                        }
+
+                        propertyDidChange(this, key);
+                    }
+
+                    propertyDidChange(this._content, '@each');
+                }, this);
+            },
+
+            // ..........................................................
+            // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
+            // Start monitoring keys based on who is listening...
+
+            didAddListener: function(eventName) {
+                if (IS_OBSERVER.test(eventName)) {
+                    this.beginObservingContentKey(eventName.slice(0, -7));
+                }
+            },
+
+            didRemoveListener: function(eventName) {
+                if (IS_OBSERVER.test(eventName)) {
+                    this.stopObservingContentKey(eventName.slice(0, -7));
+                }
+            },
+
+            // ..........................................................
+            // CONTENT KEY OBSERVING
+            // Actual watch keys on the source content.
+
+            beginObservingContentKey: function(keyName) {
+                var keys = this._keys;
+                if (!keys) 
+                    keys = this._keys = {};
+                if (!keys[keyName]) {
+                    keys[keyName] = 1;
+                    var content = this._content,
+                    len = get(content, 'length');
+                    addObserverForContentKey(content, keyName, this, 0, len);
+                } else {
+                    keys[keyName]++;
+                }
+            },
+
+            stopObservingContentKey: function(keyName) {
+                var keys = this._keys;
+                if (keys &amp;&amp; (keys[keyName] &gt; 0) &amp;&amp; (--keys[keyName] &lt;= 0)) {
+                    var content = this._content,
+                    len = get(content, 'length');
+                    removeObserverForContentKey(content, keyName, this, 0, len);
+                }
+            },
+
+            contentKeyWillChange: function(obj, keyName) {
+                propertyWillChange(this, keyName);
+            },
+
+            contentKeyDidChange: function(obj, keyName) {
+                propertyDidChange(this, keyName);
+            }
+        });
+
+        __exports__.EachArray = EachArray;
+        __exports__.EachProxy = EachProxy;
+    });
+    define(&quot;ember-runtime/system/lazy_load&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/array&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        /*globals CustomEvent */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.ENV.EMBER_LOAD_HOOKS
+        var forEach = __dependency2__.forEach;
+        // make sure Ember.A is setup.
+
+        /**
+              @module ember
+              @submodule ember-runtime
+            */
+
+        var loadHooks = Ember.ENV.EMBER_LOAD_HOOKS || {};
+        var loaded = {};
+
+        /**
+              Detects when a specific package of Ember (e.g. 'Ember.Handlebars')
+              has fully loaded and is available for extension.
+
+              The provided `callback` will be called with the `name` passed
+              resolved from a string into the object:
+
+              ``` javascript
+              Ember.onLoad('Ember.Handlebars' function(hbars) {
+                hbars.registerHelper(...);
+              });
+              ```
+
+              @method onLoad
+              @for Ember
+              @param name {String} name of hook
+              @param callback {Function} callback to be called
+            */
+        function onLoad(name, callback) {
+            var object;
+
+            loadHooks[name] = loadHooks[name] || Ember.A();
+            loadHooks[name].pushObject(callback);
+
+            if (object = loaded[name]) {
+                callback(object);
+            }
+        }
+
+        __exports__.onLoad = onLoad; /**
+              Called when an Ember.js package (e.g Ember.Handlebars) has finished
+              loading. Triggers any callbacks registered for this event.
+
+              @method runLoadHooks
+              @for Ember
+              @param name {String} name of hook
+              @param object {Object} object to pass to callbacks
+            */
+        function runLoadHooks(name, object) {
+            loaded[name] = object;
+
+            if (typeof window === 'object' &amp;&amp; typeof window.dispatchEvent === 'function' &amp;&amp; typeof CustomEvent === &quot;function&quot;) {
+                var event = new CustomEvent(name, {
+                    detail: object,
+                    name: name
+                });
+                window.dispatchEvent(event);
+            }
+
+            if (loadHooks[name]) {
+                forEach.call(loadHooks[name], function(callback) {
+                    callback(object);
+                });
+            }
+        }
+
+        __exports__.runLoadHooks = runLoadHooks;
+    });
+    define(&quot;ember-runtime/system/namespace&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/array&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        // Ember.lookup, Ember.BOOTED, Ember.deprecate, Ember.NAME_KEY, Ember.anyUnprocessedMixins
+        var Ember = __dependency1__[&quot;default&quot;];
+        var get = __dependency2__.get;
+        var indexOf = __dependency3__.indexOf;
+        var GUID_KEY = __dependency4__.GUID_KEY;
+        var guidFor = __dependency4__.guidFor;
+        var Mixin = __dependency5__.Mixin;
+
+        var EmberObject = __dependency6__[&quot;default&quot;];
+
+        /**
+              A Namespace is an object usually used to contain other objects or methods
+              such as an application or framework. Create a namespace anytime you want
+              to define one of these new containers.
+
+              # Example Usage
+
+              ```javascript
+              MyFramework = Ember.Namespace.create({
+                VERSION: '1.0.0'
+              });
+              ```
+
+              @class Namespace
+              @namespace Ember
+              @extends Ember.Object
+            */
+        var Namespace = EmberObject.extend({
+            isNamespace: true,
+
+            init: function() {
+                Namespace.NAMESPACES.push(this);
+                Namespace.PROCESSED = false;
+            },
+
+            toString: function() {
+                var name = get(this, 'name');
+                if (name) {
+                    return name;
+                }
+
+                findNamespaces();
+                return this[NAME_KEY];
+            },
+
+            nameClasses: function() {
+                processNamespace([this.toString()], this, {});
+            },
+
+            destroy: function() {
+                var namespaces = Namespace.NAMESPACES,
+                toString = this.toString();
+
+                if (toString) {
+                    Ember.lookup[toString] = undefined;
+                    delete Namespace.NAMESPACES_BY_ID[toString];
+                }
+                namespaces.splice(indexOf.call(namespaces, this), 1);
+                this._super();
+            }
+        });
+
+        Namespace.reopenClass({
+            NAMESPACES: [Ember],
+            NAMESPACES_BY_ID: {},
+            PROCESSED: false,
+            processAll: processAllNamespaces,
+            byName: function(name) {
+                if (!Ember.BOOTED) {
+                    processAllNamespaces();
+                }
+
+                return NAMESPACES_BY_ID[name];
+            }
+        });
+
+        var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID;
+
+        var hasOwnProp = ({}).hasOwnProperty;
+
+        function processNamespace(paths, root, seen) {
+            var idx = paths.length;
+
+            NAMESPACES_BY_ID[paths.join('.')] = root;
+
+            // Loop over all of the keys in the namespace, looking for classes
+            for (var key in root) {
+                if (!hasOwnProp.call(root, key)) {
+                    continue;
+                }
+                var obj = root[key];
+
+                // If we are processing the `Ember` namespace, for example, the
+                // `paths` will start with `[&quot;Ember&quot;]`. Every iteration through
+                // the loop will update the **second** element of this list with
+                // the key, so processing `Ember.View` will make the Array
+                // `['Ember', 'View']`.
+                paths[idx] = key;
+
+                // If we have found an unprocessed class
+                if (obj &amp;&amp; obj.toString === classToString) {
+                    // Replace the class' `toString` with the dot-separated path
+                    // and set its `NAME_KEY`
+                    obj.toString = makeToString(paths.join('.'));
+                    obj[NAME_KEY] = paths.join('.');
+
+                    // Support nested namespaces
+                } else if (obj &amp;&amp; obj.isNamespace) {
+                    // Skip aliased namespaces
+                    if (seen[guidFor(obj)]) {
+                        continue;
+                    }
+                    seen[guidFor(obj)] = true;
+
+                    // Process the child namespace
+                    processNamespace(paths, obj, seen);
+                }
+            }
+
+            paths.length = idx; // cut out last item
+        }
+
+        var STARTS_WITH_UPPERCASE = /^[A-Z]/;
+
+        function tryIsNamespace(lookup, prop) {
+            try {
+                var obj = lookup[prop];
+                return obj &amp;&amp; obj.isNamespace &amp;&amp; obj;
+            } catch (e) {
+                // continue
+            }
+        }
+
+        function findNamespaces() {
+            var lookup = Ember.lookup, obj, isNamespace;
+
+            if (Namespace.PROCESSED) {
+                return;
+            }
+
+            for (var prop in lookup) {
+                // Only process entities that start with uppercase A-Z
+                if (!STARTS_WITH_UPPERCASE.test(prop)) {
+                    continue;
+                }
+
+                // Unfortunately, some versions of IE don't support window.hasOwnProperty
+                if (lookup.hasOwnProperty &amp;&amp; !lookup.hasOwnProperty(prop)) {
+                    continue;
+                }
+
+                // At times we are not allowed to access certain properties for security reasons.
+                // There are also times where even if we can access them, we are not allowed to access their properties.
+                obj = tryIsNamespace(lookup, prop);
+                if (obj) {
+                    obj[NAME_KEY] = prop;
+                }
+            }
+        }
+
+        var NAME_KEY = Ember.NAME_KEY = GUID_KEY + '_name';
+
+        function superClassString(mixin) {
+            var superclass = mixin.superclass;
+            if (superclass) {
+                if (superclass[NAME_KEY]) {
+                    return superclass[NAME_KEY];
+                } else {
+                    return superClassString(superclass);
+                }
+            } else {
+                return;
+            }
+        }
+
+        function classToString() {
+            if (!Ember.BOOTED &amp;&amp; !this[NAME_KEY]) {
+                processAllNamespaces();
+            }
+
+            var ret;
+
+            if (this[NAME_KEY]) {
+                ret = this[NAME_KEY];
+            } else if (this._toString) {
+                ret = this._toString;
+            } else {
+                var str = superClassString(this);
+                if (str) {
+                    ret = &quot;(subclass of &quot; + str + &quot;)&quot;;
+                } else {
+                    ret = &quot;(unknown mixin)&quot;;
+                }
+                this.toString = makeToString(ret);
+            }
+
+            return ret;
+        }
+
+        function processAllNamespaces() {
+            var unprocessedNamespaces = !Namespace.PROCESSED,
+            unprocessedMixins = Ember.anyUnprocessedMixins;
+
+            if (unprocessedNamespaces) {
+                findNamespaces();
+                Namespace.PROCESSED = true;
+            }
+
+            if (unprocessedNamespaces || unprocessedMixins) {
+                var namespaces = Namespace.NAMESPACES, namespace;
+                for (var i = 0, l = namespaces.length; i &lt; l; i++) {
+                    namespace = namespaces[i];
+                    processNamespace([namespace.toString()], namespace, {});
+                }
+
+                Ember.anyUnprocessedMixins = false;
+            }
+        }
+
+        function makeToString(ret) {
+            return function() {
+                return ret;
+            };
+        }
+
+        Mixin.prototype.toString = classToString; // ES6TODO: altering imported objects. SBB.
+
+        __exports__[&quot;default&quot;] = Namespace;
+    });
+    define(&quot;ember-runtime/system/native_array&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;ember-runtime/mixins/mutable_array&quot;, &quot;ember-runtime/mixins/observable&quot;, &quot;ember-runtime/mixins/copyable&quot;, &quot;ember-runtime/mixins/freezable&quot;, &quot;ember-runtime/copy&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.EXTEND_PROTOTYPES
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var replace = __dependency4__._replace;
+        var forEach = __dependency4__.forEach;
+        var Mixin = __dependency5__.Mixin;
+        var EmberArray = __dependency6__[&quot;default&quot;];
+        var MutableArray = __dependency7__[&quot;default&quot;];
+        var Observable = __dependency8__[&quot;default&quot;];
+        var Copyable = __dependency9__[&quot;default&quot;];
+        var FROZEN_ERROR = __dependency10__.FROZEN_ERROR;
+        var copy = __dependency11__[&quot;default&quot;];
+
+        // Add Ember.Array to Array.prototype. Remove methods with native
+        // implementations and supply some more optimized versions of generic methods
+        // because they are so common.
+
+        /**
+              The NativeArray mixin contains the properties needed to to make the native
+              Array support Ember.MutableArray and all of its dependent APIs. Unless you
+              have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` set to
+              false, this will be applied automatically. Otherwise you can apply the mixin
+              at anytime by calling `Ember.NativeArray.activate`.
+
+              @class NativeArray
+              @namespace Ember
+              @uses Ember.MutableArray
+              @uses Ember.Observable
+              @uses Ember.Copyable
+            */
+        var NativeArray = Mixin.create(MutableArray, Observable, Copyable, {
+
+            // because length is a built-in property we need to know to just get the
+            // original property.
+            get: function(key) {
+                if (key === 'length') 
+                    return this.length;
+                else if ('number' === typeof key) 
+                    return this[key];
+                else 
+                    return this._super(key);
+            },
+
+            objectAt: function(idx) {
+                return this[idx];
+            },
+
+            // primitive for array support.
+            replace: function(idx, amt, objects) {
+
+                if (this.isFrozen) 
+                    throw FROZEN_ERROR;
+
+                // if we replaced exactly the same number of items, then pass only the
+                // replaced range. Otherwise, pass the full remaining array length
+                // since everything has shifted
+                var len = objects ? get(objects, 'length') : 0;
+                this.arrayContentWillChange(idx, amt, len);
+
+                if (len === 0) {
+                    this.splice(idx, amt);
+                } else {
+                    replace(this, idx, amt, objects);
+                }
+
+                this.arrayContentDidChange(idx, amt, len);
+                return this;
+            },
+
+            // If you ask for an unknown property, then try to collect the value
+            // from member items.
+            unknownProperty: function(key, value) {
+                var ret; // = this.reducedProperty(key, value) ;
+                if ((value !== undefined) &amp;&amp; ret === undefined) {
+                    ret = this[key] = value;
+                }
+                return ret ;
+            },
+
+            // If browser did not implement indexOf natively, then override with
+            // specialized version
+            indexOf: function(object, startAt) {
+                var idx, len = this.length;
+
+                if (startAt === undefined) 
+                    startAt = 0;
+                else 
+                    startAt = (startAt &lt; 0) ? Math.ceil(startAt) : Math.floor(startAt);
+                if (startAt &lt; 0) 
+                    startAt += len;
+
+                for (idx = startAt; idx &lt; len; idx++) {
+                    if (this[idx] === object) 
+                        return idx ;
+                }
+                return -1;
+            },
+
+            lastIndexOf: function(object, startAt) {
+                var idx, len = this.length;
+
+                if (startAt === undefined) 
+                    startAt = len-1;
+                else 
+                    startAt = (startAt &lt; 0) ? Math.ceil(startAt) : Math.floor(startAt);
+                if (startAt &lt; 0) 
+                    startAt += len;
+
+                for (idx = startAt; idx &gt;= 0; idx--) {
+                    if (this[idx] === object) 
+                        return idx ;
+                }
+                return -1;
+            },
+
+            copy: function(deep) {
+                if (deep) {
+                    return this.map(function(item) {
+                        return copy(item, true);
+                    });
+                }
+
+                return this.slice();
+            }
+        });
+
+        // Remove any methods implemented natively so we don't override them
+        var ignore = ['length'];
+        forEach(NativeArray.keys(), function(methodName) {
+            if (Array.prototype[methodName]) 
+                ignore.push(methodName);
+        });
+
+        if (ignore.length &gt; 0) {
+            NativeArray = NativeArray.without.apply(NativeArray, ignore);
+        }
+
+        /**
+              Creates an `Ember.NativeArray` from an Array like object.
+              Does not modify the original object. Ember.A is not needed if
+              `Ember.EXTEND_PROTOTYPES` is `true` (the default value). However,
+              it is recommended that you use Ember.A when creating addons for
+              ember or when you can not guarantee that `Ember.EXTEND_PROTOTYPES`
+              will be `true`.
+
+              Example
+
+              ```js
+              var Pagination = Ember.CollectionView.extend({
+                tagName: 'ul',
+                classNames: ['pagination'],
+
+                init: function() {
+                  this._super();
+                  if (!this.get('content')) {
+                    this.set('content', Ember.A());
+                  }
+                }
+              });
+              ```
+
+              @method A
+              @for Ember
+              @return {Ember.NativeArray}
+            */
+        var A = function(arr) {
+            if (arr === undefined) {
+                arr = [];
+            }
+            return EmberArray.detect(arr) ? arr : NativeArray.apply(arr);
+        };
+
+        /**
+              Activates the mixin on the Array.prototype if not already applied. Calling
+              this method more than once is safe. This will be called when ember is loaded
+              unless you have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array`
+              set to `false`.
+
+              Example
+
+              ```js
+              if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
+                Ember.NativeArray.activate();
+              }
+              ```
+
+              @method activate
+              @for Ember.NativeArray
+              @static
+              @return {void}
+            */
+        NativeArray.activate = function() {
+            NativeArray.apply(Array.prototype);
+
+            A = function(arr) {
+                return arr || [];
+            };
+        };
+
+        if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
+            NativeArray.activate();
+        }
+
+        Ember.A = A; // ES6TODO: Setting A onto the object returned by ember-metal/core to avoid circles
+        __exports__.A = A;
+        __exports__.NativeArray = NativeArray;
+        __exports__[&quot;default&quot;] = NativeArray;
+    });
+    define(&quot;ember-runtime/system/object&quot;,
+    [&quot;ember-runtime/system/core_object&quot;, &quot;ember-runtime/mixins/observable&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+
+        var CoreObject = __dependency1__[&quot;default&quot;];
+        var Observable = __dependency2__[&quot;default&quot;];
+
+        /**
+              `Ember.Object` is the main base class for all Ember objects. It is a subclass
+              of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details,
+              see the documentation for each of these.
+
+              @class Object
+              @namespace Ember
+              @extends Ember.CoreObject
+              @uses Ember.Observable
+            */
+        var EmberObject = CoreObject.extend(Observable);
+        EmberObject.toString = function() {
+            return &quot;Ember.Object&quot;;
+        };
+
+        __exports__[&quot;default&quot;] = EmberObject;
+    });
+    define(&quot;ember-runtime/system/object_proxy&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var meta = __dependency4__.meta;
+        var addObserver = __dependency5__.addObserver;
+        var removeObserver = __dependency5__.removeObserver;
+        var addBeforeObserver = __dependency5__.addBeforeObserver;
+        var removeBeforeObserver = __dependency5__.removeBeforeObserver;
+        var propertyWillChange = __dependency6__.propertyWillChange;
+        var propertyDidChange = __dependency6__.propertyDidChange;
+        var computed = __dependency7__.computed;
+        var defineProperty = __dependency8__.defineProperty;
+        var observer = __dependency9__.observer;
+        var fmt = __dependency10__.fmt;
+        var EmberObject = __dependency11__[&quot;default&quot;];
+
+        function contentPropertyWillChange(content, contentKey) {
+            var key = contentKey.slice(8); // remove &quot;content.&quot;
+            if (key in this) {
+                return;
+            }
+            // if shadowed in proxy
+            propertyWillChange(this, key);
+        }
+
+        function contentPropertyDidChange(content, contentKey) {
+            var key = contentKey.slice(8); // remove &quot;content.&quot;
+            if (key in this) {
+                return;
+            }
+            // if shadowed in proxy
+            propertyDidChange(this, key);
+        }
+
+        /**
+              `Ember.ObjectProxy` forwards all properties not defined by the proxy itself
+              to a proxied `content` object.
+
+              ```javascript
+              object = Ember.Object.create({
+                name: 'Foo'
+              });
+
+              proxy = Ember.ObjectProxy.create({
+                content: object
+              });
+
+              // Access and change existing properties
+              proxy.get('name')          // 'Foo'
+              proxy.set('name', 'Bar');
+              object.get('name')         // 'Bar'
+
+              // Create new 'description' property on `object`
+              proxy.set('description', 'Foo is a whizboo baz');
+              object.get('description')  // 'Foo is a whizboo baz'
+              ```
+
+              While `content` is unset, setting a property to be delegated will throw an
+              Error.
+
+              ```javascript
+              proxy = Ember.ObjectProxy.create({
+                content: null,
+                flag: null
+              });
+              proxy.set('flag', true);
+              proxy.get('flag');         // true
+              proxy.get('foo');          // undefined
+              proxy.set('foo', 'data');  // throws Error
+              ```
+
+              Delegated properties can be bound to and will change when content is updated.
+
+              Computed properties on the proxy itself can depend on delegated properties.
+
+              ```javascript
+              ProxyWithComputedProperty = Ember.ObjectProxy.extend({
+                fullName: function () {
+                  var firstName = this.get('firstName'),
+                      lastName = this.get('lastName');
+                  if (firstName &amp;&amp; lastName) {
+                    return firstName + ' ' + lastName;
+                  }
+                  return firstName || lastName;
+                }.property('firstName', 'lastName')
+              });
+
+              proxy = ProxyWithComputedProperty.create();
+
+              proxy.get('fullName');  // undefined
+              proxy.set('content', {
+                firstName: 'Tom', lastName: 'Dale'
+              }); // triggers property change for fullName on proxy
+
+              proxy.get('fullName');  // 'Tom Dale'
+              ```
+
+              @class ObjectProxy
+              @namespace Ember
+              @extends Ember.Object
+            */
+        var ObjectProxy = EmberObject.extend({
+            /**
+                    The object whose properties will be forwarded.
+
+                    @property content
+                    @type Ember.Object
+                    @default null
+                  */
+            content: null,
+            _contentDidChange: observer('content', function() {
+                Ember.assert(&quot;Can't set ObjectProxy's content to itself&quot;, get(this, 'content') !== this);
+            }),
+
+            isTruthy: computed.bool('content'),
+
+            _debugContainerKey: null,
+
+            willWatchProperty: function (key) {
+                var contentKey = 'content.' + key;
+                addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
+                addObserver(this, contentKey, null, contentPropertyDidChange);
+            },
+
+            didUnwatchProperty: function (key) {
+                var contentKey = 'content.' + key;
+                removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
+                removeObserver(this, contentKey, null, contentPropertyDidChange);
+            },
+
+            unknownProperty: function (key) {
+                var content = get(this, 'content');
+                if (content) {
+                    return get(content, key);
+                }
+            },
+
+            setUnknownProperty: function (key, value) {
+                var m = meta(this);
+                if (m.proto === this) {
+                    // if marked as prototype then just defineProperty
+                    // rather than delegate
+                    defineProperty(this, key, null, value);
+                    return value;
+                }
+
+                var content = get(this, 'content');
+                Ember.assert(fmt(&quot;Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.&quot;, [key, value, this]), content);
+                return set(content, key, value);
+            }
+
+        });
+
+        __exports__[&quot;default&quot;] = ObjectProxy;
+    });
+    define(&quot;ember-runtime/system/set&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/core_object&quot;, &quot;ember-runtime/mixins/mutable_enumerable&quot;, &quot;ember-runtime/mixins/enumerable&quot;, &quot;ember-runtime/mixins/copyable&quot;, &quot;ember-runtime/mixins/freezable&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/computed&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.isNone
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var guidFor = __dependency4__.guidFor;
+        var isNone = __dependency5__.isNone;
+        var fmt = __dependency6__.fmt;
+        var CoreObject = __dependency7__[&quot;default&quot;];
+        var MutableEnumerable = __dependency8__[&quot;default&quot;];
+        var Enumerable = __dependency9__[&quot;default&quot;];
+        var Copyable = __dependency10__[&quot;default&quot;];
+        var Freezable = __dependency11__.Freezable;
+        var FROZEN_ERROR = __dependency11__.FROZEN_ERROR;
+        var EmberError = __dependency12__[&quot;default&quot;];
+        var propertyWillChange = __dependency13__.propertyWillChange;
+        var propertyDidChange = __dependency13__.propertyDidChange;
+        var aliasMethod = __dependency14__.aliasMethod;
+        var computed = __dependency15__.computed;
+
+        /**
+              An unordered collection of objects.
+
+              A Set works a bit like an array except that its items are not ordered. You
+              can create a set to efficiently test for membership for an object. You can
+              also iterate through a set just like an array, even accessing objects by
+              index, however there is no guarantee as to their order.
+
+              All Sets are observable via the Enumerable Observer API - which works
+              on any enumerable object including both Sets and Arrays.
+
+              ## Creating a Set
+
+              You can create a set like you would most objects using
+              `new Ember.Set()`. Most new sets you create will be empty, but you can
+              also initialize the set with some content by passing an array or other
+              enumerable of objects to the constructor.
+
+              Finally, you can pass in an existing set and the set will be copied. You
+              can also create a copy of a set by calling `Ember.Set#copy()`.
+
+              ```javascript
+              // creates a new empty set
+              var foundNames = new Ember.Set();
+
+              // creates a set with four names in it.
+              var names = new Ember.Set([&quot;Charles&quot;, &quot;Tom&quot;, &quot;Juan&quot;, &quot;Alex&quot;]); // :P
+
+              // creates a copy of the names set.
+              var namesCopy = new Ember.Set(names);
+
+              // same as above.
+              var anotherNamesCopy = names.copy();
+              ```
+
+              ## Adding/Removing Objects
+
+              You generally add or remove objects from a set using `add()` or
+              `remove()`. You can add any type of object including primitives such as
+              numbers, strings, and booleans.
+
+              Unlike arrays, objects can only exist one time in a set. If you call `add()`
+              on a set with the same object multiple times, the object will only be added
+              once. Likewise, calling `remove()` with the same object multiple times will
+              remove the object the first time and have no effect on future calls until
+              you add the object to the set again.
+
+              NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do
+              so will be ignored.
+
+              In addition to add/remove you can also call `push()`/`pop()`. Push behaves
+              just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary
+              object, remove it and return it. This is a good way to use a set as a job
+              queue when you don't care which order the jobs are executed in.
+
+              ## Testing for an Object
+
+              To test for an object's presence in a set you simply call
+              `Ember.Set#contains()`.
+
+              ## Observing changes
+
+              When using `Ember.Set`, you can observe the `&quot;[]&quot;` property to be
+              alerted whenever the content changes. You can also add an enumerable
+              observer to the set to be notified of specific objects that are added and
+              removed from the set. See [Ember.Enumerable](/api/classes/Ember.Enumerable.html)
+              for more information on enumerables.
+
+              This is often unhelpful. If you are filtering sets of objects, for instance,
+              it is very inefficient to re-filter all of the items each time the set
+              changes. It would be better if you could just adjust the filtered set based
+              on what was changed on the original set. The same issue applies to merging
+              sets, as well.
+
+              ## Other Methods
+
+              `Ember.Set` primary implements other mixin APIs. For a complete reference
+              on the methods you will use with `Ember.Set`, please consult these mixins.
+              The most useful ones will be `Ember.Enumerable` and
+              `Ember.MutableEnumerable` which implement most of the common iterator
+              methods you are used to on Array.
+
+              Note that you can also use the `Ember.Copyable` and `Ember.Freezable`
+              APIs on `Ember.Set` as well. Once a set is frozen it can no longer be
+              modified. The benefit of this is that when you call `frozenCopy()` on it,
+              Ember will avoid making copies of the set. This allows you to write
+              code that can know with certainty when the underlying set data will or
+              will not be modified.
+
+              @class Set
+              @namespace Ember
+              @extends Ember.CoreObject
+              @uses Ember.MutableEnumerable
+              @uses Ember.Copyable
+              @uses Ember.Freezable
+              @since Ember 0.9
+            */
+        __exports__[&quot;default&quot;] = CoreObject.extend(MutableEnumerable, Copyable, Freezable, {
+
+            // ..........................................................
+            // IMPLEMENT ENUMERABLE APIS
+            //
+
+            /**
+                    This property will change as the number of objects in the set changes.
+
+                    @property length
+                    @type number
+                    @default 0
+                  */
+            length: 0,
+
+            /**
+                    Clears the set. This is useful if you want to reuse an existing set
+                    without having to recreate it.
+
+                    ```javascript
+                    var colors = new Ember.Set([&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]);
+                    colors.length;  // 3
+                    colors.clear();
+                    colors.length;  // 0
+                    ```
+
+                    @method clear
+                    @return {Ember.Set} An empty Set
+                  */
+            clear: function() {
+                if (this.isFrozen) {
+                    throw new EmberError(FROZEN_ERROR);
+                }
+
+                var len = get(this, 'length');
+                if (len === 0) {
+                    return this;
+                }
+
+                var guid;
+
+                this.enumerableContentWillChange(len, 0);
+                propertyWillChange(this, 'firstObject');
+                propertyWillChange(this, 'lastObject');
+
+                for (var i = 0; i &lt; len; i++) {
+                    guid = guidFor(this[i]);
+                    delete this[guid];
+                    delete this[i];
+                }
+
+                set(this, 'length', 0);
+
+                propertyDidChange(this, 'firstObject');
+                propertyDidChange(this, 'lastObject');
+                this.enumerableContentDidChange(len, 0);
+
+                return this;
+            },
+
+            /**
+                    Returns true if the passed object is also an enumerable that contains the
+                    same objects as the receiver.
+
+                    ```javascript
+                    var colors = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;],
+                        same_colors = new Ember.Set(colors);
+
+                    same_colors.isEqual(colors);               // true
+                    same_colors.isEqual([&quot;purple&quot;, &quot;brown&quot;]);  // false
+                    ```
+
+                    @method isEqual
+                    @param {Ember.Set} obj the other object.
+                    @return {Boolean}
+                  */
+            isEqual: function(obj) {
+                // fail fast
+                if (!Enumerable.detect(obj)) 
+                    return false;
+
+                var loc = get(this, 'length');
+                if (get(obj, 'length') !== loc) 
+                    return false;
+
+                while (--loc &gt;= 0) {
+                    if (!obj.contains(this[loc])) 
+                        return false;
+                }
+
+                return true;
+            },
+
+            /**
+                    Adds an object to the set. Only non-`null` objects can be added to a set
+                    and those can only be added once. If the object is already in the set or
+                    the passed value is null this method will have no effect.
+
+                    This is an alias for `Ember.MutableEnumerable.addObject()`.
+
+                    ```javascript
+                    var colors = new Ember.Set();
+                    colors.add(&quot;blue&quot;);     // [&quot;blue&quot;]
+                    colors.add(&quot;blue&quot;);     // [&quot;blue&quot;]
+                    colors.add(&quot;red&quot;);      // [&quot;blue&quot;, &quot;red&quot;]
+                    colors.add(null);       // [&quot;blue&quot;, &quot;red&quot;]
+                    colors.add(undefined);  // [&quot;blue&quot;, &quot;red&quot;]
+                    ```
+
+                    @method add
+                    @param {Object} obj The object to add.
+                    @return {Ember.Set} The set itself.
+                  */
+            add: aliasMethod('addObject'),
+
+            /**
+                    Removes the object from the set if it is found. If you pass a `null` value
+                    or an object that is already not in the set, this method will have no
+                    effect. This is an alias for `Ember.MutableEnumerable.removeObject()`.
+
+                    ```javascript
+                    var colors = new Ember.Set([&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]);
+                    colors.remove(&quot;red&quot;);     // [&quot;blue&quot;, &quot;green&quot;]
+                    colors.remove(&quot;purple&quot;);  // [&quot;blue&quot;, &quot;green&quot;]
+                    colors.remove(null);      // [&quot;blue&quot;, &quot;green&quot;]
+                    ```
+
+                    @method remove
+                    @param {Object} obj The object to remove
+                    @return {Ember.Set} The set itself.
+                  */
+            remove: aliasMethod('removeObject'),
+
+            /**
+                    Removes the last element from the set and returns it, or `null` if it's empty.
+
+                    ```javascript
+                    var colors = new Ember.Set([&quot;green&quot;, &quot;blue&quot;]);
+                    colors.pop();  // &quot;blue&quot;
+                    colors.pop();  // &quot;green&quot;
+                    colors.pop();  // null
+                    ```
+
+                    @method pop
+                    @return {Object} The removed object from the set or null.
+                  */
+            pop: function() {
+                if (get(this, 'isFrozen')) 
+                    throw new EmberError(FROZEN_ERROR);
+                var obj = this.length &gt; 0 ? this[this.length-1] : null;
+                this.remove(obj);
+                return obj;
+            },
+
+            /**
+                    Inserts the given object on to the end of the set. It returns
+                    the set itself.
+
+                    This is an alias for `Ember.MutableEnumerable.addObject()`.
+
+                    ```javascript
+                    var colors = new Ember.Set();
+                    colors.push(&quot;red&quot;);   // [&quot;red&quot;]
+                    colors.push(&quot;green&quot;); // [&quot;red&quot;, &quot;green&quot;]
+                    colors.push(&quot;blue&quot;);  // [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]
+                    ```
+
+                    @method push
+                    @return {Ember.Set} The set itself.
+                  */
+            push: aliasMethod('addObject'),
+
+            /**
+                    Removes the last element from the set and returns it, or `null` if it's empty.
+
+                    This is an alias for `Ember.Set.pop()`.
+
+                    ```javascript
+                    var colors = new Ember.Set([&quot;green&quot;, &quot;blue&quot;]);
+                    colors.shift();  // &quot;blue&quot;
+                    colors.shift();  // &quot;green&quot;
+                    colors.shift();  // null
+                    ```
+
+                    @method shift
+                    @return {Object} The removed object from the set or null.
+                  */
+            shift: aliasMethod('pop'),
+
+            /**
+                    Inserts the given object on to the end of the set. It returns
+                    the set itself.
+
+                    This is an alias of `Ember.Set.push()`
+
+                    ```javascript
+                    var colors = new Ember.Set();
+                    colors.unshift(&quot;red&quot;);    // [&quot;red&quot;]
+                    colors.unshift(&quot;green&quot;);  // [&quot;red&quot;, &quot;green&quot;]
+                    colors.unshift(&quot;blue&quot;);   // [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]
+                    ```
+
+                    @method unshift
+                    @return {Ember.Set} The set itself.
+                  */
+            unshift: aliasMethod('push'),
+
+            /**
+                    Adds each object in the passed enumerable to the set.
+
+                    This is an alias of `Ember.MutableEnumerable.addObjects()`
+
+                    ```javascript
+                    var colors = new Ember.Set();
+                    colors.addEach([&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]);  // [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]
+                    ```
+
+                    @method addEach
+                    @param {Ember.Enumerable} objects the objects to add.
+                    @return {Ember.Set} The set itself.
+                  */
+            addEach: aliasMethod('addObjects'),
+
+            /**
+                    Removes each object in the passed enumerable to the set.
+
+                    This is an alias of `Ember.MutableEnumerable.removeObjects()`
+
+                    ```javascript
+                    var colors = new Ember.Set([&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]);
+                    colors.removeEach([&quot;red&quot;, &quot;blue&quot;]);  //  [&quot;green&quot;]
+                    ```
+
+                    @method removeEach
+                    @param {Ember.Enumerable} objects the objects to remove.
+                    @return {Ember.Set} The set itself.
+                  */
+            removeEach: aliasMethod('removeObjects'),
+
+            // ..........................................................
+            // PRIVATE ENUMERABLE SUPPORT
+            //
+
+            init: function(items) {
+                this._super();
+                if (items) 
+                    this.addObjects(items);
+            },
+
+            // implement Ember.Enumerable
+            nextObject: function(idx) {
+                return this[idx];
+            },
+
+            // more optimized version
+            firstObject: computed(function() {
+                return this.length &gt; 0 ? this[0] : undefined;
+            }),
+
+            // more optimized version
+            lastObject: computed(function() {
+                return this.length &gt; 0 ? this[this.length-1] : undefined;
+            }),
+
+            // implements Ember.MutableEnumerable
+            addObject: function(obj) {
+                if (get(this, 'isFrozen')) 
+                    throw new EmberError(FROZEN_ERROR);
+                if (isNone(obj)) 
+                    return this; // nothing to do
+
+                var guid = guidFor(obj),
+                idx = this[guid],
+                len = get(this, 'length'),
+                added ;
+
+                if (idx &gt;= 0 &amp;&amp; idx &lt; len &amp;&amp; (this[idx] === obj)) 
+                    return this; // added
+
+                added = [obj];
+
+                this.enumerableContentWillChange(null, added);
+                propertyWillChange(this, 'lastObject');
+
+                len = get(this, 'length');
+                this[guid] = len;
+                this[len] = obj;
+                set(this, 'length', len + 1);
+
+                propertyDidChange(this, 'lastObject');
+                this.enumerableContentDidChange(null, added);
+
+                return this;
+            },
+
+            // implements Ember.MutableEnumerable
+            removeObject: function(obj) {
+                if (get(this, 'isFrozen')) 
+                    throw new EmberError(FROZEN_ERROR);
+                if (isNone(obj)) 
+                    return this; // nothing to do
+
+                var guid = guidFor(obj),
+                idx = this[guid],
+                len = get(this, 'length'),
+                isFirst = idx === 0,
+                isLast = idx === len-1,
+                last, removed;
+
+
+                if (idx &gt;= 0 &amp;&amp; idx &lt; len &amp;&amp; (this[idx] === obj)) {
+                    removed = [obj];
+
+                    this.enumerableContentWillChange(removed, null);
+                    if (isFirst) {
+                        propertyWillChange(this, 'firstObject');
+                    }
+                    if (isLast) {
+                        propertyWillChange(this, 'lastObject');
+                    }
+
+                    // swap items - basically move the item to the end so it can be removed
+                    if (idx &lt; len-1) {
+                        last = this[len-1];
+                        this[idx] = last;
+                        this[guidFor(last)] = idx;
+                    }
+
+                    delete this[guid];
+                    delete this[len-1];
+                    set(this, 'length', len-1);
+
+                    if (isFirst) {
+                        propertyDidChange(this, 'firstObject');
+                    }
+                    if (isLast) {
+                        propertyDidChange(this, 'lastObject');
+                    }
+                    this.enumerableContentDidChange(removed, null);
+                }
+
+                return this;
+            },
+
+            // optimized version
+            contains: function(obj) {
+                return this[guidFor(obj)] &gt;= 0;
+            },
+
+            copy: function() {
+                var C = this.constructor, ret = new C(), loc = get(this, 'length');
+                set(ret, 'length', loc);
+                while (--loc &gt;= 0) {
+                    ret[loc] = this[loc];
+                    ret[guidFor(this[loc])] = loc;
+                }
+                return ret;
+            },
+
+            toString: function() {
+                var len = this.length, idx, array = [];
+                for (idx = 0; idx &lt; len; idx++) {
+                    array[idx] = this[idx];
+                }
+                return fmt(&quot;Ember.Set&lt;%@&gt;&quot;, [array.join(',')]);
+            }
+        });
+    });
+    define(&quot;ember-runtime/system/string&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-runtime
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.STRINGS, Ember.FEATURES
+        var isArray = __dependency2__.isArray;
+        var emberInspect = __dependency2__.inspect;
+
+        var STRING_DASHERIZE_REGEXP = (/[ _]/g);
+        var STRING_DASHERIZE_CACHE = {};
+        var STRING_DECAMELIZE_REGEXP = (/([a-z\d])([A-Z])/g);
+        var STRING_CAMELIZE_REGEXP = (/(\-|_|\.|\s)+(.)?/g);
+        var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
+        var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
+
+        function fmt(str, formats) {
+            if (!isArray(formats) || arguments.length &gt; 2) {
+                formats = Array.prototype.slice.call(arguments, 1);
+            }
+
+            // first, replace any ORDERED replacements.
+            var idx = 0; // the current index for non-numerical replacements
+            return str.replace(/%@([0-9]+)?/g, function(s, argIndex) {
+                argIndex = (argIndex) ? parseInt(argIndex, 10) - 1 : idx++;
+                s = formats[argIndex];
+                return (s === null) ? '(null)' : (s === undefined) ? '' : emberInspect(s);
+            });
+        }
+
+        function loc(str, formats) {
+            if (!isArray(formats) || arguments.length &gt; 2) {
+                formats = Array.prototype.slice.call(arguments, 1);
+            }
+
+            str = Ember.STRINGS[str] || str;
+            return fmt(str, formats);
+        }
+
+        function w(str) {
+            return str.split(/\s+/);
+        }
+
+        function decamelize(str) {
+            return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
+        }
+
+        function dasherize(str) {
+            var cache = STRING_DASHERIZE_CACHE,
+            hit = cache.hasOwnProperty(str),
+            ret;
+
+            if (hit) {
+                return cache[str];
+            } else {
+                ret = decamelize(str).replace(STRING_DASHERIZE_REGEXP, '-');
+                cache[str] = ret;
+            }
+
+            return ret;
+        }
+
+        function camelize(str) {
+            return str.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) {
+                return chr ? chr.toUpperCase() : '';
+            }).replace(/^([A-Z])/, function(match, separator, chr) {
+                return match.toLowerCase();
+            });
+        }
+
+        function classify(str) {
+            var parts = str.split(&quot;.&quot;),
+            out = [];
+
+            for (var i = 0, l = parts.length; i &lt; l; i++) {
+                var camelized = camelize(parts[i]);
+                out.push(camelized.charAt(0).toUpperCase() + camelized.substr(1));
+            }
+
+            return out.join(&quot;.&quot;);
+        }
+
+        function underscore(str) {
+            return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
+            replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
+        }
+
+        function capitalize(str) {
+            return str.charAt(0).toUpperCase() + str.substr(1);
+        }
+
+        /**
+              Defines the hash of localized strings for the current language. Used by
+              the `Ember.String.loc()` helper. To localize, add string values to this
+              hash.
+
+              @property STRINGS
+              @for Ember
+              @type Hash
+            */
+        Ember.STRINGS = {};
+
+        /**
+              Defines string helper methods including string formatting and localization.
+              Unless `Ember.EXTEND_PROTOTYPES.String` is `false` these methods will also be
+              added to the `String.prototype` as well.
+
+              @class String
+              @namespace Ember
+              @static
+            */
+        __exports__[&quot;default&quot;] = {
+            /**
+                    Apply formatting options to the string. This will look for occurrences
+                    of &quot;%@&quot; in your string and substitute them with the arguments you pass into
+                    this method. If you want to control the specific order of replacement,
+                    you can add a number after the key as well to indicate which argument
+                    you want to insert.
+
+                    Ordered insertions are most useful when building loc strings where values
+                    you need to insert may appear in different orders.
+
+                    ```javascript
+                    &quot;Hello %@ %@&quot;.fmt('John', 'Doe');     // &quot;Hello John Doe&quot;
+                    &quot;Hello %@2, %@1&quot;.fmt('John', 'Doe');  // &quot;Hello Doe, John&quot;
+                    ```
+
+                    @method fmt
+                    @param {String} str The string to format
+                    @param {Array} formats An array of parameters to interpolate into string.
+                    @return {String} formatted string
+                  */
+            fmt: fmt,
+
+            /**
+                    Formats the passed string, but first looks up the string in the localized
+                    strings hash. This is a convenient way to localize text. See
+                    `Ember.String.fmt()` for more information on formatting.
+
+                    Note that it is traditional but not required to prefix localized string
+                    keys with an underscore or other character so you can easily identify
+                    localized strings.
+
+                    ```javascript
+                    Ember.STRINGS = {
+                      '_Hello World': 'Bonjour le monde',
+                      '_Hello %@ %@': 'Bonjour %@ %@'
+                    };
+
+                    Ember.String.loc(&quot;_Hello World&quot;);  // 'Bonjour le monde';
+                    Ember.String.loc(&quot;_Hello %@ %@&quot;, [&quot;John&quot;, &quot;Smith&quot;]);  // &quot;Bonjour John Smith&quot;;
+                    ```
+
+                    @method loc
+                    @param {String} str The string to format
+                    @param {Array} formats Optional array of parameters to interpolate into string.
+                    @return {String} formatted string
+                  */
+            loc: loc,
+
+            /**
+                    Splits a string into separate units separated by spaces, eliminating any
+                    empty strings in the process. This is a convenience method for split that
+                    is mostly useful when applied to the `String.prototype`.
+
+                    ```javascript
+                    Ember.String.w(&quot;alpha beta gamma&quot;).forEach(function(key) {
+                      console.log(key);
+                    });
+
+                    // &gt; alpha
+                    // &gt; beta
+                    // &gt; gamma
+                    ```
+
+                    @method w
+                    @param {String} str The string to split
+                    @return {Array} array containing the split strings
+                  */
+            w: w,
+
+            /**
+                    Converts a camelized string into all lower case separated by underscores.
+
+                    ```javascript
+                    'innerHTML'.decamelize();           // 'inner_html'
+                    'action_name'.decamelize();        // 'action_name'
+                    'css-class-name'.decamelize();     // 'css-class-name'
+                    'my favorite items'.decamelize();  // 'my favorite items'
+                    ```
+
+                    @method decamelize
+                    @param {String} str The string to decamelize.
+                    @return {String} the decamelized string.
+                  */
+            decamelize: decamelize,
+
+            /**
+                    Replaces underscores, spaces, or camelCase with dashes.
+
+                    ```javascript
+                    'innerHTML'.dasherize();          // 'inner-html'
+                    'action_name'.dasherize();        // 'action-name'
+                    'css-class-name'.dasherize();     // 'css-class-name'
+                    'my favorite items'.dasherize();  // 'my-favorite-items'
+                    ```
+
+                    @method dasherize
+                    @param {String} str The string to dasherize.
+                    @return {String} the dasherized string.
+                  */
+            dasherize: dasherize,
+
+            /**
+                    Returns the lowerCamelCase form of a string.
+
+                    ```javascript
+                    'innerHTML'.camelize();          // 'innerHTML'
+                    'action_name'.camelize();        // 'actionName'
+                    'css-class-name'.camelize();     // 'cssClassName'
+                    'my favorite items'.camelize();  // 'myFavoriteItems'
+                    'My Favorite Items'.camelize();  // 'myFavoriteItems'
+                    ```
+
+                    @method camelize
+                    @param {String} str The string to camelize.
+                    @return {String} the camelized string.
+                  */
+            camelize: camelize,
+
+            /**
+                    Returns the UpperCamelCase form of a string.
+
+                    ```javascript
+                    'innerHTML'.classify();          // 'InnerHTML'
+                    'action_name'.classify();        // 'ActionName'
+                    'css-class-name'.classify();     // 'CssClassName'
+                    'my favorite items'.classify();  // 'MyFavoriteItems'
+                    ```
+
+                    @method classify
+                    @param {String} str the string to classify
+                    @return {String} the classified string
+                  */
+            classify: classify,
+
+            /**
+                    More general than decamelize. Returns the lower\_case\_and\_underscored
+                    form of a string.
+
+                    ```javascript
+                    'innerHTML'.underscore();          // 'inner_html'
+                    'action_name'.underscore();        // 'action_name'
+                    'css-class-name'.underscore();     // 'css_class_name'
+                    'my favorite items'.underscore();  // 'my_favorite_items'
+                    ```
+
+                    @method underscore
+                    @param {String} str The string to underscore.
+                    @return {String} the underscored string.
+                  */
+            underscore: underscore,
+
+            /**
+                    Returns the Capitalized form of a string
+
+                    ```javascript
+                    'innerHTML'.capitalize()         // 'InnerHTML'
+                    'action_name'.capitalize()       // 'Action_name'
+                    'css-class-name'.capitalize()    // 'Css-class-name'
+                    'my favorite items'.capitalize() // 'My favorite items'
+                    ```
+
+                    @method capitalize
+                    @param {String} str The string to capitalize.
+                    @return {String} The capitalized string.
+                  */
+            capitalize: capitalize
+        };
+
+        __exports__.fmt = fmt;
+        __exports__.loc = loc;
+        __exports__.w = w;
+        __exports__.decamelize = decamelize;
+        __exports__.dasherize = dasherize;
+        __exports__.camelize = camelize;
+        __exports__.classify = classify;
+        __exports__.underscore = underscore;
+        __exports__.capitalize = capitalize;
+    });
+    define(&quot;ember-runtime/system/subarray&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var EmberError = __dependency2__[&quot;default&quot;];
+        var EnumerableUtils = __dependency3__[&quot;default&quot;];
+
+        var RETAIN = 'r';
+        var FILTER = 'f';
+
+        function Operation(type, count) {
+            this.type = type;
+            this.count = count;
+        }
+
+        __exports__[&quot;default&quot;] = SubArray;
+
+        /**
+              An `Ember.SubArray` tracks an array in a way similar to, but more specialized
+              than, `Ember.TrackedArray`.  It is useful for keeping track of the indexes of
+              items within a filtered array.
+
+              @class SubArray
+              @namespace Ember
+            */
+        function SubArray (length) {
+            if (arguments.length &lt; 1) {
+                length = 0;
+            }
+
+            if (length &gt; 0) {
+                this._operations = [new Operation(RETAIN, length)];
+            } else {
+                this._operations = [];
+            }
+        }
+
+
+        SubArray.prototype = {
+            /**
+                    Track that an item was added to the tracked array.
+
+                    @method addItem
+
+                    @param {number} index The index of the item in the tracked array.
+                    @param {boolean} match `true` iff the item is included in the subarray.
+
+                    @return {number} The index of the item in the subarray.
+                  */
+            addItem: function(index, match) {
+                var returnValue = -1,
+                itemType = match ? RETAIN : FILTER,
+                self = this;
+
+                this._findOperation(index, function(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) {
+                    var newOperation, splitOperation;
+
+                    if (itemType === operation.type) {
+                        ++operation.count;
+                    } else if (index === rangeStart) {
+                        // insert to the left of `operation`
+                        self._operations.splice(operationIndex, 0, new Operation(itemType, 1));
+                    } else {
+                        newOperation = new Operation(itemType, 1);
+                        splitOperation = new Operation(operation.type, rangeEnd - index + 1);
+                        operation.count = index - rangeStart;
+
+                        self._operations.splice(operationIndex + 1, 0, newOperation, splitOperation);
+                    }
+
+                    if (match) {
+                        if (operation.type === RETAIN) {
+                            returnValue = seenInSubArray + (index - rangeStart);
+                        } else {
+                            returnValue = seenInSubArray;
+                        }
+                    }
+
+                    self._composeAt(operationIndex);
+                }, function(seenInSubArray) {
+                    self._operations.push(new Operation(itemType, 1));
+
+                    if (match) {
+                        returnValue = seenInSubArray;
+                    }
+
+                    self._composeAt(self._operations.length-1);
+                });
+
+                return returnValue;
+            },
+
+            /**
+                    Track that an item was removed from the tracked array.
+
+                    @method removeItem
+
+                    @param {number} index The index of the item in the tracked array.
+
+                    @return {number} The index of the item in the subarray, or `-1` if the item
+                    was not in the subarray.
+                  */
+            removeItem: function(index) {
+                var returnValue = -1,
+                self = this;
+
+                this._findOperation(index, function (operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) {
+                    if (operation.type === RETAIN) {
+                        returnValue = seenInSubArray + (index - rangeStart);
+                    }
+
+                    if (operation.count &gt; 1) {
+                        --operation.count;
+                    } else {
+                        self._operations.splice(operationIndex, 1);
+                        self._composeAt(operationIndex);
+                    }
+                }, function() {
+                    throw new EmberError(&quot;Can't remove an item that has never been added.&quot;);
+                });
+
+                return returnValue;
+            },
+
+
+            _findOperation: function (index, foundCallback, notFoundCallback) {
+                var operationIndex,
+                len,
+                operation,
+                rangeStart,
+                rangeEnd,
+                seenInSubArray = 0;
+
+                // OPTIMIZE: change to balanced tree
+                // find leftmost operation to the right of `index`
+                for (operationIndex = rangeStart = 0, len = this._operations.length; operationIndex &lt; len; rangeStart = rangeEnd + 1, ++operationIndex) {
+                    operation = this._operations[operationIndex];
+                    rangeEnd = rangeStart + operation.count - 1;
+
+                    if (index &gt;= rangeStart &amp;&amp; index &lt;= rangeEnd) {
+                        foundCallback(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray);
+                        return;
+                    } else if (operation.type === RETAIN) {
+                        seenInSubArray += operation.count;
+                    }
+                }
+
+                notFoundCallback(seenInSubArray);
+            },
+
+            _composeAt: function(index) {
+                var op = this._operations[index],
+                otherOp;
+
+                if (!op) {
+                    // Composing out of bounds is a no-op, as when removing the last operation
+                    // in the list.
+                    return;
+                }
+
+                if (index &gt; 0) {
+                    otherOp = this._operations[index-1];
+                    if (otherOp.type === op.type) {
+                        op.count += otherOp.count;
+                        this._operations.splice(index-1, 1);
+                        --index;
+                    }
+                }
+
+                if (index &lt; this._operations.length-1) {
+                    otherOp = this._operations[index + 1];
+                    if (otherOp.type === op.type) {
+                        op.count += otherOp.count;
+                        this._operations.splice(index + 1, 1);
+                    }
+                }
+            },
+
+            toString: function () {
+                var str = &quot;&quot;;
+                EnumerableUtils.forEach(this._operations, function (operation) {
+                    str += &quot; &quot; + operation.type + &quot;:&quot; + operation.count;
+                });
+                return str.substring(1);
+            }
+        };
+    });
+    define(&quot;ember-runtime/system/tracked_array&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var forEach = __dependency2__.forEach;
+
+        var RETAIN = 'r';
+        var INSERT = 'i';
+        var DELETE = 'd';
+
+        __exports__[&quot;default&quot;] = TrackedArray;
+
+        /**
+              An `Ember.TrackedArray` tracks array operations.  It's useful when you want to
+              lazily compute the indexes of items in an array after they've been shifted by
+              subsequent operations.
+
+              @class TrackedArray
+              @namespace Ember
+              @param {array} [items=[]] The array to be tracked.  This is used just to get
+              the initial items for the starting state of retain:n.
+            */
+        function TrackedArray(items) {
+            if (arguments.length &lt; 1) {
+                items = [];
+            }
+
+            var length = get(items, 'length');
+
+            if (length) {
+                this._operations = [new ArrayOperation(RETAIN, length, items)];
+            } else {
+                this._operations = [];
+            }
+        }
+
+        TrackedArray.RETAIN = RETAIN;
+        TrackedArray.INSERT = INSERT;
+        TrackedArray.DELETE = DELETE;
+
+        TrackedArray.prototype = {
+
+            /**
+                    Track that `newItems` were added to the tracked array at `index`.
+
+                    @method addItems
+                    @param index
+                    @param newItems
+                  */
+            addItems: function (index, newItems) {
+                var count = get(newItems, 'length');
+                if (count &lt; 1) {
+                    return;
+                }
+
+                var match = this._findArrayOperation(index),
+                arrayOperation = match.operation,
+                arrayOperationIndex = match.index,
+                arrayOperationRangeStart = match.rangeStart,
+                composeIndex,
+                splitIndex,
+                splitItems,
+                splitArrayOperation,
+                newArrayOperation;
+
+                newArrayOperation = new ArrayOperation(INSERT, count, newItems);
+
+                if (arrayOperation) {
+                    if (!match.split) {
+                        // insert left of arrayOperation
+                        this._operations.splice(arrayOperationIndex, 0, newArrayOperation);
+                        composeIndex = arrayOperationIndex;
+                    } else {
+                        this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation);
+                        composeIndex = arrayOperationIndex + 1;
+                    }
+                } else {
+                    // insert at end
+                    this._operations.push(newArrayOperation);
+                    composeIndex = arrayOperationIndex;
+                }
+
+                this._composeInsert(composeIndex);
+            },
+
+            /**
+                    Track that `count` items were removed at `index`.
+
+                    @method removeItems
+                    @param index
+                    @param count
+                  */
+            removeItems: function (index, count) {
+                if (count &lt; 1) {
+                    return;
+                }
+
+                var match = this._findArrayOperation(index),
+                arrayOperation = match.operation,
+                arrayOperationIndex = match.index,
+                arrayOperationRangeStart = match.rangeStart,
+                newArrayOperation,
+                composeIndex;
+
+                newArrayOperation = new ArrayOperation(DELETE, count);
+                if (!match.split) {
+                    // insert left of arrayOperation
+                    this._operations.splice(arrayOperationIndex, 0, newArrayOperation);
+                    composeIndex = arrayOperationIndex;
+                } else {
+                    this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation);
+                    composeIndex = arrayOperationIndex + 1;
+                }
+
+                return this._composeDelete(composeIndex);
+            },
+
+            /**
+                    Apply all operations, reducing them to retain:n, for `n`, the number of
+                    items in the array.
+
+                    `callback` will be called for each operation and will be passed the following arguments:
+
+                    * {array} items The items for the given operation
+                    * {number} offset The computed offset of the items, ie the index in the
+                    array of the first item for this operation.
+                    * {string} operation The type of the operation.  One of
+                    `Ember.TrackedArray.{RETAIN, DELETE, INSERT}`
+
+                    @method apply
+                    @param {function} callback
+                  */
+            apply: function (callback) {
+                var items = [],
+                offset = 0;
+
+                forEach(this._operations, function (arrayOperation, operationIndex) {
+                    callback(arrayOperation.items, offset, arrayOperation.type, operationIndex);
+
+                    if (arrayOperation.type !== DELETE) {
+                        offset += arrayOperation.count;
+                        items = items.concat(arrayOperation.items);
+                    }
+                });
+
+                this._operations = [new ArrayOperation(RETAIN, items.length, items)];
+            },
+
+            /**
+                    Return an `ArrayOperationMatch` for the operation that contains the item at `index`.
+
+                    @method _findArrayOperation
+
+                    @param {number} index the index of the item whose operation information
+                    should be returned.
+                    @private
+                  */
+            _findArrayOperation: function (index) {
+                var arrayOperationIndex,
+                len,
+                split = false,
+                arrayOperation,
+                arrayOperationRangeStart,
+                arrayOperationRangeEnd;
+
+                // OPTIMIZE: we could search these faster if we kept a balanced tree.
+                // find leftmost arrayOperation to the right of `index`
+                for (arrayOperationIndex = arrayOperationRangeStart = 0, len = this._operations.length; arrayOperationIndex &lt; len; ++arrayOperationIndex) {
+                    arrayOperation = this._operations[arrayOperationIndex];
+
+                    if (arrayOperation.type === DELETE) {
+                        continue;
+                    }
+
+                    arrayOperationRangeEnd = arrayOperationRangeStart + arrayOperation.count - 1;
+
+                    if (index === arrayOperationRangeStart) {
+                        break;
+                    } else if (index &gt; arrayOperationRangeStart &amp;&amp; index &lt;= arrayOperationRangeEnd) {
+                        split = true;
+                        break;
+                    } else {
+                        arrayOperationRangeStart = arrayOperationRangeEnd + 1;
+                    }
+                }
+
+                return new ArrayOperationMatch(arrayOperation, arrayOperationIndex, split, arrayOperationRangeStart);
+            },
+
+            _split: function (arrayOperationIndex, splitIndex, newArrayOperation) {
+                var arrayOperation = this._operations[arrayOperationIndex];
+                var splitItems = arrayOperation.items.slice(splitIndex);
+                var splitArrayOperation = new ArrayOperation(arrayOperation.type, splitItems.length, splitItems);
+
+                // truncate LHS
+                arrayOperation.count = splitIndex;
+                arrayOperation.items = arrayOperation.items.slice(0, splitIndex);
+
+                this._operations.splice(arrayOperationIndex + 1, 0, newArrayOperation, splitArrayOperation);
+            },
+
+            // see SubArray for a better implementation.
+            _composeInsert: function (index) {
+                var newArrayOperation = this._operations[index],
+                leftArrayOperation = this._operations[index-1], // may be undefined
+                rightArrayOperation = this._operations[index + 1], // may be undefined
+                leftOp = leftArrayOperation &amp;&amp; leftArrayOperation.type,
+                rightOp = rightArrayOperation &amp;&amp; rightArrayOperation.type;
+
+                if (leftOp === INSERT) {
+                    // merge left
+                    leftArrayOperation.count += newArrayOperation.count;
+                    leftArrayOperation.items = leftArrayOperation.items.concat(newArrayOperation.items);
+
+                    if (rightOp === INSERT) {
+                        // also merge right (we have split an insert with an insert)
+                        leftArrayOperation.count += rightArrayOperation.count;
+                        leftArrayOperation.items = leftArrayOperation.items.concat(rightArrayOperation.items);
+                        this._operations.splice(index, 2);
+                    } else {
+                        // only merge left
+                        this._operations.splice(index, 1);
+                    }
+                } else if (rightOp === INSERT) {
+                    // merge right
+                    newArrayOperation.count += rightArrayOperation.count;
+                    newArrayOperation.items = newArrayOperation.items.concat(rightArrayOperation.items);
+                    this._operations.splice(index + 1, 1);
+                }
+            },
+
+            _composeDelete: function (index) {
+                var arrayOperation = this._operations[index],
+                deletesToGo = arrayOperation.count,
+                leftArrayOperation = this._operations[index-1], // may be undefined
+                leftOp = leftArrayOperation &amp;&amp; leftArrayOperation.type,
+                nextArrayOperation,
+                nextOp,
+                nextCount,
+                removeNewAndNextOp = false,
+                removedItems = [];
+
+                if (leftOp === DELETE) {
+                    arrayOperation = leftArrayOperation;
+                    index -= 1;
+                }
+
+                for (var i = index + 1; deletesToGo &gt; 0; ++i) {
+                    nextArrayOperation = this._operations[i];
+                    nextOp = nextArrayOperation.type;
+                    nextCount = nextArrayOperation.count;
+
+                    if (nextOp === DELETE) {
+                        arrayOperation.count += nextCount;
+                        continue;
+                    }
+
+                    if (nextCount &gt; deletesToGo) {
+                        // d:2 {r,i}:5  we reduce the retain or insert, but it stays
+                        removedItems = removedItems.concat(nextArrayOperation.items.splice(0, deletesToGo));
+                        nextArrayOperation.count -= deletesToGo;
+
+                        // In the case where we truncate the last arrayOperation, we don't need to
+                        // remove it; also the deletesToGo reduction is not the entirety of
+                        // nextCount
+                        i -= 1;
+                        nextCount = deletesToGo;
+
+                        deletesToGo = 0;
+                    } else {
+                        if (nextCount === deletesToGo) {
+                            // Handle edge case of d:2 i:2 in which case both operations go away
+                            // during composition.
+                            removeNewAndNextOp = true;
+                        }
+                        removedItems = removedItems.concat(nextArrayOperation.items);
+                        deletesToGo -= nextCount;
+                    }
+
+                    if (nextOp === INSERT) {
+                        // d:2 i:3 will result in delete going away
+                        arrayOperation.count -= nextCount;
+                    }
+                }
+
+                if (arrayOperation.count &gt; 0) {
+                    // compose our new delete with possibly several operations to the right of
+                    // disparate types
+                    this._operations.splice(index + 1, i-1 - index);
+                } else {
+                    // The delete operation can go away; it has merely reduced some other
+                    // operation, as in d:3 i:4; it may also have eliminated that operation,
+                    // as in d:3 i:3.
+                    this._operations.splice(index, removeNewAndNextOp ? 2 : 1);
+                }
+
+                return removedItems;
+            },
+
+            toString: function () {
+                var str = &quot;&quot;;
+                forEach(this._operations, function (operation) {
+                    str += &quot; &quot; + operation.type + &quot;:&quot; + operation.count;
+                });
+                return str.substring(1);
+            }
+        };
+
+        /**
+              Internal data structure to represent an array operation.
+
+              @method ArrayOperation
+              @private
+              @param {string} type The type of the operation.  One of
+              `Ember.TrackedArray.{RETAIN, INSERT, DELETE}`
+              @param {number} count The number of items in this operation.
+              @param {array} items The items of the operation, if included.  RETAIN and
+              INSERT include their items, DELETE does not.
+            */
+        function ArrayOperation (operation, count, items) {
+            this.type = operation; // RETAIN | INSERT | DELETE
+            this.count = count;
+            this.items = items;
+        }
+
+        /**
+              Internal data structure used to include information when looking up operations
+              by item index.
+
+              @method ArrayOperationMatch
+              @private
+              @param {ArrayOperation} operation
+              @param {number} index The index of `operation` in the array of operations.
+              @param {boolean} split Whether or not the item index searched for would
+              require a split for a new operation type.
+              @param {number} rangeStart The index of the first item in the operation,
+              with respect to the tracked array.  The index of the last item can be computed
+              from `rangeStart` and `operation.count`.
+            */
+        function ArrayOperationMatch(operation, index, split, rangeStart) {
+            this.operation = operation;
+            this.index = index;
+            this.split = split;
+            this.rangeStart = rangeStart;
+        }
+    });
+    define(&quot;ember-testing&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-testing/initializers&quot;, &quot;ember-testing/support&quot;, &quot;ember-testing/setup_for_testing&quot;, &quot;ember-testing/test&quot;, &quot;ember-testing/adapters/adapter&quot;, &quot;ember-testing/adapters/qunit&quot;, &quot;ember-testing/helpers&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+
+        // to setup initializer
+        // to handle various edge cases
+
+        var setupForTesting = __dependency4__[&quot;default&quot;];
+        var Test = __dependency5__[&quot;default&quot;];
+        var Adapter = __dependency6__[&quot;default&quot;];
+        var QUnitAdapter = __dependency7__[&quot;default&quot;];
+        // adds helpers to helpers object in Test
+
+        /**
+              Ember Testing
+
+              @module ember
+              @submodule ember-testing
+              @requires ember-application
+            */
+
+        Ember.Test = Test;
+        Ember.Test.Adapter = Adapter;
+        Ember.Test.QUnitAdapter = QUnitAdapter;
+        Ember.setupForTesting = setupForTesting;
+    });
+    define(&quot;ember-testing/adapters/adapter&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/object&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.K
+        var inspect = __dependency2__.inspect;
+        var EmberObject = __dependency3__[&quot;default&quot;];
+
+        /**
+             @module ember
+             @submodule ember-testing
+            */
+
+        /**
+              The primary purpose of this class is to create hooks that can be implemented
+              by an adapter for various test frameworks.
+
+              @class Adapter
+              @namespace Ember.Test
+            */
+        var Adapter = EmberObject.extend({
+            /**
+                    This callback will be called whenever an async operation is about to start.
+
+                    Override this to call your framework's methods that handle async
+                    operations.
+
+                    @public
+                    @method asyncStart
+                  */
+            asyncStart: Ember.K,
+
+            /**
+                    This callback will be called whenever an async operation has completed.
+
+                    @public
+                    @method asyncEnd
+                  */
+            asyncEnd: Ember.K,
+
+            /**
+                    Override this method with your testing framework's false assertion.
+                    This function is called whenever an exception occurs causing the testing
+                    promise to fail.
+
+                    QUnit example:
+
+                    ```javascript
+                      exception: function(error) {
+                        ok(false, error);
+                      };
+                    ```
+
+                    @public
+                    @method exception
+                    @param {String} error The exception to be raised.
+                  */
+            exception: function(error) {
+                throw error;
+            }
+        });
+
+        __exports__[&quot;default&quot;] = Adapter;
+    });
+    define(&quot;ember-testing/adapters/qunit&quot;,
+    [&quot;ember-testing/adapters/adapter&quot;, &quot;ember-metal/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var Adapter = __dependency1__[&quot;default&quot;];
+        var inspect = __dependency2__.inspect;
+
+        /**
+              This class implements the methods defined by Ember.Test.Adapter for the
+              QUnit testing framework.
+
+              @class QUnitAdapter
+              @namespace Ember.Test
+              @extends Ember.Test.Adapter
+            */
+        __exports__[&quot;default&quot;] = Adapter.extend({
+            asyncStart: function() {
+                QUnit.stop();
+            },
+            asyncEnd: function() {
+                QUnit.start();
+            },
+            exception: function(error) {
+                ok(false, inspect(error));
+            }
+        });
+    });
+    define(&quot;ember-testing/helpers&quot;,
+    [&quot;ember-metal/property_get&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-testing/test&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
+        &quot;use strict&quot;;
+        var get = __dependency1__.get;
+        var EmberError = __dependency2__[&quot;default&quot;];
+        var run = __dependency3__[&quot;default&quot;];
+        var jQuery = __dependency4__[&quot;default&quot;];
+        var Test = __dependency5__[&quot;default&quot;];
+
+        /**
+            * @module ember
+            * @submodule ember-testing
+            */
+
+        var helper = Test.registerHelper;
+        var asyncHelper = Test.registerAsyncHelper;
+        var countAsync = 0;
+
+        function currentRouteName(app) {
+            var appController = app.__container__.lookup('controller:application');
+
+            return get(appController, 'currentRouteName');
+        }
+
+        function currentPath(app) {
+            var appController = app.__container__.lookup('controller:application');
+
+            return get(appController, 'currentPath');
+        }
+
+        function currentURL(app) {
+            var router = app.__container__.lookup('router:main');
+
+            return get(router, 'location').getURL();
+        }
+
+        function visit(app, url) {
+            var router = app.__container__.lookup('router:main');
+            router.location.setURL(url);
+
+            if (app._readinessDeferrals &gt; 0) {
+                router['initialURL'] = url;
+                run(app, 'advanceReadiness');
+                delete router['initialURL'];
+            } else {
+                run(app, app.handleURL, url);
+            }
+
+            return app.testHelpers.wait();
+        }
+
+        function click(app, selector, context) {
+            var $el = app.testHelpers.findWithAssert(selector, context);
+            run($el, 'mousedown');
+
+            if ($el.is(':input')) {
+                var type = $el.prop('type');
+                if (type !== 'checkbox' &amp;&amp; type !== 'radio' &amp;&amp; type !== 'hidden') {
+                    run($el, function() {
+                        // Firefox does not trigger the `focusin` event if the window
+                        // does not have focus. If the document doesn't have focus just
+                        // use trigger('focusin') instead.
+                        if (!document.hasFocus || document.hasFocus()) {
+                            this.focus();
+                        } else {
+                            this.trigger('focusin');
+                        }
+                    });
+                }
+            }
+
+            run($el, 'mouseup');
+            run($el, 'click');
+
+            return app.testHelpers.wait();
+        }
+
+        function triggerEvent(app, selector, context, type, options) {
+            if (arguments.length === 3) {
+                options = type;
+                type = context;
+                context = null;
+            }
+
+            if (typeof options === 'undefined') {
+                options = {};
+            }
+
+            var $el = app.testHelpers.findWithAssert(selector, context);
+
+            var event = jQuery.Event(type, options);
+
+            run($el, 'trigger', event);
+
+            return app.testHelpers.wait();
+        }
+
+        function keyEvent(app, selector, context, type, keyCode) {
+            if (typeof keyCode === 'undefined') {
+                keyCode = type;
+                type = context;
+                context = null;
+            }
+
+            return app.testHelpers.triggerEvent(selector, context, type, {
+                keyCode: keyCode,
+                which: keyCode 
+            });
+        }
+
+        function fillIn(app, selector, context, text) {
+            var $el;
+            if (typeof text === 'undefined') {
+                text = context;
+                context = null;
+            }
+            $el = app.testHelpers.findWithAssert(selector, context);
+            run(function() {
+                $el.val(text).change();
+            });
+            return app.testHelpers.wait();
+        }
+
+        function findWithAssert(app, selector, context) {
+            var $el = app.testHelpers.find(selector, context);
+            if ($el.length === 0) {
+                throw new EmberError(&quot;Element &quot; + selector + &quot; not found.&quot;);
+            }
+            return $el;
+        }
+
+        function find(app, selector, context) {
+            var $el;
+            context = context || get(app, 'rootElement');
+            $el = app.$(selector, context);
+
+            return $el;
+        }
+
+        function andThen(app, callback) {
+            return app.testHelpers.wait(callback(app));
+        }
+
+        function wait(app, value) {
+            return Test.promise(function(resolve) {
+                // If this is the first async promise, kick off the async test
+                if (++countAsync === 1) {
+                    Test.adapter.asyncStart();
+                }
+
+                // Every 10ms, poll for the async thing to have finished
+                var watcher = setInterval(function() {
+                    // 1. If the router is loading, keep polling
+                    var routerIsLoading = !!app.__container__.lookup('router:main').router.activeTransition;
+                    if (routerIsLoading) {
+                        return;
+                    }
+
+                    // 2. If there are pending Ajax requests, keep polling
+                    if (Test.pendingAjaxRequests) {
+                        return;
+                    }
+
+                    // 3. If there are scheduled timers or we are inside of a run loop, keep polling
+                    if (run.hasScheduledTimers() || run.currentRunLoop) {
+                        return;
+                    }
+                    if (Test.waiters &amp;&amp; Test.waiters.any(function(waiter) {
+                        var context = waiter[0];
+                        var callback = waiter[1];
+                        return !callback.call(context);
+                    })) {
+                        return;
+                    }
+                    // Stop polling
+                    clearInterval(watcher);
+
+                    // If this is the last async promise, end the async test
+                    if (--countAsync === 0) {
+                        Test.adapter.asyncEnd();
+                    }
+
+                    // Synchronously resolve the promise
+                    run(null, resolve, value);
+                }, 10);
+            });
+
+        }
+
+
+        /**
+            * Loads a route, sets up any controllers, and renders any templates associated
+            * with the route as though a real user had triggered the route change while
+            * using your app.
+            *
+            * Example:
+            *
+            * ```javascript
+            * visit('posts/index').then(function() {
+            *   // assert something
+            * });
+            * ```
+            *
+            * @method visit
+            * @param {String} url the name of the route
+            * @return {RSVP.Promise}
+            */
+        asyncHelper('visit', visit);
+
+        /**
+            * Clicks an element and triggers any actions triggered by the element's `click`
+            * event.
+            *
+            * Example:
+            *
+            * ```javascript
+            * click('.some-jQuery-selector').then(function() {
+            *   // assert something
+            * });
+            * ```
+            *
+            * @method click
+            * @param {String} selector jQuery selector for finding element on the DOM
+            * @return {RSVP.Promise}
+            */
+        asyncHelper('click', click);
+
+        /**
+            * Simulates a key event, e.g. `keypress`, `keydown`, `keyup` with the desired keyCode
+            *
+            * Example:
+            *
+            * ```javascript
+            * keyEvent('.some-jQuery-selector', 'keypress', 13).then(function() {
+            *  // assert something
+            * });
+            * ```
+            *
+            * @method keyEvent
+            * @param {String} selector jQuery selector for finding element on the DOM
+            * @param {String} type the type of key event, e.g. `keypress`, `keydown`, `keyup`
+            * @param {Number} keyCode the keyCode of the simulated key event
+            * @return {RSVP.Promise}
+            * @since 1.5.0
+            */
+        asyncHelper('keyEvent', keyEvent);
+
+        /**
+            * Fills in an input element with some text.
+            *
+            * Example:
+            *
+            * ```javascript
+            * fillIn('#email', 'you@example.com').then(function() {
+            *   // assert something
+            * });
+            * ```
+            *
+            * @method fillIn
+            * @param {String} selector jQuery selector finding an input element on the DOM
+            * to fill text with
+            * @param {String} text text to place inside the input element
+            * @return {RSVP.Promise}
+            */
+        asyncHelper('fillIn', fillIn);
+
+        /**
+            * Finds an element in the context of the app's container element. A simple alias
+            * for `app.$(selector)`.
+            *
+            * Example:
+            *
+            * ```javascript
+            * var $el = find('.my-selector');
+            * ```
+            *
+            * @method find
+            * @param {String} selector jQuery string selector for element lookup
+            * @return {Object} jQuery object representing the results of the query
+            */
+        helper('find', find);
+
+        /**
+            * Like `find`, but throws an error if the element selector returns no results.
+            *
+            * Example:
+            *
+            * ```javascript
+            * var $el = findWithAssert('.doesnt-exist'); // throws error
+            * ```
+            *
+            * @method findWithAssert
+            * @param {String} selector jQuery selector string for finding an element within
+            * the DOM
+            * @return {Object} jQuery object representing the results of the query
+            * @throws {Error} throws error if jQuery object returned has a length of 0
+            */
+        helper('findWithAssert', findWithAssert);
+
+        /**
+              Causes the run loop to process any pending events. This is used to ensure that
+              any async operations from other helpers (or your assertions) have been processed.
+
+              This is most often used as the return value for the helper functions (see 'click',
+              'fillIn','visit',etc).
+
+              Example:
+
+              ```javascript
+              Ember.Test.registerAsyncHelper('loginUser', function(app, username, password) {
+                visit('secured/path/here')
+                .fillIn('#username', username)
+                .fillIn('#password', username)
+                .click('.submit')
+
+                return app.testHelpers.wait();
+              });
+
+              @method wait
+              @param {Object} value The value to be returned.
+              @return {RSVP.Promise}
+            */
+        asyncHelper('wait', wait);
+        asyncHelper('andThen', andThen);
+
+
+        /**
+              Returns the currently active route name.
+
+            Example:
+
+            ```javascript
+            function validateRouteName(){
+            equal(currentRouteName(), 'some.path', &quot;correct route was transitioned into.&quot;);
+            }
+
+            visit('/some/path').then(validateRouteName)
+            ```
+
+            @method currentRouteName
+            @return {Object} The name of the currently active route.
+            @since 1.5.0
+            */
+        helper('currentRouteName', currentRouteName);
+
+        /**
+              Returns the current path.
+
+            Example:
+
+            ```javascript
+            function validateURL(){
+            equal(currentPath(), 'some.path.index', &quot;correct path was transitioned into.&quot;);
+            }
+
+            click('#some-link-id').then(validateURL);
+            ```
+
+            @method currentPath
+            @return {Object} The currently active path.
+            @since 1.5.0
+            */
+        helper('currentPath', currentPath);
+
+        /**
+              Returns the current URL.
+
+            Example:
+
+            ```javascript
+            function validateURL(){
+            equal(currentURL(), '/some/path', &quot;correct URL was transitioned into.&quot;);
+            }
+
+            click('#some-link-id').then(validateURL);
+            ```
+
+            @method currentURL
+            @return {Object} The currently active URL.
+            @since 1.5.0
+            */
+        helper('currentURL', currentURL);
+
+        /**
+              Triggers the given DOM event on the element identified by the provided selector.
+
+              Example:
+
+              ```javascript
+              triggerEvent('#some-elem-id', 'blur');
+              ```
+
+              This is actually used internally by the `keyEvent` helper like so:
+
+              ```javascript
+              triggerEvent('#some-elem-id', 'keypress', { keyCode: 13 });
+              ```
+
+             @method triggerEvent
+             @param {String} selector jQuery selector for finding element on the DOM
+             @param {String} [context] jQuery selector that will limit the selector
+                                       argument to find only within the context's children
+             @param {String} type The event type to be triggered.
+             @param {Object} options The options to be passed to jQuery.Event.
+             @return {RSVP.Promise}
+             @since 1.5.0
+            */
+        asyncHelper('triggerEvent', triggerEvent);
+    });
+    define(&quot;ember-testing/initializers&quot;,
+    [&quot;ember-runtime/system/lazy_load&quot;],
+    function(__dependency1__) {
+        &quot;use strict&quot;;
+        var onLoad = __dependency1__.onLoad;
+
+        var name = 'deferReadiness in `testing` mode';
+
+        onLoad('Ember.Application', function(Application) {
+            if (!Application.initializers[name]) {
+                Application.initializer({
+                    name: name,
+
+                    initialize: function(container, application) {
+                        if (application.testing) {
+                            application.deferReadiness();
+                        }
+                    }
+                });
+            }
+        });
+    });
+    define(&quot;ember-testing/setup_for_testing&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-testing/adapters/qunit&quot;, &quot;ember-views/system/jquery&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // import Test from &quot;ember-testing/test&quot;;  // ES6TODO: fix when cycles are supported
+        var QUnitAdapter = __dependency2__[&quot;default&quot;];
+        var jQuery = __dependency3__[&quot;default&quot;];
+
+        var Test, requests;
+
+        function incrementAjaxPendingRequests(_, xhr) {
+            requests.push(xhr);
+            Test.pendingAjaxRequests = requests.length;
+        }
+
+        function decrementAjaxPendingRequests(_, xhr) {
+            for (var i = 0; i &lt; requests.length; i++) {
+                if (xhr === requests[i]) {
+                    requests.splice(i, 1);
+                }
+            }
+            Test.pendingAjaxRequests = requests.length;
+        }
+
+        /**
+              Sets Ember up for testing. This is useful to perform
+              basic setup steps in order to unit test.
+
+              Use `App.setupForTesting` to perform integration tests (full
+              application testing).
+
+              @method setupForTesting
+              @namespace Ember
+              @since 1.5.0
+            */
+        __exports__[&quot;default&quot;] = function setupForTesting() {
+            if (!Test) {
+                Test = requireModule('ember-testing/test')['default'];
+            }
+
+            Ember.testing = true;
+
+            // if adapter is not manually set default to QUnit
+            if (!Test.adapter) {
+                Test.adapter = QUnitAdapter.create();
+            }
+
+            requests = [];
+            Test.pendingAjaxRequests = requests.length;
+
+            jQuery(document).off('ajaxSend', incrementAjaxPendingRequests);
+            jQuery(document).off('ajaxComplete', decrementAjaxPendingRequests);
+            jQuery(document).on('ajaxSend', incrementAjaxPendingRequests);
+            jQuery(document).on('ajaxComplete', decrementAjaxPendingRequests);
+        }
+    });
+    define(&quot;ember-testing/support&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-views/system/jquery&quot;],
+    function(__dependency1__, __dependency2__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var jQuery = __dependency2__[&quot;default&quot;];
+
+        /**
+              @module ember
+              @submodule ember-testing
+             */
+
+        var $ = jQuery;
+
+        /**
+              This method creates a checkbox and triggers the click event to fire the
+              passed in handler. It is used to correct for a bug in older versions
+              of jQuery (e.g 1.8.3).
+
+              @private
+              @method testCheckboxClick
+            */
+        function testCheckboxClick(handler) {
+            $('&lt;input type=&quot;checkbox&quot;&gt;')
+            .css({
+                position: 'absolute',
+                left: '-1000px',
+                top: '-1000px' 
+            })
+            .appendTo('body')
+            .on('click', handler)
+            .trigger('click')
+            .remove();
+        }
+
+        $(function() {
+            /*
+                    Determine whether a checkbox checked using jQuery's &quot;click&quot; method will have
+                    the correct value for its checked property.
+
+                    If we determine that the current jQuery version exhibits this behavior,
+                    patch it to work correctly as in the commit for the actual fix:
+                    https://github.com/jquery/jquery/commit/1fb2f92.
+                  */
+            testCheckboxClick(function() {
+                if (!this.checked &amp;&amp; !$.event.special.click) {
+                    $.event.special.click = {
+                        // For checkbox, fire native event so checked state will be right
+                        trigger: function() {
+                            if ($.nodeName( this, &quot;input&quot; ) &amp;&amp; this.type === &quot;checkbox&quot; &amp;&amp; this.click) {
+                                this.click();
+                                return false;
+                            }
+                        }
+                    };
+                }
+            });
+
+            // Try again to verify that the patch took effect or blow up.
+            testCheckboxClick(function() {
+                Ember.warn(&quot;clicked checkboxes should be checked! the jQuery patch didn't work&quot;, this.checked);
+            });
+        });
+    });
+    define(&quot;ember-testing/test&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/platform&quot;, &quot;ember-runtime/compare&quot;, &quot;ember-runtime/ext/rsvp&quot;, &quot;ember-testing/setup_for_testing&quot;, &quot;ember-application/system/application&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        var emberRun = __dependency2__[&quot;default&quot;];
+        var create = __dependency3__.create;
+        var compare = __dependency4__[&quot;default&quot;];
+        var RSVP = __dependency5__[&quot;default&quot;];
+        var setupForTesting = __dependency6__[&quot;default&quot;];
+        var EmberApplication = __dependency7__[&quot;default&quot;];
+
+        /**
+              @module ember
+              @submodule ember-testing
+             */
+        var slice = [].slice;
+        var helpers = {};
+        var injectHelpersCallbacks = [];
+
+        /**
+              This is a container for an assortment of testing related functionality:
+
+              * Choose your default test adapter (for your framework of choice).
+              * Register/Unregister additional test helpers.
+              * Setup callbacks to be fired when the test helpers are injected into
+                your application.
+
+              @class Test
+              @namespace Ember
+            */
+        var Test = {
+            /**
+                    Hash containing all known test helpers.
+
+                    @property _helpers
+                    @private
+                  */
+            _helpers: helpers,
+
+            /**
+                    `registerHelper` is used to register a test helper that will be injected
+                    when `App.injectTestHelpers` is called.
+
+                    The helper method will always be called with the current Application as
+                    the first parameter.
+
+                    For example:
+
+                    ```javascript
+                    Ember.Test.registerHelper('boot', function(app) {
+                      Ember.run(app, app.advanceReadiness);
+                    });
+                    ```
+
+                    This helper can later be called without arguments because it will be
+                    called with `app` as the first parameter.
+
+                    ```javascript
+                    App = Ember.Application.create();
+                    App.injectTestHelpers();
+                    boot();
+                    ```
+
+                    @public
+                    @method registerHelper
+                    @param {String} name The name of the helper method to add.
+                    @param {Function} helperMethod
+                    @param options {Object}
+                  */
+            registerHelper: function(name, helperMethod) {
+                helpers[name] = {
+                    method: helperMethod,
+                    meta: {
+                        wait: false 
+                    }
+                };
+            },
+
+            /**
+                    `registerAsyncHelper` is used to register an async test helper that will be injected
+                    when `App.injectTestHelpers` is called.
+
+                    The helper method will always be called with the current Application as
+                    the first parameter.
+
+                    For example:
+
+                    ```javascript
+                    Ember.Test.registerAsyncHelper('boot', function(app) {
+                      Ember.run(app, app.advanceReadiness);
+                    });
+                    ```
+
+                    The advantage of an async helper is that it will not run
+                    until the last async helper has completed.  All async helpers
+                    after it will wait for it complete before running.
+
+
+                    For example:
+
+                    ```javascript
+                    Ember.Test.registerAsyncHelper('deletePost', function(app, postId) {
+                      click('.delete-' + postId);
+                    });
+
+                    // ... in your test
+                    visit('/post/2');
+                    deletePost(2);
+                    visit('/post/3');
+                    deletePost(3);
+                    ```
+
+                    @public
+                    @method registerAsyncHelper
+                    @param {String} name The name of the helper method to add.
+                    @param {Function} helperMethod
+                    @since 1.2.0
+                  */
+            registerAsyncHelper: function(name, helperMethod) {
+                helpers[name] = {
+                    method: helperMethod,
+                    meta: {
+                        wait: true 
+                    }
+                };
+            },
+
+            /**
+                    Remove a previously added helper method.
+
+                    Example:
+
+                    ```javascript
+                    Ember.Test.unregisterHelper('wait');
+                    ```
+
+                    @public
+                    @method unregisterHelper
+                    @param {String} name The helper to remove.
+                  */
+            unregisterHelper: function(name) {
+                delete helpers[name];
+                delete Test.Promise.prototype[name];
+            },
+
+            /**
+                    Used to register callbacks to be fired whenever `App.injectTestHelpers`
+                    is called.
+
+                    The callback will receive the current application as an argument.
+
+                    Example:
+
+                    ```javascript
+                    Ember.Test.onInjectHelpers(function() {
+                      Ember.$(document).ajaxSend(function() {
+                        Test.pendingAjaxRequests++;
+                      });
+
+                      Ember.$(document).ajaxComplete(function() {
+                        Test.pendingAjaxRequests--;
+                      });
+                    });
+                    ```
+
+                    @public
+                    @method onInjectHelpers
+                    @param {Function} callback The function to be called.
+                  */
+            onInjectHelpers: function(callback) {
+                injectHelpersCallbacks.push(callback);
+            },
+
+            /**
+                    This returns a thenable tailored for testing.  It catches failed
+                    `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception`
+                    callback in the last chained then.
+
+                    This method should be returned by async helpers such as `wait`.
+
+                    @public
+                    @method promise
+                    @param {Function} resolver The function used to resolve the promise.
+                  */
+            promise: function(resolver) {
+                return new Test.Promise(resolver);
+            },
+
+            /**
+                   Used to allow ember-testing to communicate with a specific testing
+                   framework.
+
+                   You can manually set it before calling `App.setupForTesting()`.
+
+                   Example:
+
+                   ```javascript
+                   Ember.Test.adapter = MyCustomAdapter.create()
+                   ```
+
+                   If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`.
+
+                   @public
+                   @property adapter
+                   @type {Class} The adapter to be used.
+                   @default Ember.Test.QUnitAdapter
+                  */
+            adapter: null,
+
+            /**
+                    Replacement for `Ember.RSVP.resolve`
+                    The only difference is this uses
+                    an instance of `Ember.Test.Promise`
+
+                    @public
+                    @method resolve
+                    @param {Mixed} The value to resolve
+                    @since 1.2.0
+                  */
+            resolve: function(val) {
+                return Test.promise(function(resolve) {
+                    return resolve(val);
+                });
+            },
+
+            /**
+                     This allows ember-testing to play nicely with other asynchronous
+                     events, such as an application that is waiting for a CSS3
+                     transition or an IndexDB transaction.
+
+                     For example:
+
+                     ```javascript
+                     Ember.Test.registerWaiter(function() {
+                       return myPendingTransactions() == 0;
+                     });
+                     ```
+                     The `context` argument allows you to optionally specify the `this`
+                     with which your callback will be invoked.
+
+                     For example:
+
+                     ```javascript
+                     Ember.Test.registerWaiter(MyDB, MyDB.hasPendingTransactions);
+                     ```
+
+                     @public
+                     @method registerWaiter
+                     @param {Object} context (optional)
+                     @param {Function} callback
+                     @since 1.2.0
+                  */
+            registerWaiter: function(context, callback) {
+                if (arguments.length === 1) {
+                    callback = context;
+                    context = null;
+                }
+                if (!this.waiters) {
+                    this.waiters = Ember.A();
+                }
+                this.waiters.push([context, callback]);
+            },
+            /**
+                     `unregisterWaiter` is used to unregister a callback that was
+                     registered with `registerWaiter`.
+
+                     @public
+                     @method unregisterWaiter
+                     @param {Object} context (optional)
+                     @param {Function} callback
+                     @since 1.2.0
+                  */
+            unregisterWaiter: function(context, callback) {
+                var pair;
+                if (!this.waiters) {
+                    return;
+                }
+                if (arguments.length === 1) {
+                    callback = context;
+                    context = null;
+                }
+                pair = [context, callback];
+                this.waiters = Ember.A(this.waiters.filter(function(elt) {
+                    return compare(elt, pair) !== 0;
+                }));
+            }
+        };
+
+        function helper(app, name) {
+            var fn = helpers[name].method,
+            meta = helpers[name].meta;
+
+            return function() {
+                var args = slice.call(arguments),
+                lastPromise = Test.lastPromise;
+
+                args.unshift(app);
+
+                // some helpers are not async and
+                // need to return a value immediately.
+                // example: `find`
+                if (!meta.wait) {
+                    return fn.apply(app, args);
+                }
+
+                if (!lastPromise) {
+                    // It's the first async helper in current context
+                    lastPromise = fn.apply(app, args);
+                } else {
+                    // wait for last helper's promise to resolve
+                    // and then execute
+                    run(function() {
+                        lastPromise = Test.resolve(lastPromise).then(function() {
+                            return fn.apply(app, args);
+                        });
+                    });
+                }
+
+                return lastPromise;
+            };
+        }
+
+        function run(fn) {
+            if (!emberRun.currentRunLoop) {
+                emberRun(fn);
+            } else {
+                fn();
+            }
+        }
+
+        EmberApplication.reopen({
+            /**
+                   This property contains the testing helpers for the current application. These
+                   are created once you call `injectTestHelpers` on your `Ember.Application`
+                   instance. The included helpers are also available on the `window` object by
+                   default, but can be used from this object on the individual application also.
+
+                    @property testHelpers
+                    @type {Object}
+                    @default {}
+                  */
+            testHelpers: {},
+
+            /**
+                   This property will contain the original methods that were registered
+                   on the `helperContainer` before `injectTestHelpers` is called.
+
+                   When `removeTestHelpers` is called, these methods are restored to the
+                   `helperContainer`.
+
+                    @property originalMethods
+                    @type {Object}
+                    @default {}
+                    @private
+                    @since 1.3.0
+                  */
+            originalMethods: {},
+
+
+            /**
+                  This property indicates whether or not this application is currently in
+                  testing mode. This is set when `setupForTesting` is called on the current
+                  application.
+
+                  @property testing
+                  @type {Boolean}
+                  @default false
+                  @since 1.3.0
+                  */
+            testing: false,
+
+            /**
+                   This hook defers the readiness of the application, so that you can start
+                   the app when your tests are ready to run. It also sets the router's
+                   location to 'none', so that the window's location will not be modified
+                   (preventing both accidental leaking of state between tests and interference
+                   with your testing framework).
+
+                   Example:
+
+                  ```
+                  App.setupForTesting();
+                  ```
+
+                    @method setupForTesting
+                  */
+            setupForTesting: function() {
+                setupForTesting();
+
+                this.testing = true;
+
+                this.Router.reopen({
+                    location: 'none'
+                });
+            },
+
+            /**
+                    This will be used as the container to inject the test helpers into. By
+                    default the helpers are injected into `window`.
+
+                    @property helperContainer
+                    @type {Object} The object to be used for test helpers.
+                    @default window
+                    @since 1.2.0
+                  */
+            helperContainer: window,
+
+            /**
+                    This injects the test helpers into the `helperContainer` object. If an object is provided
+                    it will be used as the helperContainer. If `helperContainer` is not set it will default
+                    to `window`. If a function of the same name has already been defined it will be cached
+                    (so that it can be reset if the helper is removed with `unregisterHelper` or
+                    `removeTestHelpers`).
+
+                   Any callbacks registered with `onInjectHelpers` will be called once the
+                   helpers have been injected.
+
+                  Example:
+                  ```
+                  App.injectTestHelpers();
+                  ```
+
+                    @method injectTestHelpers
+                  */
+            injectTestHelpers: function(helperContainer) {
+                if (helperContainer) {
+                    this.helperContainer = helperContainer;
+                }
+
+                this.testHelpers = {};
+                for (var name in helpers) {
+                    this.originalMethods[name] = this.helperContainer[name];
+                    this.testHelpers[name] = this.helperContainer[name] = helper(this, name);
+                    protoWrap(Test.Promise.prototype, name, helper(this, name), helpers[name].meta.wait);
+                }
+
+                for (var i = 0, l = injectHelpersCallbacks.length; i &lt; l; i++) {
+                    injectHelpersCallbacks[i](this);
+                }
+            },
+
+            /**
+                    This removes all helpers that have been registered, and resets and functions
+                    that were overridden by the helpers.
+
+                    Example:
+
+                    ```javascript
+                    App.removeTestHelpers();
+                    ```
+
+                    @public
+                    @method removeTestHelpers
+                  */
+            removeTestHelpers: function() {
+                for (var name in helpers) {
+                    this.helperContainer[name] = this.originalMethods[name];
+                    delete this.testHelpers[name];
+                    delete this.originalMethods[name];
+                }
+            }
+        });
+
+        // This method is no longer needed
+        // But still here for backwards compatibility
+        // of helper chaining
+        function protoWrap(proto, name, callback, isAsync) {
+            proto[name] = function() {
+                var args = arguments;
+                if (isAsync) {
+                    return callback.apply(this, args);
+                } else {
+                    return this.then(function() {
+                        return callback.apply(this, args);
+                    });
+                }
+            };
+        }
+
+        Test.Promise = function() {
+            RSVP.Promise.apply(this, arguments);
+            Test.lastPromise = this;
+        };
+
+        Test.Promise.prototype = create(RSVP.Promise.prototype);
+        Test.Promise.prototype.constructor = Test.Promise;
+
+        // Patch `then` to isolate async methods
+        // specifically `Ember.Test.lastPromise`
+        var originalThen = RSVP.Promise.prototype.then;
+        Test.Promise.prototype.then = function(onSuccess, onFailure) {
+            return originalThen.call(this, function(val) {
+                return isolate(onSuccess, val);
+            }, onFailure);
+        };
+
+        // This method isolates nested async methods
+        // so that they don't conflict with other last promises.
+        //
+        // 1. Set `Ember.Test.lastPromise` to null
+        // 2. Invoke method
+        // 3. Return the last promise created during method
+        // 4. Restore `Ember.Test.lastPromise` to original value
+        function isolate(fn, val) {
+            var value, lastPromise;
+
+            // Reset lastPromise for nested helpers
+            Test.lastPromise = null;
+
+            value = fn(val);
+
+            lastPromise = Test.lastPromise;
+
+            // If the method returned a promise
+            // return that promise. If not,
+            // return the last async helper's promise
+            if ((value &amp;&amp; (value instanceof Test.Promise)) || !lastPromise) {
+                return value;
+            } else {
+                run(function() {
+                    lastPromise = Test.resolve(lastPromise).then(function() {
+                        return value;
+                    });
+                });
+                return lastPromise;
+            }
+        }
+
+        __exports__[&quot;default&quot;] = Test;
+    });
+    define(&quot;ember-views&quot;,
+    [&quot;ember-runtime&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-views/system/utils&quot;, &quot;ember-views/system/render_buffer&quot;, &quot;ember-views/system/ext&quot;, &quot;ember-views/views/states&quot;, &quot;ember-views/views/core_view&quot;, &quot;ember-views/views/view&quot;, &quot;ember-views/views/view_collection&quot;, &quot;ember-views/views/container_view&quot;, &quot;ember-views/views/collection_view&quot;, &quot;ember-views/views/component&quot;, &quot;ember-views/system/event_dispatcher&quot;, &quot;ember-views/mixins/view_target_action_support&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            Ember Views
+
+            @module ember
+            @submodule ember-views
+            @requires ember-runtime
+            @main ember-views
+            */
+
+        // BEGIN IMPORTS
+        var Ember = __dependency1__[&quot;default&quot;];
+        var jQuery = __dependency2__[&quot;default&quot;];
+        var setInnerHTML = __dependency3__.setInnerHTML;
+        var isSimpleClick = __dependency3__.isSimpleClick;
+        var RenderBuffer = __dependency4__[&quot;default&quot;];
+        // for the side effect of extending Ember.run.queues
+        var cloneStates = __dependency6__.cloneStates;
+        var states = __dependency6__.states;
+
+        var CoreView = __dependency7__[&quot;default&quot;];
+        var View = __dependency8__[&quot;default&quot;];
+        var ViewCollection = __dependency9__[&quot;default&quot;];
+        var ContainerView = __dependency10__[&quot;default&quot;];
+        var CollectionView = __dependency11__[&quot;default&quot;];
+        var Component = __dependency12__[&quot;default&quot;];
+
+        var EventDispatcher = __dependency13__[&quot;default&quot;];
+        var ViewTargetActionSupport = __dependency14__[&quot;default&quot;];
+        // END IMPORTS
+
+        /**
+              Alias for jQuery
+
+              @method $
+              @for Ember
+            */
+
+        // BEGIN EXPORTS
+        Ember.$ = jQuery;
+
+        Ember.ViewTargetActionSupport = ViewTargetActionSupport;
+        Ember.RenderBuffer = RenderBuffer;
+
+        var ViewUtils = Ember.ViewUtils = {};
+        ViewUtils.setInnerHTML = setInnerHTML;
+        ViewUtils.isSimpleClick = isSimpleClick;
+
+        Ember.CoreView = CoreView;
+        Ember.View = View;
+        Ember.View.states = states;
+        Ember.View.cloneStates = cloneStates;
+
+        Ember._ViewCollection = ViewCollection;
+        Ember.ContainerView = ContainerView;
+        Ember.CollectionView = CollectionView;
+        Ember.Component = Component;
+        Ember.EventDispatcher = EventDispatcher;
+        // END EXPORTS
+
+        __exports__[&quot;default&quot;] = Ember;
+    });
+    define(&quot;ember-views/mixins/component_template_deprecation&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/mixin&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.deprecate
+        var get = __dependency2__.get;
+        var Mixin = __dependency3__.Mixin;
+
+        /**
+              The ComponentTemplateDeprecation mixin is used to provide a useful
+              deprecation warning when using either `template` or `templateName` with
+              a component. The `template` and `templateName` properties specified at
+              extend time are moved to `layout` and `layoutName` respectively.
+
+              `Ember.ComponentTemplateDeprecation` is used internally by Ember in
+              `Ember.Component`.
+
+              @class ComponentTemplateDeprecation
+              @namespace Ember
+            */
+        __exports__[&quot;default&quot;] = Mixin.create({
+            /**
+                    @private
+
+                    Moves `templateName` to `layoutName` and `template` to `layout` at extend
+                    time if a layout is not also specified.
+
+                    Note that this currently modifies the mixin themselves, which is technically
+                    dubious but is practically of little consequence. This may change in the
+                    future.
+
+                    @method willMergeMixin
+                    @since 1.4.0
+                  */
+            willMergeMixin: function(props) {
+                // must call _super here to ensure that the ActionHandler
+                // mixin is setup properly (moves actions -&gt; _actions)
+                //
+                // Calling super is only OK here since we KNOW that
+                // there is another Mixin loaded first.
+                this._super.apply(this, arguments);
+
+                var deprecatedProperty, replacementProperty,
+                layoutSpecified = (props.layoutName || props.layout || get(this, 'layoutName'));
+
+                if (props.templateName &amp;&amp; !layoutSpecified) {
+                    deprecatedProperty = 'templateName';
+                    replacementProperty = 'layoutName';
+
+                    props.layoutName = props.templateName;
+                    delete props['templateName'];
+                }
+
+                if (props.template &amp;&amp; !layoutSpecified) {
+                    deprecatedProperty = 'template';
+                    replacementProperty = 'layout';
+
+                    props.layout = props.template;
+                    delete props['template'];
+                }
+
+                if (deprecatedProperty) {
+                    Ember.deprecate('Do not specify ' + deprecatedProperty + ' on a Component, use ' + replacementProperty + ' instead.', false);
+                }
+            }
+        });
+    });
+    define(&quot;ember-views/mixins/view_target_action_support&quot;,
+    [&quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/target_action_support&quot;, &quot;ember-metal/computed&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Mixin = __dependency1__.Mixin;
+        var TargetActionSupport = __dependency2__[&quot;default&quot;];
+
+        // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed
+        var computed = __dependency3__.computed;
+        var alias = computed.alias;
+
+        /**
+            `Ember.ViewTargetActionSupport` is a mixin that can be included in a
+            view class to add a `triggerAction` method with semantics similar to
+            the Handlebars `{{action}}` helper. It provides intelligent defaults
+            for the action's target: the view's controller; and the context that is
+            sent with the action: the view's context.
+
+            Note: In normal Ember usage, the `{{action}}` helper is usually the best
+            choice. This mixin is most often useful when you are doing more complex
+            event handling in custom View subclasses.
+
+            For example:
+
+            ```javascript
+            App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
+              action: 'save',
+              click: function() {
+                this.triggerAction(); // Sends the `save` action, along with the current context
+                                      // to the current controller
+              }
+            });
+            ```
+
+            The `action` can be provided as properties of an optional object argument
+            to `triggerAction` as well.
+
+            ```javascript
+            App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, {
+              click: function() {
+                this.triggerAction({
+                  action: 'save'
+                }); // Sends the `save` action, along with the current context
+                    // to the current controller
+              }
+            });
+            ```
+
+            @class ViewTargetActionSupport
+            @namespace Ember
+            @extends Ember.TargetActionSupport
+            */
+        __exports__[&quot;default&quot;] = Mixin.create(TargetActionSupport, {
+            /**
+                  @property target
+                  */
+            target: alias('controller'),
+            /**
+                  @property actionContext
+                  */
+            actionContext: alias('context')
+        });
+    });
+    define(&quot;ember-views/system/event_dispatcher&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/utils&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-views/views/view&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-views
+            */
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var isNone = __dependency4__.isNone;
+        var run = __dependency5__[&quot;default&quot;];
+        var typeOf = __dependency6__.typeOf;
+        var fmt = __dependency7__.fmt;
+        var EmberObject = __dependency8__[&quot;default&quot;];
+        var jQuery = __dependency9__[&quot;default&quot;];
+        var View = __dependency10__[&quot;default&quot;];
+
+        var ActionHelper;
+
+        //ES6TODO:
+        // find a better way to do Ember.View.views without global state
+
+        /**
+              `Ember.EventDispatcher` handles delegating browser events to their
+              corresponding `Ember.Views.` For example, when you click on a view,
+              `Ember.EventDispatcher` ensures that that view's `mouseDown` method gets
+              called.
+
+              @class EventDispatcher
+              @namespace Ember
+              @private
+              @extends Ember.Object
+            */
+        __exports__[&quot;default&quot;] = EmberObject.extend({
+
+            /**
+                    The set of events names (and associated handler function names) to be setup
+                    and dispatched by the `EventDispatcher`. Custom events can added to this list at setup
+                    time, generally via the `Ember.Application.customEvents` hash. Only override this
+                    default set to prevent the EventDispatcher from listening on some events all together.
+
+                    This set will be modified by `setup` to also include any events added at that time.
+
+                    @property events
+                    @type Object
+                  */
+            events: {
+                touchstart : 'touchStart',
+                touchmove : 'touchMove',
+                touchend : 'touchEnd',
+                touchcancel : 'touchCancel',
+                keydown : 'keyDown',
+                keyup : 'keyUp',
+                keypress : 'keyPress',
+                mousedown : 'mouseDown',
+                mouseup : 'mouseUp',
+                contextmenu : 'contextMenu',
+                click : 'click',
+                dblclick : 'doubleClick',
+                mousemove : 'mouseMove',
+                focusin : 'focusIn',
+                focusout : 'focusOut',
+                mouseenter : 'mouseEnter',
+                mouseleave : 'mouseLeave',
+                submit : 'submit',
+                input : 'input',
+                change : 'change',
+                dragstart : 'dragStart',
+                drag : 'drag',
+                dragenter : 'dragEnter',
+                dragleave : 'dragLeave',
+                dragover : 'dragOver',
+                drop : 'drop',
+                dragend : 'dragEnd'
+            },
+
+            /**
+                    The root DOM element to which event listeners should be attached. Event
+                    listeners will be attached to the document unless this is overridden.
+
+                    Can be specified as a DOMElement or a selector string.
+
+                    The default body is a string since this may be evaluated before document.body
+                    exists in the DOM.
+
+                    @private
+                    @property rootElement
+                    @type DOMElement
+                    @default 'body'
+                  */
+            rootElement: 'body',
+
+            /**
+                    It enables events to be dispatched to the view's `eventManager.` When present,
+                    this object takes precedence over handling of events on the view itself.
+
+                    Note that most Ember applications do not use this feature. If your app also
+                    does not use it, consider setting this property to false to gain some performance
+                    improvement by allowing the EventDispatcher to skip the search for the
+                    `eventManager` on the view tree.
+
+                    ```javascript
+                    var EventDispatcher = Em.EventDispatcher.extend({
+                      events: {
+                          click       : 'click',
+                          focusin     : 'focusIn',
+                          focusout    : 'focusOut',
+                          change      : 'change'
+                      },
+                      canDispatchToEventManager: false
+                    });
+                    container.register('event_dispatcher:main', EventDispatcher);
+                    ```
+
+                    @property canDispatchToEventManager
+                    @type boolean
+                    @default 'true'
+                  */
+            canDispatchToEventManager: true,
+
+            /**
+                    Sets up event listeners for standard browser events.
+
+                    This will be called after the browser sends a `DOMContentReady` event. By
+                    default, it will set up all of the listeners on the document body. If you
+                    would like to register the listeners on a different element, set the event
+                    dispatcher's `root` property.
+
+                    @private
+                    @method setup
+                    @param addedEvents {Hash}
+                  */
+            setup: function(addedEvents, rootElement) {
+                var event, events = get(this, 'events');
+
+                jQuery.extend(events, addedEvents || {});
+
+                if (!isNone(rootElement)) {
+                    set(this, 'rootElement', rootElement);
+                }
+
+                rootElement = jQuery(get(this, 'rootElement'));
+
+                Ember.assert(fmt('You cannot use the same root element (%@) multiple times in an Ember.Application', [rootElement.selector || rootElement[0].tagName]), !rootElement.is('.ember-application'));
+                Ember.assert('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest('.ember-application').length);
+                Ember.assert('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.find('.ember-application').length);
+
+                rootElement.addClass('ember-application');
+
+                Ember.assert('Unable to add &quot;ember-application&quot; class to rootElement. Make sure you set rootElement to the body or an element in the body.', rootElement.is('.ember-application'));
+
+                for (event in events) {
+                    if (events.hasOwnProperty(event)) {
+                        this.setupHandler(rootElement, event, events[event]);
+                    }
+                }
+            },
+
+            /**
+                    Registers an event listener on the rootElement. If the given event is
+                    triggered, the provided event handler will be triggered on the target view.
+
+                    If the target view does not implement the event handler, or if the handler
+                    returns `false`, the parent view will be called. The event will continue to
+                    bubble to each successive parent view until it reaches the top.
+
+                    @private
+                    @method setupHandler
+                    @param {Element} rootElement
+                    @param {String} event the browser-originated event to listen to
+                    @param {String} eventName the name of the method to call on the view
+                  */
+            setupHandler: function(rootElement, event, eventName) {
+                var self = this;
+
+                rootElement.on(event + '.ember', '.ember-view', function(evt, triggeringManager) {
+                    var view = View.views[this.id],
+                    result = true;
+
+                    var manager = self.canDispatchToEventManager ? self._findNearestEventManager(view, eventName) : null;
+
+                    if (manager &amp;&amp; manager !== triggeringManager) {
+                        result = self._dispatchEvent(manager, evt, eventName, view);
+                    } else if (view) {
+                        result = self._bubbleEvent(view, evt, eventName);
+                    }
+
+                    return result;
+                });
+
+                rootElement.on(event + '.ember', '[data-ember-action]', function(evt) {
+                    //ES6TODO: Needed for ActionHelper (generally not available in ember-views test suite)
+                    if (!ActionHelper) {
+                        ActionHelper = requireModule(&quot;ember-routing-handlebars/helpers/action&quot;)[&quot;ActionHelper&quot;];
+                    }
+
+                    var actionId = jQuery(evt.currentTarget).attr('data-ember-action'),
+                    action = ActionHelper.registeredActions[actionId];
+
+                    // We have to check for action here since in some cases, jQuery will trigger
+                    // an event on `removeChild` (i.e. focusout) after we've already torn down the
+                    // action handlers for the view.
+                    if (action &amp;&amp; action.eventName === eventName) {
+                        return action.handler(evt);
+                    }
+                });
+            },
+
+            _findNearestEventManager: function(view, eventName) {
+                var manager = null;
+
+                while (view) {
+                    manager = get(view, 'eventManager');
+                    if (manager &amp;&amp; manager[eventName]) {
+                        break;
+                    }
+
+                    view = get(view, 'parentView');
+                }
+
+                return manager;
+            },
+
+            _dispatchEvent: function(object, evt, eventName, view) {
+                var result = true;
+
+                var handler = object[eventName];
+                if (typeOf(handler) === 'function') {
+                    result = run(object, handler, evt, view);
+                    // Do not preventDefault in eventManagers.
+                    evt.stopPropagation();
+                } else {
+                    result = this._bubbleEvent(view, evt, eventName);
+                }
+
+                return result;
+            },
+
+            _bubbleEvent: function(view, evt, eventName) {
+                return run(view, view.handleEvent, eventName, evt);
+            },
+
+            destroy: function() {
+                var rootElement = get(this, 'rootElement');
+                jQuery(rootElement).off('.ember', '**').removeClass('ember-application');
+                return this._super();
+            },
+
+            toString: function() {
+                return '(EventDisptacher)';
+            }
+        });
+    });
+    define(&quot;ember-views/system/ext&quot;,
+    [&quot;ember-metal/run_loop&quot;],
+    function(__dependency1__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var run = __dependency1__[&quot;default&quot;];
+
+        // Add a new named queue for rendering views that happens
+        // after bindings have synced, and a queue for scheduling actions
+        // that that should occur after view rendering.
+        var queues = run.queues;
+        run._addQueue('render', 'actions');
+        run._addQueue('afterRender', 'render');
+    });
+    define(&quot;ember-views/system/jquery&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var w = __dependency2__.w;
+
+        // ES6TODO: the functions on EnumerableUtils need their own exports
+        var forEach = __dependency3__.forEach;
+
+        /**
+            Ember Views
+
+            @module ember
+            @submodule ember-views
+            @requires ember-runtime
+            @main ember-views
+            */
+
+        var jQuery = (Ember.imports &amp;&amp; Ember.imports.jQuery) || (this &amp;&amp; this.jQuery);
+        if (!jQuery &amp;&amp; typeof require === 'function') {
+            jQuery = require('jquery');
+        }
+
+        Ember.assert(&quot;Ember Views require jQuery between 1.7 and 2.1&quot;, jQuery &amp;&amp; (jQuery().jquery.match(/^((1\.(7|8|9|10|11))|(2\.(0|1)))(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+        if (jQuery) {
+            // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
+            var dragEvents = w('dragstart drag dragenter dragleave dragover drop dragend');
+
+            // Copies the `dataTransfer` property from a browser event object onto the
+            // jQuery event object for the specified events
+            forEach(dragEvents, function(eventName) {
+                jQuery.event.fixHooks[eventName] = {
+                    props: ['dataTransfer'] 
+                };
+            });
+        }
+
+        __exports__[&quot;default&quot;] = jQuery;
+    });
+    define(&quot;ember-views/system/render_buffer&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/system/utils&quot;, &quot;ember-views/system/jquery&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // jQuery
+
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var setInnerHTML = __dependency4__.setInnerHTML;
+        var jQuery = __dependency5__[&quot;default&quot;];
+
+        function ClassSet() {
+            this.seen = {};
+            this.list = [];
+        }
+
+        ClassSet.prototype = {
+            add: function(string) {
+                if (string in this.seen) {
+                    return;
+                }
+                this.seen[string] = true;
+
+                this.list.push(string);
+            },
+
+            toDOM: function() {
+                return this.list.join(&quot; &quot;);
+            }
+        };
+
+        var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z0-9\-]/;
+        var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z0-9\-]/g;
+
+        function stripTagName(tagName) {
+            if (!tagName) {
+                return tagName;
+            }
+
+            if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
+                return tagName;
+            }
+
+            return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
+        }
+
+        var BAD_CHARS_REGEXP = /&amp;(?!\w+;)|[&lt;&gt;&quot;'`]/g;
+        var POSSIBLE_CHARS_REGEXP = /[&amp;&lt;&gt;&quot;'`]/;
+
+        function escapeAttribute(value) {
+            // Stolen shamelessly from Handlebars
+
+            var escape = {
+                &quot;&lt;&quot;: &quot;&amp;lt;&quot;,
+                &quot;&gt;&quot;: &quot;&amp;gt;&quot;,
+                '&quot;': &quot;&amp;quot;&quot;,
+                &quot;'&quot;: &quot;&amp;#x27;&quot;,
+                &quot;`&quot;: &quot;&amp;#x60;&quot;
+            };
+
+            var escapeChar = function(chr) {
+                return escape[chr] || &quot;&amp;amp;&quot;;
+            };
+
+            var string = value.toString();
+
+            if (!POSSIBLE_CHARS_REGEXP.test(string)) {
+                return string;
+            }
+            return string.replace(BAD_CHARS_REGEXP, escapeChar);
+        }
+
+        // IE 6/7 have bugs around setting names on inputs during creation.
+        // From http://msdn.microsoft.com/en-us/library/ie/ms536389(v=vs.85).aspx:
+        // &quot;To include the NAME attribute at run time on objects created with the createElement method, use the eTag.&quot;
+        var canSetNameOnInputs = (function() {
+            var div = document.createElement('div'),
+            el = document.createElement('input');
+
+            el.setAttribute('name', 'foo');
+            div.appendChild(el);
+
+            return !!div.innerHTML.match('foo');
+        })();
+
+        /**
+              `Ember.RenderBuffer` gathers information regarding the view and generates the
+              final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
+              to the DOM.
+
+               ```javascript
+               var buffer = Ember.RenderBuffer('div');
+              ```
+
+              @class RenderBuffer
+              @namespace Ember
+              @constructor
+              @param {String} tagName tag name (such as 'div' or 'p') used for the buffer
+            */
+        __exports__[&quot;default&quot;] = function RenderBuffer(tagName) {
+            return new _RenderBuffer(tagName); // jshint ignore:line
+        }
+
+        function _RenderBuffer(tagName) {
+            this.tagNames = [tagName || null];
+            this.buffer = &quot;&quot;;
+        }
+
+        _RenderBuffer.prototype = {
+
+            // The root view's element
+            _element: null,
+
+            _hasElement: true,
+
+            /**
+                    An internal set used to de-dupe class names when `addClass()` is
+                    used. After each call to `addClass()`, the `classes` property
+                    will be updated.
+
+                    @private
+                    @property elementClasses
+                    @type Array
+                    @default null
+                  */
+            elementClasses: null,
+
+            /**
+                    Array of class names which will be applied in the class attribute.
+
+                    You can use `setClasses()` to set this property directly. If you
+                    use `addClass()`, it will be maintained for you.
+
+                    @property classes
+                    @type Array
+                    @default null
+                  */
+            classes: null,
+
+            /**
+                    The id in of the element, to be applied in the id attribute.
+
+                    You should not set this property yourself, rather, you should use
+                    the `id()` method of `Ember.RenderBuffer`.
+
+                    @property elementId
+                    @type String
+                    @default null
+                  */
+            elementId: null,
+
+            /**
+                    A hash keyed on the name of the attribute and whose value will be
+                    applied to that attribute. For example, if you wanted to apply a
+                    `data-view=&quot;Foo.bar&quot;` property to an element, you would set the
+                    elementAttributes hash to `{'data-view':'Foo.bar'}`.
+
+                    You should not maintain this hash yourself, rather, you should use
+                    the `attr()` method of `Ember.RenderBuffer`.
+
+                    @property elementAttributes
+                    @type Hash
+                    @default {}
+                  */
+            elementAttributes: null,
+
+            /**
+                    A hash keyed on the name of the properties and whose value will be
+                    applied to that property. For example, if you wanted to apply a
+                    `checked=true` property to an element, you would set the
+                    elementProperties hash to `{'checked':true}`.
+
+                    You should not maintain this hash yourself, rather, you should use
+                    the `prop()` method of `Ember.RenderBuffer`.
+
+                    @property elementProperties
+                    @type Hash
+                    @default {}
+                  */
+            elementProperties: null,
+
+            /**
+                    The tagname of the element an instance of `Ember.RenderBuffer` represents.
+
+                    Usually, this gets set as the first parameter to `Ember.RenderBuffer`. For
+                    example, if you wanted to create a `p` tag, then you would call
+
+                    ```javascript
+                    Ember.RenderBuffer('p')
+                    ```
+
+                    @property elementTag
+                    @type String
+                    @default null
+                  */
+            elementTag: null,
+
+            /**
+                    A hash keyed on the name of the style attribute and whose value will
+                    be applied to that attribute. For example, if you wanted to apply a
+                    `background-color:black;` style to an element, you would set the
+                    elementStyle hash to `{'background-color':'black'}`.
+
+                    You should not maintain this hash yourself, rather, you should use
+                    the `style()` method of `Ember.RenderBuffer`.
+
+                    @property elementStyle
+                    @type Hash
+                    @default {}
+                  */
+            elementStyle: null,
+
+            /**
+                    Adds a string of HTML to the `RenderBuffer`.
+
+                    @method push
+                    @param {String} string HTML to push into the buffer
+                    @chainable
+                  */
+            push: function(string) {
+                this.buffer += string;
+                return this;
+            },
+
+            /**
+                    Adds a class to the buffer, which will be rendered to the class attribute.
+
+                    @method addClass
+                    @param {String} className Class name to add to the buffer
+                    @chainable
+                  */
+            addClass: function(className) {
+                // lazily create elementClasses
+                this.elementClasses = (this.elementClasses || new ClassSet());
+                this.elementClasses.add(className);
+                this.classes = this.elementClasses.list;
+
+                return this;
+            },
+
+            setClasses: function(classNames) {
+                this.elementClasses = null;
+                var len = classNames.length, i;
+                for (i = 0; i &lt; len; i++) {
+                    this.addClass(classNames[i]);
+                }
+            },
+
+            /**
+                    Sets the elementID to be used for the element.
+
+                    @method id
+                    @param {String} id
+                    @chainable
+                  */
+            id: function(id) {
+                this.elementId = id;
+                return this;
+            },
+
+            // duck type attribute functionality like jQuery so a render buffer
+            // can be used like a jQuery object in attribute binding scenarios.
+
+            /**
+                    Adds an attribute which will be rendered to the element.
+
+                    @method attr
+                    @param {String} name The name of the attribute
+                    @param {String} value The value to add to the attribute
+                    @chainable
+                    @return {Ember.RenderBuffer|String} this or the current attribute value
+                  */
+            attr: function(name, value) {
+                var attributes = this.elementAttributes = (this.elementAttributes || {});
+
+                if (arguments.length === 1) {
+                    return attributes[name];
+                } else {
+                    attributes[name] = value;
+                }
+
+                return this;
+            },
+
+            /**
+                    Remove an attribute from the list of attributes to render.
+
+                    @method removeAttr
+                    @param {String} name The name of the attribute
+                    @chainable
+                  */
+            removeAttr: function(name) {
+                var attributes = this.elementAttributes;
+                if (attributes) {
+                    delete attributes[name];
+                }
+
+                return this;
+            },
+
+            /**
+                    Adds a property which will be rendered to the element.
+
+                    @method prop
+                    @param {String} name The name of the property
+                    @param {String} value The value to add to the property
+                    @chainable
+                    @return {Ember.RenderBuffer|String} this or the current property value
+                  */
+            prop: function(name, value) {
+                var properties = this.elementProperties = (this.elementProperties || {});
+
+                if (arguments.length === 1) {
+                    return properties[name];
+                } else {
+                    properties[name] = value;
+                }
+
+                return this;
+            },
+
+            /**
+                    Remove an property from the list of properties to render.
+
+                    @method removeProp
+                    @param {String} name The name of the property
+                    @chainable
+                  */
+            removeProp: function(name) {
+                var properties = this.elementProperties;
+                if (properties) {
+                    delete properties[name];
+                }
+
+                return this;
+            },
+
+            /**
+                    Adds a style to the style attribute which will be rendered to the element.
+
+                    @method style
+                    @param {String} name Name of the style
+                    @param {String} value
+                    @chainable
+                  */
+            style: function(name, value) {
+                this.elementStyle = (this.elementStyle || {});
+
+                this.elementStyle[name] = value;
+                return this;
+            },
+
+            begin: function(tagName) {
+                this.tagNames.push(tagName || null);
+                return this;
+            },
+
+            pushOpeningTag: function() {
+                var tagName = this.currentTagName();
+                if (!tagName) {
+                    return;
+                }
+
+                if (this._hasElement &amp;&amp; !this._element &amp;&amp; this.buffer.length === 0) {
+                    this._element = this.generateElement();
+                    return;
+                }
+
+                var buffer = this.buffer,
+                id = this.elementId,
+                classes = this.classes,
+                attrs = this.elementAttributes,
+                props = this.elementProperties,
+                style = this.elementStyle,
+                attr, prop;
+
+                buffer += '&lt;' + stripTagName(tagName);
+
+                if (id) {
+                    buffer += ' id=&quot;' + escapeAttribute(id) + '&quot;';
+                    this.elementId = null;
+                }
+                if (classes) {
+                    buffer += ' class=&quot;' + escapeAttribute(classes.join(' ')) + '&quot;';
+                    this.classes = null;
+                    this.elementClasses = null;
+                }
+
+                if (style) {
+                    buffer += ' style=&quot;';
+
+                    for (prop in style) {
+                        if (style.hasOwnProperty(prop)) {
+                            buffer += prop + ':' + escapeAttribute(style[prop]) + ';';
+                        }
+                    }
+
+                    buffer += '&quot;';
+
+                    this.elementStyle = null;
+                }
+
+                if (attrs) {
+                    for (attr in attrs) {
+                        if (attrs.hasOwnProperty(attr)) {
+                            buffer += ' ' + attr + '=&quot;' + escapeAttribute(attrs[attr]) + '&quot;';
+                        }
+                    }
+
+                    this.elementAttributes = null;
+                }
+
+                if (props) {
+                    for (prop in props) {
+                        if (props.hasOwnProperty(prop)) {
+                            var value = props[prop];
+                            if (value || typeof(value) === 'number') {
+                                if (value === true) {
+                                    buffer += ' ' + prop + '=&quot;' + prop + '&quot;';
+                                } else {
+                                    buffer += ' ' + prop + '=&quot;' + escapeAttribute(props[prop]) + '&quot;';
+                                }
+                            }
+                        }
+                    }
+
+                    this.elementProperties = null;
+                }
+
+                buffer += '&gt;';
+                this.buffer = buffer;
+            },
+
+            pushClosingTag: function() {
+                var tagName = this.tagNames.pop();
+                if (tagName) {
+                    this.buffer += '&lt;/' + stripTagName(tagName) + '&gt;';
+                }
+            },
+
+            currentTagName: function() {
+                return this.tagNames[this.tagNames.length-1];
+            },
+
+            generateElement: function() {
+                var tagName = this.tagNames.pop(), // pop since we don't need to close
+                id = this.elementId,
+                classes = this.classes,
+                attrs = this.elementAttributes,
+                props = this.elementProperties,
+                style = this.elementStyle,
+                styleBuffer = '', attr, prop, tagString;
+
+                if (attrs &amp;&amp; attrs.name &amp;&amp; !canSetNameOnInputs) {
+                    // IE allows passing a tag to createElement. See note on `canSetNameOnInputs` above as well.
+                    tagString = '&lt;' + stripTagName(tagName) + ' name=&quot;' + escapeAttribute(attrs.name) + '&quot;&gt;';
+                } else {
+                    tagString = tagName;
+                }
+
+                var element = document.createElement(tagString),
+                $element = jQuery(element);
+
+                if (id) {
+                    $element.attr('id', id);
+                    this.elementId = null;
+                }
+                if (classes) {
+                    $element.attr('class', classes.join(' '));
+                    this.classes = null;
+                    this.elementClasses = null;
+                }
+
+                if (style) {
+                    for (prop in style) {
+                        if (style.hasOwnProperty(prop)) {
+                            styleBuffer += (prop + ':' + style[prop] + ';');
+                        }
+                    }
+
+                    $element.attr('style', styleBuffer);
+
+                    this.elementStyle = null;
+                }
+
+                if (attrs) {
+                    for (attr in attrs) {
+                        if (attrs.hasOwnProperty(attr)) {
+                            $element.attr(attr, attrs[attr]);
+                        }
+                    }
+
+                    this.elementAttributes = null;
+                }
+
+                if (props) {
+                    for (prop in props) {
+                        if (props.hasOwnProperty(prop)) {
+                            $element.prop(prop, props[prop]);
+                        }
+                    }
+
+                    this.elementProperties = null;
+                }
+
+                return element;
+            },
+
+            /**
+                    @method element
+                    @return {DOMElement} The element corresponding to the generated HTML
+                      of this buffer
+                  */
+            element: function() {
+                var html = this.innerString();
+
+                if (html) {
+                    this._element = setInnerHTML(this._element, html);
+                }
+
+                return this._element;
+            },
+
+            /**
+                    Generates the HTML content for this buffer.
+
+                    @method string
+                    @return {String} The generated HTML
+                  */
+            string: function() {
+                if (this._hasElement &amp;&amp; this._element) {
+                    // Firefox versions &lt; 11 do not have support for element.outerHTML.
+                    var thisElement = this.element(), outerHTML = thisElement.outerHTML;
+                    if (typeof outerHTML === 'undefined') {
+                        return jQuery('&lt;div/&gt;').append(thisElement).html();
+                    }
+                    return outerHTML;
+                } else {
+                    return this.innerString();
+                }
+            },
+
+            innerString: function() {
+                return this.buffer;
+            }
+        };
+    });
+    define(&quot;ember-views/system/utils&quot;,
+    [&quot;ember-metal/core&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        /* globals XMLSerializer */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        /* BEGIN METAMORPH HELPERS */
+
+        // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
+        // is a &quot;zero-scope&quot; element. This problem can be worked around by making
+        // the first node an invisible text node. We, like Modernizr, use &amp;shy;
+
+        var needsShy = typeof document !== 'undefined' &amp;&amp; (function() {
+            var testEl = document.createElement('div');
+            testEl.innerHTML = &quot;&lt;div&gt;&lt;/div&gt;&quot;;
+            testEl.firstChild.innerHTML = &quot;&lt;script&gt;&lt;/script&gt;&quot;;
+            return testEl.firstChild.innerHTML === '';
+        })();
+
+        // IE 8 (and likely earlier) likes to move whitespace preceeding
+        // a script tag to appear after it. This means that we can
+        // accidentally remove whitespace when updating a morph.
+        var movesWhitespace = typeof document !== 'undefined' &amp;&amp; (function() {
+            var testEl = document.createElement('div');
+            testEl.innerHTML = &quot;Test: &lt;script type='text/x-placeholder'&gt;&lt;/script&gt;Value&quot;;
+            return testEl.childNodes[0].nodeValue === 'Test:' &amp;&amp;
+            testEl.childNodes[2].nodeValue === ' Value';
+        })();
+
+        // Use this to find children by ID instead of using jQuery
+        var findChildById = function(element, id) {
+            if (element.getAttribute('id') === id) {
+                return element;
+            }
+
+            var len = element.childNodes.length, idx, node, found;
+            for (idx = 0; idx &lt; len; idx++) {
+                node = element.childNodes[idx];
+                found = node.nodeType === 1 &amp;&amp; findChildById(node, id);
+                if (found) {
+                    return found;
+                }
+            }
+        };
+
+        var setInnerHTMLWithoutFix = function(element, html) {
+            if (needsShy) {
+                html = '&amp;shy;' + html;
+            }
+
+            var matches = [];
+            if (movesWhitespace) {
+                // Right now we only check for script tags with ids with the
+                // goal of targeting morphs.
+                html = html.replace(/(\s+)(&lt;script id='([^']+)')/g, function(match, spaces, tag, id) {
+                    matches.push([id, spaces]);
+                    return tag;
+                });
+            }
+
+            element.innerHTML = html;
+
+            // If we have to do any whitespace adjustments do them now
+            if (matches.length &gt; 0) {
+                var len = matches.length, idx;
+                for (idx = 0; idx &lt; len; idx++) {
+                    var script = findChildById(element, matches[idx][0]),
+                    node = document.createTextNode(matches[idx][1]);
+                    script.parentNode.insertBefore(node, script);
+                }
+            }
+
+            if (needsShy) {
+                var shyElement = element.firstChild;
+                while (shyElement.nodeType === 1 &amp;&amp; !shyElement.nodeName) {
+                    shyElement = shyElement.firstChild;
+                }
+                if (shyElement.nodeType === 3 &amp;&amp; shyElement.nodeValue.charAt(0) === &quot;\u00AD&quot;) {
+                    shyElement.nodeValue = shyElement.nodeValue.slice(1);
+                }
+            }
+        };
+
+        /* END METAMORPH HELPERS */
+
+
+        var innerHTMLTags = {};
+        var canSetInnerHTML = function(tagName) {
+            if (innerHTMLTags[tagName] !== undefined) {
+                return innerHTMLTags[tagName];
+            }
+
+            var canSet = true;
+
+            // IE 8 and earlier don't allow us to do innerHTML on select
+            if (tagName.toLowerCase() === 'select') {
+                var el = document.createElement('select');
+                setInnerHTMLWithoutFix(el, '&lt;option value=&quot;test&quot;&gt;Test&lt;/option&gt;');
+                canSet = el.options.length === 1;
+            }
+
+            innerHTMLTags[tagName] = canSet;
+
+            return canSet;
+        };
+
+        function setInnerHTML(element, html) {
+            var tagName = element.tagName;
+
+            if (canSetInnerHTML(tagName)) {
+                setInnerHTMLWithoutFix(element, html);
+            } else {
+                // Firefox versions &lt; 11 do not have support for element.outerHTML.
+                var outerHTML = element.outerHTML || new XMLSerializer().serializeToString(element);
+                Ember.assert(&quot;Can't set innerHTML on &quot; + element.tagName + &quot; in this browser&quot;, outerHTML);
+
+                var startTag = outerHTML.match(new RegExp(&quot;&lt;&quot; + tagName + &quot;([^&gt;]*)&gt;&quot;, 'i'))[0],
+                endTag = '&lt;/' + tagName + '&gt;';
+
+                var wrapper = document.createElement('div');
+                setInnerHTMLWithoutFix(wrapper, startTag + html + endTag);
+                element = wrapper.firstChild;
+                while (element.tagName !== tagName) {
+                    element = element.nextSibling;
+                }
+            }
+
+            return element;
+        }
+
+        __exports__.setInnerHTML = setInnerHTML;
+        function isSimpleClick(event) {
+            var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey,
+            secondaryClick = event.which &gt; 1; // IE9 may return undefined
+
+            return !modifier &amp;&amp; !secondaryClick;
+        }
+
+        __exports__.isSimpleClick = isSimpleClick;
+    });
+    define(&quot;ember-views/views/collection_view&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/binding&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-views/views/container_view&quot;, &quot;ember-views/views/core_view&quot;, &quot;ember-views/views/view&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/mixins/array&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) {
+        &quot;use strict&quot;;
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var create = __dependency2__.create;
+        var isGlobalPath = __dependency3__.isGlobalPath;
+        var merge = __dependency4__[&quot;default&quot;];
+        var get = __dependency5__.get;
+        var set = __dependency6__.set;
+        var fmt = __dependency7__.fmt;
+        var ContainerView = __dependency8__[&quot;default&quot;];
+        var CoreView = __dependency9__[&quot;default&quot;];
+        var View = __dependency10__[&quot;default&quot;];
+        var observer = __dependency11__.observer;
+        var beforeObserver = __dependency11__.beforeObserver;
+        var EmberArray = __dependency12__[&quot;default&quot;];
+
+        /**
+              `Ember.CollectionView` is an `Ember.View` descendent responsible for managing
+              a collection (an array or array-like object) by maintaining a child view object
+              and associated DOM representation for each item in the array and ensuring
+              that child views and their associated rendered HTML are updated when items in
+              the array are added, removed, or replaced.
+
+              ## Setting content
+
+              The managed collection of objects is referenced as the `Ember.CollectionView`
+              instance's `content` property.
+
+              ```javascript
+              someItemsView = Ember.CollectionView.create({
+                content: ['A', 'B','C']
+              })
+              ```
+
+              The view for each item in the collection will have its `content` property set
+              to the item.
+
+              ## Specifying itemViewClass
+
+              By default the view class for each item in the managed collection will be an
+              instance of `Ember.View`. You can supply a different class by setting the
+              `CollectionView`'s `itemViewClass` property.
+
+              Given an empty `&lt;body&gt;` and the following code:
+
+              ```javascript
+              someItemsView = Ember.CollectionView.create({
+                classNames: ['a-collection'],
+                content: ['A','B','C'],
+                itemViewClass: Ember.View.extend({
+                  template: Ember.Handlebars.compile(&quot;the letter: {{view.content}}&quot;)
+                })
+              });
+
+              someItemsView.appendTo('body');
+              ```
+
+              Will result in the following HTML structure
+
+              ```html
+              &lt;div class=&quot;ember-view a-collection&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;the letter: A&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;the letter: B&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;the letter: C&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ## Automatic matching of parent/child tagNames
+
+              Setting the `tagName` property of a `CollectionView` to any of
+              &quot;ul&quot;, &quot;ol&quot;, &quot;table&quot;, &quot;thead&quot;, &quot;tbody&quot;, &quot;tfoot&quot;, &quot;tr&quot;, or &quot;select&quot; will result
+              in the item views receiving an appropriately matched `tagName` property.
+
+              Given an empty `&lt;body&gt;` and the following code:
+
+              ```javascript
+              anUnorderedListView = Ember.CollectionView.create({
+                tagName: 'ul',
+                content: ['A','B','C'],
+                itemViewClass: Ember.View.extend({
+                  template: Ember.Handlebars.compile(&quot;the letter: {{view.content}}&quot;)
+                })
+              });
+
+              anUnorderedListView.appendTo('body');
+              ```
+
+              Will result in the following HTML structure
+
+              ```html
+              &lt;ul class=&quot;ember-view a-collection&quot;&gt;
+                &lt;li class=&quot;ember-view&quot;&gt;the letter: A&lt;/li&gt;
+                &lt;li class=&quot;ember-view&quot;&gt;the letter: B&lt;/li&gt;
+                &lt;li class=&quot;ember-view&quot;&gt;the letter: C&lt;/li&gt;
+              &lt;/ul&gt;
+              ```
+
+              Additional `tagName` pairs can be provided by adding to
+              `Ember.CollectionView.CONTAINER_MAP `
+
+              ```javascript
+              Ember.CollectionView.CONTAINER_MAP['article'] = 'section'
+              ```
+
+              ## Programmatic creation of child views
+
+              For cases where additional customization beyond the use of a single
+              `itemViewClass` or `tagName` matching is required CollectionView's
+              `createChildView` method can be overidden:
+
+              ```javascript
+              CustomCollectionView = Ember.CollectionView.extend({
+                createChildView: function(viewClass, attrs) {
+                  if (attrs.content.kind == 'album') {
+                    viewClass = App.AlbumView;
+                  } else {
+                    viewClass = App.SongView;
+                  }
+                  return this._super(viewClass, attrs);
+                }
+              });
+              ```
+
+              ## Empty View
+
+              You can provide an `Ember.View` subclass to the `Ember.CollectionView`
+              instance as its `emptyView` property. If the `content` property of a
+              `CollectionView` is set to `null` or an empty array, an instance of this view
+              will be the `CollectionView`s only child.
+
+              ```javascript
+              aListWithNothing = Ember.CollectionView.create({
+                classNames: ['nothing']
+                content: null,
+                emptyView: Ember.View.extend({
+                  template: Ember.Handlebars.compile(&quot;The collection is empty&quot;)
+                })
+              });
+
+              aListWithNothing.appendTo('body');
+              ```
+
+              Will result in the following HTML structure
+
+              ```html
+              &lt;div class=&quot;ember-view nothing&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;
+                  The collection is empty
+                &lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ## Adding and Removing items
+
+              The `childViews` property of a `CollectionView` should not be directly
+              manipulated. Instead, add, remove, replace items from its `content` property.
+              This will trigger appropriate changes to its rendered HTML.
+
+
+              @class CollectionView
+              @namespace Ember
+              @extends Ember.ContainerView
+              @since Ember 0.9
+            */
+        var CollectionView = ContainerView.extend({
+
+            /**
+                    A list of items to be displayed by the `Ember.CollectionView`.
+
+                    @property content
+                    @type Ember.Array
+                    @default null
+                  */
+            content: null,
+
+            /**
+                    This provides metadata about what kind of empty view class this
+                    collection would like if it is being instantiated from another
+                    system (like Handlebars)
+
+                    @private
+                    @property emptyViewClass
+                  */
+            emptyViewClass: View,
+
+            /**
+                    An optional view to display if content is set to an empty array.
+
+                    @property emptyView
+                    @type Ember.View
+                    @default null
+                  */
+            emptyView: null,
+
+            /**
+                    @property itemViewClass
+                    @type Ember.View
+                    @default Ember.View
+                  */
+            itemViewClass: View,
+
+            /**
+                    Setup a CollectionView
+
+                    @method init
+                  */
+            init: function() {
+                var ret = this._super();
+                this._contentDidChange();
+                return ret;
+            },
+
+            /**
+                    Invoked when the content property is about to change. Notifies observers that the
+                    entire array content will change.
+
+                    @private
+                    @method _contentWillChange
+                  */
+            _contentWillChange: beforeObserver('content', function() {
+                var content = this.get('content');
+
+                if (content) {
+                    content.removeArrayObserver(this);
+                }
+                var len = content ? get(content, 'length') : 0;
+                this.arrayWillChange(content, 0, len);
+            }),
+
+            /**
+                    Check to make sure that the content has changed, and if so,
+                    update the children directly. This is always scheduled
+                    asynchronously, to allow the element to be created before
+                    bindings have synchronized and vice versa.
+
+                    @private
+                    @method _contentDidChange
+                  */
+            _contentDidChange: observer('content', function() {
+                var content = get(this, 'content');
+
+                if (content) {
+                    this._assertArrayLike(content);
+                    content.addArrayObserver(this);
+                }
+
+                var len = content ? get(content, 'length') : 0;
+                this.arrayDidChange(content, 0, null, len);
+            }),
+
+            /**
+                    Ensure that the content implements Ember.Array
+
+                    @private
+                    @method _assertArrayLike
+                  */
+            _assertArrayLike: function(content) {
+                Ember.assert(fmt(&quot;an Ember.CollectionView's content must implement Ember.Array. You passed %@&quot;, [content]), EmberArray.detect(content));
+            },
+
+            /**
+                    Removes the content and content observers.
+
+                    @method destroy
+                  */
+            destroy: function() {
+                if (!this._super()) {
+                    return;
+                }
+
+                var content = get(this, 'content');
+                if (content) {
+                    content.removeArrayObserver(this);
+                }
+
+                if (this._createdEmptyView) {
+                    this._createdEmptyView.destroy();
+                }
+
+                return this;
+            },
+
+            /**
+                    Called when a mutation to the underlying content array will occur.
+
+                    This method will remove any views that are no longer in the underlying
+                    content array.
+
+                    Invokes whenever the content array itself will change.
+
+                    @method arrayWillChange
+                    @param {Array} content the managed collection of objects
+                    @param {Number} start the index at which the changes will occurr
+                    @param {Number} removed number of object to be removed from content
+                  */
+            arrayWillChange: function(content, start, removedCount) {
+                // If the contents were empty before and this template collection has an
+                // empty view remove it now.
+                var emptyView = get(this, 'emptyView');
+                if (emptyView &amp;&amp; emptyView instanceof View) {
+                    emptyView.removeFromParent();
+                }
+
+                // Loop through child views that correspond with the removed items.
+                // Note that we loop from the end of the array to the beginning because
+                // we are mutating it as we go.
+                var childViews = this._childViews, childView, idx, len;
+
+                len = this._childViews.length;
+
+                var removingAll = removedCount === len;
+
+                if (removingAll) {
+                    this.currentState.empty(this);
+                    this.invokeRecursively(function(view) {
+                        view.removedFromDOM = true;
+                    }, false);
+                }
+
+                for (idx = start + removedCount - 1; idx &gt;= start; idx--) {
+                    childView = childViews[idx];
+                    childView.destroy();
+                }
+            },
+
+            /**
+                    Called when a mutation to the underlying content array occurs.
+
+                    This method will replay that mutation against the views that compose the
+                    `Ember.CollectionView`, ensuring that the view reflects the model.
+
+                    This array observer is added in `contentDidChange`.
+
+                    @method arrayDidChange
+                    @param {Array} content the managed collection of objects
+                    @param {Number} start the index at which the changes occurred
+                    @param {Number} removed number of object removed from content
+                    @param {Number} added number of object added to content
+                  */
+            arrayDidChange: function(content, start, removed, added) {
+                var addedViews = [], view, item, idx, len, itemViewClass,
+                emptyView;
+
+                len = content ? get(content, 'length') : 0;
+
+                if (len) {
+                    itemViewClass = get(this, 'itemViewClass');
+
+                    if ('string' === typeof itemViewClass &amp;&amp; isGlobalPath(itemViewClass)) {
+                        itemViewClass = get(itemViewClass) || itemViewClass;
+                    }
+
+                    Ember.assert(fmt(&quot;itemViewClass must be a subclass of Ember.View, not %@&quot;,
+                    [itemViewClass]),
+                    'string' === typeof itemViewClass || View.detect(itemViewClass));
+
+                    for (idx = start; idx &lt; start + added; idx++) {
+                        item = content.objectAt(idx);
+
+                        view = this.createChildView(itemViewClass, {
+                            content: item,
+                            contentIndex: idx
+                        });
+
+                        addedViews.push(view);
+                    }
+                } else {
+                    emptyView = get(this, 'emptyView');
+
+                    if (!emptyView) {
+                        return;
+                    }
+
+                    if ('string' === typeof emptyView &amp;&amp; isGlobalPath(emptyView)) {
+                        emptyView = get(emptyView) || emptyView;
+                    }
+
+                    emptyView = this.createChildView(emptyView);
+                    addedViews.push(emptyView);
+                    set(this, 'emptyView', emptyView);
+
+                    if (CoreView.detect(emptyView)) {
+                        this._createdEmptyView = emptyView;
+                    }
+                }
+
+                this.replace(start, 0, addedViews);
+            },
+
+            /**
+                    Instantiates a view to be added to the childViews array during view
+                    initialization. You generally will not call this method directly unless
+                    you are overriding `createChildViews()`. Note that this method will
+                    automatically configure the correct settings on the new view instance to
+                    act as a child of the parent.
+
+                    The tag name for the view will be set to the tagName of the viewClass
+                    passed in.
+
+                    @method createChildView
+                    @param {Class} viewClass
+                    @param {Hash} [attrs] Attributes to add
+                    @return {Ember.View} new instance
+                  */
+            createChildView: function(view, attrs) {
+                view = this._super(view, attrs);
+
+                var itemTagName = get(view, 'tagName');
+
+                if (itemTagName === null || itemTagName === undefined) {
+                    itemTagName = CollectionView.CONTAINER_MAP[get(this, 'tagName')];
+                    set(view, 'tagName', itemTagName);
+                }
+
+                return view;
+            }
+        });
+
+        /**
+              A map of parent tags to their default child tags. You can add
+              additional parent tags if you want collection views that use
+              a particular parent tag to default to a child tag.
+
+              @property CONTAINER_MAP
+              @type Hash
+              @static
+              @final
+            */
+        CollectionView.CONTAINER_MAP = {
+            ul: 'li',
+            ol: 'li',
+            table: 'tr',
+            thead: 'tr',
+            tbody: 'tr',
+            tfoot: 'tr',
+            tr: 'td',
+            select: 'option'
+        };
+
+        __exports__[&quot;default&quot;] = CollectionView;
+    });
+    define(&quot;ember-views/views/component&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-views/mixins/component_template_deprecation&quot;, &quot;ember-runtime/mixins/target_action_support&quot;, &quot;ember-views/views/view&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/is_none&quot;, &quot;ember-metal/computed&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert, Ember.Handlebars
+
+        var ComponentTemplateDeprecation = __dependency2__[&quot;default&quot;];
+        var TargetActionSupport = __dependency3__[&quot;default&quot;];
+        var View = __dependency4__[&quot;default&quot;];
+
+        var get = __dependency5__.get;
+        var set = __dependency6__.set;
+        var isNone = __dependency7__.isNone;
+
+        var computed = __dependency8__.computed;
+
+        var a_slice = Array.prototype.slice;
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        /**
+              An `Ember.Component` is a view that is completely
+              isolated. Property access in its templates go
+              to the view object and actions are targeted at
+              the view object. There is no access to the
+              surrounding context or outer controller; all
+              contextual information must be passed in.
+
+              The easiest way to create an `Ember.Component` is via
+              a template. If you name a template
+              `components/my-foo`, you will be able to use
+              `{{my-foo}}` in other templates, which will make
+              an instance of the isolated component.
+
+              ```handlebars
+              {{app-profile person=currentUser}}
+              ```
+
+              ```handlebars
+              &lt;!-- app-profile template --&gt;
+              &lt;h1&gt;{{person.title}}&lt;/h1&gt;
+              &lt;img {{bind-attr src=person.avatar}}&gt;
+              &lt;p class='signature'&gt;{{person.signature}}&lt;/p&gt;
+              ```
+
+              You can use `yield` inside a template to
+              include the **contents** of any block attached to
+              the component. The block will be executed in the
+              context of the surrounding context or outer controller:
+
+              ```handlebars
+              {{#app-profile person=currentUser}}
+                &lt;p&gt;Admin mode&lt;/p&gt;
+                {{! Executed in the controller's context. }}
+              {{/app-profile}}
+              ```
+
+              ```handlebars
+              &lt;!-- app-profile template --&gt;
+              &lt;h1&gt;{{person.title}}&lt;/h1&gt;
+              {{! Executed in the components context. }}
+              {{yield}} {{! block contents }}
+              ```
+
+              If you want to customize the component, in order to
+              handle events or actions, you implement a subclass
+              of `Ember.Component` named after the name of the
+              component. Note that `Component` needs to be appended to the name of
+              your subclass like `AppProfileComponent`.
+
+              For example, you could implement the action
+              `hello` for the `app-profile` component:
+
+              ```javascript
+              App.AppProfileComponent = Ember.Component.extend({
+                actions: {
+                  hello: function(name) {
+                    console.log(&quot;Hello&quot;, name);
+                  }
+                }
+              });
+              ```
+
+              And then use it in the component's template:
+
+              ```handlebars
+              &lt;!-- app-profile template --&gt;
+
+              &lt;h1&gt;{{person.title}}&lt;/h1&gt;
+              {{yield}} &lt;!-- block contents --&gt;
+
+              &lt;button {{action 'hello' person.name}}&gt;
+                Say Hello to {{person.name}}
+              &lt;/button&gt;
+              ```
+
+              Components must have a `-` in their name to avoid
+              conflicts with built-in controls that wrap HTML
+              elements. This is consistent with the same
+              requirement in web components.
+
+              @class Component
+              @namespace Ember
+              @extends Ember.View
+            */
+        var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, {
+            instrumentName: 'component',
+            instrumentDisplay: computed(function() {
+                if (this._debugContainerKey) {
+                    return '{{' + this._debugContainerKey.split(':')[1] + '}}';
+                }
+            }),
+
+            init: function() {
+                this._super();
+                set(this, 'origContext', get(this, 'context'));
+                set(this, 'context', this);
+                set(this, 'controller', this);
+            },
+
+            defaultLayout: function(context, options) {
+                Ember.Handlebars.helpers['yield'].call(context, options);
+            },
+
+            /**
+                  A components template property is set by passing a block
+                  during its invocation. It is executed within the parent context.
+
+                  Example:
+
+                  ```handlebars
+                  {{#my-component}}
+                    // something that is run in the context
+                    // of the parent context
+                  {{/my-component}}
+                  ```
+
+                  Specifying a template directly to a component is deprecated without
+                  also specifying the layout property.
+
+                  @deprecated
+                  @property template
+                  */
+            template: computed(function(key, value) {
+                if (value !== undefined) {
+                    return value;
+                }
+
+                var templateName = get(this, 'templateName'),
+                template = this.templateForName(templateName, 'template');
+
+                Ember.assert(&quot;You specified the templateName &quot; + templateName + &quot; for &quot; + this + &quot;, but it did not exist.&quot;, !templateName || template);
+
+                return template || get(this, 'defaultTemplate');
+            }).property('templateName'),
+
+            /**
+                  Specifying a components `templateName` is deprecated without also
+                  providing the `layout` or `layoutName` properties.
+
+                  @deprecated
+                  @property templateName
+                  */
+            templateName: null,
+
+            // during render, isolate keywords
+            cloneKeywords: function() {
+                return {
+                    view: this,
+                    controller: this
+                };
+            },
+
+            _yield: function(context, options) {
+                var view = options.data.view,
+                parentView = this._parentView,
+                template = get(this, 'template');
+
+                if (template) {
+                    Ember.assert(&quot;A Component must have a parent view in order to yield.&quot;, parentView);
+
+                    view.appendChild(View, {
+                        isVirtual: true,
+                        tagName: '',
+                        _contextView: parentView,
+                        template: template,
+                        context: options.data.insideGroup ? get(this, 'origContext') : get(parentView, 'context'),
+                        controller: get(parentView, 'controller'),
+                        templateData: {
+                            keywords: parentView.cloneKeywords(),
+                            insideGroup: options.data.insideGroup 
+                        }
+                    });
+                }
+            },
+
+            /**
+                    If the component is currently inserted into the DOM of a parent view, this
+                    property will point to the controller of the parent view.
+
+                    @property targetObject
+                    @type Ember.Controller
+                    @default null
+                  */
+            targetObject: computed(function(key) {
+                var parentView = get(this, '_parentView');
+                return parentView ? get(parentView, 'controller') : null;
+            }).property('_parentView'),
+
+            /**
+                    Triggers a named action on the controller context where the component is used if
+                    this controller has registered for notifications of the action.
+
+                    For example a component for playing or pausing music may translate click events
+                    into action notifications of &quot;play&quot; or &quot;stop&quot; depending on some internal state
+                    of the component:
+
+
+                    ```javascript
+                    App.PlayButtonComponent = Ember.Component.extend({
+                      click: function(){
+                        if (this.get('isPlaying')) {
+                          this.sendAction('play');
+                        } else {
+                          this.sendAction('stop');
+                        }
+                      }
+                    });
+                    ```
+
+                    When used inside a template these component actions are configured to
+                    trigger actions in the outer application context:
+
+                    ```handlebars
+                    {{! application.hbs }}
+                    {{play-button play=&quot;musicStarted&quot; stop=&quot;musicStopped&quot;}}
+                    ```
+
+                    When the component receives a browser `click` event it translate this
+                    interaction into application-specific semantics (&quot;play&quot; or &quot;stop&quot;) and
+                    triggers the specified action name on the controller for the template
+                    where the component is used:
+
+
+                    ```javascript
+                    App.ApplicationController = Ember.Controller.extend({
+                      actions: {
+                        musicStarted: function(){
+                          // called when the play button is clicked
+                          // and the music started playing
+                        },
+                        musicStopped: function(){
+                          // called when the play button is clicked
+                          // and the music stopped playing
+                        }
+                      }
+                    });
+                    ```
+
+                    If no action name is passed to `sendAction` a default name of &quot;action&quot;
+                    is assumed.
+
+                    ```javascript
+                    App.NextButtonComponent = Ember.Component.extend({
+                      click: function(){
+                        this.sendAction();
+                      }
+                    });
+                    ```
+
+                    ```handlebars
+                    {{! application.hbs }}
+                    {{next-button action=&quot;playNextSongInAlbum&quot;}}
+                    ```
+
+                    ```javascript
+                    App.ApplicationController = Ember.Controller.extend({
+                      actions: {
+                        playNextSongInAlbum: function(){
+                          ...
+                        }
+                      }
+                    });
+                    ```
+
+                    @method sendAction
+                    @param [action] {String} the action to trigger
+                    @param [context] {*} a context to send with the action
+                  */
+            sendAction: function(action) {
+                var actionName,
+                contexts = a_slice.call(arguments, 1);
+
+                // Send the default action
+                if (action === undefined) {
+                    actionName = get(this, 'action');
+                    Ember.assert(&quot;The default action was triggered on the component &quot; + this.toString() +
+                    &quot;, but the action name (&quot; + actionName + &quot;) was not a string.&quot;,
+                    isNone(actionName) || typeof actionName === 'string');
+                } else {
+                    actionName = get(this, action);
+                    Ember.assert(&quot;The &quot; + action + &quot; action was triggered on the component &quot; +
+                    this.toString() + &quot;, but the action name (&quot; + actionName +
+                    &quot;) was not a string.&quot;,
+                    isNone(actionName) || typeof actionName === 'string');
+                }
+
+                // If no action name for that action could be found, just abort.
+                if (actionName === undefined) {
+                    return;
+                }
+
+                this.triggerAction({
+                    action: actionName,
+                    actionContext: contexts
+                });
+            }
+        });
+
+        __exports__[&quot;default&quot;] = Component;
+    });
+    define(&quot;ember-views/views/container_view&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/merge&quot;, &quot;ember-runtime/mixins/mutable_array&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-views/views/view&quot;, &quot;ember-views/views/view_collection&quot;, &quot;ember-views/views/states&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/properties&quot;, &quot;ember-views/system/render_buffer&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert, Ember.K
+
+        var merge = __dependency2__[&quot;default&quot;];
+        var MutableArray = __dependency3__[&quot;default&quot;];
+        var get = __dependency4__.get;
+        var set = __dependency5__.set;
+
+        var View = __dependency6__[&quot;default&quot;];
+        var ViewCollection = __dependency7__[&quot;default&quot;];
+
+        var cloneStates = __dependency8__.cloneStates;
+        var EmberViewStates = __dependency8__.states;
+
+        var EmberError = __dependency9__[&quot;default&quot;];
+
+        var forEach = __dependency10__.forEach;
+
+        var computed = __dependency11__.computed;
+        var run = __dependency12__[&quot;default&quot;];
+        var defineProperty = __dependency13__.defineProperty;
+        var renderBuffer = __dependency14__[&quot;default&quot;];
+        var observer = __dependency15__.observer;
+        var beforeObserver = __dependency15__.beforeObserver;
+        var emberA = __dependency16__.A;
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var states = cloneStates(EmberViewStates);
+
+        /**
+              A `ContainerView` is an `Ember.View` subclass that implements `Ember.MutableArray`
+              allowing programmatic management of its child views.
+
+              ## Setting Initial Child Views
+
+              The initial array of child views can be set in one of two ways. You can
+              provide a `childViews` property at creation time that contains instance of
+              `Ember.View`:
+
+              ```javascript
+              aContainer = Ember.ContainerView.create({
+                childViews: [Ember.View.create(), Ember.View.create()]
+              });
+              ```
+
+              You can also provide a list of property names whose values are instances of
+              `Ember.View`:
+
+              ```javascript
+              aContainer = Ember.ContainerView.create({
+                childViews: ['aView', 'bView', 'cView'],
+                aView: Ember.View.create(),
+                bView: Ember.View.create(),
+                cView: Ember.View.create()
+              });
+              ```
+
+              The two strategies can be combined:
+
+              ```javascript
+              aContainer = Ember.ContainerView.create({
+                childViews: ['aView', Ember.View.create()],
+                aView: Ember.View.create()
+              });
+              ```
+
+              Each child view's rendering will be inserted into the container's rendered
+              HTML in the same order as its position in the `childViews` property.
+
+              ## Adding and Removing Child Views
+
+              The container view implements `Ember.MutableArray` allowing programmatic management of its child views.
+
+              To remove a view, pass that view into a `removeObject` call on the container view.
+
+              Given an empty `&lt;body&gt;` the following code
+
+              ```javascript
+              aContainer = Ember.ContainerView.create({
+                classNames: ['the-container'],
+                childViews: ['aView', 'bView'],
+                aView: Ember.View.create({
+                  template: Ember.Handlebars.compile(&quot;A&quot;)
+                }),
+                bView: Ember.View.create({
+                  template: Ember.Handlebars.compile(&quot;B&quot;)
+                })
+              });
+
+              aContainer.appendTo('body');
+              ```
+
+              Results in the HTML
+
+              ```html
+              &lt;div class=&quot;ember-view the-container&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;A&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;B&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              Removing a view
+
+              ```javascript
+              aContainer.toArray();  // [aContainer.aView, aContainer.bView]
+              aContainer.removeObject(aContainer.get('bView'));
+              aContainer.toArray();  // [aContainer.aView]
+              ```
+
+              Will result in the following HTML
+
+              ```html
+              &lt;div class=&quot;ember-view the-container&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;A&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              Similarly, adding a child view is accomplished by adding `Ember.View` instances to the
+              container view.
+
+              Given an empty `&lt;body&gt;` the following code
+
+              ```javascript
+              aContainer = Ember.ContainerView.create({
+                classNames: ['the-container'],
+                childViews: ['aView', 'bView'],
+                aView: Ember.View.create({
+                  template: Ember.Handlebars.compile(&quot;A&quot;)
+                }),
+                bView: Ember.View.create({
+                  template: Ember.Handlebars.compile(&quot;B&quot;)
+                })
+              });
+
+              aContainer.appendTo('body');
+              ```
+
+              Results in the HTML
+
+              ```html
+              &lt;div class=&quot;ember-view the-container&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;A&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;B&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              Adding a view
+
+              ```javascript
+              AnotherViewClass = Ember.View.extend({
+                template: Ember.Handlebars.compile(&quot;Another view&quot;)
+              });
+
+              aContainer.toArray();  // [aContainer.aView, aContainer.bView]
+              aContainer.pushObject(AnotherViewClass.create());
+              aContainer.toArray(); // [aContainer.aView, aContainer.bView, &lt;AnotherViewClass instance&gt;]
+              ```
+
+              Will result in the following HTML
+
+              ```html
+              &lt;div class=&quot;ember-view the-container&quot;&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;A&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;B&lt;/div&gt;
+                &lt;div class=&quot;ember-view&quot;&gt;Another view&lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              ## Templates and Layout
+
+              A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or
+              `defaultLayout` property on a container view will not result in the template
+              or layout being rendered. The HTML contents of a `Ember.ContainerView`'s DOM
+              representation will only be the rendered HTML of its child views.
+
+              @class ContainerView
+              @namespace Ember
+              @extends Ember.View
+            */
+        var ContainerView = View.extend(MutableArray, {
+            _states: states,
+
+            init: function() {
+                this._super();
+
+                var childViews = get(this, 'childViews');
+
+                // redefine view's childViews property that was obliterated
+                defineProperty(this, 'childViews', View.childViewsProperty);
+
+                var _childViews = this._childViews;
+
+                forEach(childViews, function(viewName, idx) {
+                    var view;
+
+                    if ('string' === typeof viewName) {
+                        view = get(this, viewName);
+                        view = this.createChildView(view);
+                        set(this, viewName, view);
+                    } else {
+                        view = this.createChildView(viewName);
+                    }
+
+                    _childViews[idx] = view;
+                }, this);
+
+                var currentView = get(this, 'currentView');
+                if (currentView) {
+                    if (!_childViews.length) {
+                        _childViews = this._childViews = this._childViews.slice();
+                    }
+                    _childViews.push(this.createChildView(currentView));
+                }
+            },
+
+            replace: function(idx, removedCount, addedViews) {
+                var addedCount = addedViews ? get(addedViews, 'length') : 0;
+                var self = this;
+                Ember.assert(&quot;You can't add a child to a container - the child is already a child of another view&quot;, emberA(addedViews).every(function(item) {
+                    return !get(item, '_parentView') || get(item, '_parentView') === self;
+                }));
+
+                this.arrayContentWillChange(idx, removedCount, addedCount);
+                this.childViewsWillChange(this._childViews, idx, removedCount);
+
+                if (addedCount === 0) {
+                    this._childViews.splice(idx, removedCount) ;
+                } else {
+                    var args = [idx, removedCount].concat(addedViews);
+                    if (addedViews.length &amp;&amp; !this._childViews.length) {
+                        this._childViews = this._childViews.slice();
+                    }
+                    this._childViews.splice.apply(this._childViews, args);
+                }
+
+                this.arrayContentDidChange(idx, removedCount, addedCount);
+                this.childViewsDidChange(this._childViews, idx, removedCount, addedCount);
+
+                return this;
+            },
+
+            objectAt: function(idx) {
+                return this._childViews[idx];
+            },
+
+            length: computed(function () {
+                return this._childViews.length;
+            })[&quot;volatile&quot;](),
+
+            /**
+                    Instructs each child view to render to the passed render buffer.
+
+                    @private
+                    @method render
+                    @param {Ember.RenderBuffer} buffer the buffer to render to
+                  */
+            render: function(buffer) {
+                this.forEachChildView(function(view) {
+                    view.renderToBuffer(buffer);
+                });
+            },
+
+            instrumentName: 'container',
+
+            /**
+                    When a child view is removed, destroy its element so that
+                    it is removed from the DOM.
+
+                    The array observer that triggers this action is set up in the
+                    `renderToBuffer` method.
+
+                    @private
+                    @method childViewsWillChange
+                    @param {Ember.Array} views the child views array before mutation
+                    @param {Number} start the start position of the mutation
+                    @param {Number} removed the number of child views removed
+                  **/
+            childViewsWillChange: function(views, start, removed) {
+                this.propertyWillChange('childViews');
+
+                if (removed &gt; 0) {
+                    var changedViews = views.slice(start, start + removed);
+                    // transition to preRender before clearing parentView
+                    this.currentState.childViewsWillChange(this, views, start, removed);
+                    this.initializeViews(changedViews, null, null);
+                }
+            },
+
+            removeChild: function(child) {
+                this.removeObject(child);
+                return this;
+            },
+
+            /**
+                    When a child view is added, make sure the DOM gets updated appropriately.
+
+                    If the view has already rendered an element, we tell the child view to
+                    create an element and insert it into the DOM. If the enclosing container
+                    view has already written to a buffer, but not yet converted that buffer
+                    into an element, we insert the string representation of the child into the
+                    appropriate place in the buffer.
+
+                    @private
+                    @method childViewsDidChange
+                    @param {Ember.Array} views the array of child views after the mutation has occurred
+                    @param {Number} start the start position of the mutation
+                    @param {Number} removed the number of child views removed
+                    @param {Number} added the number of child views added
+                  */
+            childViewsDidChange: function(views, start, removed, added) {
+                if (added &gt; 0) {
+                    var changedViews = views.slice(start, start + added);
+                    this.initializeViews(changedViews, this, get(this, 'templateData'));
+                    this.currentState.childViewsDidChange(this, views, start, added);
+                }
+                this.propertyDidChange('childViews');
+            },
+
+            initializeViews: function(views, parentView, templateData) {
+                forEach(views, function(view) {
+                    set(view, '_parentView', parentView);
+
+                    if (!view.container &amp;&amp; parentView) {
+                        set(view, 'container', parentView.container);
+                    }
+
+                    if (!get(view, 'templateData')) {
+                        set(view, 'templateData', templateData);
+                    }
+                });
+            },
+
+            currentView: null,
+
+            _currentViewWillChange: beforeObserver('currentView', function() {
+                var currentView = get(this, 'currentView');
+                if (currentView) {
+                    currentView.destroy();
+                }
+            }),
+
+            _currentViewDidChange: observer('currentView', function() {
+                var currentView = get(this, 'currentView');
+                if (currentView) {
+                    Ember.assert(&quot;You tried to set a current view that already has a parent. Make sure you don't have multiple outlets in the same view.&quot;, !get(currentView, '_parentView'));
+                    this.pushObject(currentView);
+                }
+            }),
+
+            _ensureChildrenAreInDOM: function () {
+                this.currentState.ensureChildrenAreInDOM(this);
+            }
+        });
+
+        merge(states._default, {
+            childViewsWillChange: Ember.K,
+            childViewsDidChange: Ember.K,
+            ensureChildrenAreInDOM: Ember.K
+        });
+
+        merge(states.inBuffer, {
+            childViewsDidChange: function(parentView, views, start, added) {
+                throw new EmberError('You cannot modify child views while in the inBuffer state');
+            }
+        });
+
+        merge(states.hasElement, {
+            childViewsWillChange: function(view, views, start, removed) {
+                for (var i = start; i &lt; start + removed; i++) {
+                    views[i].remove();
+                }
+            },
+
+            childViewsDidChange: function(view, views, start, added) {
+                run.scheduleOnce('render', view, '_ensureChildrenAreInDOM');
+            },
+
+            ensureChildrenAreInDOM: function(view) {
+                var childViews = view._childViews, i, len, childView, previous, buffer, viewCollection = new ViewCollection();
+
+                for (i = 0, len = childViews.length; i &lt; len; i++) {
+                    childView = childViews[i];
+
+                    if (!buffer) {
+                        buffer = renderBuffer();
+                        buffer._hasElement = false;
+                    }
+
+                    if (childView.renderToBufferIfNeeded(buffer)) {
+                        viewCollection.push(childView);
+                    } else if (viewCollection.length) {
+                        insertViewCollection(view, viewCollection, previous, buffer);
+                        buffer = null;
+                        previous = childView;
+                        viewCollection.clear();
+                    } else {
+                        previous = childView;
+                    }
+                }
+
+                if (viewCollection.length) {
+                    insertViewCollection(view, viewCollection, previous, buffer);
+                }
+            }
+        });
+
+        function insertViewCollection(view, viewCollection, previous, buffer) {
+            viewCollection.triggerRecursively('willInsertElement');
+
+            if (previous) {
+                previous.domManager.after(previous, buffer.string());
+            } else {
+                view.domManager.prepend(view, buffer.string());
+            }
+
+            viewCollection.forEach(function(v) {
+                v._transitionTo('inDOM');
+                v.propertyDidChange('element');
+                v.triggerRecursively('didInsertElement');
+            });
+        }
+
+
+        __exports__[&quot;default&quot;] = ContainerView;
+    });
+    define(&quot;ember-views/views/core_view&quot;,
+    [&quot;ember-views/views/states&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-runtime/mixins/evented&quot;, &quot;ember-runtime/mixins/action_handler&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/instrumentation&quot;, &quot;ember-views/system/render_buffer&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) {
+        &quot;use strict&quot;;
+        var cloneStates = __dependency1__.cloneStates;
+        var states = __dependency1__.states;
+        var EmberObject = __dependency2__[&quot;default&quot;];
+        var Evented = __dependency3__[&quot;default&quot;];
+        var ActionHandler = __dependency4__[&quot;default&quot;];
+
+        var defineProperty = __dependency5__.defineProperty;
+        var deprecateProperty = __dependency5__.deprecateProperty;
+        var get = __dependency6__.get;
+        var set = __dependency7__.set;
+        var computed = __dependency8__.computed;
+
+        var typeOf = __dependency9__.typeOf;
+
+        var instrument = __dependency10__.instrument;
+
+
+        var renderBuffer = __dependency11__[&quot;default&quot;];
+
+        /**
+              `Ember.CoreView` is an abstract class that exists to give view-like behavior
+              to both Ember's main view class `Ember.View` and other classes like
+              `Ember._SimpleMetamorphView` that don't need the fully functionaltiy of
+              `Ember.View`.
+
+              Unless you have specific needs for `CoreView`, you will use `Ember.View`
+              in your applications.
+
+              @class CoreView
+              @namespace Ember
+              @extends Ember.Object
+              @uses Ember.Evented
+              @uses Ember.ActionHandler
+            */
+        var CoreView = EmberObject.extend(Evented, ActionHandler, {
+            isView: true,
+
+            _states: cloneStates(states),
+
+            init: function() {
+                this._super();
+                this._transitionTo('preRender');
+                this._isVisible = get(this, 'isVisible');
+
+                deprecateProperty(this, 'states', '_states');
+                deprecateProperty(this, 'state', '_state');
+            },
+
+            /**
+                    If the view is currently inserted into the DOM of a parent view, this
+                    property will point to the parent of the view.
+
+                    @property parentView
+                    @type Ember.View
+                    @default null
+                  */
+            parentView: computed('_parentView', function() {
+                var parent = this._parentView;
+
+                if (parent &amp;&amp; parent.isVirtual) {
+                    return get(parent, 'parentView');
+                } else {
+                    return parent;
+                }
+            }),
+
+            _state: null,
+
+            _parentView: null,
+
+            // return the current view, not including virtual views
+            concreteView: computed('parentView', function() {
+                if (!this.isVirtual) {
+                    return this;
+                } else {
+                    return get(this, 'parentView.concreteView');
+                }
+            }),
+
+            instrumentName: 'core_view',
+
+            instrumentDetails: function(hash) {
+                hash.object = this.toString();
+                hash.containerKey = this._debugContainerKey;
+                hash.view = this;
+            },
+
+            /**
+                    Invoked by the view system when this view needs to produce an HTML
+                    representation. This method will create a new render buffer, if needed,
+                    then apply any default attributes, such as class names and visibility.
+                    Finally, the `render()` method is invoked, which is responsible for
+                    doing the bulk of the rendering.
+
+                    You should not need to override this method; instead, implement the
+                    `template` property, or if you need more control, override the `render`
+                    method.
+
+                    @method renderToBuffer
+                    @param {Ember.RenderBuffer} buffer the render buffer. If no buffer is
+                      passed, a default buffer, using the current view's `tagName`, will
+                      be used.
+                    @private
+                  */
+            renderToBuffer: function(buffer) {
+                var name = 'render.' + this.instrumentName,
+                details = {};
+
+                this.instrumentDetails(details);
+
+                return instrument(name, details, function instrumentRenderToBuffer() {
+                    return this._renderToBuffer(buffer);
+                }, this);
+            },
+
+            _renderToBuffer: function(_buffer) {
+                // If this is the top-most view, start a new buffer. Otherwise,
+                // create a new buffer relative to the original using the
+                // provided buffer operation (for example, `insertAfter` will
+                // insert a new buffer after the &quot;parent buffer&quot;).
+                var tagName = this.tagName;
+
+                if (tagName === null || tagName === undefined) {
+                    tagName = 'div';
+                }
+
+                var buffer = this.buffer = _buffer &amp;&amp; _buffer.begin(tagName) || renderBuffer(tagName);
+                this._transitionTo('inBuffer', false);
+
+                this.beforeRender(buffer);
+                this.render(buffer);
+                this.afterRender(buffer);
+
+                return buffer;
+            },
+
+            /**
+                    Override the default event firing from `Ember.Evented` to
+                    also call methods with the given name.
+
+                    @method trigger
+                    @param name {String}
+                    @private
+                  */
+            trigger: function() {
+                this._super.apply(this, arguments);
+                var name = arguments[0];
+                var method = this[name];
+                if (method) {
+                    var length = arguments.length;
+                    var args = new Array(length - 1);
+                    for (var i = 1; i &lt; length; i++) {
+                        args[i - 1] = arguments[i];
+                    }
+                    return method.apply(this, args);
+                }
+            },
+
+            deprecatedSendHandles: function(actionName) {
+                return !!this[actionName];
+            },
+
+            deprecatedSend: function(actionName) {
+                var args = [].slice.call(arguments, 1);
+                Ember.assert('' + this + &quot; has the action &quot; + actionName + &quot; but it is not a function&quot;, typeof this[actionName] === 'function');
+                Ember.deprecate('Action handlers implemented directly on views are deprecated in favor of action handlers on an `actions` object ( action: `' + actionName + '` on ' + this + ')', false);
+                this[actionName].apply(this, args);
+                return;
+            },
+
+            has: function(name) {
+                return typeOf(this[name]) === 'function' || this._super(name);
+            },
+
+            destroy: function() {
+                var parent = this._parentView;
+
+                if (!this._super()) {
+                    return;
+                }
+
+                // destroy the element -- this will avoid each child view destroying
+                // the element over and over again...
+                if (!this.removedFromDOM) {
+                    this.destroyElement();
+                }
+
+                // remove from parent if found. Don't call removeFromParent,
+                // as removeFromParent will try to remove the element from
+                // the DOM again.
+                if (parent) {
+                    parent.removeChild(this);
+                }
+
+                this._transitionTo('destroying', false);
+
+                return this;
+            },
+
+            clearRenderedChildren: Ember.K,
+            triggerRecursively: Ember.K,
+            invokeRecursively: Ember.K,
+            _transitionTo: Ember.K,
+            destroyElement: Ember.K
+        });
+
+        __exports__[&quot;default&quot;] = CoreView;
+    });
+    define(&quot;ember-views/views/states&quot;,
+    [&quot;ember-metal/platform&quot;, &quot;ember-metal/merge&quot;, &quot;ember-views/views/states/default&quot;, &quot;ember-views/views/states/pre_render&quot;, &quot;ember-views/views/states/in_buffer&quot;, &quot;ember-views/views/states/has_element&quot;, &quot;ember-views/views/states/in_dom&quot;, &quot;ember-views/views/states/destroying&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var create = __dependency1__.create;
+        var merge = __dependency2__[&quot;default&quot;];
+        var _default = __dependency3__[&quot;default&quot;];
+        var preRender = __dependency4__[&quot;default&quot;];
+        var inBuffer = __dependency5__[&quot;default&quot;];
+        var hasElement = __dependency6__[&quot;default&quot;];
+        var inDOM = __dependency7__[&quot;default&quot;];
+        var destroying = __dependency8__[&quot;default&quot;];
+
+        function cloneStates(from) {
+            var into = {};
+
+            into._default = {};
+            into.preRender = create(into._default);
+            into.destroying = create(into._default);
+            into.inBuffer = create(into._default);
+            into.hasElement = create(into._default);
+            into.inDOM = create(into.hasElement);
+
+            for (var stateName in from) {
+                if (!from.hasOwnProperty(stateName)) {
+                    continue;
+                }
+                merge(into[stateName], from[stateName]);
+            }
+
+            return into;
+        }
+
+        __exports__.cloneStates = cloneStates;
+        var states = {
+            _default: _default,
+            preRender: preRender,
+            inDOM: inDOM,
+            inBuffer: inBuffer,
+            hasElement: hasElement,
+            destroying: destroying
+        };
+        __exports__.states = states;
+    });
+    define(&quot;ember-views/views/states/default&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.K
+        var get = __dependency2__.get;
+        var set = __dependency3__.set;
+        var run = __dependency4__[&quot;default&quot;];
+        var EmberError = __dependency5__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+        __exports__[&quot;default&quot;] = {
+            // appendChild is only legal while rendering the buffer.
+            appendChild: function() {
+                throw new EmberError(&quot;You can't use appendChild outside of the rendering process&quot;);
+            },
+
+            $: function() {
+                return undefined;
+            },
+
+            getElement: function() {
+                return null;
+            },
+
+            // Handle events from `Ember.EventDispatcher`
+            handleEvent: function() {
+                return true; // continue event propagation
+            },
+
+            destroyElement: function(view) {
+                set(view, 'element', null);
+                if (view._scheduledInsert) {
+                    run.cancel(view._scheduledInsert);
+                    view._scheduledInsert = null;
+                }
+                return view;
+            },
+
+            renderToBufferIfNeeded: function () {
+                return false;
+            },
+
+            rerender: Ember.K,
+            invokeObserver: Ember.K
+        };
+    });
+    define(&quot;ember-views/views/states/destroying&quot;,
+    [&quot;ember-metal/merge&quot;, &quot;ember-metal/platform&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-views/views/states/default&quot;, &quot;ember-metal/error&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var merge = __dependency1__[&quot;default&quot;];
+        var create = __dependency2__.create;
+        var fmt = __dependency3__.fmt;
+        var _default = __dependency4__[&quot;default&quot;];
+        var EmberError = __dependency5__[&quot;default&quot;];
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var destroyingError = &quot;You can't call %@ on a view being destroyed&quot;;
+
+        var destroying = create(_default);
+
+        merge(destroying, {
+            appendChild: function() {
+                throw new EmberError(fmt(destroyingError, ['appendChild']));
+            },
+            rerender: function() {
+                throw new EmberError(fmt(destroyingError, ['rerender']));
+            },
+            destroyElement: function() {
+                throw new EmberError(fmt(destroyingError, ['destroyElement']));
+            },
+            empty: function() {
+                throw new EmberError(fmt(destroyingError, ['empty']));
+            },
+
+            setElement: function() {
+                throw new EmberError(fmt(destroyingError, [&quot;set('element', ...)&quot;]));
+            },
+
+            renderToBufferIfNeeded: function() {
+                return false;
+            },
+
+            // Since element insertion is scheduled, don't do anything if
+            // the view has been destroyed between scheduling and execution
+            insertElement: Ember.K
+        });
+
+        __exports__[&quot;default&quot;] = destroying;
+    });
+    define(&quot;ember-views/views/states/has_element&quot;,
+    [&quot;ember-views/views/states/default&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/platform&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var _default = __dependency1__[&quot;default&quot;];
+        var run = __dependency2__[&quot;default&quot;];
+        var merge = __dependency3__[&quot;default&quot;];
+        var create = __dependency4__.create;
+        var jQuery = __dependency5__[&quot;default&quot;];
+        var EmberError = __dependency6__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var get = __dependency7__.get;
+        var set = __dependency8__.set;
+
+        var hasElement = create(_default);
+
+        merge(hasElement, {
+            $: function(view, sel) {
+                var elem = get(view, 'element');
+                return sel ? jQuery(sel, elem) : jQuery(elem);
+            },
+
+            getElement: function(view) {
+                var parent = get(view, 'parentView');
+                if (parent) {
+                    parent = get(parent, 'element');
+                }
+                if (parent) {
+                    return view.findElementInParentElement(parent);
+                }
+                return jQuery(&quot;#&quot; + get(view, 'elementId'))[0];
+            },
+
+            setElement: function(view, value) {
+                if (value === null) {
+                    view._transitionTo('preRender');
+                } else {
+                    throw new EmberError(&quot;You cannot set an element to a non-null value when the element is already in the DOM.&quot;);
+                }
+
+                return value;
+            },
+
+            // once the view has been inserted into the DOM, rerendering is
+            // deferred to allow bindings to synchronize.
+            rerender: function(view) {
+                view.triggerRecursively('willClearRender');
+
+                view.clearRenderedChildren();
+
+                view.domManager.replace(view);
+                return view;
+            },
+
+            // once the view is already in the DOM, destroying it removes it
+            // from the DOM, nukes its element, and puts it back into the
+            // preRender state if inDOM.
+
+            destroyElement: function(view) {
+                view._notifyWillDestroyElement();
+                view.domManager.remove(view);
+                set(view, 'element', null);
+                if (view._scheduledInsert) {
+                    run.cancel(view._scheduledInsert);
+                    view._scheduledInsert = null;
+                }
+                return view;
+            },
+
+            empty: function(view) {
+                var _childViews = view._childViews, len, idx;
+                if (_childViews) {
+                    len = _childViews.length;
+                    for (idx = 0; idx &lt; len; idx++) {
+                        _childViews[idx]._notifyWillDestroyElement();
+                    }
+                }
+                view.domManager.empty(view);
+            },
+
+            // Handle events from `Ember.EventDispatcher`
+            handleEvent: function(view, eventName, evt) {
+                if (view.has(eventName)) {
+                    // Handler should be able to re-dispatch events, so we don't
+                    // preventDefault or stopPropagation.
+                    return view.trigger(eventName, evt);
+                } else {
+                    return true; // continue event propagation
+                }
+            },
+
+            invokeObserver: function(target, observer) {
+                observer.call(target);
+            }
+        });
+
+        __exports__[&quot;default&quot;] = hasElement;
+    });
+    define(&quot;ember-views/views/states/in_buffer&quot;,
+    [&quot;ember-views/views/states/default&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/core&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/merge&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var _default = __dependency1__[&quot;default&quot;];
+        var EmberError = __dependency2__[&quot;default&quot;];
+
+        var Ember = __dependency3__[&quot;default&quot;];
+        // Ember.assert
+        var create = __dependency4__.create;
+        var merge = __dependency5__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var inBuffer = create(_default);
+
+        merge(inBuffer, {
+            $: function(view, sel) {
+                // if we don't have an element yet, someone calling this.$() is
+                // trying to update an element that isn't in the DOM. Instead,
+                // rerender the view to allow the render method to reflect the
+                // changes.
+                view.rerender();
+                return Ember.$();
+            },
+
+            // when a view is rendered in a buffer, rerendering it simply
+            // replaces the existing buffer with a new one
+            rerender: function(view) {
+                throw new EmberError(&quot;Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.&quot;);
+            },
+
+            // when a view is rendered in a buffer, appending a child
+            // view will render that view and append the resulting
+            // buffer into its buffer.
+            appendChild: function(view, childView, options) {
+                var buffer = view.buffer, _childViews = view._childViews;
+
+                childView = view.createChildView(childView, options);
+                if (!_childViews.length) {
+                    _childViews = view._childViews = _childViews.slice();
+                }
+                _childViews.push(childView);
+
+                childView.renderToBuffer(buffer);
+
+                view.propertyDidChange('childViews');
+
+                return childView;
+            },
+
+            // when a view is rendered in a buffer, destroying the
+            // element will simply destroy the buffer and put the
+            // state back into the preRender state.
+            destroyElement: function(view) {
+                view.clearBuffer();
+                var viewCollection = view._notifyWillDestroyElement();
+                viewCollection.transitionTo('preRender', false);
+
+                return view;
+            },
+
+            empty: function() {
+                Ember.assert(&quot;Emptying a view in the inBuffer state is not allowed and &quot; +
+                &quot;should not happen under normal circumstances. Most likely &quot; +
+                &quot;there is a bug in your application. This may be due to &quot; +
+                &quot;excessive property change notifications.&quot;);
+            },
+
+            renderToBufferIfNeeded: function (view, buffer) {
+                return false;
+            },
+
+            // It should be impossible for a rendered view to be scheduled for
+            // insertion.
+            insertElement: function() {
+                throw new EmberError(&quot;You can't insert an element that has already been rendered&quot;);
+            },
+
+            setElement: function(view, value) {
+                if (value === null) {
+                    view._transitionTo('preRender');
+                } else {
+                    view.clearBuffer();
+                    view._transitionTo('hasElement');
+                }
+
+                return value;
+            },
+
+            invokeObserver: function(target, observer) {
+                observer.call(target);
+            }
+        });
+
+        __exports__[&quot;default&quot;] = inBuffer;
+    });
+    define(&quot;ember-views/views/states/in_dom&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/merge&quot;, &quot;ember-metal/error&quot;, &quot;ember-views/views/states/has_element&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
+        &quot;use strict&quot;;
+        var Ember = __dependency1__[&quot;default&quot;];
+        // Ember.assert
+        var create = __dependency2__.create;
+        var merge = __dependency3__[&quot;default&quot;];
+        var EmberError = __dependency4__[&quot;default&quot;];
+
+        var hasElement = __dependency5__[&quot;default&quot;];
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var inDOM = create(hasElement);
+
+        var View;
+
+        merge(inDOM, {
+            enter: function(view) {
+                if (!View) {
+                    View = requireModule('ember-views/views/view')[&quot;default&quot;];
+                }
+                // ES6TODO: this sucks. Have to avoid cycles...
+
+                // Register the view for event handling. This hash is used by
+                // Ember.EventDispatcher to dispatch incoming events.
+                if (!view.isVirtual) {
+                    Ember.assert(&quot;Attempted to register a view with an id already in use: &quot; + view.elementId, !View.views[view.elementId]);
+                    View.views[view.elementId] = view;
+                }
+
+                view.addBeforeObserver('elementId', function() {
+                    throw new EmberError(&quot;Changing a view's elementId after creation is not allowed&quot;);
+                });
+            },
+
+            exit: function(view) {
+                if (!View) {
+                    View = requireModule('ember-views/views/view')[&quot;default&quot;];
+                }
+                // ES6TODO: this sucks. Have to avoid cycles...
+
+                if (!this.isVirtual) 
+                    delete View.views[view.elementId];
+            },
+
+            insertElement: function(view, fn) {
+                throw new EmberError(&quot;You can't insert an element into the DOM that has already been inserted&quot;);
+            }
+        });
+
+        __exports__[&quot;default&quot;] = inDOM;
+    });
+    define(&quot;ember-views/views/states/pre_render&quot;,
+    [&quot;ember-views/views/states/default&quot;, &quot;ember-metal/platform&quot;, &quot;ember-metal/merge&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var _default = __dependency1__[&quot;default&quot;];
+        var create = __dependency2__.create;
+        var merge = __dependency3__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+        var preRender = create(_default);
+
+        merge(preRender, {
+            // a view leaves the preRender state once its element has been
+            // created (createElement).
+            insertElement: function(view, fn) {
+                view.createElement();
+                var viewCollection = view.viewHierarchyCollection();
+
+                viewCollection.trigger('willInsertElement');
+
+                fn.call(view);
+
+                // We transition to `inDOM` if the element exists in the DOM
+                var element = view.get('element');
+                if (document.body.contains(element)) {
+                    viewCollection.transitionTo('inDOM', false);
+                    viewCollection.trigger('didInsertElement');
+                }
+            },
+
+            renderToBufferIfNeeded: function(view, buffer) {
+                view.renderToBuffer(buffer);
+                return true;
+            },
+
+            empty: Ember.K,
+
+            setElement: function(view, value) {
+                if (value !== null) {
+                    view._transitionTo('hasElement');
+                }
+                return value;
+            }
+        });
+
+        __exports__[&quot;default&quot;] = preRender;
+    });
+    define(&quot;ember-views/views/view&quot;,
+    [&quot;ember-metal/core&quot;, &quot;ember-runtime/mixins/evented&quot;, &quot;ember-runtime/system/object&quot;, &quot;ember-metal/error&quot;, &quot;ember-metal/property_get&quot;, &quot;ember-metal/property_set&quot;, &quot;ember-metal/set_properties&quot;, &quot;ember-metal/run_loop&quot;, &quot;ember-metal/observer&quot;, &quot;ember-metal/properties&quot;, &quot;ember-metal/utils&quot;, &quot;ember-metal/computed&quot;, &quot;ember-metal/mixin&quot;, &quot;ember-metal/is_none&quot;, &quot;container/container&quot;, &quot;ember-runtime/system/native_array&quot;, &quot;ember-runtime/system/string&quot;, &quot;ember-metal/enumerable_utils&quot;, &quot;ember-runtime/copy&quot;, &quot;ember-metal/binding&quot;, &quot;ember-metal/property_events&quot;, &quot;ember-views/system/jquery&quot;, &quot;ember-views/system/ext&quot;, &quot;ember-views/views/core_view&quot;, &quot;ember-views/views/view_collection&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __exports__) {
+        &quot;use strict&quot;;
+        // Ember.assert, Ember.deprecate, Ember.warn, Ember.TEMPLATES,
+        // Ember.K, jQuery, Ember.lookup,
+        // Ember.ContainerView circular dependency
+        // Ember.ENV
+        var Ember = __dependency1__[&quot;default&quot;];
+
+        var Evented = __dependency2__[&quot;default&quot;];
+        var EmberObject = __dependency3__[&quot;default&quot;];
+        var EmberError = __dependency4__[&quot;default&quot;];
+        var get = __dependency5__.get;
+        var set = __dependency6__.set;
+        var setProperties = __dependency7__[&quot;default&quot;];
+        var run = __dependency8__[&quot;default&quot;];
+        var addObserver = __dependency9__.addObserver;
+        var removeObserver = __dependency9__.removeObserver;
+
+        var defineProperty = __dependency10__.defineProperty;
+        var deprecateProperty = __dependency10__.deprecateProperty;
+        var guidFor = __dependency11__.guidFor;
+        var meta = __dependency11__.meta;
+        var computed = __dependency12__.computed;
+        var observer = __dependency13__.observer;
+
+        var typeOf = __dependency11__.typeOf;
+        var isArray = __dependency11__.isArray;
+        var isNone = __dependency14__.isNone;
+        var Mixin = __dependency13__.Mixin;
+        var Container = __dependency15__[&quot;default&quot;];
+        var emberA = __dependency16__.A;
+
+        var dasherize = __dependency17__.dasherize;
+
+        // ES6TODO: functions on EnumerableUtils should get their own export
+        var forEach = __dependency18__.forEach;
+        var addObject = __dependency18__.addObject;
+        var removeObject = __dependency18__.removeObject;
+
+        var beforeObserver = __dependency13__.beforeObserver;
+        var copy = __dependency19__[&quot;default&quot;];
+        var isGlobalPath = __dependency20__.isGlobalPath;
+
+        var propertyWillChange = __dependency21__.propertyWillChange;
+        var propertyDidChange = __dependency21__.propertyDidChange;
+
+        var jQuery = __dependency22__[&quot;default&quot;];
+        // for the side effect of extending Ember.run.queues
+
+        var CoreView = __dependency24__[&quot;default&quot;];
+        var ViewCollection = __dependency25__[&quot;default&quot;];
+
+        /**
+            @module ember
+            @submodule ember-views
+            */
+
+        var ContainerView;
+
+        function nullViewsBuffer(view) {
+            view.buffer = null;
+
+        }
+
+        function clearCachedElement(view) {
+            meta(view).cache.element = undefined;
+        }
+
+        var childViewsProperty = computed(function() {
+            var childViews = this._childViews, ret = emberA(), view = this;
+
+            forEach(childViews, function(view) {
+                var currentChildViews;
+                if (view.isVirtual) {
+                    if (currentChildViews = get(view, 'childViews')) {
+                        ret.pushObjects(currentChildViews);
+                    }
+                } else {
+                    ret.push(view);
+                }
+            });
+
+            ret.replace = function (idx, removedCount, addedViews) {
+                if (!ContainerView) {
+                    ContainerView = requireModule('ember-views/views/container_view')['default'];
+                }
+                // ES6TODO: stupid circular dep
+
+                if (view instanceof ContainerView) {
+                    Ember.deprecate(&quot;Manipulating an Ember.ContainerView through its childViews property is deprecated. Please use the ContainerView instance itself as an Ember.MutableArray.&quot;);
+                    return view.replace(idx, removedCount, addedViews);
+                }
+                throw new EmberError(&quot;childViews is immutable&quot;);
+            };
+
+            return ret;
+        });
+
+        Ember.warn(&quot;The VIEW_PRESERVES_CONTEXT flag has been removed and the functionality can no longer be disabled.&quot;, Ember.ENV.VIEW_PRESERVES_CONTEXT !== false);
+
+        /**
+              Global hash of shared templates. This will automatically be populated
+              by the build tools so that you can store your Handlebars templates in
+              separate files that get loaded into JavaScript at buildtime.
+
+              @property TEMPLATES
+              @for Ember
+              @type Hash
+            */
+        Ember.TEMPLATES = {};
+
+        var EMPTY_ARRAY = [];
+
+        /**
+              `Ember.View` is the class in Ember responsible for encapsulating templates of
+              HTML content, combining templates with data to render as sections of a page's
+              DOM, and registering and responding to user-initiated events.
+
+              ## HTML Tag
+
+              The default HTML tag name used for a view's DOM representation is `div`. This
+              can be customized by setting the `tagName` property. The following view
+              class:
+
+              ```javascript
+              ParagraphView = Ember.View.extend({
+                tagName: 'em'
+              });
+              ```
+
+              Would result in instances with the following HTML:
+
+              ```html
+              &lt;em id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;&lt;/em&gt;
+              ```
+
+              ## HTML `class` Attribute
+
+              The HTML `class` attribute of a view's tag can be set by providing a
+              `classNames` property that is set to an array of strings:
+
+              ```javascript
+              MyView = Ember.View.extend({
+                classNames: ['my-class', 'my-other-class']
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view my-class my-other-class&quot;&gt;&lt;/div&gt;
+              ```
+
+              `class` attribute values can also be set by providing a `classNameBindings`
+              property set to an array of properties names for the view. The return value
+              of these properties will be added as part of the value for the view's `class`
+              attribute. These properties can be computed properties:
+
+              ```javascript
+              MyView = Ember.View.extend({
+                classNameBindings: ['propertyA', 'propertyB'],
+                propertyA: 'from-a',
+                propertyB: function() {
+                  if (someLogic) { return 'from-b'; }
+                }.property()
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view from-a from-b&quot;&gt;&lt;/div&gt;
+              ```
+
+              If the value of a class name binding returns a boolean the property name
+              itself will be used as the class name if the property is true. The class name
+              will not be added if the value is `false` or `undefined`.
+
+              ```javascript
+              MyView = Ember.View.extend({
+                classNameBindings: ['hovered'],
+                hovered: true
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view hovered&quot;&gt;&lt;/div&gt;
+              ```
+
+              When using boolean class name bindings you can supply a string value other
+              than the property name for use as the `class` HTML attribute by appending the
+              preferred value after a &quot;:&quot; character when defining the binding:
+
+              ```javascript
+              MyView = Ember.View.extend({
+                classNameBindings: ['awesome:so-very-cool'],
+                awesome: true
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view so-very-cool&quot;&gt;&lt;/div&gt;
+              ```
+
+              Boolean value class name bindings whose property names are in a
+              camelCase-style format will be converted to a dasherized format:
+
+              ```javascript
+              MyView = Ember.View.extend({
+                classNameBindings: ['isUrgent'],
+                isUrgent: true
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view is-urgent&quot;&gt;&lt;/div&gt;
+              ```
+
+              Class name bindings can also refer to object values that are found by
+              traversing a path relative to the view itself:
+
+              ```javascript
+              MyView = Ember.View.extend({
+                classNameBindings: ['messages.empty']
+                messages: Ember.Object.create({
+                  empty: true
+                })
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view empty&quot;&gt;&lt;/div&gt;
+              ```
+
+              If you want to add a class name for a property which evaluates to true and
+              and a different class name if it evaluates to false, you can pass a binding
+              like this:
+
+              ```javascript
+              // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false
+              Ember.View.extend({
+                classNameBindings: ['isEnabled:enabled:disabled']
+                isEnabled: true
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view enabled&quot;&gt;&lt;/div&gt;
+              ```
+
+              When isEnabled is `false`, the resulting HTML reprensentation looks like
+              this:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view disabled&quot;&gt;&lt;/div&gt;
+              ```
+
+              This syntax offers the convenience to add a class if a property is `false`:
+
+              ```javascript
+              // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false
+              Ember.View.extend({
+                classNameBindings: ['isEnabled::disabled']
+                isEnabled: true
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;&lt;/div&gt;
+              ```
+
+              When the `isEnabled` property on the view is set to `false`, it will result
+              in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view disabled&quot;&gt;&lt;/div&gt;
+              ```
+
+              Updates to the the value of a class name binding will result in automatic
+              update of the  HTML `class` attribute in the view's rendered HTML
+              representation. If the value becomes `false` or `undefined` the class name
+              will be removed.
+
+              Both `classNames` and `classNameBindings` are concatenated properties. See
+              [Ember.Object](/api/classes/Ember.Object.html) documentation for more
+              information about concatenated properties.
+
+              ## HTML Attributes
+
+              The HTML attribute section of a view's tag can be set by providing an
+              `attributeBindings` property set to an array of property names on the view.
+              The return value of these properties will be used as the value of the view's
+              HTML associated attribute:
+
+              ```javascript
+              AnchorView = Ember.View.extend({
+                tagName: 'a',
+                attributeBindings: ['href'],
+                href: 'http://google.com'
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;a id=&quot;ember1&quot; class=&quot;ember-view&quot; href=&quot;http://google.com&quot;&gt;&lt;/a&gt;
+              ```
+
+              One property can be mapped on to another by placing a &quot;:&quot; between
+              the source property and the destination property:
+
+              ```javascript
+              AnchorView = Ember.View.extend({
+                tagName: 'a',
+                attributeBindings: ['url:href'],
+                url: 'http://google.com'
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;a id=&quot;ember1&quot; class=&quot;ember-view&quot; href=&quot;http://google.com&quot;&gt;&lt;/a&gt;
+              ```
+
+              If the return value of an `attributeBindings` monitored property is a boolean
+              the property will follow HTML's pattern of repeating the attribute's name as
+              its value:
+
+              ```javascript
+              MyTextInput = Ember.View.extend({
+                tagName: 'input',
+                attributeBindings: ['disabled'],
+                disabled: true
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;input id=&quot;ember1&quot; class=&quot;ember-view&quot; disabled=&quot;disabled&quot; /&gt;
+              ```
+
+              `attributeBindings` can refer to computed properties:
+
+              ```javascript
+              MyTextInput = Ember.View.extend({
+                tagName: 'input',
+                attributeBindings: ['disabled'],
+                disabled: function() {
+                  if (someLogic) {
+                    return true;
+                  } else {
+                    return false;
+                  }
+                }.property()
+              });
+              ```
+
+              Updates to the the property of an attribute binding will result in automatic
+              update of the  HTML attribute in the view's rendered HTML representation.
+
+              `attributeBindings` is a concatenated property. See [Ember.Object](/api/classes/Ember.Object.html)
+              documentation for more information about concatenated properties.
+
+              ## Templates
+
+              The HTML contents of a view's rendered representation are determined by its
+              template. Templates can be any function that accepts an optional context
+              parameter and returns a string of HTML that will be inserted within the
+              view's tag. Most typically in Ember this function will be a compiled
+              `Ember.Handlebars` template.
+
+              ```javascript
+              AView = Ember.View.extend({
+                template: Ember.Handlebars.compile('I am the template')
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;I am the template&lt;/div&gt;
+              ```
+
+              Within an Ember application is more common to define a Handlebars templates as
+              part of a page:
+
+              ```html
+              &lt;script type='text/x-handlebars' data-template-name='some-template'&gt;
+                Hello
+              &lt;/script&gt;
+              ```
+
+              And associate it by name using a view's `templateName` property:
+
+              ```javascript
+              AView = Ember.View.extend({
+                templateName: 'some-template'
+              });
+              ```
+
+              If you have nested resources, your Handlebars template will look like this:
+
+              ```html
+              &lt;script type='text/x-handlebars' data-template-name='posts/new'&gt;
+                &lt;h1&gt;New Post&lt;/h1&gt;
+              &lt;/script&gt;
+              ```
+
+              And `templateName` property:
+
+              ```javascript
+              AView = Ember.View.extend({
+                templateName: 'posts/new'
+              });
+              ```
+
+              Using a value for `templateName` that does not have a Handlebars template
+              with a matching `data-template-name` attribute will throw an error.
+
+              For views classes that may have a template later defined (e.g. as the block
+              portion of a `{{view}}` Handlebars helper call in another template or in
+              a subclass), you can provide a `defaultTemplate` property set to compiled
+              template function. If a template is not later provided for the view instance
+              the `defaultTemplate` value will be used:
+
+              ```javascript
+              AView = Ember.View.extend({
+                defaultTemplate: Ember.Handlebars.compile('I was the default'),
+                template: null,
+                templateName: null
+              });
+              ```
+
+              Will result in instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;I was the default&lt;/div&gt;
+              ```
+
+              If a `template` or `templateName` is provided it will take precedence over
+              `defaultTemplate`:
+
+              ```javascript
+              AView = Ember.View.extend({
+                defaultTemplate: Ember.Handlebars.compile('I was the default')
+              });
+
+              aView = AView.create({
+                template: Ember.Handlebars.compile('I was the template, not default')
+              });
+              ```
+
+              Will result in the following HTML representation when rendered:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;I was the template, not default&lt;/div&gt;
+              ```
+
+              ## View Context
+
+              The default context of the compiled template is the view's controller:
+
+              ```javascript
+              AView = Ember.View.extend({
+                template: Ember.Handlebars.compile('Hello {{excitedGreeting}}')
+              });
+
+              aController = Ember.Object.create({
+                firstName: 'Barry',
+                excitedGreeting: function() {
+                  return this.get(&quot;content.firstName&quot;) + &quot;!!!&quot;
+                }.property()
+              });
+
+              aView = AView.create({
+                controller: aController
+              });
+              ```
+
+              Will result in an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;Hello Barry!!!&lt;/div&gt;
+              ```
+
+              A context can also be explicitly supplied through the view's `context`
+              property. If the view has neither `context` nor `controller` properties, the
+              `parentView`'s context will be used.
+
+              ## Layouts
+
+              Views can have a secondary template that wraps their main template. Like
+              primary templates, layouts can be any function that  accepts an optional
+              context parameter and returns a string of HTML that will be inserted inside
+              view's tag. Views whose HTML element is self closing (e.g. `&lt;input /&gt;`)
+              cannot have a layout and this property will be ignored.
+
+              Most typically in Ember a layout will be a compiled `Ember.Handlebars`
+              template.
+
+              A view's layout can be set directly with the `layout` property or reference
+              an existing Handlebars template by name with the `layoutName` property.
+
+              A template used as a layout must contain a single use of the Handlebars
+              `{{yield}}` helper. The HTML contents of a view's rendered `template` will be
+              inserted at this location:
+
+              ```javascript
+              AViewWithLayout = Ember.View.extend({
+                layout: Ember.Handlebars.compile(&quot;&lt;div class='my-decorative-class'&gt;{{yield}}&lt;/div&gt;&quot;),
+                template: Ember.Handlebars.compile(&quot;I got wrapped&quot;)
+              });
+              ```
+
+              Will result in view instances with an HTML representation of:
+
+              ```html
+              &lt;div id=&quot;ember1&quot; class=&quot;ember-view&quot;&gt;
+                &lt;div class=&quot;my-decorative-class&quot;&gt;
+                  I got wrapped
+                &lt;/div&gt;
+              &lt;/div&gt;
+              ```
+
+              See [Ember.Handlebars.helpers.yield](/api/classes/Ember.Handlebars.helpers.html#method_yield)
+              for more information.
+
+              ## Responding to Browser Events
+
+              Views can respond to user-initiated events in one of three ways: method
+              implementation, through an event manager, and through `{{action}}` helper use
+              in their template or layout.
+
+              ### Method Implementation
+
+              Views can respond to user-initiated events by implementing a method that
+              matches the event name. A `jQuery.Event` object will be passed as the
+              argument to this method.
+
+              ```javascript
+              AView = Ember.View.extend({
+                click: function(event) {
+                  // will be called when when an instance's
+                  // rendered element is clicked
+                }
+              });
+              ```
+
+              ### Event Managers
+
+              Views can define an object as their `eventManager` property. This object can
+              then implement methods that match the desired event names. Matching events
+              that occur on the view's rendered HTML or the rendered HTML of any of its DOM
+              descendants will trigger this method. A `jQuery.Event` object will be passed
+              as the first argument to the method and an  `Ember.View` object as the
+              second. The `Ember.View` will be the view whose rendered HTML was interacted
+              with. This may be the view with the `eventManager` property or one of its
+              descendent views.
+
+              ```javascript
+              AView = Ember.View.extend({
+                eventManager: Ember.Object.create({
+                  doubleClick: function(event, view) {
+                    // will be called when when an instance's
+                    // rendered element or any rendering
+                    // of this views's descendent
+                    // elements is clicked
+                  }
+                })
+              });
+              ```
+
+              An event defined for an event manager takes precedence over events of the
+              same name handled through methods on the view.
+
+              ```javascript
+              AView = Ember.View.extend({
+                mouseEnter: function(event) {
+                  // will never trigger.
+                },
+                eventManager: Ember.Object.create({
+                  mouseEnter: function(event, view) {
+                    // takes precedence over AView#mouseEnter
+                  }
+                })
+              });
+              ```
+
+              Similarly a view's event manager will take precedence for events of any views
+              rendered as a descendent. A method name that matches an event name will not
+              be called if the view instance was rendered inside the HTML representation of
+              a view that has an `eventManager` property defined that handles events of the
+              name. Events not handled by the event manager will still trigger method calls
+              on the descendent.
+
+              ```javascript
+              OuterView = Ember.View.extend({
+                template: Ember.Handlebars.compile(&quot;outer {{#view InnerView}}inner{{/view}} outer&quot;),
+                eventManager: Ember.Object.create({
+                  mouseEnter: function(event, view) {
+                    // view might be instance of either
+                    // OuterView or InnerView depending on
+                    // where on the page the user interaction occured
+                  }
+                })
+              });
+
+              InnerView = Ember.View.extend({
+                click: function(event) {
+                  // will be called if rendered inside
+                  // an OuterView because OuterView's
+                  // eventManager doesn't handle click events
+                },
+                mouseEnter: function(event) {
+                  // will never be called if rendered inside
+                  // an OuterView.
+                }
+              });
+              ```
+
+              ### Handlebars `{{action}}` Helper
+
+              See [Handlebars.helpers.action](/api/classes/Ember.Handlebars.helpers.html#method_action).
+
+              ### Event Names
+
+              All of the event handling approaches described above respond to the same set
+              of events. The names of the built-in events are listed below. (The hash of
+              built-in events exists in `Ember.EventDispatcher`.) Additional, custom events
+              can be registered by using `Ember.Application.customEvents`.
+
+              Touch events:
+
+              * `touchStart`
+              * `touchMove`
+              * `touchEnd`
+              * `touchCancel`
+
+              Keyboard events
+
+              * `keyDown`
+              * `keyUp`
+              * `keyPress`
+
+              Mouse events
+
+              * `mouseDown`
+              * `mouseUp`
+              * `contextMenu`
+              * `click`
+              * `doubleClick`
+              * `mouseMove`
+              * `focusIn`
+              * `focusOut`
+              * `mouseEnter`
+              * `mouseLeave`
+
+              Form events:
+
+              * `submit`
+              * `change`
+              * `focusIn`
+              * `focusOut`
+              * `input`
+
+              HTML5 drag and drop events:
+
+              * `dragStart`
+              * `drag`
+              * `dragEnter`
+              * `dragLeave`
+              * `dragOver`
+              * `dragEnd`
+              * `drop`
+
+              ## Handlebars `{{view}}` Helper
+
+              Other `Ember.View` instances can be included as part of a view's template by
+              using the `{{view}}` Handlebars helper. See [Ember.Handlebars.helpers.view](/api/classes/Ember.Handlebars.helpers.html#method_view)
+              for additional information.
+
+              @class View
+              @namespace Ember
+              @extends Ember.CoreView
+            */
+        var View = CoreView.extend({
+
+            concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'],
+
+            /**
+                    @property isView
+                    @type Boolean
+                    @default true
+                    @static
+                  */
+            isView: true,
+
+            // ..........................................................
+            // TEMPLATE SUPPORT
+            //
+
+            /**
+                    The name of the template to lookup if no template is provided.
+
+                    By default `Ember.View` will lookup a template with this name in
+                    `Ember.TEMPLATES` (a shared global object).
+
+                    @property templateName
+                    @type String
+                    @default null
+                  */
+            templateName: null,
+
+            /**
+                    The name of the layout to lookup if no layout is provided.
+
+                    By default `Ember.View` will lookup a template with this name in
+                    `Ember.TEMPLATES` (a shared global object).
+
+                    @property layoutName
+                    @type String
+                    @default null
+                  */
+            layoutName: null,
+
+            /**
+                    Used to identify this view during debugging
+
+                    @property instrumentDisplay
+                    @type String
+                  */
+            instrumentDisplay: computed(function() {
+                if (this.helperName) {
+                    return '{{' + this.helperName + '}}';
+                }
+            }),
+
+            /**
+                    The template used to render the view. This should be a function that
+                    accepts an optional context parameter and returns a string of HTML that
+                    will be inserted into the DOM relative to its parent view.
+
+                    In general, you should set the `templateName` property instead of setting
+                    the template yourself.
+
+                    @property template
+                    @type Function
+                  */
+            template: computed('templateName', function(key, value) {
+                if (value !== undefined) {
+                    return value;
+                }
+
+                var templateName = get(this, 'templateName'),
+                template = this.templateForName(templateName, 'template');
+
+                Ember.assert(&quot;You specified the templateName &quot; + templateName + &quot; for &quot; + this + &quot;, but it did not exist.&quot;, !templateName || template);
+
+                return template || get(this, 'defaultTemplate');
+            }),
+
+            /**
+                    The controller managing this view. If this property is set, it will be
+                    made available for use by the template.
+
+                    @property controller
+                    @type Object
+                  */
+            controller: computed('_parentView', function(key) {
+                var parentView = get(this, '_parentView');
+                return parentView ? get(parentView, 'controller') : null;
+            }),
+
+            /**
+                    A view may contain a layout. A layout is a regular template but
+                    supersedes the `template` property during rendering. It is the
+                    responsibility of the layout template to retrieve the `template`
+                    property from the view (or alternatively, call `Handlebars.helpers.yield`,
+                    `{{yield}}`) to render it in the correct location.
+
+                    This is useful for a view that has a shared wrapper, but which delegates
+                    the rendering of the contents of the wrapper to the `template` property
+                    on a subclass.
+
+                    @property layout
+                    @type Function
+                  */
+            layout: computed(function(key) {
+                var layoutName = get(this, 'layoutName'),
+                layout = this.templateForName(layoutName, 'layout');
+
+                Ember.assert(&quot;You specified the layoutName &quot; + layoutName + &quot; for &quot; + this + &quot;, but it did not exist.&quot;, !layoutName || layout);
+
+                return layout || get(this, 'defaultLayout');
+            }).property('layoutName'),
+
+            _yield: function(context, options) {
+                var template = get(this, 'template');
+                if (template) {
+                    template(context, options);
+                }
+            },
+
+            templateForName: function(name, type) {
+                if (!name) {
+                    return;
+                }
+                Ember.assert(&quot;templateNames are not allowed to contain periods: &quot; + name, name.indexOf('.') === -1);
+
+                // the defaultContainer is deprecated
+                var container = this.container || (Container &amp;&amp; Container.defaultContainer);
+                return container &amp;&amp; container.lookup('template:' + name);
+            },
+
+            /**
+                    The object from which templates should access properties.
+
+                    This object will be passed to the template function each time the render
+                    method is called, but it is up to the individual function to decide what
+                    to do with it.
+
+                    By default, this will be the view's controller.
+
+                    @property context
+                    @type Object
+                  */
+            context: computed(function(key, value) {
+                if (arguments.length === 2) {
+                    set(this, '_context', value);
+                    return value;
+                } else {
+                    return get(this, '_context');
+                }
+            })[&quot;volatile&quot;](),
+
+            /**
+                    Private copy of the view's template context. This can be set directly
+                    by Handlebars without triggering the observer that causes the view
+                    to be re-rendered.
+
+                    The context of a view is looked up as follows:
+
+                    1. Supplied context (usually by Handlebars)
+                    2. Specified controller
+                    3. `parentView`'s context (for a child of a ContainerView)
+
+                    The code in Handlebars that overrides the `_context` property first
+                    checks to see whether the view has a specified controller. This is
+                    something of a hack and should be revisited.
+
+                    @property _context
+                    @private
+                  */
+            _context: computed(function(key) {
+                var parentView, controller;
+
+                if (controller = get(this, 'controller')) {
+                    return controller;
+                }
+
+                parentView = this._parentView;
+                if (parentView) {
+                    return get(parentView, '_context');
+                }
+
+                return null;
+            }),
+
+            /**
+                    If a value that affects template rendering changes, the view should be
+                    re-rendered to reflect the new value.
+
+                    @method _contextDidChange
+                    @private
+                  */
+            _contextDidChange: observer('context', function() {
+                this.rerender();
+            }),
+
+            /**
+                    If `false`, the view will appear hidden in DOM.
+
+                    @property isVisible
+                    @type Boolean
+                    @default null
+                  */
+            isVisible: true,
+
+            /**
+                    Array of child views. You should never edit this array directly.
+                    Instead, use `appendChild` and `removeFromParent`.
+
+                    @property childViews
+                    @type Array
+                    @default []
+                    @private
+                  */
+            childViews: childViewsProperty,
+
+            _childViews: EMPTY_ARRAY,
+
+            // When it's a virtual view, we need to notify the parent that their
+            // childViews will change.
+            _childViewsWillChange: beforeObserver('childViews', function() {
+                if (this.isVirtual) {
+                    var parentView = get(this, 'parentView');
+                    if (parentView) {
+                        propertyWillChange(parentView, 'childViews');
+                    }
+                }
+            }),
+
+            // When it's a virtual view, we need to notify the parent that their
+            // childViews did change.
+            _childViewsDidChange: observer('childViews', function() {
+                if (this.isVirtual) {
+                    var parentView = get(this, 'parentView');
+                    if (parentView) {
+                        propertyDidChange(parentView, 'childViews');
+                    }
+                }
+            }),
+
+            /**
+                    Return the nearest ancestor that is an instance of the provided
+                    class.
+
+                    @method nearestInstanceOf
+                    @param {Class} klass Subclass of Ember.View (or Ember.View itself)
+                    @return Ember.View
+                    @deprecated
+                  */
+            nearestInstanceOf: function(klass) {
+                Ember.deprecate(&quot;nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType.&quot;);
+                var view = get(this, 'parentView');
+
+                while (view) {
+                    if (view instanceof klass) {
+                        return view;
+                    }
+                    view = get(view, 'parentView');
+                }
+            },
+
+            /**
+                    Return the nearest ancestor that is an instance of the provided
+                    class or mixin.
+
+                    @method nearestOfType
+                    @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself),
+                           or an instance of Ember.Mixin.
+                    @return Ember.View
+                  */
+            nearestOfType: function(klass) {
+                var view = get(this, 'parentView'),
+                isOfType = klass instanceof Mixin ?
+                function(view) {
+                    return klass.detect(view);
+                }
+                :
+                function(view) {
+                    return klass.detect(view.constructor);
+                };
+
+                while (view) {
+                    if (isOfType(view)) {
+                        return view;
+                    }
+                    view = get(view, 'parentView');
+                }
+            },
+
+            /**
+                    Return the nearest ancestor that has a given property.
+
+                    @method nearestWithProperty
+                    @param {String} property A property name
+                    @return Ember.View
+                  */
+            nearestWithProperty: function(property) {
+                var view = get(this, 'parentView');
+
+                while (view) {
+                    if (property in view) {
+                        return view;
+                    }
+                    view = get(view, 'parentView');
+                }
+            },
+
+            /**
+                    Return the nearest ancestor whose parent is an instance of
+                    `klass`.
+
+                    @method nearestChildOf
+                    @param {Class} klass Subclass of Ember.View (or Ember.View itself)
+                    @return Ember.View
+                  */
+            nearestChildOf: function(klass) {
+                var view = get(this, 'parentView');
+
+                while (view) {
+                    if (get(view, 'parentView') instanceof klass) {
+                        return view;
+                    }
+                    view = get(view, 'parentView');
+                }
+            },
+
+            /**
+                    When the parent view changes, recursively invalidate `controller`
+
+                    @method _parentViewDidChange
+                    @private
+                  */
+            _parentViewDidChange: observer('_parentView', function() {
+                if (this.isDestroying) {
+                    return;
+                }
+
+                this.trigger('parentViewDidChange');
+
+                if (get(this, 'parentView.controller') &amp;&amp; !get(this, 'controller')) {
+                    this.notifyPropertyChange('controller');
+                }
+            }),
+
+            _controllerDidChange: observer('controller', function() {
+                if (this.isDestroying) {
+                    return;
+                }
+
+                this.rerender();
+
+                this.forEachChildView(function(view) {
+                    view.propertyDidChange('controller');
+                });
+            }),
+
+            cloneKeywords: function() {
+                var templateData = get(this, 'templateData');
+
+                var keywords = templateData ? copy(templateData.keywords) : {};
+                set(keywords, 'view', this.isVirtual ? keywords.view : this);
+                set(keywords, '_view', this);
+                set(keywords, 'controller', get(this, 'controller'));
+
+                return keywords;
+            },
+
+            /**
+                    Called on your view when it should push strings of HTML into a
+                    `Ember.RenderBuffer`. Most users will want to override the `template`
+                    or `templateName` properties instead of this method.
+
+                    By default, `Ember.View` will look for a function in the `template`
+                    property and invoke it with the value of `context`. The value of
+                    `context` will be the view's controller unless you override it.
+
+                    @method render
+                    @param {Ember.RenderBuffer} buffer The render buffer
+                  */
+            render: function(buffer) {
+                // If this view has a layout, it is the responsibility of the
+                // the layout to render the view's template. Otherwise, render the template
+                // directly.
+                var template = get(this, 'layout') || get(this, 'template');
+
+                if (template) {
+                    var context = get(this, 'context');
+                    var keywords = this.cloneKeywords();
+                    var output;
+
+                    var data = {
+                        view: this,
+                        buffer: buffer,
+                        isRenderData: true,
+                        keywords: keywords,
+                        insideGroup: get(this, 'templateData.insideGroup')
+                    };
+
+                    // Invoke the template with the provided template context, which
+                    // is the view's controller by default. A hash of data is also passed that provides
+                    // the template with access to the view and render buffer.
+
+                    Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile(&quot;...&quot;) or specify templateName instead?', typeof template === 'function');
+                    // The template should write directly to the render buffer instead
+                    // of returning a string.
+                    output = template(context, {
+                        data: data 
+                    });
+
+                    // If the template returned a string instead of writing to the buffer,
+                    // push the string onto the buffer.
+                    if (output !== undefined) {
+                        buffer.push(output);
+                    }
+                }
+            },
+
+            /**
+                    Renders the view again. This will work regardless of whether the
+                    view is already in the DOM or not. If the view is in the DOM, the
+                    rendering process will be deferred to give bindings a chance
+                    to synchronize.
+
+                    If children were added during the rendering process using `appendChild`,
+                    `rerender` will remove them, because they will be added again
+                    if needed by the next `render`.
+
+                    In general, if the display of your view changes, you should modify
+                    the DOM element directly instead of manually calling `rerender`, which can
+                    be slow.
+
+                    @method rerender
+                  */
+            rerender: function() {
+                return this.currentState.rerender(this);
+            },
+
+            clearRenderedChildren: function() {
+                var lengthBefore = this.lengthBeforeRender,
+                lengthAfter = this.lengthAfterRender;
+
+                // If there were child views created during the last call to render(),
+                // remove them under the assumption that they will be re-created when
+                // we re-render.
+
+                // VIEW-TODO: Unit test this path.
+                var childViews = this._childViews;
+                for (var i = lengthAfter-1; i &gt;= lengthBefore; i--) {
+                    if (childViews[i]) {
+                        childViews[i].destroy();
+                    }
+                }
+            },
+
+            /**
+                    Iterates over the view's `classNameBindings` array, inserts the value
+                    of the specified property into the `classNames` array, then creates an
+                    observer to update the view's element if the bound property ever changes
+                    in the future.
+
+                    @method _applyClassNameBindings
+                    @private
+                  */
+            _applyClassNameBindings: function(classBindings) {
+                var classNames = this.classNames,
+                elem, newClass, dasherizedClass;
+
+                // Loop through all of the configured bindings. These will be either
+                // property names ('isUrgent') or property paths relative to the view
+                // ('content.isUrgent')
+                forEach(classBindings, function(binding) {
+
+                    Ember.assert(&quot;classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. ['foo', ':bar']&quot;, binding.indexOf(' ') === -1);
+
+                    // Variable in which the old class value is saved. The observer function
+                    // closes over this variable, so it knows which string to remove when
+                    // the property changes.
+                    var oldClass;
+                    // Extract just the property name from bindings like 'foo:bar'
+                    var parsedPath = View._parsePropertyPath(binding);
+
+                    // Set up an observer on the context. If the property changes, toggle the
+                    // class name.
+                    var observer = function() {
+                        // Get the current value of the property
+                        newClass = this._classStringForProperty(binding);
+                        elem = this.$();
+
+                        // If we had previously added a class to the element, remove it.
+                        if (oldClass) {
+                            elem.removeClass(oldClass);
+                            // Also remove from classNames so that if the view gets rerendered,
+                            // the class doesn't get added back to the DOM.
+                            classNames.removeObject(oldClass);
+                        }
+
+                        // If necessary, add a new class. Make sure we keep track of it so
+                        // it can be removed in the future.
+                        if (newClass) {
+                            elem.addClass(newClass);
+                            oldClass = newClass;
+                        } else {
+                            oldClass = null;
+                        }
+                    };
+
+                    // Get the class name for the property at its current value
+                    dasherizedClass = this._classStringForProperty(binding);
+
+                    if (dasherizedClass) {
+                        // Ensure that it gets into the classNames array
+                        // so it is displayed when we render.
+                        addObject(classNames, dasherizedClass);
+
+                        // Save a reference to the class name so we can remove it
+                        // if the observer fires. Remember that this variable has
+                        // been closed over by the observer.
+                        oldClass = dasherizedClass;
+                    }
+
+                    this.registerObserver(this, parsedPath.path, observer);
+                    // Remove className so when the view is rerendered,
+                    // the className is added based on binding reevaluation
+                    this.one('willClearRender', function() {
+                        if (oldClass) {
+                            classNames.removeObject(oldClass);
+                            oldClass = null;
+                        }
+                    });
+
+                }, this);
+            },
+
+            _unspecifiedAttributeBindings: null,
+
+            /**
+                    Iterates through the view's attribute bindings, sets up observers for each,
+                    then applies the current value of the attributes to the passed render buffer.
+
+                    @method _applyAttributeBindings
+                    @param {Ember.RenderBuffer} buffer
+                    @private
+                  */
+            _applyAttributeBindings: function(buffer, attributeBindings) {
+                var attributeValue,
+                unspecifiedAttributeBindings = this._unspecifiedAttributeBindings = this._unspecifiedAttributeBindings || {};
+
+                forEach(attributeBindings, function(binding) {
+                    var split = binding.split(':'),
+                    property = split[0],
+                    attributeName = split[1] || property;
+
+                    if (property in this) {
+                        this._setupAttributeBindingObservation(property, attributeName);
+
+                        // Determine the current value and add it to the render buffer
+                        // if necessary.
+                        attributeValue = get(this, property);
+                        View.applyAttributeBindings(buffer, attributeName, attributeValue);
+                    } else {
+                        unspecifiedAttributeBindings[property] = attributeName;
+                    }
+                }, this);
+
+                // Lazily setup setUnknownProperty after attributeBindings are initially applied
+                this.setUnknownProperty = this._setUnknownProperty;
+            },
+
+            _setupAttributeBindingObservation: function(property, attributeName) {
+                var attributeValue, elem;
+
+                // Create an observer to add/remove/change the attribute if the
+                // JavaScript property changes.
+                var observer = function() {
+                    elem = this.$();
+
+                    attributeValue = get(this, property);
+
+                    View.applyAttributeBindings(elem, attributeName, attributeValue);
+                };
+
+                this.registerObserver(this, property, observer);
+            },
+
+            /**
+                    We're using setUnknownProperty as a hook to setup attributeBinding observers for
+                    properties that aren't defined on a view at initialization time.
+
+                    Note: setUnknownProperty will only be called once for each property.
+
+                    @method setUnknownProperty
+                    @param key
+                    @param value
+                    @private
+                  */
+            setUnknownProperty: null,
+            // Gets defined after initialization by _applyAttributeBindings
+
+            _setUnknownProperty: function(key, value) {
+                var attributeName = this._unspecifiedAttributeBindings &amp;&amp; this._unspecifiedAttributeBindings[key];
+                if (attributeName) {
+                    this._setupAttributeBindingObservation(key, attributeName);
+                }
+
+                defineProperty(this, key);
+                return set(this, key, value);
+            },
+
+            /**
+                    Given a property name, returns a dasherized version of that
+                    property name if the property evaluates to a non-falsy value.
+
+                    For example, if the view has property `isUrgent` that evaluates to true,
+                    passing `isUrgent` to this method will return `&quot;is-urgent&quot;`.
+
+                    @method _classStringForProperty
+                    @param property
+                    @private
+                  */
+            _classStringForProperty: function(property) {
+                var parsedPath = View._parsePropertyPath(property);
+                var path = parsedPath.path;
+
+                var val = get(this, path);
+                if (val === undefined &amp;&amp; isGlobalPath(path)) {
+                    val = get(Ember.lookup, path);
+                }
+
+                return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName);
+            },
+
+            // ..........................................................
+            // ELEMENT SUPPORT
+            //
+
+            /**
+                    Returns the current DOM element for the view.
+
+                    @property element
+                    @type DOMElement
+                  */
+            element: computed('_parentView', function(key, value) {
+                if (value !== undefined) {
+                    return this.currentState.setElement(this, value);
+                } else {
+                    return this.currentState.getElement(this);
+                }
+            }),
+
+            /**
+                    Returns a jQuery object for this view's element. If you pass in a selector
+                    string, this method will return a jQuery object, using the current element
+                    as its buffer.
+
+                    For example, calling `view.$('li')` will return a jQuery object containing
+                    all of the `li` elements inside the DOM element of this view.
+
+                    @method $
+                    @param {String} [selector] a jQuery-compatible selector string
+                    @return {jQuery} the jQuery object for the DOM node
+                  */
+            $: function(sel) {
+                return this.currentState.$(this, sel);
+            },
+
+            mutateChildViews: function(callback) {
+                var childViews = this._childViews,
+                idx = childViews.length,
+                view;
+
+                while (--idx &gt;= 0) {
+                    view = childViews[idx];
+                    callback(this, view, idx);
+                }
+
+                return this;
+            },
+
+            forEachChildView: function(callback) {
+                var childViews = this._childViews;
+
+                if (!childViews) {
+                    return this;
+                }
+
+                var len = childViews.length,
+                view, idx;
+
+                for (idx = 0; idx &lt; len; idx++) {
+                    view = childViews[idx];
+                    callback(view);
+                }
+
+                return this;
+            },
+
+            /**
+                    Appends the view's element to the specified parent element.
+
+                    If the view does not have an HTML representation yet, `createElement()`
+                    will be called automatically.
+
+                    Note that this method just schedules the view to be appended; the DOM
+                    element will not be appended to the given element until all bindings have
+                    finished synchronizing.
+
+                    This is not typically a function that you will need to call directly when
+                    building your application. You might consider using `Ember.ContainerView`
+                    instead. If you do need to use `appendTo`, be sure that the target element
+                    you are providing is associated with an `Ember.Application` and does not
+                    have an ancestor element that is associated with an Ember view.
+
+                    @method appendTo
+                    @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object
+                    @return {Ember.View} receiver
+                  */
+            appendTo: function(target) {
+                // Schedule the DOM element to be created and appended to the given
+                // element after bindings have synchronized.
+                this._insertElementLater(function() {
+                    Ember.assert(&quot;You tried to append to (&quot; + target + &quot;) but that isn't in the DOM&quot;, jQuery(target).length &gt; 0);
+                    Ember.assert(&quot;You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.&quot;, !jQuery(target).is('.ember-view') &amp;&amp; !jQuery(target).parents().is('.ember-view'));
+                    this.$().appendTo(target);
+                });
+
+                return this;
+            },
+
+            /**
+                    Replaces the content of the specified parent element with this view's
+                    element. If the view does not have an HTML representation yet,
+                    `createElement()` will be called automatically.
+
+                    Note that this method just schedules the view to be appended; the DOM
+                    element will not be appended to the given element until all bindings have
+                    finished synchronizing
+
+                    @method replaceIn
+                    @param {String|DOMElement|jQuery} target A selector, element, HTML string, or jQuery object
+                    @return {Ember.View} received
+                  */
+            replaceIn: function(target) {
+                Ember.assert(&quot;You tried to replace in (&quot; + target + &quot;) but that isn't in the DOM&quot;, jQuery(target).length &gt; 0);
+                Ember.assert(&quot;You cannot replace an existing Ember.View. Consider using Ember.ContainerView instead.&quot;, !jQuery(target).is('.ember-view') &amp;&amp; !jQuery(target).parents().is('.ember-view'));
+
+                this._insertElementLater(function() {
+                    jQuery(target).empty();
+                    this.$().appendTo(target);
+                });
+
+                return this;
+            },
+
+            /**
+                    Schedules a DOM operation to occur during the next render phase. This
+                    ensures that all bindings have finished synchronizing before the view is
+                    rendered.
+
+                    To use, pass a function that performs a DOM operation.
+
+                    Before your function is called, this view and all child views will receive
+                    the `willInsertElement` event. After your function is invoked, this view
+                    and all of its child views will receive the `didInsertElement` event.
+
+                    ```javascript
+                    view._insertElementLater(function() {
+                      this.createElement();
+                      this.$().appendTo('body');
+                    });
+                    ```
+
+                    @method _insertElementLater
+                    @param {Function} fn the function that inserts the element into the DOM
+                    @private
+                  */
+            _insertElementLater: function(fn) {
+                this._scheduledInsert = run.scheduleOnce('render', this, '_insertElement', fn);
+            },
+
+            _insertElement: function (fn) {
+                this._scheduledInsert = null;
+                this.currentState.insertElement(this, fn);
+            },
+
+            /**
+                    Appends the view's element to the document body. If the view does
+                    not have an HTML representation yet, `createElement()` will be called
+                    automatically.
+
+                    If your application uses the `rootElement` property, you must append
+                    the view within that element. Rendering views outside of the `rootElement`
+                    is not supported.
+
+                    Note that this method just schedules the view to be appended; the DOM
+                    element will not be appended to the document body until all bindings have
+                    finished synchronizing.
+
+                    @method append
+                    @return {Ember.View} receiver
+                  */
+            append: function() {
+                return this.appendTo(document.body);
+            },
+
+            /**
+                    Removes the view's element from the element to which it is attached.
+
+                    @method remove
+                    @return {Ember.View} receiver
+                  */
+            remove: function() {
+                // What we should really do here is wait until the end of the run loop
+                // to determine if the element has been re-appended to a different
+                // element.
+                // In the interim, we will just re-render if that happens. It is more
+                // important than elements get garbage collected.
+                if (!this.removedFromDOM) {
+                    this.destroyElement();
+                }
+                this.invokeRecursively(function(view) {
+                    if (view.clearRenderedChildren) {
+                        view.clearRenderedChildren();
+                    }
+                });
+            },
+
+            elementId: null,
+
+            /**
+                    Attempts to discover the element in the parent element. The default
+                    implementation looks for an element with an ID of `elementId` (or the
+                    view's guid if `elementId` is null). You can override this method to
+                    provide your own form of lookup. For example, if you want to discover your
+                    element using a CSS class name instead of an ID.
+
+                    @method findElementInParentElement
+                    @param {DOMElement} parentElement The parent's DOM element
+                    @return {DOMElement} The discovered element
+                  */
+            findElementInParentElement: function(parentElem) {
+                var id = &quot;#&quot; + this.elementId;
+                return jQuery(id)[0] || jQuery(id, parentElem)[0];
+            },
+
+            /**
+                    Creates a DOM representation of the view and all of its
+                    child views by recursively calling the `render()` method.
+
+                    After the element has been created, `didInsertElement` will
+                    be called on this view and all of its child views.
+
+                    @method createElement
+                    @return {Ember.View} receiver
+                  */
+            createElement: function() {
+                if (get(this, 'element')) {
+                    return this;
+                }
+
+                var buffer = this.renderToBuffer();
+                set(this, 'element', buffer.element());
+
+                return this;
+            },
+
+            /**
+                    Called when a view is going to insert an element into the DOM.
+
+                    @event willInsertElement
+                  */
+            willInsertElement: Ember.K,
+
+            /**
+                    Called when the element of the view has been inserted into the DOM
+                    or after the view was re-rendered. Override this function to do any
+                    set up that requires an element in the document body.
+
+                    @event didInsertElement
+                  */
+            didInsertElement: Ember.K,
+
+            /**
+                    Called when the view is about to rerender, but before anything has
+                    been torn down. This is a good opportunity to tear down any manual
+                    observers you have installed based on the DOM state
+
+                    @event willClearRender
+                  */
+            willClearRender: Ember.K,
+
+            /**
+                    Run this callback on the current view (unless includeSelf is false) and recursively on child views.
+
+                    @method invokeRecursively
+                    @param fn {Function}
+                    @param includeSelf {Boolean} Includes itself if true.
+                    @private
+                  */
+            invokeRecursively: function(fn, includeSelf) {
+                var childViews = (includeSelf === false) ? this._childViews : [this];
+                var currentViews, view, currentChildViews;
+
+                while (childViews.length) {
+                    currentViews = childViews.slice();
+                    childViews = [];
+
+                    for (var i = 0, l = currentViews.length; i &lt; l; i++) {
+                        view = currentViews[i];
+                        currentChildViews = view._childViews ? view._childViews.slice(0) : null;
+                        fn(view);
+                        if (currentChildViews) {
+                            childViews.push.apply(childViews, currentChildViews);
+                        }
+                    }
+                }
+            },
+
+            triggerRecursively: function(eventName) {
+                var childViews = [this], currentViews, view, currentChildViews;
+
+                while (childViews.length) {
+                    currentViews = childViews.slice();
+                    childViews = [];
+
+                    for (var i = 0, l = currentViews.length; i &lt; l; i++) {
+                        view = currentViews[i];
+                        currentChildViews = view._childViews ? view._childViews.slice(0) : null;
+                        if (view.trigger) {
+                            view.trigger(eventName);
+                        }
+                        if (currentChildViews) {
+                            childViews.push.apply(childViews, currentChildViews);
+                        }
+
+                    }
+                }
+            },
+
+            viewHierarchyCollection: function() {
+                var currentView, viewCollection = new ViewCollection([this]);
+
+                for (var i = 0; i &lt; viewCollection.length; i++) {
+                    currentView = viewCollection.objectAt(i);
+                    if (currentView._childViews) {
+                        viewCollection.push.apply(viewCollection, currentView._childViews);
+                    }
+                }
+
+                return viewCollection;
+            },
+
+            /**
+                    Destroys any existing element along with the element for any child views
+                    as well. If the view does not currently have a element, then this method
+                    will do nothing.
+
+                    If you implement `willDestroyElement()` on your view, then this method will
+                    be invoked on your view before your element is destroyed to give you a
+                    chance to clean up any event handlers, etc.
+
+                    If you write a `willDestroyElement()` handler, you can assume that your
+                    `didInsertElement()` handler was called earlier for the same element.
+
+                    You should not call or override this method yourself, but you may
+                    want to implement the above callbacks.
+
+                    @method destroyElement
+                    @return {Ember.View} receiver
+                  */
+            destroyElement: function() {
+                return this.currentState.destroyElement(this);
+            },
+
+            /**
+                    Called when the element of the view is going to be destroyed. Override
+                    this function to do any teardown that requires an element, like removing
+                    event listeners.
+
+                    @event willDestroyElement
+                  */
+            willDestroyElement: Ember.K,
+
+            /**
+                    Triggers the `willDestroyElement` event (which invokes the
+                    `willDestroyElement()` method if it exists) on this view and all child
+                    views.
+
+                    Before triggering `willDestroyElement`, it first triggers the
+                    `willClearRender` event recursively.
+
+                    @method _notifyWillDestroyElement
+                    @private
+                  */
+            _notifyWillDestroyElement: function() {
+                var viewCollection = this.viewHierarchyCollection();
+                viewCollection.trigger('willClearRender');
+                viewCollection.trigger('willDestroyElement');
+                return viewCollection;
+            },
+
+            /**
+                    If this view's element changes, we need to invalidate the caches of our
+                    child views so that we do not retain references to DOM elements that are
+                    no longer needed.
+
+                    @method _elementDidChange
+                    @private
+                  */
+            _elementDidChange: observer('element', function() {
+                this.forEachChildView(clearCachedElement);
+            }),
+
+            /**
+                    Called when the parentView property has changed.
+
+                    @event parentViewDidChange
+                  */
+            parentViewDidChange: Ember.K,
+
+            instrumentName: 'view',
+
+            instrumentDetails: function(hash) {
+                hash.template = get(this, 'templateName');
+                this._super(hash);
+            },
+
+            _renderToBuffer: function(buffer) {
+                this.lengthBeforeRender = this._childViews.length;
+                buffer = this._super(buffer);
+                this.lengthAfterRender = this._childViews.length;
+
+                return buffer;
+            },
+
+            renderToBufferIfNeeded: function (buffer) {
+                return this.currentState.renderToBufferIfNeeded(this, buffer);
+            },
+
+            beforeRender: function(buffer) {
+                this.applyAttributesToBuffer(buffer);
+                buffer.pushOpeningTag();
+            },
+
+            afterRender: function(buffer) {
+                buffer.pushClosingTag();
+            },
+
+            applyAttributesToBuffer: function(buffer) {
+                // Creates observers for all registered class name and attribute bindings,
+                // then adds them to the element.
+                var classNameBindings = get(this, 'classNameBindings');
+                if (classNameBindings.length) {
+                    this._applyClassNameBindings(classNameBindings);
+                }
+
+                // Pass the render buffer so the method can apply attributes directly.
+                // This isn't needed for class name bindings because they use the
+                // existing classNames infrastructure.
+                var attributeBindings = get(this, 'attributeBindings');
+                if (attributeBindings.length) {
+                    this._applyAttributeBindings(buffer, attributeBindings);
+                }
+
+                buffer.setClasses(this.classNames);
+                buffer.id(this.elementId);
+
+                var role = get(this, 'ariaRole');
+                if (role) {
+                    buffer.attr('role', role);
+                }
+
+                if (get(this, 'isVisible') === false) {
+                    buffer.style('display', 'none');
+                }
+            },
+
+            // ..........................................................
+            // STANDARD RENDER PROPERTIES
+            //
+
+            /**
+                    Tag name for the view's outer element. The tag name is only used when an
+                    element is first created. If you change the `tagName` for an element, you
+                    must destroy and recreate the view element.
+
+                    By default, the render buffer will use a `&lt;div&gt;` tag for views.
+
+                    @property tagName
+                    @type String
+                    @default null
+                  */
+
+            // We leave this null by default so we can tell the difference between
+            // the default case and a user-specified tag.
+            tagName: null,
+
+            /**
+                    The WAI-ARIA role of the control represented by this view. For example, a
+                    button may have a role of type 'button', or a pane may have a role of
+                    type 'alertdialog'. This property is used by assistive software to help
+                    visually challenged users navigate rich web applications.
+
+                    The full list of valid WAI-ARIA roles is available at:
+                    [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization)
+
+                    @property ariaRole
+                    @type String
+                    @default null
+                  */
+            ariaRole: null,
+
+            /**
+                    Standard CSS class names to apply to the view's outer element. This
+                    property automatically inherits any class names defined by the view's
+                    superclasses as well.
+
+                    @property classNames
+                    @type Array
+                    @default ['ember-view']
+                  */
+            classNames: ['ember-view'],
+
+            /**
+                    A list of properties of the view to apply as class names. If the property
+                    is a string value, the value of that string will be applied as a class
+                    name.
+
+                    ```javascript
+                    // Applies the 'high' class to the view element
+                    Ember.View.extend({
+                      classNameBindings: ['priority']
+                      priority: 'high'
+                    });
+                    ```
+
+                    If the value of the property is a Boolean, the name of that property is
+                    added as a dasherized class name.
+
+                    ```javascript
+                    // Applies the 'is-urgent' class to the view element
+                    Ember.View.extend({
+                      classNameBindings: ['isUrgent']
+                      isUrgent: true
+                    });
+                    ```
+
+                    If you would prefer to use a custom value instead of the dasherized
+                    property name, you can pass a binding like this:
+
+                    ```javascript
+                    // Applies the 'urgent' class to the view element
+                    Ember.View.extend({
+                      classNameBindings: ['isUrgent:urgent']
+                      isUrgent: true
+                    });
+                    ```
+
+                    This list of properties is inherited from the view's superclasses as well.
+
+                    @property classNameBindings
+                    @type Array
+                    @default []
+                  */
+            classNameBindings: EMPTY_ARRAY,
+
+            /**
+                    A list of properties of the view to apply as attributes. If the property is
+                    a string value, the value of that string will be applied as the attribute.
+
+                    ```javascript
+                    // Applies the type attribute to the element
+                    // with the value &quot;button&quot;, like &lt;div type=&quot;button&quot;&gt;
+                    Ember.View.extend({
+                      attributeBindings: ['type'],
+                      type: 'button'
+                    });
+                    ```
+
+                    If the value of the property is a Boolean, the name of that property is
+                    added as an attribute.
+
+                    ```javascript
+                    // Renders something like &lt;div enabled=&quot;enabled&quot;&gt;
+                    Ember.View.extend({
+                      attributeBindings: ['enabled'],
+                      enabled: true
+                    });
+                    ```
+
+                    @property attributeBindings
+                  */
+            attributeBindings: EMPTY_ARRAY,
+
+            // .......................................................
+            // CORE DISPLAY METHODS
+            //
+
+            /**
+                    Setup a view, but do not finish waking it up.
+
+                    * configure `childViews`
+                    * register the view with the global views hash, which is used for event
+                      dispatch
+
+                    @method init
+                    @private
+                  */
+            init: function() {
+                this.elementId = this.elementId || guidFor(this);
+
+                this._super();
+
+                // setup child views. be sure to clone the child views array first
+                this._childViews = this._childViews.slice();
+
+                Ember.assert(&quot;Only arrays are allowed for 'classNameBindings'&quot;, typeOf(this.classNameBindings) === 'array');
+                this.classNameBindings = emberA(this.classNameBindings.slice());
+
+                Ember.assert(&quot;Only arrays are allowed for 'classNames'&quot;, typeOf(this.classNames) === 'array');
+                this.classNames = emberA(this.classNames.slice());
+            },
+
+            appendChild: function(view, options) {
+                return this.currentState.appendChild(this, view, options);
+            },
+
+            /**
+                    Removes the child view from the parent view.
+
+                    @method removeChild
+                    @param {Ember.View} view
+                    @return {Ember.View} receiver
+                  */
+            removeChild: function(view) {
+                // If we're destroying, the entire subtree will be
+                // freed, and the DOM will be handled separately,
+                // so no need to mess with childViews.
+                if (this.isDestroying) {
+                    return;
+                }
+
+                // update parent node
+                set(view, '_parentView', null);
+
+                // remove view from childViews array.
+                var childViews = this._childViews;
+
+                removeObject(childViews, view);
+
+                this.propertyDidChange('childViews'); // HUH?! what happened to will change?
+
+                return this;
+            },
+
+            /**
+                    Removes all children from the `parentView`.
+
+                    @method removeAllChildren
+                    @return {Ember.View} receiver
+                  */
+            removeAllChildren: function() {
+                return this.mutateChildViews(function(parentView, view) {
+                    parentView.removeChild(view);
+                });
+            },
+
+            destroyAllChildren: function() {
+                return this.mutateChildViews(function(parentView, view) {
+                    view.destroy();
+                });
+            },
+
+            /**
+                    Removes the view from its `parentView`, if one is found. Otherwise
+                    does nothing.
+
+                    @method removeFromParent
+                    @return {Ember.View} receiver
+                  */
+            removeFromParent: function() {
+                var parent = this._parentView;
+
+                // Remove DOM element from parent
+                this.remove();
+
+                if (parent) {
+                    parent.removeChild(this);
+                }
+                return this;
+            },
+
+            /**
+                    You must call `destroy` on a view to destroy the view (and all of its
+                    child views). This will remove the view from any parent node, then make
+                    sure that the DOM element managed by the view can be released by the
+                    memory manager.
+
+                    @method destroy
+                  */
+            destroy: function() {
+                var childViews = this._childViews,
+                // get parentView before calling super because it'll be destroyed
+                nonVirtualParentView = get(this, 'parentView'),
+                viewName = this.viewName,
+                childLen, i;
+
+                if (!this._super()) {
+                    return;
+                }
+
+                childLen = childViews.length;
+                for (i = childLen-1; i &gt;= 0; i--) {
+                    childViews[i].removedFromDOM = true;
+                }
+
+                // remove from non-virtual parent view if viewName was specified
+                if (viewName &amp;&amp; nonVirtualParentView) {
+                    nonVirtualParentView.set(viewName, null);
+                }
+
+                childLen = childViews.length;
+                for (i = childLen-1; i &gt;= 0; i--) {
+                    childViews[i].destroy();
+                }
+
+                return this;
+            },
+
+            /**
+                    Instantiates a view to be added to the childViews array during view
+                    initialization. You generally will not call this method directly unless
+                    you are overriding `createChildViews()`. Note that this method will
+                    automatically configure the correct settings on the new view instance to
+                    act as a child of the parent.
+
+                    @method createChildView
+                    @param {Class|String} viewClass
+                    @param {Hash} [attrs] Attributes to add
+                    @return {Ember.View} new instance
+                  */
+            createChildView: function(view, attrs) {
+                if (!view) {
+                    throw new TypeError(&quot;createChildViews first argument must exist&quot;);
+                }
+
+                if (view.isView &amp;&amp; view._parentView === this &amp;&amp; view.container === this.container) {
+                    return view;
+                }
+
+                attrs = attrs || {};
+                attrs._parentView = this;
+
+                if (CoreView.detect(view)) {
+                    attrs.templateData = attrs.templateData || get(this, 'templateData');
+
+                    attrs.container = this.container;
+                    view = view.create(attrs);
+
+                    // don't set the property on a virtual view, as they are invisible to
+                    // consumers of the view API
+                    if (view.viewName) {
+                        set(get(this, 'concreteView'), view.viewName, view);
+                    }
+                } else if ('string' === typeof view) {
+                    var fullName = 'view:' + view;
+                    var ViewKlass = this.container.lookupFactory(fullName);
+
+                    Ember.assert(&quot;Could not find view: '&quot; + fullName + &quot;'&quot;, !!ViewKlass);
+
+                    attrs.templateData = get(this, 'templateData');
+                    view = ViewKlass.create(attrs);
+                } else {
+                    Ember.assert('You must pass instance or subclass of View', view.isView);
+                    attrs.container = this.container;
+
+                    if (!get(view, 'templateData')) {
+                        attrs.templateData = get(this, 'templateData');
+                    }
+
+                    setProperties(view, attrs);
+
+                }
+
+                return view;
+            },
+
+            becameVisible: Ember.K,
+            becameHidden: Ember.K,
+
+            /**
+                    When the view's `isVisible` property changes, toggle the visibility
+                    element of the actual DOM element.
+
+                    @method _isVisibleDidChange
+                    @private
+                  */
+            _isVisibleDidChange: observer('isVisible', function() {
+                if (this._isVisible === get(this, 'isVisible')) {
+                    return ;
+                }
+                run.scheduleOnce('render', this, this._toggleVisibility);
+            }),
+
+            _toggleVisibility: function() {
+                var $el = this.$();
+                if (!$el) {
+                    return;
+                }
+
+                var isVisible = get(this, 'isVisible');
+
+                if (this._isVisible === isVisible) {
+                    return ;
+                }
+
+                $el.toggle(isVisible);
+
+                this._isVisible = isVisible;
+
+                if (this._isAncestorHidden()) {
+                    return;
+                }
+
+                if (isVisible) {
+                    this._notifyBecameVisible();
+                } else {
+                    this._notifyBecameHidden();
+                }
+            },
+
+            _notifyBecameVisible: function() {
+                this.trigger('becameVisible');
+
+                this.forEachChildView(function(view) {
+                    var isVisible = get(view, 'isVisible');
+
+                    if (isVisible || isVisible === null) {
+                        view._notifyBecameVisible();
+                    }
+                });
+            },
+
+            _notifyBecameHidden: function() {
+                this.trigger('becameHidden');
+                this.forEachChildView(function(view) {
+                    var isVisible = get(view, 'isVisible');
+
+                    if (isVisible || isVisible === null) {
+                        view._notifyBecameHidden();
+                    }
+                });
+            },
+
+            _isAncestorHidden: function() {
+                var parent = get(this, 'parentView');
+
+                while (parent) {
+                    if (get(parent, 'isVisible') === false) {
+                        return true;
+                    }
+
+                    parent = get(parent, 'parentView');
+                }
+
+                return false;
+            },
+
+            clearBuffer: function() {
+                this.invokeRecursively(nullViewsBuffer);
+            },
+            transitionTo: function(state, children) {
+                Ember.deprecate(&quot;Ember.View#transitionTo has been deprecated, it is for internal use only&quot;);
+                this._transitionTo(state, children);
+            },
+            _transitionTo: function(state, children) {
+                var priorState = this.currentState;
+                var currentState = this.currentState = this._states[state];
+
+                this._state = state;
+
+                if (priorState &amp;&amp; priorState.exit) {
+                    priorState.exit(this);
+                }
+                if (currentState.enter) {
+                    currentState.enter(this);
+                }
+                if (state === 'inDOM') {
+                    meta(this).cache.element = undefined;
+                }
+
+                if (children !== false) {
+                    this.forEachChildView(function(view) {
+                        view._transitionTo(state);
+                    });
+                }
+            },
+
+            // .......................................................
+            // EVENT HANDLING
+            //
+
+            /**
+                    Handle events from `Ember.EventDispatcher`
+
+                    @method handleEvent
+                    @param eventName {String}
+                    @param evt {Event}
+                    @private
+                  */
+            handleEvent: function(eventName, evt) {
+                return this.currentState.handleEvent(this, eventName, evt);
+            },
+
+            registerObserver: function(root, path, target, observer) {
+                if (!observer &amp;&amp; 'function' === typeof target) {
+                    observer = target;
+                    target = null;
+                }
+
+                if (!root || typeof root !== 'object') {
+                    return;
+                }
+
+                var view = this,
+                stateCheckedObserver = function() {
+                    view.currentState.invokeObserver(this, observer);
+                },
+                scheduledObserver = function() {
+                    run.scheduleOnce('render', this, stateCheckedObserver);
+                };
+
+                addObserver(root, path, target, scheduledObserver);
+
+                this.one('willClearRender', function() {
+                    removeObserver(root, path, target, scheduledObserver);
+                });
+            }
+
+        });
+
+        /*
+              Describe how the specified actions should behave in the various
+              states that a view can exist in. Possible states:
+
+              * preRender: when a view is first instantiated, and after its
+                element was destroyed, it is in the preRender state
+              * inBuffer: once a view has been rendered, but before it has
+                been inserted into the DOM, it is in the inBuffer state
+              * hasElement: the DOM representation of the view is created,
+                and is ready to be inserted
+              * inDOM: once a view has been inserted into the DOM it is in
+                the inDOM state. A view spends the vast majority of its
+                existence in this state.
+              * destroyed: once a view has been destroyed (using the destroy
+                method), it is in this state. No further actions can be invoked
+                on a destroyed view.
+            */
+
+        // in the destroyed state, everything is illegal
+
+        // before rendering has begun, all legal manipulations are noops.
+
+        // inside the buffer, legal manipulations are done on the buffer
+
+        // once the view has been inserted into the DOM, legal manipulations
+        // are done on the DOM element.
+
+        function notifyMutationListeners() {
+            run.once(View, 'notifyMutationListeners');
+        }
+
+        var DOMManager = {
+            prepend: function(view, html) {
+                view.$().prepend(html);
+                notifyMutationListeners();
+            },
+
+            after: function(view, html) {
+                view.$().after(html);
+                notifyMutationListeners();
+            },
+
+            html: function(view, html) {
+                view.$().html(html);
+                notifyMutationListeners();
+            },
+
+            replace: function(view) {
+                var element = get(view, 'element');
+
+                set(view, 'element', null);
+
+                view._insertElementLater(function() {
+                    jQuery(element).replaceWith(get(view, 'element'));
+                    notifyMutationListeners();
+                });
+            },
+
+            remove: function(view) {
+                view.$().remove();
+                notifyMutationListeners();
+            },
+
+            empty: function(view) {
+                view.$().empty();
+                notifyMutationListeners();
+            }
+        };
+
+        View.reopen({
+            domManager: DOMManager
+        });
+
+        View.reopenClass({
+
+            /**
+                    Parse a path and return an object which holds the parsed properties.
+
+                    For example a path like &quot;content.isEnabled:enabled:disabled&quot; will return the
+                    following object:
+
+                    ```javascript
+                    {
+                      path: &quot;content.isEnabled&quot;,
+                      className: &quot;enabled&quot;,
+                      falsyClassName: &quot;disabled&quot;,
+                      classNames: &quot;:enabled:disabled&quot;
+                    }
+                    ```
+
+                    @method _parsePropertyPath
+                    @static
+                    @private
+                  */
+            _parsePropertyPath: function(path) {
+                var split = path.split(':'),
+                propertyPath = split[0],
+                classNames = &quot;&quot;,
+                className,
+                falsyClassName;
+
+                // check if the property is defined as prop:class or prop:trueClass:falseClass
+                if (split.length &gt; 1) {
+                    className = split[1];
+                    if (split.length === 3) {
+                        falsyClassName = split[2];
+                    }
+
+                    classNames = ':' + className;
+                    if (falsyClassName) {
+                        classNames += &quot;:&quot; + falsyClassName;
+                    }
+                }
+
+                return {
+                    path: propertyPath,
+                    classNames: classNames,
+                    className: (className === '') ? undefined : className,
+                    falsyClassName: falsyClassName
+                };
+            },
+
+            /**
+                    Get the class name for a given value, based on the path, optional
+                    `className` and optional `falsyClassName`.
+
+                    - if a `className` or `falsyClassName` has been specified:
+                      - if the value is truthy and `className` has been specified,
+                        `className` is returned
+                      - if the value is falsy and `falsyClassName` has been specified,
+                        `falsyClassName` is returned
+                      - otherwise `null` is returned
+                    - if the value is `true`, the dasherized last part of the supplied path
+                      is returned
+                    - if the value is not `false`, `undefined` or `null`, the `value`
+                      is returned
+                    - if none of the above rules apply, `null` is returned
+
+                    @method _classStringForValue
+                    @param path
+                    @param val
+                    @param className
+                    @param falsyClassName
+                    @static
+                    @private
+                  */
+            _classStringForValue: function(path, val, className, falsyClassName) {
+                if (isArray(val)) {
+                    val = get(val, 'length') !== 0;
+                }
+
+                // When using the colon syntax, evaluate the truthiness or falsiness
+                // of the value to determine which className to return
+                if (className || falsyClassName) {
+                    if (className &amp;&amp; !!val) {
+                        return className;
+
+                    } else if (falsyClassName &amp;&amp; !val) {
+                        return falsyClassName;
+
+                    } else {
+                        return null;
+                    }
+
+                    // If value is a Boolean and true, return the dasherized property
+                    // name.
+                } else if (val === true) {
+                    // Normalize property path to be suitable for use
+                    // as a class name. For exaple, content.foo.barBaz
+                    // becomes bar-baz.
+                    var parts = path.split('.');
+                    return dasherize(parts[parts.length-1]);
+
+                    // If the value is not false, undefined, or null, return the current
+                    // value of the property.
+                } else if (val !== false &amp;&amp; val != null) {
+                    return val;
+
+                    // Nothing to display. Return null so that the old class is removed
+                    // but no new class is added.
+                } else {
+                    return null;
+                }
+            }
+        });
+
+        var mutation = EmberObject.extend(Evented).create();
+
+        View.addMutationListener = function(callback) {
+            mutation.on('change', callback);
+        };
+
+        View.removeMutationListener = function(callback) {
+            mutation.off('change', callback);
+        };
+
+        View.notifyMutationListeners = function() {
+            mutation.trigger('change');
+        };
+
+        /**
+              Global views hash
+
+              @property views
+              @static
+              @type Hash
+            */
+        View.views = {};
+
+        // If someone overrides the child views computed property when
+        // defining their class, we want to be able to process the user's
+        // supplied childViews and then restore the original computed property
+        // at view initialization time. This happens in Ember.ContainerView's init
+        // method.
+        View.childViewsProperty = childViewsProperty;
+
+        View.applyAttributeBindings = function(elem, name, value) {
+            var type = typeOf(value);
+
+            // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
+            if (name !== 'value' &amp;&amp; (type === 'string' || (type === 'number' &amp;&amp; !isNaN(value)))) {
+                if (value !== elem.attr(name)) {
+                    elem.attr(name, value);
+                }
+            } else if (name === 'value' || type === 'boolean') {
+                if (isNone(value) || value === false) {
+                    // `null`, `undefined` or `false` should remove attribute
+                    elem.removeAttr(name);
+                    // In IE8 `prop` couldn't remove attribute when name is `required`.
+                    if (name === 'required') {
+                        elem.removeProp(name);
+                    } else {
+                        elem.prop(name, '');
+                    }
+                } else if (value !== elem.prop(name)) {
+                    // value should always be properties
+                    elem.prop(name, value);
+                }
+            } else if (!value) {
+                elem.removeAttr(name);
+            }
+        };
+
+        __exports__[&quot;default&quot;] = View;
+    });
+    define(&quot;ember-views/views/view_collection&quot;,
+    [&quot;ember-metal/enumerable_utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var forEach = __dependency1__.forEach;
+
+        function ViewCollection(initialViews) {
+            var views = this.views = initialViews || [];
+            this.length = views.length;
+        }
+
+        ViewCollection.prototype = {
+            length: 0,
+
+            trigger: function(eventName) {
+                var views = this.views, view;
+                for (var i = 0, l = views.length; i &lt; l; i++) {
+                    view = views[i];
+                    if (view.trigger) {
+                        view.trigger(eventName);
+                    }
+                }
+            },
+
+            triggerRecursively: function(eventName) {
+                var views = this.views;
+                for (var i = 0, l = views.length; i &lt; l; i++) {
+                    views[i].triggerRecursively(eventName);
+                }
+            },
+
+            invokeRecursively: function(fn) {
+                var views = this.views, view;
+
+                for (var i = 0, l = views.length; i &lt; l; i++) {
+                    view = views[i];
+                    fn(view);
+                }
+            },
+
+            transitionTo: function(state, children) {
+                var views = this.views;
+                for (var i = 0, l = views.length; i &lt; l; i++) {
+                    views[i]._transitionTo(state, children);
+                }
+            },
+
+            push: function() {
+                this.length += arguments.length;
+                var views = this.views;
+                return views.push.apply(views, arguments);
+            },
+
+            objectAt: function(idx) {
+                return this.views[idx];
+            },
+
+            forEach: function(callback) {
+                var views = this.views;
+                return forEach(views, callback);
+            },
+
+            clear: function() {
+                this.length = 0;
+                this.views.length = 0;
+            }
+        };
+
+        __exports__[&quot;default&quot;] = ViewCollection;
+    });
+    define(&quot;ember&quot;,
+    [&quot;ember-metal&quot;, &quot;ember-runtime&quot;, &quot;ember-handlebars&quot;, &quot;ember-views&quot;, &quot;ember-routing&quot;, &quot;ember-routing-handlebars&quot;, &quot;ember-application&quot;, &quot;ember-extension-support&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
+        &quot;use strict&quot;;
+        // require the main entry points for each of these packages
+        // this is so that the global exports occur properly
+
+        // do this to ensure that Ember.Test is defined properly on the global
+        // if it is present.
+        if (Ember.__loader.registry['ember-testing']) {
+            requireModule('ember-testing');
+        }
+
+        /**
+            Ember
+
+            @module ember
+            */
+
+        function throwWithMessage(msg) {
+            return function() {
+                throw new Ember.Error(msg);
+            };
+        }
+
+        function generateRemovedClass(className) {
+            var msg = &quot; has been moved into a plugin: https://github.com/emberjs/ember-states&quot;;
+
+            return {
+                extend: throwWithMessage(className + msg),
+                create: throwWithMessage(className + msg)
+            };
+        }
+
+        Ember.StateManager = generateRemovedClass(&quot;Ember.StateManager&quot;);
+
+        /**
+              This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states
+
+              @class StateManager
+              @namespace Ember
+            */
+
+        Ember.State = generateRemovedClass(&quot;Ember.State&quot;);
+
+        /**
+              This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states
+
+              @class State
+              @namespace Ember
+            */
+    });
+    define(&quot;metamorph&quot;,
+    [],
+    function() {
+        &quot;use strict&quot;;
+        // ==========================================================================
+        // Project:   metamorph
+        // Copyright: ©2014 Tilde, Inc. All rights reserved.
+        // ==========================================================================
+
+        var K = function() {},
+        guid = 0,
+        disableRange = (function() {
+            if ('undefined' !== typeof MetamorphENV) {
+                return MetamorphENV.DISABLE_RANGE_API;
+            } else if ('undefined' !== ENV) {
+                return ENV.DISABLE_RANGE_API;
+            } else {
+                return false;
+            }
+        })(),
+        // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
+        supportsRange = (!disableRange) &amp;&amp; typeof document !== 'undefined' &amp;&amp; ('createRange' in document) &amp;&amp; (typeof Range !== 'undefined') &amp;&amp; Range.prototype.createContextualFragment,
+        // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
+        // is a &quot;zero-scope&quot; element. This problem can be worked around by making
+        // the first node an invisible text node. We, like Modernizr, use &amp;shy;
+        needsShy = typeof document !== 'undefined' &amp;&amp; (function() {
+            var testEl = document.createElement('div');
+            testEl.innerHTML = &quot;&lt;div&gt;&lt;/div&gt;&quot;;
+            testEl.firstChild.innerHTML = &quot;&lt;script&gt;&lt;/script&gt;&quot;;
+            return testEl.firstChild.innerHTML === '';
+        })(),
+
+        // IE 8 (and likely earlier) likes to move whitespace preceeding
+        // a script tag to appear after it. This means that we can
+        // accidentally remove whitespace when updating a morph.
+        movesWhitespace = document &amp;&amp; (function() {
+            var testEl = document.createElement('div');
+            testEl.innerHTML = &quot;Test: &lt;script type='text/x-placeholder'&gt;&lt;/script&gt;Value&quot;;
+            return testEl.childNodes[0].nodeValue === 'Test:' &amp;&amp;
+            testEl.childNodes[2].nodeValue === ' Value';
+        })();
+
+        // Constructor that supports either Metamorph('foo') or new
+        // Metamorph('foo');
+        //
+        // Takes a string of HTML as the argument.
+
+        var Metamorph = function(html) {
+            var self;
+
+            if (this instanceof Metamorph) {
+                self = this;
+            } else {
+                self = new K();
+            }
+
+            self.innerHTML = html;
+            var myGuid = 'metamorph-' + (guid++);
+            self.start = myGuid + '-start';
+            self.end = myGuid + '-end';
+
+            return self;
+        };
+
+        K.prototype = Metamorph.prototype;
+
+        var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;
+
+        outerHTMLFunc = function() {
+            return this.startTag() + this.innerHTML + this.endTag();
+        };
+
+        startTagFunc = function() {
+            /*
+                   * We replace chevron by its hex code in order to prevent escaping problems.
+                   * Check this thread for more explaination:
+                   * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
+                   */
+            return &quot;&lt;script id='&quot; + this.start + &quot;' type='text/x-placeholder'&gt;\x3C/script&gt;&quot;;
+        };
+
+        endTagFunc = function() {
+            /*
+                   * We replace chevron by its hex code in order to prevent escaping problems.
+                   * Check this thread for more explaination:
+                   * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
+                   */
+            return &quot;&lt;script id='&quot; + this.end + &quot;' type='text/x-placeholder'&gt;\x3C/script&gt;&quot;;
+        };
+
+        // If we have the W3C range API, this process is relatively straight forward.
+        if (supportsRange) {
+
+            // Get a range for the current morph. Optionally include the starting and
+            // ending placeholders.
+            rangeFor = function(morph, outerToo) {
+                var range = document.createRange();
+                var before = document.getElementById(morph.start);
+                var after = document.getElementById(morph.end);
+
+                if (outerToo) {
+                    range.setStartBefore(before);
+                    range.setEndAfter(after);
+                } else {
+                    range.setStartAfter(before);
+                    range.setEndBefore(after);
+                }
+
+                return range;
+            };
+
+            htmlFunc = function(html, outerToo) {
+                // get a range for the current metamorph object
+                var range = rangeFor(this, outerToo);
+
+                // delete the contents of the range, which will be the
+                // nodes between the starting and ending placeholder.
+                range.deleteContents();
+
+                // create a new document fragment for the HTML
+                var fragment = range.createContextualFragment(html);
+
+                // insert the fragment into the range
+                range.insertNode(fragment);
+            };
+
+            /**
+                  * @public
+                  *
+                  * Remove this object (including starting and ending
+                  * placeholders).
+                  *
+                  * @method remove
+                  */
+            removeFunc = function() {
+                // get a range for the current metamorph object including
+                // the starting and ending placeholders.
+                var range = rangeFor(this, true);
+
+                // delete the entire range.
+                range.deleteContents();
+            };
+
+            appendToFunc = function(node) {
+                var range = document.createRange();
+                range.setStart(node);
+                range.collapse(false);
+                var frag = range.createContextualFragment(this.outerHTML());
+                node.appendChild(frag);
+            };
+
+            afterFunc = function(html) {
+                var range = document.createRange();
+                var after = document.getElementById(this.end);
+
+                range.setStartAfter(after);
+                range.setEndAfter(after);
+
+                var fragment = range.createContextualFragment(html);
+                range.insertNode(fragment);
+            };
+
+            prependFunc = function(html) {
+                var range = document.createRange();
+                var start = document.getElementById(this.start);
+
+                range.setStartAfter(start);
+                range.setEndAfter(start);
+
+                var fragment = range.createContextualFragment(html);
+                range.insertNode(fragment);
+            };
+
+        } else {
+            /*
+                   * This code is mostly taken from jQuery, with one exception. In jQuery's case, we
+                   * have some HTML and we need to figure out how to convert it into some nodes.
+                   *
+                   * In this case, jQuery needs to scan the HTML looking for an opening tag and use
+                   * that as the key for the wrap map. In our case, we know the parent node, and
+                   * can use its type as the key for the wrap map.
+                   **/
+            Metamorph._wrapMap = {
+                select: [ 1, &quot;&lt;select multiple='multiple'&gt;&quot;, &quot;&lt;/select&gt;&quot; ],
+                fieldset: [ 1, &quot;&lt;fieldset&gt;&quot;, &quot;&lt;/fieldset&gt;&quot; ],
+                table: [ 1, &quot;&lt;table&gt;&quot;, &quot;&lt;/table&gt;&quot; ],
+                tbody: [ 2, &quot;&lt;table&gt;&lt;tbody&gt;&quot;, &quot;&lt;/tbody&gt;&lt;/table&gt;&quot; ],
+                tr: [ 3, &quot;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&quot;, &quot;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&quot; ],
+                colgroup: [ 2, &quot;&lt;table&gt;&lt;tbody&gt;&lt;/tbody&gt;&lt;colgroup&gt;&quot;, &quot;&lt;/colgroup&gt;&lt;/table&gt;&quot; ],
+                map: [ 1, &quot;&lt;map&gt;&quot;, &quot;&lt;/map&gt;&quot; ],
+                _default: [ 0, &quot;&quot;, &quot;&quot; ]
+            };
+
+            var findChildById = function(element, id) {
+                if (element.getAttribute('id') === id) {
+                    return element;
+                }
+
+                var len = element.childNodes.length, idx, node, found;
+                for (idx = 0; idx &lt; len; idx++) {
+                    node = element.childNodes[idx];
+                    found = node.nodeType === 1 &amp;&amp; findChildById(node, id);
+                    if (found) {
+                        return found;
+                    }
+                }
+            };
+
+            var setInnerHTML = function(element, html) {
+                var matches = [];
+                if (movesWhitespace) {
+                    // Right now we only check for script tags with ids with the
+                    // goal of targeting morphs.
+                    html = html.replace(/(\s+)(&lt;script id='([^']+)')/g, function(match, spaces, tag, id) {
+                        matches.push([id, spaces]);
+                        return tag;
+                    });
+                }
+
+                element.innerHTML = html;
+
+                // If we have to do any whitespace adjustments do them now
+                if (matches.length &gt; 0) {
+                    var len = matches.length, idx;
+                    for (idx = 0; idx &lt; len; idx++) {
+                        var script = findChildById(element, matches[idx][0]),
+                        node = document.createTextNode(matches[idx][1]);
+                        script.parentNode.insertBefore(node, script);
+                    }
+                }
+            };
+
+            /*
+                   * Given a parent node and some HTML, generate a set of nodes. Return the first
+                   * node, which will allow us to traverse the rest using nextSibling.
+                   *
+                   * We need to do this because innerHTML in IE does not really parse the nodes.
+                   */
+            var firstNodeFor = function(parentNode, html) {
+                var wrapMap = Metamorph._wrapMap;
+                var arr = wrapMap[parentNode.tagName.toLowerCase()] || wrapMap._default;
+                var depth = arr[0], start = arr[1], end = arr[2];
+
+                if (needsShy) {
+                    html = '&amp;shy;' + html;
+                }
+
+                var element = document.createElement('div');
+
+                setInnerHTML(element, start + html + end);
+
+                for (var i = 0; i &lt;= depth; i++) {
+                    element = element.firstChild;
+                }
+
+                // Look for &amp;shy; to remove it.
+                if (needsShy) {
+                    var shyElement = element;
+
+                    // Sometimes we get nameless elements with the shy inside
+                    while (shyElement.nodeType === 1 &amp;&amp; !shyElement.nodeName) {
+                        shyElement = shyElement.firstChild;
+                    }
+
+                    // At this point it's the actual unicode character.
+                    if (shyElement.nodeType === 3 &amp;&amp; shyElement.nodeValue.charAt(0) === &quot;\u00AD&quot;) {
+                        shyElement.nodeValue = shyElement.nodeValue.slice(1);
+                    }
+                }
+
+                return element;
+            };
+
+            /*
+                   * In some cases, Internet Explorer can create an anonymous node in
+                   * the hierarchy with no tagName. You can create this scenario via:
+                   *
+                   *     div = document.createElement(&quot;div&quot;);
+                   *     div.innerHTML = &quot;&lt;table&gt;&amp;shy&lt;script&gt;&lt;/script&gt;&lt;tr&gt;&lt;td&gt;hi&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&quot;;
+                   *     div.firstChild.firstChild.tagName //=&gt; &quot;&quot;
+                   *
+                   * If our script markers are inside such a node, we need to find that
+                   * node and use *it* as the marker.
+                   */
+            var realNode = function(start) {
+                while (start.parentNode.tagName === &quot;&quot;) {
+                    start = start.parentNode;
+                }
+
+                return start;
+            };
+
+            /*
+                   * When automatically adding a tbody, Internet Explorer inserts the
+                   * tbody immediately before the first &lt;tr&gt;. Other browsers create it
+                   * before the first node, no matter what.
+                   *
+                   * This means the the following code:
+                   *
+                   *     div = document.createElement(&quot;div&quot;);
+                   *     div.innerHTML = &quot;&lt;table&gt;&lt;script id='first'&gt;&lt;/script&gt;&lt;tr&gt;&lt;td&gt;hi&lt;/td&gt;&lt;/tr&gt;&lt;script id='last'&gt;&lt;/script&gt;&lt;/table&gt;
+                   *
+                   * Generates the following DOM in IE:
+                   *
+                   *     + div
+                   *       + table
+                   *         - script id='first'
+                   *         + tbody
+                   *           + tr
+                   *             + td
+                   *               - &quot;hi&quot;
+                   *           - script id='last'
+                   *
+                   * Which means that the two script tags, even though they were
+                   * inserted at the same point in the hierarchy in the original
+                   * HTML, now have different parents.
+                   *
+                   * This code reparents the first script tag by making it the tbody's
+                   * first child.
+                   *
+                   */
+            var fixParentage = function(start, end) {
+                if (start.parentNode !== end.parentNode) {
+                    end.parentNode.insertBefore(start, end.parentNode.firstChild);
+                }
+            };
+
+            htmlFunc = function(html, outerToo) {
+                // get the real starting node. see realNode for details.
+                var start = realNode(document.getElementById(this.start));
+                var end = document.getElementById(this.end);
+                var parentNode = end.parentNode;
+                var node, nextSibling, last;
+
+                // make sure that the start and end nodes share the same
+                // parent. If not, fix it.
+                fixParentage(start, end);
+
+                // remove all of the nodes after the starting placeholder and
+                // before the ending placeholder.
+                node = start.nextSibling;
+                while (node) {
+                    nextSibling = node.nextSibling;
+                    last = node === end;
+
+                    // if this is the last node, and we want to remove it as well,
+                    // set the `end` node to the next sibling. This is because
+                    // for the rest of the function, we insert the new nodes
+                    // before the end (note that insertBefore(node, null) is
+                    // the same as appendChild(node)).
+                    //
+                    // if we do not want to remove it, just break.
+                    if (last) {
+                        if (outerToo) {
+                            end = node.nextSibling;
+                        } else {
+                            break;
+                        }
+                    }
+
+                    node.parentNode.removeChild(node);
+
+                    // if this is the last node and we didn't break before
+                    // (because we wanted to remove the outer nodes), break
+                    // now.
+                    if (last) {
+                        break;
+                    }
+
+                    node = nextSibling;
+                }
+
+                // get the first node for the HTML string, even in cases like
+                // tables and lists where a simple innerHTML on a div would
+                // swallow some of the content.
+                node = firstNodeFor(start.parentNode, html);
+
+                if (outerToo) {
+                    start.parentNode.removeChild(start);
+                }
+
+                // copy the nodes for the HTML between the starting and ending
+                // placeholder.
+                while (node) {
+                    nextSibling = node.nextSibling;
+                    parentNode.insertBefore(node, end);
+                    node = nextSibling;
+                }
+            };
+
+            // remove the nodes in the DOM representing this metamorph.
+            //
+            // this includes the starting and ending placeholders.
+            removeFunc = function() {
+                var start = realNode(document.getElementById(this.start));
+                var end = document.getElementById(this.end);
+
+                this.html('');
+                start.parentNode.removeChild(start);
+                end.parentNode.removeChild(end);
+            };
+
+            appendToFunc = function(parentNode) {
+                var node = firstNodeFor(parentNode, this.outerHTML());
+                var nextSibling;
+
+                while (node) {
+                    nextSibling = node.nextSibling;
+                    parentNode.appendChild(node);
+                    node = nextSibling;
+                }
+            };
+
+            afterFunc = function(html) {
+                // get the real starting node. see realNode for details.
+                var end = document.getElementById(this.end);
+                var insertBefore = end.nextSibling;
+                var parentNode = end.parentNode;
+                var nextSibling;
+                var node;
+
+                // get the first node for the HTML string, even in cases like
+                // tables and lists where a simple innerHTML on a div would
+                // swallow some of the content.
+                node = firstNodeFor(parentNode, html);
+
+                // copy the nodes for the HTML between the starting and ending
+                // placeholder.
+                while (node) {
+                    nextSibling = node.nextSibling;
+                    parentNode.insertBefore(node, insertBefore);
+                    node = nextSibling;
+                }
+            };
+
+            prependFunc = function(html) {
+                var start = document.getElementById(this.start);
+                var parentNode = start.parentNode;
+                var nextSibling;
+                var node;
+
+                node = firstNodeFor(parentNode, html);
+                var insertBefore = start.nextSibling;
+
+                while (node) {
+                    nextSibling = node.nextSibling;
+                    parentNode.insertBefore(node, insertBefore);
+                    node = nextSibling;
+                }
+            };
+        }
+
+        Metamorph.prototype.html = function(html) {
+            this.checkRemoved();
+            if (html === undefined) {
+                return this.innerHTML;
+            }
+
+            htmlFunc.call(this, html);
+
+            this.innerHTML = html;
+        };
+
+        Metamorph.prototype.replaceWith = function(html) {
+            this.checkRemoved();
+            htmlFunc.call(this, html, true);
+        };
+
+        Metamorph.prototype.remove = removeFunc;
+        Metamorph.prototype.outerHTML = outerHTMLFunc;
+        Metamorph.prototype.appendTo = appendToFunc;
+        Metamorph.prototype.after = afterFunc;
+        Metamorph.prototype.prepend = prependFunc;
+        Metamorph.prototype.startTag = startTagFunc;
+        Metamorph.prototype.endTag = endTagFunc;
+
+        Metamorph.prototype.isRemoved = function() {
+            var before = document.getElementById(this.start);
+            var after = document.getElementById(this.end);
+
+            return !before || !after;
+        };
+
+        Metamorph.prototype.checkRemoved = function() {
+            if (this.isRemoved()) {
+                throw new Error(&quot;Cannot perform operations on a Metamorph that is not in the DOM.&quot;);
+            }
+        };
+
+        return Metamorph;
+    });
+
+    define(&quot;route-recognizer&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        var specials = [
+        '/', '.', '*', '+', '?', '|',
+        '(', ')', '[', ']', '{', '}', '\\'
+        ];
+
+        var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
+
+        function isArray(test) {
+            return Object.prototype.toString.call(test) === &quot;[object Array]&quot;;
+        }
+
+        // A Segment represents a segment in the original route description.
+        // Each Segment type provides an `eachChar` and `regex` method.
+        //
+        // The `eachChar` method invokes the callback with one or more character
+        // specifications. A character specification consumes one or more input
+        // characters.
+        //
+        // The `regex` method returns a regex fragment for the segment. If the
+        // segment is a dynamic of star segment, the regex fragment also includes
+        // a capture.
+        //
+        // A character specification contains:
+        //
+        // * `validChars`: a String with a list of all valid characters, or
+        // * `invalidChars`: a String with a list of all invalid characters
+        // * `repeat`: true if the character specification can repeat
+
+        function StaticSegment(string) {
+            this.string = string;
+        }
+        StaticSegment.prototype = {
+            eachChar: function(callback) {
+                var string = this.string, ch;
+
+                for (var i = 0, l = string.length; i &lt; l; i++) {
+                    ch = string.charAt(i);
+                    callback({
+                        validChars: ch 
+                    });
+                }
+            },
+
+            regex: function() {
+                return this.string.replace(escapeRegex, '\\$1');
+            },
+
+            generate: function() {
+                return this.string;
+            }
+        };
+
+        function DynamicSegment(name) {
+            this.name = name;
+        }
+        DynamicSegment.prototype = {
+            eachChar: function(callback) {
+                callback({
+                    invalidChars: &quot;/&quot;,
+                    repeat: true 
+                });
+            },
+
+            regex: function() {
+                return &quot;([^/]+)&quot;;
+            },
+
+            generate: function(params) {
+                return params[this.name];
+            }
+        };
+
+        function StarSegment(name) {
+            this.name = name;
+        }
+        StarSegment.prototype = {
+            eachChar: function(callback) {
+                callback({
+                    invalidChars: &quot;&quot;,
+                    repeat: true 
+                });
+            },
+
+            regex: function() {
+                return &quot;(.+)&quot;;
+            },
+
+            generate: function(params) {
+                return params[this.name];
+            }
+        };
+
+        function EpsilonSegment() {}
+        EpsilonSegment.prototype = {
+            eachChar: function() {},
+            regex: function() {
+                return &quot;&quot;;
+            },
+            generate: function() {
+                return &quot;&quot;;
+            }
+        };
+
+        function parse(route, names, types) {
+            // normalize route as not starting with a &quot;/&quot;. Recognition will
+            // also normalize.
+            if (route.charAt(0) === &quot;/&quot;) {
+                route = route.substr(1);
+            }
+
+            var segments = route.split(&quot;/&quot;), results = [];
+
+            for (var i = 0, l = segments.length; i &lt; l; i++) {
+                var segment = segments[i], match;
+
+                if (match = segment.match(/^:([^\/]+)$/)) {
+                    results.push(new DynamicSegment(match[1]));
+                    names.push(match[1]);
+                    types.dynamics++;
+                } else if (match = segment.match(/^\*([^\/]+)$/)) {
+                    results.push(new StarSegment(match[1]));
+                    names.push(match[1]);
+                    types.stars++;
+                } else if (segment === &quot;&quot;) {
+                    results.push(new EpsilonSegment());
+                } else {
+                    results.push(new StaticSegment(segment));
+                    types.statics++;
+                }
+            }
+
+            return results;
+        }
+
+        // A State has a character specification and (`charSpec`) and a list of possible
+        // subsequent states (`nextStates`).
+        //
+        // If a State is an accepting state, it will also have several additional
+        // properties:
+        //
+        // * `regex`: A regular expression that is used to extract parameters from paths
+        //   that reached this accepting state.
+        // * `handlers`: Information on how to convert the list of captures into calls
+        //   to registered handlers with the specified parameters
+        // * `types`: How many static, dynamic or star segments in this route. Used to
+        //   decide which route to use if multiple registered routes match a path.
+        //
+        // Currently, State is implemented naively by looping over `nextStates` and
+        // comparing a character specification against a character. A more efficient
+        // implementation would use a hash of keys pointing at one or more next states.
+
+        function State(charSpec) {
+            this.charSpec = charSpec;
+            this.nextStates = [];
+        }
+
+        State.prototype = {
+            get: function(charSpec) {
+                var nextStates = this.nextStates;
+
+                for (var i = 0, l = nextStates.length; i &lt; l; i++) {
+                    var child = nextStates[i];
+
+                    var isEqual = child.charSpec.validChars === charSpec.validChars;
+                    isEqual = isEqual &amp;&amp; child.charSpec.invalidChars === charSpec.invalidChars;
+
+                    if (isEqual) {
+                        return child;
+                    }
+                }
+            },
+
+            put: function(charSpec) {
+                var state;
+
+                // If the character specification already exists in a child of the current
+                // state, just return that state.
+                if (state = this.get(charSpec)) {
+                    return state;
+                }
+
+                // Make a new state for the character spec
+                state = new State(charSpec);
+
+                // Insert the new state as a child of the current state
+                this.nextStates.push(state);
+
+                // If this character specification repeats, insert the new state as a child
+                // of itself. Note that this will not trigger an infinite loop because each
+                // transition during recognition consumes a character.
+                if (charSpec.repeat) {
+                    state.nextStates.push(state);
+                }
+
+                // Return the new state
+                return state;
+            },
+
+            // Find a list of child states matching the next character
+            match: function(ch) {
+                // DEBUG &quot;Processing `&quot; + ch + &quot;`:&quot;
+                var nextStates = this.nextStates,
+                child, charSpec, chars;
+
+                // DEBUG &quot;  &quot; + debugState(this)
+                var returned = [];
+
+                for (var i = 0, l = nextStates.length; i &lt; l; i++) {
+                    child = nextStates[i];
+
+                    charSpec = child.charSpec;
+
+                    if (typeof (chars = charSpec.validChars) !== 'undefined') {
+                        if (chars.indexOf(ch) !== -1) {
+                            returned.push(child);
+                        }
+                    } else if (typeof (chars = charSpec.invalidChars) !== 'undefined') {
+                        if (chars.indexOf(ch) === -1) {
+                            returned.push(child);
+                        }
+                    }
+                }
+
+                return returned;
+            }
+
+            /** IF DEBUG
+                  , debug: function() {
+                    var charSpec = this.charSpec,
+                        debug = &quot;[&quot;,
+                        chars = charSpec.validChars || charSpec.invalidChars;
+
+                    if (charSpec.invalidChars) { debug += &quot;^&quot;; }
+                    debug += chars;
+                    debug += &quot;]&quot;;
+
+                    if (charSpec.repeat) { debug += &quot;+&quot;; }
+
+                    return debug;
+                  }
+                  END IF **/
+        };
+
+        /** IF DEBUG
+            function debug(log) {
+              console.log(log);
+            }
+
+            function debugState(state) {
+              return state.nextStates.map(function(n) {
+                if (n.nextStates.length === 0) { return &quot;( &quot; + n.debug() + &quot; [accepting] )&quot;; }
+                return &quot;( &quot; + n.debug() + &quot; &lt;then&gt; &quot; + n.nextStates.map(function(s) { return s.debug() }).join(&quot; or &quot;) + &quot; )&quot;;
+              }).join(&quot;, &quot;)
+            }
+            END IF **/
+
+        // This is a somewhat naive strategy, but should work in a lot of cases
+        // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id.
+        //
+        // This strategy generally prefers more static and less dynamic matching.
+        // Specifically, it
+        //
+        //  * prefers fewer stars to more, then
+        //  * prefers using stars for less of the match to more, then
+        //  * prefers fewer dynamic segments to more, then
+        //  * prefers more static segments to more
+        function sortSolutions(states) {
+            return states.sort(function(a, b) {
+                if (a.types.stars !== b.types.stars) {
+                    return a.types.stars - b.types.stars;
+                }
+
+                if (a.types.stars) {
+                    if (a.types.statics !== b.types.statics) {
+                        return b.types.statics - a.types.statics;
+                    }
+                    if (a.types.dynamics !== b.types.dynamics) {
+                        return b.types.dynamics - a.types.dynamics;
+                    }
+                }
+
+                if (a.types.dynamics !== b.types.dynamics) {
+                    return a.types.dynamics - b.types.dynamics;
+                }
+                if (a.types.statics !== b.types.statics) {
+                    return b.types.statics - a.types.statics;
+                }
+
+                return 0;
+            });
+        }
+
+        function recognizeChar(states, ch) {
+            var nextStates = [];
+
+            for (var i = 0, l = states.length; i &lt; l; i++) {
+                var state = states[i];
+
+                nextStates = nextStates.concat(state.match(ch));
+            }
+
+            return nextStates;
+        }
+
+        var oCreate = Object.create || function(proto) {
+            function F() {}
+            F.prototype = proto;
+            return new F();
+        };
+
+        function RecognizeResults(queryParams) {
+            this.queryParams = queryParams || {};
+        }
+        RecognizeResults.prototype = oCreate({
+            splice: Array.prototype.splice,
+            slice: Array.prototype.slice,
+            push: Array.prototype.push,
+            length: 0,
+            queryParams: null
+        });
+
+        function findHandler(state, path, queryParams) {
+            var handlers = state.handlers, regex = state.regex;
+            var captures = path.match(regex), currentCapture = 1;
+            var result = new RecognizeResults(queryParams);
+
+            for (var i = 0, l = handlers.length; i &lt; l; i++) {
+                var handler = handlers[i], names = handler.names, params = {};
+
+                for (var j = 0, m = names.length; j &lt; m; j++) {
+                    params[names[j]] = captures[currentCapture++];
+                }
+
+                result.push({
+                    handler: handler.handler,
+                    params: params,
+                    isDynamic: !!names.length 
+                });
+            }
+
+            return result;
+        }
+
+        function addSegment(currentState, segment) {
+            segment.eachChar(function(ch) {
+                var state;
+
+                currentState = currentState.put(ch);
+            });
+
+            return currentState;
+        }
+
+        // The main interface
+
+        var RouteRecognizer = function() {
+            this.rootState = new State();
+            this.names = {};
+        };
+
+
+        RouteRecognizer.prototype = {
+            add: function(routes, options) {
+                var currentState = this.rootState, regex = &quot;^&quot;,
+                types = {
+                    statics: 0,
+                    dynamics: 0,
+                    stars: 0 
+                },
+                handlers = [], allSegments = [], name;
+
+                var isEmpty = true;
+
+                for (var i = 0, l = routes.length; i &lt; l; i++) {
+                    var route = routes[i], names = [];
+
+                    var segments = parse(route.path, names, types);
+
+                    allSegments = allSegments.concat(segments);
+
+                    for (var j = 0, m = segments.length; j &lt; m; j++) {
+                        var segment = segments[j];
+
+                        if (segment instanceof EpsilonSegment) {
+                            continue;
+                        }
+
+                        isEmpty = false;
+
+                        // Add a &quot;/&quot; for the new segment
+                        currentState = currentState.put({
+                            validChars: &quot;/&quot; 
+                        });
+                        regex += &quot;/&quot;;
+
+                        // Add a representation of the segment to the NFA and regex
+                        currentState = addSegment(currentState, segment);
+                        regex += segment.regex();
+                    }
+
+                    var handler = {
+                        handler: route.handler,
+                        names: names 
+                    };
+                    handlers.push(handler);
+                }
+
+                if (isEmpty) {
+                    currentState = currentState.put({
+                        validChars: &quot;/&quot; 
+                    });
+                    regex += &quot;/&quot;;
+                }
+
+                currentState.handlers = handlers;
+                currentState.regex = new RegExp(regex + &quot;$&quot;);
+                currentState.types = types;
+
+                if (name = options &amp;&amp; options.as) {
+                    this.names[name] = {
+                        segments: allSegments,
+                        handlers: handlers
+                    };
+                }
+            },
+
+            handlersFor: function(name) {
+                var route = this.names[name], result = [];
+                if (!route) {
+                    throw new Error(&quot;There is no route named &quot; + name);
+                }
+
+                for (var i = 0, l = route.handlers.length; i &lt; l; i++) {
+                    result.push(route.handlers[i]);
+                }
+
+                return result;
+            },
+
+            hasRoute: function(name) {
+                return !!this.names[name];
+            },
+
+            generate: function(name, params) {
+                var route = this.names[name], output = &quot;&quot;;
+                if (!route) {
+                    throw new Error(&quot;There is no route named &quot; + name);
+                }
+
+                var segments = route.segments;
+
+                for (var i = 0, l = segments.length; i &lt; l; i++) {
+                    var segment = segments[i];
+
+                    if (segment instanceof EpsilonSegment) {
+                        continue;
+                    }
+
+                    output += &quot;/&quot;;
+                    output += segment.generate(params);
+                }
+
+                if (output.charAt(0) !== '/') {
+                    output = '/' + output;
+                }
+
+                if (params &amp;&amp; params.queryParams) {
+                    output += this.generateQueryString(params.queryParams, route.handlers);
+                }
+
+                return output;
+            },
+
+            generateQueryString: function(params, handlers) {
+                var pairs = [];
+                var keys = [];
+                for (var key in params) {
+                    if (params.hasOwnProperty(key)) {
+                        keys.push(key);
+                    }
+                }
+                keys.sort();
+                for (var i = 0, len = keys.length; i &lt; len; i++) {
+                    key = keys[i];
+                    var value = params[key];
+                    if (value == null) {
+                        continue;
+                    }
+                    var pair = key;
+                    if (isArray(value)) {
+                        for (var j = 0, l = value.length; j &lt; l; j++) {
+                            var arrayPair = key + '[]' + '=' + encodeURIComponent(value[j]);
+                            pairs.push(arrayPair);
+                        }
+                    } else {
+                        pair += &quot;=&quot; + encodeURIComponent(value);
+                        pairs.push(pair);
+                    }
+                }
+
+                if (pairs.length === 0) {
+                    return '';
+                }
+
+                return &quot;?&quot; + pairs.join(&quot;&amp;&quot;);
+            },
+
+            parseQueryString: function(queryString) {
+                var pairs = queryString.split(&quot;&amp;&quot;), queryParams = {};
+                for (var i = 0; i &lt; pairs.length; i++) {
+                    var pair = pairs[i].split('='),
+                    key = decodeURIComponent(pair[0]),
+                    keyLength = key.length,
+                    isArray = false,
+                    value;
+                    if (pair.length === 1) {
+                        value = 'true';
+                    } else {
+                        //Handle arrays
+                        if (keyLength &gt; 2 &amp;&amp; key.slice(keyLength -2) === '[]') {
+                            isArray = true;
+                            key = key.slice(0, keyLength - 2);
+                            if (!queryParams[key]) {
+                                queryParams[key] = [];
+                            }
+                        }
+                        value = pair[1] ? decodeURIComponent(pair[1]) : '';
+                    }
+                    if (isArray) {
+                        queryParams[key].push(value);
+                    } else {
+                        queryParams[key] = decodeURIComponent(value);
+                    }
+                }
+                return queryParams;
+            },
+
+            recognize: function(path) {
+                var states = [ this.rootState ],
+                pathLen, i, l, queryStart, queryParams = {},
+                isSlashDropped = false;
+
+                path = decodeURI(path);
+
+                queryStart = path.indexOf('?');
+                if (queryStart !== -1) {
+                    var queryString = path.substr(queryStart + 1, path.length);
+                    path = path.substr(0, queryStart);
+                    queryParams = this.parseQueryString(queryString);
+                }
+
+                // DEBUG GROUP path
+
+                if (path.charAt(0) !== &quot;/&quot;) {
+                    path = &quot;/&quot; + path;
+                }
+
+                pathLen = path.length;
+                if (pathLen &gt; 1 &amp;&amp; path.charAt(pathLen - 1) === &quot;/&quot;) {
+                    path = path.substr(0, pathLen - 1);
+                    isSlashDropped = true;
+                }
+
+                for (i = 0, l = path.length; i &lt; l; i++) {
+                    states = recognizeChar(states, path.charAt(i));
+                    if (!states.length) {
+                        break;
+                    }
+                }
+
+                // END DEBUG GROUP
+
+                var solutions = [];
+                for (i = 0, l = states.length; i &lt; l; i++) {
+                    if (states[i].handlers) {
+                        solutions.push(states[i]);
+                    }
+                }
+
+                states = sortSolutions(solutions);
+
+                var state = solutions[0];
+
+                if (state &amp;&amp; state.handlers) {
+                    // if a trailing slash was dropped and a star segment is the last segment
+                    // specified, put the trailing slash back
+                    if (isSlashDropped &amp;&amp; state.regex.source.slice(-5) === &quot;(.+)$&quot;) {
+                        path = path + &quot;/&quot;;
+                    }
+                    return findHandler(state, path, queryParams);
+                }
+            }
+        };
+
+        __exports__[&quot;default&quot;] = RouteRecognizer;
+
+        function Target(path, matcher, delegate) {
+            this.path = path;
+            this.matcher = matcher;
+            this.delegate = delegate;
+        }
+
+        Target.prototype = {
+            to: function(target, callback) {
+                var delegate = this.delegate;
+
+                if (delegate &amp;&amp; delegate.willAddRoute) {
+                    target = delegate.willAddRoute(this.matcher.target, target);
+                }
+
+                this.matcher.add(this.path, target);
+
+                if (callback) {
+                    if (callback.length === 0) {
+                        throw new Error(&quot;You must have an argument in the function passed to `to`&quot;);
+                    }
+                    this.matcher.addChild(this.path, target, callback, this.delegate);
+                }
+                return this;
+            }
+        };
+
+        function Matcher(target) {
+            this.routes = {};
+            this.children = {};
+            this.target = target;
+        }
+
+        Matcher.prototype = {
+            add: function(path, handler) {
+                this.routes[path] = handler;
+            },
+
+            addChild: function(path, target, callback, delegate) {
+                var matcher = new Matcher(target);
+                this.children[path] = matcher;
+
+                var match = generateMatch(path, matcher, delegate);
+
+                if (delegate &amp;&amp; delegate.contextEntered) {
+                    delegate.contextEntered(target, match);
+                }
+
+                callback(match);
+            }
+        };
+
+        function generateMatch(startingPath, matcher, delegate) {
+            return function(path, nestedCallback) {
+                var fullPath = startingPath + path;
+
+                if (nestedCallback) {
+                    nestedCallback(generateMatch(fullPath, matcher, delegate));
+                } else {
+                    return new Target(startingPath + path, matcher, delegate);
+                }
+            };
+        }
+
+        function addRoute(routeArray, path, handler) {
+            var len = 0;
+            for (var i = 0, l = routeArray.length; i &lt; l; i++) {
+                len += routeArray[i].path.length;
+            }
+
+            path = path.substr(len);
+            var route = {
+                path: path,
+                handler: handler 
+            };
+            routeArray.push(route);
+        }
+
+        function eachRoute(baseRoute, matcher, callback, binding) {
+            var routes = matcher.routes;
+
+            for (var path in routes) {
+                if (routes.hasOwnProperty(path)) {
+                    var routeArray = baseRoute.slice();
+                    addRoute(routeArray, path, routes[path]);
+
+                    if (matcher.children[path]) {
+                        eachRoute(routeArray, matcher.children[path], callback, binding);
+                    } else {
+                        callback.call(binding, routeArray);
+                    }
+                }
+            }
+        }
+
+        RouteRecognizer.prototype.map = function(callback, addRouteCallback) {
+            var matcher = new Matcher();
+
+            callback(generateMatch(&quot;&quot;, matcher, this.delegate));
+
+            eachRoute([], matcher, function(route) {
+                if (addRouteCallback) {
+                    addRouteCallback(this, route);
+                } else {
+                    this.add(route);
+                }
+            }, this);
+        };
+    });
+
+    define(&quot;router/handler-info&quot;,
+    [&quot;./utils&quot;, &quot;rsvp/promise&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var bind = __dependency1__.bind;
+        var merge = __dependency1__.merge;
+        var serialize = __dependency1__.serialize;
+        var promiseLabel = __dependency1__.promiseLabel;
+        var Promise = __dependency2__[&quot;default&quot;];
+
+        function HandlerInfo(_props) {
+            var props = _props || {};
+            merge(this, props);
+            this.initialize(props);
+        }
+
+        HandlerInfo.prototype = {
+            name: null,
+            handler: null,
+            params: null,
+            context: null,
+
+            // Injected by the handler info factory.
+            factory: null,
+
+            initialize: function() {},
+
+            log: function(payload, message) {
+                if (payload.log) {
+                    payload.log(this.name + ': ' + message);
+                }
+            },
+
+            promiseLabel: function(label) {
+                return promiseLabel(&quot;'&quot; + this.name + &quot;' &quot; + label);
+            },
+
+            getUnresolved: function() {
+                return this;
+            },
+
+            serialize: function() {
+                return this.params || {};
+            },
+
+            resolve: function(shouldContinue, payload) {
+                var checkForAbort = bind(this, this.checkForAbort, shouldContinue),
+                beforeModel = bind(this, this.runBeforeModelHook, payload),
+                model = bind(this, this.getModel, payload),
+                afterModel = bind(this, this.runAfterModelHook, payload),
+                becomeResolved = bind(this, this.becomeResolved, payload);
+
+                return Promise.resolve(undefined, this.promiseLabel(&quot;Start handler&quot;))
+                .then(checkForAbort, null, this.promiseLabel(&quot;Check for abort&quot;))
+                .then(beforeModel, null, this.promiseLabel(&quot;Before model&quot;))
+                .then(checkForAbort, null, this.promiseLabel(&quot;Check if aborted during 'beforeModel' hook&quot;))
+                .then(model, null, this.promiseLabel(&quot;Model&quot;))
+                .then(checkForAbort, null, this.promiseLabel(&quot;Check if aborted in 'model' hook&quot;))
+                .then(afterModel, null, this.promiseLabel(&quot;After model&quot;))
+                .then(checkForAbort, null, this.promiseLabel(&quot;Check if aborted in 'afterModel' hook&quot;))
+                .then(becomeResolved, null, this.promiseLabel(&quot;Become resolved&quot;));
+            },
+
+            runBeforeModelHook: function(payload) {
+                if (payload.trigger) {
+                    payload.trigger(true, 'willResolveModel', payload, this.handler);
+                }
+                return this.runSharedModelHook(payload, 'beforeModel', []);
+            },
+
+            runAfterModelHook: function(payload, resolvedModel) {
+                // Stash the resolved model on the payload.
+                // This makes it possible for users to swap out
+                // the resolved model in afterModel.
+                var name = this.name;
+                this.stashResolvedModel(payload, resolvedModel);
+
+                return this.runSharedModelHook(payload, 'afterModel', [resolvedModel])
+                .then(function() {
+                    // Ignore the fulfilled value returned from afterModel.
+                    // Return the value stashed in resolvedModels, which
+                    // might have been swapped out in afterModel.
+                    return payload.resolvedModels[name];
+                }, null, this.promiseLabel(&quot;Ignore fulfillment value and return model value&quot;));
+            },
+
+            runSharedModelHook: function(payload, hookName, args) {
+                this.log(payload, &quot;calling &quot; + hookName + &quot; hook&quot;);
+
+                if (this.queryParams) {
+                    args.push(this.queryParams);
+                }
+                args.push(payload);
+
+                var handler = this.handler;
+                var result = handler[hookName] &amp;&amp; handler[hookName].apply(handler, args);
+
+                if (result &amp;&amp; result.isTransition) {
+                    result = null;
+                }
+
+                return Promise.resolve(result, null, this.promiseLabel(&quot;Resolve value returned from one of the model hooks&quot;));
+            },
+
+            // overridden by subclasses
+            getModel: null,
+
+            checkForAbort: function(shouldContinue, promiseValue) {
+                return Promise.resolve(shouldContinue(), this.promiseLabel(&quot;Check for abort&quot;)).then(function() {
+                    // We don't care about shouldContinue's resolve value;
+                    // pass along the original value passed to this fn.
+                    return promiseValue;
+                }, null, this.promiseLabel(&quot;Ignore fulfillment value and continue&quot;));
+            },
+
+            stashResolvedModel: function(payload, resolvedModel) {
+                payload.resolvedModels = payload.resolvedModels || {};
+                payload.resolvedModels[this.name] = resolvedModel;
+            },
+
+            becomeResolved: function(payload, resolvedContext) {
+                var params = this.serialize(resolvedContext);
+
+                if (payload) {
+                    this.stashResolvedModel(payload, resolvedContext);
+                    payload.params = payload.params || {};
+                    payload.params[this.name] = params;
+                }
+
+                return this.factory('resolved', {
+                    context: resolvedContext,
+                    name: this.name,
+                    handler: this.handler,
+                    params: params
+                });
+            },
+
+            shouldSupercede: function(other) {
+                // Prefer this newer handlerInfo over `other` if:
+                // 1) The other one doesn't exist
+                // 2) The names don't match
+                // 3) This handler has a context that doesn't match
+                //    the other one (or the other one doesn't have one).
+                // 4) This handler has parameters that don't match the other.
+                if (!other) {
+                    return true;
+                }
+
+                var contextsMatch = (other.context === this.context);
+                return other.name !== this.name ||
+                (this.hasOwnProperty('context') &amp;&amp; !contextsMatch) ||
+                (this.hasOwnProperty('params') &amp;&amp; !paramsMatch(this.params, other.params));
+            }
+        };
+
+        function paramsMatch(a, b) {
+            if ((!a) ^ (!b)) {
+                // Only one is null.
+                return false;
+            }
+
+            if (!a) {
+                // Both must be null.
+                return true;
+            }
+
+            // Note: this assumes that both params have the same
+            // number of keys, but since we're comparing the
+            // same handlers, they should.
+            for (var k in a) {
+                if (a.hasOwnProperty(k) &amp;&amp; a[k] !== b[k]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        __exports__[&quot;default&quot;] = HandlerInfo;
+    });
+    define(&quot;router/handler-info/factory&quot;,
+    [&quot;router/handler-info/resolved-handler-info&quot;, &quot;router/handler-info/unresolved-handler-info-by-object&quot;, &quot;router/handler-info/unresolved-handler-info-by-param&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var ResolvedHandlerInfo = __dependency1__[&quot;default&quot;];
+        var UnresolvedHandlerInfoByObject = __dependency2__[&quot;default&quot;];
+        var UnresolvedHandlerInfoByParam = __dependency3__[&quot;default&quot;];
+
+        handlerInfoFactory.klasses = {
+            resolved: ResolvedHandlerInfo,
+            param: UnresolvedHandlerInfoByParam,
+            object: UnresolvedHandlerInfoByObject
+        };
+
+        function handlerInfoFactory(name, props) {
+            var Ctor = handlerInfoFactory.klasses[name],
+            handlerInfo = new Ctor(props || {});
+            handlerInfo.factory = handlerInfoFactory;
+            return handlerInfo;
+        }
+
+        __exports__[&quot;default&quot;] = handlerInfoFactory;
+    });
+    define(&quot;router/handler-info/resolved-handler-info&quot;,
+    [&quot;../handler-info&quot;, &quot;router/utils&quot;, &quot;rsvp/promise&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var HandlerInfo = __dependency1__[&quot;default&quot;];
+        var subclass = __dependency2__.subclass;
+        var promiseLabel = __dependency2__.promiseLabel;
+        var Promise = __dependency3__[&quot;default&quot;];
+
+        var ResolvedHandlerInfo = subclass(HandlerInfo, {
+            resolve: function(shouldContinue, payload) {
+                // A ResolvedHandlerInfo just resolved with itself.
+                if (payload &amp;&amp; payload.resolvedModels) {
+                    payload.resolvedModels[this.name] = this.context;
+                }
+                return Promise.resolve(this, this.promiseLabel(&quot;Resolve&quot;));
+            },
+
+            getUnresolved: function() {
+                return this.factory('param', {
+                    name: this.name,
+                    handler: this.handler,
+                    params: this.params
+                });
+            },
+
+            isResolved: true
+        });
+
+        __exports__[&quot;default&quot;] = ResolvedHandlerInfo;
+    });
+    define(&quot;router/handler-info/unresolved-handler-info-by-object&quot;,
+    [&quot;../handler-info&quot;, &quot;router/utils&quot;, &quot;rsvp/promise&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var HandlerInfo = __dependency1__[&quot;default&quot;];
+        var merge = __dependency2__.merge;
+        var subclass = __dependency2__.subclass;
+        var promiseLabel = __dependency2__.promiseLabel;
+        var isParam = __dependency2__.isParam;
+        var Promise = __dependency3__[&quot;default&quot;];
+
+        var UnresolvedHandlerInfoByObject = subclass(HandlerInfo, {
+            getModel: function(payload) {
+                this.log(payload, this.name + &quot;: resolving provided model&quot;);
+                return Promise.resolve(this.context);
+            },
+
+            initialize: function(props) {
+                this.names = props.names || [];
+                this.context = props.context;
+            },
+
+            /**
+                    @private
+
+                    Serializes a handler using its custom `serialize` method or
+                    by a default that looks up the expected property name from
+                    the dynamic segment.
+
+                    @param {Object} model the model to be serialized for this handler
+                  */
+            serialize: function(_model) {
+                var model = _model || this.context,
+                names = this.names,
+                handler = this.handler;
+
+                var object = {};
+                if (isParam(model)) {
+                    object[names[0]] = model;
+                    return object;
+                }
+
+                // Use custom serialize if it exists.
+                if (handler.serialize) {
+                    return handler.serialize(model, names);
+                }
+
+                if (names.length !== 1) {
+                    return;
+                }
+
+                var name = names[0];
+
+                if (/_id$/.test(name)) {
+                    object[name] = model.id;
+                } else {
+                    object[name] = model;
+                }
+                return object;
+            }
+        });
+
+        __exports__[&quot;default&quot;] = UnresolvedHandlerInfoByObject;
+    });
+    define(&quot;router/handler-info/unresolved-handler-info-by-param&quot;,
+    [&quot;../handler-info&quot;, &quot;router/utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __exports__) {
+        &quot;use strict&quot;;
+        var HandlerInfo = __dependency1__[&quot;default&quot;];
+        var merge = __dependency2__.merge;
+        var subclass = __dependency2__.subclass;
+        var promiseLabel = __dependency2__.promiseLabel;
+
+        // Generated by URL transitions and non-dynamic route segments in named Transitions.
+        var UnresolvedHandlerInfoByParam = subclass (HandlerInfo, {
+            initialize: function(props) {
+                this.params = props.params || {};
+            },
+
+            getModel: function(payload) {
+                var fullParams = this.params;
+                if (payload &amp;&amp; payload.queryParams) {
+                    fullParams = {};
+                    merge(fullParams, this.params);
+                    fullParams.queryParams = payload.queryParams;
+                }
+
+                var hookName = typeof this.handler.deserialize === 'function' ?
+                'deserialize' : 'model';
+
+                return this.runSharedModelHook(payload, hookName, [fullParams]);
+            }
+        });
+
+        __exports__[&quot;default&quot;] = UnresolvedHandlerInfoByParam;
+    });
+    define(&quot;router/router&quot;,
+    [&quot;route-recognizer&quot;, &quot;rsvp/promise&quot;, &quot;./utils&quot;, &quot;./transition-state&quot;, &quot;./transition&quot;, &quot;./transition-intent/named-transition-intent&quot;, &quot;./transition-intent/url-transition-intent&quot;, &quot;./handler-info&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
+        &quot;use strict&quot;;
+        var RouteRecognizer = __dependency1__[&quot;default&quot;];
+        var Promise = __dependency2__[&quot;default&quot;];
+        var trigger = __dependency3__.trigger;
+        var log = __dependency3__.log;
+        var slice = __dependency3__.slice;
+        var forEach = __dependency3__.forEach;
+        var merge = __dependency3__.merge;
+        var serialize = __dependency3__.serialize;
+        var extractQueryParams = __dependency3__.extractQueryParams;
+        var getChangelist = __dependency3__.getChangelist;
+        var promiseLabel = __dependency3__.promiseLabel;
+        var TransitionState = __dependency4__[&quot;default&quot;];
+        var logAbort = __dependency5__.logAbort;
+        var Transition = __dependency5__.Transition;
+        var TransitionAborted = __dependency5__.TransitionAborted;
+        var NamedTransitionIntent = __dependency6__[&quot;default&quot;];
+        var URLTransitionIntent = __dependency7__[&quot;default&quot;];
+        var ResolvedHandlerInfo = __dependency8__.ResolvedHandlerInfo;
+
+        var pop = Array.prototype.pop;
+
+        function Router() {
+            this.recognizer = new RouteRecognizer();
+            this.reset();
+        }
+
+        Router.prototype = {
+
+            /**
+                    The main entry point into the router. The API is essentially
+                    the same as the `map` method in `route-recognizer`.
+
+                    This method extracts the String handler at the last `.to()`
+                    call and uses it as the name of the whole route.
+
+                    @param {Function} callback
+                  */
+            map: function(callback) {
+                this.recognizer.delegate = this.delegate;
+
+                this.recognizer.map(callback, function(recognizer, routes) {
+                    for (var i = routes.length - 1, proceed = true; i &gt;= 0 &amp;&amp; proceed; --i) {
+                        var route = routes[i];
+                        recognizer.add(routes, {
+                            as: route.handler 
+                        });
+                        proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index';
+                    }
+                });
+            },
+
+            hasRoute: function(route) {
+                return this.recognizer.hasRoute(route);
+            },
+
+            queryParamsTransition: function(changelist, wasTransitioning, oldState, newState) {
+                var router = this;
+
+                fireQueryParamDidChange(this, newState, changelist);
+
+                if (!wasTransitioning &amp;&amp; this.activeTransition) {
+                    // One of the handlers in queryParamsDidChange
+                    // caused a transition. Just return that transition.
+                    return this.activeTransition;
+                } else {
+                    // Running queryParamsDidChange didn't change anything.
+                    // Just update query params and be on our way.
+
+                    // We have to return a noop transition that will
+                    // perform a URL update at the end. This gives
+                    // the user the ability to set the url update
+                    // method (default is replaceState).
+                    var newTransition = new Transition(this);
+                    newTransition.queryParamsOnly = true;
+
+                    oldState.queryParams = finalizeQueryParamChange(this, newState.handlerInfos, newState.queryParams, newTransition);
+
+                    newTransition.promise = newTransition.promise.then(function(result) {
+                        updateURL(newTransition, oldState, true);
+                        if (router.didTransition) {
+                            router.didTransition(router.currentHandlerInfos);
+                        }
+                        return result;
+                    }, null, promiseLabel(&quot;Transition complete&quot;));
+                    return newTransition;
+                }
+            },
+
+            // NOTE: this doesn't really belong here, but here
+            // it shall remain until our ES6 transpiler can
+            // handle cyclical deps.
+            transitionByIntent: function(intent, isIntermediate) {
+
+                var wasTransitioning = !!this.activeTransition;
+                var oldState = wasTransitioning ? this.activeTransition.state : this.state;
+                var newTransition;
+                var router = this;
+
+                try {
+                    var newState = intent.applyToState(oldState, this.recognizer, this.getHandler, isIntermediate);
+                    var queryParamChangelist = getChangelist(oldState.queryParams, newState.queryParams);
+
+                    if (handlerInfosEqual(newState.handlerInfos, oldState.handlerInfos)) {
+
+                        // This is a no-op transition. See if query params changed.
+                        if (queryParamChangelist) {
+                            newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState);
+                            if (newTransition) {
+                                return newTransition;
+                            }
+                        }
+
+                        // No-op. No need to create a new transition.
+                        return new Transition(this);
+                    }
+
+                    if (isIntermediate) {
+                        setupContexts(this, newState);
+                        return;
+                    }
+
+                    // Create a new transition to the destination route.
+                    newTransition = new Transition(this, intent, newState);
+
+                    // Abort and usurp any previously active transition.
+                    if (this.activeTransition) {
+                        this.activeTransition.abort();
+                    }
+                    this.activeTransition = newTransition;
+
+                    // Transition promises by default resolve with resolved state.
+                    // For our purposes, swap out the promise to resolve
+                    // after the transition has been finalized.
+                    newTransition.promise = newTransition.promise.then(function(result) {
+                        return finalizeTransition(newTransition, result.state);
+                    }, null, promiseLabel(&quot;Settle transition promise when transition is finalized&quot;));
+
+                    if (!wasTransitioning) {
+                        notifyExistingHandlers(this, newState, newTransition);
+                    }
+
+                    fireQueryParamDidChange(this, newState, queryParamChangelist);
+
+                    return newTransition;
+                } catch (e) {
+                    return new Transition(this, intent, null, e);
+                }
+            },
+
+            /**
+                    Clears the current and target route handlers and triggers exit
+                    on each of them starting at the leaf and traversing up through
+                    its ancestors.
+                  */
+            reset: function() {
+                if (this.state) {
+                    forEach(this.state.handlerInfos, function(handlerInfo) {
+                        var handler = handlerInfo.handler;
+                        if (handler.exit) {
+                            handler.exit();
+                        }
+                    });
+                }
+
+                this.state = new TransitionState();
+                this.currentHandlerInfos = null;
+            },
+
+            activeTransition: null,
+
+            /**
+                    var handler = handlerInfo.handler;
+                    The entry point for handling a change to the URL (usually
+                    via the back and forward button).
+
+                    Returns an Array of handlers and the parameters associated
+                    with those parameters.
+
+                    @param {String} url a URL to process
+
+                    @return {Array} an Array of `[handler, parameter]` tuples
+                  */
+            handleURL: function(url) {
+                // Perform a URL-based transition, but don't change
+                // the URL afterward, since it already happened.
+                var args = slice.call(arguments);
+                if (url.charAt(0) !== '/') {
+                    args[0] = '/' + url;
+                }
+
+                return doTransition(this, args).method(null);
+            },
+
+            /**
+                    Hook point for updating the URL.
+
+                    @param {String} url a URL to update to
+                  */
+            updateURL: function() {
+                throw new Error(&quot;updateURL is not implemented&quot;);
+            },
+
+            /**
+                    Hook point for replacing the current URL, i.e. with replaceState
+
+                    By default this behaves the same as `updateURL`
+
+                    @param {String} url a URL to update to
+                  */
+            replaceURL: function(url) {
+                this.updateURL(url);
+            },
+
+            /**
+                    Transition into the specified named route.
+
+                    If necessary, trigger the exit callback on any handlers
+                    that are no longer represented by the target route.
+
+                    @param {String} name the name of the route
+                  */
+            transitionTo: function(name) {
+                return doTransition(this, arguments);
+            },
+
+            intermediateTransitionTo: function(name) {
+                doTransition(this, arguments, true);
+            },
+
+            refresh: function(pivotHandler) {
+                var state = this.activeTransition ? this.activeTransition.state : this.state;
+                var handlerInfos = state.handlerInfos;
+                var params = {};
+                for (var i = 0, len = handlerInfos.length; i &lt; len; ++i) {
+                    var handlerInfo = handlerInfos[i];
+                    params[handlerInfo.name] = handlerInfo.params || {};
+                }
+
+                log(this, &quot;Starting a refresh transition&quot;);
+                var intent = new NamedTransitionIntent({
+                    name: handlerInfos[handlerInfos.length - 1].name,
+                    pivotHandler: pivotHandler || handlerInfos[0].handler,
+                    contexts: [],
+                    // TODO collect contexts...?
+                    queryParams: this._changedQueryParams || state.queryParams || {}
+                });
+
+                return this.transitionByIntent(intent, false);
+            },
+
+            /**
+                    Identical to `transitionTo` except that the current URL will be replaced
+                    if possible.
+
+                    This method is intended primarily for use with `replaceState`.
+
+                    @param {String} name the name of the route
+                  */
+            replaceWith: function(name) {
+                return doTransition(this, arguments).method('replace');
+            },
+
+            /**
+                    Take a named route and context objects and generate a
+                    URL.
+
+                    @param {String} name the name of the route to generate
+                      a URL for
+                    @param {...Object} objects a list of objects to serialize
+
+                    @return {String} a URL
+                  */
+            generate: function(handlerName) {
+
+                var partitionedArgs = extractQueryParams(slice.call(arguments, 1)),
+                suppliedParams = partitionedArgs[0],
+                queryParams = partitionedArgs[1];
+
+                // Construct a TransitionIntent with the provided params
+                // and apply it to the present state of the router.
+                var intent = new NamedTransitionIntent({
+                    name: handlerName,
+                    contexts: suppliedParams 
+                });
+                var state = intent.applyToState(this.state, this.recognizer, this.getHandler);
+                var params = {};
+
+                for (var i = 0, len = state.handlerInfos.length; i &lt; len; ++i) {
+                    var handlerInfo = state.handlerInfos[i];
+                    var handlerParams = handlerInfo.serialize();
+                    merge(params, handlerParams);
+                }
+                params.queryParams = queryParams;
+
+                return this.recognizer.generate(handlerName, params);
+            },
+
+            applyIntent: function(handlerName, contexts) {
+                var intent = new NamedTransitionIntent({
+                    name: handlerName,
+                    contexts: contexts
+                });
+
+                var state = this.activeTransition &amp;&amp; this.activeTransition.state || this.state;
+                return intent.applyToState(state, this.recognizer, this.getHandler);
+            },
+
+            isActiveIntent: function(handlerName, contexts, queryParams) {
+                var targetHandlerInfos = this.state.handlerInfos,
+                found = false, names, object, handlerInfo, handlerObj, i, len;
+
+                if (!targetHandlerInfos.length) {
+                    return false;
+                }
+
+                var targetHandler = targetHandlerInfos[targetHandlerInfos.length - 1].name;
+                var recogHandlers = this.recognizer.handlersFor(targetHandler);
+
+                var index = 0;
+                for (len = recogHandlers.length; index &lt; len; ++index) {
+                    handlerInfo = targetHandlerInfos[index];
+                    if (handlerInfo.name === handlerName) {
+                        break;
+                    }
+                }
+
+                if (index === recogHandlers.length) {
+                    // The provided route name isn't even in the route hierarchy.
+                    return false;
+                }
+
+                var state = new TransitionState();
+                state.handlerInfos = targetHandlerInfos.slice(0, index + 1);
+                recogHandlers = recogHandlers.slice(0, index + 1);
+
+                var intent = new NamedTransitionIntent({
+                    name: targetHandler,
+                    contexts: contexts
+                });
+
+                var newState = intent.applyToHandlers(state, recogHandlers, this.getHandler, targetHandler, true, true);
+
+                var handlersEqual = handlerInfosEqual(newState.handlerInfos, state.handlerInfos);
+                if (!queryParams || !handlersEqual) {
+                    return handlersEqual;
+                }
+
+                // Get a hash of QPs that will still be active on new route
+                var activeQPsOnNewHandler = {};
+                merge(activeQPsOnNewHandler, queryParams);
+
+                var activeQueryParams = this.state.queryParams;
+                for (var key in activeQueryParams) {
+                    if (activeQueryParams.hasOwnProperty(key) &amp;&amp;
+                    activeQPsOnNewHandler.hasOwnProperty(key)) {
+                        activeQPsOnNewHandler[key] = activeQueryParams[key];
+                    }
+                }
+
+                return handlersEqual &amp;&amp; !getChangelist(activeQPsOnNewHandler, queryParams);
+            },
+
+            isActive: function(handlerName) {
+                var partitionedArgs = extractQueryParams(slice.call(arguments, 1));
+                return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
+            },
+
+            trigger: function(name) {
+                var args = slice.call(arguments);
+                trigger(this, this.currentHandlerInfos, false, args);
+            },
+
+            /**
+                    Hook point for logging transition status updates.
+
+                    @param {String} message The message to log.
+                  */
+            log: null,
+
+            _willChangeContextEvent: 'willChangeContext',
+            _triggerWillChangeContext: function(handlerInfos, newTransition) {
+                trigger(this, handlerInfos, true, [this._willChangeContextEvent, newTransition]);
+            },
+
+            _triggerWillLeave: function(handlerInfos, newTransition, leavingChecker) {
+                trigger(this, handlerInfos, true, ['willLeave', newTransition, leavingChecker]);
+            }
+        };
+
+        /**
+              @private
+
+              Fires queryParamsDidChange event
+            */
+        function fireQueryParamDidChange(router, newState, queryParamChangelist) {
+            // If queryParams changed trigger event
+            if (queryParamChangelist) {
+
+                // This is a little hacky but we need some way of storing
+                // changed query params given that no activeTransition
+                // is guaranteed to have occurred.
+                router._changedQueryParams = queryParamChangelist.all;
+                trigger(router, newState.handlerInfos, true, ['queryParamsDidChange', queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]);
+                router._changedQueryParams = null;
+            }
+        }
+
+        /**
+              @private
+
+              Takes an Array of `HandlerInfo`s, figures out which ones are
+              exiting, entering, or changing contexts, and calls the
+              proper handler hooks.
+
+              For example, consider the following tree of handlers. Each handler is
+              followed by the URL segment it handles.
+
+              ```
+              |~index (&quot;/&quot;)
+              | |~posts (&quot;/posts&quot;)
+              | | |-showPost (&quot;/:id&quot;)
+              | | |-newPost (&quot;/new&quot;)
+              | | |-editPost (&quot;/edit&quot;)
+              | |~about (&quot;/about/:id&quot;)
+              ```
+
+              Consider the following transitions:
+
+              1. A URL transition to `/posts/1`.
+                 1. Triggers the `*model` callbacks on the
+                    `index`, `posts`, and `showPost` handlers
+                 2. Triggers the `enter` callback on the same
+                 3. Triggers the `setup` callback on the same
+              2. A direct transition to `newPost`
+                 1. Triggers the `exit` callback on `showPost`
+                 2. Triggers the `enter` callback on `newPost`
+                 3. Triggers the `setup` callback on `newPost`
+              3. A direct transition to `about` with a specified
+                 context object
+                 1. Triggers the `exit` callback on `newPost`
+                    and `posts`
+                 2. Triggers the `serialize` callback on `about`
+                 3. Triggers the `enter` callback on `about`
+                 4. Triggers the `setup` callback on `about`
+
+              @param {Router} transition
+              @param {TransitionState} newState
+            */
+        function setupContexts(router, newState, transition) {
+            var partition = partitionHandlers(router.state, newState);
+
+            forEach(partition.exited, function(handlerInfo) {
+                var handler = handlerInfo.handler;
+                delete handler.context;
+                if (handler.reset) {
+                    handler.reset(true, transition);
+                }
+                if (handler.exit) {
+                    handler.exit(transition);
+                }
+            });
+
+            var oldState = router.oldState = router.state;
+            router.state = newState;
+            var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice();
+
+            try {
+                forEach(partition.reset, function(handlerInfo) {
+                    var handler = handlerInfo.handler;
+                    if (handler.reset) {
+                        handler.reset(false, transition);
+                    }
+                });
+
+                forEach(partition.updatedContext, function(handlerInfo) {
+                    return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, false, transition);
+                });
+
+                forEach(partition.entered, function(handlerInfo) {
+                    return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, true, transition);
+                });
+            } catch (e) {
+                router.state = oldState;
+                router.currentHandlerInfos = oldState.handlerInfos;
+                throw e;
+            }
+
+            router.state.queryParams = finalizeQueryParamChange(router, currentHandlerInfos, newState.queryParams, transition);
+        }
+
+
+        /**
+              @private
+
+              Helper method used by setupContexts. Handles errors or redirects
+              that may happen in enter/setup.
+            */
+        function handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, enter, transition) {
+
+            var handler = handlerInfo.handler,
+            context = handlerInfo.context;
+
+            if (enter &amp;&amp; handler.enter) {
+                handler.enter(transition);
+            }
+            if (transition &amp;&amp; transition.isAborted) {
+                throw new TransitionAborted();
+            }
+
+            handler.context = context;
+            if (handler.contextDidChange) {
+                handler.contextDidChange();
+            }
+
+            if (handler.setup) {
+                handler.setup(context, transition);
+            }
+            if (transition &amp;&amp; transition.isAborted) {
+                throw new TransitionAborted();
+            }
+
+            currentHandlerInfos.push(handlerInfo);
+
+            return true;
+        }
+
+
+        /**
+              @private
+
+              This function is called when transitioning from one URL to
+              another to determine which handlers are no longer active,
+              which handlers are newly active, and which handlers remain
+              active but have their context changed.
+
+              Take a list of old handlers and new handlers and partition
+              them into four buckets:
+
+              * unchanged: the handler was active in both the old and
+                new URL, and its context remains the same
+              * updated context: the handler was active in both the
+                old and new URL, but its context changed. The handler's
+                `setup` method, if any, will be called with the new
+                context.
+              * exited: the handler was active in the old URL, but is
+                no longer active.
+              * entered: the handler was not active in the old URL, but
+                is now active.
+
+              The PartitionedHandlers structure has four fields:
+
+              * `updatedContext`: a list of `HandlerInfo` objects that
+                represent handlers that remain active but have a changed
+                context
+              * `entered`: a list of `HandlerInfo` objects that represent
+                handlers that are newly active
+              * `exited`: a list of `HandlerInfo` objects that are no
+                longer active.
+              * `unchanged`: a list of `HanderInfo` objects that remain active.
+
+              @param {Array[HandlerInfo]} oldHandlers a list of the handler
+                information for the previous URL (or `[]` if this is the
+                first handled transition)
+              @param {Array[HandlerInfo]} newHandlers a list of the handler
+                information for the new URL
+
+              @return {Partition}
+            */
+        function partitionHandlers(oldState, newState) {
+            var oldHandlers = oldState.handlerInfos;
+            var newHandlers = newState.handlerInfos;
+
+            var handlers = {
+                updatedContext: [],
+                exited: [],
+                entered: [],
+                unchanged: []
+            };
+
+            var handlerChanged, contextChanged, i, l;
+
+            for (i = 0, l = newHandlers.length; i &lt; l; i++) {
+                var oldHandler = oldHandlers[i], newHandler = newHandlers[i];
+
+                if (!oldHandler || oldHandler.handler !== newHandler.handler) {
+                    handlerChanged = true;
+                }
+
+                if (handlerChanged) {
+                    handlers.entered.push(newHandler);
+                    if (oldHandler) {
+                        handlers.exited.unshift(oldHandler);
+                    }
+                } else if (contextChanged || oldHandler.context !== newHandler.context) {
+                    contextChanged = true;
+                    handlers.updatedContext.push(newHandler);
+                } else {
+                    handlers.unchanged.push(oldHandler);
+                }
+            }
+
+            for (i = newHandlers.length, l = oldHandlers.length; i &lt; l; i++) {
+                handlers.exited.unshift(oldHandlers[i]);
+            }
+
+            handlers.reset = handlers.updatedContext.slice();
+            handlers.reset.reverse();
+
+            return handlers;
+        }
+
+        function updateURL(transition, state, inputUrl) {
+            var urlMethod = transition.urlMethod;
+
+            if (!urlMethod) {
+                return;
+            }
+
+            var router = transition.router,
+            handlerInfos = state.handlerInfos,
+            handlerName = handlerInfos[handlerInfos.length - 1].name,
+            params = {};
+
+            for (var i = handlerInfos.length - 1; i &gt;= 0; --i) {
+                var handlerInfo = handlerInfos[i];
+                merge(params, handlerInfo.params);
+                if (handlerInfo.handler.inaccessibleByURL) {
+                    urlMethod = null;
+                }
+            }
+
+            if (urlMethod) {
+                params.queryParams = transition._visibleQueryParams || state.queryParams;
+                var url = router.recognizer.generate(handlerName, params);
+
+                if (urlMethod === 'replace') {
+                    router.replaceURL(url);
+                } else {
+                    router.updateURL(url);
+                }
+            }
+        }
+
+        /**
+              @private
+
+              Updates the URL (if necessary) and calls `setupContexts`
+              to update the router's array of `currentHandlerInfos`.
+             */
+        function finalizeTransition(transition, newState) {
+
+            try {
+                log(transition.router, transition.sequence, &quot;Resolved all models on destination route; finalizing transition.&quot;);
+
+                var router = transition.router,
+                handlerInfos = newState.handlerInfos,
+                seq = transition.sequence;
+
+                // Run all the necessary enter/setup/exit hooks
+                setupContexts(router, newState, transition);
+
+                // Check if a redirect occurred in enter/setup
+                if (transition.isAborted) {
+                    // TODO: cleaner way? distinguish b/w targetHandlerInfos?
+                    router.state.handlerInfos = router.currentHandlerInfos;
+                    return Promise.reject(logAbort(transition));
+                }
+
+                updateURL(transition, newState, transition.intent.url);
+
+                transition.isActive = false;
+                router.activeTransition = null;
+
+                trigger(router, router.currentHandlerInfos, true, ['didTransition']);
+
+                if (router.didTransition) {
+                    router.didTransition(router.currentHandlerInfos);
+                }
+
+                log(router, transition.sequence, &quot;TRANSITION COMPLETE.&quot;);
+
+                // Resolve with the final handler.
+                return handlerInfos[handlerInfos.length - 1].handler;
+            } catch (e) {
+                if (!((e instanceof TransitionAborted))) {
+                    //var erroneousHandler = handlerInfos.pop();
+                    var infos = transition.state.handlerInfos;
+                    transition.trigger(true, 'error', e, transition, infos[infos.length-1].handler);
+                    transition.abort();
+                }
+
+                throw e;
+            }
+        }
+
+        /**
+              @private
+
+              Begins and returns a Transition based on the provided
+              arguments. Accepts arguments in the form of both URL
+              transitions and named transitions.
+
+              @param {Router} router
+              @param {Array[Object]} args arguments passed to transitionTo,
+                replaceWith, or handleURL
+            */
+        function doTransition(router, args, isIntermediate) {
+            // Normalize blank transitions to root URL transitions.
+            var name = args[0] || '/';
+
+            var lastArg = args[args.length-1];
+            var queryParams = {};
+            if (lastArg &amp;&amp; lastArg.hasOwnProperty('queryParams')) {
+                queryParams = pop.call(args).queryParams;
+            }
+
+            var intent;
+            if (args.length === 0) {
+
+                log(router, &quot;Updating query params&quot;);
+
+                // A query param update is really just a transition
+                // into the route you're already on.
+                var handlerInfos = router.state.handlerInfos;
+                intent = new NamedTransitionIntent({
+                    name: handlerInfos[handlerInfos.length - 1].name,
+                    contexts: [],
+                    queryParams: queryParams
+                });
+
+            } else if (name.charAt(0) === '/') {
+
+                log(router, &quot;Attempting URL transition to &quot; + name);
+                intent = new URLTransitionIntent({
+                    url: name 
+                });
+
+            } else {
+
+                log(router, &quot;Attempting transition to &quot; + name);
+                intent = new NamedTransitionIntent({
+                    name: args[0],
+                    contexts: slice.call(args, 1),
+                    queryParams: queryParams
+                });
+            }
+
+            return router.transitionByIntent(intent, isIntermediate);
+        }
+
+        function handlerInfosEqual(handlerInfos, otherHandlerInfos) {
+            if (handlerInfos.length !== otherHandlerInfos.length) {
+                return false;
+            }
+
+            for (var i = 0, len = handlerInfos.length; i &lt; len; ++i) {
+                if (handlerInfos[i] !== otherHandlerInfos[i]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        function finalizeQueryParamChange(router, resolvedHandlers, newQueryParams, transition) {
+            // We fire a finalizeQueryParamChange event which
+            // gives the new route hierarchy a chance to tell
+            // us which query params it's consuming and what
+            // their final values are. If a query param is
+            // no longer consumed in the final route hierarchy,
+            // its serialized segment will be removed
+            // from the URL.
+
+            for (var k in newQueryParams) {
+                if (newQueryParams.hasOwnProperty(k) &amp;&amp;
+                newQueryParams[k] === null) {
+                    delete newQueryParams[k];
+                }
+            }
+
+            var finalQueryParamsArray = [];
+            trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]);
+
+            if (transition) {
+                transition._visibleQueryParams = {};
+            }
+
+            var finalQueryParams = {};
+            for (var i = 0, len = finalQueryParamsArray.length; i &lt; len; ++i) {
+                var qp = finalQueryParamsArray[i];
+                finalQueryParams[qp.key] = qp.value;
+                if (transition &amp;&amp; qp.visible !== false) {
+                    transition._visibleQueryParams[qp.key] = qp.value;
+                }
+            }
+            return finalQueryParams;
+        }
+
+        function notifyExistingHandlers(router, newState, newTransition) {
+            var oldHandlers = router.state.handlerInfos,
+            changing = [],
+            leavingIndex = null,
+            leaving, leavingChecker, i, oldHandler, newHandler;
+
+            for (i = 0; i &lt; oldHandlers.length; i++) {
+                oldHandler = oldHandlers[i];
+                newHandler = newState.handlerInfos[i];
+
+                if (!newHandler || oldHandler.name !== newHandler.name) {
+                    leavingIndex = i;
+                    break;
+                }
+
+                if (!newHandler.isResolved) {
+                    changing.push(oldHandler);
+                }
+            }
+
+            if (leavingIndex !== null) {
+                leaving = oldHandlers.slice(leavingIndex, oldHandlers.length);
+                leavingChecker = function(name) {
+                    for (var h = 0; h &lt; leaving.length; h++) {
+                        if (leaving[h].name === name) {
+                            return true;
+                        }
+                    }
+                    return false;
+                };
+
+                router._triggerWillLeave(leaving, newTransition, leavingChecker);
+            }
+
+            if (changing.length &gt; 0) {
+                router._triggerWillChangeContext(changing, newTransition);
+            }
+
+            trigger(router, oldHandlers, true, ['willTransition', newTransition]);
+        }
+
+        __exports__[&quot;default&quot;] = Router;
+    });
+    define(&quot;router/transition-intent&quot;,
+    [&quot;./utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var merge = __dependency1__.merge;
+
+        function TransitionIntent(props) {
+            this.initialize(props);
+
+            // TODO: wat
+            this.data = this.data || {};
+        }
+
+        TransitionIntent.prototype = {
+            initialize: null,
+            applyToState: null
+        };
+
+        __exports__[&quot;default&quot;] = TransitionIntent;
+    });
+    define(&quot;router/transition-intent/named-transition-intent&quot;,
+    [&quot;../transition-intent&quot;, &quot;../transition-state&quot;, &quot;../handler-info/factory&quot;, &quot;../utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var TransitionIntent = __dependency1__[&quot;default&quot;];
+        var TransitionState = __dependency2__[&quot;default&quot;];
+        var handlerInfoFactory = __dependency3__[&quot;default&quot;];
+        var isParam = __dependency4__.isParam;
+        var extractQueryParams = __dependency4__.extractQueryParams;
+        var merge = __dependency4__.merge;
+        var subclass = __dependency4__.subclass;
+
+        __exports__[&quot;default&quot;] = subclass(TransitionIntent, {
+            name: null,
+            pivotHandler: null,
+            contexts: null,
+            queryParams: null,
+
+            initialize: function(props) {
+                this.name = props.name;
+                this.pivotHandler = props.pivotHandler;
+                this.contexts = props.contexts || [];
+                this.queryParams = props.queryParams;
+            },
+
+            applyToState: function(oldState, recognizer, getHandler, isIntermediate) {
+
+                var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)),
+                pureArgs = partitionedArgs[0],
+                queryParams = partitionedArgs[1],
+                handlers = recognizer.handlersFor(pureArgs[0]);
+
+                var targetRouteName = handlers[handlers.length-1].handler;
+
+                return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate);
+            },
+
+            applyToHandlers: function(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive) {
+
+                var i;
+                var newState = new TransitionState();
+                var objects = this.contexts.slice(0);
+
+                var invalidateIndex = handlers.length;
+
+                // Pivot handlers are provided for refresh transitions
+                if (this.pivotHandler) {
+                    for (i = 0; i &lt; handlers.length; ++i) {
+                        if (getHandler(handlers[i].handler) === this.pivotHandler) {
+                            invalidateIndex = i;
+                            break;
+                        }
+                    }
+                }
+
+                var pivotHandlerFound = !this.pivotHandler;
+
+                for (i = handlers.length - 1; i &gt;= 0; --i) {
+                    var result = handlers[i];
+                    var name = result.handler;
+                    var handler = getHandler(name);
+
+                    var oldHandlerInfo = oldState.handlerInfos[i];
+                    var newHandlerInfo = null;
+
+                    if (result.names.length &gt; 0) {
+                        if (i &gt;= invalidateIndex) {
+                            newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
+                        } else {
+                            newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, handler, result.names, objects, oldHandlerInfo, targetRouteName, i);
+                        }
+                    } else {
+                        // This route has no dynamic segment.
+                        // Therefore treat as a param-based handlerInfo
+                        // with empty params. This will cause the `model`
+                        // hook to be called with empty params, which is desirable.
+                        newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
+                    }
+
+                    if (checkingIfActive) {
+                        // If we're performing an isActive check, we want to
+                        // serialize URL params with the provided context, but
+                        // ignore mismatches between old and new context.
+                        newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context);
+                        var oldContext = oldHandlerInfo &amp;&amp; oldHandlerInfo.context;
+                        if (result.names.length &gt; 0 &amp;&amp; newHandlerInfo.context === oldContext) {
+                            // If contexts match in isActive test, assume params also match.
+                            // This allows for flexibility in not requiring that every last
+                            // handler provide a `serialize` method
+                            newHandlerInfo.params = oldHandlerInfo &amp;&amp; oldHandlerInfo.params;
+                        }
+                        newHandlerInfo.context = oldContext;
+                    }
+
+                    var handlerToUse = oldHandlerInfo;
+                    if (i &gt;= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
+                        invalidateIndex = Math.min(i, invalidateIndex);
+                        handlerToUse = newHandlerInfo;
+                    }
+
+                    if (isIntermediate &amp;&amp; !checkingIfActive) {
+                        handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context);
+                    }
+
+                    newState.handlerInfos.unshift(handlerToUse);
+                }
+
+                if (objects.length &gt; 0) {
+                    throw new Error(&quot;More context objects were passed than there are dynamic segments for the route: &quot; + targetRouteName);
+                }
+
+                if (!isIntermediate) {
+                    this.invalidateChildren(newState.handlerInfos, invalidateIndex);
+                }
+
+                merge(newState.queryParams, this.queryParams || {});
+
+                return newState;
+            },
+
+            invalidateChildren: function(handlerInfos, invalidateIndex) {
+                for (var i = invalidateIndex, l = handlerInfos.length; i &lt; l; ++i) {
+                    var handlerInfo = handlerInfos[i];
+                    handlerInfos[i] = handlerInfos[i].getUnresolved();
+                }
+            },
+
+            getHandlerInfoForDynamicSegment: function(name, handler, names, objects, oldHandlerInfo, targetRouteName, i) {
+
+                var numNames = names.length;
+                var objectToUse;
+                if (objects.length &gt; 0) {
+
+                    // Use the objects provided for this transition.
+                    objectToUse = objects[objects.length - 1];
+                    if (isParam(objectToUse)) {
+                        return this.createParamHandlerInfo(name, handler, names, objects, oldHandlerInfo);
+                    } else {
+                        objects.pop();
+                    }
+                } else if (oldHandlerInfo &amp;&amp; oldHandlerInfo.name === name) {
+                    // Reuse the matching oldHandlerInfo
+                    return oldHandlerInfo;
+                } else {
+                    if (this.preTransitionState) {
+                        var preTransitionHandlerInfo = this.preTransitionState.handlerInfos[i];
+                        objectToUse = preTransitionHandlerInfo &amp;&amp; preTransitionHandlerInfo.context;
+                    } else {
+                        // Ideally we should throw this error to provide maximal
+                        // information to the user that not enough context objects
+                        // were provided, but this proves too cumbersome in Ember
+                        // in cases where inner template helpers are evaluated
+                        // before parent helpers un-render, in which cases this
+                        // error somewhat prematurely fires.
+                        //throw new Error(&quot;Not enough context objects were provided to complete a transition to &quot; + targetRouteName + &quot;. Specifically, the &quot; + name + &quot; route needs an object that can be serialized into its dynamic URL segments [&quot; + names.join(', ') + &quot;]&quot;);
+                        return oldHandlerInfo;
+                    }
+                }
+
+                return handlerInfoFactory('object', {
+                    name: name,
+                    handler: handler,
+                    context: objectToUse,
+                    names: names
+                });
+            },
+
+            createParamHandlerInfo: function(name, handler, names, objects, oldHandlerInfo) {
+                var params = {};
+
+                // Soak up all the provided string/numbers
+                var numNames = names.length;
+                while (numNames--) {
+
+                    // Only use old params if the names match with the new handler
+                    var oldParams = (oldHandlerInfo &amp;&amp; name === oldHandlerInfo.name &amp;&amp; oldHandlerInfo.params) || {};
+
+                    var peek = objects[objects.length - 1];
+                    var paramName = names[numNames];
+                    if (isParam(peek)) {
+                        params[paramName] = &quot;&quot; + objects.pop();
+                    } else {
+                        // If we're here, this means only some of the params
+                        // were string/number params, so try and use a param
+                        // value from a previous handler.
+                        if (oldParams.hasOwnProperty(paramName)) {
+                            params[paramName] = oldParams[paramName];
+                        } else {
+                            throw new Error(&quot;You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route &quot; + name);
+                        }
+                    }
+                }
+
+                return handlerInfoFactory('param', {
+                    name: name,
+                    handler: handler,
+                    params: params
+                });
+            }
+        });
+    });
+    define(&quot;router/transition-intent/url-transition-intent&quot;,
+    [&quot;../transition-intent&quot;, &quot;../transition-state&quot;, &quot;../handler-info/factory&quot;, &quot;../utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        &quot;use strict&quot;;
+        var TransitionIntent = __dependency1__[&quot;default&quot;];
+        var TransitionState = __dependency2__[&quot;default&quot;];
+        var handlerInfoFactory = __dependency3__[&quot;default&quot;];
+        var oCreate = __dependency4__.oCreate;
+        var merge = __dependency4__.merge;
+        var subclass = __dependency4__.subclass;
+
+        __exports__[&quot;default&quot;] = subclass(TransitionIntent, {
+            url: null,
+
+            initialize: function(props) {
+                this.url = props.url;
+            },
+
+            applyToState: function(oldState, recognizer, getHandler) {
+                var newState = new TransitionState();
+
+                var results = recognizer.recognize(this.url),
+                queryParams = {},
+                i, len;
+
+                if (!results) {
+                    throw new UnrecognizedURLError(this.url);
+                }
+
+                var statesDiffer = false;
+
+                for (i = 0, len = results.length; i &lt; len; ++i) {
+                    var result = results[i];
+                    var name = result.handler;
+                    var handler = getHandler(name);
+
+                    if (handler.inaccessibleByURL) {
+                        throw new UnrecognizedURLError(this.url);
+                    }
+
+                    var newHandlerInfo = handlerInfoFactory('param', {
+                        name: name,
+                        handler: handler,
+                        params: result.params
+                    });
+
+                    var oldHandlerInfo = oldState.handlerInfos[i];
+                    if (statesDiffer || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
+                        statesDiffer = true;
+                        newState.handlerInfos[i] = newHandlerInfo;
+                    } else {
+                        newState.handlerInfos[i] = oldHandlerInfo;
+                    }
+                }
+
+                merge(newState.queryParams, results.queryParams);
+
+                return newState;
+            }
+        });
+
+        /**
+              Promise reject reasons passed to promise rejection
+              handlers for failed transitions.
+             */
+        function UnrecognizedURLError(message) {
+            this.message = (message || &quot;UnrecognizedURLError&quot;);
+            this.name = &quot;UnrecognizedURLError&quot;;
+        }
+    });
+    define(&quot;router/transition-state&quot;,
+    [&quot;./handler-info&quot;, &quot;./utils&quot;, &quot;rsvp/promise&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var ResolvedHandlerInfo = __dependency1__.ResolvedHandlerInfo;
+        var forEach = __dependency2__.forEach;
+        var promiseLabel = __dependency2__.promiseLabel;
+        var Promise = __dependency3__[&quot;default&quot;];
+
+        function TransitionState(other) {
+            this.handlerInfos = [];
+            this.queryParams = {};
+            this.params = {};
+        }
+
+        TransitionState.prototype = {
+            handlerInfos: null,
+            queryParams: null,
+            params: null,
+
+            promiseLabel: function(label) {
+                var targetName = '';
+                forEach(this.handlerInfos, function(handlerInfo) {
+                    if (targetName !== '') {
+                        targetName += '.';
+                    }
+                    targetName += handlerInfo.name;
+                });
+                return promiseLabel(&quot;'&quot; + targetName + &quot;': &quot; + label);
+            },
+
+            resolve: function(shouldContinue, payload) {
+                var self = this;
+                // First, calculate params for this state. This is useful
+                // information to provide to the various route hooks.
+                var params = this.params;
+                forEach(this.handlerInfos, function(handlerInfo) {
+                    params[handlerInfo.name] = handlerInfo.params || {};
+                });
+
+                payload = payload || {};
+                payload.resolveIndex = 0;
+
+                var currentState = this;
+                var wasAborted = false;
+
+                // The prelude RSVP.resolve() asyncs us into the promise land.
+                return Promise.resolve(null, this.promiseLabel(&quot;Start transition&quot;))
+                .then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error'));
+
+                function innerShouldContinue() {
+                    return Promise.resolve(shouldContinue(), promiseLabel(&quot;Check if should continue&quot;))['catch'](function(reason) {
+                        // We distinguish between errors that occurred
+                        // during resolution (e.g. beforeModel/model/afterModel),
+                        // and aborts due to a rejecting promise from shouldContinue().
+                        wasAborted = true;
+                        return Promise.reject(reason);
+                    }, promiseLabel(&quot;Handle abort&quot;));
+                }
+
+                function handleError(error) {
+                    // This is the only possible
+                    // reject value of TransitionState#resolve
+                    var handlerInfos = currentState.handlerInfos;
+                    var errorHandlerIndex = payload.resolveIndex &gt;= handlerInfos.length ?
+                    handlerInfos.length - 1 : payload.resolveIndex;
+                    return Promise.reject({
+                        error: error,
+                        handlerWithError: currentState.handlerInfos[errorHandlerIndex].handler,
+                        wasAborted: wasAborted,
+                        state: currentState
+                    });
+                }
+
+                function proceed(resolvedHandlerInfo) {
+                    var wasAlreadyResolved = currentState.handlerInfos[payload.resolveIndex].isResolved;
+
+                    // Swap the previously unresolved handlerInfo with
+                    // the resolved handlerInfo
+                    currentState.handlerInfos[payload.resolveIndex++] = resolvedHandlerInfo;
+
+                    if (!wasAlreadyResolved) {
+                        // Call the redirect hook. The reason we call it here
+                        // vs. afterModel is so that redirects into child
+                        // routes don't re-run the model hooks for this
+                        // already-resolved route.
+                        var handler = resolvedHandlerInfo.handler;
+                        if (handler &amp;&amp; handler.redirect) {
+                            handler.redirect(resolvedHandlerInfo.context, payload);
+                        }
+                    }
+
+                    // Proceed after ensuring that the redirect hook
+                    // didn't abort this transition by transitioning elsewhere.
+                    return innerShouldContinue().then(resolveOneHandlerInfo, null, promiseLabel('Resolve handler'));
+                }
+
+                function resolveOneHandlerInfo() {
+                    if (payload.resolveIndex === currentState.handlerInfos.length) {
+                        // This is is the only possible
+                        // fulfill value of TransitionState#resolve
+                        return {
+                            error: null,
+                            state: currentState
+                        };
+                    }
+
+                    var handlerInfo = currentState.handlerInfos[payload.resolveIndex];
+
+                    return handlerInfo.resolve(innerShouldContinue, payload)
+                    .then(proceed, null, promiseLabel('Proceed'));
+                }
+            }
+        };
+
+        __exports__[&quot;default&quot;] = TransitionState;
+    });
+    define(&quot;router/transition&quot;,
+    [&quot;rsvp/promise&quot;, &quot;./handler-info&quot;, &quot;./utils&quot;, &quot;exports&quot;],
+    function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        &quot;use strict&quot;;
+        var Promise = __dependency1__[&quot;default&quot;];
+        var ResolvedHandlerInfo = __dependency2__.ResolvedHandlerInfo;
+        var trigger = __dependency3__.trigger;
+        var slice = __dependency3__.slice;
+        var log = __dependency3__.log;
+        var promiseLabel = __dependency3__.promiseLabel;
+
+        /**
+              @private
+
+              A Transition is a thennable (a promise-like object) that represents
+              an attempt to transition to another route. It can be aborted, either
+              explicitly via `abort` or by attempting another transition while a
+              previous one is still underway. An aborted transition can also
+              be `retry()`d later.
+             */
+        function Transition(router, intent, state, error) {
+            var transition = this;
+            this.state = state || router.state;
+            this.intent = intent;
+            this.router = router;
+            this.data = this.intent &amp;&amp; this.intent.data || {};
+            this.resolvedModels = {};
+            this.queryParams = {};
+
+            if (error) {
+                this.promise = Promise.reject(error);
+                return;
+            }
+
+            if (state) {
+                this.params = state.params;
+                this.queryParams = state.queryParams;
+                this.handlerInfos = state.handlerInfos;
+
+                var len = state.handlerInfos.length;
+                if (len) {
+                    this.targetName = state.handlerInfos[state.handlerInfos.length-1].name;
+                }
+
+                for (var i = 0; i &lt; len; ++i) {
+                    var handlerInfo = state.handlerInfos[i];
+
+                    // TODO: this all seems hacky
+                    if (!handlerInfo.isResolved) {
+                        break;
+                    }
+                    this.pivotHandler = handlerInfo.handler;
+                }
+
+                this.sequence = Transition.currentSequence++;
+                this.promise = state.resolve(checkForAbort, this)['catch'](function(result) {
+                    if (result.wasAborted || transition.isAborted) {
+                        return Promise.reject(logAbort(transition));
+                    } else {
+                        transition.trigger('error', result.error, transition, result.handlerWithError);
+                        transition.abort();
+                        return Promise.reject(result.error);
+                    }
+                }, promiseLabel('Handle Abort'));
+            } else {
+                this.promise = Promise.resolve(this.state);
+                this.params = {};
+            }
+
+            function checkForAbort() {
+                if (transition.isAborted) {
+                    return Promise.reject(undefined, promiseLabel(&quot;Transition aborted - reject&quot;));
+                }
+            }
+        }
+
+        Transition.currentSequence = 0;
+
+        Transition.prototype = {
+            targetName: null,
+            urlMethod: 'update',
+            intent: null,
+            params: null,
+            pivotHandler: null,
+            resolveIndex: 0,
+            handlerInfos: null,
+            resolvedModels: null,
+            isActive: true,
+            state: null,
+            queryParamsOnly: false,
+
+            isTransition: true,
+
+            isExiting: function(handler) {
+                var handlerInfos = this.handlerInfos;
+                for (var i = 0, len = handlerInfos.length; i &lt; len; ++i) {
+                    var handlerInfo = handlerInfos[i];
+                    if (handlerInfo.name === handler || handlerInfo.handler === handler) {
+                        return false;
+                    }
+                }
+                return true;
+            },
+
+            /**
+                    @public
+
+                    The Transition's internal promise. Calling `.then` on this property
+                    is that same as calling `.then` on the Transition object itself, but
+                    this property is exposed for when you want to pass around a
+                    Transition's promise, but not the Transition object itself, since
+                    Transition object can be externally `abort`ed, while the promise
+                    cannot.
+                   */
+            promise: null,
+
+            /**
+                    @public
+
+                    Custom state can be stored on a Transition's `data` object.
+                    This can be useful for decorating a Transition within an earlier
+                    hook and shared with a later hook. Properties set on `data` will
+                    be copied to new transitions generated by calling `retry` on this
+                    transition.
+                   */
+            data: null,
+
+            /**
+                    @public
+
+                    A standard promise hook that resolves if the transition
+                    succeeds and rejects if it fails/redirects/aborts.
+
+                    Forwards to the internal `promise` property which you can
+                    use in situations where you want to pass around a thennable,
+                    but not the Transition itself.
+
+                    @param {Function} success
+                    @param {Function} failure
+                   */
+            then: function(success, failure) {
+                return this.promise.then(success, failure);
+            },
+
+            /**
+                    @public
+
+                    Aborts the Transition. Note you can also implicitly abort a transition
+                    by initiating another transition while a previous one is underway.
+                   */
+            abort: function() {
+                if (this.isAborted) {
+                    return this;
+                }
+                log(this.router, this.sequence, this.targetName + &quot;: transition was aborted&quot;);
+                this.intent.preTransitionState = this.router.state;
+                this.isAborted = true;
+                this.isActive = false;
+                this.router.activeTransition = null;
+                return this;
+            },
+
+            /**
+                    @public
+
+                    Retries a previously-aborted transition (making sure to abort the
+                    transition if it's still active). Returns a new transition that
+                    represents the new attempt to transition.
+                   */
+            retry: function() {
+                // TODO: add tests for merged state retry()s
+                this.abort();
+                return this.router.transitionByIntent(this.intent, false);
+            },
+
+            /**
+                    @public
+
+                    Sets the URL-changing method to be employed at the end of a
+                    successful transition. By default, a new Transition will just
+                    use `updateURL`, but passing 'replace' to this method will
+                    cause the URL to update using 'replaceWith' instead. Omitting
+                    a parameter will disable the URL change, allowing for transitions
+                    that don't update the URL at completion (this is also used for
+                    handleURL, since the URL has already changed before the
+                    transition took place).
+
+                    @param {String} method the type of URL-changing method to use
+                      at the end of a transition. Accepted values are 'replace',
+                      falsy values, or any other non-falsy value (which is
+                      interpreted as an updateURL transition).
+
+                    @return {Transition} this transition
+                   */
+            method: function(method) {
+                this.urlMethod = method;
+                return this;
+            },
+
+            /**
+                    @public
+
+                    Fires an event on the current list of resolved/resolving
+                    handlers within this transition. Useful for firing events
+                    on route hierarchies that haven't fully been entered yet.
+
+                    Note: This method is also aliased as `send`
+
+                    @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error
+                    @param {String} name the name of the event to fire
+                   */
+            trigger: function (ignoreFailure) {
+                var args = slice.call(arguments);
+                if (typeof ignoreFailure === 'boolean') {
+                    args.shift();
+                } else {
+                    // Throw errors on unhandled trigger events by default
+                    ignoreFailure = false;
+                }
+                trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
+            },
+
+            /**
+                    @public
+
+                    Transitions are aborted and their promises rejected
+                    when redirects occur; this method returns a promise
+                    that will follow any redirects that occur and fulfill
+                    with the value fulfilled by any redirecting transitions
+                    that occur.
+
+                    @return {Promise} a promise that fulfills with the same
+                      value that the final redirecting transition fulfills with
+                   */
+            followRedirects: function() {
+                var router = this.router;
+                return this.promise['catch'](function(reason) {
+                    if (router.activeTransition) {
+                        return router.activeTransition.followRedirects();
+                    }
+                    return Promise.reject(reason);
+                });
+            },
+
+            toString: function() {
+                return &quot;Transition (sequence &quot; + this.sequence + &quot;)&quot;;
+            },
+
+            /**
+                    @private
+                   */
+            log: function(message) {
+                log(this.router, this.sequence, message);
+            }
+        };
+
+        // Alias 'trigger' as 'send'
+        Transition.prototype.send = Transition.prototype.trigger;
+
+        /**
+              @private
+
+              Logs and returns a TransitionAborted error.
+             */
+        function logAbort(transition) {
+            log(transition.router, transition.sequence, &quot;detected abort.&quot;);
+            return new TransitionAborted();
+        }
+
+        function TransitionAborted(message) {
+            this.message = (message || &quot;TransitionAborted&quot;);
+            this.name = &quot;TransitionAborted&quot;;
+        }
+
+        __exports__.Transition = Transition;
+        __exports__.logAbort = logAbort;
+        __exports__.TransitionAborted = TransitionAborted;
+    });
+    define(&quot;router/utils&quot;,
+    [&quot;exports&quot;],
+    function(__exports__) {
+        &quot;use strict&quot;;
+        var slice = Array.prototype.slice;
+
+        var _isArray;
+        if (!Array.isArray) {
+            _isArray = function (x) {
+                return Object.prototype.toString.call(x) === &quot;[object Array]&quot;;
+            };
+        } else {
+            _isArray = Array.isArray;
+        }
+
+        var isArray = _isArray;
+        __exports__.isArray = isArray;
+        function merge(hash, other) {
+            for (var prop in other) {
+                if (other.hasOwnProperty(prop)) {
+                    hash[prop] = other[prop];
+                }
+            }
+        }
+
+        var oCreate = Object.create || function(proto) {
+            function F() {}
+            F.prototype = proto;
+            return new F();
+        };
+        __exports__.oCreate = oCreate;
+        /**
+              @private
+
+              Extracts query params from the end of an array
+            **/
+        function extractQueryParams(array) {
+            var len = (array &amp;&amp; array.length), head, queryParams;
+
+            if (len &amp;&amp; len &gt; 0 &amp;&amp; array[len - 1] &amp;&amp; array[len - 1].hasOwnProperty('queryParams')) {
+                queryParams = array[len - 1].queryParams;
+                head = slice.call(array, 0, len - 1);
+                return [head, queryParams];
+            } else {
+                return [array, null];
+            }
+        }
+
+        __exports__.extractQueryParams = extractQueryParams; /**
+              @private
+
+              Coerces query param properties and array elements into strings.
+            **/
+        function coerceQueryParamsToString(queryParams) {
+            for (var key in queryParams) {
+                if (typeof queryParams[key] === 'number') {
+                    queryParams[key] = '' + queryParams[key];
+                } else if (isArray(queryParams[key])) {
+                    for (var i = 0, l = queryParams[key].length; i &lt; l; i++) {
+                        queryParams[key][i] = '' + queryParams[key][i];
+                    }
+                }
+            }
+        }
+        /**
+              @private
+             */
+        function log(router, sequence, msg) {
+            if (!router.log) {
+                return;
+            }
+
+            if (arguments.length === 3) {
+                router.log(&quot;Transition #&quot; + sequence + &quot;: &quot; + msg);
+            } else {
+                msg = sequence;
+                router.log(msg);
+            }
+        }
+
+        __exports__.log = log;
+        function bind(context, fn) {
+            var boundArgs = arguments;
+            return function(value) {
+                var args = slice.call(boundArgs, 2);
+                args.push(value);
+                return fn.apply(context, args);
+            };
+        }
+
+        __exports__.bind = bind;
+        function isParam(object) {
+            return (typeof object === &quot;string&quot; || object instanceof String || typeof object === &quot;number&quot; || object instanceof Number);
+        }
+
+
+        function forEach(array, callback) {
+            for (var i = 0, l = array.length; i &lt; l &amp;&amp; false !== callback(array[i]); i++) {}
+        }
+
+        __exports__.forEach = forEach;
+        function trigger(router, handlerInfos, ignoreFailure, args) {
+            if (router.triggerEvent) {
+                router.triggerEvent(handlerInfos, ignoreFailure, args);
+                return;
+            }
+
+            var name = args.shift();
+
+            if (!handlerInfos) {
+                if (ignoreFailure) {
+                    return;
+                }
+                throw new Error(&quot;Could not trigger event '&quot; + name + &quot;'. There are no active handlers&quot;);
+            }
+
+            var eventWasHandled = false;
+
+            for (var i = handlerInfos.length-1; i &gt;= 0; i--) {
+                var handlerInfo = handlerInfos[i],
+                handler = handlerInfo.handler;
+
+                if (handler.events &amp;&amp; handler.events[name]) {
+                    if (handler.events[name].apply(handler, args) === true) {
+                        eventWasHandled = true;
+                    } else {
+                        return;
+                    }
+                }
+            }
+
+            if (!eventWasHandled &amp;&amp; !ignoreFailure) {
+                throw new Error(&quot;Nothing handled the event '&quot; + name + &quot;'.&quot;);
+            }
+        }
+
+        __exports__.trigger = trigger;
+        function getChangelist(oldObject, newObject) {
+            var key;
+            var results = {
+                all: {},
+                changed: {},
+                removed: {}
+            };
+
+            merge(results.all, newObject);
+
+            var didChange = false;
+            coerceQueryParamsToString(oldObject);
+            coerceQueryParamsToString(newObject);
+
+            // Calculate removals
+            for (key in oldObject) {
+                if (oldObject.hasOwnProperty(key)) {
+                    if (!newObject.hasOwnProperty(key)) {
+                        didChange = true;
+                        results.removed[key] = oldObject[key];
+                    }
+                }
+            }
+
+            // Calculate changes
+            for (key in newObject) {
+                if (newObject.hasOwnProperty(key)) {
+                    if (isArray(oldObject[key]) &amp;&amp; isArray(newObject[key])) {
+                        if (oldObject[key].length !== newObject[key].length) {
+                            results.changed[key] = newObject[key];
+                            didChange = true;
+                        } else {
+                            for (var i = 0, l = oldObject[key].length; i &lt; l; i++) {
+                                if (oldObject[key][i] !== newObject[key][i]) {
+                                    results.changed[key] = newObject[key];
+                                    didChange = true;
+                                }
+                            }
+                        }
+                    } else {
+                        if (oldObject[key] !== newObject[key]) {
+                            results.changed[key] = newObject[key];
+                            didChange = true;
+                        }
+                    }
+                }
+            }
+
+            return didChange &amp;&amp; results;
+        }
+
+        __exports__.getChangelist = getChangelist;
+        function promiseLabel(label) {
+            return 'Router: ' + label;
+        }
+
+        __exports__.promiseLabel = promiseLabel;
+        function subclass(parentConstructor, proto) {
+            function C(props) {
+                parentConstructor.call(this, props || {});
+            }
+            C.prototype = oCreate(parentConstructor.prototype);
+            merge(C.prototype, proto);
+            return C;
+        }
+
+        __exports__.subclass = subclass;
+        __exports__.merge = merge;
+        __exports__.slice = slice;
+        __exports__.isParam = isParam;
+        __exports__.coerceQueryParamsToString = coerceQueryParamsToString;
+    });
+    define(&quot;router&quot;,
+    [&quot;./router/router&quot;, &quot;exports&quot;],
+    function(__dependency1__, __exports__) {
+        &quot;use strict&quot;;
+        var Router = __dependency1__[&quot;default&quot;];
+
+        __exports__[&quot;default&quot;] = Router;
+    });
+    /**
+      @class RSVP
+      @module RSVP
+      */
+    define('rsvp/-internal', [
+    './utils',
+    './instrument',
+    './config',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        'use strict';
+        var objectOrFunction = __dependency1__.objectOrFunction;
+        var isFunction = __dependency1__.isFunction;
+        var now = __dependency1__.now;
+        var instrument = __dependency2__['default'];
+        var config = __dependency3__.config;
+        function noop() {}
+        var PENDING = void 0;
+        var FULFILLED = 1;
+        var REJECTED = 2;
+        var GET_THEN_ERROR = new ErrorObject();
+        function getThen(promise) {
+            try {
+                return promise.then;
+            } catch (error) {
+                GET_THEN_ERROR.error = error;
+                return GET_THEN_ERROR;
+            }
+        }
+        function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
+            try {
+                then.call(value, fulfillmentHandler, rejectionHandler);
+            } catch (e) {
+                return e;
+            }
+        }
+        function handleForeignThenable(promise, thenable, then) {
+            config.async(function (promise$2) {
+                var sealed = false;
+                var error = tryThen(then, thenable, function (value) {
+                    if (sealed) {
+                        return;
+                    }
+                    sealed = true;
+                    if (thenable !== value) {
+                        resolve(promise$2, value);
+                    } else {
+                        fulfill(promise$2, value);
+                    }
+                }, function (reason) {
+                    if (sealed) {
+                        return;
+                    }
+                    sealed = true;
+                    reject(promise$2, reason);
+                }, 'Settle: ' + (promise$2._label || ' unknown promise'));
+                if (!sealed &amp;&amp; error) {
+                    sealed = true;
+                    reject(promise$2, error);
+                }
+            }, promise);
+        }
+        function handleOwnThenable(promise, thenable) {
+            promise._onerror = null;
+            if (thenable._state === FULFILLED) {
+                fulfill(promise, thenable._result);
+            } else if (promise._state === REJECTED) {
+                reject(promise, thenable._result);
+            } else {
+                subscribe(thenable, undefined, function (value) {
+                    if (thenable !== value) {
+                        resolve(promise, value);
+                    } else {
+                        fulfill(promise, value);
+                    }
+                }, function (reason) {
+                    reject(promise, reason);
+                });
+            }
+        }
+        function handleMaybeThenable(promise, maybeThenable) {
+            if (maybeThenable instanceof promise.constructor) {
+                handleOwnThenable(promise, maybeThenable);
+            } else {
+                var then = getThen(maybeThenable);
+                if (then === GET_THEN_ERROR) {
+                    reject(promise, GET_THEN_ERROR.error);
+                } else if (then === undefined) {
+                    fulfill(promise, maybeThenable);
+                } else if (isFunction(then)) {
+                    handleForeignThenable(promise, maybeThenable, then);
+                } else {
+                    fulfill(promise, maybeThenable);
+                }
+            }
+        }
+        function resolve(promise, value) {
+            if (promise === value) {
+                fulfill(promise, value);
+            } else if (objectOrFunction(value)) {
+                handleMaybeThenable(promise, value);
+            } else {
+                fulfill(promise, value);
+            }
+        }
+        function publishRejection(promise) {
+            if (promise._onerror) {
+                promise._onerror(promise._result);
+            }
+            publish(promise);
+        }
+        function fulfill(promise, value) {
+            if (promise._state !== PENDING) {
+                return;
+            }
+            promise._result = value;
+            promise._state = FULFILLED;
+            if (promise._subscribers.length === 0) {
+                if (config.instrument) {
+                    instrument('fulfilled', promise);
+                }
+            } else {
+                config.async(publish, promise);
+            }
+        }
+        function reject(promise, reason) {
+            if (promise._state !== PENDING) {
+                return;
+            }
+            promise._state = REJECTED;
+            promise._result = reason;
+            config.async(publishRejection, promise);
+        }
+        function subscribe(parent, child, onFulfillment, onRejection) {
+            var subscribers = parent._subscribers;
+            var length = subscribers.length;
+            parent._onerror = null;
+            subscribers[length] = child;
+            subscribers[length + FULFILLED] = onFulfillment;
+            subscribers[length + REJECTED] = onRejection;
+            if (length === 0 &amp;&amp; parent._state) {
+                config.async(publish, parent);
+            }
+        }
+        function publish(promise) {
+            var subscribers = promise._subscribers;
+            var settled = promise._state;
+            if (config.instrument) {
+                instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);
+            }
+            if (subscribers.length === 0) {
+                return;
+            }
+            var child, callback, detail = promise._result;
+            for (var i = 0; i &lt; subscribers.length; i += 3) {
+                child = subscribers[i];
+                callback = subscribers[i + settled];
+                if (child) {
+                    invokeCallback(settled, child, callback, detail);
+                } else {
+                    callback(detail);
+                }
+            }
+            promise._subscribers.length = 0;
+        }
+        function ErrorObject() {
+            this.error = null;
+        }
+        var TRY_CATCH_ERROR = new ErrorObject();
+        function tryCatch(callback, detail) {
+            try {
+                return callback(detail);
+            } catch (e) {
+                TRY_CATCH_ERROR.error = e;
+                return TRY_CATCH_ERROR;
+            }
+        }
+        function invokeCallback(settled, promise, callback, detail) {
+            var hasCallback = isFunction(callback), value, error, succeeded, failed;
+            if (hasCallback) {
+                value = tryCatch(callback, detail);
+                if (value === TRY_CATCH_ERROR) {
+                    failed = true;
+                    error = value.error;
+                    value = null;
+                } else {
+                    succeeded = true;
+                }
+                if (promise === value) {
+                    reject(promise, new TypeError('A promises callback cannot return that same promise.'));
+                    return;
+                }
+            } else {
+                value = detail;
+                succeeded = true;
+            }
+            if (promise._state !== PENDING) {}
+            // noop
+            else if (hasCallback &amp;&amp; succeeded) {
+                resolve(promise, value);
+            } else if (failed) {
+                reject(promise, error);
+            } else if (settled === FULFILLED) {
+                fulfill(promise, value);
+            } else if (settled === REJECTED) {
+                reject(promise, value);
+            }
+        }
+        function initializePromise(promise, resolver) {
+            try {
+                resolver(function resolvePromise(value) {
+                    resolve(promise, value);
+                }, function rejectPromise(reason) {
+                    reject(promise, reason);
+                });
+            } catch (e) {
+                reject(promise, e);
+            }
+        }
+        __exports__.noop = noop;
+        __exports__.resolve = resolve;
+        __exports__.reject = reject;
+        __exports__.fulfill = fulfill;
+        __exports__.subscribe = subscribe;
+        __exports__.publish = publish;
+        __exports__.publishRejection = publishRejection;
+        __exports__.initializePromise = initializePromise;
+        __exports__.invokeCallback = invokeCallback;
+        __exports__.FULFILLED = FULFILLED;
+        __exports__.REJECTED = REJECTED;
+    });
+    define('rsvp/all-settled', [
+    './enumerator',
+    './promise',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        'use strict';
+        var Enumerator = __dependency1__['default'];
+        var makeSettledResult = __dependency1__.makeSettledResult;
+        var Promise = __dependency2__['default'];
+        var o_create = __dependency3__.o_create;
+        function AllSettled(Constructor, entries, label) {
+            this._superConstructor(Constructor, entries, false, label);
+        }
+        AllSettled.prototype = o_create(Enumerator.prototype);
+        AllSettled.prototype._superConstructor = Enumerator;
+        AllSettled.prototype._makeResult = makeSettledResult;
+        AllSettled.prototype._validationError = function () {
+            return new Error('allSettled must be called with an array');
+        };
+        /**
+              `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing
+              a fail-fast method, it waits until all the promises have returned and
+              shows you all the results. This is useful if you want to handle multiple
+              promises' failure states together as a set.
+
+              Returns a promise that is fulfilled when all the given promises have been
+              settled. The return promise is fulfilled with an array of the states of
+              the promises passed into the `promises` array argument.
+
+              Each state object will either indicate fulfillment or rejection, and
+              provide the corresponding value or reason. The states will take one of
+              the following formats:
+
+              ```javascript
+              { state: 'fulfilled', value: value }
+                or
+              { state: 'rejected', reason: reason }
+              ```
+
+              Example:
+
+              ```javascript
+              var promise1 = RSVP.Promise.resolve(1);
+              var promise2 = RSVP.Promise.reject(new Error('2'));
+              var promise3 = RSVP.Promise.reject(new Error('3'));
+              var promises = [ promise1, promise2, promise3 ];
+
+              RSVP.allSettled(promises).then(function(array){
+                // array == [
+                //   { state: 'fulfilled', value: 1 },
+                //   { state: 'rejected', reason: Error },
+                //   { state: 'rejected', reason: Error }
+                // ]
+                // Note that for the second item, reason.message will be &quot;2&quot;, and for the
+                // third item, reason.message will be &quot;3&quot;.
+              }, function(error) {
+                // Not run. (This block would only be called if allSettled had failed,
+                // for instance if passed an incorrect argument type.)
+              });
+              ```
+
+              @method allSettled
+              @static
+              @for RSVP
+              @param {Array} promises
+              @param {String} label - optional string that describes the promise.
+              Useful for tooling.
+              @return {Promise} promise that is fulfilled with an array of the settled
+              states of the constituent promises.
+            */
+        __exports__['default'] = function allSettled(entries, label) {
+            return new AllSettled(Promise, entries, label).promise;
+        };
+    });
+    define('rsvp/all', [
+    './promise',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        /**
+              This is a convenient alias for `RSVP.Promise.all`.
+
+              @method all
+              @static
+              @for RSVP
+              @param {Array} array Array of promises.
+              @param {String} label An optional label. This is useful
+              for tooling.
+            */
+        __exports__['default'] = function all(array, label) {
+            return Promise.all(array, label);
+        };
+    });
+    define('rsvp/asap', ['exports'], function (__exports__) {
+        'use strict';
+        var length = 0;
+        __exports__['default'] = function asap(callback, arg) {
+            queue[length] = callback;
+            queue[length + 1] = arg;
+            length += 2;
+            if (length === 2) {
+                // If length is 1, that means that we need to schedule an async flush.
+                // If additional callbacks are queued before the queue is flushed, they
+                // will be processed by this flush that we are scheduling.
+                scheduleFlush();
+            }
+        };
+        var browserGlobal = typeof window !== 'undefined' ? window : {};
+        var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
+        // test for web worker but not in IE10
+        var isWorker = typeof Uint8ClampedArray !== 'undefined' &amp;&amp; typeof importScripts !== 'undefined' &amp;&amp; typeof MessageChannel !== 'undefined';
+        // node
+        function useNextTick() {
+            return function () {
+                process.nextTick(flush);
+            };
+        }
+        function useMutationObserver() {
+            var iterations = 0;
+            var observer = new BrowserMutationObserver(flush);
+            var node = document.createTextNode('');
+            observer.observe(node, {
+                characterData: true 
+            });
+            return function () {
+                node.data = iterations = ++iterations % 2;
+            };
+        }
+        // web worker
+        function useMessageChannel() {
+            var channel = new MessageChannel();
+            channel.port1.onmessage = flush;
+            return function () {
+                channel.port2.postMessage(0);
+            };
+        }
+        function useSetTimeout() {
+            return function () {
+                setTimeout(flush, 1);
+            };
+        }
+        var queue = new Array(1000);
+        function flush() {
+            for (var i = 0; i &lt; length; i += 2) {
+                var callback = queue[i];
+                var arg = queue[i + 1];
+                callback(arg);
+                queue[i] = undefined;
+                queue[i + 1] = undefined;
+            }
+            length = 0;
+        }
+        var scheduleFlush;
+        // Decide what async method to use to triggering processing of queued callbacks:
+        if (typeof process !== 'undefined' &amp;&amp; {}.toString.call(process) === '[object process]') {
+            scheduleFlush = useNextTick();
+        } else if (BrowserMutationObserver) {
+            scheduleFlush = useMutationObserver();
+        } else if (isWorker) {
+            scheduleFlush = useMessageChannel();
+        } else {
+            scheduleFlush = useSetTimeout();
+        }
+    });
+    define('rsvp/config', [
+    './events',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var EventTarget = __dependency1__['default'];
+        var config = {
+            instrument: false 
+        };
+        EventTarget.mixin(config);
+        function configure(name, value) {
+            if (name === 'onerror') {
+                // handle for legacy users that expect the actual
+                // error to be passed to their function added via
+                // `RSVP.configure('onerror', someFunctionHere);`
+                config.on('error', value);
+                return;
+            }
+            if (arguments.length === 2) {
+                config[name] = value;
+            } else {
+                return config[name];
+            }
+        }
+        __exports__.config = config;
+        __exports__.configure = configure;
+    });
+    define('rsvp/defer', [
+    './promise',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        /**
+              `RSVP.defer` returns an object similar to jQuery's `$.Deferred`.
+              `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s
+              interface. New code should use the `RSVP.Promise` constructor instead.
+
+              The object returned from `RSVP.defer` is a plain object with three properties:
+
+              * promise - an `RSVP.Promise`.
+              * reject - a function that causes the `promise` property on this object to
+                become rejected
+              * resolve - a function that causes the `promise` property on this object to
+                become fulfilled.
+
+              Example:
+
+               ```javascript
+               var deferred = RSVP.defer();
+
+               deferred.resolve(&quot;Success!&quot;);
+
+               defered.promise.then(function(value){
+                 // value here is &quot;Success!&quot;
+               });
+               ```
+
+              @method defer
+              @static
+              @for RSVP
+              @param {String} label optional string for labeling the promise.
+              Useful for tooling.
+              @return {Object}
+             */
+        __exports__['default'] = function defer(label) {
+            var deferred = {};
+            deferred.promise = new Promise(function (resolve, reject) {
+                deferred.resolve = resolve;
+                deferred.reject = reject;
+            }, label);
+            return deferred;
+        };
+    });
+    define('rsvp/enumerator', [
+    './utils',
+    './-internal',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __exports__) {
+        'use strict';
+        var isArray = __dependency1__.isArray;
+        var isMaybeThenable = __dependency1__.isMaybeThenable;
+        var noop = __dependency2__.noop;
+        var reject = __dependency2__.reject;
+        var fulfill = __dependency2__.fulfill;
+        var subscribe = __dependency2__.subscribe;
+        var FULFILLED = __dependency2__.FULFILLED;
+        var REJECTED = __dependency2__.REJECTED;
+        var PENDING = __dependency2__.PENDING;
+        var ABORT_ON_REJECTION = true;
+        __exports__.ABORT_ON_REJECTION = ABORT_ON_REJECTION;
+        function makeSettledResult(state, position, value) {
+            if (state === FULFILLED) {
+                return {
+                    state: 'fulfilled',
+                    value: value
+                };
+            } else {
+                return {
+                    state: 'rejected',
+                    reason: value
+                };
+            }
+        }
+        __exports__.makeSettledResult = makeSettledResult;
+        function Enumerator(Constructor, input, abortOnReject, label) {
+            this._instanceConstructor = Constructor;
+            this.promise = new Constructor(noop, label);
+            this._abortOnReject = abortOnReject;
+            if (this._validateInput(input)) {
+                this._input = input;
+                this.length = input.length;
+                this._remaining = input.length;
+                this._init();
+                if (this.length === 0) {
+                    fulfill(this.promise, this._result);
+                } else {
+                    this.length = this.length || 0;
+                    this._enumerate();
+                    if (this._remaining === 0) {
+                        fulfill(this.promise, this._result);
+                    }
+                }
+            } else {
+                reject(this.promise, this._validationError());
+            }
+        }
+        Enumerator.prototype._validateInput = function (input) {
+            return isArray(input);
+        };
+        Enumerator.prototype._validationError = function () {
+            return new Error('Array Methods must be provided an Array');
+        };
+        Enumerator.prototype._init = function () {
+            this._result = new Array(this.length);
+        };
+        __exports__['default'] = Enumerator;
+        Enumerator.prototype._enumerate = function () {
+            var length = this.length;
+            var promise = this.promise;
+            var input = this._input;
+            for (var i = 0; promise._state === PENDING &amp;&amp; i &lt; length; i++) {
+                this._eachEntry(input[i], i);
+            }
+        };
+        Enumerator.prototype._eachEntry = function (entry, i) {
+            var c = this._instanceConstructor;
+            if (isMaybeThenable(entry)) {
+                if (entry.constructor === c &amp;&amp; entry._state !== PENDING) {
+                    entry._onerror = null;
+                    this._settledAt(entry._state, i, entry._result);
+                } else {
+                    this._willSettleAt(c.resolve(entry), i);
+                }
+            } else {
+                this._remaining--;
+                this._result[i] = this._makeResult(FULFILLED, i, entry);
+            }
+        };
+        Enumerator.prototype._settledAt = function (state, i, value) {
+            var promise = this.promise;
+            if (promise._state === PENDING) {
+                this._remaining--;
+                if (this._abortOnReject &amp;&amp; state === REJECTED) {
+                    reject(promise, value);
+                } else {
+                    this._result[i] = this._makeResult(state, i, value);
+                }
+            }
+            if (this._remaining === 0) {
+                fulfill(promise, this._result);
+            }
+        };
+        Enumerator.prototype._makeResult = function (state, i, value) {
+            return value;
+        };
+        Enumerator.prototype._willSettleAt = function (promise, i) {
+            var enumerator = this;
+            subscribe(promise, undefined, function (value) {
+                enumerator._settledAt(FULFILLED, i, value);
+            }, function (reason) {
+                enumerator._settledAt(REJECTED, i, reason);
+            });
+        };
+    });
+    define('rsvp/events', ['exports'], function (__exports__) {
+        'use strict';
+        function indexOf(callbacks, callback) {
+            for (var i = 0, l = callbacks.length; i &lt; l; i++) {
+                if (callbacks[i] === callback) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+        function callbacksFor(object) {
+            var callbacks = object._promiseCallbacks;
+            if (!callbacks) {
+                callbacks = object._promiseCallbacks = {};
+            }
+            return callbacks;
+        }
+        /**
+              @class RSVP.EventTarget
+            */
+        __exports__['default'] = {
+            mixin: function (object) {
+                object.on = this.on;
+                object.off = this.off;
+                object.trigger = this.trigger;
+                object._promiseCallbacks = undefined;
+                return object;
+            },
+            on: function (eventName, callback) {
+                var allCallbacks = callbacksFor(this), callbacks;
+                callbacks = allCallbacks[eventName];
+                if (!callbacks) {
+                    callbacks = allCallbacks[eventName] = [];
+                }
+                if (indexOf(callbacks, callback) === -1) {
+                    callbacks.push(callback);
+                }
+            },
+            off: function (eventName, callback) {
+                var allCallbacks = callbacksFor(this), callbacks, index;
+                if (!callback) {
+                    allCallbacks[eventName] = [];
+                    return;
+                }
+                callbacks = allCallbacks[eventName];
+                index = indexOf(callbacks, callback);
+                if (index !== -1) {
+                    callbacks.splice(index, 1);
+                }
+            },
+            trigger: function (eventName, options) {
+                var allCallbacks = callbacksFor(this), callbacks, callbackTuple, callback, binding;
+                if (callbacks = allCallbacks[eventName]) {
+                    // Don't cache the callbacks.length since it may grow
+                    for (var i = 0; i &lt; callbacks.length; i++) {
+                        callback = callbacks[i];
+                        callback(options);
+                    }
+                }
+            }
+        };
+    });
+    define('rsvp/filter', [
+    './promise',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        var isFunction = __dependency2__.isFunction;
+        var isMaybeThenable = __dependency2__.isMaybeThenable;
+        /**
+             `RSVP.filter` is similar to JavaScript's native `filter` method, except that it
+              waits for all promises to become fulfilled before running the `filterFn` on
+              each item in given to `promises`. `RSVP.filter` returns a promise that will
+              become fulfilled with the result of running `filterFn` on the values the
+              promises become fulfilled with.
+
+              For example:
+
+              ```javascript
+
+              var promise1 = RSVP.resolve(1);
+              var promise2 = RSVP.resolve(2);
+              var promise3 = RSVP.resolve(3);
+
+              var promises = [promise1, promise2, promise3];
+
+              var filterFn = function(item){
+                return item &gt; 1;
+              };
+
+              RSVP.filter(promises, filterFn).then(function(result){
+                // result is [ 2, 3 ]
+              });
+              ```
+
+              If any of the `promises` given to `RSVP.filter` are rejected, the first promise
+              that is rejected will be given as an argument to the returned promise's
+              rejection handler. For example:
+
+              ```javascript
+              var promise1 = RSVP.resolve(1);
+              var promise2 = RSVP.reject(new Error(&quot;2&quot;));
+              var promise3 = RSVP.reject(new Error(&quot;3&quot;));
+              var promises = [ promise1, promise2, promise3 ];
+
+              var filterFn = function(item){
+                return item &gt; 1;
+              };
+
+              RSVP.filter(promises, filterFn).then(function(array){
+                // Code here never runs because there are rejected promises!
+              }, function(reason) {
+                // reason.message === &quot;2&quot;
+              });
+              ```
+
+              `RSVP.filter` will also wait for any promises returned from `filterFn`.
+              For instance, you may want to fetch a list of users then return a subset
+              of those users based on some asynchronous operation:
+
+              ```javascript
+
+              var alice = { name: 'alice' };
+              var bob   = { name: 'bob' };
+              var users = [ alice, bob ];
+
+              var promises = users.map(function(user){
+                return RSVP.resolve(user);
+              });
+
+              var filterFn = function(user){
+                // Here, Alice has permissions to create a blog post, but Bob does not.
+                return getPrivilegesForUser(user).then(function(privs){
+                  return privs.can_create_blog_post === true;
+                });
+              };
+              RSVP.filter(promises, filterFn).then(function(users){
+                // true, because the server told us only Alice can create a blog post.
+                users.length === 1;
+                // false, because Alice is the only user present in `users`
+                users[0] === bob;
+              });
+              ```
+
+              @method filter
+              @static
+              @for RSVP
+              @param {Array} promises
+              @param {Function} filterFn - function to be called on each resolved value to
+              filter the final results.
+              @param {String} label optional string describing the promise. Useful for
+              tooling.
+              @return {Promise}
+            */
+        __exports__['default'] = function filter(promises, filterFn, label) {
+            return Promise.all(promises, label).then(function (values) {
+                if (!isFunction(filterFn)) {
+                    throw new TypeError('You must pass a function as filter\'s second argument.');
+                }
+                var length = values.length;
+                var filtered = new Array(length);
+                for (var i = 0; i &lt; length; i++) {
+                    filtered[i] = filterFn(values[i]);
+                }
+                return Promise.all(filtered, label).then(function (filtered$2) {
+                    var results = new Array(length);
+                    var newLength = 0;
+                    for (var i$2 = 0; i$2 &lt; length; i$2++) {
+                        if (filtered$2[i$2]) {
+                            results[newLength] = values[i$2];
+                            newLength++;
+                        }
+                    }
+                    results.length = newLength;
+                    return results;
+                });
+            });
+        };
+    });
+    define('rsvp/hash-settled', [
+    './promise',
+    './enumerator',
+    './promise-hash',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        var makeSettledResult = __dependency2__.makeSettledResult;
+        var PromiseHash = __dependency3__['default'];
+        var Enumerator = __dependency2__['default'];
+        var o_create = __dependency4__.o_create;
+        function HashSettled(Constructor, object, label) {
+            this._superConstructor(Constructor, object, false, label);
+        }
+        HashSettled.prototype = o_create(PromiseHash.prototype);
+        HashSettled.prototype._superConstructor = Enumerator;
+        HashSettled.prototype._makeResult = makeSettledResult;
+        HashSettled.prototype._validationError = function () {
+            return new Error('hashSettled must be called with an object');
+        };
+        /**
+              `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object
+              instead of an array for its `promises` argument.
+
+              Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method,
+              but like `RSVP.allSettled`, `hashSettled` waits until all the
+              constituent promises have returned and then shows you all the results
+              with their states and values/reasons. This is useful if you want to
+              handle multiple promises' failure states together as a set.
+
+              Returns a promise that is fulfilled when all the given promises have been
+              settled, or rejected if the passed parameters are invalid.
+
+              The returned promise is fulfilled with a hash that has the same key names as
+              the `promises` object argument. If any of the values in the object are not
+              promises, they will be copied over to the fulfilled object and marked with state
+              'fulfilled'.
+
+              Example:
+
+              ```javascript
+              var promises = {
+                myPromise: RSVP.Promise.resolve(1),
+                yourPromise: RSVP.Promise.resolve(2),
+                theirPromise: RSVP.Promise.resolve(3),
+                notAPromise: 4
+              };
+
+              RSVP.hashSettled(promises).then(function(hash){
+                // hash here is an object that looks like:
+                // {
+                //   myPromise: { state: 'fulfilled', value: 1 },
+                //   yourPromise: { state: 'fulfilled', value: 2 },
+                //   theirPromise: { state: 'fulfilled', value: 3 },
+                //   notAPromise: { state: 'fulfilled', value: 4 }
+                // }
+              });
+              ```
+
+              If any of the `promises` given to `RSVP.hash` are rejected, the state will
+              be set to 'rejected' and the reason for rejection provided.
+
+              Example:
+
+              ```javascript
+              var promises = {
+                myPromise: RSVP.Promise.resolve(1),
+                rejectedPromise: RSVP.Promise.reject(new Error('rejection')),
+                anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection'))
+              };
+
+              RSVP.hashSettled(promises).then(function(hash){
+                // hash here is an object that looks like:
+                // {
+                //   myPromise:              { state: 'fulfilled', value: 1 },
+                //   rejectedPromise:        { state: 'rejected', reason: Error },
+                //   anotherRejectedPromise: { state: 'rejected', reason: Error },
+                // }
+                // Note that for rejectedPromise, reason.message == 'rejection',
+                // and for anotherRejectedPromise, reason.message == 'more rejection'.
+              });
+              ```
+
+              An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that
+              are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype
+              chains.
+
+              Example:
+
+              ```javascript
+              function MyConstructor(){
+                this.example = RSVP.Promise.resolve('Example');
+              }
+
+              MyConstructor.prototype = {
+                protoProperty: RSVP.Promise.resolve('Proto Property')
+              };
+
+              var myObject = new MyConstructor();
+
+              RSVP.hashSettled(myObject).then(function(hash){
+                // protoProperty will not be present, instead you will just have an
+                // object that looks like:
+                // {
+                //   example: { state: 'fulfilled', value: 'Example' }
+                // }
+                //
+                // hash.hasOwnProperty('protoProperty'); // false
+                // 'undefined' === typeof hash.protoProperty
+              });
+              ```
+
+              @method hashSettled
+              @for RSVP
+              @param {Object} promises
+              @param {String} label optional string that describes the promise.
+              Useful for tooling.
+              @return {Promise} promise that is fulfilled when when all properties of `promises`
+              have been settled.
+              @static
+            */
+        __exports__['default'] = function hashSettled(object, label) {
+            return new HashSettled(Promise, object, label).promise;
+        };
+    });
+    define('rsvp/hash', [
+    './promise',
+    './promise-hash',
+    './enumerator',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        var PromiseHash = __dependency2__['default'];
+        var ABORT_ON_REJECTION = __dependency3__.ABORT_ON_REJECTION;
+        /**
+              `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array
+              for its `promises` argument.
+
+              Returns a promise that is fulfilled when all the given promises have been
+              fulfilled, or rejected if any of them become rejected. The returned promise
+              is fulfilled with a hash that has the same key names as the `promises` object
+              argument. If any of the values in the object are not promises, they will
+              simply be copied over to the fulfilled object.
+
+              Example:
+
+              ```javascript
+              var promises = {
+                myPromise: RSVP.resolve(1),
+                yourPromise: RSVP.resolve(2),
+                theirPromise: RSVP.resolve(3),
+                notAPromise: 4
+              };
+
+              RSVP.hash(promises).then(function(hash){
+                // hash here is an object that looks like:
+                // {
+                //   myPromise: 1,
+                //   yourPromise: 2,
+                //   theirPromise: 3,
+                //   notAPromise: 4
+                // }
+              });
+              ````
+
+              If any of the `promises` given to `RSVP.hash` are rejected, the first promise
+              that is rejected will be given as the reason to the rejection handler.
+
+              Example:
+
+              ```javascript
+              var promises = {
+                myPromise: RSVP.resolve(1),
+                rejectedPromise: RSVP.reject(new Error(&quot;rejectedPromise&quot;)),
+                anotherRejectedPromise: RSVP.reject(new Error(&quot;anotherRejectedPromise&quot;))
+              };
+
+              RSVP.hash(promises).then(function(hash){
+                // Code here never runs because there are rejected promises!
+              }, function(reason) {
+                // reason.message === &quot;rejectedPromise&quot;
+              });
+              ```
+
+              An important note: `RSVP.hash` is intended for plain JavaScript objects that
+              are just a set of keys and values. `RSVP.hash` will NOT preserve prototype
+              chains.
+
+              Example:
+
+              ```javascript
+              function MyConstructor(){
+                this.example = RSVP.resolve(&quot;Example&quot;);
+              }
+
+              MyConstructor.prototype = {
+                protoProperty: RSVP.resolve(&quot;Proto Property&quot;)
+              };
+
+              var myObject = new MyConstructor();
+
+              RSVP.hash(myObject).then(function(hash){
+                // protoProperty will not be present, instead you will just have an
+                // object that looks like:
+                // {
+                //   example: &quot;Example&quot;
+                // }
+                //
+                // hash.hasOwnProperty('protoProperty'); // false
+                // 'undefined' === typeof hash.protoProperty
+              });
+              ```
+
+              @method hash
+              @static
+              @for RSVP
+              @param {Object} promises
+              @param {String} label optional string that describes the promise.
+              Useful for tooling.
+              @return {Promise} promise that is fulfilled when all properties of `promises`
+              have been fulfilled, or rejected if any of them become rejected.
+            */
+        __exports__['default'] = function hash(object, label) {
+            return new PromiseHash(Promise, object, label).promise;
+        };
+    });
+    define('rsvp/instrument', [
+    './config',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __exports__) {
+        'use strict';
+        var config = __dependency1__.config;
+        var now = __dependency2__.now;
+        var queue = [];
+        __exports__['default'] = function instrument(eventName, promise, child) {
+            if (1 === queue.push({
+                name: eventName,
+                payload: {
+                    guid: promise._guidKey + promise._id,
+                    eventName: eventName,
+                    detail: promise._result,
+                    childGuid: child &amp;&amp; promise._guidKey + child._id,
+                    label: promise._label,
+                    timeStamp: now(),
+                    stack: new Error(promise._label).stack
+                }
+            })) {
+                setTimeout(function () {
+                    var entry;
+                    for (var i = 0; i &lt; queue.length; i++) {
+                        entry = queue[i];
+                        config.trigger(entry.name, entry.payload);
+                    }
+                    queue.length = 0;
+                }, 50);
+            }
+        };
+    });
+    define('rsvp/map', [
+    './promise',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        var isArray = __dependency2__.isArray;
+        var isFunction = __dependency2__.isFunction;
+        /**
+             `RSVP.map` is similar to JavaScript's native `map` method, except that it
+              waits for all promises to become fulfilled before running the `mapFn` on
+              each item in given to `promises`. `RSVP.map` returns a promise that will
+              become fulfilled with the result of running `mapFn` on the values the promises
+              become fulfilled with.
+
+              For example:
+
+              ```javascript
+
+              var promise1 = RSVP.resolve(1);
+              var promise2 = RSVP.resolve(2);
+              var promise3 = RSVP.resolve(3);
+              var promises = [ promise1, promise2, promise3 ];
+
+              var mapFn = function(item){
+                return item + 1;
+              };
+
+              RSVP.map(promises, mapFn).then(function(result){
+                // result is [ 2, 3, 4 ]
+              });
+              ```
+
+              If any of the `promises` given to `RSVP.map` are rejected, the first promise
+              that is rejected will be given as an argument to the returned promise's
+              rejection handler. For example:
+
+              ```javascript
+              var promise1 = RSVP.resolve(1);
+              var promise2 = RSVP.reject(new Error(&quot;2&quot;));
+              var promise3 = RSVP.reject(new Error(&quot;3&quot;));
+              var promises = [ promise1, promise2, promise3 ];
+
+              var mapFn = function(item){
+                return item + 1;
+              };
+
+              RSVP.map(promises, mapFn).then(function(array){
+                // Code here never runs because there are rejected promises!
+              }, function(reason) {
+                // reason.message === &quot;2&quot;
+              });
+              ```
+
+              `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,
+              say you want to get all comments from a set of blog posts, but you need
+              the blog posts first because they contain a url to those comments.
+
+              ```javscript
+
+              var mapFn = function(blogPost){
+                // getComments does some ajax and returns an RSVP.Promise that is fulfilled
+                // with some comments data
+                return getComments(blogPost.comments_url);
+              };
+
+              // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled
+              // with some blog post data
+              RSVP.map(getBlogPosts(), mapFn).then(function(comments){
+                // comments is the result of asking the server for the comments
+                // of all blog posts returned from getBlogPosts()
+              });
+              ```
+
+              @method map
+              @static
+              @for RSVP
+              @param {Array} promises
+              @param {Function} mapFn function to be called on each fulfilled promise.
+              @param {String} label optional string for labeling the promise.
+              Useful for tooling.
+              @return {Promise} promise that is fulfilled with the result of calling
+              `mapFn` on each fulfilled promise or value when they become fulfilled.
+               The promise will be rejected if any of the given `promises` become rejected.
+              @static
+            */
+        __exports__['default'] = function map(promises, mapFn, label) {
+            return Promise.all(promises, label).then(function (values) {
+                if (!isFunction(mapFn)) {
+                    throw new TypeError('You must pass a function as map\'s second argument.');
+                }
+                var length = values.length;
+                var results = new Array(length);
+                for (var i = 0; i &lt; length; i++) {
+                    results[i] = mapFn(values[i]);
+                }
+                return Promise.all(results, label);
+            });
+        };
+    });
+    define('rsvp/node', [
+    './promise',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __exports__) {
+        'use strict';
+        /* global  arraySlice */
+        var Promise = __dependency1__['default'];
+        var isArray = __dependency2__.isArray;
+        /**
+              `RSVP.denodeify` takes a &quot;node-style&quot; function and returns a function that
+              will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the
+              browser when you'd prefer to use promises over using callbacks. For example,
+              `denodeify` transforms the following:
+
+              ```javascript
+              var fs = require('fs');
+
+              fs.readFile('myfile.txt', function(err, data){
+                if (err) return handleError(err);
+                handleData(data);
+              });
+              ```
+
+              into:
+
+              ```javascript
+              var fs = require('fs');
+              var readFile = RSVP.denodeify(fs.readFile);
+
+              readFile('myfile.txt').then(handleData, handleError);
+              ```
+
+              If the node function has multiple success parameters, then `denodeify`
+              just returns the first one:
+
+              ```javascript
+              var request = RSVP.denodeify(require('request'));
+
+              request('http://example.com').then(function(res) {
+                // ...
+              });
+              ```
+
+              However, if you need all success parameters, setting `denodeify`'s
+              second parameter to `true` causes it to return all success parameters
+              as an array:
+
+              ```javascript
+              var request = RSVP.denodeify(require('request'), true);
+
+              request('http://example.com').then(function(result) {
+                // result[0] -&gt; res
+                // result[1] -&gt; body
+              });
+              ```
+
+              Or if you pass it an array with names it returns the parameters as a hash:
+
+              ```javascript
+              var request = RSVP.denodeify(require('request'), ['res', 'body']);
+
+              request('http://example.com').then(function(result) {
+                // result.res
+                // result.body
+              });
+              ```
+
+              Sometimes you need to retain the `this`:
+
+              ```javascript
+              var app = require('express')();
+              var render = RSVP.denodeify(app.render.bind(app));
+              ```
+
+              The denodified function inherits from the original function. It works in all
+              environments, except IE 10 and below. Consequently all properties of the original
+              function are available to you. However, any properties you change on the
+              denodeified function won't be changed on the original function. Example:
+
+              ```javascript
+              var request = RSVP.denodeify(require('request')),
+                  cookieJar = request.jar(); // &lt;- Inheritance is used here
+
+              request('http://example.com', {jar: cookieJar}).then(function(res) {
+                // cookieJar.cookies holds now the cookies returned by example.com
+              });
+              ```
+
+              Using `denodeify` makes it easier to compose asynchronous operations instead
+              of using callbacks. For example, instead of:
+
+              ```javascript
+              var fs = require('fs');
+
+              fs.readFile('myfile.txt', function(err, data){
+                if (err) { ... } // Handle error
+                fs.writeFile('myfile2.txt', data, function(err){
+                  if (err) { ... } // Handle error
+                  console.log('done')
+                });
+              });
+              ```
+
+              you can chain the operations together using `then` from the returned promise:
+
+              ```javascript
+              var fs = require('fs');
+              var readFile = RSVP.denodeify(fs.readFile);
+              var writeFile = RSVP.denodeify(fs.writeFile);
+
+              readFile('myfile.txt').then(function(data){
+                return writeFile('myfile2.txt', data);
+              }).then(function(){
+                console.log('done')
+              }).catch(function(error){
+                // Handle error
+              });
+              ```
+
+              @method denodeify
+              @static
+              @for RSVP
+              @param {Function} nodeFunc a &quot;node-style&quot; function that takes a callback as
+              its last argument. The callback expects an error to be passed as its first
+              argument (if an error occurred, otherwise null), and the value from the
+              operation as its second argument (&quot;function(err, value){ }&quot;).
+              @param {Boolean|Array} argumentNames An optional paramter that if set
+              to `true` causes the promise to fulfill with the callback's success arguments
+              as an array. This is useful if the node function has multiple success
+              paramters. If you set this paramter to an array with names, the promise will
+              fulfill with a hash with these names as keys and the success parameters as
+              values.
+              @return {Function} a function that wraps `nodeFunc` to return an
+              `RSVP.Promise`
+              @static
+            */
+        __exports__['default'] = function denodeify(nodeFunc, argumentNames) {
+            var asArray = argumentNames === true;
+            var asHash = isArray(argumentNames);
+            function denodeifiedFunction() {
+                var length = arguments.length;
+                var nodeArgs = new Array(length);
+                for (var i = 0; i &lt; length; i++) {
+                    nodeArgs[i] = arguments[i];
+                }
+                var thisArg;
+                if (!asArray &amp;&amp; !asHash &amp;&amp; argumentNames) {
+                    if (typeof console === 'object') {
+                        console.warn('Deprecation: RSVP.denodeify() doesn\'t allow setting the ' + '&quot;this&quot; binding anymore. Use yourFunction.bind(yourThis) instead.');
+                    }
+                    thisArg = argumentNames;
+                } else {
+                    thisArg = this;
+                }
+                return Promise.all(nodeArgs).then(function (nodeArgs$2) {
+                    return new Promise(resolver);
+                    // sweet.js has a bug, this resolver can't be defined in the constructor
+                    // or the arraySlice macro doesn't work
+                    function resolver(resolve, reject) {
+                        function callback() {
+                            var length$2 = arguments.length;
+                            var args = new Array(length$2);
+                            for (var i$2 = 0; i$2 &lt; length$2; i$2++) {
+                                args[i$2] = arguments[i$2];
+                            }
+                            var error = args[0];
+                            var value = args[1];
+                            if (error) {
+                                reject(error);
+                            } else if (asArray) {
+                                resolve(args.slice(1));
+                            } else if (asHash) {
+                                var obj = {};
+                                var successArguments = args.slice(1);
+                                var name;
+                                var i$3;
+                                for (i$3 = 0; i$3 &lt; argumentNames.length; i$3++) {
+                                    name = argumentNames[i$3];
+                                    obj[name] = successArguments[i$3];
+                                }
+                                resolve(obj);
+                            } else {
+                                resolve(value);
+                            }
+                        }
+                        nodeArgs$2.push(callback);
+                        nodeFunc.apply(thisArg, nodeArgs$2);
+                    }
+                });
+            }
+            denodeifiedFunction.__proto__ = nodeFunc;
+            return denodeifiedFunction;
+        };
+    });
+    define('rsvp/promise-hash', [
+    './enumerator',
+    './-internal',
+    './utils',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __exports__) {
+        'use strict';
+        var Enumerator = __dependency1__['default'];
+        var PENDING = __dependency2__.PENDING;
+        var FULFILLED = __dependency2__.FULFILLED;
+        var o_create = __dependency3__.o_create;
+        function PromiseHash(Constructor, object, label) {
+            this._superConstructor(Constructor, object, true, label);
+        }
+        __exports__['default'] = PromiseHash;
+        PromiseHash.prototype = o_create(Enumerator.prototype);
+        PromiseHash.prototype._superConstructor = Enumerator;
+        PromiseHash.prototype._init = function () {
+            this._result = {};
+        };
+        PromiseHash.prototype._validateInput = function (input) {
+            return input &amp;&amp; typeof input === 'object';
+        };
+        PromiseHash.prototype._validationError = function () {
+            return new Error('Promise.hash must be called with an object');
+        };
+        PromiseHash.prototype._enumerate = function () {
+            var promise = this.promise;
+            var input = this._input;
+            var results = [];
+            for (var key in input) {
+                if (promise._state === PENDING &amp;&amp; input.hasOwnProperty(key)) {
+                    results.push({
+                        position: key,
+                        entry: input[key]
+                    });
+                }
+            }
+            var length = results.length;
+            this._remaining = length;
+            var result;
+            for (var i = 0; promise._state === PENDING &amp;&amp; i &lt; length; i++) {
+                result = results[i];
+                this._eachEntry(result.entry, result.position);
+            }
+        };
+    });
+    define('rsvp/promise', [
+    './config',
+    './events',
+    './instrument',
+    './utils',
+    './-internal',
+    './promise/cast',
+    './promise/all',
+    './promise/race',
+    './promise/resolve',
+    './promise/reject',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
+        'use strict';
+        var config = __dependency1__.config;
+        var EventTarget = __dependency2__['default'];
+        var instrument = __dependency3__['default'];
+        var objectOrFunction = __dependency4__.objectOrFunction;
+        var isFunction = __dependency4__.isFunction;
+        var now = __dependency4__.now;
+        var noop = __dependency5__.noop;
+        var resolve = __dependency5__.resolve;
+        var reject = __dependency5__.reject;
+        var fulfill = __dependency5__.fulfill;
+        var subscribe = __dependency5__.subscribe;
+        var initializePromise = __dependency5__.initializePromise;
+        var invokeCallback = __dependency5__.invokeCallback;
+        var FULFILLED = __dependency5__.FULFILLED;
+        var cast = __dependency6__['default'];
+        var all = __dependency7__['default'];
+        var race = __dependency8__['default'];
+        var Resolve = __dependency9__['default'];
+        var Reject = __dependency10__['default'];
+        var guidKey = 'rsvp_' + now() + '-';
+        var counter = 0;
+        function needsResolver() {
+            throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
+        }
+        function needsNew() {
+            throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
+        }
+        __exports__['default'] = Promise;
+        /**
+              Promise objects represent the eventual result of an asynchronous operation. The
+              primary way of interacting with a promise is through its `then` method, which
+              registers callbacks to receive either a promise’s eventual value or the reason
+              why the promise cannot be fulfilled.
+
+              Terminology
+              -----------
+
+              - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
+              - `thenable` is an object or function that defines a `then` method.
+              - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
+              - `exception` is a value that is thrown using the throw statement.
+              - `reason` is a value that indicates why a promise was rejected.
+              - `settled` the final resting state of a promise, fulfilled or rejected.
+
+              A promise can be in one of three states: pending, fulfilled, or rejected.
+
+              Promises that are fulfilled have a fulfillment value and are in the fulfilled
+              state.  Promises that are rejected have a rejection reason and are in the
+              rejected state.  A fulfillment value is never a thenable.
+
+              Promises can also be said to *resolve* a value.  If this value is also a
+              promise, then the original promise's settled state will match the value's
+              settled state.  So a promise that *resolves* a promise that rejects will
+              itself reject, and a promise that *resolves* a promise that fulfills will
+              itself fulfill.
+
+
+              Basic Usage:
+              ------------
+
+              ```js
+              var promise = new Promise(function(resolve, reject) {
+                // on success
+                resolve(value);
+
+                // on failure
+                reject(reason);
+              });
+
+              promise.then(function(value) {
+                // on fulfillment
+              }, function(reason) {
+                // on rejection
+              });
+              ```
+
+              Advanced Usage:
+              ---------------
+
+              Promises shine when abstracting away asynchronous interactions such as
+              `XMLHttpRequest`s.
+
+              ```js
+              function getJSON(url) {
+                return new Promise(function(resolve, reject){
+                  var xhr = new XMLHttpRequest();
+
+                  xhr.open('GET', url);
+                  xhr.onreadystatechange = handler;
+                  xhr.responseType = 'json';
+                  xhr.setRequestHeader('Accept', 'application/json');
+                  xhr.send();
+
+                  function handler() {
+                    if (this.readyState === this.DONE) {
+                      if (this.status === 200) {
+                        resolve(this.response);
+                      } else {
+                        reject(new Error(&quot;getJSON: `&quot; + url + &quot;` failed with status: [&quot; + this.status + &quot;]&quot;));
+                      }
+                    }
+                  };
+                });
+              }
+
+              getJSON('/posts.json').then(function(json) {
+                // on fulfillment
+              }, function(reason) {
+                // on rejection
+              });
+              ```
+
+              Unlike callbacks, promises are great composable primitives.
+
+              ```js
+              Promise.all([
+                getJSON('/posts'),
+                getJSON('/comments')
+              ]).then(function(values){
+                values[0] // =&gt; postsJSON
+                values[1] // =&gt; commentsJSON
+
+                return values;
+              });
+              ```
+
+              @class RSVP.Promise
+              @param {function} resolver
+              @param {String} label optional string for labeling the promise.
+              Useful for tooling.
+              @constructor
+            */
+        function Promise(resolver, label) {
+            this._id = counter++;
+            this._label = label;
+            this._subscribers = [];
+            if (config.instrument) {
+                instrument('created', this);
+            }
+            if (noop !== resolver) {
+                if (!isFunction(resolver)) {
+                    needsResolver();
+                }
+                if (!(this instanceof Promise)) {
+                    needsNew();
+                }
+                initializePromise(this, resolver);
+            }
+        }
+        Promise.cast = cast;
+        Promise.all = all;
+        Promise.race = race;
+        Promise.resolve = Resolve;
+        Promise.reject = Reject;
+        Promise.prototype = {
+            constructor: Promise,
+            _id: undefined,
+            _guidKey: guidKey,
+            _label: undefined,
+            _state: undefined,
+            _result: undefined,
+            _subscribers: undefined,
+            _onerror: function (reason) {
+                config.trigger('error', reason);
+            },
+            then: function (onFulfillment, onRejection, label) {
+                var parent = this;
+                parent._onerror = null;
+                var child = new this.constructor(noop, label);
+                var state = parent._state;
+                var result = parent._result;
+                if (config.instrument) {
+                    instrument('chained', parent, child);
+                }
+                if (state === FULFILLED &amp;&amp; onFulfillment) {
+                    config.async(function () {
+                        invokeCallback(state, child, onFulfillment, result);
+                    });
+                } else {
+                    subscribe(parent, child, onFulfillment, onRejection);
+                }
+                return child;
+            },
+            'catch': function (onRejection, label) {
+                return this.then(null, onRejection, label);
+            },
+            'finally': function (callback, label) {
+                var constructor = this.constructor;
+                return this.then(function (value) {
+                    return constructor.resolve(callback()).then(function () {
+                        return value;
+                    });
+                }, function (reason) {
+                    return constructor.resolve(callback()).then(function () {
+                        throw reason;
+                    });
+                }, label);
+            }
+        };
+    });
+    define('rsvp/promise/all', [
+    '../enumerator',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var Enumerator = __dependency1__['default'];
+        /**
+              `RSVP.Promise.all` accepts an array of promises, and returns a new promise which
+              is fulfilled with an array of fulfillment values for the passed promises, or
+              rejected with the reason of the first passed promise to be rejected. It casts all
+              elements of the passed iterable to promises as it runs this algorithm.
+
+              Example:
+
+              ```javascript
+              var promise1 = RSVP.resolve(1);
+              var promise2 = RSVP.resolve(2);
+              var promise3 = RSVP.resolve(3);
+              var promises = [ promise1, promise2, promise3 ];
+
+              RSVP.Promise.all(promises).then(function(array){
+                // The array here would be [ 1, 2, 3 ];
+              });
+              ```
+
+              If any of the `promises` given to `RSVP.all` are rejected, the first promise
+              that is rejected will be given as an argument to the returned promises's
+              rejection handler. For example:
+
+              Example:
+
+              ```javascript
+              var promise1 = RSVP.resolve(1);
+              var promise2 = RSVP.reject(new Error(&quot;2&quot;));
+              var promise3 = RSVP.reject(new Error(&quot;3&quot;));
+              var promises = [ promise1, promise2, promise3 ];
+
+              RSVP.Promise.all(promises).then(function(array){
+                // Code here never runs because there are rejected promises!
+              }, function(error) {
+                // error.message === &quot;2&quot;
+              });
+              ```
+
+              @method all
+              @static
+              @param {Array} entries array of promises
+              @param {String} label optional string for labeling the promise.
+              Useful for tooling.
+              @return {Promise} promise that is fulfilled when all `promises` have been
+              fulfilled, or rejected if any of them become rejected.
+              @static
+            */
+        __exports__['default'] = function all(entries, label) {
+            return new Enumerator(this, entries, true, label).promise;
+        };
+    });
+    define('rsvp/promise/cast', [
+    './resolve',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var resolve = __dependency1__['default'];
+        /**
+              @deprecated
+
+              `RSVP.Promise.cast` coerces its argument to a promise, or returns the
+              argument if it is already a promise which shares a constructor with the caster.
+
+              Example:
+
+              ```javascript
+              var promise = RSVP.Promise.resolve(1);
+              var casted = RSVP.Promise.cast(promise);
+
+              console.log(promise === casted); // true
+              ```
+
+              In the case of a promise whose constructor does not match, it is assimilated.
+              The resulting promise will fulfill or reject based on the outcome of the
+              promise being casted.
+
+              Example:
+
+              ```javascript
+              var thennable = $.getJSON('/api/foo');
+              var casted = RSVP.Promise.cast(thennable);
+
+              console.log(thennable === casted); // false
+              console.log(casted instanceof RSVP.Promise) // true
+
+              casted.then(function(data) {
+                // data is the value getJSON fulfills with
+              });
+              ```
+
+              In the case of a non-promise, a promise which will fulfill with that value is
+              returned.
+
+              Example:
+
+              ```javascript
+              var value = 1; // could be a number, boolean, string, undefined...
+              var casted = RSVP.Promise.cast(value);
+
+              console.log(value === casted); // false
+              console.log(casted instanceof RSVP.Promise) // true
+
+              casted.then(function(val) {
+                val === value // =&gt; true
+              });
+              ```
+
+              `RSVP.Promise.cast` is similar to `RSVP.Promise.resolve`, but `RSVP.Promise.cast` differs in the
+              following ways:
+
+              * `RSVP.Promise.cast` serves as a memory-efficient way of getting a promise, when you
+              have something that could either be a promise or a value. RSVP.resolve
+              will have the same effect but will create a new promise wrapper if the
+              argument is a promise.
+              * `RSVP.Promise.cast` is a way of casting incoming thenables or promise subclasses to
+              promises of the exact class specified, so that the resulting object's `then` is
+              ensured to have the behavior of the constructor you are calling cast on (i.e., RSVP.Promise).
+
+              @method cast
+              @static
+              @param {Object} object to be casted
+              @param {String} label optional string for labeling the promise.
+              Useful for tooling.
+              @return {Promise} promise
+            */
+        __exports__['default'] = resolve;
+    });
+    define('rsvp/promise/race', [
+    '../utils',
+    '../-internal',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __exports__) {
+        'use strict';
+        var isArray = __dependency1__.isArray;
+        var isFunction = __dependency1__.isFunction;
+        var isMaybeThenable = __dependency1__.isMaybeThenable;
+        var noop = __dependency2__.noop;
+        var resolve = __dependency2__.resolve;
+        var reject = __dependency2__.reject;
+        var subscribe = __dependency2__.subscribe;
+        var PENDING = __dependency2__.PENDING;
+        /**
+              `RSVP.Promise.race` returns a new promise which is settled in the same way as the
+              first passed promise to settle.
+
+              Example:
+
+              ```javascript
+              var promise1 = new RSVP.Promise(function(resolve, reject){
+                setTimeout(function(){
+                  resolve(&quot;promise 1&quot;);
+                }, 200);
+              });
+
+              var promise2 = new RSVP.Promise(function(resolve, reject){
+                setTimeout(function(){
+                  resolve(&quot;promise 2&quot;);
+                }, 100);
+              });
+
+              RSVP.Promise.race([promise1, promise2]).then(function(result){
+                // result === &quot;promise 2&quot; because it was resolved before promise1
+                // was resolved.
+              });
+              ```
+
+              `RSVP.Promise.race` is deterministic in that only the state of the first
+              settled promise matters. For example, even if other promises given to the
+              `promises` array argument are resolved, but the first settled promise has
+              become rejected before the other promises became fulfilled, the returned
+              promise will become rejected:
+
+              ```javascript
+              var promise1 = new RSVP.Promise(function(resolve, reject){
+                setTimeout(function(){
+                  resolve(&quot;promise 1&quot;);
+                }, 200);
+              });
+
+              var promise2 = new RSVP.Promise(function(resolve, reject){
+                setTimeout(function(){
+                  reject(new Error(&quot;promise 2&quot;));
+                }, 100);
+              });
+
+              RSVP.Promise.race([promise1, promise2]).then(function(result){
+                // Code here never runs
+              }, function(reason){
+                // reason.message === &quot;promise 2&quot; because promise 2 became rejected before
+                // promise 1 became fulfilled
+              });
+              ```
+
+              An example real-world use case is implementing timeouts:
+
+              ```javascript
+              RSVP.Promise.race([ajax('foo.json'), timeout(5000)])
+              ```
+
+              @method race
+              @static
+              @param {Array} promises array of promises to observe
+              @param {String} label optional string for describing the promise returned.
+              Useful for tooling.
+              @return {Promise} a promise which settles in the same way as the first passed
+              promise to settle.
+            */
+        __exports__['default'] = function race(entries, label) {
+            /*jshint validthis:true */
+            var Constructor = this, entry;
+            var promise = new Constructor(noop, label);
+            if (!isArray(entries)) {
+                reject(promise, new TypeError('You must pass an array to race.'));
+                return promise;
+            }
+            var length = entries.length;
+            function onFulfillment(value) {
+                resolve(promise, value);
+            }
+            function onRejection(reason) {
+                reject(promise, reason);
+            }
+            for (var i = 0; promise._state === PENDING &amp;&amp; i &lt; length; i++) {
+                subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
+            }
+            return promise;
+        };
+    });
+    define('rsvp/promise/reject', [
+    '../-internal',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var noop = __dependency1__.noop;
+        var _reject = __dependency1__.reject;
+        /**
+              `RSVP.Promise.reject` returns a promise rejected with the passed `reason`.
+              It is shorthand for the following:
+
+              ```javascript
+              var promise = new RSVP.Promise(function(resolve, reject){
+                reject(new Error('WHOOPS'));
+              });
+
+              promise.then(function(value){
+                // Code here doesn't run because the promise is rejected!
+              }, function(reason){
+                // reason.message === 'WHOOPS'
+              });
+              ```
+
+              Instead of writing the above, your code now simply becomes the following:
+
+              ```javascript
+              var promise = RSVP.Promise.reject(new Error('WHOOPS'));
+
+              promise.then(function(value){
+                // Code here doesn't run because the promise is rejected!
+              }, function(reason){
+                // reason.message === 'WHOOPS'
+              });
+              ```
+
+              @method reject
+              @static
+              @param {Any} reason value that the returned promise will be rejected with.
+              @param {String} label optional string for identifying the returned promise.
+              Useful for tooling.
+              @return {Promise} a promise rejected with the given `reason`.
+            */
+        __exports__['default'] = function reject(reason, label) {
+            /*jshint validthis:true */
+            var Constructor = this;
+            var promise = new Constructor(noop, label);
+            _reject(promise, reason);
+            return promise;
+        };
+    });
+    define('rsvp/promise/resolve', [
+    '../-internal',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var noop = __dependency1__.noop;
+        var _resolve = __dependency1__.resolve;
+        /**
+              `RSVP.Promise.resolve` returns a promise that will become resolved with the
+              passed `value`. It is shorthand for the following:
+
+              ```javascript
+              var promise = new RSVP.Promise(function(resolve, reject){
+                resolve(1);
+              });
+
+              promise.then(function(value){
+                // value === 1
+              });
+              ```
+
+              Instead of writing the above, your code now simply becomes the following:
+
+              ```javascript
+              var promise = RSVP.Promise.resolve(1);
+
+              promise.then(function(value){
+                // value === 1
+              });
+              ```
+
+              @method resolve
+              @static
+              @param {Any} value value that the returned promise will be resolved with
+              @param {String} label optional string for identifying the returned promise.
+              Useful for tooling.
+              @return {Promise} a promise that will become fulfilled with the given
+              `value`
+            */
+        __exports__['default'] = function resolve(object, label) {
+            /*jshint validthis:true */
+            var Constructor = this;
+            if (object &amp;&amp; typeof object === 'object' &amp;&amp; object.constructor === Constructor) {
+                return object;
+            }
+            var promise = new Constructor(noop, label);
+            _resolve(promise, object);
+            return promise;
+        };
+    });
+    define('rsvp/race', [
+    './promise',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        /**
+              This is a convenient alias for `RSVP.Promise.race`.
+
+              @method race
+              @static
+              @for RSVP
+              @param {Array} array Array of promises.
+              @param {String} label An optional label. This is useful
+              for tooling.
+             */
+        __exports__['default'] = function race(array, label) {
+            return Promise.race(array, label);
+        };
+    });
+    define('rsvp/reject', [
+    './promise',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        /**
+              This is a convenient alias for `RSVP.Promise.reject`.
+
+              @method reject
+              @static
+              @for RSVP
+              @param {Any} reason value that the returned promise will be rejected with.
+              @param {String} label optional string for identifying the returned promise.
+              Useful for tooling.
+              @return {Promise} a promise rejected with the given `reason`.
+            */
+        __exports__['default'] = function reject(reason, label) {
+            return Promise.reject(reason, label);
+        };
+    });
+    define('rsvp/resolve', [
+    './promise',
+    'exports'
+    ], function (__dependency1__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        /**
+              This is a convenient alias for `RSVP.Promise.resolve`.
+
+              @method resolve
+              @static
+              @for RSVP
+              @param {Any} value value that the returned promise will be resolved with
+              @param {String} label optional string for identifying the returned promise.
+              Useful for tooling.
+              @return {Promise} a promise that will become fulfilled with the given
+              `value`
+            */
+        __exports__['default'] = function resolve(value, label) {
+            return Promise.resolve(value, label);
+        };
+    });
+    define('rsvp/rethrow', ['exports'], function (__exports__) {
+        'use strict';
+        /**
+              `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event
+              loop in order to aid debugging.
+
+              Promises A+ specifies that any exceptions that occur with a promise must be
+              caught by the promises implementation and bubbled to the last handler. For
+              this reason, it is recommended that you always specify a second rejection
+              handler function to `then`. However, `RSVP.rethrow` will throw the exception
+              outside of the promise, so it bubbles up to your console if in the browser,
+              or domain/cause uncaught exception in Node. `rethrow` will also throw the
+              error again so the error can be handled by the promise per the spec.
+
+              ```javascript
+              function throws(){
+                throw new Error('Whoops!');
+              }
+
+              var promise = new RSVP.Promise(function(resolve, reject){
+                throws();
+              });
+
+              promise.catch(RSVP.rethrow).then(function(){
+                // Code here doesn't run because the promise became rejected due to an
+                // error!
+              }, function (err){
+                // handle the error here
+              });
+              ```
+
+              The 'Whoops' error will be thrown on the next turn of the event loop
+              and you can watch for it in your console. You can also handle it using a
+              rejection handler given to `.then` or `.catch` on the returned promise.
+
+              @method rethrow
+              @static
+              @for RSVP
+              @param {Error} reason reason the promise became rejected.
+              @throws Error
+              @static
+            */
+        __exports__['default'] = function rethrow(reason) {
+            setTimeout(function () {
+                throw reason;
+            });
+            throw reason;
+        };
+    });
+    define('rsvp/utils', ['exports'], function (__exports__) {
+        'use strict';
+        function objectOrFunction(x) {
+            return typeof x === 'function' || typeof x === 'object' &amp;&amp; x !== null;
+        }
+        __exports__.objectOrFunction = objectOrFunction;
+        function isFunction(x) {
+            return typeof x === 'function';
+        }
+        __exports__.isFunction = isFunction;
+        function isMaybeThenable(x) {
+            return typeof x === 'object' &amp;&amp; x !== null;
+        }
+        __exports__.isMaybeThenable = isMaybeThenable;
+        var _isArray;
+        if (!Array.isArray) {
+            _isArray = function (x) {
+                return Object.prototype.toString.call(x) === '[object Array]';
+            };
+        } else {
+            _isArray = Array.isArray;
+        }
+        var isArray = _isArray;
+        __exports__.isArray = isArray;
+        // Date.now is not available in browsers &lt; IE9
+        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
+        var now = Date.now || function () {
+            return new Date().getTime();
+        };
+        __exports__.now = now;
+        var o_create = Object.create || function (object) {
+            var o = function () {};
+            o.prototype = object;
+            return o;
+        };
+        __exports__.o_create = o_create;
+    });
+    define('rsvp', [
+    './rsvp/promise',
+    './rsvp/events',
+    './rsvp/node',
+    './rsvp/all',
+    './rsvp/all-settled',
+    './rsvp/race',
+    './rsvp/hash',
+    './rsvp/hash-settled',
+    './rsvp/rethrow',
+    './rsvp/defer',
+    './rsvp/config',
+    './rsvp/map',
+    './rsvp/resolve',
+    './rsvp/reject',
+    './rsvp/filter',
+    './rsvp/asap',
+    'exports'
+    ], function (__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
+        'use strict';
+        var Promise = __dependency1__['default'];
+        var EventTarget = __dependency2__['default'];
+        var denodeify = __dependency3__['default'];
+        var all = __dependency4__['default'];
+        var allSettled = __dependency5__['default'];
+        var race = __dependency6__['default'];
+        var hash = __dependency7__['default'];
+        var hashSettled = __dependency8__['default'];
+        var rethrow = __dependency9__['default'];
+        var defer = __dependency10__['default'];
+        var config = __dependency11__.config;
+        var configure = __dependency11__.configure;
+        var map = __dependency12__['default'];
+        var resolve = __dependency13__['default'];
+        var reject = __dependency14__['default'];
+        var filter = __dependency15__['default'];
+        var asap = __dependency16__['default'];
+        config.async = asap;
+        // default async is asap;
+        function async(callback, arg) {
+            config.async(callback, arg);
+        }
+        function on() {
+            config.on.apply(config, arguments);
+        }
+        function off() {
+            config.off.apply(config, arguments);
+        }
+        // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`
+        if (typeof window !== 'undefined' &amp;&amp; typeof window.__PROMISE_INSTRUMENTATION__ === 'object') {
+            var callbacks = window.__PROMISE_INSTRUMENTATION__;
+            configure('instrument', true);
+            for (var eventName in callbacks) {
+                if (callbacks.hasOwnProperty(eventName)) {
+                    on(eventName, callbacks[eventName]);
+                }
+            }
+        }
+        __exports__.Promise = Promise;
+        __exports__.EventTarget = EventTarget;
+        __exports__.all = all;
+        __exports__.allSettled = allSettled;
+        __exports__.race = race;
+        __exports__.hash = hash;
+        __exports__.hashSettled = hashSettled;
+        __exports__.rethrow = rethrow;
+        __exports__.defer = defer;
+        __exports__.denodeify = denodeify;
+        __exports__.configure = configure;
+        __exports__.on = on;
+        __exports__.off = off;
+        __exports__.resolve = resolve;
+        __exports__.reject = reject;
+        __exports__.async = async;
+        __exports__.map = map;
+        __exports__.filter = filter;
+    });
+
+    requireModule(&quot;ember&quot;);
+
+})();
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/ember.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jshandlebarsjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/handlebars.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/handlebars.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/handlebars.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,2746 @@
</span><ins>+/*!
+
+ handlebars v1.3.0
+
+Copyright (C) 2011 by Yehuda Katz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the &quot;Software&quot;), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+@license
+*/
+/* exported Handlebars */
+var Handlebars = (function() {
+// handlebars/safe-string.js
+var __module4__ = (function() {
+  &quot;use strict&quot;;
+  var __exports__;
+  // Build out our basic SafeString type
+  function SafeString(string) {
+    this.string = string;
+  }
+
+  SafeString.prototype.toString = function() {
+    return &quot;&quot; + this.string;
+  };
+
+  __exports__ = SafeString;
+  return __exports__;
+})();
+
+// handlebars/utils.js
+var __module3__ = (function(__dependency1__) {
+  &quot;use strict&quot;;
+  var __exports__ = {};
+  /*jshint -W004 */
+  var SafeString = __dependency1__;
+
+  var escape = {
+    &quot;&amp;&quot;: &quot;&amp;amp;&quot;,
+    &quot;&lt;&quot;: &quot;&amp;lt;&quot;,
+    &quot;&gt;&quot;: &quot;&amp;gt;&quot;,
+    '&quot;': &quot;&amp;quot;&quot;,
+    &quot;'&quot;: &quot;&amp;#x27;&quot;,
+    &quot;`&quot;: &quot;&amp;#x60;&quot;
+  };
+
+  var badChars = /[&amp;&lt;&gt;&quot;'`]/g;
+  var possible = /[&amp;&lt;&gt;&quot;'`]/;
+
+  function escapeChar(chr) {
+    return escape[chr] || &quot;&amp;amp;&quot;;
+  }
+
+  function extend(obj, value) {
+    for(var key in value) {
+      if(Object.prototype.hasOwnProperty.call(value, key)) {
+        obj[key] = value[key];
+      }
+    }
+  }
+
+  __exports__.extend = extend;var toString = Object.prototype.toString;
+  __exports__.toString = toString;
+  // Sourced from lodash
+  // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
+  var isFunction = function(value) {
+    return typeof value === 'function';
+  };
+  // fallback for older versions of Chrome and Safari
+  if (isFunction(/x/)) {
+    isFunction = function(value) {
+      return typeof value === 'function' &amp;&amp; toString.call(value) === '[object Function]';
+    };
+  }
+  var isFunction;
+  __exports__.isFunction = isFunction;
+  var isArray = Array.isArray || function(value) {
+    return (value &amp;&amp; typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
+  };
+  __exports__.isArray = isArray;
+
+  function escapeExpression(string) {
+    // don't escape SafeStrings, since they're already safe
+    if (string instanceof SafeString) {
+      return string.toString();
+    } else if (!string &amp;&amp; string !== 0) {
+      return &quot;&quot;;
+    }
+
+    // Force a string conversion as this will be done by the append regardless and
+    // the regex test will do this transparently behind the scenes, causing issues if
+    // an object's to string has escaped characters in it.
+    string = &quot;&quot; + string;
+
+    if(!possible.test(string)) { return string; }
+    return string.replace(badChars, escapeChar);
+  }
+
+  __exports__.escapeExpression = escapeExpression;function isEmpty(value) {
+    if (!value &amp;&amp; value !== 0) {
+      return true;
+    } else if (isArray(value) &amp;&amp; value.length === 0) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  __exports__.isEmpty = isEmpty;
+  return __exports__;
+})(__module4__);
+
+// handlebars/exception.js
+var __module5__ = (function() {
+  &quot;use strict&quot;;
+  var __exports__;
+
+  var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
+
+  function Exception(message, node) {
+    var line;
+    if (node &amp;&amp; node.firstLine) {
+      line = node.firstLine;
+
+      message += ' - ' + line + ':' + node.firstColumn;
+    }
+
+    var tmp = Error.prototype.constructor.call(this, message);
+
+    // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
+    for (var idx = 0; idx &lt; errorProps.length; idx++) {
+      this[errorProps[idx]] = tmp[errorProps[idx]];
+    }
+
+    if (line) {
+      this.lineNumber = line;
+      this.column = node.firstColumn;
+    }
+  }
+
+  Exception.prototype = new Error();
+
+  __exports__ = Exception;
+  return __exports__;
+})();
+
+// handlebars/base.js
+var __module2__ = (function(__dependency1__, __dependency2__) {
+  &quot;use strict&quot;;
+  var __exports__ = {};
+  var Utils = __dependency1__;
+  var Exception = __dependency2__;
+
+  var VERSION = &quot;1.3.0&quot;;
+  __exports__.VERSION = VERSION;var COMPILER_REVISION = 4;
+  __exports__.COMPILER_REVISION = COMPILER_REVISION;
+  var REVISION_CHANGES = {
+    1: '&lt;= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
+    2: '== 1.0.0-rc.3',
+    3: '== 1.0.0-rc.4',
+    4: '&gt;= 1.0.0'
+  };
+  __exports__.REVISION_CHANGES = REVISION_CHANGES;
+  var isArray = Utils.isArray,
+      isFunction = Utils.isFunction,
+      toString = Utils.toString,
+      objectType = '[object Object]';
+
+  function HandlebarsEnvironment(helpers, partials) {
+    this.helpers = helpers || {};
+    this.partials = partials || {};
+
+    registerDefaultHelpers(this);
+  }
+
+  __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
+    constructor: HandlebarsEnvironment,
+
+    logger: logger,
+    log: log,
+
+    registerHelper: function(name, fn, inverse) {
+      if (toString.call(name) === objectType) {
+        if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
+        Utils.extend(this.helpers, name);
+      } else {
+        if (inverse) { fn.not = inverse; }
+        this.helpers[name] = fn;
+      }
+    },
+
+    registerPartial: function(name, str) {
+      if (toString.call(name) === objectType) {
+        Utils.extend(this.partials,  name);
+      } else {
+        this.partials[name] = str;
+      }
+    }
+  };
+
+  function registerDefaultHelpers(instance) {
+    instance.registerHelper('helperMissing', function(arg) {
+      if(arguments.length === 2) {
+        return undefined;
+      } else {
+        throw new Exception(&quot;Missing helper: '&quot; + arg + &quot;'&quot;);
+      }
+    });
+
+    instance.registerHelper('blockHelperMissing', function(context, options) {
+      var inverse = options.inverse || function() {}, fn = options.fn;
+
+      if (isFunction(context)) { context = context.call(this); }
+
+      if(context === true) {
+        return fn(this);
+      } else if(context === false || context == null) {
+        return inverse(this);
+      } else if (isArray(context)) {
+        if(context.length &gt; 0) {
+          return instance.helpers.each(context, options);
+        } else {
+          return inverse(this);
+        }
+      } else {
+        return fn(context);
+      }
+    });
+
+    instance.registerHelper('each', function(context, options) {
+      var fn = options.fn, inverse = options.inverse;
+      var i = 0, ret = &quot;&quot;, data;
+
+      if (isFunction(context)) { context = context.call(this); }
+
+      if (options.data) {
+        data = createFrame(options.data);
+      }
+
+      if(context &amp;&amp; typeof context === 'object') {
+        if (isArray(context)) {
+          for(var j = context.length; i&lt;j; i++) {
+            if (data) {
+              data.index = i;
+              data.first = (i === 0);
+              data.last  = (i === (context.length-1));
+            }
+            ret = ret + fn(context[i], { data: data });
+          }
+        } else {
+          for(var key in context) {
+            if(context.hasOwnProperty(key)) {
+              if(data) { 
+                data.key = key; 
+                data.index = i;
+                data.first = (i === 0);
+              }
+              ret = ret + fn(context[key], {data: data});
+              i++;
+            }
+          }
+        }
+      }
+
+      if(i === 0){
+        ret = inverse(this);
+      }
+
+      return ret;
+    });
+
+    instance.registerHelper('if', function(conditional, options) {
+      if (isFunction(conditional)) { conditional = conditional.call(this); }
+
+      // Default behavior is to render the positive path if the value is truthy and not empty.
+      // The `includeZero` option may be set to treat the condtional as purely not empty based on the
+      // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
+      if ((!options.hash.includeZero &amp;&amp; !conditional) || Utils.isEmpty(conditional)) {
+        return options.inverse(this);
+      } else {
+        return options.fn(this);
+      }
+    });
+
+    instance.registerHelper('unless', function(conditional, options) {
+      return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
+    });
+
+    instance.registerHelper('with', function(context, options) {
+      if (isFunction(context)) { context = context.call(this); }
+
+      if (!Utils.isEmpty(context)) return options.fn(context);
+    });
+
+    instance.registerHelper('log', function(context, options) {
+      var level = options.data &amp;&amp; options.data.level != null ? parseInt(options.data.level, 10) : 1;
+      instance.log(level, context);
+    });
+  }
+
+  var logger = {
+    methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
+
+    // State enum
+    DEBUG: 0,
+    INFO: 1,
+    WARN: 2,
+    ERROR: 3,
+    level: 3,
+
+    // can be overridden in the host environment
+    log: function(level, obj) {
+      if (logger.level &lt;= level) {
+        var method = logger.methodMap[level];
+        if (typeof console !== 'undefined' &amp;&amp; console[method]) {
+          console[method].call(console, obj);
+        }
+      }
+    }
+  };
+  __exports__.logger = logger;
+  function log(level, obj) { logger.log(level, obj); }
+
+  __exports__.log = log;var createFrame = function(object) {
+    var obj = {};
+    Utils.extend(obj, object);
+    return obj;
+  };
+  __exports__.createFrame = createFrame;
+  return __exports__;
+})(__module3__, __module5__);
+
+// handlebars/runtime.js
+var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
+  &quot;use strict&quot;;
+  var __exports__ = {};
+  var Utils = __dependency1__;
+  var Exception = __dependency2__;
+  var COMPILER_REVISION = __dependency3__.COMPILER_REVISION;
+  var REVISION_CHANGES = __dependency3__.REVISION_CHANGES;
+
+  function checkRevision(compilerInfo) {
+    var compilerRevision = compilerInfo &amp;&amp; compilerInfo[0] || 1,
+        currentRevision = COMPILER_REVISION;
+
+    if (compilerRevision !== currentRevision) {
+      if (compilerRevision &lt; currentRevision) {
+        var runtimeVersions = REVISION_CHANGES[currentRevision],
+            compilerVersions = REVISION_CHANGES[compilerRevision];
+        throw new Exception(&quot;Template was precompiled with an older version of Handlebars than the current runtime. &quot;+
+              &quot;Please update your precompiler to a newer version (&quot;+runtimeVersions+&quot;) or downgrade your runtime to an older version (&quot;+compilerVersions+&quot;).&quot;);
+      } else {
+        // Use the embedded version info since the runtime doesn't know about this revision yet
+        throw new Exception(&quot;Template was precompiled with a newer version of Handlebars than the current runtime. &quot;+
+              &quot;Please update your runtime to a newer version (&quot;+compilerInfo[1]+&quot;).&quot;);
+      }
+    }
+  }
+
+  __exports__.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
+
+  function template(templateSpec, env) {
+    if (!env) {
+      throw new Exception(&quot;No environment passed to template&quot;);
+    }
+
+    // Note: Using env.VM references rather than local var references throughout this section to allow
+    // for external users to override these as psuedo-supported APIs.
+    var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
+      var result = env.VM.invokePartial.apply(this, arguments);
+      if (result != null) { return result; }
+
+      if (env.compile) {
+        var options = { helpers: helpers, partials: partials, data: data };
+        partials[name] = env.compile(partial, { data: data !== undefined }, env);
+        return partials[name](context, options);
+      } else {
+        throw new Exception(&quot;The partial &quot; + name + &quot; could not be compiled when running in runtime-only mode&quot;);
+      }
+    };
+
+    // Just add water
+    var container = {
+      escapeExpression: Utils.escapeExpression,
+      invokePartial: invokePartialWrapper,
+      programs: [],
+      program: function(i, fn, data) {
+        var programWrapper = this.programs[i];
+        if(data) {
+          programWrapper = program(i, fn, data);
+        } else if (!programWrapper) {
+          programWrapper = this.programs[i] = program(i, fn);
+        }
+        return programWrapper;
+      },
+      merge: function(param, common) {
+        var ret = param || common;
+
+        if (param &amp;&amp; common &amp;&amp; (param !== common)) {
+          ret = {};
+          Utils.extend(ret, common);
+          Utils.extend(ret, param);
+        }
+        return ret;
+      },
+      programWithDepth: env.VM.programWithDepth,
+      noop: env.VM.noop,
+      compilerInfo: null
+    };
+
+    return function(context, options) {
+      options = options || {};
+      var namespace = options.partial ? options : env,
+          helpers,
+          partials;
+
+      if (!options.partial) {
+        helpers = options.helpers;
+        partials = options.partials;
+      }
+      var result = templateSpec.call(
+            container,
+            namespace, context,
+            helpers,
+            partials,
+            options.data);
+
+      if (!options.partial) {
+        env.VM.checkRevision(container.compilerInfo);
+      }
+
+      return result;
+    };
+  }
+
+  __exports__.template = template;function programWithDepth(i, fn, data /*, $depth */) {
+    var args = Array.prototype.slice.call(arguments, 3);
+
+    var prog = function(context, options) {
+      options = options || {};
+
+      return fn.apply(this, [context, options.data || data].concat(args));
+    };
+    prog.program = i;
+    prog.depth = args.length;
+    return prog;
+  }
+
+  __exports__.programWithDepth = programWithDepth;function program(i, fn, data) {
+    var prog = function(context, options) {
+      options = options || {};
+
+      return fn(context, options.data || data);
+    };
+    prog.program = i;
+    prog.depth = 0;
+    return prog;
+  }
+
+  __exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data) {
+    var options = { partial: true, helpers: helpers, partials: partials, data: data };
+
+    if(partial === undefined) {
+      throw new Exception(&quot;The partial &quot; + name + &quot; could not be found&quot;);
+    } else if(partial instanceof Function) {
+      return partial(context, options);
+    }
+  }
+
+  __exports__.invokePartial = invokePartial;function noop() { return &quot;&quot;; }
+
+  __exports__.noop = noop;
+  return __exports__;
+})(__module3__, __module5__, __module2__);
+
+// handlebars.runtime.js
+var __module1__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
+  &quot;use strict&quot;;
+  var __exports__;
+  /*globals Handlebars: true */
+  var base = __dependency1__;
+
+  // Each of these augment the Handlebars object. No need to setup here.
+  // (This is done to easily share code between commonjs and browse envs)
+  var SafeString = __dependency2__;
+  var Exception = __dependency3__;
+  var Utils = __dependency4__;
+  var runtime = __dependency5__;
+
+  // For compatibility and usage outside of module systems, make the Handlebars object a namespace
+  var create = function() {
+    var hb = new base.HandlebarsEnvironment();
+
+    Utils.extend(hb, base);
+    hb.SafeString = SafeString;
+    hb.Exception = Exception;
+    hb.Utils = Utils;
+
+    hb.VM = runtime;
+    hb.template = function(spec) {
+      return runtime.template(spec, hb);
+    };
+
+    return hb;
+  };
+
+  var Handlebars = create();
+  Handlebars.create = create;
+
+  __exports__ = Handlebars;
+  return __exports__;
+})(__module2__, __module4__, __module5__, __module3__, __module6__);
+
+// handlebars/compiler/ast.js
+var __module7__ = (function(__dependency1__) {
+  &quot;use strict&quot;;
+  var __exports__;
+  var Exception = __dependency1__;
+
+  function LocationInfo(locInfo){
+    locInfo = locInfo || {};
+    this.firstLine   = locInfo.first_line;
+    this.firstColumn = locInfo.first_column;
+    this.lastColumn  = locInfo.last_column;
+    this.lastLine    = locInfo.last_line;
+  }
+
+  var AST = {
+    ProgramNode: function(statements, inverseStrip, inverse, locInfo) {
+      var inverseLocationInfo, firstInverseNode;
+      if (arguments.length === 3) {
+        locInfo = inverse;
+        inverse = null;
+      } else if (arguments.length === 2) {
+        locInfo = inverseStrip;
+        inverseStrip = null;
+      }
+
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;program&quot;;
+      this.statements = statements;
+      this.strip = {};
+
+      if(inverse) {
+        firstInverseNode = inverse[0];
+        if (firstInverseNode) {
+          inverseLocationInfo = {
+            first_line: firstInverseNode.firstLine,
+            last_line: firstInverseNode.lastLine,
+            last_column: firstInverseNode.lastColumn,
+            first_column: firstInverseNode.firstColumn
+          };
+          this.inverse = new AST.ProgramNode(inverse, inverseStrip, inverseLocationInfo);
+        } else {
+          this.inverse = new AST.ProgramNode(inverse, inverseStrip);
+        }
+        this.strip.right = inverseStrip.left;
+      } else if (inverseStrip) {
+        this.strip.left = inverseStrip.right;
+      }
+    },
+
+    MustacheNode: function(rawParams, hash, open, strip, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;mustache&quot;;
+      this.strip = strip;
+
+      // Open may be a string parsed from the parser or a passed boolean flag
+      if (open != null &amp;&amp; open.charAt) {
+        // Must use charAt to support IE pre-10
+        var escapeFlag = open.charAt(3) || open.charAt(2);
+        this.escaped = escapeFlag !== '{' &amp;&amp; escapeFlag !== '&amp;';
+      } else {
+        this.escaped = !!open;
+      }
+
+      if (rawParams instanceof AST.SexprNode) {
+        this.sexpr = rawParams;
+      } else {
+        // Support old AST API
+        this.sexpr = new AST.SexprNode(rawParams, hash);
+      }
+
+      this.sexpr.isRoot = true;
+
+      // Support old AST API that stored this info in MustacheNode
+      this.id = this.sexpr.id;
+      this.params = this.sexpr.params;
+      this.hash = this.sexpr.hash;
+      this.eligibleHelper = this.sexpr.eligibleHelper;
+      this.isHelper = this.sexpr.isHelper;
+    },
+
+    SexprNode: function(rawParams, hash, locInfo) {
+      LocationInfo.call(this, locInfo);
+
+      this.type = &quot;sexpr&quot;;
+      this.hash = hash;
+
+      var id = this.id = rawParams[0];
+      var params = this.params = rawParams.slice(1);
+
+      // a mustache is an eligible helper if:
+      // * its id is simple (a single part, not `this` or `..`)
+      var eligibleHelper = this.eligibleHelper = id.isSimple;
+
+      // a mustache is definitely a helper if:
+      // * it is an eligible helper, and
+      // * it has at least one parameter or hash segment
+      this.isHelper = eligibleHelper &amp;&amp; (params.length || hash);
+
+      // if a mustache is an eligible helper but not a definite
+      // helper, it is ambiguous, and will be resolved in a later
+      // pass or at runtime.
+    },
+
+    PartialNode: function(partialName, context, strip, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type         = &quot;partial&quot;;
+      this.partialName  = partialName;
+      this.context      = context;
+      this.strip = strip;
+    },
+
+    BlockNode: function(mustache, program, inverse, close, locInfo) {
+      LocationInfo.call(this, locInfo);
+
+      if(mustache.sexpr.id.original !== close.path.original) {
+        throw new Exception(mustache.sexpr.id.original + &quot; doesn't match &quot; + close.path.original, this);
+      }
+
+      this.type = 'block';
+      this.mustache = mustache;
+      this.program  = program;
+      this.inverse  = inverse;
+
+      this.strip = {
+        left: mustache.strip.left,
+        right: close.strip.right
+      };
+
+      (program || inverse).strip.left = mustache.strip.right;
+      (inverse || program).strip.right = close.strip.left;
+
+      if (inverse &amp;&amp; !program) {
+        this.isInverse = true;
+      }
+    },
+
+    ContentNode: function(string, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;content&quot;;
+      this.string = string;
+    },
+
+    HashNode: function(pairs, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;hash&quot;;
+      this.pairs = pairs;
+    },
+
+    IdNode: function(parts, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;ID&quot;;
+
+      var original = &quot;&quot;,
+          dig = [],
+          depth = 0;
+
+      for(var i=0,l=parts.length; i&lt;l; i++) {
+        var part = parts[i].part;
+        original += (parts[i].separator || '') + part;
+
+        if (part === &quot;..&quot; || part === &quot;.&quot; || part === &quot;this&quot;) {
+          if (dig.length &gt; 0) {
+            throw new Exception(&quot;Invalid path: &quot; + original, this);
+          } else if (part === &quot;..&quot;) {
+            depth++;
+          } else {
+            this.isScoped = true;
+          }
+        } else {
+          dig.push(part);
+        }
+      }
+
+      this.original = original;
+      this.parts    = dig;
+      this.string   = dig.join('.');
+      this.depth    = depth;
+
+      // an ID is simple if it only has one part, and that part is not
+      // `..` or `this`.
+      this.isSimple = parts.length === 1 &amp;&amp; !this.isScoped &amp;&amp; depth === 0;
+
+      this.stringModeValue = this.string;
+    },
+
+    PartialNameNode: function(name, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;PARTIAL_NAME&quot;;
+      this.name = name.original;
+    },
+
+    DataNode: function(id, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;DATA&quot;;
+      this.id = id;
+    },
+
+    StringNode: function(string, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;STRING&quot;;
+      this.original =
+        this.string =
+        this.stringModeValue = string;
+    },
+
+    IntegerNode: function(integer, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;INTEGER&quot;;
+      this.original =
+        this.integer = integer;
+      this.stringModeValue = Number(integer);
+    },
+
+    BooleanNode: function(bool, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;BOOLEAN&quot;;
+      this.bool = bool;
+      this.stringModeValue = bool === &quot;true&quot;;
+    },
+
+    CommentNode: function(comment, locInfo) {
+      LocationInfo.call(this, locInfo);
+      this.type = &quot;comment&quot;;
+      this.comment = comment;
+    }
+  };
+
+  // Must be exported as an object rather than the root of the module as the jison lexer
+  // most modify the object to operate properly.
+  __exports__ = AST;
+  return __exports__;
+})(__module5__);
+
+// handlebars/compiler/parser.js
+var __module9__ = (function() {
+  &quot;use strict&quot;;
+  var __exports__;
+  /* jshint ignore:start */
+  /* Jison generated parser */
+  var handlebars = (function(){
+  var parser = {trace: function trace() { },
+  yy: {},
+  symbols_: {&quot;error&quot;:2,&quot;root&quot;:3,&quot;statements&quot;:4,&quot;EOF&quot;:5,&quot;program&quot;:6,&quot;simpleInverse&quot;:7,&quot;statement&quot;:8,&quot;openInverse&quot;:9,&quot;closeBlock&quot;:10,&quot;openBlock&quot;:11,&quot;mustache&quot;:12,&quot;partial&quot;:13,&quot;CONTENT&quot;:14,&quot;COMMENT&quot;:15,&quot;OPEN_BLOCK&quot;:16,&quot;sexpr&quot;:17,&quot;CLOSE&quot;:18,&quot;OPEN_INVERSE&quot;:19,&quot;OPEN_ENDBLOCK&quot;:20,&quot;path&quot;:21,&quot;OPEN&quot;:22,&quot;OPEN_UNESCAPED&quot;:23,&quot;CLOSE_UNESCAPED&quot;:24,&quot;OPEN_PARTIAL&quot;:25,&quot;partialName&quot;:26,&quot;partial_option0&quot;:27,&quot;sexpr_repetition0&quot;:28,&quot;sexpr_option0&quot;:29,&quot;dataName&quot;:30,&quot;param&quot;:31,&quot;STRING&quot;:32,&quot;INTEGER&quot;:33,&quot;BOOLEAN&quot;:34,&quot;OPEN_SEXPR&quot;:35,&quot;CLOSE_SEXPR&quot;:36,&quot;hash&quot;:37,&quot;hash_repetition_plus0&quot;:38,&quot;hashSegment&quot;:39,&quot;ID&quot;:40,&quot;EQUALS&quot;:41,&quot;DATA&quot;:42,&quot;pathSegments&quot;:43,&quot;SEP&quot;:44,&quot;$accept&quot;:0,&quot;$end&quot;:1},
+  terminals_: {2:&quot;error&quot;,5:&quot;EOF&quot;,14:&quot;CONTENT&quot;,15:&quot;COMMENT&quot;,16:&quot;OPEN_BLOCK&quot;,18:&quot;CLOSE&quot;,19:&quot;OPEN_INVERSE&quot;,20:&quot;OPEN_ENDBLOCK&quot;,22:&quot;OPEN&quot;,23:&quot;OPEN_UNESCAPED&quot;,24:&quot;CLOSE_UNESCAPED&quot;,25:&quot;OPEN_PARTIAL&quot;,32:&quot;STRING&quot;,33:&quot;INTEGER&quot;,34:&quot;BOOLEAN&quot;,35:&quot;OPEN_SEXPR&quot;,36:&quot;CLOSE_SEXPR&quot;,40:&quot;ID&quot;,41:&quot;EQUALS&quot;,42:&quot;DATA&quot;,44:&quot;SEP&quot;},
+  productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]],
+  performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
+
+  var $0 = $$.length - 1;
+  switch (yystate) {
+  case 1: return new yy.ProgramNode($$[$0-1], this._$); 
+  break;
+  case 2: return new yy.ProgramNode([], this._$); 
+  break;
+  case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0], this._$);
+  break;
+  case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0], this._$);
+  break;
+  case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], [], this._$);
+  break;
+  case 6:this.$ = new yy.ProgramNode($$[$0], this._$);
+  break;
+  case 7:this.$ = new yy.ProgramNode([], this._$);
+  break;
+  case 8:this.$ = new yy.ProgramNode([], this._$);
+  break;
+  case 9:this.$ = [$$[$0]];
+  break;
+  case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; 
+  break;
+  case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0], this._$);
+  break;
+  case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0], this._$);
+  break;
+  case 13:this.$ = $$[$0];
+  break;
+  case 14:this.$ = $$[$0];
+  break;
+  case 15:this.$ = new yy.ContentNode($$[$0], this._$);
+  break;
+  case 16:this.$ = new yy.CommentNode($$[$0], this._$);
+  break;
+  case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
+  break;
+  case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
+  break;
+  case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])};
+  break;
+  case 20:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
+  break;
+  case 21:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
+  break;
+  case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]), this._$);
+  break;
+  case 23:this.$ = stripFlags($$[$0-1], $$[$0]);
+  break;
+  case 24:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$);
+  break;
+  case 25:this.$ = new yy.SexprNode([$$[$0]], null, this._$);
+  break;
+  case 26:this.$ = $$[$0];
+  break;
+  case 27:this.$ = new yy.StringNode($$[$0], this._$);
+  break;
+  case 28:this.$ = new yy.IntegerNode($$[$0], this._$);
+  break;
+  case 29:this.$ = new yy.BooleanNode($$[$0], this._$);
+  break;
+  case 30:this.$ = $$[$0];
+  break;
+  case 31:$$[$0-1].isHelper = true; this.$ = $$[$0-1];
+  break;
+  case 32:this.$ = new yy.HashNode($$[$0], this._$);
+  break;
+  case 33:this.$ = [$$[$0-2], $$[$0]];
+  break;
+  case 34:this.$ = new yy.PartialNameNode($$[$0], this._$);
+  break;
+  case 35:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$);
+  break;
+  case 36:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0], this._$));
+  break;
+  case 37:this.$ = new yy.DataNode($$[$0], this._$);
+  break;
+  case 38:this.$ = new yy.IdNode($$[$0], this._$);
+  break;
+  case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; 
+  break;
+  case 40:this.$ = [{part: $$[$0]}];
+  break;
+  case 43:this.$ = [];
+  break;
+  case 44:$$[$0-1].push($$[$0]);
+  break;
+  case 47:this.$ = [$$[$0]];
+  break;
+  case 48:$$[$0-1].push($$[$0]);
+  break;
+  }
+  },
+  table: [{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:29,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:30,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:31,21:24,30:25,40:[1,28],42:[1,27],43:26},{21:33,26:32,32:[1,34],33:[1,35],40:[1,28],43:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,40:[1,28],42:[1,27],43:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,43],24:[2,43],28:43,32:[2,43],33:[2,43],34:[2,43],35:[2,43],36:[2,43],40:[2,43],42:[2,43]},{18:[2,25],24:[2,25],36:[2,25]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],35:[2,38],36:[2,38],40:[2,38],42:[2,38],44:[1,44]},{21:45,40:[1,28],43:26},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],42:[2,40],44:[2,40]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,41],21:50,27:49,40:[1,28],43:26},{18:[2,34],40:[2,34]},{18:[2,35],40:[2,35]},{18:[2,36],40:[2,36]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,40:[1,28],43:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,45],21:56,24:[2,45],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:[1,61],36:[2,45],37:55,38:62,39:63,40:[1,64],42:[1,27],43:26},{40:[1,65]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],35:[2,37],36:[2,37],40:[2,37],42:[2,37]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,66]},{18:[2,42]},{18:[1,67]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24],36:[2,24]},{18:[2,44],24:[2,44],32:[2,44],33:[2,44],34:[2,44],35:[2,44],36:[2,44],40:[2,44],42:[2,44]},{18:[2,46],24:[2,46],36:[2,46]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],35:[2,26],36:[2,26],40:[2,26],42:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],35:[2,27],36:[2,27],40:[2,27],42:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],35:[2,28],36:[2,28],40:[2,28],42:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],35:[2,29],36:[2,29],40:[2,29],42:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],35:[2,30],36:[2,30],40:[2,30],42:[2,30]},{17:68,21:24,30:25,40:[1,28],42:[1,27],43:26},{18:[2,32],24:[2,32],36:[2,32],39:69,40:[1,70]},{18:[2,47],24:[2,47],36:[2,47],40:[2,47]},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],41:[1,71],42:[2,40],44:[2,40]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],35:[2,39],36:[2,39],40:[2,39],42:[2,39],44:[2,39]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{36:[1,72]},{18:[2,48],24:[2,48],36:[2,48],40:[2,48]},{41:[1,71]},{21:56,30:60,31:73,32:[1,57],33:[1,58],34:[1,59],35:[1,61],40:[1,28],42:[1,27],43:26},{18:[2,31],24:[2,31],32:[2,31],33:[2,31],34:[2,31],35:[2,31],36:[2,31],40:[2,31],42:[2,31]},{18:[2,33],24:[2,33],36:[2,33],40:[2,33]}],
+  defaultActions: {3:[2,2],16:[2,1],50:[2,42]},
+  parseError: function parseError(str, hash) {
+      throw new Error(str);
+  },
+  parse: function parse(input) {
+      var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = &quot;&quot;, yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
+      this.lexer.setInput(input);
+      this.lexer.yy = this.yy;
+      this.yy.lexer = this.lexer;
+      this.yy.parser = this;
+      if (typeof this.lexer.yylloc == &quot;undefined&quot;)
+          this.lexer.yylloc = {};
+      var yyloc = this.lexer.yylloc;
+      lstack.push(yyloc);
+      var ranges = this.lexer.options &amp;&amp; this.lexer.options.ranges;
+      if (typeof this.yy.parseError === &quot;function&quot;)
+          this.parseError = this.yy.parseError;
+      function popStack(n) {
+          stack.length = stack.length - 2 * n;
+          vstack.length = vstack.length - n;
+          lstack.length = lstack.length - n;
+      }
+      function lex() {
+          var token;
+          token = self.lexer.lex() || 1;
+          if (typeof token !== &quot;number&quot;) {
+              token = self.symbols_[token] || token;
+          }
+          return token;
+      }
+      var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
+      while (true) {
+          state = stack[stack.length - 1];
+          if (this.defaultActions[state]) {
+              action = this.defaultActions[state];
+          } else {
+              if (symbol === null || typeof symbol == &quot;undefined&quot;) {
+                  symbol = lex();
+              }
+              action = table[state] &amp;&amp; table[state][symbol];
+          }
+          if (typeof action === &quot;undefined&quot; || !action.length || !action[0]) {
+              var errStr = &quot;&quot;;
+              if (!recovering) {
+                  expected = [];
+                  for (p in table[state])
+                      if (this.terminals_[p] &amp;&amp; p &gt; 2) {
+                          expected.push(&quot;'&quot; + this.terminals_[p] + &quot;'&quot;);
+                      }
+                  if (this.lexer.showPosition) {
+                      errStr = &quot;Parse error on line &quot; + (yylineno + 1) + &quot;:\n&quot; + this.lexer.showPosition() + &quot;\nExpecting &quot; + expected.join(&quot;, &quot;) + &quot;, got '&quot; + (this.terminals_[symbol] || symbol) + &quot;'&quot;;
+                  } else {
+                      errStr = &quot;Parse error on line &quot; + (yylineno + 1) + &quot;: Unexpected &quot; + (symbol == 1?&quot;end of input&quot;:&quot;'&quot; + (this.terminals_[symbol] || symbol) + &quot;'&quot;);
+                  }
+                  this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
+              }
+          }
+          if (action[0] instanceof Array &amp;&amp; action.length &gt; 1) {
+              throw new Error(&quot;Parse Error: multiple actions possible at state: &quot; + state + &quot;, token: &quot; + symbol);
+          }
+          switch (action[0]) {
+          case 1:
+              stack.push(symbol);
+              vstack.push(this.lexer.yytext);
+              lstack.push(this.lexer.yylloc);
+              stack.push(action[1]);
+              symbol = null;
+              if (!preErrorSymbol) {
+                  yyleng = this.lexer.yyleng;
+                  yytext = this.lexer.yytext;
+                  yylineno = this.lexer.yylineno;
+                  yyloc = this.lexer.yylloc;
+                  if (recovering &gt; 0)
+                      recovering--;
+              } else {
+                  symbol = preErrorSymbol;
+                  preErrorSymbol = null;
+              }
+              break;
+          case 2:
+              len = this.productions_[action[1]][1];
+              yyval.$ = vstack[vstack.length - len];
+              yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
+              if (ranges) {
+                  yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
+              }
+              r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+              if (typeof r !== &quot;undefined&quot;) {
+                  return r;
+              }
+              if (len) {
+                  stack = stack.slice(0, -1 * len * 2);
+                  vstack = vstack.slice(0, -1 * len);
+                  lstack = lstack.slice(0, -1 * len);
+              }
+              stack.push(this.productions_[action[1]][0]);
+              vstack.push(yyval.$);
+              lstack.push(yyval._$);
+              newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+              stack.push(newState);
+              break;
+          case 3:
+              return true;
+          }
+      }
+      return true;
+  }
+  };
+
+
+  function stripFlags(open, close) {
+    return {
+      left: open.charAt(2) === '~',
+      right: close.charAt(0) === '~' || close.charAt(1) === '~'
+    };
+  }
+
+  /* Jison generated lexer */
+  var lexer = (function(){
+  var lexer = ({EOF:1,
+  parseError:function parseError(str, hash) {
+          if (this.yy.parser) {
+              this.yy.parser.parseError(str, hash);
+          } else {
+              throw new Error(str);
+          }
+      },
+  setInput:function (input) {
+          this._input = input;
+          this._more = this._less = this.done = false;
+          this.yylineno = this.yyleng = 0;
+          this.yytext = this.matched = this.match = '';
+          this.conditionStack = ['INITIAL'];
+          this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
+          if (this.options.ranges) this.yylloc.range = [0,0];
+          this.offset = 0;
+          return this;
+      },
+  input:function () {
+          var ch = this._input[0];
+          this.yytext += ch;
+          this.yyleng++;
+          this.offset++;
+          this.match += ch;
+          this.matched += ch;
+          var lines = ch.match(/(?:\r\n?|\n).*/g);
+          if (lines) {
+              this.yylineno++;
+              this.yylloc.last_line++;
+          } else {
+              this.yylloc.last_column++;
+          }
+          if (this.options.ranges) this.yylloc.range[1]++;
+
+          this._input = this._input.slice(1);
+          return ch;
+      },
+  unput:function (ch) {
+          var len = ch.length;
+          var lines = ch.split(/(?:\r\n?|\n)/g);
+
+          this._input = ch + this._input;
+          this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
+          //this.yyleng -= len;
+          this.offset -= len;
+          var oldLines = this.match.split(/(?:\r\n?|\n)/g);
+          this.match = this.match.substr(0, this.match.length-1);
+          this.matched = this.matched.substr(0, this.matched.length-1);
+
+          if (lines.length-1) this.yylineno -= lines.length-1;
+          var r = this.yylloc.range;
+
+          this.yylloc = {first_line: this.yylloc.first_line,
+            last_line: this.yylineno+1,
+            first_column: this.yylloc.first_column,
+            last_column: lines ?
+                (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
+                this.yylloc.first_column - len
+            };
+
+          if (this.options.ranges) {
+              this.yylloc.range = [r[0], r[0] + this.yyleng - len];
+          }
+          return this;
+      },
+  more:function () {
+          this._more = true;
+          return this;
+      },
+  less:function (n) {
+          this.unput(this.match.slice(n));
+      },
+  pastInput:function () {
+          var past = this.matched.substr(0, this.matched.length - this.match.length);
+          return (past.length &gt; 20 ? '...':'') + past.substr(-20).replace(/\n/g, &quot;&quot;);
+      },
+  upcomingInput:function () {
+          var next = this.match;
+          if (next.length &lt; 20) {
+              next += this._input.substr(0, 20-next.length);
+          }
+          return (next.substr(0,20)+(next.length &gt; 20 ? '...':'')).replace(/\n/g, &quot;&quot;);
+      },
+  showPosition:function () {
+          var pre = this.pastInput();
+          var c = new Array(pre.length + 1).join(&quot;-&quot;);
+          return pre + this.upcomingInput() + &quot;\n&quot; + c+&quot;^&quot;;
+      },
+  next:function () {
+          if (this.done) {
+              return this.EOF;
+          }
+          if (!this._input) this.done = true;
+
+          var token,
+              match,
+              tempMatch,
+              index,
+              col,
+              lines;
+          if (!this._more) {
+              this.yytext = '';
+              this.match = '';
+          }
+          var rules = this._currentRules();
+          for (var i=0;i &lt; rules.length; i++) {
+              tempMatch = this._input.match(this.rules[rules[i]]);
+              if (tempMatch &amp;&amp; (!match || tempMatch[0].length &gt; match[0].length)) {
+                  match = tempMatch;
+                  index = i;
+                  if (!this.options.flex) break;
+              }
+          }
+          if (match) {
+              lines = match[0].match(/(?:\r\n?|\n).*/g);
+              if (lines) this.yylineno += lines.length;
+              this.yylloc = {first_line: this.yylloc.last_line,
+                             last_line: this.yylineno+1,
+                             first_column: this.yylloc.last_column,
+                             last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
+              this.yytext += match[0];
+              this.match += match[0];
+              this.matches = match;
+              this.yyleng = this.yytext.length;
+              if (this.options.ranges) {
+                  this.yylloc.range = [this.offset, this.offset += this.yyleng];
+              }
+              this._more = false;
+              this._input = this._input.slice(match[0].length);
+              this.matched += match[0];
+              token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
+              if (this.done &amp;&amp; this._input) this.done = false;
+              if (token) return token;
+              else return;
+          }
+          if (this._input === &quot;&quot;) {
+              return this.EOF;
+          } else {
+              return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
+                      {text: &quot;&quot;, token: null, line: this.yylineno});
+          }
+      },
+  lex:function lex() {
+          var r = this.next();
+          if (typeof r !== 'undefined') {
+              return r;
+          } else {
+              return this.lex();
+          }
+      },
+  begin:function begin(condition) {
+          this.conditionStack.push(condition);
+      },
+  popState:function popState() {
+          return this.conditionStack.pop();
+      },
+  _currentRules:function _currentRules() {
+          return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
+      },
+  topState:function () {
+          return this.conditionStack[this.conditionStack.length-2];
+      },
+  pushState:function begin(condition) {
+          this.begin(condition);
+      }});
+  lexer.options = {};
+  lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
+
+
+  function strip(start, end) {
+    return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end);
+  }
+
+
+  var YYSTATE=YY_START
+  switch($avoiding_name_collisions) {
+  case 0:
+                                     if(yy_.yytext.slice(-2) === &quot;\\\\&quot;) {
+                                       strip(0,1);
+                                       this.begin(&quot;mu&quot;);
+                                     } else if(yy_.yytext.slice(-1) === &quot;\\&quot;) {
+                                       strip(0,1);
+                                       this.begin(&quot;emu&quot;);
+                                     } else {
+                                       this.begin(&quot;mu&quot;);
+                                     }
+                                     if(yy_.yytext) return 14;
+                                   
+  break;
+  case 1:return 14;
+  break;
+  case 2:
+                                     this.popState();
+                                     return 14;
+                                   
+  break;
+  case 3:strip(0,4); this.popState(); return 15;
+  break;
+  case 4:return 35;
+  break;
+  case 5:return 36;
+  break;
+  case 6:return 25;
+  break;
+  case 7:return 16;
+  break;
+  case 8:return 20;
+  break;
+  case 9:return 19;
+  break;
+  case 10:return 19;
+  break;
+  case 11:return 23;
+  break;
+  case 12:return 22;
+  break;
+  case 13:this.popState(); this.begin('com');
+  break;
+  case 14:strip(3,5); this.popState(); return 15;
+  break;
+  case 15:return 22;
+  break;
+  case 16:return 41;
+  break;
+  case 17:return 40;
+  break;
+  case 18:return 40;
+  break;
+  case 19:return 44;
+  break;
+  case 20:// ignore whitespace
+  break;
+  case 21:this.popState(); return 24;
+  break;
+  case 22:this.popState(); return 18;
+  break;
+  case 23:yy_.yytext = strip(1,2).replace(/\\&quot;/g,'&quot;'); return 32;
+  break;
+  case 24:yy_.yytext = strip(1,2).replace(/\\'/g,&quot;'&quot;); return 32;
+  break;
+  case 25:return 42;
+  break;
+  case 26:return 34;
+  break;
+  case 27:return 34;
+  break;
+  case 28:return 33;
+  break;
+  case 29:return 40;
+  break;
+  case 30:yy_.yytext = strip(1,2); return 40;
+  break;
+  case 31:return 'INVALID';
+  break;
+  case 32:return 5;
+  break;
+  }
+  };
+  lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?&gt;)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&amp;)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:&quot;(\\[&quot;]|[^&quot;])*&quot;)/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?=([~}\s)])))/,/^(?:([^\s!&quot;#%-,\.\/;-&gt;@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
+  lexer.conditions = {&quot;mu&quot;:{&quot;rules&quot;:[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],&quot;inclusive&quot;:false},&quot;emu&quot;:{&quot;rules&quot;:[2],&quot;inclusive&quot;:false},&quot;com&quot;:{&quot;rules&quot;:[3],&quot;inclusive&quot;:false},&quot;INITIAL&quot;:{&quot;rules&quot;:[0,1,32],&quot;inclusive&quot;:true}};
+  return lexer;})()
+  parser.lexer = lexer;
+  function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
+  return new Parser;
+  })();__exports__ = handlebars;
+  /* jshint ignore:end */
+  return __exports__;
+})();
+
+// handlebars/compiler/base.js
+var __module8__ = (function(__dependency1__, __dependency2__) {
+  &quot;use strict&quot;;
+  var __exports__ = {};
+  var parser = __dependency1__;
+  var AST = __dependency2__;
+
+  __exports__.parser = parser;
+
+  function parse(input) {
+    // Just return if an already-compile AST was passed in.
+    if(input.constructor === AST.ProgramNode) { return input; }
+
+    parser.yy = AST;
+    return parser.parse(input);
+  }
+
+  __exports__.parse = parse;
+  return __exports__;
+})(__module9__, __module7__);
+
+// handlebars/compiler/compiler.js
+var __module10__ = (function(__dependency1__) {
+  &quot;use strict&quot;;
+  var __exports__ = {};
+  var Exception = __dependency1__;
+
+  function Compiler() {}
+
+  __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
+  // function in a context. This is necessary for mustache compatibility, which
+  // requires that context functions in blocks are evaluated by blockHelperMissing,
+  // and then proceed as if the resulting value was provided to blockHelperMissing.
+
+  Compiler.prototype = {
+    compiler: Compiler,
+
+    disassemble: function() {
+      var opcodes = this.opcodes, opcode, out = [], params, param;
+
+      for (var i=0, l=opcodes.length; i&lt;l; i++) {
+        opcode = opcodes[i];
+
+        if (opcode.opcode === 'DECLARE') {
+          out.push(&quot;DECLARE &quot; + opcode.name + &quot;=&quot; + opcode.value);
+        } else {
+          params = [];
+          for (var j=0; j&lt;opcode.args.length; j++) {
+            param = opcode.args[j];
+            if (typeof param === &quot;string&quot;) {
+              param = &quot;\&quot;&quot; + param.replace(&quot;\n&quot;, &quot;\\n&quot;) + &quot;\&quot;&quot;;
+            }
+            params.push(param);
+          }
+          out.push(opcode.opcode + &quot; &quot; + params.join(&quot; &quot;));
+        }
+      }
+
+      return out.join(&quot;\n&quot;);
+    },
+
+    equals: function(other) {
+      var len = this.opcodes.length;
+      if (other.opcodes.length !== len) {
+        return false;
+      }
+
+      for (var i = 0; i &lt; len; i++) {
+        var opcode = this.opcodes[i],
+            otherOpcode = other.opcodes[i];
+        if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
+          return false;
+        }
+        for (var j = 0; j &lt; opcode.args.length; j++) {
+          if (opcode.args[j] !== otherOpcode.args[j]) {
+            return false;
+          }
+        }
+      }
+
+      len = this.children.length;
+      if (other.children.length !== len) {
+        return false;
+      }
+      for (i = 0; i &lt; len; i++) {
+        if (!this.children[i].equals(other.children[i])) {
+          return false;
+        }
+      }
+
+      return true;
+    },
+
+    guid: 0,
+
+    compile: function(program, options) {
+      this.opcodes = [];
+      this.children = [];
+      this.depths = {list: []};
+      this.options = options;
+
+      // These changes will propagate to the other compiler components
+      var knownHelpers = this.options.knownHelpers;
+      this.options.knownHelpers = {
+        'helperMissing': true,
+        'blockHelperMissing': true,
+        'each': true,
+        'if': true,
+        'unless': true,
+        'with': true,
+        'log': true
+      };
+      if (knownHelpers) {
+        for (var name in knownHelpers) {
+          this.options.knownHelpers[name] = knownHelpers[name];
+        }
+      }
+
+      return this.accept(program);
+    },
+
+    accept: function(node) {
+      var strip = node.strip || {},
+          ret;
+      if (strip.left) {
+        this.opcode('strip');
+      }
+
+      ret = this[node.type](node);
+
+      if (strip.right) {
+        this.opcode('strip');
+      }
+
+      return ret;
+    },
+
+    program: function(program) {
+      var statements = program.statements;
+
+      for(var i=0, l=statements.length; i&lt;l; i++) {
+        this.accept(statements[i]);
+      }
+      this.isSimple = l === 1;
+
+      this.depths.list = this.depths.list.sort(function(a, b) {
+        return a - b;
+      });
+
+      return this;
+    },
+
+    compileProgram: function(program) {
+      var result = new this.compiler().compile(program, this.options);
+      var guid = this.guid++, depth;
+
+      this.usePartial = this.usePartial || result.usePartial;
+
+      this.children[guid] = result;
+
+      for(var i=0, l=result.depths.list.length; i&lt;l; i++) {
+        depth = result.depths.list[i];
+
+        if(depth &lt; 2) { continue; }
+        else { this.addDepth(depth - 1); }
+      }
+
+      return guid;
+    },
+
+    block: function(block) {
+      var mustache = block.mustache,
+          program = block.program,
+          inverse = block.inverse;
+
+      if (program) {
+        program = this.compileProgram(program);
+      }
+
+      if (inverse) {
+        inverse = this.compileProgram(inverse);
+      }
+
+      var sexpr = mustache.sexpr;
+      var type = this.classifySexpr(sexpr);
+
+      if (type === &quot;helper&quot;) {
+        this.helperSexpr(sexpr, program, inverse);
+      } else if (type === &quot;simple&quot;) {
+        this.simpleSexpr(sexpr);
+
+        // now that the simple mustache is resolved, we need to
+        // evaluate it by executing `blockHelperMissing`
+        this.opcode('pushProgram', program);
+        this.opcode('pushProgram', inverse);
+        this.opcode('emptyHash');
+        this.opcode('blockValue');
+      } else {
+        this.ambiguousSexpr(sexpr, program, inverse);
+
+        // now that the simple mustache is resolved, we need to
+        // evaluate it by executing `blockHelperMissing`
+        this.opcode('pushProgram', program);
+        this.opcode('pushProgram', inverse);
+        this.opcode('emptyHash');
+        this.opcode('ambiguousBlockValue');
+      }
+
+      this.opcode('append');
+    },
+
+    hash: function(hash) {
+      var pairs = hash.pairs, pair, val;
+
+      this.opcode('pushHash');
+
+      for(var i=0, l=pairs.length; i&lt;l; i++) {
+        pair = pairs[i];
+        val  = pair[1];
+
+        if (this.options.stringParams) {
+          if(val.depth) {
+            this.addDepth(val.depth);
+          }
+          this.opcode('getContext', val.depth || 0);
+          this.opcode('pushStringParam', val.stringModeValue, val.type);
+
+          if (val.type === 'sexpr') {
+            // Subexpressions get evaluated and passed in
+            // in string params mode.
+            this.sexpr(val);
+          }
+        } else {
+          this.accept(val);
+        }
+
+        this.opcode('assignToHash', pair[0]);
+      }
+      this.opcode('popHash');
+    },
+
+    partial: function(partial) {
+      var partialName = partial.partialName;
+      this.usePartial = true;
+
+      if(partial.context) {
+        this.ID(partial.context);
+      } else {
+        this.opcode('push', 'depth0');
+      }
+
+      this.opcode('invokePartial', partialName.name);
+      this.opcode('append');
+    },
+
+    content: function(content) {
+      this.opcode('appendContent', content.string);
+    },
+
+    mustache: function(mustache) {
+      this.sexpr(mustache.sexpr);
+
+      if(mustache.escaped &amp;&amp; !this.options.noEscape) {
+        this.opcode('appendEscaped');
+      } else {
+        this.opcode('append');
+      }
+    },
+
+    ambiguousSexpr: function(sexpr, program, inverse) {
+      var id = sexpr.id,
+          name = id.parts[0],
+          isBlock = program != null || inverse != null;
+
+      this.opcode('getContext', id.depth);
+
+      this.opcode('pushProgram', program);
+      this.opcode('pushProgram', inverse);
+
+      this.opcode('invokeAmbiguous', name, isBlock);
+    },
+
+    simpleSexpr: function(sexpr) {
+      var id = sexpr.id;
+
+      if (id.type === 'DATA') {
+        this.DATA(id);
+      } else if (id.parts.length) {
+        this.ID(id);
+      } else {
+        // Simplified ID for `this`
+        this.addDepth(id.depth);
+        this.opcode('getContext', id.depth);
+        this.opcode('pushContext');
+      }
+
+      this.opcode('resolvePossibleLambda');
+    },
+
+    helperSexpr: function(sexpr, program, inverse) {
+      var params = this.setupFullMustacheParams(sexpr, program, inverse),
+          name = sexpr.id.parts[0];
+
+      if (this.options.knownHelpers[name]) {
+        this.opcode('invokeKnownHelper', params.length, name);
+      } else if (this.options.knownHelpersOnly) {
+        throw new Exception(&quot;You specified knownHelpersOnly, but used the unknown helper &quot; + name, sexpr);
+      } else {
+        this.opcode('invokeHelper', params.length, name, sexpr.isRoot);
+      }
+    },
+
+    sexpr: function(sexpr) {
+      var type = this.classifySexpr(sexpr);
+
+      if (type === &quot;simple&quot;) {
+        this.simpleSexpr(sexpr);
+      } else if (type === &quot;helper&quot;) {
+        this.helperSexpr(sexpr);
+      } else {
+        this.ambiguousSexpr(sexpr);
+      }
+    },
+
+    ID: function(id) {
+      this.addDepth(id.depth);
+      this.opcode('getContext', id.depth);
+
+      var name = id.parts[0];
+      if (!name) {
+        this.opcode('pushContext');
+      } else {
+        this.opcode('lookupOnContext', id.parts[0]);
+      }
+
+      for(var i=1, l=id.parts.length; i&lt;l; i++) {
+        this.opcode('lookup', id.parts[i]);
+      }
+    },
+
+    DATA: function(data) {
+      this.options.data = true;
+      if (data.id.isScoped || data.id.depth) {
+        throw new Exception('Scoped data references are not supported: ' + data.original, data);
+      }
+
+      this.opcode('lookupData');
+      var parts = data.id.parts;
+      for(var i=0, l=parts.length; i&lt;l; i++) {
+        this.opcode('lookup', parts[i]);
+      }
+    },
+
+    STRING: function(string) {
+      this.opcode('pushString', string.string);
+    },
+
+    INTEGER: function(integer) {
+      this.opcode('pushLiteral', integer.integer);
+    },
+
+    BOOLEAN: function(bool) {
+      this.opcode('pushLiteral', bool.bool);
+    },
+
+    comment: function() {},
+
+    // HELPERS
+    opcode: function(name) {
+      this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
+    },
+
+    declare: function(name, value) {
+      this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
+    },
+
+    addDepth: function(depth) {
+      if(depth === 0) { return; }
+
+      if(!this.depths[depth]) {
+        this.depths[depth] = true;
+        this.depths.list.push(depth);
+      }
+    },
+
+    classifySexpr: function(sexpr) {
+      var isHelper   = sexpr.isHelper;
+      var isEligible = sexpr.eligibleHelper;
+      var options    = this.options;
+
+      // if ambiguous, we can possibly resolve the ambiguity now
+      if (isEligible &amp;&amp; !isHelper) {
+        var name = sexpr.id.parts[0];
+
+        if (options.knownHelpers[name]) {
+          isHelper = true;
+        } else if (options.knownHelpersOnly) {
+          isEligible = false;
+        }
+      }
+
+      if (isHelper) { return &quot;helper&quot;; }
+      else if (isEligible) { return &quot;ambiguous&quot;; }
+      else { return &quot;simple&quot;; }
+    },
+
+    pushParams: function(params) {
+      var i = params.length, param;
+
+      while(i--) {
+        param = params[i];
+
+        if(this.options.stringParams) {
+          if(param.depth) {
+            this.addDepth(param.depth);
+          }
+
+          this.opcode('getContext', param.depth || 0);
+          this.opcode('pushStringParam', param.stringModeValue, param.type);
+
+          if (param.type === 'sexpr') {
+            // Subexpressions get evaluated and passed in
+            // in string params mode.
+            this.sexpr(param);
+          }
+        } else {
+          this[param.type](param);
+        }
+      }
+    },
+
+    setupFullMustacheParams: function(sexpr, program, inverse) {
+      var params = sexpr.params;
+      this.pushParams(params);
+
+      this.opcode('pushProgram', program);
+      this.opcode('pushProgram', inverse);
+
+      if (sexpr.hash) {
+        this.hash(sexpr.hash);
+      } else {
+        this.opcode('emptyHash');
+      }
+
+      return params;
+    }
+  };
+
+  function precompile(input, options, env) {
+    if (input == null || (typeof input !== 'string' &amp;&amp; input.constructor !== env.AST.ProgramNode)) {
+      throw new Exception(&quot;You must pass a string or Handlebars AST to Handlebars.precompile. You passed &quot; + input);
+    }
+
+    options = options || {};
+    if (!('data' in options)) {
+      options.data = true;
+    }
+
+    var ast = env.parse(input);
+    var environment = new env.Compiler().compile(ast, options);
+    return new env.JavaScriptCompiler().compile(environment, options);
+  }
+
+  __exports__.precompile = precompile;function compile(input, options, env) {
+    if (input == null || (typeof input !== 'string' &amp;&amp; input.constructor !== env.AST.ProgramNode)) {
+      throw new Exception(&quot;You must pass a string or Handlebars AST to Handlebars.compile. You passed &quot; + input);
+    }
+
+    options = options || {};
+
+    if (!('data' in options)) {
+      options.data = true;
+    }
+
+    var compiled;
+
+    function compileInput() {
+      var ast = env.parse(input);
+      var environment = new env.Compiler().compile(ast, options);
+      var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
+      return env.template(templateSpec);
+    }
+
+    // Template is only compiled on first use and cached after that point.
+    return function(context, options) {
+      if (!compiled) {
+        compiled = compileInput();
+      }
+      return compiled.call(this, context, options);
+    };
+  }
+
+  __exports__.compile = compile;
+  return __exports__;
+})(__module5__);
+
+// handlebars/compiler/javascript-compiler.js
+var __module11__ = (function(__dependency1__, __dependency2__) {
+  &quot;use strict&quot;;
+  var __exports__;
+  var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
+  var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
+  var log = __dependency1__.log;
+  var Exception = __dependency2__;
+
+  function Literal(value) {
+    this.value = value;
+  }
+
+  function JavaScriptCompiler() {}
+
+  JavaScriptCompiler.prototype = {
+    // PUBLIC API: You can override these methods in a subclass to provide
+    // alternative compiled forms for name lookup and buffering semantics
+    nameLookup: function(parent, name /* , type*/) {
+      var wrap,
+          ret;
+      if (parent.indexOf('depth') === 0) {
+        wrap = true;
+      }
+
+      if (/^[0-9]+$/.test(name)) {
+        ret = parent + &quot;[&quot; + name + &quot;]&quot;;
+      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
+        ret = parent + &quot;.&quot; + name;
+      }
+      else {
+        ret = parent + &quot;['&quot; + name + &quot;']&quot;;
+      }
+
+      if (wrap) {
+        return '(' + parent + ' &amp;&amp; ' + ret + ')';
+      } else {
+        return ret;
+      }
+    },
+
+    compilerInfo: function() {
+      var revision = COMPILER_REVISION,
+          versions = REVISION_CHANGES[revision];
+      return &quot;this.compilerInfo = [&quot;+revision+&quot;,'&quot;+versions+&quot;'];\n&quot;;
+    },
+
+    appendToBuffer: function(string) {
+      if (this.environment.isSimple) {
+        return &quot;return &quot; + string + &quot;;&quot;;
+      } else {
+        return {
+          appendToBuffer: true,
+          content: string,
+          toString: function() { return &quot;buffer += &quot; + string + &quot;;&quot;; }
+        };
+      }
+    },
+
+    initializeBuffer: function() {
+      return this.quotedString(&quot;&quot;);
+    },
+
+    namespace: &quot;Handlebars&quot;,
+    // END PUBLIC API
+
+    compile: function(environment, options, context, asObject) {
+      this.environment = environment;
+      this.options = options || {};
+
+      log('debug', this.environment.disassemble() + &quot;\n\n&quot;);
+
+      this.name = this.environment.name;
+      this.isChild = !!context;
+      this.context = context || {
+        programs: [],
+        environments: [],
+        aliases: { }
+      };
+
+      this.preamble();
+
+      this.stackSlot = 0;
+      this.stackVars = [];
+      this.registers = { list: [] };
+      this.hashes = [];
+      this.compileStack = [];
+      this.inlineStack = [];
+
+      this.compileChildren(environment, options);
+
+      var opcodes = environment.opcodes, opcode;
+
+      this.i = 0;
+
+      for(var l=opcodes.length; this.i&lt;l; this.i++) {
+        opcode = opcodes[this.i];
+
+        if(opcode.opcode === 'DECLARE') {
+          this[opcode.name] = opcode.value;
+        } else {
+          this[opcode.opcode].apply(this, opcode.args);
+        }
+
+        // Reset the stripNext flag if it was not set by this operation.
+        if (opcode.opcode !== this.stripNext) {
+          this.stripNext = false;
+        }
+      }
+
+      // Flush any trailing content that might be pending.
+      this.pushSource('');
+
+      if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
+        throw new Exception('Compile completed with content left on stack');
+      }
+
+      return this.createFunctionContext(asObject);
+    },
+
+    preamble: function() {
+      var out = [];
+
+      if (!this.isChild) {
+        var namespace = this.namespace;
+
+        var copies = &quot;helpers = this.merge(helpers, &quot; + namespace + &quot;.helpers);&quot;;
+        if (this.environment.usePartial) { copies = copies + &quot; partials = this.merge(partials, &quot; + namespace + &quot;.partials);&quot;; }
+        if (this.options.data) { copies = copies + &quot; data = data || {};&quot;; }
+        out.push(copies);
+      } else {
+        out.push('');
+      }
+
+      if (!this.environment.isSimple) {
+        out.push(&quot;, buffer = &quot; + this.initializeBuffer());
+      } else {
+        out.push(&quot;&quot;);
+      }
+
+      // track the last context pushed into place to allow skipping the
+      // getContext opcode when it would be a noop
+      this.lastContext = 0;
+      this.source = out;
+    },
+
+    createFunctionContext: function(asObject) {
+      var locals = this.stackVars.concat(this.registers.list);
+
+      if(locals.length &gt; 0) {
+        this.source[1] = this.source[1] + &quot;, &quot; + locals.join(&quot;, &quot;);
+      }
+
+      // Generate minimizer alias mappings
+      if (!this.isChild) {
+        for (var alias in this.context.aliases) {
+          if (this.context.aliases.hasOwnProperty(alias)) {
+            this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
+          }
+        }
+      }
+
+      if (this.source[1]) {
+        this.source[1] = &quot;var &quot; + this.source[1].substring(2) + &quot;;&quot;;
+      }
+
+      // Merge children
+      if (!this.isChild) {
+        this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
+      }
+
+      if (!this.environment.isSimple) {
+        this.pushSource(&quot;return buffer;&quot;);
+      }
+
+      var params = this.isChild ? [&quot;depth0&quot;, &quot;data&quot;] : [&quot;Handlebars&quot;, &quot;depth0&quot;, &quot;helpers&quot;, &quot;partials&quot;, &quot;data&quot;];
+
+      for(var i=0, l=this.environment.depths.list.length; i&lt;l; i++) {
+        params.push(&quot;depth&quot; + this.environment.depths.list[i]);
+      }
+
+      // Perform a second pass over the output to merge content when possible
+      var source = this.mergeSource();
+
+      if (!this.isChild) {
+        source = this.compilerInfo()+source;
+      }
+
+      if (asObject) {
+        params.push(source);
+
+        return Function.apply(this, params);
+      } else {
+        var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n  ' + source + '}';
+        log('debug', functionSource + &quot;\n\n&quot;);
+        return functionSource;
+      }
+    },
+    mergeSource: function() {
+      // WARN: We are not handling the case where buffer is still populated as the source should
+      // not have buffer append operations as their final action.
+      var source = '',
+          buffer;
+      for (var i = 0, len = this.source.length; i &lt; len; i++) {
+        var line = this.source[i];
+        if (line.appendToBuffer) {
+          if (buffer) {
+            buffer = buffer + '\n    + ' + line.content;
+          } else {
+            buffer = line.content;
+          }
+        } else {
+          if (buffer) {
+            source += 'buffer += ' + buffer + ';\n  ';
+            buffer = undefined;
+          }
+          source += line + '\n  ';
+        }
+      }
+      return source;
+    },
+
+    // [blockValue]
+    //
+    // On stack, before: hash, inverse, program, value
+    // On stack, after: return value of blockHelperMissing
+    //
+    // The purpose of this opcode is to take a block of the form
+    // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
+    // replace it on the stack with the result of properly
+    // invoking blockHelperMissing.
+    blockValue: function() {
+      this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+
+      var params = [&quot;depth0&quot;];
+      this.setupParams(0, params);
+
+      this.replaceStack(function(current) {
+        params.splice(1, 0, current);
+        return &quot;blockHelperMissing.call(&quot; + params.join(&quot;, &quot;) + &quot;)&quot;;
+      });
+    },
+
+    // [ambiguousBlockValue]
+    //
+    // On stack, before: hash, inverse, program, value
+    // Compiler value, before: lastHelper=value of last found helper, if any
+    // On stack, after, if no lastHelper: same as [blockValue]
+    // On stack, after, if lastHelper: value
+    ambiguousBlockValue: function() {
+      this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+
+      var params = [&quot;depth0&quot;];
+      this.setupParams(0, params);
+
+      var current = this.topStack();
+      params.splice(1, 0, current);
+
+      this.pushSource(&quot;if (!&quot; + this.lastHelper + &quot;) { &quot; + current + &quot; = blockHelperMissing.call(&quot; + params.join(&quot;, &quot;) + &quot;); }&quot;);
+    },
+
+    // [appendContent]
+    //
+    // On stack, before: ...
+    // On stack, after: ...
+    //
+    // Appends the string value of `content` to the current buffer
+    appendContent: function(content) {
+      if (this.pendingContent) {
+        content = this.pendingContent + content;
+      }
+      if (this.stripNext) {
+        content = content.replace(/^\s+/, '');
+      }
+
+      this.pendingContent = content;
+    },
+
+    // [strip]
+    //
+    // On stack, before: ...
+    // On stack, after: ...
+    //
+    // Removes any trailing whitespace from the prior content node and flags
+    // the next operation for stripping if it is a content node.
+    strip: function() {
+      if (this.pendingContent) {
+        this.pendingContent = this.pendingContent.replace(/\s+$/, '');
+      }
+      this.stripNext = 'strip';
+    },
+
+    // [append]
+    //
+    // On stack, before: value, ...
+    // On stack, after: ...
+    //
+    // Coerces `value` to a String and appends it to the current buffer.
+    //
+    // If `value` is truthy, or 0, it is coerced into a string and appended
+    // Otherwise, the empty string is appended
+    append: function() {
+      // Force anything that is inlined onto the stack so we don't have duplication
+      // when we examine local
+      this.flushInline();
+      var local = this.popStack();
+      this.pushSource(&quot;if(&quot; + local + &quot; || &quot; + local + &quot; === 0) { &quot; + this.appendToBuffer(local) + &quot; }&quot;);
+      if (this.environment.isSimple) {
+        this.pushSource(&quot;else { &quot; + this.appendToBuffer(&quot;''&quot;) + &quot; }&quot;);
+      }
+    },
+
+    // [appendEscaped]
+    //
+    // On stack, before: value, ...
+    // On stack, after: ...
+    //
+    // Escape `value` and append it to the buffer
+    appendEscaped: function() {
+      this.context.aliases.escapeExpression = 'this.escapeExpression';
+
+      this.pushSource(this.appendToBuffer(&quot;escapeExpression(&quot; + this.popStack() + &quot;)&quot;));
+    },
+
+    // [getContext]
+    //
+    // On stack, before: ...
+    // On stack, after: ...
+    // Compiler value, after: lastContext=depth
+    //
+    // Set the value of the `lastContext` compiler value to the depth
+    getContext: function(depth) {
+      if(this.lastContext !== depth) {
+        this.lastContext = depth;
+      }
+    },
+
+    // [lookupOnContext]
+    //
+    // On stack, before: ...
+    // On stack, after: currentContext[name], ...
+    //
+    // Looks up the value of `name` on the current context and pushes
+    // it onto the stack.
+    lookupOnContext: function(name) {
+      this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
+    },
+
+    // [pushContext]
+    //
+    // On stack, before: ...
+    // On stack, after: currentContext, ...
+    //
+    // Pushes the value of the current context onto the stack.
+    pushContext: function() {
+      this.pushStackLiteral('depth' + this.lastContext);
+    },
+
+    // [resolvePossibleLambda]
+    //
+    // On stack, before: value, ...
+    // On stack, after: resolved value, ...
+    //
+    // If the `value` is a lambda, replace it on the stack by
+    // the return value of the lambda
+    resolvePossibleLambda: function() {
+      this.context.aliases.functionType = '&quot;function&quot;';
+
+      this.replaceStack(function(current) {
+        return &quot;typeof &quot; + current + &quot; === functionType ? &quot; + current + &quot;.apply(depth0) : &quot; + current;
+      });
+    },
+
+    // [lookup]
+    //
+    // On stack, before: value, ...
+    // On stack, after: value[name], ...
+    //
+    // Replace the value on the stack with the result of looking
+    // up `name` on `value`
+    lookup: function(name) {
+      this.replaceStack(function(current) {
+        return current + &quot; == null || &quot; + current + &quot; === false ? &quot; + current + &quot; : &quot; + this.nameLookup(current, name, 'context');
+      });
+    },
+
+    // [lookupData]
+    //
+    // On stack, before: ...
+    // On stack, after: data, ...
+    //
+    // Push the data lookup operator
+    lookupData: function() {
+      this.pushStackLiteral('data');
+    },
+
+    // [pushStringParam]
+    //
+    // On stack, before: ...
+    // On stack, after: string, currentContext, ...
+    //
+    // This opcode is designed for use in string mode, which
+    // provides the string value of a parameter along with its
+    // depth rather than resolving it immediately.
+    pushStringParam: function(string, type) {
+      this.pushStackLiteral('depth' + this.lastContext);
+
+      this.pushString(type);
+
+      // If it's a subexpression, the string result
+      // will be pushed after this opcode.
+      if (type !== 'sexpr') {
+        if (typeof string === 'string') {
+          this.pushString(string);
+        } else {
+          this.pushStackLiteral(string);
+        }
+      }
+    },
+
+    emptyHash: function() {
+      this.pushStackLiteral('{}');
+
+      if (this.options.stringParams) {
+        this.push('{}'); // hashContexts
+        this.push('{}'); // hashTypes
+      }
+    },
+    pushHash: function() {
+      if (this.hash) {
+        this.hashes.push(this.hash);
+      }
+      this.hash = {values: [], types: [], contexts: []};
+    },
+    popHash: function() {
+      var hash = this.hash;
+      this.hash = this.hashes.pop();
+
+      if (this.options.stringParams) {
+        this.push('{' + hash.contexts.join(',') + '}');
+        this.push('{' + hash.types.join(',') + '}');
+      }
+
+      this.push('{\n    ' + hash.values.join(',\n    ') + '\n  }');
+    },
+
+    // [pushString]
+    //
+    // On stack, before: ...
+    // On stack, after: quotedString(string), ...
+    //
+    // Push a quoted version of `string` onto the stack
+    pushString: function(string) {
+      this.pushStackLiteral(this.quotedString(string));
+    },
+
+    // [push]
+    //
+    // On stack, before: ...
+    // On stack, after: expr, ...
+    //
+    // Push an expression onto the stack
+    push: function(expr) {
+      this.inlineStack.push(expr);
+      return expr;
+    },
+
+    // [pushLiteral]
+    //
+    // On stack, before: ...
+    // On stack, after: value, ...
+    //
+    // Pushes a value onto the stack. This operation prevents
+    // the compiler from creating a temporary variable to hold
+    // it.
+    pushLiteral: function(value) {
+      this.pushStackLiteral(value);
+    },
+
+    // [pushProgram]
+    //
+    // On stack, before: ...
+    // On stack, after: program(guid), ...
+    //
+    // Push a program expression onto the stack. This takes
+    // a compile-time guid and converts it into a runtime-accessible
+    // expression.
+    pushProgram: function(guid) {
+      if (guid != null) {
+        this.pushStackLiteral(this.programExpression(guid));
+      } else {
+        this.pushStackLiteral(null);
+      }
+    },
+
+    // [invokeHelper]
+    //
+    // On stack, before: hash, inverse, program, params..., ...
+    // On stack, after: result of helper invocation
+    //
+    // Pops off the helper's parameters, invokes the helper,
+    // and pushes the helper's return value onto the stack.
+    //
+    // If the helper is not found, `helperMissing` is called.
+    invokeHelper: function(paramSize, name, isRoot) {
+      this.context.aliases.helperMissing = 'helpers.helperMissing';
+      this.useRegister('helper');
+
+      var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
+      var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
+
+      var lookup = 'helper = ' + helper.name + ' || ' + nonHelper;
+      if (helper.paramsInit) {
+        lookup += ',' + helper.paramsInit;
+      }
+
+      this.push(
+        '('
+          + lookup
+          + ',helper '
+            + '? helper.call(' + helper.callParams + ') '
+            + ': helperMissing.call(' + helper.helperMissingParams + '))');
+
+      // Always flush subexpressions. This is both to prevent the compounding size issue that
+      // occurs when the code has to be duplicated for inlining and also to prevent errors
+      // due to the incorrect options object being passed due to the shared register.
+      if (!isRoot) {
+        this.flushInline();
+      }
+    },
+
+    // [invokeKnownHelper]
+    //
+    // On stack, before: hash, inverse, program, params..., ...
+    // On stack, after: result of helper invocation
+    //
+    // This operation is used when the helper is known to exist,
+    // so a `helperMissing` fallback is not required.
+    invokeKnownHelper: function(paramSize, name) {
+      var helper = this.setupHelper(paramSize, name);
+      this.push(helper.name + &quot;.call(&quot; + helper.callParams + &quot;)&quot;);
+    },
+
+    // [invokeAmbiguous]
+    //
+    // On stack, before: hash, inverse, program, params..., ...
+    // On stack, after: result of disambiguation
+    //
+    // This operation is used when an expression like `{{foo}}`
+    // is provided, but we don't know at compile-time whether it
+    // is a helper or a path.
+    //
+    // This operation emits more code than the other options,
+    // and can be avoided by passing the `knownHelpers` and
+    // `knownHelpersOnly` flags at compile-time.
+    invokeAmbiguous: function(name, helperCall) {
+      this.context.aliases.functionType = '&quot;function&quot;';
+      this.useRegister('helper');
+
+      this.emptyHash();
+      var helper = this.setupHelper(0, name, helperCall);
+
+      var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
+
+      var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
+      var nextStack = this.nextStack();
+
+      if (helper.paramsInit) {
+        this.pushSource(helper.paramsInit);
+      }
+      this.pushSource('if (helper = ' + helperName + ') { ' + nextStack + ' = helper.call(' + helper.callParams + '); }');
+      this.pushSource('else { helper = ' + nonHelper + '; ' + nextStack + ' = typeof helper === functionType ? helper.call(' + helper.callParams + ') : helper; }');
+    },
+
+    // [invokePartial]
+    //
+    // On stack, before: context, ...
+    // On stack after: result of partial invocation
+    //
+    // This operation pops off a context, invokes a partial with that context,
+    // and pushes the result of the invocation back.
+    invokePartial: function(name) {
+      var params = [this.nameLookup('partials', name, 'partial'), &quot;'&quot; + name + &quot;'&quot;, this.popStack(), &quot;helpers&quot;, &quot;partials&quot;];
+
+      if (this.options.data) {
+        params.push(&quot;data&quot;);
+      }
+
+      this.context.aliases.self = &quot;this&quot;;
+      this.push(&quot;self.invokePartial(&quot; + params.join(&quot;, &quot;) + &quot;)&quot;);
+    },
+
+    // [assignToHash]
+    //
+    // On stack, before: value, hash, ...
+    // On stack, after: hash, ...
+    //
+    // Pops a value and hash off the stack, assigns `hash[key] = value`
+    // and pushes the hash back onto the stack.
+    assignToHash: function(key) {
+      var value = this.popStack(),
+          context,
+          type;
+
+      if (this.options.stringParams) {
+        type = this.popStack();
+        context = this.popStack();
+      }
+
+      var hash = this.hash;
+      if (context) {
+        hash.contexts.push(&quot;'&quot; + key + &quot;': &quot; + context);
+      }
+      if (type) {
+        hash.types.push(&quot;'&quot; + key + &quot;': &quot; + type);
+      }
+      hash.values.push(&quot;'&quot; + key + &quot;': (&quot; + value + &quot;)&quot;);
+    },
+
+    // HELPERS
+
+    compiler: JavaScriptCompiler,
+
+    compileChildren: function(environment, options) {
+      var children = environment.children, child, compiler;
+
+      for(var i=0, l=children.length; i&lt;l; i++) {
+        child = children[i];
+        compiler = new this.compiler();
+
+        var index = this.matchExistingProgram(child);
+
+        if (index == null) {
+          this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children
+          index = this.context.programs.length;
+          child.index = index;
+          child.name = 'program' + index;
+          this.context.programs[index] = compiler.compile(child, options, this.context);
+          this.context.environments[index] = child;
+        } else {
+          child.index = index;
+          child.name = 'program' + index;
+        }
+      }
+    },
+    matchExistingProgram: function(child) {
+      for (var i = 0, len = this.context.environments.length; i &lt; len; i++) {
+        var environment = this.context.environments[i];
+        if (environment &amp;&amp; environment.equals(child)) {
+          return i;
+        }
+      }
+    },
+
+    programExpression: function(guid) {
+      this.context.aliases.self = &quot;this&quot;;
+
+      if(guid == null) {
+        return &quot;self.noop&quot;;
+      }
+
+      var child = this.environment.children[guid],
+          depths = child.depths.list, depth;
+
+      var programParams = [child.index, child.name, &quot;data&quot;];
+
+      for(var i=0, l = depths.length; i&lt;l; i++) {
+        depth = depths[i];
+
+        if(depth === 1) { programParams.push(&quot;depth0&quot;); }
+        else { programParams.push(&quot;depth&quot; + (depth - 1)); }
+      }
+
+      return (depths.length === 0 ? &quot;self.program(&quot; : &quot;self.programWithDepth(&quot;) + programParams.join(&quot;, &quot;) + &quot;)&quot;;
+    },
+
+    register: function(name, val) {
+      this.useRegister(name);
+      this.pushSource(name + &quot; = &quot; + val + &quot;;&quot;);
+    },
+
+    useRegister: function(name) {
+      if(!this.registers[name]) {
+        this.registers[name] = true;
+        this.registers.list.push(name);
+      }
+    },
+
+    pushStackLiteral: function(item) {
+      return this.push(new Literal(item));
+    },
+
+    pushSource: function(source) {
+      if (this.pendingContent) {
+        this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
+        this.pendingContent = undefined;
+      }
+
+      if (source) {
+        this.source.push(source);
+      }
+    },
+
+    pushStack: function(item) {
+      this.flushInline();
+
+      var stack = this.incrStack();
+      if (item) {
+        this.pushSource(stack + &quot; = &quot; + item + &quot;;&quot;);
+      }
+      this.compileStack.push(stack);
+      return stack;
+    },
+
+    replaceStack: function(callback) {
+      var prefix = '',
+          inline = this.isInline(),
+          stack,
+          createdStack,
+          usedLiteral;
+
+      // If we are currently inline then we want to merge the inline statement into the
+      // replacement statement via ','
+      if (inline) {
+        var top = this.popStack(true);
+
+        if (top instanceof Literal) {
+          // Literals do not need to be inlined
+          stack = top.value;
+          usedLiteral = true;
+        } else {
+          // Get or create the current stack name for use by the inline
+          createdStack = !this.stackSlot;
+          var name = !createdStack ? this.topStackName() : this.incrStack();
+
+          prefix = '(' + this.push(name) + ' = ' + top + '),';
+          stack = this.topStack();
+        }
+      } else {
+        stack = this.topStack();
+      }
+
+      var item = callback.call(this, stack);
+
+      if (inline) {
+        if (!usedLiteral) {
+          this.popStack();
+        }
+        if (createdStack) {
+          this.stackSlot--;
+        }
+        this.push('(' + prefix + item + ')');
+      } else {
+        // Prevent modification of the context depth variable. Through replaceStack
+        if (!/^stack/.test(stack)) {
+          stack = this.nextStack();
+        }
+
+        this.pushSource(stack + &quot; = (&quot; + prefix + item + &quot;);&quot;);
+      }
+      return stack;
+    },
+
+    nextStack: function() {
+      return this.pushStack();
+    },
+
+    incrStack: function() {
+      this.stackSlot++;
+      if(this.stackSlot &gt; this.stackVars.length) { this.stackVars.push(&quot;stack&quot; + this.stackSlot); }
+      return this.topStackName();
+    },
+    topStackName: function() {
+      return &quot;stack&quot; + this.stackSlot;
+    },
+    flushInline: function() {
+      var inlineStack = this.inlineStack;
+      if (inlineStack.length) {
+        this.inlineStack = [];
+        for (var i = 0, len = inlineStack.length; i &lt; len; i++) {
+          var entry = inlineStack[i];
+          if (entry instanceof Literal) {
+            this.compileStack.push(entry);
+          } else {
+            this.pushStack(entry);
+          }
+        }
+      }
+    },
+    isInline: function() {
+      return this.inlineStack.length;
+    },
+
+    popStack: function(wrapped) {
+      var inline = this.isInline(),
+          item = (inline ? this.inlineStack : this.compileStack).pop();
+
+      if (!wrapped &amp;&amp; (item instanceof Literal)) {
+        return item.value;
+      } else {
+        if (!inline) {
+          if (!this.stackSlot) {
+            throw new Exception('Invalid stack pop');
+          }
+          this.stackSlot--;
+        }
+        return item;
+      }
+    },
+
+    topStack: function(wrapped) {
+      var stack = (this.isInline() ? this.inlineStack : this.compileStack),
+          item = stack[stack.length - 1];
+
+      if (!wrapped &amp;&amp; (item instanceof Literal)) {
+        return item.value;
+      } else {
+        return item;
+      }
+    },
+
+    quotedString: function(str) {
+      return '&quot;' + str
+        .replace(/\\/g, '\\\\')
+        .replace(/&quot;/g, '\\&quot;')
+        .replace(/\n/g, '\\n')
+        .replace(/\r/g, '\\r')
+        .replace(/\u2028/g, '\\u2028')   // Per Ecma-262 7.3 + 7.8.4
+        .replace(/\u2029/g, '\\u2029') + '&quot;';
+    },
+
+    setupHelper: function(paramSize, name, missingParams) {
+      var params = [],
+          paramsInit = this.setupParams(paramSize, params, missingParams);
+      var foundHelper = this.nameLookup('helpers', name, 'helper');
+
+      return {
+        params: params,
+        paramsInit: paramsInit,
+        name: foundHelper,
+        callParams: [&quot;depth0&quot;].concat(params).join(&quot;, &quot;),
+        helperMissingParams: missingParams &amp;&amp; [&quot;depth0&quot;, this.quotedString(name)].concat(params).join(&quot;, &quot;)
+      };
+    },
+
+    setupOptions: function(paramSize, params) {
+      var options = [], contexts = [], types = [], param, inverse, program;
+
+      options.push(&quot;hash:&quot; + this.popStack());
+
+      if (this.options.stringParams) {
+        options.push(&quot;hashTypes:&quot; + this.popStack());
+        options.push(&quot;hashContexts:&quot; + this.popStack());
+      }
+
+      inverse = this.popStack();
+      program = this.popStack();
+
+      // Avoid setting fn and inverse if neither are set. This allows
+      // helpers to do a check for `if (options.fn)`
+      if (program || inverse) {
+        if (!program) {
+          this.context.aliases.self = &quot;this&quot;;
+          program = &quot;self.noop&quot;;
+        }
+
+        if (!inverse) {
+          this.context.aliases.self = &quot;this&quot;;
+          inverse = &quot;self.noop&quot;;
+        }
+
+        options.push(&quot;inverse:&quot; + inverse);
+        options.push(&quot;fn:&quot; + program);
+      }
+
+      for(var i=0; i&lt;paramSize; i++) {
+        param = this.popStack();
+        params.push(param);
+
+        if(this.options.stringParams) {
+          types.push(this.popStack());
+          contexts.push(this.popStack());
+        }
+      }
+
+      if (this.options.stringParams) {
+        options.push(&quot;contexts:[&quot; + contexts.join(&quot;,&quot;) + &quot;]&quot;);
+        options.push(&quot;types:[&quot; + types.join(&quot;,&quot;) + &quot;]&quot;);
+      }
+
+      if(this.options.data) {
+        options.push(&quot;data:data&quot;);
+      }
+
+      return options;
+    },
+
+    // the params and contexts arguments are passed in arrays
+    // to fill in
+    setupParams: function(paramSize, params, useRegister) {
+      var options = '{' + this.setupOptions(paramSize, params).join(',') + '}';
+
+      if (useRegister) {
+        this.useRegister('options');
+        params.push('options');
+        return 'options=' + options;
+      } else {
+        params.push(options);
+        return '';
+      }
+    }
+  };
+
+  var reservedWords = (
+    &quot;break else new var&quot; +
+    &quot; case finally return void&quot; +
+    &quot; catch for switch while&quot; +
+    &quot; continue function this with&quot; +
+    &quot; default if throw&quot; +
+    &quot; delete in try&quot; +
+    &quot; do instanceof typeof&quot; +
+    &quot; abstract enum int short&quot; +
+    &quot; boolean export interface static&quot; +
+    &quot; byte extends long super&quot; +
+    &quot; char final native synchronized&quot; +
+    &quot; class float package throws&quot; +
+    &quot; const goto private transient&quot; +
+    &quot; debugger implements protected volatile&quot; +
+    &quot; double import public let yield&quot;
+  ).split(&quot; &quot;);
+
+  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
+
+  for(var i=0, l=reservedWords.length; i&lt;l; i++) {
+    compilerWords[reservedWords[i]] = true;
+  }
+
+  JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
+    if(!JavaScriptCompiler.RESERVED_WORDS[name] &amp;&amp; /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) {
+      return true;
+    }
+    return false;
+  };
+
+  __exports__ = JavaScriptCompiler;
+  return __exports__;
+})(__module2__, __module5__);
+
+// handlebars.js
+var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
+  &quot;use strict&quot;;
+  var __exports__;
+  /*globals Handlebars: true */
+  var Handlebars = __dependency1__;
+
+  // Compiler imports
+  var AST = __dependency2__;
+  var Parser = __dependency3__.parser;
+  var parse = __dependency3__.parse;
+  var Compiler = __dependency4__.Compiler;
+  var compile = __dependency4__.compile;
+  var precompile = __dependency4__.precompile;
+  var JavaScriptCompiler = __dependency5__;
+
+  var _create = Handlebars.create;
+  var create = function() {
+    var hb = _create();
+
+    hb.compile = function(input, options) {
+      return compile(input, options, hb);
+    };
+    hb.precompile = function (input, options) {
+      return precompile(input, options, hb);
+    };
+
+    hb.AST = AST;
+    hb.Compiler = Compiler;
+    hb.JavaScriptCompiler = JavaScriptCompiler;
+    hb.Parser = Parser;
+    hb.parse = parse;
+
+    return hb;
+  };
+
+  Handlebars = create();
+  Handlebars.create = create;
+
+  __exports__ = Handlebars;
+  return __exports__;
+})(__module1__, __module7__, __module8__, __module10__, __module11__);
+
+  return __module0__;
+})();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/handlebars.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsjqueryminjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/jquery.min.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/jquery.min.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/jquery.min.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,3178 @@
</span><ins>+/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery.min.map
+*/
+(function(e, t) {
+    var n, r, i = typeof t, o = e.document, a = e.location, s = e.jQuery, u = e.$, l = {}, c = [], p = &quot;1.9.1&quot;, f = c.concat, d = c.push, h = c.slice, g = c.indexOf, m = l.toString, y = l.hasOwnProperty, v = p.trim, b = function(e, t) {
+        return new b.fn.init(e, t, r)
+    }, x = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, w = /\S+/g, T = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, N = /^(?:(&lt;[\w\W]+&gt;)[^&gt;]*|#([\w-]*))$/, C = /^&lt;(\w+)\s*\/?&gt;(?:&lt;\/\1&gt;|)$/, k = /^[\],:{}\s]*$/, E = /(?:^|:|,)(?:\s*\[)+/g, S = /\\(?:[&quot;\\\/bfnrt]|u[\da-fA-F]{4})/g, A = /&quot;[^&quot;\\\r\n]*&quot;|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, j = /^-ms-/, D = /-([\da-z])/gi, L = function(e, t) {
+        return t.toUpperCase()
+    }, H = function(e) {
+        (o.addEventListener || &quot;load&quot; === e.type || &quot;complete&quot; === o.readyState) &amp;&amp; (q(), b.ready())
+    }, q = function() {
+        o.addEventListener ? (o.removeEventListener(&quot;DOMContentLoaded&quot;, H, !1), e.removeEventListener(&quot;load&quot;, H, !1)) : (o.detachEvent(&quot;onreadystatechange&quot;, H), e.detachEvent(&quot;onload&quot;, H))
+    };
+    b.fn = b.prototype = {
+        jquery: p,
+        constructor: b,
+        init: function(e, n, r) {
+            var i, a;
+            if (!e)
+                return this;
+            if (&quot;string&quot; == typeof e) {
+                if (i = &quot;&lt;&quot; === e.charAt(0) &amp;&amp; &quot;&gt;&quot; === e.charAt(e.length-1) &amp;&amp; e.length &gt;= 3 ? [null, e, null] : N.exec(e), !i ||!i[1] &amp;&amp; n)
+                    return !n || n.jquery ? (n || r).find(e) : this.constructor(n).find(e);
+                if (i[1]) {
+                    if (n = n instanceof b ? n[0] : n, b.merge(this, b.parseHTML(i[1], n &amp;&amp; n.nodeType ? n.ownerDocument || n : o, !0)
+                        ), C.test(i[1]) &amp;&amp; b.isPlainObject(n))for (i in n)
+                        b.isFunction(this[i]) ? this[i](n[i]) : this.attr(i, n[i]);
+                    return this
+                }
+                if (a = o.getElementById(i[2]), a &amp;&amp; a.parentNode) {
+                    if (a.id !== i[2])
+                        return r.find(e);
+                    this.length = 1, this[0] = a
+                }
+                return this.context = o, this.selector = e, this
+            }
+            return e.nodeType ? (this.context = this[0] = e, this.length = 1, this) : b.isFunction(e) ? r.ready(e) : (e.selector !== t &amp;&amp; (this.selector = e.selector, this.context = e.context), b.makeArray(e, this))
+        },
+        selector: &quot;&quot;,
+        length: 0,
+        size: function() {
+            return this.length
+        },
+        toArray: function() {
+            return h.call(this)
+        },
+        get: function(e) {
+            return null == e ? this.toArray() : 0 &gt; e ? this[this.length + e] : this[e]
+        },
+        pushStack: function(e) {
+            var t = b.merge(this.constructor(), e);
+            return t.prevObject = this, t.context = this.context, t
+        },
+        each: function(e, t) {
+            return b.each(this, e, t)
+        },
+        ready: function(e) {
+            return b.ready.promise().done(e), this
+        },
+        slice: function() {
+            return this.pushStack(h.apply(this, arguments))
+        },
+        first: function() {
+            return this.eq(0)
+        },
+        last: function() {
+            return this.eq(-1)
+        },
+        eq: function(e) {
+            var t = this.length, n =+ e + (0 &gt; e ? t : 0);
+            return this.pushStack(n &gt;= 0 &amp;&amp; t &gt; n ? [this[n]] : [])
+        },
+        map: function(e) {
+            return this.pushStack(b.map(this, function(t, n) {
+                return e.call(t, n, t)
+            }))
+        },
+        end: function() {
+            return this.prevObject || this.constructor(null)
+        },
+        push: d,
+        sort: [].sort,
+        splice: [].splice
+    }, b.fn.init.prototype = b.fn, b.extend = b.fn.extend = function() {
+        var e, n, r, i, o, a, s = arguments[0] || {}, u = 1, l = arguments.length, c=!1;
+        for (&quot;boolean&quot; == typeof s &amp;&amp; (c = s, s = arguments[1] || {}, u = 2), &quot;object&quot; == typeof s || b.isFunction(s) || (s = {}), l === u &amp;&amp; (s = this, --u);
+        l &gt; u;
+        u++)if (null != (o = arguments[u]))
+            for (i in o)
+                e = s[i], r = o[i], s !== r &amp;&amp; (c &amp;&amp; r &amp;&amp; (b.isPlainObject(r) || (n = b.isArray(r))) ? (n ? (n=!1, a = e &amp;&amp; b.isArray(e) ? e : []) : a = e &amp;&amp; b.isPlainObject(e) ? e : {}, s[i] = b.extend(c, a, r)) : r !== t &amp;&amp; (s[i] = r));
+        return s
+    }, b.extend({
+        noConflict: function(t) {
+            return e.$ === b &amp;&amp; (e.$ = u), t &amp;&amp; e.jQuery === b &amp;&amp; (e.jQuery = s), b
+        },
+        isReady: !1,
+        readyWait: 1,
+        holdReady: function(e) {
+            e ? b.readyWait++ : b.ready(!0)
+        },
+        ready: function(e) {
+            if (e===!0?!--b.readyWait : !b.isReady) {
+                if (!o.body)
+                    return setTimeout(b.ready);
+                b.isReady=!0, e!==!0&amp;&amp;--b.readyWait &gt; 0 || (n.resolveWith(o, [b]), b.fn.trigger &amp;&amp; b(o).trigger(&quot;ready&quot;).off(&quot;ready&quot;))
+            }
+        },
+        isFunction: function(e) {
+            return &quot;function&quot; === b.type(e)
+        },
+        isArray: Array.isArray || function(e) {
+            return &quot;array&quot; === b.type(e)
+        },
+        isWindow: function(e) {
+            return null != e &amp;&amp; e == e.window
+        },
+        isNumeric: function(e) {
+            return !isNaN(parseFloat(e)) &amp;&amp; isFinite(e)
+        },
+        type: function(e) {
+            return null == e ? e + &quot;&quot; : &quot;object&quot; == typeof e || &quot;function&quot; == typeof e ? l[m.call(e)] || &quot;object&quot; : typeof e
+        },
+        isPlainObject: function(e) {
+            if (!e || &quot;object&quot; !== b.type(e) || e.nodeType || b.isWindow(e))
+                return !1;
+            try {
+                if (e.constructor&amp;&amp;!y.call(e, &quot;constructor&quot;)&amp;&amp;!y.call(e.constructor.prototype, &quot;isPrototypeOf&quot;))
+                    return !1
+            } catch (n) {
+                return !1
+            }
+            var r;
+            for (r in e);
+            return r === t || y.call(e, r)
+        },
+        isEmptyObject: function(e) {
+            var t;
+            for (t in e)
+                return !1;
+            return !0
+        },
+        error: function(e) {
+            throw Error(e)
+        },
+        parseHTML: function(e, t, n) {
+            if (!e || &quot;string&quot; != typeof e)
+                return null;
+            &quot;boolean&quot; == typeof t &amp;&amp; (n = t, t=!1), t = t || o;
+            var r = C.exec(e), i=!n &amp;&amp; [];
+            return r ? [t.createElement(r[1])] : (r = b.buildFragment([e], t, i), i &amp;&amp; b(i).remove(), b.merge([], r.childNodes))
+        },
+        parseJSON: function(n) {
+            return e.JSON &amp;&amp; e.JSON.parse ? e.JSON.parse(n) : null === n ? n : &quot;string&quot; == typeof n &amp;&amp; (n = b.trim(n), n &amp;&amp; k.test(n.replace(S, &quot;@&quot;).replace(A, &quot;]&quot;).replace(E, &quot;&quot;))) ? Function(&quot;return &quot; + n)() : (b.error(&quot;Invalid JSON: &quot; + n), t)
+        },
+        parseXML: function(n) {
+            var r, i;
+            if (!n || &quot;string&quot; != typeof n)
+                return null;
+            try {
+                e.DOMParser ? (i = new DOMParser, r = i.parseFromString(n, &quot;text/xml&quot;)) : (r = new ActiveXObject(&quot;Microsoft.XMLDOM&quot;), r.async = &quot;false&quot;, r.loadXML(n))
+            } catch (o) {
+                r = t
+            }
+            return r &amp;&amp; r.documentElement&amp;&amp;!r.getElementsByTagName(&quot;parsererror&quot;).length || b.error(&quot;Invalid XML: &quot; + n), r
+        },
+        noop: function() {},
+        globalEval: function(t) {
+            t &amp;&amp; b.trim(t) &amp;&amp; (e.execScript || function(t) {
+                e.eval.call(e, t)
+            })(t)
+        },
+        camelCase: function(e) {
+            return e.replace(j, &quot;ms-&quot;).replace(D, L)
+        },
+        nodeName: function(e, t) {
+            return e.nodeName &amp;&amp; e.nodeName.toLowerCase() === t.toLowerCase()
+        },
+        each: function(e, t, n) {
+            var r, i = 0, o = e.length, a = M(e);
+            if (n) {
+                if (a) {
+                    for (; o &gt; i; i++)
+                        if (r = t.apply(e[i], n), r===!1)
+                            break
+                } else 
+                    for (i in e)
+                        if (r = t.apply(e[i], n), r===!1)
+                            break
+            } else if (a) {
+                for (; o &gt; i; i++)
+                    if (r = t.call(e[i], i, e[i]), r===!1)
+                        break
+            } else 
+                for (i in e)
+                    if (r = t.call(e[i], i, e[i]), r===!1)
+                        break;
+            return e
+        },
+        trim: v&amp;&amp;!v.call(&quot;\ufeff\u00a0&quot;) ? function(e) {
+            return null == e ? &quot;&quot; : v.call(e)
+        }
+        : function(e) {
+            return null == e ? &quot;&quot; : (e + &quot;&quot;).replace(T, &quot;&quot;)
+        },
+        makeArray: function(e, t) {
+            var n = t || [];
+            return null != e &amp;&amp; (M(Object(e)) ? b.merge(n, &quot;string&quot; == typeof e ? [e] : e) : d.call(n, e)), n
+        },
+        inArray: function(e, t, n) {
+            var r;
+            if (t) {
+                if (g)
+                    return g.call(t, e, n);
+                for (r = t.length, n = n ? 0 &gt; n ? Math.max(0, r + n) 
+                    : n:
+                0;
+                r &gt; n;
+                n++)if (n in t &amp;&amp; t[n] === e)
+                    return n
+            }
+            return -1
+        },
+        merge: function(e, n) {
+            var r = n.length, i = e.length, o = 0;
+            if (&quot;number&quot; == typeof r)
+                for (; r &gt; o; o++)
+                    e[i++] = n[o];
+            else 
+                while (n[o] !== t)
+                    e[i++] = n[o++];
+            return e.length = i, e
+        },
+        grep: function(e, t, n) {
+            var r, i = [], o = 0, a = e.length;
+            for (n=!!n; a &gt; o; o++)
+                r=!!t(e[o], o), n !== r &amp;&amp; i.push(e[o]);
+            return i
+        },
+        map: function(e, t, n) {
+            var r, i = 0, o = e.length, a = M(e), s = [];
+            if (a)
+                for (; o &gt; i; i++)
+                    r = t(e[i], i, n), null != r &amp;&amp; (s[s.length] = r);
+            else 
+                for (i in e)
+                    r = t(e[i], i, n), null != r &amp;&amp; (s[s.length] = r);
+            return f.apply([], s)
+        },
+        guid: 1,
+        proxy: function(e, n) {
+            var r, i, o;
+            return &quot;string&quot; == typeof n &amp;&amp; (o = e[n], n = e, e = o), b.isFunction(e) ? (r = h.call(arguments, 2), i = function() {
+                return e.apply(n || this, r.concat(h.call(arguments)))
+            }, i.guid = e.guid = e.guid || b.guid++, i) : t
+        },
+        access: function(e, n, r, i, o, a, s) {
+            var u = 0, l = e.length, c = null == r;
+            if (&quot;object&quot; === b.type(r)) {
+                o=!0;
+                for (u in r)
+                    b.access(e, n, u, r[u], !0, a, s)
+            } else if (i !== t &amp;&amp; (o=!0, b.isFunction(i) || (s=!0), c &amp;&amp; (s ? (n.call(e, i)
+                , n = null) : (c = n, n = function(e, t, n) {
+                return c.call(b(e), n)
+            })), n))for (; l &gt; u; u++)
+                n(e[u], r, s ? i : i.call(e[u], u, n(e[u], r)));
+            return o ? e : c ? n.call(e) : l ? n(e[0], r) : a
+        },
+        now: function() {
+            return (new Date).getTime()
+        }
+    }), b.ready.promise = function(t) {
+        if (!n)
+            if (n = b.Deferred(), &quot;complete&quot; === o.readyState)
+                setTimeout(b.ready);
+            else if (o.addEventListener)
+                o.addEventListener(&quot;DOMContentLoaded&quot;, H, !1), e.addEventListener(&quot;load&quot;, H, !1);
+        else {
+            o.attachEvent(&quot;onreadystatechange&quot;, H), e.attachEvent(&quot;onload&quot;, H);
+            var r=!1;
+            try {
+                r = null == e.frameElement &amp;&amp; o.documentElement
+            } catch (i) {}
+            r &amp;&amp; r.doScroll &amp;&amp; function a() {
+                if (!b.isReady) {
+                    try {
+                        r.doScroll(&quot;left&quot;)
+                    } catch (e) {
+                        return setTimeout(a, 50)
+                    }
+                    q(), b.ready()
+                }
+            }()
+        }
+        return n.promise(t)
+    }, b.each(&quot;Boolean Number String Function Array Date RegExp Object Error&quot;.split(&quot; &quot;), function(e, t) {
+        l[&quot;[object &quot; + t + &quot;]&quot;] = t.toLowerCase()
+    });
+    function M(e) {
+        var t = e.length, n = b.type(e);
+        return b.isWindow(e)?!1 : 1 === e.nodeType &amp;&amp; t?!0 : &quot;array&quot; === n || &quot;function&quot; !== n &amp;&amp; (0 === t || &quot;number&quot; == typeof t &amp;&amp; t &gt; 0 &amp;&amp; t-1 in e)
+    }
+    r = b(o);
+    var _ = {};
+    function F(e) {
+        var t = _[e] = {};
+        return b.each(e.match(w) || [], function(e, n) {
+            t[n]=!0
+        }), t
+    }
+    b.Callbacks = function(e) {
+        e = &quot;string&quot; == typeof e ? _[e] || F(e) : b.extend({}, e);
+        var n, r, i, o, a, s, u = [], l=!e.once &amp;&amp; [], c = function(t) {
+            for (r = e.memory &amp;&amp; t, i=!0, a = s || 0, s = 0, o = u.length, n=!0; u &amp;&amp; o &gt; a; a++)
+                if (u[a].apply(t[0], t[1])===!1 &amp;&amp; e.stopOnFalse) {
+                    r=!1;
+                    break
+                }
+            n=!1, u &amp;&amp; (l ? l.length &amp;&amp; c(l.shift()) : r ? u = [] : p.disable())
+        }, p = {
+            add: function() {
+                if (u) {
+                    var t = u.length;
+                    (function i(t) {
+                        b.each(t, function(t, n) {
+                            var r = b.type(n);
+                            &quot;function&quot; === r ? e.unique &amp;&amp; p.has(n) || u.push(n) : n &amp;&amp; n.length &amp;&amp; &quot;string&quot; !== r &amp;&amp; i(n)
+                        })
+                    })(arguments), n ? o = u.length : r &amp;&amp; (s = t, c(r))
+                }
+                return this
+            },
+            remove: function() {
+                return u &amp;&amp; b.each(arguments, function(e, t) {
+                    var r;
+                    while ((r = b.inArray(t, u, r))&gt;-1)
+                        u.splice(r, 1), n &amp;&amp; (o &gt;= r &amp;&amp; o--, a &gt;= r &amp;&amp; a--)
+                }), this
+            },
+            has: function(e) {
+                return e ? b.inArray(e, u)&gt;-1 : !(!u ||!u.length)
+            },
+            empty: function() {
+                return u = [], this
+            },
+            disable: function() {
+                return u = l = r = t, this
+            },
+            disabled: function() {
+                return !u
+            },
+            lock: function() {
+                return l = t, r || p.disable(), this
+            },
+            locked: function() {
+                return !l
+            },
+            fireWith: function(e, t) {
+                return t = t || [], t = [e, t.slice ? t.slice(): t], !u || i&amp;&amp;!l || (n ? l.push(t) : c(t)), this
+            },
+            fire: function() {
+                return p.fireWith(this, arguments), this
+            },
+            fired: function() {
+                return !!i
+            }
+        };
+        return p
+    }, b.extend({
+        Deferred: function(e) {
+            var t = [[&quot;resolve&quot;, &quot;done&quot;, b.Callbacks(&quot;once memory&quot;), &quot;resolved&quot;], [&quot;reject&quot;, &quot;fail&quot;, b.Callbacks(&quot;once memory&quot;), &quot;rejected&quot;], [&quot;notify&quot;, &quot;progress&quot;, b.Callbacks(&quot;memory&quot;)]], n = &quot;pending&quot;, r = {
+                state: function() {
+                    return n
+                },
+                always: function() {
+                    return i.done(arguments).fail(arguments), this
+                },
+                then: function() {
+                    var e = arguments;
+                    return b.Deferred(function(n) {
+                        b.each(t, function(t, o) {
+                            var a = o[0], s = b.isFunction(e[t]) &amp;&amp; e[t];
+                            i[o[1]](function() {
+                                var e = s &amp;&amp; s.apply(this, arguments);
+                                e &amp;&amp; b.isFunction(e.promise) ? e.promise().done(n.resolve).fail(n.reject).progress(n.notify) : n[a + &quot;With&quot;](this === r ? n.promise() : this, s ? [e] : arguments)
+                            })
+                        }), e = null
+                    }).promise()
+                },
+                promise: function(e) {
+                    return null != e ? b.extend(e, r) : r
+                }
+            }, i = {};
+            return r.pipe = r.then, b.each(t, function(e, o) {
+                var a = o[2], s = o[3];
+                r[o[1]] = a.add, s &amp;&amp; a.add(function() {
+                    n = s
+                }, t[1^e][2].disable, t[2][2].lock), i[o[0]] = function() {
+                    return i[o[0] + &quot;With&quot;](this === i ? r : this, arguments), this
+                }, i[o[0] + &quot;With&quot;] = a.fireWith
+            }), r.promise(i), e &amp;&amp; e.call(i, i), i
+        },
+        when: function(e) {
+            var t = 0, n = h.call(arguments), r = n.length, i = 1 !== r || e &amp;&amp; b.isFunction(e.promise) ? r: 0, o = 1 === i ? e: b.Deferred(), a = function(e, t, n) {
+                return function(r) {
+                    t[e] = this, n[e] = arguments.length &gt; 1 ? h.call(arguments) : r, n === s ? o.notifyWith(t, n) : --i || o.resolveWith(t, n)
+                }
+            }, s, u, l;
+            if (r &gt; 1)
+                for (s = Array(r), u = Array(r)
+                    , l = Array(r);
+            r &gt; t;
+            t++)n[t] &amp;&amp; b.isFunction(n[t].promise) ? n[t].promise().done(a(t, l, n)).fail(o.reject).progress(a(t, u, s)) : --i;
+            return i || o.resolveWith(l, n), o.promise()
+        }
+    }), b.support = function() {
+        var t, n, r, a, s, u, l, c, p, f, d = o.createElement(&quot;div&quot;);
+        if (d.setAttribute(&quot;className&quot;, &quot;t&quot;), d.innerHTML = &quot;  &lt;link/&gt;&lt;table&gt;&lt;/table&gt;&lt;a href='/a'&gt;a&lt;/a&gt;&lt;input type='checkbox'/&gt;&quot;, n = d.getElementsByTagName(&quot;*&quot;)
+            , r = d.getElementsByTagName(&quot;a&quot;)[0], !n ||!r ||!n.length)return {};
+        s = o.createElement(&quot;select&quot;), l = s.appendChild(o.createElement(&quot;option&quot;)), a = d.getElementsByTagName(&quot;input&quot;)[0], r.style.cssText = &quot;top:1px;float:left;opacity:.5&quot;, t = {
+            getSetAttribute: &quot;t&quot; !== d.className,
+            leadingWhitespace: 3 === d.firstChild.nodeType,
+            tbody: !d.getElementsByTagName(&quot;tbody&quot;).length,
+            htmlSerialize: !!d.getElementsByTagName(&quot;link&quot;).length,
+            style: /top/.test(r.getAttribute(&quot;style&quot;)),
+            hrefNormalized: &quot;/a&quot; === r.getAttribute(&quot;href&quot;),
+            opacity: /^0.5/.test(r.style.opacity),
+            cssFloat: !!r.style.cssFloat,
+            checkOn: !!a.value,
+            optSelected: l.selected,
+            enctype: !!o.createElement(&quot;form&quot;).enctype,
+            html5Clone: &quot;&lt;:nav&gt;&lt;/:nav&gt;&quot; !== o.createElement(&quot;nav&quot;).cloneNode(!0).outerHTML,
+            boxModel: &quot;CSS1Compat&quot; === o.compatMode,
+            deleteExpando: !0,
+            noCloneEvent: !0,
+            inlineBlockNeedsLayout: !1,
+            shrinkWrapBlocks: !1,
+            reliableMarginRight: !0,
+            boxSizingReliable: !0,
+            pixelPosition: !1
+        }, a.checked=!0, t.noCloneChecked = a.cloneNode(!0).checked, s.disabled=!0, t.optDisabled=!l.disabled;
+        try {
+            delete d.test
+        } catch (h) {
+            t.deleteExpando=!1
+        }
+        a = o.createElement(&quot;input&quot;), a.setAttribute(&quot;value&quot;, &quot;&quot;), t.input = &quot;&quot; === a.getAttribute(&quot;value&quot;), a.value = &quot;t&quot;, a.setAttribute(&quot;type&quot;, &quot;radio&quot;), t.radioValue = &quot;t&quot; === a.value, a.setAttribute(&quot;checked&quot;, &quot;t&quot;), a.setAttribute(&quot;name&quot;, &quot;t&quot;), u = o.createDocumentFragment(), u.appendChild(a), t.appendChecked = a.checked, t.checkClone = u.cloneNode(!0).cloneNode(!0).lastChild.checked, d.attachEvent &amp;&amp; (d.attachEvent(&quot;onclick&quot;, function() {
+            t.noCloneEvent=!1
+        }), d.cloneNode(!0).click());
+        for (f in{
+            submit: !0,
+            change: !0,
+            focusin: !0
+        })
+            d.setAttribute(c = &quot;on&quot; + f, &quot;t&quot;), t[f + &quot;Bubbles&quot;] = c in e || d.attributes[c].expando===!1;
+        return d.style.backgroundClip = &quot;content-box&quot;, d.cloneNode(!0).style.backgroundClip = &quot;&quot;, t.clearCloneStyle = &quot;content-box&quot; === d.style.backgroundClip, b(function() {
+            var n, r, a, s = &quot;padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;&quot;, u = o.getElementsByTagName(&quot;body&quot;)[0];
+            u &amp;&amp; (n = o.createElement(&quot;div&quot;), n.style.cssText = &quot;border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px&quot;, u.appendChild(n).appendChild(d), d.innerHTML = &quot;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;t&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&quot;, a = d.getElementsByTagName(&quot;td&quot;), a[0].style.cssText = &quot;padding:0;margin:0;border:0;display:none&quot;, p = 0 === a[0].offsetHeight, a[0].style.display = &quot;&quot;, a[1].style.display = &quot;none&quot;, t.reliableHiddenOffsets = p &amp;&amp; 0 === a[0].offsetHeight, d.innerHTML = &quot;&quot;, d.style.cssText = &quot;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;&quot;, t.boxSizing = 4 === d.offsetWidth, t.doesNotIncludeMarginInBodyOffset = 1 !== u.offsetTop, e.getComputedStyle &amp;&amp; (t.pixelPosition = &quot;1%&quot; !== (e.getComputedStyle(d, null) || {}).top, t.boxSizingReliable = &quot;4px&quot; === (e.getComputedStyle(d, null) || {
+                width: &quot;4px&quot;
+            }).width, r = d.appendChild(o.createElement(&quot;div&quot;)), r.style.cssText = d.style.cssText = s, r.style.marginRight = r.style.width = &quot;0&quot;, d.style.width = &quot;1px&quot;, t.reliableMarginRight=!parseFloat((e.getComputedStyle(r, null) || {}).marginRight)), typeof d.style.zoom !== i &amp;&amp; (d.innerHTML = &quot;&quot;, d.style.cssText = s + &quot;width:1px;padding:1px;display:inline;zoom:1&quot;, t.inlineBlockNeedsLayout = 3 === d.offsetWidth, d.style.display = &quot;block&quot;, d.innerHTML = &quot;&lt;div&gt;&lt;/div&gt;&quot;, d.firstChild.style.width = &quot;5px&quot;, t.shrinkWrapBlocks = 3 !== d.offsetWidth, t.inlineBlockNeedsLayout &amp;&amp; (u.style.zoom = 1)), u.removeChild(n), n = d = a = r = null)
+        }), n = s = u = l = r = a = null, t
+    }();
+    var O = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, B = /([A-Z])/g;
+    function P(e, n, r, i) {
+        if (b.acceptData(e)) {
+            var o, a, s = b.expando, u = &quot;string&quot; == typeof n, l = e.nodeType, p = l ? b.cache: e, f = l ? e[s]: e[s] &amp;&amp; s;
+            if (f &amp;&amp; p[f] &amp;&amp; (i || p[f].data) ||!u || r !== t)
+                return f || (l ? e[s] = f = c.pop() || b.guid++ : f = s), p[f] || (p[f] = {}, l || (p[f].toJSON = b.noop)), (&quot;object&quot; == typeof n || &quot;function&quot; == typeof n) &amp;&amp; (i ? p[f] = b.extend(p[f], n) : p[f].data = b.extend(p[f].data, n)), o = p[f], i || (o.data || (o.data = {}), o = o.data), r !== t &amp;&amp; (o[b.camelCase(n)] = r), u ? (a = o[n], null == a &amp;&amp; (a = o[b.camelCase(n)])) : a = o, a
+        }
+    }
+    function R(e, t, n) {
+        if (b.acceptData(e)) {
+            var r, i, o, a = e.nodeType, s = a ? b.cache: e, u = a ? e[b.expando]: b.expando;
+            if (s[u]) {
+                if (t &amp;&amp; (o = n ? s[u] : s[u].data)) {
+                    b.isArray(t) ? t = t.concat(b.map(t, b.camelCase)) : t in o ? t = [t] : (t = b.camelCase(t), t = t in o ? [t] : t.split(&quot; &quot;));
+                    for (r = 0, i = t.length; i &gt; r; r++)
+                        delete o[t[r]];
+                    if (!(n ? $ : b.isEmptyObject)(o))
+                        return 
+                }(n || (delete s[u].data, $(s[u]))) &amp;&amp; (a ? b.cleanData([e], !0) : b.support.deleteExpando || s != s.window ? delete s[u] : s[u] = null)
+            }
+        }
+    }
+    b.extend({
+        cache: {},
+        expando: &quot;jQuery&quot; + (p + Math.random()).replace(/\D/g, &quot;&quot;),
+        noData: {
+            embed: !0,
+            object: &quot;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&quot;,
+            applet: !0
+        },
+        hasData: function(e) {
+            return e = e.nodeType ? b.cache[e[b.expando]] : e[b.expando], !!e&amp;&amp;!$(e)
+        },
+        data: function(e, t, n) {
+            return P(e, t, n)
+        },
+        removeData: function(e, t) {
+            return R(e, t)
+        },
+        _data: function(e, t, n) {
+            return P(e, t, n, !0)
+        },
+        _removeData: function(e, t) {
+            return R(e, t, !0)
+        },
+        acceptData: function(e) {
+            if (e.nodeType &amp;&amp; 1 !== e.nodeType &amp;&amp; 9 !== e.nodeType)
+                return !1;
+            var t = e.nodeName &amp;&amp; b.noData[e.nodeName.toLowerCase()];
+            return !t || t!==!0 &amp;&amp; e.getAttribute(&quot;classid&quot;) === t
+        }
+    }), b.fn.extend({
+        data: function(e, n) {
+            var r, i, o = this[0], a = 0, s = null;
+            if (e === t) {
+                if (this.length &amp;&amp; (s = b.data(o), 1 === o.nodeType&amp;&amp;!b._data(o, &quot;parsedAttrs&quot;))
+                    ) {
+                    for (r = o.attributes; r.length &gt; a; a++)
+                        i = r[a].name, i.indexOf(&quot;data-&quot;) || (i = b.camelCase(i.slice(5)), W(o, i, s[i]));
+                    b._data(o, &quot;parsedAttrs&quot;, !0)
+                }
+                return s
+            }
+            return &quot;object&quot; == typeof e ? this.each(function() {
+                b.data(this, e)
+            }) : b.access(this, function(n) {
+                return n === t ? o ? W(o, e, b.data(o, e)) : null : (this.each(function() {
+                    b.data(this, e, n)
+                }), t)
+            }, null, n, arguments.length &gt; 1, null, !0)
+        },
+        removeData: function(e) {
+            return this.each(function() {
+                b.removeData(this, e)
+            })
+        }
+    });
+    function W(e, n, r) {
+        if (r === t &amp;&amp; 1 === e.nodeType) {
+            var i = &quot;data-&quot; + n.replace(B, &quot;-$1&quot;).toLowerCase();
+            if (r = e.getAttribute(i), &quot;string&quot; == typeof r) {
+                try {
+                    r = &quot;true&quot; === r?!0 : &quot;false&quot; === r?!1 : &quot;null&quot; === r ? null : + r + &quot;&quot; === r?+r : O.test(r) ? b.parseJSON(r) : r
+                } catch (o) {}
+                b.data(e, n, r)
+            } else 
+                r = t
+        }
+        return r
+    }
+    function $(e) {
+        var t;
+        for (t in e)
+            if ((&quot;data&quot; !== t ||!b.isEmptyObject(e[t])) &amp;&amp; &quot;toJSON&quot; !== t)
+                return !1;
+        return !0
+    }
+    b.extend({
+        queue: function(e, n, r) {
+            var i;
+            return e ? (n = (n || &quot;fx&quot;) + &quot;queue&quot;, i = b._data(e, n), r &amp;&amp; (!i || b.isArray(r) ? i = b._data(e, n, b.makeArray(r)) : i.push(r)), i || []) : t
+        },
+        dequeue: function(e, t) {
+            t = t || &quot;fx&quot;;
+            var n = b.queue(e, t), r = n.length, i = n.shift(), o = b._queueHooks(e, t), a = function() {
+                b.dequeue(e, t)
+            };
+            &quot;inprogress&quot; === i &amp;&amp; (i = n.shift(), r--), o.cur = i, i &amp;&amp; (&quot;fx&quot; === t &amp;&amp; n.unshift(&quot;inprogress&quot;), delete o.stop, i.call(e, a, o)), !r &amp;&amp; o &amp;&amp; o.empty.fire()
+        },
+        _queueHooks: function(e, t) {
+            var n = t + &quot;queueHooks&quot;;
+            return b._data(e, n) || b._data(e, n, {
+                empty: b.Callbacks(&quot;once memory&quot;).add(function() {
+                    b._removeData(e, t + &quot;queue&quot;), b._removeData(e, n)
+                })
+            })
+        }
+    }), b.fn.extend({
+        queue: function(e, n) {
+            var r = 2;
+            return &quot;string&quot; != typeof e &amp;&amp; (n = e, e = &quot;fx&quot;, r--), r &gt; arguments.length ? b.queue(this[0], e) : n === t ? this : this.each(function() {
+                var t = b.queue(this, e, n);
+                b._queueHooks(this, e), &quot;fx&quot; === e &amp;&amp; &quot;inprogress&quot; !== t[0] &amp;&amp; b.dequeue(this, e)
+            })
+        },
+        dequeue: function(e) {
+            return this.each(function() {
+                b.dequeue(this, e)
+            })
+        },
+        delay: function(e, t) {
+            return e = b.fx ? b.fx.speeds[e] || e : e, t = t || &quot;fx&quot;, this.queue(t, function(t, n) {
+                var r = setTimeout(t, e);
+                n.stop = function() {
+                    clearTimeout(r)
+                }
+            })
+        },
+        clearQueue: function(e) {
+            return this.queue(e || &quot;fx&quot;, [])
+        },
+        promise: function(e, n) {
+            var r, i = 1, o = b.Deferred(), a = this, s = this.length, u = function() {
+                --i || o.resolveWith(a, [a])
+            };
+            &quot;string&quot; != typeof e &amp;&amp; (n = e, e = t), e = e || &quot;fx&quot;;
+            while (s--)
+                r = b._data(a[s], e + &quot;queueHooks&quot;), r &amp;&amp; r.empty &amp;&amp; (i++, r.empty.add(u));
+            return u(), o.promise(n)
+        }
+    });
+    var I, z, X = /[\t\r\n]/g, U = /\r/g, V = /^(?:input|select|textarea|button|object)$/i, Y = /^(?:a|area)$/i, J = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, G = /^(?:checked|selected)$/i, Q = b.support.getSetAttribute, K = b.support.input;
+    b.fn.extend({
+        attr: function(e, t) {
+            return b.access(this, b.attr, e, t, arguments.length &gt; 1)
+        },
+        removeAttr: function(e) {
+            return this.each(function() {
+                b.removeAttr(this, e)
+            })
+        },
+        prop: function(e, t) {
+            return b.access(this, b.prop, e, t, arguments.length &gt; 1)
+        },
+        removeProp: function(e) {
+            return e = b.propFix[e] || e, this.each(function() {
+                try {
+                    this[e] = t, delete this[e]
+                } catch (n) {}
+            })
+        },
+        addClass: function(e) {
+            var t, n, r, i, o, a = 0, s = this.length, u = &quot;string&quot; == typeof e &amp;&amp; e;
+            if (b.isFunction(e))
+                return this.each(function(t) {
+                    b(this).addClass(e.call(this, t, this.className))
+                });
+            if (u)
+                for (t = (e || &quot;&quot;).match(w) || []; s &gt; a; a++)
+                    if (n = this[a], r = 1 === n.nodeType &amp;&amp; (n.className ? (&quot; &quot; + n.className + &quot; &quot;).replace(X, &quot; &quot;) 
+                        : &quot; &quot;)) {
+                o = 0;
+                while (i = t[o++])
+                    0 &gt; r.indexOf(&quot; &quot; + i + &quot; &quot;) &amp;&amp; (r += i + &quot; &quot;);
+                n.className = b.trim(r)
+            }
+            return this
+        },
+        removeClass: function(e) {
+            var t, n, r, i, o, a = 0, s = this.length, u = 0 === arguments.length || &quot;string&quot; == typeof e &amp;&amp; e;
+            if (b.isFunction(e))
+                return this.each(function(t) {
+                    b(this).removeClass(e.call(this, t, this.className))
+                });
+            if (u)
+                for (t = (e || &quot;&quot;).match(w) || []; s &gt; a; a++)
+                    if (n = this[a], r = 1 === n.nodeType &amp;&amp; (n.className ? (&quot; &quot; + n.className + &quot; &quot;).replace(X, &quot; &quot;) 
+                        : &quot;&quot;)) {
+                o = 0;
+                while (i = t[o++])
+                    while (r.indexOf(&quot; &quot; + i + &quot; &quot;) &gt;= 0)
+                        r = r.replace(&quot; &quot; + i + &quot; &quot;, &quot; &quot;);
+                n.className = e ? b.trim(r) : &quot;&quot;
+            }
+            return this
+        },
+        toggleClass: function(e, t) {
+            var n = typeof e, r = &quot;boolean&quot; == typeof t;
+            return b.isFunction(e) ? this.each(function(n) {
+                b(this).toggleClass(e.call(this, n, this.className, t), t)
+            }) : this.each(function() {
+                if (&quot;string&quot; === n) {
+                    var o, a = 0, s = b(this), u = t, l = e.match(w) || [];
+                    while (o = l[a++])
+                        u = r ? u : !s.hasClass(o), s[u ? &quot;addClass&quot;: &quot;removeClass&quot;](o)
+                } else (n === i || &quot;boolean&quot; === n) 
+                    &amp;&amp; (this.className &amp;&amp; b._data(this, &quot;__className__&quot;, this.className), this.className = this.className || e===!1 ? &quot;&quot; : b._data(this, &quot;__className__&quot;) || &quot;&quot;)
+            })
+        },
+        hasClass: function(e) {
+            var t = &quot; &quot; + e + &quot; &quot;, n = 0, r = this.length;
+            for (; r &gt; n; n++)
+                if (1 === this[n].nodeType &amp;&amp; (&quot; &quot; + this[n].className + &quot; &quot;).replace(X, &quot; &quot;).indexOf(t) &gt;= 0)
+                    return !0;
+            return !1
+        },
+        val: function(e) {
+            var n, r, i, o = this[0];
+            {
+                if (arguments.length)
+                    return i = b.isFunction(e), this.each(function(n) {
+                    var o, a = b(this);
+                    1 === this.nodeType &amp;&amp; (o = i ? e.call(this, n, a.val()) : e, null == o ? o = &quot;&quot; : &quot;number&quot; == typeof o ? o += &quot;&quot; : b.isArray(o) &amp;&amp; (o = b.map(o, function(e) {
+                        return null == e ? &quot;&quot; : e + &quot;&quot;
+                    })), r = b.valHooks[this.type] || b.valHooks[this.nodeName.toLowerCase()], r &amp;&amp; &quot;set&quot;in r &amp;&amp; r.set(this, o, &quot;value&quot;) !== t || (this.value = o))
+                });
+                if (o)
+                    return r = b.valHooks[o.type] || b.valHooks[o.nodeName.toLowerCase()], r &amp;&amp; &quot;get&quot;in r &amp;&amp; (n = r.get(o, &quot;value&quot;)) !== t ? n : (n = o.value, &quot;string&quot; == typeof n ? n.replace(U, &quot;&quot;) : null == n ? &quot;&quot; : n)
+            }
+        }
+    }), b.extend({
+        valHooks: {
+            option: {
+                get: function(e) {
+                    var t = e.attributes.value;
+                    return !t || t.specified ? e.value : e.text
+                }
+            },
+            select: {
+                get: function(e) {
+                    var t, n, r = e.options, i = e.selectedIndex, o = &quot;select-one&quot; === e.type || 0 &gt; i, a = o ? null: [], s = o ? i + 1: r.length, u = 0 &gt; i ? s: o ? i: 0;
+                    for (; s &gt; u; u++)
+                        if (n = r[u], !(!n.selected &amp;&amp; u !== i || (b.support.optDisabled ? n.disabled : null !== n.getAttribute(&quot;disabled&quot;)
+                            ) || n.parentNode.disabled &amp;&amp; b.nodeName(n.parentNode, &quot;optgroup&quot;))) {
+                        if (t = b(n).val(), o)
+                            return t;
+                        a.push(t)
+                    }
+                    return a
+                },
+                set: function(e, t) {
+                    var n = b.makeArray(t);
+                    return b(e).find(&quot;option&quot;).each(function() {
+                        this.selected = b.inArray(b(this).val(), n) &gt;= 0
+                    }), n.length || (e.selectedIndex =- 1), n
+                }
+            }
+        },
+        attr: function(e, n, r) {
+            var o, a, s, u = e.nodeType;
+            if (e &amp;&amp; 3 !== u &amp;&amp; 8 !== u &amp;&amp; 2 !== u)
+                return typeof e.getAttribute === i ? b.prop(e, n, r) : (a = 1 !== u ||!b.isXMLDoc(e), a &amp;&amp; (n = n.toLowerCase(), o = b.attrHooks[n] || (J.test(n) ? z : I)), r === t ? o &amp;&amp; a &amp;&amp; &quot;get&quot;in o &amp;&amp; null !== (s = o.get(e, n)) ? s : (typeof e.getAttribute !== i &amp;&amp; (s = e.getAttribute(n)), null == s ? t : s) : null !== r ? o &amp;&amp; a &amp;&amp; &quot;set&quot;in o &amp;&amp; (s = o.set(e, r, n)) !== t ? s : (e.setAttribute(n, r + &quot;&quot;), r) : (b.removeAttr(e, n), t))
+        },
+        removeAttr: function(e, t) {
+            var n, r, i = 0, o = t &amp;&amp; t.match(w);
+            if (o &amp;&amp; 1 === e.nodeType)
+                while (n = o[i++])
+                    r = b.propFix[n] || n, J.test(n)?!Q &amp;&amp; G.test(n) ? e[b.camelCase(&quot;default-&quot; + n)] = e[r]=!1 : e[r]=!1 : b.attr(e, n, &quot;&quot;), e.removeAttribute(Q ? n : r)
+        },
+        attrHooks: {
+            type: {
+                set: function(e, t) {
+                    if (!b.support.radioValue &amp;&amp; &quot;radio&quot; === t &amp;&amp; b.nodeName(e, &quot;input&quot;)) {
+                        var n = e.value;
+                        return e.setAttribute(&quot;type&quot;, t), n &amp;&amp; (e.value = n), t
+                    }
+                }
+            }
+        },
+        propFix: {
+            tabindex: &quot;tabIndex&quot;,
+            readonly: &quot;readOnly&quot;,
+            &quot;for&quot;: &quot;htmlFor&quot;,
+            &quot;class&quot;: &quot;className&quot;,
+            maxlength: &quot;maxLength&quot;,
+            cellspacing: &quot;cellSpacing&quot;,
+            cellpadding: &quot;cellPadding&quot;,
+            rowspan: &quot;rowSpan&quot;,
+            colspan: &quot;colSpan&quot;,
+            usemap: &quot;useMap&quot;,
+            frameborder: &quot;frameBorder&quot;,
+            contenteditable: &quot;contentEditable&quot;
+        },
+        prop: function(e, n, r) {
+            var i, o, a, s = e.nodeType;
+            if (e &amp;&amp; 3 !== s &amp;&amp; 8 !== s &amp;&amp; 2 !== s)
+                return a = 1 !== s ||!b.isXMLDoc(e), a &amp;&amp; (n = b.propFix[n] || n, o = b.propHooks[n]), r !== t ? o &amp;&amp; &quot;set&quot;in o &amp;&amp; (i = o.set(e, r, n)) !== t ? i : e[n] = r : o &amp;&amp; &quot;get&quot;in o &amp;&amp; null !== (i = o.get(e, n)) ? i : e[n]
+        },
+        propHooks: {
+            tabIndex: {
+                get: function(e) {
+                    var n = e.getAttributeNode(&quot;tabindex&quot;);
+                    return n &amp;&amp; n.specified ? parseInt(n.value, 10) : V.test(e.nodeName) || Y.test(e.nodeName) &amp;&amp; e.href ? 0 : t
+                }
+            }
+        }
+    }), z = {
+        get: function(e, n) {
+            var r = b.prop(e, n), i = &quot;boolean&quot; == typeof r &amp;&amp; e.getAttribute(n), o = &quot;boolean&quot; == typeof r ? K &amp;&amp; Q ? null != i: G.test(n) ? e[b.camelCase(&quot;default-&quot; + n)]: !!i: e.getAttributeNode(n);
+            return o &amp;&amp; o.value!==!1 ? n.toLowerCase() : t
+        },
+        set: function(e, t, n) {
+            return t===!1 ? b.removeAttr(e, n) : K &amp;&amp; Q ||!G.test(n) ? e.setAttribute(!Q &amp;&amp; b.propFix[n] || n, n) : e[b.camelCase(&quot;default-&quot; + n)] = e[n]=!0, n
+        }
+    }, K &amp;&amp; Q || (b.attrHooks.value = {
+        get: function(e, n) {
+            var r = e.getAttributeNode(n);
+            return b.nodeName(e, &quot;input&quot;) ? e.defaultValue : r &amp;&amp; r.specified ? r.value : t
+        },
+        set: function(e, n, r) {
+            return b.nodeName(e, &quot;input&quot;) ? (e.defaultValue = n, t) : I &amp;&amp; I.set(e, n, r)
+        }
+    }), Q || (I = b.valHooks.button = {
+        get: function(e, n) {
+            var r = e.getAttributeNode(n);
+            return r &amp;&amp; (&quot;id&quot; === n || &quot;name&quot; === n || &quot;coords&quot; === n ? &quot;&quot; !== r.value : r.specified) ? r.value : t
+        },
+        set: function(e, n, r) {
+            var i = e.getAttributeNode(r);
+            return i || e.setAttributeNode(i = e.ownerDocument.createAttribute(r)), i.value = n += &quot;&quot;, &quot;value&quot; === r || n === e.getAttribute(r) ? n : t
+        }
+    }, b.attrHooks.contenteditable = {
+        get : I.get, set : function(e, t, n) {
+            I.set(e, &quot;&quot; === t?!1 : t, n)
+        }
+    }, b.each([&quot;width&quot;, &quot;height&quot;], function(e, n) {
+        b.attrHooks[n] = b.extend(b.attrHooks[n], {
+            set: function(e, r) {
+                return &quot;&quot; === r ? (e.setAttribute(n, &quot;auto&quot;), r) : t
+            }
+        })
+    })), b.support.hrefNormalized || (b.each([&quot;href&quot;, &quot;src&quot;, &quot;width&quot;, &quot;height&quot;], function(e, n) {
+        b.attrHooks[n] = b.extend(b.attrHooks[n], {
+            get: function(e) {
+                var r = e.getAttribute(n, 2);
+                return null == r ? t : r
+            }
+        })
+    }), b.each([&quot;href&quot;, &quot;src&quot;], function(e, t) {
+        b.propHooks[t] = {
+            get: function(e) {
+                return e.getAttribute(t, 4)
+            }
+        }
+    })), b.support.style || (b.attrHooks.style = {
+        get: function(e) {
+            return e.style.cssText || t
+        },
+        set: function(e, t) {
+            return e.style.cssText = t + &quot;&quot;
+        }
+    }), b.support.optSelected || (b.propHooks.selected = b.extend(b.propHooks.selected, {
+        get: function(e) {
+            var t = e.parentNode;
+            return t &amp;&amp; (t.selectedIndex, t.parentNode &amp;&amp; t.parentNode.selectedIndex), null
+        }
+    })), b.support.enctype || (b.propFix.enctype = &quot;encoding&quot;), b.support.checkOn || b.each([&quot;radio&quot;, &quot;checkbox&quot;], function() {
+        b.valHooks[this] = {
+            get: function(e) {
+                return null === e.getAttribute(&quot;value&quot;) ? &quot;on&quot; : e.value
+            }
+        }
+    }), b.each([&quot;radio&quot;, &quot;checkbox&quot;], function() {
+        b.valHooks[this] = b.extend(b.valHooks[this], {
+            set: function(e, n) {
+                return b.isArray(n) ? e.checked = b.inArray(b(e).val(), n) &gt;= 0 : t
+            }
+        })
+    });
+    var Z = /^(?:input|select|textarea)$/i, et = /^key/, tt = /^(?:mouse|contextmenu)|click/, nt = /^(?:focusinfocus|focusoutblur)$/, rt = /^([^.]*)(?:\.(.+)|)$/;
+    function it() {
+        return !0
+    }
+    function ot() {
+        return !1
+    }
+    b.event = {
+        global: {},
+        add: function(e, n, r, o, a) {
+            var s, u, l, c, p, f, d, h, g, m, y, v = b._data(e);
+            if (v) {
+                r.handler &amp;&amp; (c = r, r = c.handler, a = c.selector), r.guid || (r.guid = b.guid++), (u = v.events) || (u = v.events = {}), (f = v.handle) || (f = v.handle = function(e) {
+                    return typeof b === i || e &amp;&amp; b.event.triggered === e.type ? t : b.event.dispatch.apply(f.elem, arguments)
+                }, f.elem = e), n = (n || &quot;&quot;).match(w) || [&quot;&quot;], l = n.length;
+                while (l--)
+                    s = rt.exec(n[l]) || [], g = y = s[1], m = (s[2] || &quot;&quot;).split(&quot;.&quot;).sort(), p = b.event.special[g] || {}, g = (a ? p.delegateType : p.bindType) || g, p = b.event.special[g] || {}, d = b.extend({
+                    type: g,
+                    origType: y,
+                    data: o,
+                    handler: r,
+                    guid: r.guid,
+                    selector: a,
+                    needsContext: a &amp;&amp; b.expr.match.needsContext.test(a),
+                    namespace: m.join(&quot;.&quot;)
+                }, c), (h = u[g]) || (h = u[g] = [], h.delegateCount = 0, p.setup &amp;&amp; p.setup.call(e, o, m, f)!==!1 || (e.addEventListener ? e.addEventListener(g, f, !1) : e.attachEvent &amp;&amp; e.attachEvent(&quot;on&quot; + g, f))), p.add &amp;&amp; (p.add.call(e, d), d.handler.guid || (d.handler.guid = r.guid)), a ? h.splice(h.delegateCount++, 0, d) : h.push(d), b.event.global[g]=!0;
+                e = null
+            }
+        },
+        remove: function(e, t, n, r, i) {
+            var o, a, s, u, l, c, p, f, d, h, g, m = b.hasData(e) &amp;&amp; b._data(e);
+            if (m &amp;&amp; (c = m.events)) {
+                t = (t || &quot;&quot;).match(w) || [&quot;&quot;], l = t.length;
+                while (l--)
+                    if (s = rt.exec(t[l]) || [], d = g = s[1], h = (s[2] || &quot;&quot;).split(&quot;.&quot;).sort()
+                        , d) {
+                    p = b.event.special[d] || {}, d = (r ? p.delegateType : p.bindType) || d, f = c[d] || [], s = s[2] &amp;&amp; RegExp(&quot;(^|\\.)&quot; + h.join(&quot;\\.(?:.*\\.|)&quot;) + &quot;(\\.|$)&quot;), u = o = f.length;
+                    while (o--)
+                        a = f[o], !i &amp;&amp; g !== a.origType || n &amp;&amp; n.guid !== a.guid || s&amp;&amp;!s.test(a.namespace) || r &amp;&amp; r !== a.selector &amp;&amp; (&quot;**&quot; !== r ||!a.selector) || (f.splice(o, 1), a.selector &amp;&amp; f.delegateCount--, p.remove &amp;&amp; p.remove.call(e, a));
+                    u&amp;&amp;!f.length &amp;&amp; (p.teardown &amp;&amp; p.teardown.call(e, h, m.handle)!==!1 || b.removeEvent(e, d, m.handle), delete c[d])
+                } else 
+                    for (d in c)
+                        b.event.remove(e, d + t[l], n, r, !0);
+                b.isEmptyObject(c) &amp;&amp; (delete m.handle, b._removeData(e, &quot;events&quot;))
+            }
+        },
+        trigger: function(n, r, i, a) {
+            var s, u, l, c, p, f, d, h = [i || o], g = y.call(n, &quot;type&quot;) ? n.type: n, m = y.call(n, &quot;namespace&quot;) ? n.namespace.split(&quot;.&quot;): [];
+            if (l = f = i = i || o, 3 !== i.nodeType &amp;&amp; 8 !== i.nodeType&amp;&amp;!nt.test(g + b.event.triggered) &amp;&amp; (g.indexOf(&quot;.&quot;) &gt;= 0 &amp;&amp; (m = g.split(&quot;.&quot;), g = m.shift(), m.sort()
+                ), u = 0 &gt; g.indexOf(&quot;:&quot;) &amp;&amp; &quot;on&quot; + g, n = n[b.expando] ? n : new b.Event(g, &quot;object&quot; == typeof n &amp;&amp; n), n.isTrigger=!0, n.namespace = m.join(&quot;.&quot;), n.namespace_re = n.namespace ? RegExp(&quot;(^|\\.)&quot; + m.join(&quot;\\.(?:.*\\.|)&quot;) + &quot;(\\.|$)&quot;) : null, n.result = t, n.target || (n.target = i), r = null == r ? [n] : b.makeArray(r, [n]), p = b.event.special[g] || {}, a ||!p.trigger || p.trigger.apply(i, r)!==!1)) {
+                if (!a&amp;&amp;!p.noBubble&amp;&amp;!b.isWindow(i)) {
+                    for (c = p.delegateType || g, nt.test(c + g) 
+                        || (l = l.parentNode);
+                    l;
+                    l = l.parentNode)h.push(l), f = l;
+                    f === (i.ownerDocument || o) &amp;&amp; h.push(f.defaultView || f.parentWindow || e)
+                }
+                d = 0;
+                while ((l = h[d++])&amp;&amp;!n.isPropagationStopped())
+                    n.type = d &gt; 1 ? c : p.bindType || g, s = (b._data(l, &quot;events&quot;) || {})[n.type] &amp;&amp; b._data(l, &quot;handle&quot;), s &amp;&amp; s.apply(l, r), s = u &amp;&amp; l[u], s &amp;&amp; b.acceptData(l) &amp;&amp; s.apply &amp;&amp; s.apply(l, r)===!1 &amp;&amp; n.preventDefault();
+                if (n.type = g, !(a || n.isDefaultPrevented() || p._default &amp;&amp; p._default.apply(i.ownerDocument, r)!==!1 || &quot;click&quot; === g &amp;&amp; b.nodeName(i, &quot;a&quot;) ||!b.acceptData(i) ||!u ||!i[g] || b.isWindow(i)
+                    )) {
+                    f = i[u], f &amp;&amp; (i[u] = null), b.event.triggered = g;
+                    try {
+                        i[g]()
+                    } catch (v) {}
+                    b.event.triggered = t, f &amp;&amp; (i[u] = f)
+                }
+                return n.result
+            }
+        },
+        dispatch: function(e) {
+            e = b.event.fix(e);
+            var n, r, i, o, a, s = [], u = h.call(arguments), l = (b._data(this, &quot;events&quot;) || {})[e.type] || [], c = b.event.special[e.type] || {};
+            if (u[0] = e, e.delegateTarget = this, !c.preDispatch || c.preDispatch.call(this, e)!==!1) {
+                s = b.event.handlers.call(this, e, l), n = 0;
+                while ((o = s[n++])&amp;&amp;!e.isPropagationStopped()) {
+                    e.currentTarget = o.elem, a = 0;
+                    while ((i = o.handlers[a++])&amp;&amp;!e.isImmediatePropagationStopped())(!e.namespace_re || e.namespace_re.test(i.namespace)) &amp;&amp; (e.handleObj = i, e.data = i.data, r = ((b.event.special[i.origType] || {}).handle || i.handler).apply(o.elem, u), r !== t &amp;&amp; (e.result = r)===!1 &amp;&amp; (e.preventDefault(), e.stopPropagation()))
+                }
+                return c.postDispatch &amp;&amp; c.postDispatch.call(this, e), e.result
+            }
+        },
+        handlers: function(e, n) {
+            var r, i, o, a, s = [], u = n.delegateCount, l = e.target;
+            if (u &amp;&amp; l.nodeType &amp;&amp; (!e.button || &quot;click&quot; !== e.type))
+                for (; l != this; l = l.parentNode || this)
+                    if (1 === l.nodeType &amp;&amp; (l.disabled!==!0 || &quot;click&quot; !== e.type)) {
+                        for (o = [], a = 0;
+                        u &gt; a;
+                        a++)i = n[a], r = i.selector + &quot; &quot;, o[r] === t &amp;&amp; (o[r] = i.needsContext ? b(r, this)
+                            .index(l) &gt;= 0 : b.find(r, this, null, [l]).length), o[r] &amp;&amp; o.push(i);
+                            o.length &amp;&amp; s.push({
+                                elem: l,
+                                handlers: o
+                            })
+                    }
+            return n.length &gt; u &amp;&amp; s.push({
+                elem: this,
+                handlers: n.slice(u)
+            }), s
+        },
+        fix: function(e) {
+            if (e[b.expando])
+                return e;
+            var t, n, r, i = e.type, a = e, s = this.fixHooks[i];
+            s || (this.fixHooks[i] = s = tt.test(i) ? this.mouseHooks : et.test(i) ? this.keyHooks : {}), r = s.props ? this.props.concat(s.props) : this.props, e = new b.Event(a), t = r.length;
+            while (t--)
+                n = r[t], e[n] = a[n];
+            return e.target || (e.target = a.srcElement || o), 3 === e.target.nodeType &amp;&amp; (e.target = e.target.parentNode), e.metaKey=!!e.metaKey, s.filter ? s.filter(e, a) : e
+        },
+        props: &quot;altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which&quot;.split(&quot; &quot;),
+        fixHooks: {},
+        keyHooks: {
+            props: &quot;char charCode key keyCode&quot;.split(&quot; &quot;),
+            filter: function(e, t) {
+                return null == e.which &amp;&amp; (e.which = null != t.charCode ? t.charCode : t.keyCode), e
+            }
+        },
+        mouseHooks: {
+            props: &quot;button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement&quot;.split(&quot; &quot;),
+            filter: function(e, n) {
+                var r, i, a, s = n.button, u = n.fromElement;
+                return null == e.pageX &amp;&amp; null != n.clientX &amp;&amp; (i = e.target.ownerDocument || o, a = i.documentElement, r = i.body, e.pageX = n.clientX + (a &amp;&amp; a.scrollLeft || r &amp;&amp; r.scrollLeft || 0) - (a &amp;&amp; a.clientLeft || r &amp;&amp; r.clientLeft || 0), e.pageY = n.clientY + (a &amp;&amp; a.scrollTop || r &amp;&amp; r.scrollTop || 0) - (a &amp;&amp; a.clientTop || r &amp;&amp; r.clientTop || 0)), !e.relatedTarget &amp;&amp; u &amp;&amp; (e.relatedTarget = u === e.target ? n.toElement : u), e.which || s === t || (e.which = 1 &amp; s ? 1 : 2 &amp; s ? 3 : 4 &amp; s ? 2 : 0), e
+            }
+        },
+        special: {
+            load: {
+                noBubble: !0
+            },
+            click: {
+                trigger: function() {
+                    return b.nodeName(this, &quot;input&quot;) &amp;&amp; &quot;checkbox&quot; === this.type &amp;&amp; this.click ? (this.click(), !1) : t
+                }
+            },
+            focus: {
+                trigger: function() {
+                    if (this !== o.activeElement &amp;&amp; this.focus)
+                        try {
+                            return this.focus(), !1
+                    } catch (e) {}
+                },
+                delegateType: &quot;focusin&quot;
+            },
+            blur: {
+                trigger: function() {
+                    return this === o.activeElement &amp;&amp; this.blur ? (this.blur(), !1) : t
+                },
+                delegateType: &quot;focusout&quot;
+            },
+            beforeunload: {
+                postDispatch: function(e) {
+                    e.result !== t &amp;&amp; (e.originalEvent.returnValue = e.result)
+                }
+            }
+        },
+        simulate: function(e, t, n, r) {
+            var i = b.extend(new b.Event, n, {
+                type: e,
+                isSimulated: !0,
+                originalEvent: {}
+            });
+            r ? b.event.trigger(i, null, t) : b.event.dispatch.call(t, i), i.isDefaultPrevented() &amp;&amp; n.preventDefault()
+        }
+    }, b.removeEvent = o.removeEventListener ? function(e, t, n) {
+        e.removeEventListener &amp;&amp; e.removeEventListener(t, n, !1)
+    } : function(e, t, n) {
+        var r = &quot;on&quot; + t;
+        e.detachEvent &amp;&amp; (typeof e[r] === i &amp;&amp; (e[r] = null), e.detachEvent(r, n))
+    }, b.Event = function(e, n) {
+        return this instanceof b.Event ? (e &amp;&amp; e.type ? (this.originalEvent = e, this.type = e.type, this.isDefaultPrevented = e.defaultPrevented || e.returnValue===!1 || e.getPreventDefault &amp;&amp; e.getPreventDefault() ? it : ot) : this.type = e, n &amp;&amp; b.extend(this, n), this.timeStamp = e &amp;&amp; e.timeStamp || b.now(), this[b.expando]=!0, t) : new b.Event(e, n)
+    }, b.Event.prototype = {
+        isDefaultPrevented: ot,
+        isPropagationStopped: ot,
+        isImmediatePropagationStopped: ot,
+        preventDefault: function() {
+            var e = this.originalEvent;
+            this.isDefaultPrevented = it, e &amp;&amp; (e.preventDefault ? e.preventDefault() : e.returnValue=!1)
+        },
+        stopPropagation: function() {
+            var e = this.originalEvent;
+            this.isPropagationStopped = it, e &amp;&amp; (e.stopPropagation &amp;&amp; e.stopPropagation(), e.cancelBubble=!0)
+        },
+        stopImmediatePropagation: function() {
+            this.isImmediatePropagationStopped = it, this.stopPropagation()
+        }
+    }, b.each({
+        mouseenter: &quot;mouseover&quot;,
+        mouseleave: &quot;mouseout&quot;
+    }, function(e, t) {
+        b.event.special[e] = {
+            delegateType: t,
+            bindType: t,
+            handle: function(e) {
+                var n, r = this, i = e.relatedTarget, o = e.handleObj;
+                return (!i || i !== r&amp;&amp;!b.contains(r, i)) &amp;&amp; (e.type = o.origType, n = o.handler.apply(this, arguments), e.type = t), n
+            }
+        }
+    }), b.support.submitBubbles || (b.event.special.submit = {
+        setup: function() {
+            return b.nodeName(this, &quot;form&quot;)?!1 : (b.event.add(this, &quot;click._submit keypress._submit&quot;, function(e) {
+                var n = e.target, r = b.nodeName(n, &quot;input&quot;) || b.nodeName(n, &quot;button&quot;) ? n.form: t;
+                r&amp;&amp;!b._data(r, &quot;submitBubbles&quot;) &amp;&amp; (b.event.add(r, &quot;submit._submit&quot;, function(e) {
+                    e._submit_bubble=!0
+                }), b._data(r, &quot;submitBubbles&quot;, !0))
+            }), t)
+        },
+        postDispatch: function(e) {
+            e._submit_bubble &amp;&amp; (delete e._submit_bubble, this.parentNode&amp;&amp;!e.isTrigger &amp;&amp; b.event.simulate(&quot;submit&quot;, this.parentNode, e, !0))
+        },
+        teardown: function() {
+            return b.nodeName(this, &quot;form&quot;)?!1 : (b.event.remove(this, &quot;._submit&quot;), t)
+        }
+    }), b.support.changeBubbles || (b.event.special.change = {
+        setup: function() {
+            return Z.test(this.nodeName) ? ((&quot;checkbox&quot; === this.type || &quot;radio&quot; === this.type) &amp;&amp; (b.event.add(this, &quot;propertychange._change&quot;, function(e) {
+                &quot;checked&quot; === e.originalEvent.propertyName &amp;&amp; (this._just_changed=!0)
+            }), b.event.add(this, &quot;click._change&quot;, function(e) {
+                this._just_changed&amp;&amp;!e.isTrigger &amp;&amp; (this._just_changed=!1), b.event.simulate(&quot;change&quot;, this, e, !0)
+            })), !1) : (b.event.add(this, &quot;beforeactivate._change&quot;, function(e) {
+                var t = e.target;
+                Z.test(t.nodeName)&amp;&amp;!b._data(t, &quot;changeBubbles&quot;) &amp;&amp; (b.event.add(t, &quot;change._change&quot;, function(e) {
+                    !this.parentNode || e.isSimulated || e.isTrigger || b.event.simulate(&quot;change&quot;, this.parentNode, e, !0)
+                }), b._data(t, &quot;changeBubbles&quot;, !0))
+            }), t)
+        },
+        handle: function(e) {
+            var n = e.target;
+            return this !== n || e.isSimulated || e.isTrigger || &quot;radio&quot; !== n.type &amp;&amp; &quot;checkbox&quot; !== n.type ? e.handleObj.handler.apply(this, arguments) : t
+        },
+        teardown: function() {
+            return b.event.remove(this, &quot;._change&quot;), !Z.test(this.nodeName)
+        }
+    }), b.support.focusinBubbles || b.each({
+        focus: &quot;focusin&quot;,
+        blur: &quot;focusout&quot;
+    }, function(e, t) {
+        var n = 0, r = function(e) {
+            b.event.simulate(t, e.target, b.event.fix(e), !0)
+        };
+        b.event.special[t] = {
+            setup: function() {
+                0 === n++&amp;&amp;o.addEventListener(e, r, !0)
+            },
+            teardown: function() {
+                0===--n &amp;&amp; o.removeEventListener(e, r, !0)
+            }
+        }
+    }), b.fn.extend({
+        on: function(e, n, r, i, o) {
+            var a, s;
+            if (&quot;object&quot; == typeof e) {
+                &quot;string&quot; != typeof n &amp;&amp; (r = r || n, n = t);
+                for (a in e)
+                    this.on(a, n, r, e[a], o);
+                return this
+            }
+            if (null == r &amp;&amp; null == i ? (i = n, r = n = t) : null == i &amp;&amp; (&quot;string&quot; == typeof n ? (i = r, r = t) : (i = r, r = n, n = t)), i===!1)
+                i = ot;
+            else if (!i)
+                return this;
+            return 1 === o &amp;&amp; (s = i, i = function(e) {
+                return b().off(e), s.apply(this, arguments)
+            }, i.guid = s.guid || (s.guid = b.guid++)), this.each(function() {
+                b.event.add(this, e, i, r, n)
+            })
+        },
+        one: function(e, t, n, r) {
+            return this.on(e, t, n, r, 1)
+        },
+        off: function(e, n, r) {
+            var i, o;
+            if (e &amp;&amp; e.preventDefault &amp;&amp; e.handleObj)
+                return i = e.handleObj, b(e.delegateTarget).off(i.namespace ? i.origType + &quot;.&quot; + i.namespace : i.origType, i.selector, i.handler), this;
+            if (&quot;object&quot; == typeof e) {
+                for (o in e)
+                    this.off(o, n, e[o]);
+                return this
+            }
+            return (n===!1 || &quot;function&quot; == typeof n) &amp;&amp; (r = n, n = t), r===!1 &amp;&amp; (r = ot), this.each(function() {
+                b.event.remove(this, e, r, n)
+            })
+        },
+        bind: function(e, t, n) {
+            return this.on(e, null, t, n)
+        },
+        unbind: function(e, t) {
+            return this.off(e, null, t)
+        },
+        delegate: function(e, t, n, r) {
+            return this.on(t, e, n, r)
+        },
+        undelegate: function(e, t, n) {
+            return 1 === arguments.length ? this.off(e, &quot;**&quot;) : this.off(t, e || &quot;**&quot;, n)
+        },
+        trigger: function(e, t) {
+            return this.each(function() {
+                b.event.trigger(e, t, this)
+            })
+        },
+        triggerHandler: function(e, n) {
+            var r = this[0];
+            return r ? b.event.trigger(e, n, r, !0) : t
+        }
+    }), function(e, t) {
+        var n, r, i, o, a, s, u, l, c, p, f, d, h, g, m, y, v, x = &quot;sizzle&quot; +- new Date, w = e.document, T = {}, N = 0, C = 0, k = it(), E = it(), S = it(), A = typeof t, j = 1&lt;&lt;31, D = [], L = D.pop, H = D.push, q = D.slice, M = D.indexOf || function(e) {
+            var t = 0, n = this.length;
+            for (; n &gt; t; t++)
+                if (this[t] === e)
+                    return t;
+            return -1
+        }, _ = &quot;[\\x20\\t\\r\\n\\f]&quot;, F = &quot;(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+&quot;, O = F.replace(&quot;w&quot;, &quot;w#&quot;), B = &quot;([*^$|!~]?=)&quot;, P = &quot;\\[&quot; + _ + &quot;*(&quot; + F + &quot;)&quot; + _ + &quot;*(?:&quot; + B + _ + &quot;*(?:(['\&quot;])((?:\\\\.|[^\\\\])*?)\\3|(&quot; + O + &quot;)|)|)&quot; + _ + &quot;*\\]&quot;, R = &quot;:(&quot; + F + &quot;)(?:\\(((['\&quot;])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|&quot; + P.replace(3, 8) + &quot;)*)|.*)\\)|)&quot;, W = RegExp(&quot;^&quot; + _ + &quot;+|((?:^|[^\\\\])(?:\\\\.)*)&quot; + _ + &quot;+$&quot;, &quot;g&quot;), $ = RegExp(&quot;^&quot; + _ + &quot;*,&quot; + _ + &quot;*&quot;), I = RegExp(&quot;^&quot; + _ + &quot;*([\\x20\\t\\r\\n\\f&gt;+~])&quot; + _ + &quot;*&quot;), z = RegExp(R), X = RegExp(&quot;^&quot; + O + &quot;$&quot;), U = {
+            ID: RegExp(&quot;^#(&quot; + F + &quot;)&quot;),
+            CLASS: RegExp(&quot;^\\.(&quot; + F + &quot;)&quot;),
+            NAME: RegExp(&quot;^\\[name=['\&quot;]?(&quot; + F + &quot;)['\&quot;]?\\]&quot;),
+            TAG: RegExp(&quot;^(&quot; + F.replace(&quot;w&quot;, &quot;w*&quot;) + &quot;)&quot;),
+            ATTR: RegExp(&quot;^&quot; + P),
+            PSEUDO: RegExp(&quot;^&quot; + R),
+            CHILD: RegExp(&quot;^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(&quot; + _ + &quot;*(even|odd|(([+-]|)(\\d*)n|)&quot; + _ + &quot;*(?:([+-]|)&quot; + _ + &quot;*(\\d+)|))&quot; + _ + &quot;*\\)|)&quot;, &quot;i&quot;),
+            needsContext: RegExp(&quot;^&quot; + _ + &quot;*[&gt;+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(&quot; + _ + &quot;*((?:-\\d)?\\d*)&quot; + _ + &quot;*\\)|)(?=[^-]|$)&quot;, &quot;i&quot;)
+        }, V = /[\x20\t\r\n\f]*[+~]/, Y = /^[^{]+\{\s*\[native code/, J = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, G = /^(?:input|select|textarea|button)$/i, Q = /^h\d$/i, K = /'|\\/g, Z = /\=[\x20\t\r\n\f]*([^'&quot;\]]*)[\x20\t\r\n\f]*\]/g, et = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, tt = function(e, t) {
+            var n = &quot;0x&quot; + t-65536;
+            return n !== n ? t : 0 &gt; n ? String.fromCharCode(n + 65536) : String.fromCharCode(55296 | n&gt;&gt;10, 56320 | 1023 &amp; n)
+        };
+        try {
+            q.call(w.documentElement.childNodes, 0)[0].nodeType
+        } catch (nt) {
+            q = function(e) {
+                var t, n = [];
+                while (t = this[e++])
+                    n.push(t);
+                return n
+            }
+        }
+        function rt(e) {
+            return Y.test(e + &quot;&quot;)
+        }
+        function it() {
+            var e, t = [];
+            return e = function(n, r) {
+                return t.push(n += &quot; &quot;) &gt; i.cacheLength &amp;&amp; delete e[t.shift()], e[n] = r
+            }
+        }
+        function ot(e) {
+            return e[x]=!0, e
+        }
+        function at(e) {
+            var t = p.createElement(&quot;div&quot;);
+            try {
+                return e(t)
+            } catch (n) {
+                return !1
+            } finally {
+                t = null
+            }
+        }
+        function st(e, t, n, r) {
+            var i, o, a, s, u, l, f, g, m, v;
+            if ((t ? t.ownerDocument || t : w) !== p &amp;&amp; c(t), t = t || p, n = n || [], !e || &quot;string&quot; != typeof e)
+                return n;
+            if (1 !== (s = t.nodeType) &amp;&amp; 9 !== s)
+                return [];
+            if (!d&amp;&amp;!r) {
+                if (i = J.exec(e))
+                    if (a = i[1]) {
+                        if (9 === s) {
+                            if (o = t.getElementById(a), !o ||!o.parentNode)
+                                return n;
+                                if (o.id === a)
+                                    return n.push(o), n
+                        } else if (t.ownerDocument &amp;&amp; (o = t.ownerDocument.getElementById(a)) &amp;&amp; y(t, o) &amp;&amp; o.id === a)
+                            return n.push(o), n
+                    } else {
+                        if (i[2])
+                            return H.apply(n, q.call(t.getElementsByTagName(e), 0)), n;
+                            if ((a = i[3]) &amp;&amp; T.getByClassName &amp;&amp; t.getElementsByClassName)
+                                return H.apply(n, q.call(t.getElementsByClassName(a), 0)), n
+                    }
+                if (T.qsa&amp;&amp;!h.test(e)) {
+                    if (f=!0, g = x, m = t, v = 9 === s &amp;&amp; e, 1 === s &amp;&amp; &quot;object&quot; !== t.nodeName.toLowerCase()
+                        ) {
+                        l = ft(e), (f = t.getAttribute(&quot;id&quot;)) ? g = f.replace(K, &quot;\\$&amp;&quot;) : t.setAttribute(&quot;id&quot;, g), g = &quot;[id='&quot; + g + &quot;'] &quot;, u = l.length;
+                        while (u--)
+                            l[u] = g + dt(l[u]);
+                        m = V.test(e) &amp;&amp; t.parentNode || t, v = l.join(&quot;,&quot;)
+                    }
+                    if (v)
+                        try {
+                            return H.apply(n, q.call(m.querySelectorAll(v), 0)), n
+                    } catch (b) {} finally {
+                        f || t.removeAttribute(&quot;id&quot;)
+                    }
+                }
+            }
+            return wt(e.replace(W, &quot;$1&quot;), t, n, r)
+        }
+        a = st.isXML = function(e) {
+            var t = e &amp;&amp; (e.ownerDocument || e).documentElement;
+            return t ? &quot;HTML&quot; !== t.nodeName : !1
+        }, c = st.setDocument = function(e) {
+            var n = e ? e.ownerDocument || e: w;
+            return n !== p &amp;&amp; 9 === n.nodeType &amp;&amp; n.documentElement ? (p = n, f = n.documentElement, d = a(n), T.tagNameNoComments = at(function(e) {
+                return e.appendChild(n.createComment(&quot;&quot;)), !e.getElementsByTagName(&quot;*&quot;).length
+            }), T.attributes = at(function(e) {
+                e.innerHTML = &quot;&lt;select&gt;&lt;/select&gt;&quot;;
+                var t = typeof e.lastChild.getAttribute(&quot;multiple&quot;);
+                return &quot;boolean&quot; !== t &amp;&amp; &quot;string&quot; !== t
+            }), T.getByClassName = at(function(e) {
+                return e.innerHTML = &quot;&lt;div class='hidden e'&gt;&lt;/div&gt;&lt;div class='hidden'&gt;&lt;/div&gt;&quot;, e.getElementsByClassName &amp;&amp; e.getElementsByClassName(&quot;e&quot;).length ? (e.lastChild.className = &quot;e&quot;, 2 === e.getElementsByClassName(&quot;e&quot;).length) : !1
+            }), T.getByName = at(function(e) {
+                e.id = x + 0, e.innerHTML = &quot;&lt;a name='&quot; + x + &quot;'&gt;&lt;/a&gt;&lt;div name='&quot; + x + &quot;'&gt;&lt;/div&gt;&quot;, f.insertBefore(e, f.firstChild);
+                var t = n.getElementsByName &amp;&amp; n.getElementsByName(x).length === 2 + n.getElementsByName(x + 0).length;
+                return T.getIdNotName=!n.getElementById(x), f.removeChild(e), t
+            }), i.attrHandle = at(function(e) {
+                return e.innerHTML = &quot;&lt;a href='#'&gt;&lt;/a&gt;&quot;, e.firstChild &amp;&amp; typeof e.firstChild.getAttribute !== A &amp;&amp; &quot;#&quot; === e.firstChild.getAttribute(&quot;href&quot;)
+            }) ? {} : {
+                href: function(e) {
+                    return e.getAttribute(&quot;href&quot;, 2)
+                },
+                type: function(e) {
+                    return e.getAttribute(&quot;type&quot;)
+                }
+            }, T.getIdNotName ? (i.find.ID = function(e, t) {
+                if (typeof t.getElementById !== A&amp;&amp;!d) {
+                    var n = t.getElementById(e);
+                    return n &amp;&amp; n.parentNode ? [n] : []
+                }
+            }, i.filter.ID = function(e) {
+                var t = e.replace(et, tt);
+                return function(e) {
+                    return e.getAttribute(&quot;id&quot;) === t
+                }
+            }) : (i.find.ID = function(e, n) {
+                if (typeof n.getElementById !== A&amp;&amp;!d) {
+                    var r = n.getElementById(e);
+                    return r ? r.id === e || typeof r.getAttributeNode !== A &amp;&amp; r.getAttributeNode(&quot;id&quot;).value === e ? [r] : t : []
+                }
+            }, i.filter.ID = function(e) {
+                var t = e.replace(et, tt);
+                return function(e) {
+                    var n = typeof e.getAttributeNode !== A &amp;&amp; e.getAttributeNode(&quot;id&quot;);
+                    return n &amp;&amp; n.value === t
+                }
+            }), i.find.TAG = T.tagNameNoComments ? function(e, n) {
+                return typeof n.getElementsByTagName !== A ? n.getElementsByTagName(e) : t
+            } : function(e, t) {
+                var n, r = [], i = 0, o = t.getElementsByTagName(e);
+                if (&quot;*&quot; === e) {
+                    while (n = o[i++])
+                        1 === n.nodeType &amp;&amp; r.push(n);
+                    return r
+                }
+                return o
+            }, i.find.NAME = T.getByName &amp;&amp; function(e, n) {
+                return typeof n.getElementsByName !== A ? n.getElementsByName(name) : t
+            }, i.find.CLASS = T.getByClassName &amp;&amp; function(e, n) {
+                return typeof n.getElementsByClassName === A || d ? t : n.getElementsByClassName(e)
+            }, g = [], h = [&quot;:focus&quot;], (T.qsa = rt(n.querySelectorAll)) &amp;&amp; (at(function(e) {
+                e.innerHTML = &quot;&lt;select&gt;&lt;option selected=''&gt;&lt;/option&gt;&lt;/select&gt;&quot;, e.querySelectorAll(&quot;[selected]&quot;).length || h.push(&quot;\\[&quot; + _ + &quot;*(?:checked|disabled|ismap|multiple|readonly|selected|value)&quot;), e.querySelectorAll(&quot;:checked&quot;).length || h.push(&quot;:checked&quot;)
+            }), at(function(e) {
+                e.innerHTML = &quot;&lt;input type='hidden' i=''/&gt;&quot;, e.querySelectorAll(&quot;[i^='']&quot;).length &amp;&amp; h.push(&quot;[*^$]=&quot; + _ + &quot;*(?:\&quot;\&quot;|'')&quot;), e.querySelectorAll(&quot;:enabled&quot;).length || h.push(&quot;:enabled&quot;, &quot;:disabled&quot;), e.querySelectorAll(&quot;*,:x&quot;), h.push(&quot;,.*:&quot;)
+            })), (T.matchesSelector = rt(m = f.matchesSelector || f.mozMatchesSelector || f.webkitMatchesSelector || f.oMatchesSelector || f.msMatchesSelector)) &amp;&amp; at(function(e) {
+                T.disconnectedMatch = m.call(e, &quot;div&quot;), m.call(e, &quot;[s!='']:x&quot;), g.push(&quot;!=&quot;, R)
+            }), h = RegExp(h.join(&quot;|&quot;)), g = RegExp(g.join(&quot;|&quot;)), y = rt(f.contains) || f.compareDocumentPosition ? function(e, t) {
+                var n = 9 === e.nodeType ? e.documentElement: e, r = t &amp;&amp; t.parentNode;
+                return e === r ||!(!r || 1 !== r.nodeType ||!(n.contains ? n.contains(r) : e.compareDocumentPosition &amp;&amp; 16 &amp; e.compareDocumentPosition(r)))
+            } : function(e, t) {
+                if (t)
+                    while (t = t.parentNode)
+                        if (t === e)
+                            return !0;
+                return !1
+            }, v = f.compareDocumentPosition ? function(e, t) {
+                var r;
+                return e === t ? (u=!0, 0) : (r = t.compareDocumentPosition &amp;&amp; e.compareDocumentPosition &amp;&amp; e.compareDocumentPosition(t)) ? 1 &amp; r || e.parentNode &amp;&amp; 11 === e.parentNode.nodeType ? e === n || y(w, e)?-1 : t === n || y(w, t) ? 1 : 0 : 4 &amp; r?-1 : 1 : e.compareDocumentPosition?-1 : 1
+            } : function(e, t) {
+                var r, i = 0, o = e.parentNode, a = t.parentNode, s = [e], l = [t];
+                if (e === t)
+                    return u=!0, 0;
+                if (!o ||!a)
+                    return e === n?-1 : t === n ? 1 : o?-1 : a ? 1 : 0;
+                if (o === a)
+                    return ut(e, t);
+                r = e;
+                while (r = r.parentNode)
+                    s.unshift(r);
+                r = t;
+                while (r = r.parentNode)
+                    l.unshift(r);
+                while (s[i] === l[i])
+                    i++;
+                return i ? ut(s[i], l[i]) : s[i] === w?-1 : l[i] === w ? 1 : 0
+            }, u=!1, [0, 0].sort(v), T.detectDuplicates = u, p) : p
+        }, st.matches = function(e, t) {
+            return st(e, null, null, t)
+        }, st.matchesSelector = function(e, t) {
+            if ((e.ownerDocument || e) !== p &amp;&amp; c(e), t = t.replace(Z, &quot;='$1']&quot;)
+                , !(!T.matchesSelector || d || g &amp;&amp; g.test(t) || h.test(t)))try {
+                var n = m.call(e, t);
+                if (n || T.disconnectedMatch || e.document &amp;&amp; 11 !== e.document.nodeType)
+                    return n
+            } catch (r) {}
+            return st(t, p, null, [e]).length &gt; 0
+        }, st.contains = function(e, t) {
+            return (e.ownerDocument || e) !== p &amp;&amp; c(e), y(e, t)
+        }, st.attr = function(e, t) {
+            var n;
+            return (e.ownerDocument || e) !== p &amp;&amp; c(e), d || (t = t.toLowerCase()), (n = i.attrHandle[t]) ? n(e) : d || T.attributes ? e.getAttribute(t) : ((n = e.getAttributeNode(t)) || e.getAttribute(t)) &amp;&amp; e[t]===!0 ? t : n &amp;&amp; n.specified ? n.value : null
+        }, st.error = function(e) {
+            throw Error(&quot;Syntax error, unrecognized expression: &quot; + e)
+        }, st.uniqueSort = function(e) {
+            var t, n = [], r = 1, i = 0;
+            if (u=!T.detectDuplicates, e.sort(v)
+                , u) {
+                for (; t = e[r]; r++)
+                    t === e[r-1] &amp;&amp; (i = n.push(r));
+                while (i--)
+                    e.splice(n[i], 1)
+            }
+            return e
+        };
+        function ut(e, t) {
+            var n = t &amp;&amp; e, r = n &amp;&amp; (~t.sourceIndex || j) - (~e.sourceIndex || j);
+            if (r)
+                return r;
+            if (n)
+                while (n = n.nextSibling)
+                    if (n === t)
+                        return -1;
+            return e ? 1 : -1
+        }
+        function lt(e) {
+            return function(t) {
+                var n = t.nodeName.toLowerCase();
+                return &quot;input&quot; === n &amp;&amp; t.type === e
+            }
+        }
+        function ct(e) {
+            return function(t) {
+                var n = t.nodeName.toLowerCase();
+                return (&quot;input&quot; === n || &quot;button&quot; === n) &amp;&amp; t.type === e
+            }
+        }
+        function pt(e) {
+            return ot(function(t) {
+                return t =+ t, ot(function(n, r) {
+                    var i, o = e([], n.length, t), a = o.length;
+                    while (a--)
+                        n[i = o[a]] &amp;&amp; (n[i]=!(r[i] = n[i]))
+                })
+            })
+        }
+        o = st.getText = function(e) {
+            var t, n = &quot;&quot;, r = 0, i = e.nodeType;
+            if (i) {
+                if (1 === i || 9 === i || 11 === i) {
+                    if (&quot;string&quot; == typeof e.textContent)
+                        return e.textContent;
+                    for (e = e.firstChild; e; e = e.nextSibling)
+                        n += o(e)
+                    } else if (3 === i || 4 === i)
+                        return e.nodeValue
+            } else 
+                for (; t = e[r]; r++)
+                    n += o(t);
+            return n
+        }, i = st.selectors = {
+            cacheLength: 50,
+            createPseudo: ot,
+            match: U,
+            find: {},
+            relative: {
+                &quot;&gt;&quot;: {
+                    dir: &quot;parentNode&quot;,
+                    first: !0
+                },
+                &quot; &quot;: {
+                    dir: &quot;parentNode&quot;
+                },
+                &quot;+&quot;: {
+                    dir: &quot;previousSibling&quot;,
+                    first: !0
+                },
+                &quot;~&quot;: {
+                    dir: &quot;previousSibling&quot;
+                }
+            },
+            preFilter: {
+                ATTR: function(e) {
+                    return e[1] = e[1].replace(et, tt), e[3] = (e[4] || e[5] || &quot;&quot;).replace(et, tt), &quot;~=&quot; === e[2] &amp;&amp; (e[3] = &quot; &quot; + e[3] + &quot; &quot;), e.slice(0, 4)
+                },
+                CHILD: function(e) {
+                    return e[1] = e[1].toLowerCase(), &quot;nth&quot; === e[1].slice(0, 3) ? (e[3] || st.error(e[0]), e[4] =+ (e[4] ? e[5] + (e[6] || 1) : 2 * (&quot;even&quot; === e[3] || &quot;odd&quot; === e[3])), e[5] =+ (e[7] + e[8] || &quot;odd&quot; === e[3])) : e[3] &amp;&amp; st.error(e[0]), e
+                },
+                PSEUDO: function(e) {
+                    var t, n=!e[5] &amp;&amp; e[2];
+                    return U.CHILD.test(e[0]) ? null : (e[4] ? e[2] = e[4] : n &amp;&amp; z.test(n) &amp;&amp; (t = ft(n, !0)) &amp;&amp; (t = n.indexOf(&quot;)&quot;, n.length - t) - n.length) &amp;&amp; (e[0] = e[0].slice(0, t), e[2] = n.slice(0, t)), e.slice(0, 3))
+                }
+            },
+            filter: {
+                TAG: function(e) {
+                    return &quot;*&quot; === e ? function() {
+                        return !0
+                    } : (e = e.replace(et, tt).toLowerCase(), function(t) {
+                        return t.nodeName &amp;&amp; t.nodeName.toLowerCase() === e
+                    })
+                },
+                CLASS: function(e) {
+                    var t = k[e + &quot; &quot;];
+                    return t || (t = RegExp(&quot;(^|&quot; + _ + &quot;)&quot; + e + &quot;(&quot; + _ + &quot;|$)&quot;)) &amp;&amp; k(e, function(e) {
+                        return t.test(e.className || typeof e.getAttribute !== A &amp;&amp; e.getAttribute(&quot;class&quot;) || &quot;&quot;)
+                    })
+                },
+                ATTR: function(e, t, n) {
+                    return function(r) {
+                        var i = st.attr(r, e);
+                        return null == i ? &quot;!=&quot; === t : t ? (i += &quot;&quot;, &quot;=&quot; === t ? i === n : &quot;!=&quot; === t ? i !== n : &quot;^=&quot; === t ? n &amp;&amp; 0 === i.indexOf(n) : &quot;*=&quot; === t ? n &amp;&amp; i.indexOf(n)&gt;-1 : &quot;$=&quot; === t ? n &amp;&amp; i.slice( - n.length) === n : &quot;~=&quot; === t ? (&quot; &quot; + i + &quot; &quot;).indexOf(n)&gt;-1 : &quot;|=&quot; === t ? i === n || i.slice(0, n.length + 1) === n + &quot;-&quot; : !1) : !0
+                    }
+                },
+                CHILD: function(e, t, n, r, i) {
+                    var o = &quot;nth&quot; !== e.slice(0, 3), a = &quot;last&quot; !== e.slice(-4), s = &quot;of-type&quot; === t;
+                    return 1 === r &amp;&amp; 0 === i ? function(e) {
+                        return !!e.parentNode
+                    } : function(t, n, u) {
+                        var l, c, p, f, d, h, g = o !== a ? &quot;nextSibling&quot;: &quot;previousSibling&quot;, m = t.parentNode, y = s &amp;&amp; t.nodeName.toLowerCase(), v=!u&amp;&amp;!s;
+                        if (m) {
+                            if (o) {
+                                while (g) {
+                                    p = t;
+                                    while (p = p[g])
+                                        if (s ? p.nodeName.toLowerCase() === y : 1 === p.nodeType)
+                                            return !1;
+                                    h = g = &quot;only&quot; === e&amp;&amp;!h &amp;&amp; &quot;nextSibling&quot;
+                                }
+                                return !0
+                            }
+                            if (h = [a ? m.firstChild: m.lastChild], a &amp;&amp; v) {
+                                c = m[x] || (m[x] = {}), l = c[e] || [], d = l[0] === N &amp;&amp; l[1], f = l[0] === N &amp;&amp; l[2], p = d &amp;&amp; m.childNodes[d];
+                                while (p=++d &amp;&amp; p &amp;&amp; p[g] || (f = d = 0) || h.pop()
+                                    )if (1 === p.nodeType&amp;&amp;++f &amp;&amp; p === t) {
+                                    c[e] = [N, d, f];
+                                    break
+                                }
+                            } else if (v &amp;&amp; (l = (t[x] || (t[x] = {}))[e]) &amp;&amp; l[0] === N)
+                                f = l[1];
+                            else 
+                                while (p=++d &amp;&amp; p &amp;&amp; p[g] || (f = d = 0) || h.pop()
+                                    )if ((s ? p.nodeName.toLowerCase() === y : 1 === p.nodeType)&amp;&amp;++f &amp;&amp; (v &amp;&amp; ((p[x] || (p[x] = {})
+                                )[e] = [N, f]), p === t))break;
+                            return f -= i, f === r || 0 === f%r &amp;&amp; f / r &gt;= 0
+                        }
+                    }
+                },
+                PSEUDO: function(e, t) {
+                    var n, r = i.pseudos[e] || i.setFilters[e.toLowerCase()] || st.error(&quot;unsupported pseudo: &quot; + e);
+                    return r[x] ? r(t) : r.length &gt; 1 ? (n = [e, e, &quot;&quot;, t], i.setFilters.hasOwnProperty(e.toLowerCase()) ? ot(function(e, n) {
+                        var i, o = r(e, t), a = o.length;
+                        while (a--)i = M.call(e, o[a]), e[i]=!(n[i] = o[a])
+                    }) : function(e) {
+                        return r(e, 0, n)
+                    }) : r
+                }
+            },
+            pseudos: {
+                not: ot(function(e) {
+                    var t = [], n = [], r = s(e.replace(W, &quot;$1&quot;));
+                    return r[x] ? ot(function(e, t, n, i) {
+                        var o, a = r(e, null, i, []), s = e.length;
+                        while (s--)(o = a[s]) &amp;&amp; (e[s]=!(t[s] = o))
+                        }) : function(e, i, o) {
+                        return t[0] = e, r(t, null, o, n), !n.pop()
+                    }
+                }), has : ot(function(e) {
+                    return function(t) {
+                        return st(e, t).length &gt; 0
+                    }
+                }), contains: ot(function(e) {
+                    return function(t) {
+                        return (t.textContent || t.innerText || o(t)).indexOf(e)&gt;-1
+                    }
+                }), lang: ot(function(e) {
+                    return X.test(e || &quot;&quot;) || st.error(&quot;unsupported lang: &quot; + e), e = e.replace(et, tt).toLowerCase(), function(t) {
+                        var n;
+                        do 
+                            if (n = d ? t.getAttribute(&quot;xml:lang&quot;) || t.getAttribute(&quot;lang&quot;) : t.lang)
+                                return n = n.toLowerCase(), n === e || 0 === n.indexOf(e + &quot;-&quot;);
+                        while ((t = t.parentNode) &amp;&amp; 1 === t.nodeType);
+                        return !1
+                    }
+                }), target: function(t) {
+                    var n = e.location &amp;&amp; e.location.hash;
+                    return n &amp;&amp; n.slice(1) === t.id
+                }, root: function(e) {
+                    return e === f
+                }, focus: function(e) {
+                    return e === p.activeElement &amp;&amp; (!p.hasFocus || p.hasFocus())&amp;&amp;!!(e.type || e.href||~e.tabIndex)
+                }, enabled: function(e) {
+                    return e.disabled===!1
+                }, disabled: function(e) {
+                    return e.disabled===!0
+                }, checked: function(e) {
+                    var t = e.nodeName.toLowerCase();
+                    return &quot;input&quot; === t&amp;&amp;!!e.checked || &quot;option&quot; === t&amp;&amp;!!e.selected
+                }, selected: function(e) {
+                    return e.parentNode &amp;&amp; e.parentNode.selectedIndex, e.selected===!0
+                }, empty: function(e) {
+                    for (e = e.firstChild; e; e = e.nextSibling)
+                        if (e.nodeName &gt; &quot;@&quot; || 3 === e.nodeType || 4 === e.nodeType)
+                            return !1;
+                    return !0
+                }, parent: function(e) {
+                    return !i.pseudos.empty(e)
+                }, header: function(e) {
+                    return Q.test(e.nodeName)
+                }, input: function(e) {
+                    return G.test(e.nodeName)
+                }, button: function(e) {
+                    var t = e.nodeName.toLowerCase();
+                    return &quot;input&quot; === t &amp;&amp; &quot;button&quot; === e.type || &quot;button&quot; === t
+                }, text: function(e) {
+                    var t;
+                    return &quot;input&quot; === e.nodeName.toLowerCase() &amp;&amp; &quot;text&quot; === e.type &amp;&amp; (null == (t = e.getAttribute(&quot;type&quot;)) || t.toLowerCase() === e.type)
+                }, first: pt(function() {
+                    return [0]
+                }), last: pt(function(e, t) {
+                    return [t-1]
+                }), eq: pt(function(e, t, n) {
+                    return [0 &gt; n ? n + t: n]
+                }), even: pt(function(e, t) {
+                    var n = 0;
+                    for (; t &gt; n; n += 2)
+                        e.push(n);
+                    return e
+                }), odd: pt(function(e, t) {
+                    var n = 1;
+                    for (; t &gt; n; n += 2)
+                        e.push(n);
+                    return e
+                }), lt: pt(function(e, t, n) {
+                    var r = 0 &gt; n ? n + t: n;
+                    for (; --r &gt;= 0;)
+                        e.push(r);
+                    return e
+                }), gt: pt(function(e, t, n) {
+                    var r = 0 &gt; n ? n + t: n;
+                    for (; t&gt;++r;)
+                        e.push(r);
+                    return e
+                })
+            }
+        }; for (n in{
+            radio : !0, checkbox : !0, file : !0, password : !0, image : !0
+        })i.pseudos[n] = lt(n);
+        for (n in{
+            submit: !0,
+            reset: !0
+        })i.pseudos[n] = ct(n);
+        function ft(e,
+        t) {
+            var n,
+            r,
+            o,
+            a,
+            s,
+            u,
+            l,
+            c = E[e + &quot; &quot;];
+            if (c)return t ? 0: c.slice(0);
+            s = e,
+            u = [],
+            l = i.preFilter;
+            while (s) {
+                (!n || (r = $.exec(s))) &amp;&amp; (r &amp;&amp; (s = s.slice(r[0].length) || s),
+                u.push(o = [])),
+                n=!1,
+                (r = I.exec(s)) &amp;&amp; (n = r.shift(),
+                o.push({
+                    value: n,
+                    type: r[0].replace(W,
+                    &quot; &quot;)
+                }), s = s.slice(n.length));
+                for (a in i.filter)
+                    !(r = U[a].exec(s)) || l[a]&amp;&amp;!(r = l[a](r)) || (n = r.shift(), o.push({
+                        value : n, type : a, matches : r
+                    }), s = s.slice(n.length));
+                if (!n)
+                    break
+            }
+            return t ? s.length : s ? st.error(e) : E(e, u).slice(0)
+        }
+        function dt(e) {
+            var t = 0, n = e.length, r = &quot;&quot;;
+            for (; n &gt; t; t++)
+                r += e[t].value;
+            return r
+        }
+        function ht(e, t, n) {
+            var i = t.dir, o = n &amp;&amp; &quot;parentNode&quot; === i, a = C++;
+            return t.first ? function(t, n, r) {
+                while (t = t[i])
+                    if (1 === t.nodeType || o)
+                        return e(t, n, r)
+            } : function(t, n, s) {
+                var u, l, c, p = N + &quot; &quot; + a;
+                if (s) {
+                    while (t = t[i])
+                        if ((1 === t.nodeType || o) &amp;&amp; e(t, n, s))
+                            return !0
+                } else 
+                    while (t = t[i])
+                        if (1 === t.nodeType || o)
+                            if (c = t[x] || (t[x] = {}), (l = c[i]) &amp;&amp; l[0] === p) {
+                    if ((u = l[1])===!0 || u === r)
+                        return u===!0
+                } else if (l = c[i] = [p], l[1] = e(t, n, s) || r, l[1]===!0)return !0
+            }
+        }
+        function gt(e) {
+            return e.length &gt; 1 ? function(t, n, r) {
+                var i = e.length;
+                while (i--)
+                    if (!e[i](t, n, r))
+                        return !1;
+                return !0
+            } : e[0]
+        }
+        function mt(e, t, n, r, i) {
+            var o, a = [], s = 0, u = e.length, l = null != t;
+            for (; u &gt; s; s++)(o = e[s]) 
+                &amp;&amp; (!n || n(o, r, i)) &amp;&amp; (a.push(o), l &amp;&amp; t.push(s));
+            return a
+        }
+        function yt(e, t, n, r, i, o) {
+            return r&amp;&amp;!r[x] &amp;&amp; (r = yt(r)), i&amp;&amp;!i[x] &amp;&amp; (i = yt(i, o)), ot(function(o, a, s, u) {
+                var l, c, p, f = [], d = [], h = a.length, g = o || xt(t || &quot;*&quot;, s.nodeType ? [s] : s, []), m=!e ||!o &amp;&amp; t ? g : mt(g, f, e, s, u), y = n ? i || (o ? e : h || r) ? [] : a : m;
+                if (n &amp;&amp; n(m, y, s, u), r) {
+                    l = mt(y, d), r(l, [], s, u), c = l.length;
+                    while (c--)(p = l[c]) &amp;&amp; (y[d[c]]=!(m[d[c]] = p))
+                    }
+                if (o) {
+                    if (i || e) {
+                        if (i) {
+                            l = [], c = y.length;
+                            while (c--)(p = y[c]) &amp;&amp; l.push(m[c] = p);
+                            i(null, y = [], l, u)
+                        }
+                        c = y.length;
+                        while (c--)(p = y[c]) &amp;&amp; (l = i ? M.call(o, p) : f[c])&gt;-1 &amp;&amp; (o[l]=!(a[l] = p))
+                        }
+                } else 
+                    y = mt(y === a ? y.splice(h, y.length) : y), i ? i(null, a, y, u) : H.apply(a, y)
+            })
+        }
+        function vt(e) {
+            var t, n, r, o = e.length, a = i.relative[e[0].type], s = a || i.relative[&quot; &quot;], u = a ? 1: 0, c = ht(function(e) {
+                return e === t
+            }, s, !0), p = ht(function(e) {
+                return M.call(t, e)&gt;-1
+            }, s, !0), f = [function(e, n, r) {
+                return !a &amp;&amp; (r || n !== l) || ((t = n).nodeType ? c(e, n, r) : p(e, n, r))
+            }
+            ];
+            for (; o &gt; u; u++)
+                if (n = i.relative[e[u].type])
+                    f = [ht(gt(f), n)];
+                else {
+                    if (n = i.filter[e[u].type].apply(null, e[u].matches), n[x]) {
+                        for (r=++u; o &gt; r; r++)
+                            if (i.relative[e[r].type])
+                                break;
+                                return yt(u &gt; 1 &amp;&amp; gt(f), u &gt; 1 &amp;&amp; dt(e.slice(0, u-1)).replace(W, &quot;$1&quot;), n, r &gt; u &amp;&amp; vt(e.slice(u, r)), o &gt; r &amp;&amp; vt(e = e.slice(r)), o &gt; r &amp;&amp; dt(e))
+                            }
+                            f.push(n)
+                }
+            return gt(f)
+        }
+        function bt(e, t) {
+            var n = 0, o = t.length &gt; 0, a = e.length &gt; 0, s = function(s, u, c, f, d) {
+                var h, g, m, y = [], v = 0, b = &quot;0&quot;, x = s &amp;&amp; [], w = null != d, T = l, C = s || a &amp;&amp; i.find.TAG(&quot;*&quot;, d &amp;&amp; u.parentNode || u), k = N += null == T ? 1: Math.random() || .1;
+                for (w &amp;&amp; (l = u !== p &amp;&amp; u, r = n); null != (h = C[b]); b++) {
+                    if (a &amp;&amp; h) {
+                        g = 0;
+                        while (m = e[g++])
+                            if (m(h, u, c)) {
+                                f.push(h);
+                                break
+                            }
+                        w &amp;&amp; (N = k, r=++n)
+                    }
+                    o &amp;&amp; ((h=!m &amp;&amp; h) &amp;&amp; v--, s &amp;&amp; x.push(h))
+                }
+                if (v += b, o &amp;&amp; b !== v) {
+                    g = 0;
+                    while (m = t[g++])
+                        m(x, y, u, c);
+                    if (s) {
+                        if (v &gt; 0)
+                            while (b--)
+                                x[b] || y[b] || (y[b] = L.call(f));
+                        y = mt(y)
+                    }
+                    H.apply(f, y), w&amp;&amp;!s &amp;&amp; y.length &gt; 0 &amp;&amp; v + t.length &gt; 1 &amp;&amp; st.uniqueSort(f)
+                }
+                return w &amp;&amp; (N = k, l = T), x
+            };
+            return o ? ot(s) : s
+        }
+        s = st.compile = function(e, t) {
+            var n, r = [], i = [], o = S[e + &quot; &quot;];
+            if (!o) {
+                t || (t = ft(e)), n = t.length;
+                while (n--)
+                    o = vt(t[n]), o[x] ? r.push(o) : i.push(o);
+                o = S(e, bt(i, r))
+            }
+            return o
+        };
+        function xt(e, t, n) {
+            var r = 0, i = t.length;
+            for (; i &gt; r; r++)
+                st(e, t[r], n);
+            return n
+        }
+        function wt(e, t, n, r) {
+            var o, a, u, l, c, p = ft(e);
+            if (!r &amp;&amp; 1 === p.length) {
+                if (a = p[0] = p[0].slice(0), a.length &gt; 2 &amp;&amp; &quot;ID&quot; === (u = a[0]).type &amp;&amp; 9 === t.nodeType&amp;&amp;!d &amp;&amp; i.relative[a[1].type]) {
+                    if (t = i.find.ID(u.matches[0].replace(et, tt), t)[0], !t)
+                        return n;
+                    e = e.slice(a.shift().value.length)
+                }
+                o = U.needsContext.test(e) ? 0 : a.length;
+                while (o--) {
+                    if (u = a[o], i.relative[l = u.type])
+                        break;
+                    if ((c = i.find[l]) &amp;&amp; (r = c(u.matches[0].replace(et, tt), V.test(a[0].type) &amp;&amp; t.parentNode || t))) {
+                        if (a.splice(o, 1), e = r.length &amp;&amp; dt(a)
+                            , !e)return H.apply(n, q.call(r, 0)), n;
+                        break
+                    }
+                }
+            }
+            return s(e, p)(r, t, d, n, V.test(e)), n
+        }
+        i.pseudos.nth = i.pseudos.eq;
+        function Tt() {}
+        i.filters = Tt.prototype = i.pseudos, i.setFilters = new Tt, c(), st.attr = b.attr, b.find = st, b.expr = st.selectors, b.expr[&quot;:&quot;] = b.expr.pseudos, b.unique = st.uniqueSort, b.text = st.getText, b.isXMLDoc = st.isXML, b.contains = st.contains
+    }(e);
+    var at = /Until$/, st = /^(?:parents|prev(?:Until|All))/, ut = /^.[^:#\[\.,]*$/, lt = b.expr.match.needsContext, ct = {
+        children: !0,
+        contents: !0,
+        next: !0,
+        prev: !0
+    };
+    b.fn.extend({
+        find: function(e) {
+            var t, n, r, i = this.length;
+            if (&quot;string&quot; != typeof e)
+                return r = this, this.pushStack(b(e).filter(function() {
+                for (t = 0; i &gt; t; t++)
+                    if (b.contains(r[t], this))
+                        return !0
+            }));
+            for (n = [], t = 0;
+            i &gt; t;
+            t++)b.find(e, this[t], n);
+            return n = this.pushStack(i &gt; 1 ? b.unique(n) : n), n.selector = (this.selector ? this.selector + &quot; &quot; : &quot;&quot;) + e, n
+        },
+        has: function(e) {
+            var t, n = b(e, this), r = n.length;
+            return this.filter(function() {
+                for (t = 0; r &gt; t; t++)
+                    if (b.contains(this, n[t]))
+                        return !0
+            })
+        },
+        not: function(e) {
+            return this.pushStack(ft(this, e, !1))
+        },
+        filter: function(e) {
+            return this.pushStack(ft(this, e, !0))
+        },
+        is: function(e) {
+            return !!e &amp;&amp; (&quot;string&quot; == typeof e ? lt.test(e) ? b(e, this.context).index(this[0]) &gt;= 0 : b.filter(e, this).length &gt; 0 : this.filter(e).length &gt; 0)
+        },
+        closest: function(e, t) {
+            var n, r = 0, i = this.length, o = [], a = lt.test(e) || &quot;string&quot; != typeof e ? b(e, t || this.context): 0;
+            for (; i &gt; r; r++) {
+                n = this[r];
+                while (n &amp;&amp; n.ownerDocument &amp;&amp; n !== t &amp;&amp; 11 !== n.nodeType) {
+                    if (a ? a.index(n)&gt;-1 : b.find.matchesSelector(n, e)) {
+                        o.push(n);
+                        break
+                    }
+                    n = n.parentNode
+                }
+            }
+            return this.pushStack(o.length &gt; 1 ? b.unique(o) : o)
+        },
+        index: function(e) {
+            return e ? &quot;string&quot; == typeof e ? b.inArray(this[0], b(e)) : b.inArray(e.jquery ? e[0] : e, this) : this[0] &amp;&amp; this[0].parentNode ? this.first().prevAll().length : -1
+        },
+        add: function(e, t) {
+            var n = &quot;string&quot; == typeof e ? b(e, t): b.makeArray(e &amp;&amp; e.nodeType ? [e] : e), r = b.merge(this.get(), n);
+            return this.pushStack(b.unique(r))
+        },
+        addBack: function(e) {
+            return this.add(null == e ? this.prevObject : this.prevObject.filter(e))
+        }
+    }), b.fn.andSelf = b.fn.addBack;
+    function pt(e, t) {
+        do 
+            e = e[t];
+        while (e &amp;&amp; 1 !== e.nodeType);
+        return e
+    }
+    b.each({
+        parent: function(e) {
+            var t = e.parentNode;
+            return t &amp;&amp; 11 !== t.nodeType ? t : null
+        },
+        parents: function(e) {
+            return b.dir(e, &quot;parentNode&quot;)
+        },
+        parentsUntil: function(e, t, n) {
+            return b.dir(e, &quot;parentNode&quot;, n)
+        },
+        next: function(e) {
+            return pt(e, &quot;nextSibling&quot;)
+        },
+        prev: function(e) {
+            return pt(e, &quot;previousSibling&quot;)
+        },
+        nextAll: function(e) {
+            return b.dir(e, &quot;nextSibling&quot;)
+        },
+        prevAll: function(e) {
+            return b.dir(e, &quot;previousSibling&quot;)
+        },
+        nextUntil: function(e, t, n) {
+            return b.dir(e, &quot;nextSibling&quot;, n)
+        },
+        prevUntil: function(e, t, n) {
+            return b.dir(e, &quot;previousSibling&quot;, n)
+        },
+        siblings: function(e) {
+            return b.sibling((e.parentNode || {}).firstChild, e)
+        },
+        children: function(e) {
+            return b.sibling(e.firstChild)
+        },
+        contents: function(e) {
+            return b.nodeName(e, &quot;iframe&quot;) ? e.contentDocument || e.contentWindow.document : b.merge([], e.childNodes)
+        }
+    }, function(e, t) {
+        b.fn[e] = function(n, r) {
+            var i = b.map(this, t, n);
+            return at.test(e) || (r = n), r &amp;&amp; &quot;string&quot; == typeof r &amp;&amp; (i = b.filter(r, i)), i = this.length &gt; 1&amp;&amp;!ct[e] ? b.unique(i) : i, this.length &gt; 1 &amp;&amp; st.test(e) &amp;&amp; (i = i.reverse()), this.pushStack(i)
+        }
+    }), b.extend({
+        filter: function(e, t, n) {
+            return n &amp;&amp; (e = &quot;:not(&quot; + e + &quot;)&quot;), 1 === t.length ? b.find.matchesSelector(t[0], e) ? [t[0]] : [] : b.find.matches(e, t)
+        },
+        dir: function(e, n, r) {
+            var i = [], o = e[n];
+            while (o &amp;&amp; 9 !== o.nodeType &amp;&amp; (r === t || 1 !== o.nodeType ||!b(o).is(r)))
+                1 === o.nodeType &amp;&amp; i.push(o), o = o[n];
+            return i
+        },
+        sibling: function(e, t) {
+            var n = [];
+            for (; e; e = e.nextSibling)
+                1 === e.nodeType &amp;&amp; e !== t &amp;&amp; n.push(e);
+            return n
+        }
+    });
+    function ft(e, t, n) {
+        if (t = t || 0, b.isFunction(t)
+            )return b.grep(e, function(e, r) {
+            var i=!!t.call(e, r, e);
+            return i === n
+        });
+        if (t.nodeType)
+            return b.grep(e, function(e) {
+                return e === t === n
+            });
+        if (&quot;string&quot; == typeof t) {
+            var r = b.grep(e, function(e) {
+                return 1 === e.nodeType
+            });
+            if (ut.test(t))
+                return b.filter(t, r, !n);
+            t = b.filter(t, r)
+        }
+        return b.grep(e, function(e) {
+            return b.inArray(e, t) &gt;= 0 === n
+        })
+    }
+    function dt(e) {
+        var t = ht.split(&quot;|&quot;), n = e.createDocumentFragment();
+        if (n.createElement)
+            while (t.length)
+                n.createElement(t.pop());
+        return n
+    }
+    var ht = &quot;abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video&quot;, gt = / jQuery\d+=&quot;(?:null|\d+)&quot;/g, mt = RegExp(&quot;&lt;(?:&quot; + ht + &quot;)[\\s/&gt;]&quot;, &quot;i&quot;), yt = /^\s+/, vt = /&lt;(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^&gt;]*)\/&gt;/gi, bt = /&lt;([\w:]+)/, xt = /&lt;tbody/i, wt = /&lt;|&amp;#?\w+;/, Tt = /&lt;(?:script|style|link)/i, Nt = /^(?:checkbox|radio)$/i, Ct = /checked\s*(?:[^=]|=\s*.checked.)/i, kt = /^$|\/(?:java|ecma)script/i, Et = /^true\/(.*)/, St = /^\s*&lt;!(?:\[CDATA\[|--)|(?:\]\]|--)&gt;\s*$/g, At = {
+        option: [1, &quot;&lt;select multiple='multiple'&gt;&quot;, &quot;&lt;/select&gt;&quot;],
+        legend: [1, &quot;&lt;fieldset&gt;&quot;, &quot;&lt;/fieldset&gt;&quot;],
+        area: [1, &quot;&lt;map&gt;&quot;, &quot;&lt;/map&gt;&quot;],
+        param: [1, &quot;&lt;object&gt;&quot;, &quot;&lt;/object&gt;&quot;],
+        thead: [1, &quot;&lt;table&gt;&quot;, &quot;&lt;/table&gt;&quot;],
+        tr: [2, &quot;&lt;table&gt;&lt;tbody&gt;&quot;, &quot;&lt;/tbody&gt;&lt;/table&gt;&quot;],
+        col: [2, &quot;&lt;table&gt;&lt;tbody&gt;&lt;/tbody&gt;&lt;colgroup&gt;&quot;, &quot;&lt;/colgroup&gt;&lt;/table&gt;&quot;],
+        td: [3, &quot;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&quot;, &quot;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&quot;],
+        _default: b.support.htmlSerialize ? [0, &quot;&quot;, &quot;&quot;]: [1, &quot;X&lt;div&gt;&quot;, &quot;&lt;/div&gt;&quot;]
+    }, jt = dt(o), Dt = jt.appendChild(o.createElement(&quot;div&quot;));
+    At.optgroup = At.option, At.tbody = At.tfoot = At.colgroup = At.caption = At.thead, At.th = At.td, b.fn.extend({
+        text: function(e) {
+            return b.access(this, function(e) {
+                return e === t ? b.text(this) : this.empty().append((this[0] &amp;&amp; this[0].ownerDocument || o).createTextNode(e))
+            }, null, e, arguments.length)
+        },
+        wrapAll: function(e) {
+            if (b.isFunction(e))
+                return this.each(function(t) {
+                    b(this).wrapAll(e.call(this, t))
+                });
+            if (this[0]) {
+                var t = b(e, this[0].ownerDocument).eq(0).clone(!0);
+                this[0].parentNode &amp;&amp; t.insertBefore(this[0]), t.map(function() {
+                    var e = this;
+                    while (e.firstChild &amp;&amp; 1 === e.firstChild.nodeType)
+                        e = e.firstChild;
+                    return e
+                }).append(this)
+            }
+            return this
+        },
+        wrapInner: function(e) {
+            return b.isFunction(e) ? this.each(function(t) {
+                b(this).wrapInner(e.call(this, t))
+            }) : this.each(function() {
+                var t = b(this), n = t.contents();
+                n.length ? n.wrapAll(e) : t.append(e)
+            })
+        },
+        wrap: function(e) {
+            var t = b.isFunction(e);
+            return this.each(function(n) {
+                b(this).wrapAll(t ? e.call(this, n) : e)
+            })
+        },
+        unwrap: function() {
+            return this.parent().each(function() {
+                b.nodeName(this, &quot;body&quot;) || b(this).replaceWith(this.childNodes)
+            }).end()
+        },
+        append: function() {
+            return this.domManip(arguments, !0, function(e) {
+                (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) &amp;&amp; this.appendChild(e)
+            })
+        },
+        prepend: function() {
+            return this.domManip(arguments, !0, function(e) {
+                (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) &amp;&amp; this.insertBefore(e, this.firstChild)
+            })
+        },
+        before: function() {
+            return this.domManip(arguments, !1, function(e) {
+                this.parentNode &amp;&amp; this.parentNode.insertBefore(e, this)
+            })
+        },
+        after: function() {
+            return this.domManip(arguments, !1, function(e) {
+                this.parentNode &amp;&amp; this.parentNode.insertBefore(e, this.nextSibling)
+            })
+        },
+        remove: function(e, t) {
+            var n, r = 0;
+            for (; null != (n = this[r]); r++)(!e || b.filter(e, [n]).length &gt; 0) 
+                &amp;&amp; (t || 1 !== n.nodeType || b.cleanData(Ot(n)), n.parentNode &amp;&amp; (t &amp;&amp; b.contains(n.ownerDocument, n) &amp;&amp; Mt(Ot(n, &quot;script&quot;)), n.parentNode.removeChild(n)));
+            return this
+        },
+        empty: function() {
+            var e, t = 0;
+            for (; null != (e = this[t]); t++) {
+                1 === e.nodeType &amp;&amp; b.cleanData(Ot(e, !1));
+                while (e.firstChild)
+                    e.removeChild(e.firstChild);
+                e.options &amp;&amp; b.nodeName(e, &quot;select&quot;) &amp;&amp; (e.options.length = 0)
+            }
+            return this
+        },
+        clone: function(e, t) {
+            return e = null == e?!1 : e, t = null == t ? e : t, this.map(function() {
+                return b.clone(this, e, t)
+            })
+        },
+        html: function(e) {
+            return b.access(this, function(e) {
+                var n = this[0] || {}, r = 0, i = this.length;
+                if (e === t)
+                    return 1 === n.nodeType ? n.innerHTML.replace(gt, &quot;&quot;) : t;
+                if (!(&quot;string&quot; != typeof e || Tt.test(e) ||!b.support.htmlSerialize &amp;&amp; mt.test(e) ||!b.support.leadingWhitespace &amp;&amp; yt.test(e) || At[(bt.exec(e) || [&quot;&quot;, &quot;&quot;])[1].toLowerCase()])) {
+                    e = e.replace(vt, &quot;&lt;$1&gt;&lt;/$2&gt;&quot;);
+                    try {
+                        for (; i &gt; r; r++)
+                            n = this[r] || {}, 1 === n.nodeType &amp;&amp; (b.cleanData(Ot(n, !1)), n.innerHTML = e);
+                        n = 0
+                    } catch (o) {}
+                }
+                n &amp;&amp; this.empty().append(e)
+            }, null, e, arguments.length)
+        },
+        replaceWith: function(e) {
+            var t = b.isFunction(e);
+            return t || &quot;string&quot; == typeof e || (e = b(e).not(this).detach()), this.domManip([e], !0, function(e) {
+                var t = this.nextSibling, n = this.parentNode;
+                n &amp;&amp; (b(this).remove(), n.insertBefore(e, t))
+            })
+        },
+        detach: function(e) {
+            return this.remove(e, !0)
+        },
+        domManip: function(e, n, r) {
+            e = f.apply([], e);
+            var i, o, a, s, u, l, c = 0, p = this.length, d = this, h = p-1, g = e[0], m = b.isFunction(g);
+            if (m ||!(1 &gt;= p || &quot;string&quot; != typeof g || b.support.checkClone) &amp;&amp; Ct.test(g))
+                return this.each(function(i) {
+                    var o = d.eq(i);
+                    m &amp;&amp; (e[0] = g.call(this, i, n ? o.html() : t)), o.domManip(e, n, r)
+                });
+            if (p &amp;&amp; (l = b.buildFragment(e, this[0].ownerDocument, !1, this), i = l.firstChild, 1 === l.childNodes.length &amp;&amp; (l = i), i)
+                ) {
+                for (n = n &amp;&amp; b.nodeName(i, &quot;tr&quot;), s = b.map(Ot(l, &quot;script&quot;)
+                    , Ht), a = s.length;
+                p &gt; c;
+                c++)o = l, c !== h &amp;&amp; (o = b.clone(o, !0, !0), a &amp;&amp; b.merge(s, Ot(o, &quot;script&quot;))), r.call(n &amp;&amp; b.nodeName(this[c], &quot;table&quot;) ? Lt(this[c], &quot;tbody&quot;) : this[c], o, c);
+                if (a)
+                    for (u = s[s.length-1].ownerDocument, b.map(s, qt)
+                        , c = 0;
+                a &gt; c;
+                c++)o = s[c], kt.test(o.type || &quot;&quot;)&amp;&amp;!b._data(o, &quot;globalEval&quot;) &amp;&amp; b.contains(u, o) &amp;&amp; (o.src ? b.ajax({
+                    url: o.src,
+                    type: &quot;GET&quot;,
+                    dataType: &quot;script&quot;,
+                    async: !1,
+                    global: !1,
+                    &quot;throws&quot;: !0
+                }) : b.globalEval((o.text || o.textContent || o.innerHTML || &quot;&quot;).replace(St, &quot;&quot;)));
+                l = i = null
+            }
+            return this
+        }
+    });
+    function Lt(e, t) {
+        return e.getElementsByTagName(t)[0] || e.appendChild(e.ownerDocument.createElement(t))
+    }
+    function Ht(e) {
+        var t = e.getAttributeNode(&quot;type&quot;);
+        return e.type = (t &amp;&amp; t.specified) + &quot;/&quot; + e.type, e
+    }
+    function qt(e) {
+        var t = Et.exec(e.type);
+        return t ? e.type = t[1] : e.removeAttribute(&quot;type&quot;), e
+    }
+    function Mt(e, t) {
+        var n, r = 0;
+        for (; null != (n = e[r]); r++)
+            b._data(n, &quot;globalEval&quot;, !t || b._data(t[r], &quot;globalEval&quot;))
+    }
+    function _t(e, t) {
+        if (1 === t.nodeType &amp;&amp; b.hasData(e)) {
+            var n, r, i, o = b._data(e), a = b._data(t, o), s = o.events;
+            if (s) {
+                delete a.handle, a.events = {};
+                for (n in s)
+                    for (r = 0, i = s[n].length; i &gt; r; r++)
+                        b.event.add(t, n, s[n][r])
+                    }
+            a.data &amp;&amp; (a.data = b.extend({}, a.data))
+        }
+    }
+    function Ft(e, t) {
+        var n, r, i;
+        if (1 === t.nodeType) {
+            if (n = t.nodeName.toLowerCase(), !b.support.noCloneEvent &amp;&amp; t[b.expando]) {
+                i = b._data(t);
+                for (r in i.events)
+                    b.removeEvent(t, r, i.handle);
+                t.removeAttribute(b.expando)
+            }
+            &quot;script&quot; === n &amp;&amp; t.text !== e.text ? (Ht(t).text = e.text, qt(t)) : &quot;object&quot; === n ? (t.parentNode &amp;&amp; (t.outerHTML = e.outerHTML), b.support.html5Clone &amp;&amp; e.innerHTML&amp;&amp;!b.trim(t.innerHTML) &amp;&amp; (t.innerHTML = e.innerHTML)) : &quot;input&quot; === n &amp;&amp; Nt.test(e.type) ? (t.defaultChecked = t.checked = e.checked, t.value !== e.value &amp;&amp; (t.value = e.value)) : &quot;option&quot; === n ? t.defaultSelected = t.selected = e.defaultSelected : (&quot;input&quot; === n || &quot;textarea&quot; === n) &amp;&amp; (t.defaultValue = e.defaultValue)
+        }
+    }
+    b.each({
+        appendTo: &quot;append&quot;,
+        prependTo: &quot;prepend&quot;,
+        insertBefore: &quot;before&quot;,
+        insertAfter: &quot;after&quot;,
+        replaceAll: &quot;replaceWith&quot;
+    }, function(e, t) {
+        b.fn[e] = function(e) {
+            var n, r = 0, i = [], o = b(e), a = o.length-1;
+            for (; a &gt;= r; r++)
+                n = r === a ? this : this.clone(!0), b(o[r])[t](n), d.apply(i, n.get());
+            return this.pushStack(i)
+        }
+    });
+    function Ot(e, n) {
+        var r, o, a = 0, s = typeof e.getElementsByTagName !== i ? e.getElementsByTagName(n || &quot;*&quot;): typeof e.querySelectorAll !== i ? e.querySelectorAll(n || &quot;*&quot;): t;
+        if (!s)
+            for (s = [], r = e.childNodes || e;
+            null != (o = r[a]); a++)
+                !n || b.nodeName(o, n) ? s.push(o) : b.merge(s, Ot(o, n));
+        return n === t || n &amp;&amp; b.nodeName(e, n) ? b.merge([e], s) : s
+    }
+    function Bt(e) {
+        Nt.test(e.type) &amp;&amp; (e.defaultChecked = e.checked)
+    }
+    b.extend({
+        clone: function(e, t, n) {
+            var r, i, o, a, s, u = b.contains(e.ownerDocument, e);
+            if (b.support.html5Clone || b.isXMLDoc(e) ||!mt.test(&quot;&lt;&quot; + e.nodeName + &quot;&gt;&quot;) ? o = e.cloneNode(!0) : (Dt.innerHTML = e.outerHTML, Dt.removeChild(o = Dt.firstChild))
+                , !(b.support.noCloneEvent &amp;&amp; b.support.noCloneChecked || 1 !== e.nodeType &amp;&amp; 11 !== e.nodeType || b.isXMLDoc(e)))for (r = Ot(o), s = Ot(e)
+                , a = 0;
+            null != (i = s[a]);
+            ++a)r[a] &amp;&amp; Ft(i, r[a]);
+            if (t)
+                if (n)
+                    for (s = s || Ot(e), r = r || Ot(o)
+                        , a = 0;
+            null != (i = s[a]);
+            a++)_t(i, r[a]);
+            else 
+                _t(e, o);
+            return r = Ot(o, &quot;script&quot;), r.length &gt; 0 &amp;&amp; Mt(r, !u &amp;&amp; Ot(e, &quot;script&quot;)), r = s = i = null, o
+        },
+        buildFragment: function(e, t, n, r) {
+            var i, o, a, s, u, l, c, p = e.length, f = dt(t), d = [], h = 0;
+            for (; p &gt; h; h++)
+                if (o = e[h], o || 0 === o)
+                    if (&quot;object&quot; === b.type(o))
+                        b.merge(d, o.nodeType ? [o] : o);
+                    else if (wt.test(o)) {
+                        s = s || f.appendChild(t.createElement(&quot;div&quot;)), u = (bt.exec(o) || [&quot;&quot;, &quot;&quot;])[1].toLowerCase(), c = At[u] || At._default, s.innerHTML = c[1] + o.replace(vt, &quot;&lt;$1&gt;&lt;/$2&gt;&quot;) + c[2], i = c[0];
+                        while (i--)
+                            s = s.lastChild;
+                            if (!b.support.leadingWhitespace &amp;&amp; yt.test(o) &amp;&amp; d.push(t.createTextNode(yt.exec(o)[0])), !b.support.tbody) {
+                                o = &quot;table&quot; !== u || xt.test(o) ? &quot;&lt;table&gt;&quot; !== c[1] || xt.test(o) ? 0 : s : s.firstChild, i = o &amp;&amp; o.childNodes.length;
+                                while (i--)
+                                    b.nodeName(l = o.childNodes[i], &quot;tbody&quot;)&amp;&amp;!l.childNodes.length &amp;&amp; o.removeChild(l)
+                                }
+                                b.merge(d, s.childNodes), s.textContent = &quot;&quot;;
+                                while (s.firstChild)
+                                    s.removeChild(s.firstChild);
+                                    s = f.lastChild
+                        } else 
+                            d.push(t.createTextNode(o));
+            s &amp;&amp; f.removeChild(s), b.support.appendChecked || b.grep(Ot(d, &quot;input&quot;), Bt), h = 0;
+            while (o = d[h++])
+                if ((!r||-1 === b.inArray(o, r)) &amp;&amp; (a = b.contains(o.ownerDocument, o), s = Ot(f.appendChild(o), &quot;script&quot;)
+                    , a &amp;&amp; Mt(s), n)) {
+                i = 0;
+                while (o = s[i++])
+                    kt.test(o.type || &quot;&quot;) &amp;&amp; n.push(o)
+                    }
+            return s = null, f
+        },
+        cleanData: function(e, t) {
+            var n, r, o, a, s = 0, u = b.expando, l = b.cache, p = b.support.deleteExpando, f = b.event.special;
+            for (; null != (n = e[s]); s++)
+                if ((t || b.acceptData(n)) &amp;&amp; (o = n[u], a = o &amp;&amp; l[o])) {
+                    if (a.events)
+                        for (r in a.events)
+                            f[r] ? b.event.remove(n, r) : b.removeEvent(n, r, a.handle);
+                            l[o] &amp;&amp; (delete l[o], p ? delete n[u] : typeof n.removeAttribute !== i ? n.removeAttribute(u) : n[u] = null, c.push(o))
+                }
+        }
+    });
+    var Pt, Rt, Wt, $t = /alpha\([^)]*\)/i, It = /opacity\s*=\s*([^)]*)/, zt = /^(top|right|bottom|left)$/, Xt = /^(none|table(?!-c[ea]).+)/, Ut = /^margin/, Vt = RegExp(&quot;^(&quot; + x + &quot;)(.*)$&quot;, &quot;i&quot;), Yt = RegExp(&quot;^(&quot; + x + &quot;)(?!px)[a-z%]+$&quot;, &quot;i&quot;), Jt = RegExp(&quot;^([+-])=(&quot; + x + &quot;)&quot;, &quot;i&quot;), Gt = {
+        BODY: &quot;block&quot;
+    }, Qt = {
+        position: &quot;absolute&quot;,
+        visibility: &quot;hidden&quot;,
+        display: &quot;block&quot;
+    }, Kt = {
+        letterSpacing: 0,
+        fontWeight: 400
+    }, Zt = [&quot;Top&quot;, &quot;Right&quot;, &quot;Bottom&quot;, &quot;Left&quot;], en = [&quot;Webkit&quot;, &quot;O&quot;, &quot;Moz&quot;, &quot;ms&quot;];
+    function tn(e, t) {
+        if (t in e)
+            return t;
+        var n = t.charAt(0).toUpperCase() + t.slice(1), r = t, i = en.length;
+        while (i--)
+            if (t = en[i] + n, t in e)
+                return t;
+        return r
+    }
+    function nn(e, t) {
+        return e = t || e, &quot;none&quot; === b.css(e, &quot;display&quot;) ||!b.contains(e.ownerDocument, e)
+    }
+    function rn(e, t) {
+        var n, r, i, o = [], a = 0, s = e.length;
+        for (; s &gt; a; a++)
+            r = e[a], r.style &amp;&amp; (o[a] = b._data(r, &quot;olddisplay&quot;), n = r.style.display, t ? (o[a] || &quot;none&quot; !== n || (r.style.display = &quot;&quot;), &quot;&quot; === r.style.display &amp;&amp; nn(r) &amp;&amp; (o[a] = b._data(r, &quot;olddisplay&quot;, un(r.nodeName)))) : o[a] || (i = nn(r), (n &amp;&amp; &quot;none&quot; !== n ||!i) &amp;&amp; b._data(r, &quot;olddisplay&quot;, i ? n : b.css(r, &quot;display&quot;))));
+        for (a = 0; s &gt; a; a++)
+            r = e[a], r.style &amp;&amp; (t &amp;&amp; &quot;none&quot; !== r.style.display &amp;&amp; &quot;&quot; !== r.style.display || (r.style.display = t ? o[a] || &quot;&quot; : &quot;none&quot;));
+        return e
+    }
+    b.fn.extend({
+        css: function(e, n) {
+            return b.access(this, function(e, n, r) {
+                var i, o, a = {}, s = 0;
+                if (b.isArray(n)) {
+                    for (o = Rt(e), i = n.length; i &gt; s; s++)
+                        a[n[s]] = b.css(e, n[s], !1, o);
+                    return a
+                }
+                return r !== t ? b.style(e, n, r) : b.css(e, n)
+            }, e, n, arguments.length &gt; 1)
+        },
+        show: function() {
+            return rn(this, !0)
+        },
+        hide: function() {
+            return rn(this)
+        },
+        toggle: function(e) {
+            var t = &quot;boolean&quot; == typeof e;
+            return this.each(function() {
+                (t ? e : nn(this)) ? b(this).show() : b(this).hide()
+            })
+        }
+    }), b.extend({
+        cssHooks: {
+            opacity: {
+                get: function(e, t) {
+                    if (t) {
+                        var n = Wt(e, &quot;opacity&quot;);
+                        return &quot;&quot; === n ? &quot;1&quot; : n
+                    }
+                }
+            }
+        },
+        cssNumber: {
+            columnCount: !0,
+            fillOpacity: !0,
+            fontWeight: !0,
+            lineHeight: !0,
+            opacity: !0,
+            orphans: !0,
+            widows: !0,
+            zIndex: !0,
+            zoom: !0
+        },
+        cssProps: {
+            &quot;float&quot;: b.support.cssFloat ? &quot;cssFloat&quot;: &quot;styleFloat&quot;
+        },
+        style: function(e, n, r, i) {
+            if (e &amp;&amp; 3 !== e.nodeType &amp;&amp; 8 !== e.nodeType &amp;&amp; e.style) {
+                var o, a, s, u = b.camelCase(n), l = e.style;
+                if (n = b.cssProps[u] || (b.cssProps[u] = tn(l, u)), s = b.cssHooks[n] || b.cssHooks[u], r === t)
+                    return s &amp;&amp; &quot;get&quot;in s &amp;&amp; (o = s.get(e, !1, i)) !== t ? o : l[n];
+                if (a = typeof r, &quot;string&quot; === a &amp;&amp; (o = Jt.exec(r)
+                    ) &amp;&amp; (r = (o[1] + 1) * o[2] + parseFloat(b.css(e, n)), a = &quot;number&quot;), !(null == r || &quot;number&quot; === a &amp;&amp; isNaN(r) || (&quot;number&quot; !== a || b.cssNumber[u] || (r += &quot;px&quot;), b.support.clearCloneStyle || &quot;&quot; !== r || 0 !== n.indexOf(&quot;background&quot;) || (l[n] = &quot;inherit&quot;), s &amp;&amp; &quot;set&quot;in s &amp;&amp; (r = s.set(e, r, i)) === t)))try {
+                    l[n] = r
+                } catch (c) {}
+            }
+        },
+        css: function(e, n, r, i) {
+            var o, a, s, u = b.camelCase(n);
+            return n = b.cssProps[u] || (b.cssProps[u] = tn(e.style, u)), s = b.cssHooks[n] || b.cssHooks[u], s &amp;&amp; &quot;get&quot;in s &amp;&amp; (a = s.get(e, !0, r)), a === t &amp;&amp; (a = Wt(e, n, i)), &quot;normal&quot; === a &amp;&amp; n in Kt &amp;&amp; (a = Kt[n]), &quot;&quot; === r || r ? (o = parseFloat(a), r===!0 || b.isNumeric(o) ? o || 0 : a) : a
+        },
+        swap: function(e, t, n, r) {
+            var i, o, a = {};
+            for (o in t)
+                a[o] = e.style[o], e.style[o] = t[o];
+            i = n.apply(e, r || []);
+            for (o in t)
+                e.style[o] = a[o];
+            return i
+        }
+    }), e.getComputedStyle ? (Rt = function(t) {
+        return e.getComputedStyle(t, null)
+    }, Wt = function(e, n, r) {
+        var i, o, a, s = r || Rt(e), u = s ? s.getPropertyValue(n) || s[n] : t, l = e.style;
+        return s &amp;&amp; (&quot;&quot; !== u || b.contains(e.ownerDocument, e) || (u = b.style(e, n)), Yt.test(u) &amp;&amp; Ut.test(n) &amp;&amp; (i = l.width, o = l.minWidth, a = l.maxWidth, l.minWidth = l.maxWidth = l.width = u, u = s.width, l.width = i, l.minWidth = o, l.maxWidth = a)), u
+    }) : o.documentElement.currentStyle &amp;&amp; (Rt = function(e) {
+        return e.currentStyle
+    }, Wt = function(e, n, r) {
+        var i, o, a, s = r || Rt(e), u = s ? s[n]: t, l = e.style;
+        return null == u &amp;&amp; l &amp;&amp; l[n] &amp;&amp; (u = l[n]), Yt.test(u)&amp;&amp;!zt.test(n) &amp;&amp; (i = l.left, o = e.runtimeStyle, a = o &amp;&amp; o.left, a &amp;&amp; (o.left = e.currentStyle.left), l.left = &quot;fontSize&quot; === n ? &quot;1em&quot; : u, u = l.pixelLeft + &quot;px&quot;, l.left = i, a &amp;&amp; (o.left = a)), &quot;&quot; === u ? &quot;auto&quot; : u
+    });
+    function on(e, t, n) {
+        var r = Vt.exec(t);
+        return r ? Math.max(0, r[1] - (n || 0)) + (r[2] || &quot;px&quot;) : t
+    }
+    function an(e, t, n, r, i) {
+        var o = n === (r ? &quot;border&quot; : &quot;content&quot;) ? 4: &quot;width&quot; === t ? 1: 0, a = 0;
+        for (; 4 &gt; o; o += 2)
+            &quot;margin&quot; === n &amp;&amp; (a += b.css(e, n + Zt[o], !0, i)), r ? (&quot;content&quot; === n &amp;&amp; (a -= b.css(e, &quot;padding&quot; + Zt[o], !0, i)), &quot;margin&quot; !== n &amp;&amp; (a -= b.css(e, &quot;border&quot; + Zt[o] + &quot;Width&quot;, !0, i))) : (a += b.css(e, &quot;padding&quot; + Zt[o], !0, i), &quot;padding&quot; !== n &amp;&amp; (a += b.css(e, &quot;border&quot; + Zt[o] + &quot;Width&quot;, !0, i)));
+        return a
+    }
+    function sn(e, t, n) {
+        var r=!0, i = &quot;width&quot; === t ? e.offsetWidth : e.offsetHeight, o = Rt(e), a = b.support.boxSizing &amp;&amp; &quot;border-box&quot; === b.css(e, &quot;boxSizing&quot;, !1, o);
+        if (0 &gt;= i || null == i) {
+            if (i = Wt(e, t, o), (0 &gt; i || null == i) &amp;&amp; (i = e.style[t])
+                , Yt.test(i))return i;
+            r = a &amp;&amp; (b.support.boxSizingReliable || i === e.style[t]), i = parseFloat(i) || 0
+        }
+        return i + an(e, t, n || (a ? &quot;border&quot; : &quot;content&quot;), r, o) + &quot;px&quot;
+    }
+    function un(e) {
+        var t = o, n = Gt[e];
+        return n || (n = ln(e, t), &quot;none&quot; !== n &amp;&amp; n || (Pt = (Pt || b(&quot;&lt;iframe frameborder='0' width='0' height='0'/&gt;&quot;).css(&quot;cssText&quot;, &quot;display:block !important&quot;)).appendTo(t.documentElement), t = (Pt[0].contentWindow || Pt[0].contentDocument).document, t.write(&quot;&lt;!doctype html&gt;&lt;html&gt;&lt;body&gt;&quot;), t.close(), n = ln(e, t), Pt.detach()), Gt[e] = n), n
+    }
+    function ln(e, t) {
+        var n = b(t.createElement(e)).appendTo(t.body), r = b.css(n[0], &quot;display&quot;);
+        return n.remove(), r
+    }
+    b.each([&quot;height&quot;, &quot;width&quot;], function(e, n) {
+        b.cssHooks[n] = {
+            get: function(e, r, i) {
+                return r ? 0 === e.offsetWidth &amp;&amp; Xt.test(b.css(e, &quot;display&quot;)) ? b.swap(e, Qt, function() {
+                    return sn(e, n, i)
+                }) : sn(e, n, i) : t
+            },
+            set: function(e, t, r) {
+                var i = r &amp;&amp; Rt(e);
+                return on(e, t, r ? an(e, n, r, b.support.boxSizing &amp;&amp; &quot;border-box&quot; === b.css(e, &quot;boxSizing&quot;, !1, i), i) : 0)
+            }
+        }
+    }), b.support.opacity || (b.cssHooks.opacity = {
+        get: function(e, t) {
+            return It.test((t &amp;&amp; e.currentStyle ? e.currentStyle.filter : e.style.filter) || &quot;&quot;) ? .01 * parseFloat(RegExp.$1) + &quot;&quot; : t ? &quot;1&quot; : &quot;&quot;
+        },
+        set: function(e, t) {
+            var n = e.style, r = e.currentStyle, i = b.isNumeric(t) ? &quot;alpha(opacity=&quot; + 100 * t + &quot;)&quot;: &quot;&quot;, o = r &amp;&amp; r.filter || n.filter || &quot;&quot;;
+            n.zoom = 1, (t &gt;= 1 || &quot;&quot; === t) &amp;&amp; &quot;&quot; === b.trim(o.replace($t, &quot;&quot;)) &amp;&amp; n.removeAttribute &amp;&amp; (n.removeAttribute(&quot;filter&quot;), &quot;&quot; === t || r&amp;&amp;!r.filter) || (n.filter = $t.test(o) ? o.replace($t, i) : o + &quot; &quot; + i)
+        }
+    }), b(function() {
+        b.support.reliableMarginRight || (b.cssHooks.marginRight = {
+            get: function(e, n) {
+                return n ? b.swap(e, {
+                    display: &quot;inline-block&quot;
+                }, Wt, [e, &quot;marginRight&quot;]) : t
+            }
+        }), !b.support.pixelPosition &amp;&amp; b.fn.position &amp;&amp; b.each([&quot;top&quot;, &quot;left&quot;], function(e, n) {
+            b.cssHooks[n] = {
+                get: function(e, r) {
+                    return r ? (r = Wt(e, n), Yt.test(r) ? b(e).position()[n] + &quot;px&quot; : r) : t
+                }
+            }
+        })
+    }), b.expr &amp;&amp; b.expr.filters &amp;&amp; (b.expr.filters.hidden = function(e) {
+        return 0 &gt;= e.offsetWidth &amp;&amp; 0 &gt;= e.offsetHeight ||!b.support.reliableHiddenOffsets &amp;&amp; &quot;none&quot; === (e.style &amp;&amp; e.style.display || b.css(e, &quot;display&quot;))
+    }, b.expr.filters.visible = function(e) {
+        return !b.expr.filters.hidden(e)
+    }), b.each({
+        margin: &quot;&quot;,
+        padding: &quot;&quot;,
+        border: &quot;Width&quot;
+    }, function(e, t) {
+        b.cssHooks[e + t] = {
+            expand: function(n) {
+                var r = 0, i = {}, o = &quot;string&quot; == typeof n ? n.split(&quot; &quot;): [n];
+                for (; 4 &gt; r; r++)
+                    i[e + Zt[r] + t] = o[r] || o[r-2] || o[0];
+                return i
+            }
+        }, Ut.test(e) || (b.cssHooks[e + t].set = on)
+    });
+    var cn = /%20/g, pn = /\[\]$/, fn = /\r?\n/g, dn = /^(?:submit|button|image|reset|file)$/i, hn = /^(?:input|select|textarea|keygen)/i;
+    b.fn.extend({
+        serialize: function() {
+            return b.param(this.serializeArray())
+        },
+        serializeArray: function() {
+            return this.map(function() {
+                var e = b.prop(this, &quot;elements&quot;);
+                return e ? b.makeArray(e) : this
+            }).filter(function() {
+                var e = this.type;
+                return this.name&amp;&amp;!b(this).is(&quot;:disabled&quot;) &amp;&amp; hn.test(this.nodeName)&amp;&amp;!dn.test(e) &amp;&amp; (this.checked ||!Nt.test(e))
+            }).map(function(e, t) {
+                var n = b(this).val();
+                return null == n ? null : b.isArray(n) ? b.map(n, function(e) {
+                    return {
+                        name: t.name,
+                        value: e.replace(fn, &quot;\r\n&quot;)
+                    }
+                }) : {
+                    name: t.name,
+                    value: n.replace(fn, &quot;\r\n&quot;)
+                }
+            }).get()
+        }
+    }), b.param = function(e, n) {
+        var r, i = [], o = function(e, t) {
+            t = b.isFunction(t) ? t() : null == t ? &quot;&quot; : t, i[i.length] = encodeURIComponent(e) + &quot;=&quot; + encodeURIComponent(t)
+        };
+        if (n === t &amp;&amp; (n = b.ajaxSettings &amp;&amp; b.ajaxSettings.traditional), b.isArray(e) || e.jquery&amp;&amp;!b.isPlainObject(e)
+            )b.each(e, function() {
+            o(this.name, this.value)
+        });
+        else 
+            for (r in e)
+                gn(r, e[r], n, o);
+        return i.join(&quot;&amp;&quot;).replace(cn, &quot;+&quot;)
+    };
+    function gn(e, t, n, r) {
+        var i;
+        if (b.isArray(t))
+            b.each(t, function(t, i) {
+                n || pn.test(e) ? r(e, i) : gn(e + &quot;[&quot; + (&quot;object&quot; == typeof i ? t : &quot;&quot;) + &quot;]&quot;, i, n, r)
+            });
+        else if (n || &quot;object&quot; !== b.type(t))
+            r(e, t);
+        else 
+            for (i in t)
+                gn(e + &quot;[&quot; + i + &quot;]&quot;, t[i], n, r)
+    }
+    b.each(&quot;blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu&quot;.split(&quot; &quot;), function(e, t) {
+        b.fn[t] = function(e, n) {
+            return arguments.length &gt; 0 ? this.on(t, null, e, n) : this.trigger(t)
+        }
+    }), b.fn.hover = function(e, t) {
+        return this.mouseenter(e).mouseleave(t || e)
+    };
+    var mn, yn, vn = b.now(), bn = /\?/, xn = /#.*$/, wn = /([?&amp;])_=[^&amp;]*/, Tn = /^(.*?):[ \t]*([^\r\n]*)\r?$/gm, Nn = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, Cn = /^(?:GET|HEAD)$/, kn = /^\/\//, En = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, Sn = b.fn.load, An = {}, jn = {}, Dn = &quot;*/&quot;.concat(&quot;*&quot;);
+    try {
+        yn = a.href
+    } catch (Ln) {
+        yn = o.createElement(&quot;a&quot;), yn.href = &quot;&quot;, yn = yn.href
+    }
+    mn = En.exec(yn.toLowerCase()) || [];
+    function Hn(e) {
+        return function(t, n) {
+            &quot;string&quot; != typeof t &amp;&amp; (n = t, t = &quot;*&quot;);
+            var r, i = 0, o = t.toLowerCase().match(w) || [];
+            if (b.isFunction(n))
+                while (r = o[i++])
+                    &quot;+&quot; === r[0] ? (r = r.slice(1) || &quot;*&quot;, (e[r] = e[r] || []).unshift(n)) : (e[r] = e[r] || []).push(n)
+        }
+    }
+    function qn(e, n, r, i) {
+        var o = {}, a = e === jn;
+        function s(u) {
+            var l;
+            return o[u]=!0, b.each(e[u] || [], function(e, u) {
+                var c = u(n, r, i);
+                return &quot;string&quot; != typeof c || a || o[c] ? a?!(l = c) : t : (n.dataTypes.unshift(c), s(c), !1)
+            }), l
+        }
+        return s(n.dataTypes[0]) ||!o[&quot;*&quot;] &amp;&amp; s(&quot;*&quot;)
+    }
+    function Mn(e, n) {
+        var r, i, o = b.ajaxSettings.flatOptions || {};
+        for (i in n)
+            n[i] !== t &amp;&amp; ((o[i] ? e : r || (r = {}))[i] = n[i]);
+        return r &amp;&amp; b.extend(!0, e, r), e
+    }
+    b.fn.load = function(e, n, r) {
+        if (&quot;string&quot; != typeof e &amp;&amp; Sn)
+            return Sn.apply(this, arguments);
+        var i, o, a, s = this, u = e.indexOf(&quot; &quot;);
+        return u &gt;= 0 &amp;&amp; (i = e.slice(u, e.length), e = e.slice(0, u)), b.isFunction(n) ? (r = n, n = t) : n &amp;&amp; &quot;object&quot; == typeof n &amp;&amp; (a = &quot;POST&quot;), s.length &gt; 0 &amp;&amp; b.ajax({
+            url: e,
+            type: a,
+            dataType: &quot;html&quot;,
+            data: n
+        }).done(function(e) {
+            o = arguments, s.html(i ? b(&quot;&lt;div&gt;&quot;).append(b.parseHTML(e)).find(i) : e)
+        }).complete(r &amp;&amp; function(e, t) {
+            s.each(r, o || [e.responseText, t, e])
+        }), this
+    }, b.each([&quot;ajaxStart&quot;, &quot;ajaxStop&quot;, &quot;ajaxComplete&quot;, &quot;ajaxError&quot;, &quot;ajaxSuccess&quot;, &quot;ajaxSend&quot;], function(e, t) {
+        b.fn[t] = function(e) {
+            return this.on(t, e)
+        }
+    }), b.each([&quot;get&quot;, &quot;post&quot;], function(e, n) {
+        b[n] = function(e, r, i, o) {
+            return b.isFunction(r) &amp;&amp; (o = o || i, i = r, r = t), b.ajax({
+                url: e,
+                type: n,
+                dataType: o,
+                data: r,
+                success: i
+            })
+        }
+    }), b.extend({
+        active: 0,
+        lastModified: {},
+        etag: {},
+        ajaxSettings: {
+            url: yn,
+            type: &quot;GET&quot;,
+            isLocal: Nn.test(mn[1]),
+            global: !0,
+            processData: !0,
+            async: !0,
+            contentType: &quot;application/x-www-form-urlencoded; charset=UTF-8&quot;,
+            accepts: {
+                &quot;*&quot;: Dn,
+                text: &quot;text/plain&quot;,
+                html: &quot;text/html&quot;,
+                xml: &quot;application/xml, text/xml&quot;,
+                json: &quot;application/json, text/javascript&quot;
+            },
+            contents: {
+                xml: /xml/,
+                html: /html/,
+                json: /json/
+            },
+            responseFields: {
+                xml: &quot;responseXML&quot;,
+                text: &quot;responseText&quot;
+            },
+            converters: {
+                &quot;* text&quot;: e.String,
+                &quot;text html&quot;: !0,
+                &quot;text json&quot;: b.parseJSON,
+                &quot;text xml&quot;: b.parseXML
+            },
+            flatOptions: {
+                url: !0,
+                context: !0
+            }
+        },
+        ajaxSetup: function(e, t) {
+            return t ? Mn(Mn(e, b.ajaxSettings), t) : Mn(b.ajaxSettings, e)
+        },
+        ajaxPrefilter: Hn(An),
+        ajaxTransport: Hn(jn),
+        ajax: function(e, n) {
+            &quot;object&quot; == typeof e &amp;&amp; (n = e, e = t), n = n || {};
+            var r, i, o, a, s, u, l, c, p = b.ajaxSetup({}, n), f = p.context || p, d = p.context &amp;&amp; (f.nodeType || f.jquery) ? b(f): b.event, h = b.Deferred(), g = b.Callbacks(&quot;once memory&quot;), m = p.statusCode || {}, y = {}, v = {}, x = 0, T = &quot;canceled&quot;, N = {
+                readyState: 0,
+                getResponseHeader: function(e) {
+                    var t;
+                    if (2 === x) {
+                        if (!c) {
+                            c = {};
+                            while (t = Tn.exec(a))
+                                c[t[1].toLowerCase()] = t[2]
+                        }
+                        t = c[e.toLowerCase()]
+                    }
+                    return null == t ? null : t
+                },
+                getAllResponseHeaders: function() {
+                    return 2 === x ? a : null
+                },
+                setRequestHeader: function(e, t) {
+                    var n = e.toLowerCase();
+                    return x || (e = v[n] = v[n] || e, y[e] = t), this
+                },
+                overrideMimeType: function(e) {
+                    return x || (p.mimeType = e), this
+                },
+                statusCode: function(e) {
+                    var t;
+                    if (e)
+                        if (2 &gt; x)
+                            for (t in e)
+                                m[t] = [m[t], e[t]];
+                        else 
+                            N.always(e[N.status]);
+                    return this
+                },
+                abort: function(e) {
+                    var t = e || T;
+                    return l &amp;&amp; l.abort(t), k(0, t), this
+                }
+            };
+            if (h.promise(N).complete = g.add, N.success = N.done, N.error = N.fail, p.url = ((e || p.url || yn) + &quot;&quot;).replace(xn, &quot;&quot;).replace(kn, mn[1] + &quot;//&quot;), p.type = n.method || n.type || p.method || p.type, p.dataTypes = b.trim(p.dataType || &quot;*&quot;).toLowerCase().match(w) || [&quot;&quot;], null == p.crossDomain &amp;&amp; (r = En.exec(p.url.toLowerCase()), p.crossDomain=!(!r || r[1] === mn[1] &amp;&amp; r[2] === mn[2] &amp;&amp; (r[3] || (&quot;http:&quot; === r[1] ? 80 : 443)) == (mn[3] || (&quot;http:&quot; === mn[1] ? 80 : 443)))), p.data &amp;&amp; p.processData &amp;&amp; &quot;string&quot; != typeof p.data &amp;&amp; (p.data = b.param(p.data, p.traditional)), qn(An, p, n, N), 2 === x)return N;
+            u = p.global, u &amp;&amp; 0 === b.active++&amp;&amp;b.event.trigger(&quot;ajaxStart&quot;), p.type = p.type.toUpperCase(), p.hasContent=!Cn.test(p.type), o = p.url, p.hasContent || (p.data &amp;&amp; (o = p.url += (bn.test(o) ? &quot;&amp;&quot; : &quot;?&quot;) + p.data, delete p.data), p.cache===!1 &amp;&amp; (p.url = wn.test(o) ? o.replace(wn, &quot;$1_=&quot; + vn++) : o + (bn.test(o) ? &quot;&amp;&quot; : &quot;?&quot;) + &quot;_=&quot; + vn++)), p.ifModified &amp;&amp; (b.lastModified[o] &amp;&amp; N.setRequestHeader(&quot;If-Modified-Since&quot;, b.lastModified[o]), b.etag[o] &amp;&amp; N.setRequestHeader(&quot;If-None-Match&quot;, b.etag[o])), (p.data &amp;&amp; p.hasContent &amp;&amp; p.contentType!==!1 || n.contentType) &amp;&amp; N.setRequestHeader(&quot;Content-Type&quot;, p.contentType), N.setRequestHeader(&quot;Accept&quot;, p.dataTypes[0] &amp;&amp; p.accepts[p.dataTypes[0]] ? p.accepts[p.dataTypes[0]] + (&quot;*&quot; !== p.dataTypes[0] ? &quot;, &quot; + Dn + &quot;; q=0.01&quot; : &quot;&quot;) : p.accepts[&quot;*&quot;]);
+            for (i in p.headers)
+                N.setRequestHeader(i, p.headers[i]);
+            if (p.beforeSend &amp;&amp; (p.beforeSend.call(f, N, p)===!1 || 2 === x))
+                return N.abort();
+            T = &quot;abort&quot;;
+            for (i in{
+                success: 1,
+                error: 1,
+                complete: 1
+            })
+                N[i](p[i]);
+            if (l = qn(jn, p, n, N)) {
+                N.readyState = 1, u &amp;&amp; d.trigger(&quot;ajaxSend&quot;, [N, p]), p.async &amp;&amp; p.timeout &gt; 0 &amp;&amp; (s = setTimeout(function() {
+                    N.abort(&quot;timeout&quot;)
+                }, p.timeout));
+                try {
+                    x = 1, l.send(y, k)
+                } catch (C) {
+                    if (!(2 &gt; x))
+                        throw C;
+                    k(-1, C)
+                }
+            } else 
+                k(-1, &quot;No Transport&quot;);
+            function k(e, n, r, i) {
+                var c, y, v, w, T, C = n;
+                2 !== x &amp;&amp; (x = 2, s &amp;&amp; clearTimeout(s), l = t, a = i || &quot;&quot;, N.readyState = e &gt; 0 ? 4 : 0, r &amp;&amp; (w = _n(p, N, r)), e &gt;= 200 &amp;&amp; 300 &gt; e || 304 === e ? (p.ifModified &amp;&amp; (T = N.getResponseHeader(&quot;Last-Modified&quot;), T &amp;&amp; (b.lastModified[o] = T), T = N.getResponseHeader(&quot;etag&quot;), T &amp;&amp; (b.etag[o] = T)), 204 === e ? (c=!0, C = &quot;nocontent&quot;) : 304 === e ? (c=!0, C = &quot;notmodified&quot;) : (c = Fn(p, w), C = c.state, y = c.data, v = c.error, c=!v)) : (v = C, (e ||!C) &amp;&amp; (C = &quot;error&quot;, 0 &gt; e &amp;&amp; (e = 0))), N.status = e, N.statusText = (n || C) + &quot;&quot;, c ? h.resolveWith(f, [y, C, N]) : h.rejectWith(f, [N, C, v]), N.statusCode(m), m = t, u &amp;&amp; d.trigger(c ? &quot;ajaxSuccess&quot; : &quot;ajaxError&quot;, [N, p, c ? y: v]), g.fireWith(f, [N, C]), u &amp;&amp; (d.trigger(&quot;ajaxComplete&quot;, [N, p]), --b.active || b.event.trigger(&quot;ajaxStop&quot;)))
+            }
+            return N
+        },
+        getScript: function(e, n) {
+            return b.get(e, t, n, &quot;script&quot;)
+        },
+        getJSON: function(e, t, n) {
+            return b.get(e, t, n, &quot;json&quot;)
+        }
+    });
+    function _n(e, n, r) {
+        var i, o, a, s, u = e.contents, l = e.dataTypes, c = e.responseFields;
+        for (s in c)
+            s in r &amp;&amp; (n[c[s]] = r[s]);
+        while (&quot;*&quot; === l[0])
+            l.shift(), o === t &amp;&amp; (o = e.mimeType || n.getResponseHeader(&quot;Content-Type&quot;));
+        if (o)
+            for (s in u)
+                if (u[s] &amp;&amp; u[s].test(o)) {
+                    l.unshift(s);
+                    break
+                }
+        if (l[0]in r)
+            a = l[0];
+        else {
+            for (s in r) {
+                if (!l[0] || e.converters[s + &quot; &quot; + l[0]]) {
+                    a = s;
+                    break
+                }
+                i || (i = s)
+            }
+            a = a || i
+        }
+        return a ? (a !== l[0] &amp;&amp; l.unshift(a), r[a]) : t
+    }
+    function Fn(e, t) {
+        var n, r, i, o, a = {}, s = 0, u = e.dataTypes.slice(), l = u[0];
+        if (e.dataFilter &amp;&amp; (t = e.dataFilter(t, e.dataType)), u[1])
+            for (i in e.converters)
+                a[i.toLowerCase()] = e.converters[i];
+        for (; r = u[++s];)
+            if (&quot;*&quot; !== r) {
+                if (&quot;*&quot; !== l &amp;&amp; l !== r) {
+                    if (i = a[l + &quot; &quot; + r] || a[&quot;* &quot; + r], !i)
+                        for (n in a)
+                            if (o = n.split(&quot; &quot;), o[1] === r &amp;&amp; (i = a[l + &quot; &quot; + o[0]] || a[&quot;* &quot; + o[0]])
+                                ) {
+                                    i===!0 ? i = a[n] : a[n]!==!0 &amp;&amp; (r = o[0], u.splice(s--, 0, r));
+                                    break
+                                }
+                                if (i!==!0)
+                                    if (i &amp;&amp; e[&quot;throws&quot;])
+                                        t = i(t);
+                                    else 
+                                        try {
+                                            t = i(t)
+                                        } catch (c) {
+                                            return {
+                                                state: &quot;parsererror&quot;,
+                                                error: i ? c: &quot;No conversion from &quot; + l + &quot; to &quot; + r
+                                            }
+                                        }
+                                    }
+                                    l = r
+            }
+        return {
+            state: &quot;success&quot;,
+            data: t
+        }
+    }
+    b.ajaxSetup({
+        accepts: {
+            script: &quot;text/javascript, application/javascript, application/ecmascript, application/x-ecmascript&quot;
+        },
+        contents: {
+            script: /(?:java|ecma)script/
+        },
+        converters: {
+            &quot;text script&quot;: function(e) {
+                return b.globalEval(e), e
+            }
+        }
+    }), b.ajaxPrefilter(&quot;script&quot;, function(e) {
+        e.cache === t &amp;&amp; (e.cache=!1), e.crossDomain &amp;&amp; (e.type = &quot;GET&quot;, e.global=!1)
+    }), b.ajaxTransport(&quot;script&quot;, function(e) {
+        if (e.crossDomain) {
+            var n, r = o.head || b(&quot;head&quot;)[0] || o.documentElement;
+            return {
+                send: function(t, i) {
+                    n = o.createElement(&quot;script&quot;), n.async=!0, e.scriptCharset &amp;&amp; (n.charset = e.scriptCharset), n.src = e.url, n.onload = n.onreadystatechange = function(e, t) {
+                        (t ||!n.readyState || /loaded|complete/.test(n.readyState)) &amp;&amp; (n.onload = n.onreadystatechange = null, n.parentNode &amp;&amp; n.parentNode.removeChild(n), n = null, t || i(200, &quot;success&quot;))
+                    }, r.insertBefore(n, r.firstChild)
+                },
+                abort: function() {
+                    n &amp;&amp; n.onload(t, !0)
+                }
+            }
+        }
+    });
+    var On = [], Bn = /(=)\?(?=&amp;|$)|\?\?/;
+    b.ajaxSetup({
+        jsonp: &quot;callback&quot;,
+        jsonpCallback: function() {
+            var e = On.pop() || b.expando + &quot;_&quot; + vn++;
+            return this[e]=!0, e
+        }
+    }), b.ajaxPrefilter(&quot;json jsonp&quot;, function(n, r, i) {
+        var o, a, s, u = n.jsonp!==!1 &amp;&amp; (Bn.test(n.url) ? &quot;url&quot; : &quot;string&quot; == typeof n.data&amp;&amp;!(n.contentType || &quot;&quot;).indexOf(&quot;application/x-www-form-urlencoded&quot;) &amp;&amp; Bn.test(n.data) &amp;&amp; &quot;data&quot;);
+        return u || &quot;jsonp&quot; === n.dataTypes[0] ? (o = n.jsonpCallback = b.isFunction(n.jsonpCallback) ? n.jsonpCallback() : n.jsonpCallback, u ? n[u] = n[u].replace(Bn, &quot;$1&quot; + o) : n.jsonp!==!1 &amp;&amp; (n.url += (bn.test(n.url) ? &quot;&amp;&quot; : &quot;?&quot;) + n.jsonp + &quot;=&quot; + o), n.converters[&quot;script json&quot;] = function() {
+            return s || b.error(o + &quot; was not called&quot;), s[0]
+        }, n.dataTypes[0] = &quot;json&quot;, a = e[o], e[o] = function() {
+            s = arguments
+        }, i.always(function() {
+            e[o] = a, n[o] &amp;&amp; (n.jsonpCallback = r.jsonpCallback, On.push(o)), s &amp;&amp; b.isFunction(a) &amp;&amp; a(s[0]), s = a = t
+        }), &quot;script&quot;) : t
+    });
+    var Pn, Rn, Wn = 0, $n = e.ActiveXObject &amp;&amp; function() {
+        var e;
+        for (e in Pn)
+            Pn[e](t, !0)
+    };
+    function In() {
+        try {
+            return new e.XMLHttpRequest
+        } catch (t) {}
+    }
+    function zn() {
+        try {
+            return new e.ActiveXObject(&quot;Microsoft.XMLHTTP&quot;)
+        } catch (t) {}
+    }
+    b.ajaxSettings.xhr = e.ActiveXObject ? function() {
+        return !this.isLocal &amp;&amp; In() || zn()
+    } : In, Rn = b.ajaxSettings.xhr(), b.support.cors=!!Rn &amp;&amp; &quot;withCredentials&quot;in Rn, Rn = b.support.ajax=!!Rn, Rn &amp;&amp; b.ajaxTransport(function(n) {
+        if (!n.crossDomain || b.support.cors) {
+            var r;
+            return {
+                send: function(i, o) {
+                    var a, s, u = n.xhr();
+                    if (n.username ? u.open(n.type, n.url, n.async, n.username, n.password) : u.open(n.type, n.url, n.async), n.xhrFields)
+                        for (s in n.xhrFields)
+                            u[s] = n.xhrFields[s];
+                    n.mimeType &amp;&amp; u.overrideMimeType &amp;&amp; u.overrideMimeType(n.mimeType), n.crossDomain || i[&quot;X-Requested-With&quot;] || (i[&quot;X-Requested-With&quot;] = &quot;XMLHttpRequest&quot;);
+                    try {
+                        for (s in i)
+                            u.setRequestHeader(s, i[s])
+                    } catch (l) {}
+                    u.send(n.hasContent &amp;&amp; n.data || null), r = function(e, i) {
+                        var s, l, c, p;
+                        try {
+                            if (r &amp;&amp; (i || 4 === u.readyState))
+                                if (r = t, a &amp;&amp; (u.onreadystatechange = b.noop, $n &amp;&amp; delete Pn[a])
+                                    , i)4 !== u.readyState &amp;&amp; u.abort();
+                            else {
+                                p = {}, s = u.status, l = u.getAllResponseHeaders(), &quot;string&quot; == typeof u.responseText &amp;&amp; (p.text = u.responseText);
+                                try {
+                                    c = u.statusText
+                                } catch (f) {
+                                    c = &quot;&quot;
+                                }
+                                s ||!n.isLocal || n.crossDomain ? 1223 === s &amp;&amp; (s = 204) : s = p.text ? 200 : 404
+                            }
+                        } catch (d) {
+                            i || o(-1, d)
+                        }
+                        p &amp;&amp; o(s, c, p, l)
+                    }, n.async ? 4 === u.readyState ? setTimeout(r) : (a=++Wn, $n &amp;&amp; (Pn || (Pn = {}, b(e).unload($n)), Pn[a] = r), u.onreadystatechange = r) : r()
+                },
+                abort: function() {
+                    r &amp;&amp; r(t, !0)
+                }
+            }
+        }
+    });
+    var Xn, Un, Vn = /^(?:toggle|show|hide)$/, Yn = RegExp(&quot;^(?:([+-])=|)(&quot; + x + &quot;)([a-z%]*)$&quot;, &quot;i&quot;), Jn = /queueHooks$/, Gn = [nr], Qn = {
+        &quot;*&quot;: [function(e, t) {
+            var n, r, i = this.createTween(e, t), o = Yn.exec(t), a = i.cur(), s =+ a || 0, u = 1, l = 20;
+            if (o) {
+                if (n =+ o[2], r = o[3] || (b.cssNumber[e] ? &quot;&quot; : &quot;px&quot;)
+                    , &quot;px&quot; !== r &amp;&amp; s) {
+                    s = b.css(i.elem, e, !0) || n || 1;
+                    do 
+                        u = u || &quot;.5&quot;, s/=u, b.style(i.elem, e, s + r);
+                    while (u !== (u = i.cur() / a) &amp;&amp; 1 !== u&amp;&amp;--l)
+                    }
+                i.unit = r, i.start = s, i.end = o[1] ? s + (o[1] + 1) * n : n
+            }
+            return i
+        }
+        ]
+    };
+    function Kn() {
+        return setTimeout(function() {
+            Xn = t
+        }), Xn = b.now()
+    }
+    function Zn(e, t) {
+        b.each(t, function(t, n) {
+            var r = (Qn[t] || []).concat(Qn[&quot;*&quot;]),
+            i = 0,
+            o = r.length;
+            for (;
+            o &gt; i;
+            i++)if (r[i].call(e,
+            t,
+            n))return 
+        })
+    }
+    function er(e, t, n) {
+        var r, i, o = 0, a = Gn.length, s = b.Deferred().always(function() {
+            delete u.elem
+        }), u = function() {
+            if (i)
+                return !1;
+            var t = Xn || Kn(), n = Math.max(0, l.startTime + l.duration - t), r = n / l.duration || 0, o = 1 - r, a = 0, u = l.tweens.length;
+            for (; u &gt; a; a++)
+                l.tweens[a].run(o);
+            return s.notifyWith(e, [l, o, n]), 1 &gt; o &amp;&amp; u ? n : (s.resolveWith(e, [l]), !1)
+        }, l = s.promise({
+            elem: e,
+            props: b.extend({}, t),
+            opts: b.extend(!0, {
+                specialEasing: {}
+            }, n),
+            originalProperties: t,
+            originalOptions: n,
+            startTime: Xn || Kn(),
+            duration: n.duration,
+            tweens: [],
+            createTween: function(t, n) {
+                var r = b.Tween(e, l.opts, t, n, l.opts.specialEasing[t] || l.opts.easing);
+                return l.tweens.push(r), r
+            },
+            stop: function(t) {
+                var n = 0, r = t ? l.tweens.length: 0;
+                if (i)
+                    return this;
+                for (i=!0; r &gt; n; n++)
+                    l.tweens[n].run(1);
+                return t ? s.resolveWith(e, [l, t]) : s.rejectWith(e, [l, t]), this
+            }
+        }), c = l.props;
+        for (tr(c, l.opts.specialEasing);
+        a &gt; o;
+        o++)if (r = Gn[o].call(l, e, c, l.opts))
+            return r;
+        return Zn(l, c), b.isFunction(l.opts.start) &amp;&amp; l.opts.start.call(e, l), b.fx.timer(b.extend(u, {
+            elem: e,
+            anim: l,
+            queue: l.opts.queue
+        })), l.progress(l.opts.progress).done(l.opts.done, l.opts.complete).fail(l.opts.fail).always(l.opts.always)
+    }
+    function tr(e, t) {
+        var n, r, i, o, a;
+        for (i in e)
+            if (r = b.camelCase(i), o = t[r], n = e[i], b.isArray(n) &amp;&amp; (o = n[1], n = e[i] = n[0])
+                , i !== r &amp;&amp; (e[r] = n, delete e[i]), a = b.cssHooks[r], a &amp;&amp; &quot;expand&quot;in a) {
+            n = a.expand(n), delete e[r];
+            for (i in n)
+                i in e || (e[i] = n[i], t[i] = o)
+        } else 
+            t[r] = o
+    }
+    b.Animation = b.extend(er, {
+        tweener: function(e, t) {
+            b.isFunction(e) ? (t = e, e = [&quot;*&quot;]) : e = e.split(&quot; &quot;);
+            var n, r = 0, i = e.length;
+            for (; i &gt; r; r++)
+                n = e[r], Qn[n] = Qn[n] || [], Qn[n].unshift(t)
+        },
+        prefilter: function(e, t) {
+            t ? Gn.unshift(e) : Gn.push(e)
+        }
+    });
+    function nr(e, t, n) {
+        var r, i, o, a, s, u, l, c, p, f = this, d = e.style, h = {}, g = [], m = e.nodeType &amp;&amp; nn(e);
+        n.queue || (c = b._queueHooks(e, &quot;fx&quot;), null == c.unqueued &amp;&amp; (c.unqueued = 0, p = c.empty.fire, c.empty.fire = function() {
+            c.unqueued || p()
+        }), c.unqueued++, f.always(function() {
+            f.always(function() {
+                c.unqueued--, b.queue(e, &quot;fx&quot;).length || c.empty.fire()
+            })
+        })), 1 === e.nodeType &amp;&amp; (&quot;height&quot;in t || &quot;width&quot;in t) &amp;&amp; (n.overflow = [d.overflow, d.overflowX, d.overflowY], &quot;inline&quot; === b.css(e, &quot;display&quot;) &amp;&amp; &quot;none&quot; === b.css(e, &quot;float&quot;) &amp;&amp; (b.support.inlineBlockNeedsLayout &amp;&amp; &quot;inline&quot; !== un(e.nodeName) ? d.zoom = 1 : d.display = &quot;inline-block&quot;)), n.overflow &amp;&amp; (d.overflow = &quot;hidden&quot;, b.support.shrinkWrapBlocks || f.always(function() {
+            d.overflow = n.overflow[0], d.overflowX = n.overflow[1], d.overflowY = n.overflow[2]
+        }));
+        for (i in t)
+            if (a = t[i], Vn.exec(a)
+                ) {
+            if (delete t[i], u = u || &quot;toggle&quot; === a, a === (m ? &quot;hide&quot; : &quot;show&quot;)
+                )continue;
+            g.push(i)
+        }
+        if (o = g.length) {
+            s = b._data(e, &quot;fxshow&quot;) || b._data(e, &quot;fxshow&quot;, {}), &quot;hidden&quot;in s &amp;&amp; (m = s.hidden), u &amp;&amp; (s.hidden=!m), m ? b(e).show() : f.done(function() {
+                b(e).hide()
+            }), f.done(function() {
+                var t;
+                b._removeData(e, &quot;fxshow&quot;);
+                for (t in h)
+                    b.style(e, t, h[t])
+            });
+            for (i = 0; o &gt; i; i++)
+                r = g[i], l = f.createTween(r, m ? s[r] : 0), h[r] = s[r] || b.style(e, r), r in s || (s[r] = l.start, m &amp;&amp; (l.end = l.start, l.start = &quot;width&quot; === r || &quot;height&quot; === r ? 1 : 0))
+        }
+    }
+    function rr(e, t, n, r, i) {
+        return new rr.prototype.init(e, t, n, r, i)
+    }
+    b.Tween = rr, rr.prototype = {
+        constructor: rr,
+        init: function(e, t, n, r, i, o) {
+            this.elem = e, this.prop = n, this.easing = i || &quot;swing&quot;, this.options = t, this.start = this.now = this.cur(), this.end = r, this.unit = o || (b.cssNumber[n] ? &quot;&quot; : &quot;px&quot;)
+        },
+        cur: function() {
+            var e = rr.propHooks[this.prop];
+            return e &amp;&amp; e.get ? e.get(this) : rr.propHooks._default.get(this)
+        },
+        run: function(e) {
+            var t, n = rr.propHooks[this.prop];
+            return this.pos = t = this.options.duration ? b.easing[this.easing](e, this.options.duration * e, 0, 1, this.options.duration) : e, this.now = (this.end - this.start) * t + this.start, this.options.step &amp;&amp; this.options.step.call(this.elem, this.now, this), n &amp;&amp; n.set ? n.set(this) : rr.propHooks._default.set(this), this
+        }
+    }, rr.prototype.init.prototype = rr.prototype, rr.propHooks = {
+        _default: {
+            get: function(e) {
+                var t;
+                return null == e.elem[e.prop] || e.elem.style &amp;&amp; null != e.elem.style[e.prop] ? (t = b.css(e.elem, e.prop, &quot;&quot;), t &amp;&amp; &quot;auto&quot; !== t ? t : 0) : e.elem[e.prop]
+            },
+            set: function(e) {
+                b.fx.step[e.prop] ? b.fx.step[e.prop](e) : e.elem.style &amp;&amp; (null != e.elem.style[b.cssProps[e.prop]] || b.cssHooks[e.prop]) ? b.style(e.elem, e.prop, e.now + e.unit) : e.elem[e.prop] = e.now
+            }
+        }
+    }, rr.propHooks.scrollTop = rr.propHooks.scrollLeft = {
+        set: function(e) {
+            e.elem.nodeType &amp;&amp; e.elem.parentNode &amp;&amp; (e.elem[e.prop] = e.now)
+        }
+    }, b.each([&quot;toggle&quot;, &quot;show&quot;, &quot;hide&quot;], function(e, t) {
+        var n = b.fn[t];
+        b.fn[t] = function(e, r, i) {
+            return null == e || &quot;boolean&quot; == typeof e ? n.apply(this, arguments) : this.animate(ir(t, !0), e, r, i)
+        }
+    }), b.fn.extend({
+        fadeTo: function(e, t, n, r) {
+            return this.filter(nn).css(&quot;opacity&quot;, 0).show().end().animate({
+                opacity: t
+            }, e, n, r)
+        },
+        animate: function(e, t, n, r) {
+            var i = b.isEmptyObject(e), o = b.speed(t, n, r), a = function() {
+                var t = er(this, b.extend({}, e), o);
+                a.finish = function() {
+                    t.stop(!0)
+                }, (i || b._data(this, &quot;finish&quot;)) &amp;&amp; t.stop(!0)
+            };
+            return a.finish = a, i || o.queue===!1 ? this.each(a) : this.queue(o.queue, a)
+        },
+        stop: function(e, n, r) {
+            var i = function(e) {
+                var t = e.stop;
+                delete e.stop, t(r)
+            };
+            return &quot;string&quot; != typeof e &amp;&amp; (r = n, n = e, e = t), n &amp;&amp; e!==!1 &amp;&amp; this.queue(e || &quot;fx&quot;, []), this.each(function() {
+                var t=!0, n = null != e &amp;&amp; e + &quot;queueHooks&quot;, o = b.timers, a = b._data(this);
+                if (n)
+                    a[n] &amp;&amp; a[n].stop &amp;&amp; i(a[n]);
+                else 
+                    for (n in a)
+                        a[n] &amp;&amp; a[n].stop &amp;&amp; Jn.test(n) &amp;&amp; i(a[n]);
+                for (n = o.length; n--;)
+                    o[n].elem !== this || null != e &amp;&amp; o[n].queue !== e || (o[n].anim.stop(r), t=!1, o.splice(n, 1));
+                (t ||!r) &amp;&amp; b.dequeue(this, e)
+            })
+        },
+        finish: function(e) {
+            return e!==!1 &amp;&amp; (e = e || &quot;fx&quot;), this.each(function() {
+                var t, n = b._data(this), r = n[e + &quot;queue&quot;], i = n[e + &quot;queueHooks&quot;], o = b.timers, a = r ? r.length: 0;
+                for (n.finish=!0, b.queue(this, e, [])
+                    , i &amp;&amp; i.cur &amp;&amp; i.cur.finish &amp;&amp; i.cur.finish.call(this), t = o.length;
+                t--;
+                )o[t].elem === this &amp;&amp; o[t].queue === e &amp;&amp; (o[t].anim.stop(!0), o.splice(t, 1));
+                for (t = 0; a &gt; t; t++)
+                    r[t] &amp;&amp; r[t].finish &amp;&amp; r[t].finish.call(this);
+                delete n.finish
+            })
+        }
+    });
+    function ir(e, t) {
+        var n, r = {
+            height: e
+        }, i = 0;
+        for (t = t ? 1 : 0; 4 &gt; i; i += 2 - t)
+            n = Zt[i], r[&quot;margin&quot; + n] = r[&quot;padding&quot; + n] = e;
+        return t &amp;&amp; (r.opacity = r.width = e), r
+    }
+    b.each({
+        slideDown: ir(&quot;show&quot;),
+        slideUp: ir(&quot;hide&quot;),
+        slideToggle: ir(&quot;toggle&quot;),
+        fadeIn: {
+            opacity: &quot;show&quot;
+        },
+        fadeOut: {
+            opacity: &quot;hide&quot;
+        },
+        fadeToggle: {
+            opacity: &quot;toggle&quot;
+        }
+    }, function(e, t) {
+        b.fn[e] = function(e, n, r) {
+            return this.animate(t, e, n, r)
+        }
+    }), b.speed = function(e, t, n) {
+        var r = e &amp;&amp; &quot;object&quot; == typeof e ? b.extend({}, e): {
+            complete: n ||!n &amp;&amp; t || b.isFunction(e) &amp;&amp; e,
+            duration: e,
+            easing: n &amp;&amp; t || t&amp;&amp;!b.isFunction(t) &amp;&amp; t
+        };
+        return r.duration = b.fx.off ? 0 : &quot;number&quot; == typeof r.duration ? r.duration : r.duration in b.fx.speeds ? b.fx.speeds[r.duration] : b.fx.speeds._default, (null == r.queue || r.queue===!0) &amp;&amp; (r.queue = &quot;fx&quot;), r.old = r.complete, r.complete = function() {
+            b.isFunction(r.old) &amp;&amp; r.old.call(this), r.queue &amp;&amp; b.dequeue(this, r.queue)
+        }, r
+    }, b.easing = {
+        linear: function(e) {
+            return e
+        },
+        swing: function(e) {
+            return .5 - Math.cos(e * Math.PI) / 2
+        }
+    }, b.timers = [], b.fx = rr.prototype.init, b.fx.tick = function() {
+        var e, n = b.timers, r = 0;
+        for (Xn = b.now(); n.length &gt; r; r++)
+            e = n[r], e() || n[r] !== e || n.splice(r--, 1);
+        n.length || b.fx.stop(), Xn = t
+    }, b.fx.timer = function(e) {
+        e() &amp;&amp; b.timers.push(e) &amp;&amp; b.fx.start()
+    }, b.fx.interval = 13, b.fx.start = function() {
+        Un || (Un = setInterval(b.fx.tick, b.fx.interval))
+    }, b.fx.stop = function() {
+        clearInterval(Un), Un = null
+    }, b.fx.speeds = {
+        slow: 600,
+        fast: 200,
+        _default: 400
+    }, b.fx.step = {}, b.expr &amp;&amp; b.expr.filters &amp;&amp; (b.expr.filters.animated = function(e) {
+        return b.grep(b.timers, function(t) {
+            return e === t.elem
+        }).length
+    }), b.fn.offset = function(e) {
+        if (arguments.length)
+            return e === t ? this : this.each(function(t) {
+                b.offset.setOffset(this, e, t)
+            });
+        var n, r, o = {
+            top: 0,
+            left: 0
+        }, a = this[0], s = a &amp;&amp; a.ownerDocument;
+        if (s)
+            return n = s.documentElement, b.contains(n, a) ? (typeof a.getBoundingClientRect !== i &amp;&amp; (o = a.getBoundingClientRect()), r = or(s), {
+            top : o.top + (r.pageYOffset || n.scrollTop) - (n.clientTop || 0), left: o.left + (r.pageXOffset || n.scrollLeft) - (n.clientLeft || 0)
+        }) : o
+    }, b.offset = {
+        setOffset: function(e, t, n) {
+            var r = b.css(e, &quot;position&quot;);
+            &quot;static&quot; === r &amp;&amp; (e.style.position = &quot;relative&quot;);
+            var i = b(e), o = i.offset(), a = b.css(e, &quot;top&quot;), s = b.css(e, &quot;left&quot;), u = (&quot;absolute&quot; === r || &quot;fixed&quot; === r) &amp;&amp; b.inArray(&quot;auto&quot;, [a, s])&gt;-1, l = {}, c = {}, p, f;
+            u ? (c = i.position(), p = c.top, f = c.left) : (p = parseFloat(a) || 0, f = parseFloat(s) || 0), b.isFunction(t) &amp;&amp; (t = t.call(e, n, o)), null != t.top &amp;&amp; (l.top = t.top - o.top + p), null != t.left &amp;&amp; (l.left = t.left - o.left + f), &quot;using&quot;in t ? t.using.call(e, l) : i.css(l)
+        }
+    }, b.fn.extend({
+        position: function() {
+            if (this[0]) {
+                var e, t, n = {
+                    top: 0,
+                    left: 0
+                }, r = this[0];
+                return &quot;fixed&quot; === b.css(r, &quot;position&quot;) ? t = r.getBoundingClientRect() : (e = this.offsetParent(), t = this.offset(), b.nodeName(e[0], &quot;html&quot;) || (n = e.offset()), n.top += b.css(e[0], &quot;borderTopWidth&quot;, !0), n.left += b.css(e[0], &quot;borderLeftWidth&quot;, !0)), {
+                    top: t.top - n.top - b.css(r, &quot;marginTop&quot;, !0), left: t.left - n.left - b.css(r, &quot;marginLeft&quot;, !0)
+                }
+            }
+        },
+        offsetParent: function() {
+            return this.map(function() {
+                var e = this.offsetParent || o.documentElement;
+                while (e&amp;&amp;!b.nodeName(e, &quot;html&quot;) &amp;&amp; &quot;static&quot; === b.css(e, &quot;position&quot;))
+                    e = e.offsetParent;
+                return e || o.documentElement
+            })
+        }
+    }), b.each({
+        scrollLeft: &quot;pageXOffset&quot;,
+        scrollTop: &quot;pageYOffset&quot;
+    }, function(e, n) {
+        var r = /Y/.test(n);
+        b.fn[e] = function(i) {
+            return b.access(this, function(e, i, o) {
+                var a = or(e);
+                return o === t ? a ? n in a ? a[n] : a.document.documentElement[i] : e[i] : (a ? a.scrollTo(r ? b(a).scrollLeft() : o, r ? o : b(a).scrollTop()) : e[i] = o, t)
+            }, e, i, arguments.length, null)
+        }
+    });
+    function or(e) {
+        return b.isWindow(e) ? e : 9 === e.nodeType ? e.defaultView || e.parentWindow : !1
+    }
+    b.each({
+        Height: &quot;height&quot;,
+        Width: &quot;width&quot;
+    }, function(e, n) {
+        b.each({
+            padding: &quot;inner&quot; + e,
+            content: n,
+            &quot;&quot;: &quot;outer&quot; + e
+        }, function(r, i) {
+            b.fn[i] = function(i, o) {
+                var a = arguments.length &amp;&amp; (r || &quot;boolean&quot; != typeof i), s = r || (i===!0 || o===!0 ? &quot;margin&quot; : &quot;border&quot;);
+                return b.access(this, function(n, r, i) {
+                    var o;
+                    return b.isWindow(n) ? n.document.documentElement[&quot;client&quot; + e] : 9 === n.nodeType ? (o = n.documentElement, Math.max(n.body[&quot;scroll&quot; + e], o[&quot;scroll&quot; + e], n.body[&quot;offset&quot; + e], o[&quot;offset&quot; + e], o[&quot;client&quot; + e])) : i === t ? b.css(n, r, s) : b.style(n, r, i, s)
+                }, n, a ? i : t, a, null)
+            }
+        })
+    }), e.jQuery = e.$ = b, &quot;function&quot; == typeof define &amp;&amp; define.amd &amp;&amp; define.amd.jQuery &amp;&amp; define(&quot;jquery&quot;, [], function() {
+        return b
+    })
+})(window);
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/jquery.min.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2jsstatisticsjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/js/statistics.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/js/statistics.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/js/statistics.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,107 @@
</span><ins>+var Statistics = new (function () {
+
+    this.sum = function (values) {
+        return values.length ? values.reduce(function (a, b) { return a + b; }) : 0;
+    }
+
+    this.squareSum = function (values) {
+        return values.length ? values.reduce(function (sum, value) { return sum + value * value;}, 0) : 0;
+    }
+
+    // With sum and sum of squares, we can compute the sample standard deviation in O(1).
+    // See https://rniwa.com/2012-11-10/sample-standard-deviation-in-terms-of-sum-and-square-sum-of-samples/
+    this.sampleStandardDeviation = function (numberOfSamples, sum, squareSum) {
+        if (numberOfSamples &lt; 2)
+            return 0;
+        return Math.sqrt(squareSum / (numberOfSamples - 1) - sum * sum / (numberOfSamples - 1) / numberOfSamples);
+    }
+
+    this.supportedConfidenceIntervalProbabilities = function () {
+        var supportedProbabilities = [];
+        for (var quantile in tDistributionQuantiles)
+            supportedProbabilities.push((1 - (1 - quantile) * 2).toFixed(2));
+        return supportedProbabilities
+    }
+
+    // Computes the delta d s.t. (mean - d, mean + d) is the confidence interval with the specified probability in O(1).
+    this.confidenceIntervalDelta = function (probability, numberOfSamples, sum, squareSum) {
+        var quantile = (1 - (1 - probability) / 2);
+        if (!(quantile in tDistributionQuantiles)) {
+            throw 'We only support ' + this.supportedConfidenceIntervalProbabilities().map(function (probability)
+            { return probability * 100 + '%'; } ).join(', ') + ' confidence intervals.';
+        }
+        if (numberOfSamples - 2 &lt; 0)
+            return NaN;
+        var deltas = tDistributionQuantiles[quantile];
+        var degreesOfFreedom = numberOfSamples - 1;
+        if (degreesOfFreedom &gt; deltas.length)
+            throw 'We only support up to ' + deltas.length + ' degrees of freedom';
+
+        // d = c * S/sqrt(numberOfSamples) where c ~ t-distribution(degreesOfFreedom) and S is the sample standard deviation.
+        return deltas[degreesOfFreedom - 1] * this.sampleStandardDeviation(numberOfSamples, sum, squareSum) / Math.sqrt(numberOfSamples);
+    }
+
+    this.confidenceInterval = function (values, probability) {
+        var sum = this.sum(values);
+        var mean = sum / values.length;
+        var delta = this.confidenceIntervalDelta(probability || 0.95, values.length, sum, this.squareSum(values));
+        return [mean - delta, mean + delta];
+    }
+
+    var tDistributionQuantiles = {
+        0.9: [
+            3.077684, 1.885618, 1.637744, 1.533206, 1.475884, 1.439756, 1.414924, 1.396815, 1.383029, 1.372184,
+            1.363430, 1.356217, 1.350171, 1.345030, 1.340606, 1.336757, 1.333379, 1.330391, 1.327728, 1.325341,
+            1.323188, 1.321237, 1.319460, 1.317836, 1.316345, 1.314972, 1.313703, 1.312527, 1.311434, 1.310415,
+            1.309464, 1.308573, 1.307737, 1.306952, 1.306212, 1.305514, 1.304854, 1.304230, 1.303639, 1.303077,
+            1.302543, 1.302035, 1.301552, 1.301090, 1.300649, 1.300228, 1.299825, 1.299439, 1.299069, 1.298714,
+
+            1.298373, 1.298045, 1.297730, 1.297426, 1.297134, 1.296853, 1.296581, 1.296319, 1.296066, 1.295821,
+            1.295585, 1.295356, 1.295134, 1.294920, 1.294712, 1.294511, 1.294315, 1.294126, 1.293942, 1.293763,
+            1.293589, 1.293421, 1.293256, 1.293097, 1.292941, 1.292790, 1.292643, 1.292500, 1.292360, 1.292224,
+            1.292091, 1.291961, 1.291835, 1.291711, 1.291591, 1.291473, 1.291358, 1.291246, 1.291136, 1.291029,
+            1.290924, 1.290821, 1.290721, 1.290623, 1.290527, 1.290432, 1.290340, 1.290250, 1.290161, 1.290075],
+        0.95: [
+            6.313752, 2.919986, 2.353363, 2.131847, 2.015048, 1.943180, 1.894579, 1.859548, 1.833113, 1.812461,
+            1.795885, 1.782288, 1.770933, 1.761310, 1.753050, 1.745884, 1.739607, 1.734064, 1.729133, 1.724718,
+            1.720743, 1.717144, 1.713872, 1.710882, 1.708141, 1.705618, 1.703288, 1.701131, 1.699127, 1.697261,
+            1.695519, 1.693889, 1.692360, 1.690924, 1.689572, 1.688298, 1.687094, 1.685954, 1.684875, 1.683851,
+            1.682878, 1.681952, 1.681071, 1.680230, 1.679427, 1.678660, 1.677927, 1.677224, 1.676551, 1.675905,
+
+            1.675285, 1.674689, 1.674116, 1.673565, 1.673034, 1.672522, 1.672029, 1.671553, 1.671093, 1.670649,
+            1.670219, 1.669804, 1.669402, 1.669013, 1.668636, 1.668271, 1.667916, 1.667572, 1.667239, 1.666914,
+            1.666600, 1.666294, 1.665996, 1.665707, 1.665425, 1.665151, 1.664885, 1.664625, 1.664371, 1.664125,
+            1.663884, 1.663649, 1.663420, 1.663197, 1.662978, 1.662765, 1.662557, 1.662354, 1.662155, 1.661961,
+            1.661771, 1.661585, 1.661404, 1.661226, 1.661052, 1.660881, 1.660715, 1.660551, 1.660391, 1.660234],
+        0.975: [
+            12.706205, 4.302653, 3.182446, 2.776445, 2.570582, 2.446912, 2.364624, 2.306004, 2.262157, 2.228139,
+            2.200985, 2.178813, 2.160369, 2.144787, 2.131450, 2.119905, 2.109816, 2.100922, 2.093024, 2.085963,
+            2.079614, 2.073873, 2.068658, 2.063899, 2.059539, 2.055529, 2.051831, 2.048407, 2.045230, 2.042272,
+            2.039513, 2.036933, 2.034515, 2.032245, 2.030108, 2.028094, 2.026192, 2.024394, 2.022691, 2.021075,
+            2.019541, 2.018082, 2.016692, 2.015368, 2.014103, 2.012896, 2.011741, 2.010635, 2.009575, 2.008559,
+
+            2.007584, 2.006647, 2.005746, 2.004879, 2.004045, 2.003241, 2.002465, 2.001717, 2.000995, 2.000298,
+            1.999624, 1.998972, 1.998341, 1.997730, 1.997138, 1.996564, 1.996008, 1.995469, 1.994945, 1.994437,
+            1.993943, 1.993464, 1.992997, 1.992543, 1.992102, 1.991673, 1.991254, 1.990847, 1.990450, 1.990063,
+            1.989686, 1.989319, 1.988960, 1.988610, 1.988268, 1.987934, 1.987608, 1.987290, 1.986979, 1.986675,
+            1.986377, 1.986086, 1.985802, 1.985523, 1.985251, 1.984984, 1.984723, 1.984467, 1.984217, 1.983972],
+        0.99: [
+            31.820516, 6.964557, 4.540703, 3.746947, 3.364930, 3.142668, 2.997952, 2.896459, 2.821438, 2.763769,
+            2.718079, 2.680998, 2.650309, 2.624494, 2.602480, 2.583487, 2.566934, 2.552380, 2.539483, 2.527977,
+            2.517648, 2.508325, 2.499867, 2.492159, 2.485107, 2.478630, 2.472660, 2.467140, 2.462021, 2.457262,
+            2.452824, 2.448678, 2.444794, 2.441150, 2.437723, 2.434494, 2.431447, 2.428568, 2.425841, 2.423257,
+            2.420803, 2.418470, 2.416250, 2.414134, 2.412116, 2.410188, 2.408345, 2.406581, 2.404892, 2.403272,
+
+            2.401718, 2.400225, 2.398790, 2.397410, 2.396081, 2.394801, 2.393568, 2.392377, 2.391229, 2.390119,
+            2.389047, 2.388011, 2.387008, 2.386037, 2.385097, 2.384186, 2.383302, 2.382446, 2.381615, 2.380807,
+            2.380024, 2.379262, 2.378522, 2.377802, 2.377102, 2.376420, 2.375757, 2.375111, 2.374482, 2.373868,
+            2.373270, 2.372687, 2.372119, 2.371564, 2.371022, 2.370493, 2.369977, 2.369472, 2.368979, 2.368497,
+            2.368026, 2.367566, 2.367115, 2.366674, 2.366243, 2.365821, 2.365407, 2.365002, 2.364606, 2.364217]
+    };
+
+})();
+
+if (typeof module != 'undefined') {
+    for (var key in Statistics)
+        module.exports[key] = Statistics[key];
+}
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/js/statistics.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2manifestjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/manifest.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/manifest.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/manifest.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,196 @@
</span><ins>+App.NameLabelModel = DS.Model.extend({
+    name: DS.attr('string'),
+    label: function ()
+    {
+        return this.get('name');
+    }.property('name'),
+});
+
+App.Test = App.NameLabelModel.extend({
+    url: DS.attr('string'),
+    parent: DS.belongsTo('test', {inverse: 'childTests'}),
+    childTests: DS.hasMany('test', {inverse: 'parent'}),
+    metrics: DS.hasMany('metrics'),
+});
+
+App.Metric = App.NameLabelModel.extend({
+    test: DS.belongsTo('test'),
+    aggregator: DS.attr('string'),
+    label: function ()
+    {
+        return this.get('name') + ' : ' + this.get('aggregator');
+    }.property('name', 'aggregator'),
+    path: function ()
+    {
+        var path = [];
+        var parent = this.get('test');
+        while (parent) {
+            path.push(parent.get('name'));
+            parent = parent.get('parent');
+        }
+        return path.reverse();
+    }.property('name', 'test'),
+});
+
+App.Builder = App.NameLabelModel.extend({
+    buildUrl: DS.attr('string'),
+    urlFromBuildNumber: function (buildNumber)
+    {
+        var template = this.get('buildUrl');
+        return template ? template.replace(/\$buildNumber/g, buildNumber) : null;
+    }
+});
+
+App.BugTracker = App.NameLabelModel.extend({
+    buildUrl: DS.attr('string'),
+});
+
+App.Platform = App.NameLabelModel.extend({
+    _metricSet: null,
+    _testSet: null,
+    metrics: DS.hasMany('metric'),
+    containsMetric: function (metric)
+    {
+        if (!this._metricSet)
+            this._metricSet = new Ember.Set(this.get('metrics'));
+        return this._metricSet.contains(metric);
+    },
+    containsTest: function (test)
+    {
+        if (!this._testSet) {
+            var set = new Ember.Set();
+            this.get('metrics').forEach(function (metric) {
+                for (var test = metric.get('test'); test; test = test.get('parent'))
+                    set.push(test);
+            });
+            this._testSet = set;
+        }
+        return this._testSet.contains(test);
+    },
+});
+
+App.Repository = App.NameLabelModel.extend({
+    url: DS.attr('string'),
+    blameUrl: DS.attr('string'),
+    urlForRevision: function (currentRevision) {
+        return (this.get('url') || '').replace(/\$1/g, currentRevision);
+    },
+    urlForRevisionRange: function (from, to) {
+        return (this.get('blameUrl') || '').replace(/\$1/g, from).replace(/\$2/g, to);
+    },
+});
+
+App.MetricSerializer = App.PlatformSerializer = DS.RESTSerializer.extend({
+    normalizePayload: function (payload)
+    {
+        var results = {
+            platforms: this._normalizeIdMap(payload['all']),
+            builders: this._normalizeIdMap(payload['builders']),
+            tests: this._normalizeIdMap(payload['tests']).map(function (test) {
+                test['parent'] = test['parentId'];
+                return test;
+            }),
+            metrics: this._normalizeIdMap(payload['metrics']),
+            repositories: this._normalizeIdMap(payload['repositories']),
+        };
+
+        for (var testId in payload['tests']) {
+            var test = payload['tests'][testId];
+            var parent = payload['tests'][test['parent']];
+            if (!parent)
+                continue;
+            if (!parent['childTests'])
+                parent['childTests'] = [];
+            parent['childTests'].push(testId);
+        }
+
+        for (var metricId in payload['metrics']) {
+            var metric = payload['metrics'][metricId];
+            var test = payload['tests'][metric['test']];
+            if (!test['metrics'])
+                test['metrics'] = [];
+            test['metrics'].push(metricId);
+        }
+
+        return results;
+    },
+    _normalizeIdMap: function (idMap)
+    {
+        var results = [];
+        for (var id in idMap) {
+            var definition = idMap[id];
+            definition['id'] = id;
+            results.push(definition);
+        }
+        return results;
+    }
+});
+
+App.PlatformAdapter = DS.RESTAdapter.extend({
+    buildURL: function (type, id)
+    {
+        return '../data/manifest.json';
+    },
+});
+
+App.MetricAdapter = DS.RESTAdapter.extend({
+    buildURL: function (type, id)
+    {
+        return '../data/manifest.json';
+    },
+});
+
+App.Manifest = Ember.Controller.extend({
+    platforms: null,
+    topLevelTests: null,
+    _platformById: {},
+    _metricById: {},
+    _builderById: {},
+    _repositoryById: {},
+    _fetchPromise: null,
+    fetch: function ()
+    {
+        if (this._fetchPromise)
+            return this._fetchPromise;
+        // FIXME: We shouldn't use DS.Store at all.
+        var store = App.__container__.lookup('store:main');
+        var promise = store.findAll('platform');
+        this._fetchPromise = promise.then(this._fetchedManifest.bind(this, store));
+        return this._fetchPromise;
+    },
+    isFetched: function () { return !!this.get('platforms'); }.property('platforms'),
+    platform: function (id) { return this._platformById[id]; },
+    metric: function (id) { return this._metricById[id]; },
+    builder: function (id) { return this._builderById[id]; },
+    repository: function (id) { return this._repositoryById[id]; },
+    _fetchedManifest: function (store)
+    {
+        var startTime = Date.now();
+        var self = this;
+
+        var topLevelTests = [];
+        store.all('test').forEach(function (test) {
+            var parent = test.get('parent');
+            if (!parent)
+                topLevelTests.push(test);
+        });
+        this.set('topLevelTests', topLevelTests);
+
+        store.all('metric').forEach(function (metric) {
+            self._metricById[metric.get('id')] = metric;
+        });
+        var platforms = store.all('platform');
+        platforms.forEach(function (platform) {
+            self._platformById[platform.get('id')] = platform;
+        });
+        this.set('platforms', platforms);
+
+        store.all('builder').forEach(function (builder) {
+            self._builderById[builder.get('id')] = builder;
+        });
+
+        store.all('repository').forEach(function (repository) {
+            self._repositoryById[repository.get('id')] = repository;
+        });
+    }
+}).create();
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/manifest.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<a id="trunkWebsitesperfwebkitorgpublicv2popupjs"></a>
<div class="addfile"><h4>Added: trunk/Websites/perf.webkit.org/public/v2/popup.js (0 => 174477)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/public/v2/popup.js                                (rev 0)
+++ trunk/Websites/perf.webkit.org/public/v2/popup.js        2014-10-08 20:40:18 UTC (rev 174477)
</span><span class="lines">@@ -0,0 +1,116 @@
</span><ins>+App.PopupView = Ember.View.extend({
+    templateName: 'popup',
+    classNames: ['popup'],
+    popupListContainerView: Ember.ContainerView.extend(),
+    init: function ()
+    {
+        this._super();
+        this._listView = null;
+    },
+    showPopup: function ()
+    {
+        this.unscheduleHiding();
+        if (!this._listView) {
+            var list = this.get('list');
+            this._listView = App.PopupListView.create({tagName: 'ul', list: list});
+            this.get('popupListContainerViewInstance').pushObject(this._listView);
+        }
+        this._listView.showList();
+    },
+    scheduleHiding: function ()
+    {
+        this._hidingTimer = Ember.run.later(this, this.hideNow, 100);
+    },
+    unscheduleHiding: function ()
+    {
+        Ember.run.cancel(this._hidingTimer);
+        this._hidingTimer = null;
+    },
+    hideNow: function ()
+    {
+        if (this._listView)
+            this._listView.hideList();
+    }
+});
+
+App.PopupButtonView = Ember.View.extend({
+    template: Ember.Handlebars.compile('{{view.label}}'),
+    classNames: ['popup-button'],
+    attributeBindings: ['href'],
+    href: '#',
+    mouseEnter: function ()
+    {
+        this.get('parentView').showPopup();
+    },
+    click: function (event)
+    {
+        this.get('parentView').showPopup();
+        event.preventDefault();
+    },
+    mouseLeave: function ()
+    {
+        this.get('parentView').scheduleHiding();
+    },
+});
+
+App.PopupListView = Ember.View.extend({
+    templateName: 'popup-list',
+    init: function ()
+    {
+        this._super();
+        this._shouldHide = true;
+    },
+    _poupView: function ()
+    {
+        var containerView = this.get('parentView');
+        return containerView.get('parentView');
+    },
+    didInsertElement: function ()
+    {
+        if (this._shouldHide)
+            this.$().hide();
+        else
+            this._showListSyncIfPossible();
+        this._super();
+    },
+    mouseEnter: function ()
+    {
+        this._poupView().unscheduleHiding();
+    },
+    mouseLeave: function ()
+    {
+        this._poupView().scheduleHiding();
+    },
+    showList: function ()
+    {
+        this._shouldHide = false;
+        this._showListSyncIfPossible();
+    },
+    _showListSyncIfPossible: function ()
+    {
+        if (!this.$())
+            return;
+        var popupView = this._poupView();
+        if (popupView.get('parentView') instanceof App.PopupListView) {
+            var parentListView = popupView.get('parentView');
+            parentListView.get('childViews').map(function (sibling) {
+                if (sibling != popupView)
+                    sibling.hideNow();
+            });
+            this.$().css('left', parentListView.$().outerWidth() + 5);
+        } else
+            this.$().css('top', popupView.$().height() - 5);
+        this.$().show();
+    },
+    hideList: function ()
+    {
+        this._shouldHide = true;
+        this._hideListSyncIfPossible();
+    },
+    _hideListSyncIfPossible: function ()
+    {
+        if (!this.$())
+            return;
+        this.$().hide();
+    }
+});
</ins><span class="cx">Property changes on: trunk/Websites/perf.webkit.org/public/v2/popup.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
</div>

</body>
</html>