UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

232 lines (213 loc) 6.17 kB
<body> <style> * { font: 13px/16px "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; color: #333; } table { margin: 5px auto; margin-bottom: 15px; width: 95%; } td { border-top: 1px solid #eee; padding: 5px; } tr:last-child { border-bottom: 1px solid #eee; } tr:nth-child(odd) { background-color: #fcfcf1; } thead th { background-color: #ccc; color: #666; padding: 5px; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); } next-prev { margin: 5px auto;text-align: center;display: block; } next-prev a { border-radius: 3px; padding: 4px 14px; text-decoration: none; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); background-color: #f5f5f5; border: 1px solid #bbbbbb; border-color: #e6e6e6 #e6e6e6 #bfbfbf; } next-prev a.enabled { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #49afcd; border-color: #2f96b4 #2f96b4 #1f6377; } page-count { display: block; } page-count, page-count * { font-size: 11px; color: #ccc; text-align: center; } .waiting { opacity: 0.5; } </style> <div id='out'></div> <script id="app-stache" type='text/stache'> <app> <grid {promise-data}='websitesPromise'> {{#each items}} <tr> <td width='40%'>{{name}}</td> <td width='70%'>{{url}}</td> </tr> {{/each}} </grid> <next-prev {paginate}='paginate'></next-prev> <page-count {page}='paginate.page' {count}='paginate.pageCount'></page-count> </app> </script> <script src="../../node_modules/steal/steal.js" main="@empty"></script> <script type='text/javascript'> steal("can/util", "can/component", "can/map/define", "can/util/fixture", "can/model", "can/view/stache",function (can) { var Website = can.Model.extend({ findAll: "/websites" }, {}); var websites = [{id:1,name:"CanJS",url:"http://canjs.us"},{id: 2,name:"jQuery++",url:"http://jquerypp.com"}, {id:3,name:"JavaScriptMVC",url:"http://javascriptmvc.com"},{id: 4,name:"Bitovi",url:"http://bitovi.com"}, {id:5,name:"FuncUnit",url:"http://funcunit.com"},{id: 6,name:"StealJS",url:"http://stealjs.com"}, {id:7,name:"jQuery",url:"http://jquery.com"},{id: 8,name:"Mootools",url:"http://mootools.com"}, {id:9,name:"Dojo",url:"http://dojo.com"},{id: 10,name:"YUI",url:"http://yui.com"}, {id:11,name:"DoneJS",url:"http://donejs.com"},{id: 12,name:"Mindjet Connect",url:"http://connect.mindjet.com"}, {id:13,name:"JSFiddle",url:"http://jsfiddle.net"},{id: 14,name:"Zepto",url:"http://zepto.com"}, {id:15,name:"Spill",url:"http://spill.com"},{id: 16,name:"Github",url:"http://github.com"}]; can.fixture("/websites", function (request) { var start = request.data.offset || 0, end = start + (request.data.limit || websites.length); return { count: websites.length, data: websites.slice(start, end) }; }); var Paginate = can.Map.extend({ define: { count: { value: Infinity, count: function(newCount) { return newCount < 0 ? 0 : newCount; } }, offset: { value: 0, set: function(newOffset) { return newOffset < 0 ? 0 : Math.min(newOffset, !isNaN(this.count - 1) ? this.count - 1 : Infinity); } }, limit: { value: 5 }, page: { get: function() { return Math.floor(this.attr('offset') / this.attr('limit')) + 1; }, set: function(newVal) { this.attr('offset', (parseInt(newVal, 10) - 1) * this.attr('limit')); } }, pageCount: { get: function() { return this.attr('count') ? Math.ceil(this.attr('count') / this.attr('limit')) : null; } } }, next: function() { this.attr('offset', this.offset + this.limit); }, prev: function() { this.attr('offset', this.offset - this.limit); }, canNext: function() { return this.attr('offset') < this.attr('count') - this.attr('limit'); }, canPrev: function() { return this.attr('offset') > 0; } }); can.Component.extend({ tag: "app", viewModel: { define: { paginate: { value: function() { return new Paginate({ limit: 5 }); } }, websitesPromise: { get: function() { var params = { limit: this.attr('paginate.limit'), offset: this.attr('paginate.offset') }, websitesPromise = Website.findAll(params), self = this; websitesPromise.then(function(websites) { self.attr('paginate.count', websites.count); }); return websitesPromise; } } } } }); can.Component.extend({ tag: "grid", template: can.stache("<table><tbody {{#waiting}}class='waiting'{{/waiting}}><content></content></tbody></table>"), viewModel: { define: { items: { get: function(lastSet, resolve) { var promise = this.attr("promiseData"); promise.then(resolve); } }, waiting: { get: function(lastSet, resolve) { var promise = this.attr("promiseData"); if (promise.state() === "pending") { promise.then(function() { resolve(false); }); return true; } else { return false; } } } } } }); can.Component.extend({ tag: "next-prev", template: can.stache('<a href="javascript://"' + 'class="prev {{#paginate.canPrev}}enabled{{/paginate.canPrev}}" ($click)="paginate.prev()">Prev</a>' + '<a href="javascript://"' + 'class="next {{#paginate.canNext}}enabled{{/paginate.canNext}}" ($click)="paginate.next()">Next</a>') }); can.Component.extend({ tag: "page-count", template: can.stache('Page <span>{{page}}</span> of <span>{{count}}</span>.') }); $("#out").html(can.view("app-stache", {})) }); </script> </body>