[2] | 1 | // David Kaneda, jQuery jQTouch extensions |
---|
| 2 | |
---|
| 3 | (function($) { |
---|
| 4 | |
---|
| 5 | var currentPage = null; |
---|
| 6 | var currentDialog = null; |
---|
| 7 | var currentHash = location.hash; |
---|
| 8 | var hashPrefix = "#"; |
---|
| 9 | var currentWidth = 0; |
---|
| 10 | var pageHistory = []; |
---|
| 11 | var pageHistoryInfo = []; |
---|
| 12 | var newPageCount = 0; |
---|
| 13 | var checkTimer; |
---|
| 14 | |
---|
| 15 | $.fn.jQTouch = function(options) |
---|
| 16 | { |
---|
| 17 | var defaults = { |
---|
| 18 | fullScreen: true, |
---|
| 19 | slideInSelector: 'ul li a', |
---|
| 20 | backSelector: '.back', |
---|
| 21 | flipSelector: '.flip', |
---|
| 22 | slideUpSelector: '.slideup', |
---|
| 23 | statusBar: 'default', // other options: black-translucent, black |
---|
| 24 | icon: null, |
---|
| 25 | iconIsGlossy: false, |
---|
| 26 | fixedViewport: true |
---|
| 27 | }; |
---|
| 28 | |
---|
| 29 | var settings = $.extend({}, defaults, options); |
---|
| 30 | var head = $('head'); |
---|
| 31 | |
---|
| 32 | if (settings.backSelector) |
---|
| 33 | { |
---|
| 34 | $(settings.backSelector).live('click',function(){ |
---|
| 35 | history.back(); |
---|
| 36 | return false; |
---|
| 37 | }); |
---|
| 38 | } |
---|
| 39 | |
---|
| 40 | if (settings.icon) |
---|
| 41 | { |
---|
| 42 | var precomposed = (settings.iconIsGlossy) ? '' : '-precomposed'; |
---|
| 43 | head.append('<link rel="apple-touch-icon' + precomposed + '" href="' + settings.icon + '" />'); |
---|
| 44 | } |
---|
| 45 | |
---|
| 46 | if (settings.fixedViewport) |
---|
| 47 | { |
---|
| 48 | head.append('<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;"/>'); |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | if (settings.fullScreen) |
---|
| 52 | { |
---|
| 53 | head.append('<meta name="apple-mobile-web-app-capable" content="yes" />'); |
---|
| 54 | |
---|
| 55 | if (settings.statusBar) |
---|
| 56 | { |
---|
| 57 | head.append('<meta name="apple-mobile-web-app-status-bar-style" content="' + settings.statusBar + '" />'); |
---|
| 58 | } |
---|
| 59 | } |
---|
| 60 | |
---|
| 61 | var liveSelectors = []; |
---|
| 62 | |
---|
| 63 | if (settings.slideInSelector) liveSelectors.push(settings.slideInSelector); |
---|
| 64 | if (settings.flipSelector) liveSelectors.push(settings.flipSelector); |
---|
| 65 | if (settings.slideUpSelector) liveSelectors.push(settings.slideUpSelector); |
---|
| 66 | |
---|
| 67 | // Selector settings |
---|
| 68 | if (liveSelectors.length > 0) |
---|
| 69 | { |
---|
| 70 | $(liveSelectors.join(', ')).live('click',function(){ |
---|
| 71 | |
---|
| 72 | var jelem = $(this); |
---|
| 73 | var hash = jelem.attr('hash'); |
---|
| 74 | var transition = 'slideInOut'; |
---|
| 75 | |
---|
| 76 | if ($(this).is(settings.flipSelector)) transition = 'flip'; |
---|
| 77 | if ($(this).is(settings.slideUpSelector)) transition = 'slideUp'; |
---|
| 78 | |
---|
| 79 | if ( hash && hash != '#') |
---|
| 80 | { |
---|
| 81 | jelem.attr('selected', 'true'); |
---|
| 82 | $.fn.jQTouch.showPage($(hash), transition); |
---|
| 83 | setTimeout($.fn.unselect, 350, $(this)); |
---|
| 84 | } |
---|
| 85 | else if ( jelem.attr('href') != '#' ) |
---|
| 86 | { |
---|
| 87 | jelem.attr('selected', 'progress'); |
---|
| 88 | |
---|
| 89 | try { |
---|
| 90 | $.fn.jQTouch.showPageByHref($(this).attr('href'), null, null, null, transition, function(){ setTimeout($.fn.unselect, 350, jelem); |
---|
| 91 | }); |
---|
| 92 | } |
---|
| 93 | catch(err) |
---|
| 94 | { |
---|
| 95 | console.log(err); |
---|
| 96 | } |
---|
| 97 | } |
---|
| 98 | return false; |
---|
| 99 | }); |
---|
| 100 | |
---|
| 101 | // Initialize |
---|
| 102 | |
---|
| 103 | $(function(){ |
---|
| 104 | var page = $.fn.jQTouch.getSelectedPage(); |
---|
| 105 | if (page) $.fn.jQTouch.showPage(page); |
---|
| 106 | |
---|
| 107 | // setTimeout($.fn.jQTouch.checkOrientandLocation, 0); |
---|
| 108 | $.fn.jQTouch.startCheck(); |
---|
| 109 | }) |
---|
| 110 | |
---|
| 111 | } |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | $.fn.ianimate = function(css, speed, fn) { |
---|
| 115 | |
---|
| 116 | // TODO: Autoconvert top,left to translate(); |
---|
| 117 | // ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier(x1, y1, x2, y2) |
---|
| 118 | |
---|
| 119 | if(speed === 0) { // differentiate 0 from null |
---|
| 120 | this.css(css) |
---|
| 121 | window.setTimeout(fn, 0) |
---|
| 122 | } else { |
---|
| 123 | var s = [] |
---|
| 124 | for(var i in css) |
---|
| 125 | s.push(i) |
---|
| 126 | this.css({ webkitTransitionProperty: s.join(", "), webkitTransitionDuration: speed + "ms", webkitTransitionTimingFunction: 'ease-in-out' }); |
---|
| 127 | |
---|
| 128 | window.setTimeout(function(x,y) { |
---|
| 129 | x.css(y) |
---|
| 130 | },0, this, css) |
---|
| 131 | window.setTimeout(fn, speed) |
---|
| 132 | } |
---|
| 133 | return this; |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | $.fn.jQTouch.checkOrientAndLocation = function() |
---|
| 137 | { |
---|
| 138 | if (window.innerWidth != currentWidth) |
---|
| 139 | { |
---|
| 140 | currentWidth = window.innerWidth; |
---|
| 141 | currentHeight = window.innerHeight; |
---|
| 142 | var orient = currentWidth < currentHeight ? "profile" : "landscape"; |
---|
| 143 | document.body.setAttribute("orient", orient); |
---|
| 144 | setTimeout(scrollTo, 100, 0, 1); |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | if (location.hash != currentHash) |
---|
| 148 | $.fn.jQTouch.showPageById(location.hash); |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | $.fn.jQTouch.getSelectedPage = function() |
---|
| 152 | { |
---|
| 153 | return $('body > *[selected!=false]').slice(0,1); |
---|
| 154 | } |
---|
| 155 | |
---|
| 156 | $.fn.jQTouch.showPage = function( page, transition, backwards ) |
---|
| 157 | { |
---|
| 158 | if (page) |
---|
| 159 | { |
---|
| 160 | if (currentDialog) |
---|
| 161 | { |
---|
| 162 | currentDialog.attr('selected', null); |
---|
| 163 | currentDialog = null; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | var fromPage = currentPage; |
---|
| 167 | currentPage = page; |
---|
| 168 | |
---|
| 169 | if (fromPage) |
---|
| 170 | $.fn.jQTouch.animatePages(fromPage, page, transition, backwards); |
---|
| 171 | else |
---|
| 172 | $.fn.jQTouch.updatePage(page, fromPage, transition); |
---|
| 173 | } |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | $.fn.jQTouch.showPageById = function( hash ) |
---|
| 177 | { |
---|
| 178 | var page = $(hash); |
---|
| 179 | |
---|
| 180 | if (page) |
---|
| 181 | { |
---|
| 182 | var transition; |
---|
| 183 | var currentIndex = pageHistory.indexOf(currentHash); |
---|
| 184 | var index = pageHistory.indexOf(hash); |
---|
| 185 | var backwards = index != -1; |
---|
| 186 | |
---|
| 187 | if (backwards) { |
---|
| 188 | transition = pageHistoryInfo[currentIndex].transition; |
---|
| 189 | |
---|
| 190 | pageHistory.splice(index, pageHistory.length); |
---|
| 191 | pageHistoryInfo.splice(index, pageHistoryInfo.length); |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | $.fn.jQTouch.showPage(page, transition, backwards); |
---|
| 195 | } |
---|
| 196 | } |
---|
| 197 | |
---|
| 198 | $.fn.jQTouch.insertPages = function( nodes, transition ) |
---|
| 199 | { |
---|
| 200 | var targetPage; |
---|
| 201 | |
---|
| 202 | nodes.each(function(index, node){ |
---|
| 203 | |
---|
| 204 | if (!$(this).attr('id')) |
---|
| 205 | $(this).attr('id', (++newPageCount)); |
---|
| 206 | |
---|
| 207 | $(this).appendTo($('body')); |
---|
| 208 | |
---|
| 209 | if ( $(this).attr('selected') == 'true' || ( !targetPage && !$(this).hasClass('btn')) ) |
---|
| 210 | targetPage = $(this); |
---|
| 211 | }); |
---|
| 212 | |
---|
| 213 | if (targetPage) $.fn.jQTouch.showPage(targetPage, transition); |
---|
| 214 | |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | $.fn.jQTouch.showPageByHref = function(href, data, method, replace, transition, cb) |
---|
| 218 | { |
---|
| 219 | $.ajax({ |
---|
| 220 | url: href, |
---|
| 221 | data: data, |
---|
| 222 | type: method || "GET", |
---|
| 223 | success: function (data, textStatus) |
---|
| 224 | { |
---|
| 225 | $('a[selected="progress"]').attr('selected', 'true'); |
---|
| 226 | |
---|
| 227 | if (replace) $(replace).replaceWith(data); |
---|
| 228 | else |
---|
| 229 | { |
---|
| 230 | $.fn.jQTouch.insertPages( $(data) ); |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | if (cb) cb(true); |
---|
| 234 | }, |
---|
| 235 | error: function (data) |
---|
| 236 | { |
---|
| 237 | if (cb) cb(false); |
---|
| 238 | } |
---|
| 239 | }); |
---|
| 240 | |
---|
| 241 | } |
---|
| 242 | |
---|
| 243 | $.fn.jQTouch.submitForm = function() |
---|
| 244 | { |
---|
| 245 | $.fn.jQTouch.showPageByHref($(this).attr('action') || "POST", $(this).serialize(), $(this).attr('method')); |
---|
| 246 | return false; |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | $.fn.showForm = function () |
---|
| 250 | { |
---|
| 251 | return this.each(function(){ |
---|
| 252 | $(this).submit($.fn.jQTouch.submitForm); |
---|
| 253 | }); |
---|
| 254 | } |
---|
| 255 | |
---|
| 256 | $.fn.jQTouch.animatePages = function(fromPage, toPage, transition, backwards) |
---|
| 257 | { |
---|
| 258 | clearInterval(checkTimer); |
---|
| 259 | |
---|
| 260 | if (transition == 'flip'){ |
---|
| 261 | toPage.flip({backwards: backwards}); |
---|
| 262 | fromPage.flip({backwards: backwards}); |
---|
| 263 | } |
---|
| 264 | else if (transition == 'slideUp') |
---|
| 265 | { |
---|
| 266 | if (backwards) |
---|
| 267 | { |
---|
| 268 | toPage.attr('selected', true); |
---|
| 269 | fromPage.slideUpDown({backwards: backwards}); |
---|
| 270 | } |
---|
| 271 | else |
---|
| 272 | { |
---|
| 273 | toPage.slideUpDown({backwards: backwards}); |
---|
| 274 | } |
---|
| 275 | |
---|
| 276 | } |
---|
| 277 | else |
---|
| 278 | { |
---|
| 279 | toPage.slideInOut({backwards: backwards}); |
---|
| 280 | fromPage.slideInOut({backwards: backwards}); |
---|
| 281 | } |
---|
| 282 | |
---|
| 283 | setTimeout(function(){ |
---|
| 284 | fromPage.attr('selected', 'false'); |
---|
| 285 | $.fn.jQTouch.updatePage(toPage, fromPage, transition); |
---|
| 286 | $.fn.jQTouch.startCheck(); |
---|
| 287 | }, 500); |
---|
| 288 | } |
---|
| 289 | |
---|
| 290 | $.fn.jQTouch.startCheck = function() |
---|
| 291 | { |
---|
| 292 | checkTimer = setInterval($.fn.jQTouch.checkOrientAndLocation, 350); |
---|
| 293 | } |
---|
| 294 | |
---|
| 295 | $.fn.jQTouch.updatePage = function(page, fromPage, transition) |
---|
| 296 | { |
---|
| 297 | if (page) |
---|
| 298 | { |
---|
| 299 | if (!page.attr('id')) |
---|
| 300 | page.attr('id', (++newPageCount)); |
---|
| 301 | |
---|
| 302 | location.replace(hashPrefix + page.attr('id')); |
---|
| 303 | currentHash = location.hash; |
---|
| 304 | |
---|
| 305 | pageHistory.push(currentHash); |
---|
| 306 | pageHistoryInfo.push({page: page, transition: transition}); |
---|
| 307 | |
---|
| 308 | if (page.attr('localName') == "form" && !page.attr('target')) |
---|
| 309 | { |
---|
| 310 | page.showForm(); |
---|
| 311 | } |
---|
| 312 | } |
---|
| 313 | } |
---|
| 314 | |
---|
| 315 | $.fn.unselect = function(obj) |
---|
| 316 | { |
---|
| 317 | obj.attr('selected', false); |
---|
| 318 | } |
---|
| 319 | |
---|
| 320 | $.preloadImages = function( imgs ) |
---|
| 321 | { |
---|
| 322 | for (var i = imgs.length - 1; i >= 0; i--){ |
---|
| 323 | (new Image()).src = imgs[i]; |
---|
| 324 | }; |
---|
| 325 | } |
---|
| 326 | |
---|
| 327 | $.fn.flip = function(options) |
---|
| 328 | { |
---|
| 329 | this.each(function(){ |
---|
| 330 | var defaults = { |
---|
| 331 | direction : 'toggle', |
---|
| 332 | backwards: false |
---|
| 333 | }; |
---|
| 334 | |
---|
| 335 | var settings = $.extend({}, defaults, options); |
---|
| 336 | |
---|
| 337 | var dir = ((settings.direction == 'toggle' && $(this).attr('selected') == 'true') || settings.direction == 'out') ? 1 : -1; |
---|
| 338 | |
---|
| 339 | if (dir == -1) $(this).attr('selected', 'true'); |
---|
| 340 | |
---|
| 341 | $(this).parent().css({webkitPerspective: '2000'}); |
---|
| 342 | |
---|
| 343 | $(this).css({ |
---|
| 344 | '-webkit-backface-visibility': 'hidden', |
---|
| 345 | '-webkit-transform': 'rotateY(' + ((dir == 1) ? '0' : (!settings.backwards ? '-' : '') + '180') + 'deg)' |
---|
| 346 | }).ianimate({'-webkit-transform': 'rotateY(' + ((dir == 1) ? (settings.backwards ? '-' : '') + '180' : '0') + 'deg)'}, 350); |
---|
| 347 | }) |
---|
| 348 | } |
---|
| 349 | |
---|
| 350 | $.fn.slideInOut = function(options) |
---|
| 351 | { |
---|
| 352 | var defaults = { |
---|
| 353 | direction : 'toggle', |
---|
| 354 | backwards: false |
---|
| 355 | }; |
---|
| 356 | |
---|
| 357 | var settings = $.extend({}, defaults, options); |
---|
| 358 | |
---|
| 359 | this.each(function(){ |
---|
| 360 | |
---|
| 361 | var dir = ((settings.direction == 'toggle' && $(this).attr('selected') == 'true') || settings.direction == 'out') ? 1 : -1; |
---|
| 362 | // Animate in |
---|
| 363 | if (dir == -1){ |
---|
| 364 | |
---|
| 365 | $(this).attr('selected', 'true') |
---|
| 366 | .css({'-webkit-transform': 'translateX(' + (settings.backwards ? -1 : 1) * currentWidth + 'px)'}) |
---|
| 367 | .ianimate({'-webkit-transform': 'translateX(0px)'}, 350) |
---|
| 368 | .find('h1, .button') |
---|
| 369 | .css('opacity', 0) |
---|
| 370 | .ianimate({'opacity': 1}, 100); |
---|
| 371 | } |
---|
| 372 | // Animate out |
---|
| 373 | else |
---|
| 374 | { |
---|
| 375 | $(this) |
---|
| 376 | .ianimate( |
---|
| 377 | {'-webkit-transform': 'translateX(' + ((settings.backwards ? 1 : -1) * dir * currentWidth) + 'px)'}, 350) |
---|
| 378 | .find('h1, .button') |
---|
| 379 | .ianimate( {'opacity': 0}, 100); |
---|
| 380 | } |
---|
| 381 | |
---|
| 382 | }) |
---|
| 383 | } |
---|
| 384 | |
---|
| 385 | $.fn.slideUpDown = function(options) |
---|
| 386 | { |
---|
| 387 | var defaults = { |
---|
| 388 | direction : 'toggle', |
---|
| 389 | backwards: false |
---|
| 390 | }; |
---|
| 391 | |
---|
| 392 | var settings = $.extend({}, defaults, options); |
---|
| 393 | |
---|
| 394 | this.each(function(){ |
---|
| 395 | |
---|
| 396 | var dir = ((settings.direction == 'toggle' && $(this).attr('selected') == 'true') || settings.direction == 'out') ? 1 : -1; |
---|
| 397 | // Animate in |
---|
| 398 | if (dir == -1){ |
---|
| 399 | |
---|
| 400 | $(this).attr('selected', 'true') |
---|
| 401 | .css({'-webkit-transform': 'translateY(' + (settings.backwards ? -1 : 1) * currentHeight + 'px)'}) |
---|
| 402 | .ianimate({'-webkit-transform': 'translateY(0px)'}, 350) |
---|
| 403 | .find('h1, .button') |
---|
| 404 | .css('opacity', 0) |
---|
| 405 | .ianimate({'opacity': 1}, 100); |
---|
| 406 | } |
---|
| 407 | // Animate out |
---|
| 408 | else |
---|
| 409 | { |
---|
| 410 | $(this) |
---|
| 411 | .ianimate( |
---|
| 412 | {'-webkit-transform': 'translateY(' + currentHeight + 'px)'}, 350) |
---|
| 413 | .find('h1, .button') |
---|
| 414 | .ianimate( {'opacity': 0}, 100); |
---|
| 415 | } |
---|
| 416 | |
---|
| 417 | }) |
---|
| 418 | } |
---|
| 419 | |
---|
| 420 | })(jQuery); |
---|