Fun with ZeptoJS, simply-deferred & AJAX
HTML
<link rel="stylesheet" href="http://twitter.github.io/bootstrap/assets/css/bootstrap.css">
<link rel="stylesheet" href="http://twitter.github.io/bootstrap/assets/css/bootstrap-responsive.css">
<script src="http://cubiq.org/dropbox/iscroll4/src/iscroll.js"></script>
<script src="http://zeptojs.com/zepto.js"></script>
<script src="https://raw.github.com/sudhirj/simply-deferred/master/deferred.min.js"></script>
<script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.rc.1.min.js"></script>
<script src="http://static.mcclatchyinteractive.com/static/migap/fx.js"></script>
<script src="http://static.mcclatchyinteractive.com/static/migap/fx_methods.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<script type="text/javascript">
if(!window.jQuery)
{
// https://github.com/madrobby/zepto/commit/1d5daef9f8abd9b92340c135bfbb11a7ce1a83a6
Zepto.browser = {webkit: true};
window.jQuery = Zepto;
Deferred.installInto(Zepto);
console.log('window.jQuery = Zepto');
}
</script>
<div id="header"><h1>My Zepto Experiment</h1></div>
<div id="iscrollWrapper">
<div id="iscrollScroller">
<div id="scrolledContent" >
</div>
</div><!-- /#scroller -->
</div><!-- #/wrapper -->
<div id="footer"><h2>Footer</h2></div>
<!-- start: section list template -->
<span id="section-list-template-container" style="display:none;">
<script type="text/x-handlebars" id="section-list-template">
{{!-- treat 1st image differently --}}
{{#listRange this offset="0" limit="1"}}
<div id="row0" class="row-fluid story-0">
<div class="span6 col1">
<figure>
{{#ifArrayIsEmpty images this}}
<img...
CSS
html {
position: relative;
min-height: 100%;
}
body {
margin: 0 0 100px; /* bottom = footer height */
}
#header, #footer, #iscrollWrapper {
/* iscroll required */
position:absolute; z-index:2;
width:100%;
padding:0;
}
#header {
/* iscroll required */
top:0; left:0;
height:65px;
line-height:65px;
}
#footer {
/* iscroll required */
bottom:0; left:0;
height:70px;
}
#iscrollWrapper {
/* iscroll required */
z-index:1;
top:65px; bottom:70px; left:0;
overflow:auto; /* made hidden when iScroll kicks in */
}
JavaScript
Handlebars.registerHelper('on_even', function(n, block) {
if((n % 2) == 0) {
return block.fn($.extend({}, {index: n}));
}
});
Handlebars.registerHelper('on_odd', function(n, block) {
if((n % 2)) {
return block.fn($.extend({}, {index: n}));
}
});
Handlebars.registerHelper('add', function(value, addition) {
return value + addition;
});
Handlebars.registerHelper('subtract', function(value, substraction) {
return substraction - value;
});
Handlebars.registerHelper('encode', function (str) {
return encodeURIComponent(str);
});
Handlebars.registerHelper('modulo', function(n, m, block) {
if((n % m) == 0) {
return block.fn($.extend({}, {number: n}));
}
else {
return block.inverse($.extend({}, {number: n}));
}
});
Handlebars.registerHelper('htmlText', function(text) {
var y = document.createElement('textarea');
y.innerHTML = text;
return new Handlebars.SafeString(y.value);
});
Handlebars.registerHelper('cleanarg', function (input) {
var y = document.createElement('textarea');
y.innerHTML = input;
return y.value.replace(/'/g, "`").replace(/"/g, "``");
});
Handlebars.registerHelper('decodeEntities', function (input) {
var y = document.createElement('textarea');
y.innerHTML = input;
return y.value;
});
Handlebars.registerHelper('placeholderImage', function (caption) {
caption = (typeof caption === 'string') ? encodeURIComponent(caption.replace(/["|']/g, "%27")) : "%20";
return 'http://placehold.it/400x300/' + (Math.random()).toString(16).slice(2, 8) + '/e8e8e8.png&text=' + caption;
});
// moment(Date("2011-07-18T15:50:52")).format("MMMM YYYY") {{dateFormat creation_date format="MMMM YYYY"}}
Handlebars.registerHelper('dateFormat', function(context, block) {
if (window.moment) {
var f = block.hash.format || "MMM Do, YYYY";
return moment(Date(context)).format(f);
}else{
return context; // moment plugin not available. return data as is.
...