-rw-r--r-- | frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js | 159 | ||||
-rw-r--r-- | frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js | 52 | ||||
-rw-r--r-- | frontend/gamma/js/JQTouch/extensions/jqt.floaty.js | 96 | ||||
-rw-r--r-- | frontend/gamma/js/JQTouch/extensions/jqt.location.js | 51 | ||||
-rw-r--r-- | frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js | 137 | ||||
-rw-r--r-- | frontend/gamma/js/JQTouch/extensions/jqt.offline.js | 97 | ||||
-rwxr-xr-x | frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js | 123 | ||||
-rw-r--r-- | frontend/gamma/js/JQTouch/jqtouch.js | 889 |
8 files changed, 1604 insertions, 0 deletions
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js b/frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js new file mode 100644 index 0000000..2a5f8d1 --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
12 | |||
13 | (c) 2012 by jQTouch project members. | ||
14 | See LICENSE.txt for license. | ||
15 | |||
16 | Author: Thomas Yip | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | |||
21 | _/ _/_/ _/_/_/_/_/ _/ | ||
22 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
23 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
24 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
25 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
26 | _/ | ||
27 | _/ | ||
28 | |||
29 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
30 | |||
31 | (c) 2012 by jQTouch project members. | ||
32 | See LICENSE.txt for license. | ||
33 | |||
34 | Author: Thomas Yip | ||
35 | */ | ||
36 | |||
37 | (function($) { | ||
38 | var src = $("head script").last().attr("src") || ''; | ||
39 | var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/'; | ||
40 | var csspath = scriptpath + 'jqt.actionsheet.css'; | ||
41 | var link = $('<link href="' + csspath + '" rel="stylesheet">'); | ||
42 | $('head').append($(link)); | ||
43 | |||
44 | function hide(callback) { | ||
45 | var $target = $(this); | ||
46 | var data = $(this).data('actionsheet'); | ||
47 | var $source = data.source; | ||
48 | |||
49 | var timeout; | ||
50 | |||
51 | function cleanup() { | ||
52 | clearTimeout(timeout); | ||
53 | |||
54 | $source.removeClass('transition'); | ||
55 | $target.removeClass('inmotion transition'); | ||
56 | !callback || callback.apply(this, arguments); | ||
57 | }; | ||
58 | timeout = setTimeout(cleanup, 500); | ||
59 | |||
60 | if (data.shown) { | ||
61 | $(this).data('actionsheet', {}); | ||
62 | $target.one('webkitTransitionEnd', cleanup); | ||
63 | |||
64 | $source.addClass('transition'); | ||
65 | $target.removeClass('current').addClass('inmotion transition'); | ||
66 | $('#jqt').removeClass('actionopened'); | ||
67 | } | ||
68 | return $target; | ||
69 | } | ||
70 | |||
71 | function show(callback) { | ||
72 | var $target = $(this); | ||
73 | var data = $(this).data('actionsheet') || {}; | ||
74 | if (!data.shown) { | ||
75 | var $source = $('#jqt .current:not(.actionsheet)'); | ||
76 | |||
77 | $target.one('webkitTransitionEnd', function() { | ||
78 | $source.removeClass('transition'); | ||
79 | $target.removeClass('inmotion transition'); | ||
80 | !callback || callback.apply(this, arguments); | ||
81 | }); | ||
82 | |||
83 | data.shown = true; | ||
84 | data.source = $source; | ||
85 | $(this).data('actionsheet', data); | ||
86 | |||
87 | $source.addClass('transition'); | ||
88 | $target.addClass('inmotion transition'); | ||
89 | $('#jqt').addClass('actionopened'); | ||
90 | setTimeout(function() { | ||
91 | $target.addClass('current'); | ||
92 | }, 50); | ||
93 | } | ||
94 | return $target; | ||
95 | } | ||
96 | |||
97 | var methods = { | ||
98 | init: function(options) { | ||
99 | $(this).addClass('actionsheet'); | ||
100 | $(this).data({shown: false}); | ||
101 | }, | ||
102 | show: show, | ||
103 | hide: hide | ||
104 | }; | ||
105 | |||
106 | $.fn.actionsheet = function(method) { | ||
107 | if (methods[method]) { | ||
108 | if ($(this).is('.actionsheet')) { | ||
109 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | ||
110 | } else { | ||
111 | var msg = 'Target is not a `actionsheet`. Action `' + method + '` is ignored.'; | ||
112 | console.warn(msg); | ||
113 | } | ||
114 | } else if ( typeof method === 'object' || ! method ) { | ||
115 | return methods.init.apply(this, arguments); | ||
116 | } else { | ||
117 | $.error( 'Method ' + method + ' does not exist on jQuery.tooltip' ); | ||
118 | } | ||
119 | }; | ||
120 | |||
121 | if ($.jQTouch) { | ||
122 | $.jQTouch.addTapHandler({ | ||
123 | name: 'open-actionsheet', | ||
124 | isSupported: function(e, params) { | ||
125 | return params.$el.is('.action'); | ||
126 | }, | ||
127 | fn: function(e, params) { | ||
128 | params.$el.removeClass('active'); | ||
129 | |||
130 | var $target = $(params.hash); | ||
131 | $target.actionsheet('show'); | ||
132 | |||
133 | return false; | ||
134 | } | ||
135 | }); | ||
136 | $.jQTouch.addTapHandler({ | ||
137 | name: 'follow-actionlink', | ||
138 | isSupported: function(e, params) { | ||
139 | if ($('#jqt').hasClass('actionopened')) { | ||
140 | return params.$el.is('.actionsheet a'); | ||
141 | } | ||
142 | return false; | ||
143 | }, | ||
144 | fn: function(e, params) { | ||
145 | params.$el.removeClass('active'); | ||
146 | |||
147 | var $target = params.$el.closest('.actionsheet'); | ||
148 | $target.actionsheet('hide', function() { | ||
149 | if (!params.$el.is('.dismiss')) { | ||
150 | params.$el.trigger('tap'); | ||
151 | } | ||
152 | }); | ||
153 | return false; | ||
154 | } | ||
155 | }); | ||
156 | } else { | ||
157 | console.error('Extension `jqt.actionsheet` failed to load. jQT not found'); | ||
158 | } | ||
159 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js b/frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js new file mode 100644 index 0000000..94f3d9b --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Maintained by Thomas Yip <http://beedesk.com/> | ||
13 | Sponsored by Sencha Labs <http://www.sencha.com/> | ||
14 | Special thanks to Jonathan Stark <http://www.jonathanstark.com/> | ||
15 | |||
16 | Documentation and issue tracking on GitHub <http://github.com/senchalabs/jQTouch/> | ||
17 | |||
18 | (c) 2009-2011 Sencha Labs | ||
19 | jQTouch may be freely distributed under the MIT license. | ||
20 | |||
21 | */ | ||
22 | |||
23 | (function($) { | ||
24 | if ($.jQTouch) | ||
25 | { | ||
26 | $.jQTouch.addExtension(function AutoTitles(jQT){ | ||
27 | |||
28 | var titleSelector='.toolbar h1'; | ||
29 | |||
30 | $(function(){ | ||
31 | $('#jqt').bind('pageAnimationStart', function(e, data){ | ||
32 | if (data.direction === 'in'){ | ||
33 | var $title = $(titleSelector, $(e.target)); | ||
34 | var $ref = $(e.target).data('referrer'); | ||
35 | if ($title.length && $ref && $title.text() === ''){ | ||
36 | $title.html($ref.text()); | ||
37 | } | ||
38 | } | ||
39 | }); | ||
40 | }); | ||
41 | |||
42 | function setTitleSelector(ts){ | ||
43 | titleSelector=ts; | ||
44 | } | ||
45 | |||
46 | return { | ||
47 | setTitleSelector: setTitleSelector | ||
48 | }; | ||
49 | |||
50 | }); | ||
51 | } | ||
52 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.floaty.js b/frontend/gamma/js/JQTouch/extensions/jqt.floaty.js new file mode 100644 index 0000000..c7e4485 --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.floaty.js | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
13 | |||
14 | Special thanks to Jonathan Stark <http://jonathanstark.com/> | ||
15 | and pinch/zoom <http://www.pinchzoom.com/> | ||
16 | |||
17 | (c) 2009 by jQTouch project members. | ||
18 | See LICENSE.txt for license. | ||
19 | |||
20 | */ | ||
21 | |||
22 | (function($) { | ||
23 | if ($.jQTouch) | ||
24 | { | ||
25 | $.jQTouch.addExtension(function Floaty(jQT){ | ||
26 | |||
27 | $.fn.makeFloaty = function(options){ | ||
28 | var defaults = { | ||
29 | align: 'top', | ||
30 | spacing: 20, | ||
31 | time: '.3s' | ||
32 | }; | ||
33 | |||
34 | var settings = $.extend({}, defaults, options); | ||
35 | |||
36 | settings.align = (settings.align == 'top') ? 'top' : 'bottom'; | ||
37 | |||
38 | return this.each(function(){ | ||
39 | var $el = $(this); | ||
40 | |||
41 | $el.css({ | ||
42 | '-webkit-transition': 'top ' + settings.time + ' ease-in-out', | ||
43 | 'display': 'block', | ||
44 | 'min-height': '0 !important' | ||
45 | }).data('settings', settings); | ||
46 | |||
47 | $(document).scroll(function(){ | ||
48 | if ($el.data('floatyVisible') === 'true') | ||
49 | { | ||
50 | $el.scrollFloaty(); | ||
51 | } | ||
52 | }); | ||
53 | $el.scrollFloaty(); | ||
54 | }); | ||
55 | }; | ||
56 | |||
57 | $.fn.scrollFloaty = function(){ | ||
58 | |||
59 | |||
60 | return this.each(function(){ | ||
61 | var $el = $(this); | ||
62 | var settings = $el.data('settings'); // Settings not being set as object w/Zepto | ||
63 | var wHeight = $('html').attr('clientHeight'); // WRONG | ||
64 | |||
65 | var newY = window.pageYOffset + | ||
66 | ((settings.align == 'top') ? | ||
67 | settings.spacing : wHeight - settings.spacing - $el.get(0).offsetHeight); | ||
68 | |||
69 | $el.css('top', newY).data('floatyVisible', true); | ||
70 | }); | ||
71 | }; | ||
72 | |||
73 | $.fn.hideFloaty = function(){ | ||
74 | return this.each(function(){ | ||
75 | var $el = $(this); | ||
76 | var oh = $el.get(0).offsetHeight; | ||
77 | |||
78 | $el.css('top', -oh-10).data('floatyVisible', false); | ||
79 | }); | ||
80 | }; | ||
81 | |||
82 | $.fn.toggleFloaty = function(){ | ||
83 | return this.each(function(){ | ||
84 | var $el = $(this); | ||
85 | if ($el.data('floatyVisible') === 'true'){ | ||
86 | $el.hideFloaty(); | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | $el.scrollFloaty(); | ||
91 | } | ||
92 | }); | ||
93 | }; | ||
94 | }); | ||
95 | } | ||
96 | })($); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.location.js b/frontend/gamma/js/JQTouch/extensions/jqt.location.js new file mode 100644 index 0000000..9d53a1a --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.location.js | |||
@@ -0,0 +1,51 @@ | |||
1 | (function($) { | ||
2 | if ($.jQTouch) | ||
3 | { | ||
4 | $.jQTouch.addExtension(function Location(){ | ||
5 | |||
6 | var latitude, longitude, callback, callback2; | ||
7 | |||
8 | function updateLocation(fn, fn2) { | ||
9 | if (navigator.geolocation) | ||
10 | { | ||
11 | callback = fn; | ||
12 | callback2 = fn2; | ||
13 | navigator.geolocation.getCurrentPosition(savePosition, failResponse); | ||
14 | return true; | ||
15 | } else { | ||
16 | console.log('Device not capable of geo-location.'); | ||
17 | fn(false); | ||
18 | return false; | ||
19 | } | ||
20 | } | ||
21 | function failResponse(error){ | ||
22 | if (callback2) { | ||
23 | callback2(error); | ||
24 | } | ||
25 | } | ||
26 | function savePosition(position) { | ||
27 | latitude = position.coords.latitude; | ||
28 | longitude = position.coords.longitude; | ||
29 | if (callback) { | ||
30 | callback(getLocation()); | ||
31 | } | ||
32 | } | ||
33 | function getLocation() { | ||
34 | if (latitude && longitude) { | ||
35 | return { | ||
36 | latitude: latitude, | ||
37 | longitude: longitude | ||
38 | }; | ||
39 | |||
40 | } else { | ||
41 | console.log('No location available. Try calling updateLocation() first.'); | ||
42 | return false; | ||
43 | } | ||
44 | } | ||
45 | return { | ||
46 | updateLocation: updateLocation, | ||
47 | getLocation: getLocation | ||
48 | }; | ||
49 | }); | ||
50 | } | ||
51 | })($); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js b/frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js new file mode 100644 index 0000000..8d21aca --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
12 | |||
13 | (c) 2012 by jQTouch project members. | ||
14 | See LICENSE.txt for license. | ||
15 | |||
16 | Author: Thomas Yip | ||
17 | */ | ||
18 | |||
19 | (function($) { | ||
20 | var src = $("head script").last().attr("src") || ''; | ||
21 | var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/'; | ||
22 | var csspath = scriptpath + 'jqt.menusheet.css'; | ||
23 | var link = $('<link href="' + csspath + '" rel="stylesheet">'); | ||
24 | $('head').append($(link)); | ||
25 | |||
26 | function hide(callback) { | ||
27 | var $target = $(this); | ||
28 | var data = $(this).data('menusheet'); | ||
29 | if (data.shown) { | ||
30 | $(this).data('menusheet', {}); | ||
31 | var $source = data.source; | ||
32 | $source.unbind('touchstart mousedown', data.closehandler); | ||
33 | $source.one('webkitTransitionEnd', function() { | ||
34 | $source.removeClass('inmotion transition in'); | ||
35 | $target.removeClass('inmotion out'); | ||
36 | !callback || callback.apply(this, arguments); | ||
37 | }); | ||
38 | |||
39 | $source.addClass('inmotion transition in'); | ||
40 | $target.addClass('inmotion out').removeClass('current'); | ||
41 | $('#jqt').removeClass('menuopened'); | ||
42 | } | ||
43 | return $target; | ||
44 | } | ||
45 | |||
46 | function show(callback) { | ||
47 | var $target = $(this); | ||
48 | var data = $(this).data('menusheet') || {}; | ||
49 | if (!data.shown) { | ||
50 | var $source = $('#jqt .current:not(.menusheet)'); | ||
51 | var closehandler = function() { | ||
52 | $target.menusheet('hide'); | ||
53 | return false; | ||
54 | }; | ||
55 | |||
56 | $source.one('webkitTransitionEnd', function() { | ||
57 | $source.one('touchstart mousedown', closehandler); | ||
58 | $source.removeClass('inmotion transition out'); | ||
59 | $target.removeClass('inmotion in'); | ||
60 | !callback || callback.apply(this, arguments); | ||
61 | }); | ||
62 | |||
63 | data.shown = true; | ||
64 | data.closehandler = closehandler; | ||
65 | data.source = $source; | ||
66 | $(this).data('menusheet', data); | ||
67 | |||
68 | $source.addClass('inmotion transition out'); | ||
69 | $target.addClass('current in'); | ||
70 | $('#jqt').addClass('menuopened'); | ||
71 | } | ||
72 | return $target; | ||
73 | } | ||
74 | |||
75 | var methods = { | ||
76 | init: function(options) { | ||
77 | $(this).addClass('menusheet'); | ||
78 | $(this).data({shown: false}); | ||
79 | }, | ||
80 | show: show, | ||
81 | hide: hide | ||
82 | }; | ||
83 | |||
84 | $.fn.menusheet = function(method) { | ||
85 | if (methods[method]) { | ||
86 | if ($(this).is('.menusheet')) { | ||
87 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | ||
88 | } else { | ||
89 | var msg = 'Target is not a `menusheet`. Action `' + method + '` is ignored.'; | ||
90 | console.warn(msg); | ||
91 | } | ||
92 | } else if ( typeof method === 'object' || ! method ) { | ||
93 | return methods.init.apply(this, arguments); | ||
94 | } else { | ||
95 | $.error( 'Method ' + method + ' does not exist on jQuery.tooltip' ); | ||
96 | } | ||
97 | }; | ||
98 | |||
99 | if ($.jQTouch) { | ||
100 | $.jQTouch.addTapHandler({ | ||
101 | name: 'open-menusheet', | ||
102 | isSupported: function(e, params) { | ||
103 | return params.$el.is('.menu'); | ||
104 | }, | ||
105 | fn: function(e, params) { | ||
106 | params.$el.removeClass('active'); | ||
107 | |||
108 | var $target = $(params.hash); | ||
109 | $target.menusheet('show'); | ||
110 | |||
111 | return false; | ||
112 | } | ||
113 | }); | ||
114 | $.jQTouch.addTapHandler({ | ||
115 | name: 'follow-menulink', | ||
116 | isSupported: function(e, params) { | ||
117 | if ($('#jqt').hasClass('menuopened')) { | ||
118 | return params.$el.is('.menusheet a'); | ||
119 | } | ||
120 | return false; | ||
121 | }, | ||
122 | fn: function(e, params) { | ||
123 | params.$el.removeClass('active'); | ||
124 | |||
125 | var $target = params.$el.closest('.menusheet'); | ||
126 | $target.menusheet('hide', function() { | ||
127 | if (!params.$el.is('.dismiss')) { | ||
128 | params.$el.trigger('tap'); | ||
129 | } | ||
130 | }); | ||
131 | return false; | ||
132 | } | ||
133 | }); | ||
134 | } else { | ||
135 | console.error('Extension `jqt.menusheet` failed to load. jQT not found'); | ||
136 | } | ||
137 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.offline.js b/frontend/gamma/js/JQTouch/extensions/jqt.offline.js new file mode 100644 index 0000000..b333a16 --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.offline.js | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
13 | |||
14 | Special thanks to Jonathan Stark <http://jonathanstark.com/> | ||
15 | |||
16 | Lots of this code is specifically derived from Jonathan's book, | ||
17 | "Building iPhone Apps with HTML, CSS, and JavaScript" | ||
18 | |||
19 | (c) 2009 by jQTouch project members. | ||
20 | See LICENSE.txt for license. | ||
21 | |||
22 | */ | ||
23 | |||
24 | (function($) { | ||
25 | if ($.jQTouch) | ||
26 | { | ||
27 | $.jQTouch.addExtension(function Offline(){ | ||
28 | |||
29 | // Convenience array of status values | ||
30 | var cacheStatusValues = []; | ||
31 | cacheStatusValues[0] = 'uncached'; | ||
32 | cacheStatusValues[1] = 'idle'; | ||
33 | cacheStatusValues[2] = 'checking'; | ||
34 | cacheStatusValues[3] = 'downloading'; | ||
35 | cacheStatusValues[4] = 'updateready'; | ||
36 | cacheStatusValues[5] = 'obsolete'; | ||
37 | |||
38 | // Listeners for all possible events | ||
39 | var cache = window.applicationCache; | ||
40 | cache.addEventListener('cached', logEvent, false); | ||
41 | cache.addEventListener('checking', logEvent, false); | ||
42 | cache.addEventListener('downloading', logEvent, false); | ||
43 | cache.addEventListener('error', logEvent, false); | ||
44 | cache.addEventListener('noupdate', logEvent, false); | ||
45 | cache.addEventListener('obsolete', logEvent, false); | ||
46 | cache.addEventListener('progress', logEvent, false); | ||
47 | cache.addEventListener('updateready', logEvent, false); | ||
48 | |||
49 | // Log every event to the console | ||
50 | function logEvent(e) { | ||
51 | var online, status, type, message; | ||
52 | online = (isOnline()) ? 'yes' : 'no'; | ||
53 | status = cacheStatusValues[cache.status]; | ||
54 | type = e.type; | ||
55 | message = 'online: ' + online; | ||
56 | message+= ', event: ' + type; | ||
57 | message+= ', status: ' + status; | ||
58 | if (type == 'error' && navigator.onLine) { | ||
59 | message+= ' There was an unknown error, check your Cache Manifest.'; | ||
60 | } | ||
61 | console.log(message); | ||
62 | } | ||
63 | |||
64 | function isOnline() { | ||
65 | return navigator.onLine; | ||
66 | } | ||
67 | |||
68 | if (!$('html').attr('manifest')) { | ||
69 | console.log('No Cache Manifest listed on the <html> tag.') | ||
70 | } | ||
71 | |||
72 | // Swap in newly download files when update is ready | ||
73 | cache.addEventListener('updateready', function(e){ | ||
74 | // Don't perform "swap" if this is the first cache | ||
75 | if (cacheStatusValues[cache.status] != 'idle') { | ||
76 | cache.swapCache(); | ||
77 | console.log('Swapped/updated the Cache Manifest.'); | ||
78 | } | ||
79 | } | ||
80 | , false); | ||
81 | |||
82 | // These two functions check for updates to the manifest file | ||
83 | function checkForUpdates(){ | ||
84 | cache.update(); | ||
85 | } | ||
86 | function autoCheckForUpdates(){ | ||
87 | setInterval(function(){cache.update()}, 10000); | ||
88 | } | ||
89 | |||
90 | return { | ||
91 | isOnline: isOnline, | ||
92 | checkForUpdates: checkForUpdates, | ||
93 | autoCheckForUpdates: autoCheckForUpdates | ||
94 | } | ||
95 | }); | ||
96 | } | ||
97 | })(jQuery); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js b/frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js new file mode 100755 index 0000000..ef3a75d --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
12 | |||
13 | (c) 2011 by jQTouch project members. | ||
14 | See LICENSE.txt for license. | ||
15 | |||
16 | */ | ||
17 | |||
18 | (function($) { | ||
19 | if ($.jQTouch) { | ||
20 | |||
21 | var scriptpath = $("script").last().attr("src").split('?')[0].split('/').slice(0, -1).join('/')+'/'; | ||
22 | |||
23 | $.jQTouch.addExtension(function ThemeSwitcher(jQT) { | ||
24 | |||
25 | var current, | ||
26 | link, | ||
27 | titles = {}, | ||
28 | defaults = { | ||
29 | themeStyleSelector: 'link[rel="stylesheet"][title]', | ||
30 | themeIncluded: [ | ||
31 | {title: 'jQTouch', href: scriptpath + '../themes/css/jqtouch.css'}, | ||
32 | {title: 'Apple', href: scriptpath + '../themes/css/apple.css'}, | ||
33 | {title: 'Vanilla', href: scriptpath + '../themes/css/vanilla.css'} | ||
34 | |||
35 | ] | ||
36 | }, | ||
37 | options = $.extend({}, defaults, jQT.settings); | ||
38 | |||
39 | function setStyleState(item, title) { | ||
40 | var $item = $(item); | ||
41 | |||
42 | if ($item.attr('title') === title) { | ||
43 | item.disabled = false; // workaround for Firefox on Zepto | ||
44 | $item.removeAttr('disabled'); | ||
45 | } else { | ||
46 | item.disabled = true; // workaround for Firefox on Zepto | ||
47 | $item.attr('disabled', true); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | function initializeStyleState(item, title) { | ||
52 | // and, workaround for WebKit by initializing the 'disabled' attribute | ||
53 | if (!current) { | ||
54 | current = title; | ||
55 | } | ||
56 | setStyleState(item, current); | ||
57 | } | ||
58 | |||
59 | // public | ||
60 | function switchStyle(title) { | ||
61 | current = title; | ||
62 | $(options.themeStyleSelector).each(function(i, item) { | ||
63 | setStyleState(item, title); | ||
64 | }); | ||
65 | } | ||
66 | |||
67 | // collect title names, from <head> | ||
68 | $(options.themeStyleSelector).each(function(i, item) { | ||
69 | var $item = $(item); | ||
70 | var title = $item.attr('title'); | ||
71 | |||
72 | titles[title] = true; | ||
73 | |||
74 | initializeStyleState(item, title); | ||
75 | }); | ||
76 | |||
77 | // add included theme | ||
78 | for (var i=0; i < options.themeIncluded.length; i++) { | ||
79 | var hash = options.themeIncluded[i]; | ||
80 | if (!(hash.title in titles)) { | ||
81 | link = $('<link title="' + hash.title + '" href="' + hash.href + '" rel="stylesheet">'); | ||
82 | $('head').append($(link)); | ||
83 | |||
84 | titles[hash.title] = true; | ||
85 | |||
86 | initializeStyleState(link, hash.title); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | if (options.themeSelectionSelector) { | ||
91 | // create UI items | ||
92 | for (var title in titles) { | ||
93 | var $item = $('<li><a href="#" data-title="' + title + '">' + title + '</a></li>'); | ||
94 | $(options.themeSelectionSelector).append($item); | ||
95 | } | ||
96 | |||
97 | // bind to UI items | ||
98 | $(options.themeSelectionSelector).delegate('* > a', 'tap', function(e) { | ||
99 | e.preventDefault(); | ||
100 | e.stopPropagation(); | ||
101 | |||
102 | var $a = $(this).closest('a'); | ||
103 | $a.removeClass('active'); | ||
104 | switchStyle($a.attr('data-title')); | ||
105 | |||
106 | // poor-man simulation of radio button behaviour | ||
107 | $(options.themeSelectionSelector).find('a').removeClass('selected'); | ||
108 | $a.addClass('selected'); | ||
109 | }); | ||
110 | |||
111 | // poor-man simulation of radio button behaviour | ||
112 | $(options.themeSelectionSelector).closest('#jqt > *').bind('pageAnimationEnd', function(e, data){ | ||
113 | if (data.direction === 'in') { | ||
114 | $(options.themeSelectionSelector).find('a[data-title="' + current + '"]').addClass('selected'); | ||
115 | } | ||
116 | }); | ||
117 | } | ||
118 | |||
119 | return {switchStyle: switchStyle}; | ||
120 | |||
121 | }); | ||
122 | } | ||
123 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/jqtouch.js b/frontend/gamma/js/JQTouch/jqtouch.js new file mode 100644 index 0000000..bdc6d2e --- a/dev/null +++ b/frontend/gamma/js/JQTouch/jqtouch.js | |||
@@ -0,0 +1,889 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Maintained by Thomas Yip <http://beedesk.com/> | ||
13 | Sponsored by Sencha Labs <http://www.sencha.com/> | ||
14 | Special thanks to Jonathan Stark <http://www.jonathanstark.com/> | ||
15 | |||
16 | Documentation and issue tracking on GitHub <http://github.com/senchalabs/jQTouch/> | ||
17 | |||
18 | (c) 2009-2011 Sencha Labs | ||
19 | jQTouch may be freely distributed under the MIT license. | ||
20 | |||
21 | */ | ||
22 | (function() { | ||
23 | |||
24 | var fx; | ||
25 | if ('Zepto' in window) { | ||
26 | fx = window.Zepto; | ||
27 | fx.fn.prop = fx.fn.attr; | ||
28 | |||
29 | Event.prototype.isDefaultPrevented = function() { | ||
30 | return this.defaultPrevented; | ||
31 | }; | ||
32 | } else if ('jQuery' in window) { | ||
33 | fx = window.jQuery; | ||
34 | |||
35 | // trick to get Zepto/touch.js to work for jQuery | ||
36 | window.Zepto = $; | ||
37 | } else { | ||
38 | throw('Either Zepto or jQuery is required but neither can be found.'); | ||
39 | } | ||
40 | |||
41 | $.jQTouch = function(options) { | ||
42 | // Initialize internal jQT variables | ||
43 | var $ = fx, | ||
44 | $body, | ||
45 | $head=$('head'), | ||
46 | history=[], | ||
47 | newPageCount=0, | ||
48 | jQTSettings={}, | ||
49 | $currentPage='', | ||
50 | orientation='portrait', | ||
51 | touchSelectors=[], | ||
52 | publicObj={}, | ||
53 | tapBuffer=100, // High click delay = ~350, quickest animation (slide) = 250 | ||
54 | extensions=$.jQTouch.prototype.extensions, | ||
55 | extTapHandlers=$.jQTouch.prototype.tapHandlers, | ||
56 | tapHandlers=[], | ||
57 | animations=[], | ||
58 | hairExtensions='', | ||
59 | defaults = { | ||
60 | addGlossToIcon: true, | ||
61 | backSelector: '.back, .cancel, .goback', | ||
62 | cacheGetRequests: true, | ||
63 | debug: true, | ||
64 | defaultAnimation: 'slideleft', | ||
65 | fixedViewport: true, | ||
66 | formSelector: 'form', | ||
67 | fullScreen: true, | ||
68 | fullScreenClass: 'fullscreen', | ||
69 | icon: null, | ||
70 | icon4: null, // available in iOS 4.2 and later. | ||
71 | preloadImages: false, | ||
72 | startupScreen: null, | ||
73 | statusBar: 'default', // other options: black-translucent, black | ||
74 | submitSelector: '.submit', | ||
75 | touchSelector: 'a, .touch', | ||
76 | trackScrollPositions: true, | ||
77 | useAnimations: true, | ||
78 | useFastTouch: true, | ||
79 | useTouchScroll: true, | ||
80 | animations: [ // highest to lowest priority | ||
81 | {name:'cubeleft', selector:'.cubeleft, .cube', is3d: true}, | ||
82 | {name:'cuberight', selector:'.cuberight', is3d: true}, | ||
83 | {name:'dissolve', selector:'.dissolve'}, | ||
84 | {name:'fade', selector:'.fade'}, | ||
85 | {name:'flipleft', selector:'.flipleft, .flip', is3d: true}, | ||
86 | {name:'flipright', selector:'.flipright', is3d: true}, | ||
87 | {name:'pop', selector:'.pop', is3d: true}, | ||
88 | {name:'swapleft', selector:'.swap', is3d: true}, | ||
89 | {name:'slidedown', selector:'.slidedown'}, | ||
90 | {name:'slideright', selector:'.slideright'}, | ||
91 | {name:'slideup', selector:'.slideup'}, | ||
92 | {name:'slideleft', selector:'.slideleft, .slide, #jqt > * > ul li a'} | ||
93 | ] | ||
94 | }; // end defaults | ||
95 | |||
96 | function warn(message) { | ||
97 | if (window.console !== undefined && jQTSettings.debug === true) { | ||
98 | console.warn(message); | ||
99 | } | ||
100 | } | ||
101 | function addAnimation(animation) { | ||
102 | if (typeof(animation.selector) === 'string' && typeof(animation.name) === 'string') { | ||
103 | animations.push(animation); | ||
104 | } | ||
105 | } | ||
106 | function addTapHandler(tapHandler) { | ||
107 | if (typeof(tapHandler.name) === 'string' | ||
108 | && typeof(tapHandler.isSupported) === 'function' | ||
109 | && typeof(tapHandler.fn) === 'function') { | ||
110 | |||
111 | tapHandlers.push(tapHandler); | ||
112 | } | ||
113 | } | ||
114 | function addPageToHistory(page, animation) { | ||
115 | history.unshift({ | ||
116 | page: page, | ||
117 | animation: animation, | ||
118 | hash: '#' + page.attr('id'), | ||
119 | id: page.attr('id') | ||
120 | }); | ||
121 | } | ||
122 | |||
123 | // Unfortunately, we can not assume the "tap" event | ||
124 | // is being used for links, forms, etc. | ||
125 | function clickHandler(e) { | ||
126 | // Figure out whether to prevent default | ||
127 | var $el = $(e.target); | ||
128 | |||
129 | // Find the nearest tappable ancestor | ||
130 | if (!$el.is(touchSelectors.join(', '))) { | ||
131 | $el = $(e.target).closest(touchSelectors.join(', ')); | ||
132 | } | ||
133 | |||
134 | // Prevent default if we found an internal link (relative or absolute) | ||
135 | if ($el && $el.attr('href') && !$el.isExternalLink()) { | ||
136 | warn('Need to prevent default click behavior'); | ||
137 | e.preventDefault(); | ||
138 | } else { | ||
139 | warn('No need to prevent default click behavior'); | ||
140 | } | ||
141 | |||
142 | // Trigger a tap event if touchstart is not on the job | ||
143 | if ($.support.touch) { | ||
144 | warn('Not converting click to a tap event because touch handler is on the job'); | ||
145 | } else { | ||
146 | warn('Converting click event to a tap event because touch handlers are not present or off'); | ||
147 | $(e.target).trigger('tap', e); | ||
148 | } | ||
149 | |||
150 | } | ||
151 | function doNavigation(fromPage, toPage, animation, goingBack) { | ||
152 | |||
153 | goingBack = goingBack ? goingBack : false; | ||
154 | |||
155 | // Error check for target page | ||
156 | if (toPage === undefined || toPage.length === 0) { | ||
157 | $.fn.unselect(); | ||
158 | warn('Target element is missing.'); | ||
159 | return false; | ||
160 | } | ||
161 | |||
162 | // Error check for fromPage===toPage | ||
163 | if (toPage.hasClass('current')) { | ||
164 | $.fn.unselect(); | ||
165 | warn('You are already on the page you are trying to navigate to.'); | ||
166 | return false; | ||
167 | } | ||
168 | |||
169 | // Collapse the keyboard | ||
170 | $(':focus').trigger('blur'); | ||
171 | |||
172 | fromPage.trigger('pageAnimationStart', { direction: 'out', back: goingBack }); | ||
173 | toPage.trigger('pageAnimationStart', { direction: 'in', back: goingBack }); | ||
174 | |||
175 | if ($.support.animationEvents && animation && jQTSettings.useAnimations) { | ||
176 | // Fail over to 2d animation if need be | ||
177 | if (!$.support.transform3d && animation.is3d) { | ||
178 | warn('Did not detect support for 3d animations, falling back to ' + jQTSettings.defaultAnimation); | ||
179 | animation.name = jQTSettings.defaultAnimation; | ||
180 | } | ||
181 | |||
182 | // Reverse animation if need be | ||
183 | var finalAnimationName = animation.name, | ||
184 | is3d = animation.is3d ? 'animating3d' : ''; | ||
185 | |||
186 | if (goingBack) { | ||
187 | finalAnimationName = finalAnimationName.replace(/left|right|up|down|in|out/, reverseAnimation ); | ||
188 | } | ||
189 | |||
190 | warn('finalAnimationName is ' + finalAnimationName); | ||
191 | |||
192 | // Bind internal "cleanup" callback | ||
193 | fromPage.bind('webkitAnimationEnd', navigationEndHandler); | ||
194 | |||
195 | // Trigger animations | ||
196 | $body.addClass('animating ' + is3d); | ||
197 | |||
198 | var lastScroll = window.pageYOffset; | ||
199 | |||
200 | // Position the incoming page so toolbar is at top of viewport regardless of scroll position on from page | ||
201 | if (jQTSettings.trackScrollPositions === true) { | ||
202 | toPage.css('top', window.pageYOffset - (toPage.data('lastScroll') || 0)); | ||
203 | } | ||
204 | |||
205 | toPage.addClass(finalAnimationName + ' in current'); | ||
206 | fromPage.removeClass('current').addClass(finalAnimationName + ' out inmotion'); | ||
207 | |||
208 | if (jQTSettings.trackScrollPositions === true) { | ||
209 | fromPage.data('lastScroll', lastScroll); | ||
210 | $('.scroll', fromPage).each(function(){ | ||
211 | $(this).data('lastScroll', this.scrollTop); | ||
212 | }); | ||
213 | } | ||
214 | } else { | ||
215 | toPage.addClass('current in'); | ||
216 | fromPage.removeClass('current'); | ||
217 | navigationEndHandler(); | ||
218 | } | ||
219 | |||
220 | // Housekeeping | ||
221 | $currentPage = toPage; | ||
222 | if (goingBack) { | ||
223 | history.shift(); | ||
224 | } else { | ||
225 | addPageToHistory($currentPage, animation); | ||
226 | } | ||
227 | setHash($currentPage.attr('id')); | ||
228 | |||
229 | // Private navigationEnd callback | ||
230 | function navigationEndHandler(event) { | ||
231 | var bufferTime = tapBuffer; | ||
232 | |||
233 | if ($.support.animationEvents && animation && jQTSettings.useAnimations) { | ||
234 | fromPage.unbind('webkitAnimationEnd', navigationEndHandler); | ||
235 | fromPage.removeClass(finalAnimationName + ' out inmotion'); | ||
236 | if (finalAnimationName) { | ||
237 | toPage.removeClass(finalAnimationName); | ||
238 | } | ||
239 | $body.removeClass('animating animating3d'); | ||
240 | if (jQTSettings.trackScrollPositions === true) { | ||
241 | toPage.css('top', -toPage.data('lastScroll')); | ||
242 | |||
243 | // Have to make sure the scroll/style resets | ||
244 | // are outside the flow of this function. | ||
245 | setTimeout(function(){ | ||
246 | toPage.css('top', 0); | ||
247 | window.scroll(0, toPage.data('lastScroll')); | ||
248 | $('.scroll', toPage).each(function(){ | ||
249 | this.scrollTop = - $(this).data('lastScroll'); | ||
250 | }); | ||
251 | }, 0); | ||
252 | } | ||
253 | } else { | ||
254 | fromPage.removeClass(finalAnimationName + ' out inmotion'); | ||
255 | if (finalAnimationName) { | ||
256 | toPage.removeClass(finalAnimationName); | ||
257 | } | ||
258 | bufferTime += 260; | ||
259 | } | ||
260 | |||
261 | // In class is intentionally delayed, as it is our ghost click hack | ||
262 | setTimeout(function(){ | ||
263 | toPage.removeClass('in'); | ||
264 | window.scroll(0,0); | ||
265 | }, bufferTime); | ||
266 | |||
267 | fromPage.unselect(); | ||
268 | |||
269 | // Trigger custom events | ||
270 | toPage.trigger('pageAnimationEnd', { | ||
271 | direction:'in', animation: animation, back: goingBack | ||
272 | }); | ||
273 | fromPage.trigger('pageAnimationEnd', { | ||
274 | direction:'out', animation: animation, back: goingBack | ||
275 | }); | ||
276 | } | ||
277 | |||
278 | return true; | ||
279 | } | ||
280 | function reverseAnimation(animation) { | ||
281 | var opposites={ | ||
282 | 'up' : 'down', | ||
283 | 'down' : 'up', | ||
284 | 'left' : 'right', | ||
285 | 'right' : 'left', | ||
286 | 'in' : 'out', | ||
287 | 'out' : 'in' | ||
288 | }; | ||
289 | |||
290 | return opposites[animation] || animation; | ||
291 | } | ||
292 | function getOrientation() { | ||
293 | return orientation; | ||
294 | } | ||
295 | function goBack() { | ||
296 | |||
297 | // Error checking | ||
298 | if (history.length < 1 ) { | ||
299 | warn('History is empty.'); | ||
300 | } | ||
301 | |||
302 | if (history.length === 1 ) { | ||
303 | warn('You are on the first panel.'); | ||
304 | window.history.go(-1); | ||
305 | } | ||
306 | |||
307 | var from = history[0], | ||
308 | to = history[1]; | ||
309 | |||
310 | if (doNavigation(from.page, to.page, from.animation, true)) { | ||
311 | return publicObj; | ||
312 | } else { | ||
313 | warn('Could not go back.'); | ||
314 | return false; | ||
315 | } | ||
316 | |||
317 | } | ||
318 | function goTo(toPage, animation) { | ||
319 | |||
320 | var fromPage = history[0].page; | ||
321 | |||
322 | if (typeof animation === 'string') { | ||
323 | for (var i=0, max=animations.length; i < max; i++) { | ||
324 | if (animations[i].name === animation) { | ||
325 | animation = animations[i]; | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | if (typeof toPage === 'string') { | ||
332 | var nextPage = $(toPage); | ||
333 | |||
334 | if (nextPage.length < 1) { | ||
335 | showPageByHref(toPage, { | ||
336 | animation: animation | ||
337 | }); | ||
338 | return; | ||
339 | } else { | ||
340 | toPage = nextPage; | ||
341 | } | ||
342 | } | ||
343 | if (doNavigation(fromPage, toPage, animation)) { | ||
344 | return publicObj; | ||
345 | } else { | ||
346 | warn('Could not animate pages.'); | ||
347 | return false; | ||
348 | } | ||
349 | } | ||
350 | function hashChangeHandler(e) { | ||
351 | if (location.hash === history[0].hash) { | ||
352 | warn('We are on the right panel'); | ||
353 | return true; | ||
354 | } else if (location.hash === '') { | ||
355 | goBack(); | ||
356 | return true; | ||
357 | } else { | ||
358 | if( (history[1] && location.hash === history[1].hash) ) { | ||
359 | goBack(); | ||
360 | return true; | ||
361 | } else { | ||
362 | // Lastly, just try going to the ID... | ||
363 | warn('Could not find ID in history, just forwarding to DOM element.'); | ||
364 | goTo($(location.hash), jQTSettings.defaultAnimation); | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | function init(options) { | ||
369 | jQTSettings = $.extend({}, defaults, options); | ||
370 | |||
371 | // Preload images | ||
372 | if (jQTSettings.preloadImages) { | ||
373 | for (var i = jQTSettings.preloadImages.length - 1; i >= 0; i--) { | ||
374 | (new Image()).src = jQTSettings.preloadImages[i]; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | // Set appropriate icon (retina display available in iOS 4.2 and later.) | ||
379 | var precomposed = (jQTSettings.addGlossToIcon) ? '' : '-precomposed'; | ||
380 | if (jQTSettings.icon) { | ||
381 | hairExtensions += '<link rel="apple-touch-icon' + precomposed + '" href="' + jQTSettings.icon + '" />'; | ||
382 | } | ||
383 | if (jQTSettings.icon4) { | ||
384 | hairExtensions += '<link rel="apple-touch-icon' + precomposed + '" sizes="114x114" href="' + jQTSettings.icon4 + '" />'; | ||
385 | } | ||
386 | // Set startup screen | ||
387 | if (jQTSettings.startupScreen) { | ||
388 | hairExtensions += '<link rel="apple-touch-startup-image" href="' + jQTSettings.startupScreen + '" />'; | ||
389 | } | ||
390 | |||
391 | // Set viewport | ||
392 | if (jQTSettings.fixedViewport) { | ||
393 | hairExtensions += '<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>'; | ||
394 | } | ||
395 | |||
396 | // Set full-screen | ||
397 | if (jQTSettings.fullScreen) { | ||
398 | hairExtensions += '<meta name="apple-mobile-web-app-capable" content="yes" />'; | ||
399 | if (jQTSettings.statusBar) { | ||
400 | hairExtensions += '<meta name="apple-mobile-web-app-status-bar-style" content="' + jQTSettings.statusBar + '" />'; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | // Attach hair extensions | ||
405 | if (hairExtensions) { | ||
406 | $head.prepend(hairExtensions); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | function getAnimation(el) { | ||
411 | var animation; | ||
412 | |||
413 | for (var i=0, max=animations.length; i < max; i++) { | ||
414 | if (el.is(animations[i].selector)) { | ||
415 | animation = animations[i]; | ||
416 | break; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | if (!animation) { | ||
421 | warn('Animation could not be found. Using ' + jQTSettings.defaultAnimation + '.'); | ||
422 | animation = jQTSettings.defaultAnimation; | ||
423 | } | ||
424 | return animation; | ||
425 | } | ||
426 | |||
427 | function insertPages(nodes, animation) { | ||
428 | |||
429 | var targetPage = null; | ||
430 | |||
431 | // Call dom.createElement element directly instead of relying on $(nodes), | ||
432 | // to work around: https://github.com/madrobby/zepto/issues/312 | ||
433 | var div = document.createElement('div'); | ||
434 | div.innerHTML = nodes; | ||
435 | |||
436 | $(div).children().each(function(index, node) { | ||
437 | var $node = $(this); | ||
438 | if (!$node.attr('id')) { | ||
439 | $node.attr('id', 'page-' + (++newPageCount)); | ||
440 | } | ||
441 | |||
442 | // Remove any existing instance | ||
443 | $('#' + $node.attr('id')).remove(); | ||
444 | |||
445 | $body.append($node); | ||
446 | $body.trigger('pageInserted', {page: $node}); | ||
447 | |||
448 | if ($node.hasClass('current') || !targetPage) { | ||
449 | targetPage = $node; | ||
450 | } | ||
451 | }); | ||
452 | if (targetPage !== null) { | ||
453 | goTo(targetPage, animation); | ||
454 | return targetPage; | ||
455 | } else { | ||
456 | return false; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | function orientationChangeHandler() { | ||
461 | $body.css('minHeight', 1000); | ||
462 | scrollTo(0,0); | ||
463 | var bodyHeight = window.innerHeight; | ||
464 | $body.css('minHeight', bodyHeight); | ||
465 | |||
466 | orientation = Math.abs(window.orientation) == 90 ? 'landscape' : 'portrait'; | ||
467 | $body.removeClass('portrait landscape').addClass(orientation).trigger('turn', {orientation: orientation}); | ||
468 | } | ||
469 | function setHash(hash) { | ||
470 | // Sanitize | ||
471 | location.hash = '#' + hash.replace(/^#/, ''); | ||
472 | } | ||
473 | function showPageByHref(href, options) { | ||
474 | |||
475 | var defaults = { | ||
476 | data: null, | ||
477 | method: 'GET', | ||
478 | animation: null, | ||
479 | callback: null, | ||
480 | $referrer: null | ||
481 | }; | ||
482 | |||
483 | var settings = $.extend({}, defaults, options); | ||
484 | |||
485 | if (href != '#') { | ||
486 | $.ajax({ | ||
487 | url: href, | ||
488 | data: settings.data, | ||
489 | type: settings.method, | ||
490 | success: function (data) { | ||
491 | var firstPage = insertPages(data, settings.animation); | ||
492 | if (firstPage) { | ||
493 | if (settings.method == 'GET' && jQTSettings.cacheGetRequests === true && settings.$referrer) { | ||
494 | settings.$referrer.attr('href', '#' + firstPage.attr('id')); | ||
495 | } | ||
496 | if (settings.callback) { | ||
497 | settings.callback(true); | ||
498 | } | ||
499 | } | ||
500 | }, | ||
501 | error: function (data) { | ||
502 | if (settings.$referrer) { | ||
503 | settings.$referrer.unselect(); | ||
504 | } | ||
505 | if (settings.callback) { | ||
506 | settings.callback(false); | ||
507 | } | ||
508 | } | ||
509 | }); | ||
510 | } else if (settings.$referrer) { | ||
511 | settings.$referrer.unselect(); | ||
512 | } | ||
513 | } | ||
514 | function submitHandler(e, callback) { | ||
515 | |||
516 | $(':focus').trigger('blur'); | ||
517 | |||
518 | e.preventDefault(); | ||
519 | |||
520 | var $form = (typeof(e)==='string') ? $(e).eq(0) : (e.target ? $(e.target) : $(e)); | ||
521 | |||
522 | if ($form.length && $form.is(jQTSettings.formSelector) && $form.attr('action')) { | ||
523 | showPageByHref($form.attr('action'), { | ||
524 | data: $form.serialize(), | ||
525 | method: $form.attr('method') || "POST", | ||
526 | animation: getAnimation($form), | ||
527 | callback: callback | ||
528 | }); | ||
529 | return false; | ||
530 | } | ||
531 | return true; | ||
532 | } | ||
533 | function submitParentForm($el) { | ||
534 | |||
535 | var $form = $el.closest('form'); | ||
536 | if ($form.length === 0) { | ||
537 | warn('No parent form found'); | ||
538 | } else { | ||
539 | warn('About to submit parent form'); | ||
540 | $form.trigger('submit'); | ||
541 | return false; | ||
542 | } | ||
543 | return true; | ||
544 | } | ||
545 | function supportForTransform3d() { | ||
546 | |||
547 | var head, body, style, div, result; | ||
548 | |||
549 | head = document.getElementsByTagName('head')[0]; | ||
550 | body = document.body; | ||
551 | |||
552 | style = document.createElement('style'); | ||
553 | style.textContent = '@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-webkit-transform-3d){#jqt-3dtest{height:3px}}'; | ||
554 | |||
555 | div = document.createElement('div'); | ||
556 | div.id = 'jqt-3dtest'; | ||
557 | |||
558 | // Add to the page | ||
559 | head.appendChild(style); | ||
560 | body.appendChild(div); | ||
561 | |||
562 | // Check the result | ||
563 | result = div.offsetHeight === 3; | ||
564 | |||
565 | // Clean up | ||
566 | style.parentNode.removeChild(style); | ||
567 | div.parentNode.removeChild(div); | ||
568 | |||
569 | // Pass back result | ||
570 | warn('Support for 3d transforms: ' + result); | ||
571 | return result; | ||
572 | } | ||
573 | function supportIOS5() { | ||
574 | var support = false; | ||
575 | var REGEX_IOS_VERSION = /OS (\d+)(_\d+)* like Mac OS X/i; | ||
576 | |||
577 | var agentString = window.navigator.userAgent; | ||
578 | if (REGEX_IOS_VERSION.test(agentString)) { | ||
579 | support = (REGEX_IOS_VERSION.exec(agentString)[1] >= 5); | ||
580 | } | ||
581 | return support; | ||
582 | } | ||
583 | function touchStartHandler(e){ | ||
584 | |||
585 | var $el = $(e.target), | ||
586 | selectors = touchSelectors.join(', '); | ||
587 | |||
588 | // Find the nearest tappable ancestor | ||
589 | if (!$el.is(selectors)) { | ||
590 | $el = $el.closest(selectors); | ||
591 | } | ||
592 | |||
593 | // Make sure we have a tappable element | ||
594 | if ($el.length && $el.attr('href')) { | ||
595 | $el.addClass('active'); | ||
596 | } | ||
597 | |||
598 | // Remove our active class if we move | ||
599 | $el.on($.support.touch ? 'touchmove' : 'mousemove', function(){ | ||
600 | $el.removeClass('active'); | ||
601 | }); | ||
602 | |||
603 | $el.on('touchend', function(){ | ||
604 | $el.unbind('touchmove mousemove'); | ||
605 | }); | ||
606 | |||
607 | } | ||
608 | function tapHandler(e){ | ||
609 | |||
610 | if (e.isDefaultPrevented()) { | ||
611 | return true; | ||
612 | } | ||
613 | |||
614 | // Grab the target element | ||
615 | var $el = $(e.target); | ||
616 | |||
617 | // Find the nearest tappable ancestor | ||
618 | if (!$el.is(touchSelectors.join(', '))) { | ||
619 | $el = $el.closest(touchSelectors.join(', ')); | ||
620 | } | ||
621 | |||
622 | // Make sure we have a tappable element | ||
623 | if (!$el.length || !$el.attr('href')) { | ||
624 | warn('Could not find a link related to tapped element'); | ||
625 | return true; | ||
626 | } | ||
627 | |||
628 | // Init some vars | ||
629 | var target = $el.attr('target'), | ||
630 | hash = $el.prop('hash'), | ||
631 | href = $el.attr('href'); | ||
632 | |||
633 | var params = { | ||
634 | e: e, | ||
635 | $el: $el, | ||
636 | target: target, | ||
637 | hash: hash, | ||
638 | href: href, | ||
639 | jQTSettings: jQTSettings | ||
640 | }; | ||
641 | |||
642 | // Loop thru all handlers | ||
643 | for (var i=0, len=tapHandlers.length; i<len; i++) { | ||
644 | var handler = tapHandlers[i]; | ||
645 | var supported = handler.isSupported(e, params); | ||
646 | if (supported) { | ||
647 | var flag = handler.fn(e, params); | ||
648 | return flag; | ||
649 | } | ||
650 | } | ||
651 | } | ||
652 | function addDefaultTapHandlers() { | ||
653 | addTapHandler({ | ||
654 | name: 'external-link', | ||
655 | isSupported: function(e, params) { | ||
656 | return params.$el.isExternalLink(); | ||
657 | }, | ||
658 | fn: function(e, params) { | ||
659 | params.$el.unselect(); | ||
660 | return true; | ||
661 | } | ||
662 | }); | ||
663 | addTapHandler({ | ||
664 | name: 'back-selector', | ||
665 | isSupported: function(e, params) { | ||
666 | return params.$el.is(params.jQTSettings.backSelector); | ||
667 | }, | ||
668 | fn: function(e, params) { | ||
669 | // User clicked or tapped a back button | ||
670 | goBack(params.hash); | ||
671 | } | ||
672 | }); | ||
673 | addTapHandler({ | ||
674 | name: 'submit-selector', | ||
675 | isSupported: function(e, params) { | ||
676 | return params.$el.is(params.jQTSettings.submitSelector); | ||
677 | }, | ||
678 | fn: function(e, params) { | ||
679 | // User clicked or tapped a submit element | ||
680 | submitParentForm(params.$el); | ||
681 | } | ||
682 | }); | ||
683 | addTapHandler({ | ||
684 | name: 'webapp', | ||
685 | isSupported: function(e, params) { | ||
686 | return params.target === '_webapp'; | ||
687 | }, | ||
688 | fn: function(e, params) { | ||
689 | // User clicked or tapped an internal link, fullscreen mode | ||
690 | window.location = params.href; | ||
691 | return false; | ||
692 | } | ||
693 | }); | ||
694 | addTapHandler({ | ||
695 | name: 'no-op', | ||
696 | isSupported: function(e, params) { | ||
697 | return params.href === '#'; | ||
698 | }, | ||
699 | fn: function(e, params) { | ||
700 | // Allow tap on item with no href | ||
701 | params.$el.unselect(); | ||
702 | return true; | ||
703 | } | ||
704 | }); | ||
705 | addTapHandler({ | ||
706 | name: 'standard', | ||
707 | isSupported: function(e, params) { | ||
708 | return params.hash && params.hash !== '#'; | ||
709 | }, | ||
710 | fn: function(e, params) { | ||
711 | var animation = getAnimation(params.$el); | ||
712 | // Internal href | ||
713 | params.$el.addClass('active'); | ||
714 | goTo( | ||
715 | $(params.hash).data('referrer', params.$el), | ||
716 | animation, | ||
717 | params.$el.hasClass('reverse') | ||
718 | ); | ||
719 | return false; | ||
720 | } | ||
721 | }); | ||
722 | addTapHandler({ | ||
723 | name: 'external', | ||
724 | isSupported: function(e, params) { | ||
725 | return true; | ||
726 | }, | ||
727 | fn: function(e, params) { | ||
728 | var animation = getAnimation(params.$el); | ||
729 | |||
730 | // External href | ||
731 | params.$el.addClass('loading active'); | ||
732 | showPageByHref(params.$el.attr('href'), { | ||
733 | animation: animation, | ||
734 | callback: function() { | ||
735 | params.$el.removeClass('loading'); | ||
736 | setTimeout($.fn.unselect, 250, params.$el); | ||
737 | }, | ||
738 | $referrer: params.$el | ||
739 | }); | ||
740 | return false; | ||
741 | } | ||
742 | }); | ||
743 | }; | ||
744 | |||
745 | // Get the party started | ||
746 | init(options); | ||
747 | |||
748 | // Document ready stuff | ||
749 | $(document).ready(function RUMBLE() { | ||
750 | // Store some properties in a support object | ||
751 | if (!$.support) $.support = {}; | ||
752 | $.support.animationEvents = (typeof window.WebKitAnimationEvent != 'undefined'); | ||
753 | $.support.touch = (typeof window.TouchEvent != 'undefined') && (window.navigator.userAgent.indexOf('Mobile') > -1) && jQTSettings.useFastTouch; | ||
754 | $.support.transform3d = supportForTransform3d(); | ||
755 | $.support.ios5 = supportIOS5(); | ||
756 | |||
757 | if (!$.support.touch) { | ||
758 | warn('This device does not support touch interaction, or it has been deactivated by the developer. Some features might be unavailable.'); | ||
759 | } | ||
760 | if (!$.support.transform3d) { | ||
761 | warn('This device does not support 3d animation. 2d animations will be used instead.'); | ||
762 | } | ||
763 | |||
764 | // Define public jQuery functions | ||
765 | $.fn.isExternalLink = function() { | ||
766 | var $el = $(this); | ||
767 | return ($el.attr('target') == '_blank' || $el.attr('rel') == 'external' || $el.is('a[href^="http://maps.google.com"], a[href^="mailto:"], a[href^="tel:"], a[href^="javascript:"], a[href*="youtube.com/v"], a[href*="youtube.com/watch"]')); | ||
768 | }; | ||
769 | $.fn.makeActive = function() { | ||
770 | return $(this).addClass('active'); | ||
771 | }; | ||
772 | $.fn.unselect = function(obj) { | ||
773 | if (obj) { | ||
774 | obj.removeClass('active'); | ||
775 | } else { | ||
776 | $('.active').removeClass('active'); | ||
777 | } | ||
778 | }; | ||
779 | |||
780 | // Add extensions | ||
781 | for (var i=0, max=extensions.length; i < max; i++) { | ||
782 | var fn = extensions[i]; | ||
783 | if ($.isFunction(fn)) { | ||
784 | $.extend(publicObj, fn(publicObj)); | ||
785 | } | ||
786 | } | ||
787 | |||
788 | // Add extensions tapHandlers | ||
789 | for (var i=0, max=extTapHandlers.length; i < max; i++) { | ||
790 | addTapHandler(extTapHandlers[i]); | ||
791 | } | ||
792 | // Add default tapHandlers | ||
793 | addDefaultTapHandlers(); | ||
794 | |||
795 | // Add animations | ||
796 | for (var j=0, max_anims=defaults.animations.length; j < max_anims; j++) { | ||
797 | var animation = defaults.animations[j]; | ||
798 | if(jQTSettings[animation.name + 'Selector'] !== undefined){ | ||
799 | animation.selector = jQTSettings[animation.name + 'Selector']; | ||
800 | } | ||
801 | addAnimation(animation); | ||
802 | } | ||
803 | |||
804 | // Create an array of stuff that needs touch event handling | ||
805 | touchSelectors.push(jQTSettings.touchSelector); | ||
806 | touchSelectors.push(jQTSettings.backSelector); | ||
807 | touchSelectors.push(jQTSettings.submitSelector); | ||
808 | $(touchSelectors.join(', ')).css('-webkit-touch-callout', 'none'); | ||
809 | |||
810 | // Make sure we have a jqt element | ||
811 | $body = $('#jqt'); | ||
812 | var anatomy_lessons = []; | ||
813 | |||
814 | if ($body.length === 0) { | ||
815 | warn('Could not find an element with the id "jqt", so the body id has been set to "jqt". If you are having any problems, wrapping your panels in a div with the id "jqt" might help.'); | ||
816 | $body = $(document.body).attr('id', 'jqt'); | ||
817 | } | ||
818 | |||
819 | // Add some specific css if need be | ||
820 | if ($.support.transform3d) { | ||
821 | anatomy_lessons.push('supports3d'); | ||
822 | } | ||
823 | if ($.support.ios5 && jQTSettings.useTouchScroll) { | ||
824 | anatomy_lessons.push('touchscroll'); | ||
825 | } | ||
826 | |||
827 | if (jQTSettings.fullScreenClass && window.navigator.standalone === true) { | ||
828 | anatomy_lessons.push(jQTSettings.fullScreenClass, jQTSettings.statusBar); | ||
829 | } | ||
830 | |||
831 | // Bind events | ||
832 | |||
833 | $body | ||
834 | .addClass(anatomy_lessons.join(' ')) | ||
835 | .bind('click', clickHandler) | ||
836 | .bind('orientationchange', orientationChangeHandler) | ||
837 | .bind('submit', submitHandler) | ||
838 | .bind('tap', tapHandler) | ||
839 | .bind( $.support.touch ? 'touchstart' : 'mousedown', touchStartHandler) | ||
840 | .trigger('orientationchange'); | ||
841 | |||
842 | $(window).bind('hashchange', hashChangeHandler); | ||
843 | |||
844 | var startHash = location.hash; | ||
845 | |||
846 | // Determine what the initial view should be | ||
847 | if ($('#jqt > .current').length === 0) { | ||
848 | $currentPage = $('#jqt > *:first-child').addClass('current'); | ||
849 | } else { | ||
850 | $currentPage = $('#jqt > .current'); | ||
851 | } | ||
852 | |||
853 | setHash($currentPage.attr('id')); | ||
854 | addPageToHistory($currentPage); | ||
855 | |||
856 | if ($(startHash).length === 1) { | ||
857 | goTo(startHash); | ||
858 | } | ||
859 | }); | ||
860 | |||
861 | // Expose public methods and properties | ||
862 | publicObj = { | ||
863 | addAnimation: addAnimation, | ||
864 | animations: animations, | ||
865 | getOrientation: getOrientation, | ||
866 | goBack: goBack, | ||
867 | insertPages: insertPages, | ||
868 | goTo: goTo, | ||
869 | history: history, | ||
870 | settings: jQTSettings, | ||
871 | submitForm: submitHandler | ||
872 | }; | ||
873 | return publicObj; | ||
874 | }; | ||
875 | |||
876 | $.jQTouch.prototype.extensions = []; | ||
877 | $.jQTouch.prototype.tapHandlers = []; | ||
878 | |||
879 | // Extensions directly manipulate the jQTouch object, before it's initialized. | ||
880 | $.jQTouch.addExtension = function(extension) { | ||
881 | $.jQTouch.prototype.extensions.push(extension); | ||
882 | }; | ||
883 | |||
884 | // Experimental tap hanlders that can bypass default jQTouch tap handling | ||
885 | $.jQTouch.addTapHandler = function(extension) { | ||
886 | $.jQTouch.prototype.tapHandlers.push(extension); | ||
887 | }; | ||
888 | |||
889 | })(); // Double closure, ALL THE WAY ACROSS THE SKY | ||