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));
#!- }
});