Pilot 1.5 / Пример одностраничного приложения (SAP)
var Ivan = new Pilot; #!+ // Реагирует на любой url: ^/(.+)/?$ #!- Ivan.route("/:page", function (evt, req) { }); #!+ // ^/(.+)/?.*?$ #!- Ivan.route("/:page*", function (evt, req) { }); #!+ // ^/(.+)/?.+$ #!- Ivan.route("/:page+", function (evt, req) { });
Ivan.route("/:page/:details?/", function (evt, req) { }); // Реагирует на: // /foo/ // /foo/bar/ // Не реагирует // / // /foo/bar/baz
"/search/" // строгое совпадание "/user/:id(\\d+)" // только цифры "/search/(result/:page/)?" // группировка // Сложный пример: "/:mode(show|link)?/:storage(home|links|shared)"
var Moses = new Pilot; #! Moses.route("/deserts/", ctrl); // используется GET #! Moses.route("/desert/:name/:coords", ctrl); #!+ function ctrl(evt, req) { #! var name = req.params.name || req.query.name; #! var coords = req.params.coords || req.query.coords; #!- }
// Получить зачение по имени параметра // в независимости от его нахождения Pilot.fn.get = function (name) { return this.params[name] || this.query[name]; };
var Moses = new Pilot; Moses.route("/deserts/", ctrl); // используется GET Moses.route("/desert/:name/:coords", ctrl); function ctrl(evt, req) { #! var name = req.get("name"); #! var coords = req.get("coords"); }
router.route("path/:to", function (evt, req) { console.log(evt.type + ": " + req.path"); }); #! router.nav("/path/"); // (ничего) #! router.nav("/path/foo/"); // routestart: /path/foo/ #! router.nav("/path/bar/"); // routechange: /path/bar/ #! router.nav("/path/baz/"); // routechange: /path/baz/ #! router.nav("/path/"); // (ничего)
router.route("path/:to", { #! onRouteStart: function (evt, req) { }, #!+ onRoute: function (evt, req) { // routeStart + routeChange #!- }, #! onRouteEnd: function (evt, req) { } });
<div id="app"> #!+ <!-- App screen --> <div style="z-index: 1; display: none;"> #!+ <header class="bar bar-nav"> <h1 class="js-title title"></h1> #!- </header> #! <div class="js-content content"></div> </div> #!- <!-- /App screen --> </div> #!+ <!-- vendors: --> <script src="http://code.jquery.com/jquery-2.1.0.min.js"></script> #!- <script src="../../Pilot.js"></script> #!+ <!-- app:code --> #!- <script src="app.js"></script>
(function ($, Pilot) { /* app code */ })(jQuery, Pilot);
(function ($, Pilot) { var App = Pilot.create({ #! el: "#app", // корневой элемент #!+ "/": { // ключь — описание маршура id: "home", // id маршрута #!+ loadData: function (req) { return $.getJSON("./data/galleries.json"); // взял с WiKi #!- }, #!+ init: function () { #! var galleries = this.getLoadedData(); #! this.$(".js-title").text("List of art movements"); #!+ this.$(".js-list").append(galleries.map(function (name) { var url = this.getUrl("gallery", { name: name }); return "<li class='table-view-cell'><a>"+name+"</a></li>"; #!- }, this)); #!- } #!- } }); })(jQuery, Pilot);
<div id="app"> <!-- Home --> <div data-view-id="home" style="z-index: 1; display: none;"> <header class="bar bar-nav"> <h1 class="js-title title"></h1> </header> <div class="js-content content"> <ul class="js-list table-view"></ul> </div> </div> <!-- /Home --> </div>
// Gallery screen "/gallery/:name/": { id: "gallery", onRoute: function (evt, req) { this.$(".js-title").text(req.params.name); } }
"/": { // Home screen id: "home", - loadData: function (req) { + loadDataOnce: function (req) { return $.getJSON("./data/galleries.json"); }, init: function () { /* ... */ } }
"/gallery/:name/:page?": { id: "gallery", #!+ loadData: function (req) { return $.flickr("flickr.photos.search", { #! tags: req.params.name, #! page: req.params.page|0, #! per_page: 50 }).then(function (result) { #!- return result.photos; }); #!- }, onRoute: function (evt, req) { /* .. */ } }
"/gallery/:name/:page?": { id: "gallery", loadData: function (req) { return $.flickr({ /*...*/ }); }, onRoute: function (evt, req) { #!+ var name = req.params.name, photos = this.getLoadedData() #!- ; #! this.$(".js-title").text(name); #!+ this.$(".js-photos").html(photos.photo.map(function (photo) { #! var url = this.getUrl("artwork", { name: name, id: photo.id }); #! return "<a href='" + url + "'><img src='" + photo.url_q + "' /></a>"; #!- }, this)); } }
App = Pilot.create({ el: "#app", subviews: { #!+ loading: { // id подвида и [data-subview-id="loading"] #! loadData: function () { this.$el.show(); }, #! onRoute: function () { this.$el.hide(); } #!- } }, /* Home, Gallery, etc. */ });
Pilot.View.toggleEffect("transition", function ($el, state) { #!+ $el.css({ display: "", opacity: +!state, transition: "", transform: "translate3d(" + (!state ? "0" : "100%") + ",0,0)" }) #! .delay(1) #!+ .queue(function (){ $el.css({ opacity: +state, transition: "all .2s ease-in-out", transform: "translate3d(" + (state ? "0" : "100%") + ",0,0)" }) .dequeue() ; #!- }) #!- ; });
App = Pilot.create({ el: "#app", subviews: {}, "/": { id: "home", #! toggleEffect: "fadeIn" }, "/gallery/:name/:page?": { id: "gallery", #! toggleEffect: "transition" }, "/artwork/:id/": { id: "artwork", #! toggleEffect: "transition" } });
Попробовав демо, можно быстро заметить, что при переходе с Gallery на Artwork, один экран уезжает, другой приезжает, что выглядит не очень красиво.
Чтобы избавиться от такого эффекта, можно объеденить Gallery и Artwork в группу.
<!-- GalleryGroup --> <div data-view-id="gallery-group" style="z-index: 2; display: none;"> #!+ <!-- Gallery --> <div data-view-id="gallery" style="z-index: 2; display: none;"> <!--...--> </div> #!- <!-- /Gallery --> #!+ <!-- Artwork --> <div data-view-id="artwork" style="z-index: 3; display: none;"> <!--...--> </div> #!- <!-- /Artwork --> </div> <!-- /GalleryGroup -->
App = Pilot.create({ /* el, subview, home */ #!+ "/gallery/": { // Группа #! id: "gallery-group", // [data-view-id="gallery-group"] #! toggleEffect: "transition", #!+ "/:name/:page?": { // Gallery screen id: "gallery", toggleEffect: "show", // просто показать #!+ paramsRules: { // валидация параметров #! name: function (val) { return val != "artwork"; } #!- } #!- }, #!+ "/artwork/:id": { // Artwork screen id: "artwork", toggleEffect: "transition" #!- } #!- } });
var DefaultView = Pilot.View.extend({ #!+ $$: function (name) { return this.$(".js-" + name); #!- }, #!+ setTitle: function (val) { this.$$("title").text(val); #!- }, #!+ setBackUrl: function (url) { this.$$("back").prop('href', url); #!- }, #!+ setHtml: function (val) { this.$$("content").html( val ); #!- }, });
var HomeView = DefaultView.extend({ #!+ loadDataOnce: function (req) { return $.getJSON("./data/galleries.json"); #!- }, #!+ init: function () { var galleries = this.getLoadedData(); #! this.setTitle("List of art movements"); #!+ this.setHtml("list", galleries.map(function (name) { #!+ var url = this.getUrl('gallery', { name: name }); #!- return "<li class='table-view-cell'><a href='" + url + "'>" + name + "</a></li>"; #!- }, this)); #!- } });