UNPKG

can

Version:

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

294 lines (277 loc) 5.57 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"> <my-app></my-app> </div> <script src="../../node_modules/steal/steal.js" dev-bundle main="@empty"> import {DefineMap, DefineList, Component, fixture, realtimeRestModel} from "can"; const Website = DefineMap.extend({ id: "number", name: "string", url: "string" }); Website.List = DefineList.extend({ "#": Website, count: "number" }); realtimeRestModel({ Map: Website, List: Website.List, url: "/websites" }); const websiteStore = fixture.store([{ 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" }] ); fixture("/websites/{id}", websiteStore); fixture.delay = 2000; const Paginate = DefineMap.extend({ count: { default: Infinity }, offset: { default: 0, set: function(newOffset) { return newOffset < 0 ? 0 : Math.min(newOffset, !isNaN(this.count - 1) ? this.count - 1 : Infinity); } }, limit: { default: 5 }, page: { get: function() { return Math.floor(this.offset / this.limit) + 1; }, set: function(newVal) { this.offset = (parseInt(newVal, 10) - 1) * this.limit; } }, pageCount: { get: function() { return this.count ? Math.ceil(this.count / this.limit) : null; } }, get start(){ return this.offset; }, get end(){ return this.offset + this.limit - 1; }, next: function() { this.offset = this.offset + this.limit; }, prev: function() { this.offset = this.offset - this.limit; }, canNext: function() { return this.offset < this.count - this.limit; }, canPrev: function() { return this.offset > 0; } }); Component.extend({ tag: "my-grid", view: `<table> <tbody {{# if(this.waiting) }}class='waiting'{{/ if }}> <content></content> </tbody> </table>`, ViewModel: { promiseData: "any", items: { get: function(lastSet, resolve) { this.promiseData.then(resolve); } }, waiting: { get: function(lastSet, resolve) { const promise = this.promiseData; promise.then(function() { resolve(false); }); return true; } } }, leakScope: true }); Component.extend({ tag: "next-prev", view: `<a href="javascript://" class="prev {{# this.paginate.canPrev() }}enabled{{/ }}" on:click="paginate.prev()">Prev</a> <a href="javascript://" class="next {{# this.paginate.canNext() }}enabled{{/ }}" on:click="paginate.next()">Next</a>` }); Component.extend({ tag: "page-count", view: `Page <span>{{ this.page }}</span> of <span>{{ this.count }}</span>.` }); Component.extend({ tag: "my-app", view: ` <my-grid promiseData:from='websitesPromise'> {{# for( item of this.items) }} <tr> <td width='40%'>{{ item.name }}</td> <td width='70%'>{{ item.url }}</td> </tr> {{/ for }} </my-grid> <next-prev paginate:from='this.paginate'></next-prev> <page-count page:from='this.paginate.page' count:from='this.paginate.pageCount'></page-count>`, ViewModel: { paginate: { default() { return new Paginate({ limit: 5 }); } }, websitesCount: { get(lastValue, setValue) { this.websitesPromise.then(function(websites) { setValue(websites.count); }); } }, get websitesPromise() { return Website.getList({ page: { start: this.paginate.start, end: this.paginate.end } }); }, connectedCallback() { this.listenTo('websitesCount', function(event, count) { this.paginate.count = count; }); return this.stopListening.bind(this); } } }); </script> </body>