Skip to content

Instantly share code, notes, and snippets.

@ciscou
Last active February 2, 2017 14:10
Show Gist options
  • Save ciscou/300d2375a4851b4946cfd70bd52afa8f to your computer and use it in GitHub Desktop.
Save ciscou/300d2375a4851b4946cfd70bd52afa8f to your computer and use it in GitHub Desktop.
Example of a minimal Backbone Marionette + Framework7 application
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.radio/2.0.0/backbone.radio.js"></script>
<script src="http://marionettejs.com/downloads/backbone.marionette.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.5.4/jquery.timeago.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/framework7/1.5.2/css/framework7.material.css"></link>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/framework7/1.5.2/css/framework7.material.colors.css"></link>
<style>
.fullscreen {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
</style>
</head>
<body>
<script id="page-wrapper-template" type="text/template">
<div></div>
</script>
<script id="main-view-template" type="text/template">
<div class="navbar">
<div class="navbar-inner">
<div class="center">Recent changes</div>
</div>
</div>
<div class="toolbar toolbar-bottom">
<div class="toolbar-inner">
<a href="#" class="link" id="refresh" style="flex-grow: 1">Refresh</a>
</div>
</div>
<div class="page-content">
<div class="content-block-title">
Recent changes
</div>
<div class="content-block">
<div class="list-block media-list"></div>
</div>
</div>
</script>
<script id="secondary-view-template" type="text/template">
<div class="navbar">
<div class="navbar-inner">
<div class="left"><a href="#" class="back link icon-only"><i class="icon icon-back"></i></a></div>
<div class="center"><%- author.key %></div>
</div>
</div>
<div class="page-content">
<div class="content-block-title">
<time class="timeago" datetime="<%- timestamp %>Z"><%- timestamp %></time>
</div>
<div class="content-block">
<p><%- comment %></p>
</div>
</div>
</script>
<script id="recent-change-empty-template" type="text/template">
<a href="#" class="item-content item-link">
<div class="item-media">
</div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">
Loading...
</div>
</div>
<div class="item-subtitle">
</div>
<div class="item-text">
</div>
</div>
</a>
</script>
<script id="recent-change-template" type="text/template">
<a href="#" class="item-content item-link">
<div class="item-media">
<img width="64" src="http://files.softicons.com/download/game-icons/super-mario-icons-by-sandro-pereira/png/256/Goomba.png"></img>
</div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">
<%- author.key %>
</div>
</div>
<div class="item-subtitle">
<time class="timeago" datetime="<%- timestamp %>Z"><%- timestamp %></time>
</div>
<div class="item-text">
<%- comment %>
</div>
</div>
</a>
</script>
<script id="indicator-template" type="text/template">
<div class="preloader-indicator-overlay"></div>
<div class="preloader-indicator-modal"><span class="preloader preloader-white"><span class="preloader-inner"><span class="preloader-inner-gap"></span><span class="preloader-inner-left"><span class="preloader-inner-half-circle"></span></span><span class="preloader-inner-right"><span class="preloader-inner-half-circle"></span></span></span></span></div>
</script>
<script id="application-layout-template" type="text/template">
<div class="views">
<div class="view view-main">
</div>
</div>
<div id="overlay-region">
</div>
</script>
<div id="main-region" class="fullscreen">
</div>
<script type="text/javascript">
var App = Backbone.Marionette.Application.extend({
models: {},
collections: {},
views: {},
region: '#main-region',
showIndicator: function() {
app.layout.showIndicator();
},
hideIndicator: function() {
app.layout.hideIndicator();
}
});
var app = new App();
app.models.Change = Backbone.Model.extend({});
app.collections.RecentChanges = Backbone.Collection.extend({
model: app.models.Change,
url: "http://openlibrary.org/recentchanges.json"
});
app.views.ApplicationLayout = Backbone.Marionette.View.extend({
template: '#application-layout-template',
className: 'fullscreen',
regions: {
mainView: '.view-main',
overlay: '#overlay-region'
},
showIndicator: function() {
this.showChildView('overlay', new app.views.Indicator());
},
hideIndicator: function() {
this.getRegion('overlay').empty();
},
onRender: function() {
this.showChildView('mainView', this.getOption('mainView'));
}
});
app.views.Indicator = Backbone.Marionette.View.extend({
template: '#indicator-template'
});
app.views.PageWrapper = Backbone.Marionette.View.extend({
template: '#page-wrapper-template',
regions: {
page: {
el: 'div',
replaceElement: true
}
},
onRender: function() {
var view = this.model.get('view');
this.showChildView('page', view);
}
});
app.views.Pages = Backbone.Marionette.CollectionView.extend({
className: 'pages',
childView: app.views.PageWrapper,
push: function(model) {
this.collection.push(model);
var $a = this._getPageAt(-2);
var $b = this._getPageAt(-1);
if($a) {
$a.one('animationend', function() {
$a.removeClass('page-from-center-to-left').addClass('page-on-left');
});
$a.removeClass('page-on-center').addClass('page-from-center-to-left');
$b.one('animationend', function() {
$b.removeClass('page-from-right-to-center').addClass('page-on-center');
});
$b.removeClass('page-on-right').addClass('page-from-right-to-center');
}
},
pop: function() {
var $a = this._getPageAt(-2);
var $b = this._getPageAt(-1);
var collection = this.collection;
$a.one('animationend', function() {
$a.removeClass('page-from-left-to-center').addClass('page-on-center');
});
$a.removeClass('page-on-left').addClass('page-from-left-to-center');
$b.one('animationend', function() {
$b.removeClass('page-from-center-to-right').addClass('page-on-right');
collection.pop();
});
$b.removeClass('page-on-center').addClass('page-from-center-to-right');
},
_getPageAt: function(idx) {
if(idx < 0) {
idx += this.children.length;
}
view = this.children.findByIndex(idx);
if(view) {
return view.$el.find('.page');
}
}
});
app.views.RecentChange = Backbone.Marionette.View.extend({
template: "#recent-change-template",
tagName: "li",
ui: {
timeago: 'time.timeago'
},
triggers: {
click: 'clicked'
},
onDomRefresh: function() {
this.getUI('timeago').timeago();
}
});
app.views.RecentChangeEmpty = Backbone.Marionette.View.extend({
template: "#recent-change-empty-template",
tagName: "li"
});
app.views.RecentChanges = Backbone.Marionette.CollectionView.extend({
tagName: "ul",
className: "list-block media-list",
childView: app.views.RecentChange,
emptyView: app.views.RecentChangeEmpty
});
app.views.MainPage = Backbone.Marionette.View.extend({
template: "#main-view-template",
className: 'page navbar-fixed toolbar-fixed',
data: {
page: "index"
},
ui: {
refresh: 'a#refresh'
},
triggers: {
'click @ui.refresh': 'refresh'
},
regions: {
list: '.media-list'
},
collectionEvents: {
request: 'onCollectionRequest',
sync: 'onCollectionSync'
},
onRender: function() {
this.showChildView(
'list',
new app.views.RecentChanges({
collection: this.collection
})
);
},
onCollectionRequest: function() {
app.showIndicator();
this.getUI('refresh').addClass('disabled');
},
onCollectionSync: function() {
app.hideIndicator();
this.getUI('refresh').removeClass('disabled');
}
});
app.views.SecondaryPage = Backbone.Marionette.View.extend({
template: "#secondary-view-template",
className: 'page navbar-fixed',
data: {
page: "secondary"
},
ui: {
back: 'a.back',
timeago: 'time.timeago'
},
triggers: {
'click @ui.back': 'back'
},
onDomRefresh: function() {
this.getUI('timeago').timeago();
}
});
var recentChanges = new app.collections.RecentChanges();
var mainPage = new app.views.MainPage({
collection: recentChanges
});
app.pages = new app.views.Pages({
collection: new Backbone.Collection()
});
mainPage.on('refresh', function() {
recentChanges.fetch({data: {limit: 10}});
});
mainPage.on('childview:clicked', function(v) {
var secondaryView = new app.views.SecondaryPage({model: v.model});
app.pages.push({view: secondaryView});
secondaryView.on('back', function() {
app.pages.pop();
});
});
app.on('start', function() {
app.layout = new app.views.ApplicationLayout({mainView: app.pages});
app.showView(app.layout);
app.pages.push({view: mainPage});
recentChanges.fetch({data: {limit: 10}});
});
$(function() {
app.start();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment