// David Kaneda, jQuery jQTouch extensions
(function($) {
var currentPage = null;
var currentDialog = null;
var currentHash = location.hash;
var hashPrefix = "#";
var currentWidth = 0;
var pageHistory = [];
var pageHistoryInfo = [];
var newPageCount = 0;
var checkTimer;
$.fn.jQTouch = function(options)
{
var defaults = {
fullScreen: true,
slideInSelector: 'ul li a',
backSelector: '.back',
flipSelector: '.flip',
slideUpSelector: '.slideup',
statusBar: 'default', // other options: black-translucent, black
icon: null,
iconIsGlossy: false,
fixedViewport: true
};
var settings = $.extend({}, defaults, options);
var head = $('head');
if (settings.backSelector)
{
$(settings.backSelector).live('click',function(){
history.back();
return false;
});
}
if (settings.icon)
{
var precomposed = (settings.iconIsGlossy) ? '' : '-precomposed';
head.append('');
}
if (settings.fixedViewport)
{
head.append('');
}
if (settings.fullScreen)
{
head.append('');
if (settings.statusBar)
{
head.append('');
}
}
var liveSelectors = [];
if (settings.slideInSelector) liveSelectors.push(settings.slideInSelector);
if (settings.flipSelector) liveSelectors.push(settings.flipSelector);
if (settings.slideUpSelector) liveSelectors.push(settings.slideUpSelector);
// Selector settings
if (liveSelectors.length > 0)
{
$(liveSelectors.join(', ')).live('click',function(){
var jelem = $(this);
var hash = jelem.attr('hash');
var transition = 'slideInOut';
if ($(this).is(settings.flipSelector)) transition = 'flip';
if ($(this).is(settings.slideUpSelector)) transition = 'slideUp';
if ( hash && hash != '#')
{
jelem.attr('selected', 'true');
$.fn.jQTouch.showPage($(hash), transition);
setTimeout($.fn.unselect, 350, $(this));
}
else if ( jelem.attr('href') != '#' )
{
jelem.attr('selected', 'progress');
try {
$.fn.jQTouch.showPageByHref($(this).attr('href'), null, null, null, transition, function(){ setTimeout($.fn.unselect, 350, jelem);
});
}
catch(err)
{
console.log(err);
}
}
return false;
});
// Initialize
$(function(){
var page = $.fn.jQTouch.getSelectedPage();
if (page) $.fn.jQTouch.showPage(page);
// setTimeout($.fn.jQTouch.checkOrientandLocation, 0);
$.fn.jQTouch.startCheck();
})
}
}
$.fn.ianimate = function(css, speed, fn) {
// TODO: Autoconvert top,left to translate();
// ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier(x1, y1, x2, y2)
if(speed === 0) { // differentiate 0 from null
this.css(css)
window.setTimeout(fn, 0)
} else {
var s = []
for(var i in css)
s.push(i)
this.css({ webkitTransitionProperty: s.join(", "), webkitTransitionDuration: speed + "ms", webkitTransitionTimingFunction: 'ease-in-out' });
window.setTimeout(function(x,y) {
x.css(y)
},0, this, css)
window.setTimeout(fn, speed)
}
return this;
}
$.fn.jQTouch.checkOrientAndLocation = function()
{
if (window.innerWidth != currentWidth)
{
currentWidth = window.innerWidth;
currentHeight = window.innerHeight;
var orient = currentWidth < currentHeight ? "profile" : "landscape";
document.body.setAttribute("orient", orient);
setTimeout(scrollTo, 100, 0, 1);
}
if (location.hash != currentHash)
$.fn.jQTouch.showPageById(location.hash);
}
$.fn.jQTouch.getSelectedPage = function()
{
return $('body > *[selected!=false]').slice(0,1);
}
$.fn.jQTouch.showPage = function( page, transition, backwards )
{
if (page)
{
if (currentDialog)
{
currentDialog.attr('selected', null);
currentDialog = null;
}
var fromPage = currentPage;
currentPage = page;
if (fromPage)
$.fn.jQTouch.animatePages(fromPage, page, transition, backwards);
else
$.fn.jQTouch.updatePage(page, fromPage, transition);
}
}
$.fn.jQTouch.showPageById = function( hash )
{
var page = $(hash);
if (page)
{
var transition;
var currentIndex = pageHistory.indexOf(currentHash);
var index = pageHistory.indexOf(hash);
var backwards = index != -1;
if (backwards) {
transition = pageHistoryInfo[currentIndex].transition;
pageHistory.splice(index, pageHistory.length);
pageHistoryInfo.splice(index, pageHistoryInfo.length);
}
$.fn.jQTouch.showPage(page, transition, backwards);
}
}
$.fn.jQTouch.insertPages = function( nodes, transition )
{
var targetPage;
nodes.each(function(index, node){
if (!$(this).attr('id'))
$(this).attr('id', (++newPageCount));
$(this).appendTo($('body'));
if ( $(this).attr('selected') == 'true' || ( !targetPage && !$(this).hasClass('btn')) )
targetPage = $(this);
});
if (targetPage) $.fn.jQTouch.showPage(targetPage, transition);
}
$.fn.jQTouch.showPageByHref = function(href, data, method, replace, transition, cb)
{
$.ajax({
url: href,
data: data,
type: method || "GET",
success: function (data, textStatus)
{
$('a[selected="progress"]').attr('selected', 'true');
if (replace) $(replace).replaceWith(data);
else
{
$.fn.jQTouch.insertPages( $(data) );
}
if (cb) cb(true);
},
error: function (data)
{
if (cb) cb(false);
}
});
}
$.fn.jQTouch.submitForm = function()
{
$.fn.jQTouch.showPageByHref($(this).attr('action') || "POST", $(this).serialize(), $(this).attr('method'));
return false;
}
$.fn.showForm = function ()
{
return this.each(function(){
$(this).submit($.fn.jQTouch.submitForm);
});
}
$.fn.jQTouch.animatePages = function(fromPage, toPage, transition, backwards)
{
clearInterval(checkTimer);
if (transition == 'flip'){
toPage.flip({backwards: backwards});
fromPage.flip({backwards: backwards});
}
else if (transition == 'slideUp')
{
if (backwards)
{
toPage.attr('selected', true);
fromPage.slideUpDown({backwards: backwards});
}
else
{
toPage.slideUpDown({backwards: backwards});
}
}
else
{
toPage.slideInOut({backwards: backwards});
fromPage.slideInOut({backwards: backwards});
}
setTimeout(function(){
fromPage.attr('selected', 'false');
$.fn.jQTouch.updatePage(toPage, fromPage, transition);
$.fn.jQTouch.startCheck();
}, 500);
}
$.fn.jQTouch.startCheck = function()
{
checkTimer = setInterval($.fn.jQTouch.checkOrientAndLocation, 350);
}
$.fn.jQTouch.updatePage = function(page, fromPage, transition)
{
if (page)
{
if (!page.attr('id'))
page.attr('id', (++newPageCount));
location.replace(hashPrefix + page.attr('id'));
currentHash = location.hash;
pageHistory.push(currentHash);
pageHistoryInfo.push({page: page, transition: transition});
if (page.attr('localName') == "form" && !page.attr('target'))
{
page.showForm();
}
}
}
$.fn.unselect = function(obj)
{
obj.attr('selected', false);
}
$.preloadImages = function( imgs )
{
for (var i = imgs.length - 1; i >= 0; i--){
(new Image()).src = imgs[i];
};
}
$.fn.flip = function(options)
{
this.each(function(){
var defaults = {
direction : 'toggle',
backwards: false
};
var settings = $.extend({}, defaults, options);
var dir = ((settings.direction == 'toggle' && $(this).attr('selected') == 'true') || settings.direction == 'out') ? 1 : -1;
if (dir == -1) $(this).attr('selected', 'true');
$(this).parent().css({webkitPerspective: '2000'});
$(this).css({
'-webkit-backface-visibility': 'hidden',
'-webkit-transform': 'rotateY(' + ((dir == 1) ? '0' : (!settings.backwards ? '-' : '') + '180') + 'deg)'
}).ianimate({'-webkit-transform': 'rotateY(' + ((dir == 1) ? (settings.backwards ? '-' : '') + '180' : '0') + 'deg)'}, 350);
})
}
$.fn.slideInOut = function(options)
{
var defaults = {
direction : 'toggle',
backwards: false
};
var settings = $.extend({}, defaults, options);
this.each(function(){
var dir = ((settings.direction == 'toggle' && $(this).attr('selected') == 'true') || settings.direction == 'out') ? 1 : -1;
// Animate in
if (dir == -1){
$(this).attr('selected', 'true')
.css({'-webkit-transform': 'translateX(' + (settings.backwards ? -1 : 1) * currentWidth + 'px)'})
.ianimate({'-webkit-transform': 'translateX(0px)'}, 350)
.find('h1, .button')
.css('opacity', 0)
.ianimate({'opacity': 1}, 100);
}
// Animate out
else
{
$(this)
.ianimate(
{'-webkit-transform': 'translateX(' + ((settings.backwards ? 1 : -1) * dir * currentWidth) + 'px)'}, 350)
.find('h1, .button')
.ianimate( {'opacity': 0}, 100);
}
})
}
$.fn.slideUpDown = function(options)
{
var defaults = {
direction : 'toggle',
backwards: false
};
var settings = $.extend({}, defaults, options);
this.each(function(){
var dir = ((settings.direction == 'toggle' && $(this).attr('selected') == 'true') || settings.direction == 'out') ? 1 : -1;
// Animate in
if (dir == -1){
$(this).attr('selected', 'true')
.css({'-webkit-transform': 'translateY(' + (settings.backwards ? -1 : 1) * currentHeight + 'px)'})
.ianimate({'-webkit-transform': 'translateY(0px)'}, 350)
.find('h1, .button')
.css('opacity', 0)
.ianimate({'opacity': 1}, 100);
}
// Animate out
else
{
$(this)
.ianimate(
{'-webkit-transform': 'translateY(' + currentHeight + 'px)'}, 350)
.find('h1, .button')
.ianimate( {'opacity': 0}, 100);
}
})
}
})(jQuery);