summaryrefslogtreecommitdiff
path: root/frontend
Unidiff
Diffstat (limited to 'frontend') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js159
-rw-r--r--frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js52
-rw-r--r--frontend/gamma/js/JQTouch/extensions/jqt.floaty.js96
-rw-r--r--frontend/gamma/js/JQTouch/extensions/jqt.location.js51
-rw-r--r--frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js137
-rw-r--r--frontend/gamma/js/JQTouch/extensions/jqt.offline.js97
-rwxr-xr-xfrontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js123
-rw-r--r--frontend/gamma/js/JQTouch/jqtouch.js889
-rw-r--r--frontend/gamma/js/Zepto/ajax.js285
-rw-r--r--frontend/gamma/js/Zepto/assets.js21
-rw-r--r--frontend/gamma/js/Zepto/data.js67
-rw-r--r--frontend/gamma/js/Zepto/detect.js42
-rw-r--r--frontend/gamma/js/Zepto/event.js248
-rw-r--r--frontend/gamma/js/Zepto/form.js40
-rw-r--r--frontend/gamma/js/Zepto/fx.js102
-rw-r--r--frontend/gamma/js/Zepto/fx_methods.js71
-rw-r--r--frontend/gamma/js/Zepto/gesture.js35
-rw-r--r--frontend/gamma/js/Zepto/polyfill.js36
-rw-r--r--frontend/gamma/js/Zepto/selector.js81
-rw-r--r--frontend/gamma/js/Zepto/stack.js22
-rw-r--r--frontend/gamma/js/Zepto/touch.js113
-rw-r--r--frontend/gamma/js/Zepto/zepto.js751
22 files changed, 3518 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
diff --git a/frontend/gamma/js/Zepto/ajax.js b/frontend/gamma/js/Zepto/ajax.js
new file mode 100644
index 0000000..f4da150
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/ajax.js
@@ -0,0 +1,285 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 var jsonpID = 0,
7 isObject = $.isObject,
8 document = window.document,
9 key,
10 name,
11 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
12 scriptTypeRE = /^(?:text|application)\/javascript/i,
13 xmlTypeRE = /^(?:text|application)\/xml/i,
14 jsonType = 'application/json',
15 htmlType = 'text/html',
16 blankRE = /^\s*$/
17
18 // trigger a custom event and return false if it was cancelled
19 function triggerAndReturn(context, eventName, data) {
20 var event = $.Event(eventName)
21 $(context).trigger(event, data)
22 return !event.defaultPrevented
23 }
24
25 // trigger an Ajax "global" event
26 function triggerGlobal(settings, context, eventName, data) {
27 if (settings.global) return triggerAndReturn(context || document, eventName, data)
28 }
29
30 // Number of active Ajax requests
31 $.active = 0
32
33 function ajaxStart(settings) {
34 if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart')
35 }
36 function ajaxStop(settings) {
37 if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')
38 }
39
40 // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
41 function ajaxBeforeSend(xhr, settings) {
42 var context = settings.context
43 if (settings.beforeSend.call(context, xhr, settings) === false ||
44 triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)
45 return false
46
47 triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])
48 }
49 function ajaxSuccess(data, xhr, settings) {
50 var context = settings.context, status = 'success'
51 settings.success.call(context, data, status, xhr)
52 triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data])
53 ajaxComplete(status, xhr, settings)
54 }
55 // type: "timeout", "error", "abort", "parsererror"
56 function ajaxError(error, type, xhr, settings) {
57 var context = settings.context
58 settings.error.call(context, xhr, type, error)
59 triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error])
60 ajaxComplete(type, xhr, settings)
61 }
62 // status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
63 function ajaxComplete(status, xhr, settings) {
64 var context = settings.context
65 settings.complete.call(context, xhr, status)
66 triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings])
67 ajaxStop(settings)
68 }
69
70 // Empty function, used as default callback
71 function empty() {}
72
73 $.ajaxJSONP = function(options){
74 if (!('type' in options)) return $.ajax(options)
75
76 var callbackName = 'jsonp' + (++jsonpID),
77 script = document.createElement('script'),
78 abort = function(){
79 $(script).remove()
80 if (callbackName in window) window[callbackName] = empty
81 ajaxComplete('abort', xhr, options)
82 },
83 xhr = { abort: abort }, abortTimeout
84
85 if (options.error) script.onerror = function() {
86 xhr.abort()
87 options.error()
88 }
89
90 window[callbackName] = function(data){
91 clearTimeout(abortTimeout)
92 $(script).remove()
93 delete window[callbackName]
94 ajaxSuccess(data, xhr, options)
95 }
96
97 serializeData(options)
98 script.src = options.url.replace(/=\?/, '=' + callbackName)
99 $('head').append(script)
100
101 if (options.timeout > 0) abortTimeout = setTimeout(function(){
102 xhr.abort()
103 ajaxComplete('timeout', xhr, options)
104 }, options.timeout)
105
106 return xhr
107 }
108
109 $.ajaxSettings = {
110 // Default type of request
111 type: 'GET',
112 // Callback that is executed before request
113 beforeSend: empty,
114 // Callback that is executed if the request succeeds
115 success: empty,
116 // Callback that is executed the the server drops error
117 error: empty,
118 // Callback that is executed on request complete (both: error and success)
119 complete: empty,
120 // The context for the callbacks
121 context: null,
122 // Whether to trigger "global" Ajax events
123 global: true,
124 // Transport
125 xhr: function () {
126 return new window.XMLHttpRequest()
127 },
128 // MIME types mapping
129 accepts: {
130 script: 'text/javascript, application/javascript',
131 json: jsonType,
132 xml: 'application/xml, text/xml',
133 html: htmlType,
134 text: 'text/plain'
135 },
136 // Whether the request is to another domain
137 crossDomain: false,
138 // Default timeout
139 timeout: 0,
140 // Whether data should be serialized to string
141 processData: true
142 }
143
144 function mimeToDataType(mime) {
145 return mime && ( mime == htmlType ? 'html' :
146 mime == jsonType ? 'json' :
147 scriptTypeRE.test(mime) ? 'script' :
148 xmlTypeRE.test(mime) && 'xml' ) || 'text'
149 }
150
151 function appendQuery(url, query) {
152 return (url + '&' + query).replace(/[&?]{1,2}/, '?')
153 }
154
155 // serialize payload and append it to the URL for GET requests
156 function serializeData(options) {
157 if (options.processData && isObject(options.data))
158 options.data = $.param(options.data, options.traditional)
159 if (options.data && (!options.type || options.type.toUpperCase() == 'GET'))
160 options.url = appendQuery(options.url, options.data)
161 }
162
163 $.ajax = function(options){
164 var settings = $.extend({}, options || {})
165 for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key]
166
167 ajaxStart(settings)
168
169 if (!settings.crossDomain) settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) &&
170 RegExp.$2 != window.location.host
171
172 var dataType = settings.dataType, hasPlaceholder = /=\?/.test(settings.url)
173 if (dataType == 'jsonp' || hasPlaceholder) {
174 if (!hasPlaceholder) settings.url = appendQuery(settings.url, 'callback=?')
175 return $.ajaxJSONP(settings)
176 }
177
178 if (!settings.url) settings.url = window.location.toString()
179 serializeData(settings)
180
181 var mime = settings.accepts[dataType],
182 baseHeaders = { },
183 protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol,
184 xhr = $.ajaxSettings.xhr(), abortTimeout
185
186 if (!settings.crossDomain) baseHeaders['X-Requested-With'] = 'XMLHttpRequest'
187 if (mime) {
188 baseHeaders['Accept'] = mime
189 if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0]
190 xhr.overrideMimeType && xhr.overrideMimeType(mime)
191 }
192 if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET'))
193 baseHeaders['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded')
194 settings.headers = $.extend(baseHeaders, settings.headers || {})
195
196 xhr.onreadystatechange = function(){
197 if (xhr.readyState == 4) {
198 xhr.onreadystatechange = empty;
199 clearTimeout(abortTimeout)
200 var result, error = false
201 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) {
202 dataType = dataType || mimeToDataType(xhr.getResponseHeader('content-type'))
203 result = xhr.responseText
204
205 try {
206 if (dataType == 'script') (1,eval)(result)
207 else if (dataType == 'xml') result = xhr.responseXML
208 else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result)
209 } catch (e) { error = e }
210
211 if (error) ajaxError(error, 'parsererror', xhr, settings)
212 else ajaxSuccess(result, xhr, settings)
213 } else {
214 ajaxError(null, xhr.status ? 'error' : 'abort', xhr, settings)
215 }
216 }
217 }
218
219 var async = 'async' in settings ? settings.async : true
220 xhr.open(settings.type, settings.url, async)
221
222 for (name in settings.headers) xhr.setRequestHeader(name, settings.headers[name])
223
224 if (ajaxBeforeSend(xhr, settings) === false) {
225 xhr.abort()
226 return false
227 }
228
229 if (settings.timeout > 0) abortTimeout = setTimeout(function(){
230 xhr.onreadystatechange = empty
231 xhr.abort()
232 ajaxError(null, 'timeout', xhr, settings)
233 }, settings.timeout)
234
235 // avoid sending empty string (#319)
236 xhr.send(settings.data ? settings.data : null)
237 return xhr
238 }
239
240 $.get = function(url, success){ return $.ajax({ url: url, success: success }) }
241
242 $.post = function(url, data, success, dataType){
243 if ($.isFunction(data)) dataType = dataType || success, success = data, data = null
244 return $.ajax({ type: 'POST', url: url, data: data, success: success, dataType: dataType })
245 }
246
247 $.getJSON = function(url, success){
248 return $.ajax({ url: url, success: success, dataType: 'json' })
249 }
250
251 $.fn.load = function(url, success){
252 if (!this.length) return this
253 var self = this, parts = url.split(/\s/), selector
254 if (parts.length > 1) url = parts[0], selector = parts[1]
255 $.get(url, function(response){
256 self.html(selector ?
257 $('<div>').html(response.replace(rscript, "")).find(selector)
258 : response)
259 success && success.apply(self, arguments)
260 })
261 return this
262 }
263
264 var escape = encodeURIComponent
265
266 function serialize(params, obj, traditional, scope){
267 var array = $.isArray(obj)
268 $.each(obj, function(key, value) {
269 if (scope) key = traditional ? scope : scope + '[' + (array ? '' : key) + ']'
270 // handle data in serializeArray() format
271 if (!scope && array) params.add(value.name, value.value)
272 // recurse into nested objects
273 else if (traditional ? $.isArray(value) : isObject(value))
274 serialize(params, value, traditional, key)
275 else params.add(key, value)
276 })
277 }
278
279 $.param = function(obj, traditional){
280 var params = []
281 params.add = function(k, v){ this.push(escape(k) + '=' + escape(v)) }
282 serialize(params, obj, traditional)
283 return params.join('&').replace(/%20/g, '+')
284 }
285})(Zepto)
diff --git a/frontend/gamma/js/Zepto/assets.js b/frontend/gamma/js/Zepto/assets.js
new file mode 100644
index 0000000..b5a5712
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/assets.js
@@ -0,0 +1,21 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 var cache = [], timeout
7
8 $.fn.remove = function(){
9 return this.each(function(){
10 if(this.parentNode){
11 if(this.tagName === 'IMG'){
12 cache.push(this)
13 this.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
14 if (timeout) clearTimeout(timeout)
15 timeout = setTimeout(function(){ cache = [] }, 60000)
16 }
17 this.parentNode.removeChild(this)
18 }
19 })
20 }
21})(Zepto)
diff --git a/frontend/gamma/js/Zepto/data.js b/frontend/gamma/js/Zepto/data.js
new file mode 100644
index 0000000..b4c289f
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/data.js
@@ -0,0 +1,67 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5// The following code is heavily inspired by jQuery's $.fn.data()
6
7;(function($) {
8 var data = {}, dataAttr = $.fn.data, camelize = $.camelCase,
9 exp = $.expando = 'Zepto' + (+new Date())
10
11 // Get value from node:
12 // 1. first try key as given,
13 // 2. then try camelized key,
14 // 3. fall back to reading "data-*" attribute.
15 function getData(node, name) {
16 var id = node[exp], store = id && data[id]
17 if (name === undefined) return store || setData(node)
18 else {
19 if (store) {
20 if (name in store) return store[name]
21 var camelName = camelize(name)
22 if (camelName in store) return store[camelName]
23 }
24 return dataAttr.call($(node), name)
25 }
26 }
27
28 // Store value under camelized key on node
29 function setData(node, name, value) {
30 var id = node[exp] || (node[exp] = ++$.uuid),
31 store = data[id] || (data[id] = attributeData(node))
32 if (name !== undefined) store[camelize(name)] = value
33 return store
34 }
35
36 // Read all "data-*" attributes from a node
37 function attributeData(node) {
38 var store = {}
39 $.each(node.attributes, function(i, attr){
40 if (attr.name.indexOf('data-') == 0)
41 store[camelize(attr.name.replace('data-', ''))] =
42 $.zepto.deserializeValue(attr.value)
43 })
44 return store
45 }
46
47 $.fn.data = function(name, value) {
48 return value === undefined ?
49 // set multiple values via object
50 $.isPlainObject(name) ?
51 this.each(function(i, node){
52 $.each(name, function(key, value){ setData(node, key, value) })
53 }) :
54 // get value from first element
55 this.length == 0 ? undefined : getData(this[0], name) :
56 // set value on all elements
57 this.each(function(){ setData(this, name, value) })
58 }
59
60 $.fn.removeData = function(names) {
61 if (typeof names == 'string') names = names.split(/\s+/)
62 return this.each(function(){
63 var id = this[exp], store = id && data[id]
64 if (store) $.each(names, function(){ delete store[camelize(this)] })
65 })
66 }
67})(Zepto)
diff --git a/frontend/gamma/js/Zepto/detect.js b/frontend/gamma/js/Zepto/detect.js
new file mode 100644
index 0000000..22c0386
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/detect.js
@@ -0,0 +1,42 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 function detect(ua){
7 var os = this.os = {}, browser = this.browser = {},
8 webkit = ua.match(/WebKit\/([\d.]+)/),
9 android = ua.match(/(Android)\s+([\d.]+)/),
10 ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
11 iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
12 webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),
13 touchpad = webos && ua.match(/TouchPad/),
14 kindle = ua.match(/Kindle\/([\d.]+)/),
15 silk = ua.match(/Silk\/([\d._]+)/),
16 blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/),
17 chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/)
18
19 // todo clean this up with a better OS/browser
20 // separation. we need to discern between multiple
21 // browsers on android, and decide if kindle fire in
22 // silk mode is android or not
23
24 if (browser.webkit = !!webkit) browser.version = webkit[1]
25
26 if (android) os.android = true, os.version = android[2]
27 if (iphone) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.')
28 if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.')
29 if (webos) os.webos = true, os.version = webos[2]
30 if (touchpad) os.touchpad = true
31 if (blackberry) os.blackberry = true, os.version = blackberry[2]
32 if (kindle) os.kindle = true, os.version = kindle[1]
33 if (silk) browser.silk = true, browser.version = silk[1]
34 if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true
35 if (chrome) browser.chrome = true, browser.version = chrome[1]
36 }
37
38 detect.call($, navigator.userAgent)
39 // make available to unit tests
40 $.__detect = detect
41
42})(Zepto)
diff --git a/frontend/gamma/js/Zepto/event.js b/frontend/gamma/js/Zepto/event.js
new file mode 100644
index 0000000..b40af22
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/event.js
@@ -0,0 +1,248 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 var $$ = $.zepto.qsa, handlers = {}, _zid = 1, specialEvents={},
7 hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }
8
9 specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'
10
11 function zid(element) {
12 return element._zid || (element._zid = _zid++)
13 }
14 function findHandlers(element, event, fn, selector) {
15 event = parse(event)
16 if (event.ns) var matcher = matcherFor(event.ns)
17 return (handlers[zid(element)] || []).filter(function(handler) {
18 return handler
19 && (!event.e || handler.e == event.e)
20 && (!event.ns || matcher.test(handler.ns))
21 && (!fn || zid(handler.fn) === zid(fn))
22 && (!selector || handler.sel == selector)
23 })
24 }
25 function parse(event) {
26 var parts = ('' + event).split('.')
27 return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
28 }
29 function matcherFor(ns) {
30 return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
31 }
32
33 function eachEvent(events, fn, iterator){
34 if ($.isObject(events)) $.each(events, iterator)
35 else events.split(/\s/).forEach(function(type){ iterator(type, fn) })
36 }
37
38 function eventCapture(handler, captureSetting) {
39 return handler.del &&
40 (handler.e == 'focus' || handler.e == 'blur') ||
41 !!captureSetting
42 }
43
44 function realEvent(type) {
45 return hover[type] || type
46 }
47
48 function add(element, events, fn, selector, getDelegate, capture){
49 var id = zid(element), set = (handlers[id] || (handlers[id] = []))
50 eachEvent(events, fn, function(event, fn){
51 var handler = parse(event)
52 handler.fn = fn
53 handler.sel = selector
54 // emulate mouseenter, mouseleave
55 if (handler.e in hover) fn = function(e){
56 var related = e.relatedTarget
57 if (!related || (related !== this && !$.contains(this, related)))
58 return handler.fn.apply(this, arguments)
59 }
60 handler.del = getDelegate && getDelegate(fn, event)
61 var callback = handler.del || fn
62 handler.proxy = function (e) {
63 var result = callback.apply(element, [e].concat(e.data))
64 if (result === false) e.preventDefault(), e.stopPropagation()
65 return result
66 }
67 handler.i = set.length
68 set.push(handler)
69 element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
70 })
71 }
72 function remove(element, events, fn, selector, capture){
73 var id = zid(element)
74 eachEvent(events || '', fn, function(event, fn){
75 findHandlers(element, event, fn, selector).forEach(function(handler){
76 delete handlers[id][handler.i]
77 element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
78 })
79 })
80 }
81
82 $.event = { add: add, remove: remove }
83
84 $.proxy = function(fn, context) {
85 if ($.isFunction(fn)) {
86 var proxyFn = function(){ return fn.apply(context, arguments) }
87 proxyFn._zid = zid(fn)
88 return proxyFn
89 } else if (typeof context == 'string') {
90 return $.proxy(fn[context], fn)
91 } else {
92 throw new TypeError("expected function")
93 }
94 }
95
96 $.fn.bind = function(event, callback){
97 return this.each(function(){
98 add(this, event, callback)
99 })
100 }
101 $.fn.unbind = function(event, callback){
102 return this.each(function(){
103 remove(this, event, callback)
104 })
105 }
106 $.fn.one = function(event, callback){
107 return this.each(function(i, element){
108 add(this, event, callback, null, function(fn, type){
109 return function(){
110 var result = fn.apply(element, arguments)
111 remove(element, type, fn)
112 return result
113 }
114 })
115 })
116 }
117
118 var returnTrue = function(){return true},
119 returnFalse = function(){return false},
120 ignoreProperties = /^([A-Z]|layer[XY]$)/,
121 eventMethods = {
122 preventDefault: 'isDefaultPrevented',
123 stopImmediatePropagation: 'isImmediatePropagationStopped',
124 stopPropagation: 'isPropagationStopped'
125 }
126 function createProxy(event) {
127 var key, proxy = { originalEvent: event }
128 for (key in event)
129 if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]
130
131 $.each(eventMethods, function(name, predicate) {
132 proxy[name] = function(){
133 this[predicate] = returnTrue
134 return event[name].apply(event, arguments)
135 }
136 proxy[predicate] = returnFalse
137 })
138 return proxy
139 }
140
141 // emulates the 'defaultPrevented' property for browsers that have none
142 function fix(event) {
143 if (!('defaultPrevented' in event)) {
144 event.defaultPrevented = false
145 var prevent = event.preventDefault
146 event.preventDefault = function() {
147 this.defaultPrevented = true
148 prevent.call(this)
149 }
150 }
151 }
152
153 $.fn.delegate = function(selector, event, callback){
154 return this.each(function(i, element){
155 add(element, event, callback, selector, function(fn){
156 return function(e){
157 var evt, match = $(e.target).closest(selector, element).get(0)
158 if (match) {
159 evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
160 return fn.apply(match, [evt].concat([].slice.call(arguments, 1)))
161 }
162 }
163 })
164 })
165 }
166 $.fn.undelegate = function(selector, event, callback){
167 return this.each(function(){
168 remove(this, event, callback, selector)
169 })
170 }
171
172 $.fn.live = function(event, callback){
173 $(document.body).delegate(this.selector, event, callback)
174 return this
175 }
176 $.fn.die = function(event, callback){
177 $(document.body).undelegate(this.selector, event, callback)
178 return this
179 }
180
181 $.fn.on = function(event, selector, callback){
182 return !selector || $.isFunction(selector) ?
183 this.bind(event, selector || callback) : this.delegate(selector, event, callback)
184 }
185 $.fn.off = function(event, selector, callback){
186 return !selector || $.isFunction(selector) ?
187 this.unbind(event, selector || callback) : this.undelegate(selector, event, callback)
188 }
189
190 $.fn.trigger = function(event, data){
191 if (typeof event == 'string' || $.isPlainObject(event)) event = $.Event(event)
192 fix(event)
193 event.data = data
194 return this.each(function(){
195 // items in the collection might not be DOM elements
196 // (todo: possibly support events on plain old objects)
197 if('dispatchEvent' in this) this.dispatchEvent(event)
198 })
199 }
200
201 // triggers event handlers on current element just as if an event occurred,
202 // doesn't trigger an actual event, doesn't bubble
203 $.fn.triggerHandler = function(event, data){
204 var e, result
205 this.each(function(i, element){
206 e = createProxy(typeof event == 'string' ? $.Event(event) : event)
207 e.data = data
208 e.target = element
209 $.each(findHandlers(element, event.type || event), function(i, handler){
210 result = handler.proxy(e)
211 if (e.isImmediatePropagationStopped()) return false
212 })
213 })
214 return result
215 }
216
217 // shortcut methods for `.bind(event, fn)` for each event type
218 ;('focusin focusout load resize scroll unload click dblclick '+
219 'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
220 'change select keydown keypress keyup error').split(' ').forEach(function(event) {
221 $.fn[event] = function(callback) {
222 return callback ?
223 this.bind(event, callback) :
224 this.trigger(event)
225 }
226 })
227
228 ;['focus', 'blur'].forEach(function(name) {
229 $.fn[name] = function(callback) {
230 if (callback) this.bind(name, callback)
231 else this.each(function(){
232 try { this[name]() }
233 catch(e) {}
234 })
235 return this
236 }
237 })
238
239 $.Event = function(type, props) {
240 if (typeof type != 'string') props = type, type = props.type
241 var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
242 if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
243 event.initEvent(type, bubbles, true, null, null, null, null, null, null, null, null, null, null, null, null)
244 event.isDefaultPrevented = function(){ return this.defaultPrevented }
245 return event
246 }
247
248})(Zepto)
diff --git a/frontend/gamma/js/Zepto/form.js b/frontend/gamma/js/Zepto/form.js
new file mode 100644
index 0000000..4d562a6
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/form.js
@@ -0,0 +1,40 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function ($) {
6 $.fn.serializeArray = function () {
7 var result = [], el
8 $( Array.prototype.slice.call(this.get(0).elements) ).each(function () {
9 el = $(this)
10 var type = el.attr('type')
11 if (this.nodeName.toLowerCase() != 'fieldset' &&
12 !this.disabled && type != 'submit' && type != 'reset' && type != 'button' &&
13 ((type != 'radio' && type != 'checkbox') || this.checked))
14 result.push({
15 name: el.attr('name'),
16 value: el.val()
17 })
18 })
19 return result
20 }
21
22 $.fn.serialize = function () {
23 var result = []
24 this.serializeArray().forEach(function (elm) {
25 result.push( encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value) )
26 })
27 return result.join('&')
28 }
29
30 $.fn.submit = function (callback) {
31 if (callback) this.bind('submit', callback)
32 else if (this.length) {
33 var event = $.Event('submit')
34 this.eq(0).trigger(event)
35 if (!event.defaultPrevented) this.get(0).submit()
36 }
37 return this
38 }
39
40})(Zepto)
diff --git a/frontend/gamma/js/Zepto/fx.js b/frontend/gamma/js/Zepto/fx.js
new file mode 100644
index 0000000..575449a
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/fx.js
@@ -0,0 +1,102 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($, undefined){
6 var prefix = '', eventPrefix, endEventName, endAnimationName,
7 vendors = { Webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' },
8 document = window.document, testEl = document.createElement('div'),
9 supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
10 transform,
11 transitionProperty, transitionDuration, transitionTiming,
12 animationName, animationDuration, animationTiming,
13 cssReset = {}
14
15 function dasherize(str) { return downcase(str.replace(/([a-z])([A-Z])/, '$1-$2')) }
16 function downcase(str) { return str.toLowerCase() }
17 function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : downcase(name) }
18
19 $.each(vendors, function(vendor, event){
20 if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
21 prefix = '-' + downcase(vendor) + '-'
22 eventPrefix = event
23 return false
24 }
25 })
26
27 transform = prefix + 'transform'
28 cssReset[transitionProperty = prefix + 'transition-property'] =
29 cssReset[transitionDuration = prefix + 'transition-duration'] =
30 cssReset[transitionTiming = prefix + 'transition-timing-function'] =
31 cssReset[animationName = prefix + 'animation-name'] =
32 cssReset[animationDuration = prefix + 'animation-duration'] =
33 cssReset[animationTiming = prefix + 'animation-timing-function'] = ''
34
35 $.fx = {
36 off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),
37 speeds: { _default: 400, fast: 200, slow: 600 },
38 cssPrefix: prefix,
39 transitionEnd: normalizeEvent('TransitionEnd'),
40 animationEnd: normalizeEvent('AnimationEnd')
41 }
42
43 $.fn.animate = function(properties, duration, ease, callback){
44 if ($.isObject(duration))
45 ease = duration.easing, callback = duration.complete, duration = duration.duration
46 if (duration) duration = (typeof duration == 'number' ? duration :
47 ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000
48 return this.anim(properties, duration, ease, callback)
49 }
50
51 $.fn.anim = function(properties, duration, ease, callback){
52 var key, cssValues = {}, cssProperties, transforms = '',
53 that = this, wrappedCallback, endEvent = $.fx.transitionEnd
54
55 if (duration === undefined) duration = 0.4
56 if ($.fx.off) duration = 0
57
58 if (typeof properties == 'string') {
59 // keyframe animation
60 cssValues[animationName] = properties
61 cssValues[animationDuration] = duration + 's'
62 cssValues[animationTiming] = (ease || 'linear')
63 endEvent = $.fx.animationEnd
64 } else {
65 cssProperties = []
66 // CSS transitions
67 for (key in properties)
68 if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') '
69 else cssValues[key] = properties[key], cssProperties.push(dasherize(key))
70
71 if (transforms) cssValues[transform] = transforms, cssProperties.push(transform)
72 if (duration > 0 && typeof properties === 'object') {
73 cssValues[transitionProperty] = cssProperties.join(', ')
74 cssValues[transitionDuration] = duration + 's'
75 cssValues[transitionTiming] = (ease || 'linear')
76 }
77 }
78
79 wrappedCallback = function(event){
80 if (typeof event !== 'undefined') {
81 if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below"
82 $(event.target).unbind(endEvent, arguments.callee)
83 }
84 $(this).css(cssReset)
85 callback && callback.call(this)
86 }
87 if (duration > 0) this.bind(endEvent, wrappedCallback)
88
89 // trigger page reflow so new elements can animate
90 this.size() && this.get(0).clientLeft
91
92 this.css(cssValues)
93
94 if (duration <= 0) setTimeout(function() {
95 that.each(function(){ wrappedCallback.call(this) })
96 }, 0)
97
98 return this
99 }
100
101 testEl = null
102})(Zepto)
diff --git a/frontend/gamma/js/Zepto/fx_methods.js b/frontend/gamma/js/Zepto/fx_methods.js
new file mode 100644
index 0000000..23daf6e
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/fx_methods.js
@@ -0,0 +1,71 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($, undefined){
6 var document = window.document, docElem = document.documentElement,
7 origShow = $.fn.show, origHide = $.fn.hide, origToggle = $.fn.toggle
8
9 function anim(el, speed, opacity, scale, callback) {
10 if (typeof speed == 'function' && !callback) callback = speed, speed = undefined
11 var props = { opacity: opacity }
12 if (scale) {
13 props.scale = scale
14 el.css($.fx.cssPrefix + 'transform-origin', '0 0')
15 }
16 return el.animate(props, speed, null, callback)
17 }
18
19 function hide(el, speed, scale, callback) {
20 return anim(el, speed, 0, scale, function(){
21 origHide.call($(this))
22 callback && callback.call(this)
23 })
24 }
25
26 $.fn.show = function(speed, callback) {
27 origShow.call(this)
28 if (speed === undefined) speed = 0
29 else this.css('opacity', 0)
30 return anim(this, speed, 1, '1,1', callback)
31 }
32
33 $.fn.hide = function(speed, callback) {
34 if (speed === undefined) return origHide.call(this)
35 else return hide(this, speed, '0,0', callback)
36 }
37
38 $.fn.toggle = function(speed, callback) {
39 if (speed === undefined || typeof speed == 'boolean')
40 return origToggle.call(this, speed)
41 else return this.each(function(){
42 var el = $(this)
43 el[el.css('display') == 'none' ? 'show' : 'hide'](speed, callback)
44 })
45 }
46
47 $.fn.fadeTo = function(speed, opacity, callback) {
48 return anim(this, speed, opacity, null, callback)
49 }
50
51 $.fn.fadeIn = function(speed, callback) {
52 var target = this.css('opacity')
53 if (target > 0) this.css('opacity', 0)
54 else target = 1
55 return origShow.call(this).fadeTo(speed, target, callback)
56 }
57
58 $.fn.fadeOut = function(speed, callback) {
59 return hide(this, speed, null, callback)
60 }
61
62 $.fn.fadeToggle = function(speed, callback) {
63 return this.each(function(){
64 var el = $(this)
65 el[
66 (el.css('opacity') == 0 || el.css('display') == 'none') ? 'fadeIn' : 'fadeOut'
67 ](speed, callback)
68 })
69 }
70
71})(Zepto)
diff --git a/frontend/gamma/js/Zepto/gesture.js b/frontend/gamma/js/Zepto/gesture.js
new file mode 100644
index 0000000..035455b
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/gesture.js
@@ -0,0 +1,35 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 if ($.os.ios) {
7 var gesture = {}, gestureTimeout
8
9 function parentIfText(node){
10 return 'tagName' in node ? node : node.parentNode
11 }
12
13 $(document).bind('gesturestart', function(e){
14 var now = Date.now(), delta = now - (gesture.last || now)
15 gesture.target = parentIfText(e.target)
16 gestureTimeout && clearTimeout(gestureTimeout)
17 gesture.e1 = e.scale
18 gesture.last = now
19 }).bind('gesturechange', function(e){
20 gesture.e2 = e.scale
21 }).bind('gestureend', function(e){
22 if (gesture.e2 > 0) {
23 Math.abs(gesture.e1 - gesture.e2) != 0 && $(gesture.target).trigger('pinch') &&
24 $(gesture.target).trigger('pinch' + (gesture.e1 - gesture.e2 > 0 ? 'In' : 'Out'))
25 gesture.e1 = gesture.e2 = gesture.last = 0
26 } else if ('last' in gesture) {
27 gesture = {}
28 }
29 })
30
31 ;['pinch', 'pinchIn', 'pinchOut'].forEach(function(m){
32 $.fn[m] = function(callback){ return this.bind(m, callback) }
33 })
34 }
35})(Zepto)
diff --git a/frontend/gamma/js/Zepto/polyfill.js b/frontend/gamma/js/Zepto/polyfill.js
new file mode 100644
index 0000000..933d1f8
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/polyfill.js
@@ -0,0 +1,36 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function(undefined){
6 if (String.prototype.trim === undefined) // fix for iOS 3.2
7 String.prototype.trim = function(){ return this.replace(/^\s+/, '').replace(/\s+$/, '') }
8
9 // For iOS 3.x
10 // from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
11 if (Array.prototype.reduce === undefined)
12 Array.prototype.reduce = function(fun){
13 if(this === void 0 || this === null) throw new TypeError()
14 var t = Object(this), len = t.length >>> 0, k = 0, accumulator
15 if(typeof fun != 'function') throw new TypeError()
16 if(len == 0 && arguments.length == 1) throw new TypeError()
17
18 if(arguments.length >= 2)
19 accumulator = arguments[1]
20 else
21 do{
22 if(k in t){
23 accumulator = t[k++]
24 break
25 }
26 if(++k >= len) throw new TypeError()
27 } while (true)
28
29 while (k < len){
30 if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
31 k++
32 }
33 return accumulator
34 }
35
36})()
diff --git a/frontend/gamma/js/Zepto/selector.js b/frontend/gamma/js/Zepto/selector.js
new file mode 100644
index 0000000..c0b035a
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/selector.js
@@ -0,0 +1,81 @@
1;(function($){
2 var zepto = $.zepto, oldQsa = zepto.qsa, oldMatches = zepto.matches
3
4 function visible(elem){
5 elem = $(elem)
6 return !!(elem.width() || elem.height()) && elem.css("display") !== "none"
7 }
8
9 // Implements a subset from:
10 // http://api.jquery.com/category/selectors/jquery-selector-extensions/
11 //
12 // Each filter function receives the current index, all nodes in the
13 // considered set, and a value if there were parentheses. The value
14 // of `this` is the node currently being considered. The function returns the
15 // resulting node(s), null, or undefined.
16 //
17 // Complex selectors are not supported:
18 // li:has(label:contains("foo")) + li:has(label:contains("bar"))
19 // ul.inner:first > li
20 var filters = $.expr[':'] = {
21 visible: function(){ if (visible(this)) return this },
22 hidden: function(){ if (!visible(this)) return this },
23 selected: function(){ if (this.selected) return this },
24 checked: function(){ if (this.checked) return this },
25 parent: function(){ return this.parentNode },
26 first: function(idx){ if (idx === 0) return this },
27 last: function(idx, nodes){ if (idx === nodes.length - 1) return this },
28 eq: function(idx, _, value){ if (idx === value) return this },
29 contains: function(idx, _, text){ if ($(this).text().indexOf(text) > -1) return this },
30 has: function(idx, _, sel){ if (zepto.qsa(this, sel).length) return this }
31 }
32
33 var filterRe = new RegExp('(.*):(\\w+)(?:\\(([^)]+)\\))?$\\s*'),
34 childRe = /^\s*>/,
35 classTag = 'Zepto' + (+new Date())
36
37 function process(sel, fn) {
38 // quote the hash in `a[href^=#]` expression
39 sel = sel.replace(/=#\]/g, '="#"]')
40 var filter, arg, match = filterRe.exec(sel)
41 if (match && match[2] in filters) {
42 var filter = filters[match[2]], arg = match[3]
43 sel = match[1]
44 if (arg) {
45 var num = Number(arg)
46 if (isNaN(num)) arg = arg.replace(/^["']|["']$/g, '')
47 else arg = num
48 }
49 }
50 return fn(sel, filter, arg)
51 }
52
53 zepto.qsa = function(node, selector) {
54 return process(selector, function(sel, filter, arg){
55 try {
56 var taggedParent
57 if (!sel && filter) sel = '*'
58 else if (childRe.test(sel))
59 // support "> *" child queries by tagging the parent node with a
60 // unique class and prepending that classname onto the selector
61 taggedParent = $(node).addClass(classTag), sel = '.'+classTag+' '+sel
62
63 var nodes = oldQsa(node, sel)
64 } catch(e) {
65 console.error('error performing selector: %o', selector)
66 throw e
67 } finally {
68 if (taggedParent) taggedParent.removeClass(classTag)
69 }
70 return !filter ? nodes :
71 zepto.uniq($.map(nodes, function(n, i){ return filter.call(n, i, nodes, arg) }))
72 })
73 }
74
75 zepto.matches = function(node, selector){
76 return process(selector, function(sel, filter, arg){
77 return (!sel || oldMatches(node, sel)) &&
78 (!filter || filter.call(node, null, arg) === node)
79 })
80 }
81})(Zepto)
diff --git a/frontend/gamma/js/Zepto/stack.js b/frontend/gamma/js/Zepto/stack.js
new file mode 100644
index 0000000..c995285
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/stack.js
@@ -0,0 +1,22 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 $.fn.end = function(){
7 return this.prevObject || $()
8 }
9
10 $.fn.andSelf = function(){
11 return this.add(this.prevObject || $())
12 }
13
14 'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){
15 var fn = $.fn[property]
16 $.fn[property] = function(){
17 var ret = fn.apply(this, arguments)
18 ret.prevObject = this
19 return ret
20 }
21 })
22})(Zepto)
diff --git a/frontend/gamma/js/Zepto/touch.js b/frontend/gamma/js/Zepto/touch.js
new file mode 100644
index 0000000..af109b9
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/touch.js
@@ -0,0 +1,113 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5;(function($){
6 var touch = {},
7 touchTimeout, tapTimeout, swipeTimeout,
8 longTapDelay = 750, longTapTimeout
9
10 function parentIfText(node) {
11 return 'tagName' in node ? node : node.parentNode
12 }
13
14 function swipeDirection(x1, x2, y1, y2) {
15 var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
16 return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
17 }
18
19 function longTap() {
20 longTapTimeout = null
21 if (touch.last) {
22 touch.el.trigger('longTap')
23 touch = {}
24 }
25 }
26
27 function cancelLongTap() {
28 if (longTapTimeout) clearTimeout(longTapTimeout)
29 longTapTimeout = null
30 }
31
32 function cancelAll() {
33 if (touchTimeout) clearTimeout(touchTimeout)
34 if (tapTimeout) clearTimeout(tapTimeout)
35 if (swipeTimeout) clearTimeout(swipeTimeout)
36 if (longTapTimeout) clearTimeout(longTapTimeout)
37 touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
38 touch = {}
39 }
40
41 $(document).ready(function(){
42 var now, delta
43
44 $(document.body)
45 .bind('touchstart', function(e){
46 now = Date.now()
47 delta = now - (touch.last || now)
48 touch.el = $(parentIfText(e.touches[0].target))
49 touchTimeout && clearTimeout(touchTimeout)
50 touch.x1 = e.touches[0].pageX
51 touch.y1 = e.touches[0].pageY
52 if (delta > 0 && delta <= 250) touch.isDoubleTap = true
53 touch.last = now
54 longTapTimeout = setTimeout(longTap, longTapDelay)
55 })
56 .bind('touchmove', function(e){
57 cancelLongTap()
58 touch.x2 = e.touches[0].pageX
59 touch.y2 = e.touches[0].pageY
60 })
61 .bind('touchend', function(e){
62 cancelLongTap()
63
64 // swipe
65 if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
66 (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
67
68 swipeTimeout = setTimeout(function() {
69 touch.el.trigger('swipe')
70 touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
71 touch = {}
72 }, 0)
73
74 // normal tap
75 else if ('last' in touch)
76
77 // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
78 // ('tap' fires before 'scroll')
79 tapTimeout = setTimeout(function() {
80
81 // trigger universal 'tap' with the option to cancelTouch()
82 // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
83 var event = $.Event('tap')
84 event.cancelTouch = cancelAll
85 touch.el.trigger(event)
86
87 // trigger double tap immediately
88 if (touch.isDoubleTap) {
89 touch.el.trigger('doubleTap')
90 touch = {}
91 }
92
93 // trigger single tap after 250ms of inactivity
94 else {
95 touchTimeout = setTimeout(function(){
96 touchTimeout = null
97 touch.el.trigger('singleTap')
98 touch = {}
99 }, 250)
100 }
101
102 }, 0)
103
104 })
105 .bind('touchcancel', cancelAll)
106
107 $(window).bind('scroll', cancelAll)
108 })
109
110 ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
111 $.fn[m] = function(callback){ return this.bind(m, callback) }
112 })
113})(Zepto)
diff --git a/frontend/gamma/js/Zepto/zepto.js b/frontend/gamma/js/Zepto/zepto.js
new file mode 100644
index 0000000..e67b3a2
--- a/dev/null
+++ b/frontend/gamma/js/Zepto/zepto.js
@@ -0,0 +1,751 @@
1// Zepto.js
2// (c) 2010-2012 Thomas Fuchs
3// Zepto.js may be freely distributed under the MIT license.
4
5var Zepto = (function() {
6 var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter,
7 document = window.document,
8 elementDisplay = {}, classCache = {},
9 getComputedStyle = document.defaultView.getComputedStyle,
10 cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },
11 fragmentRE = /^\s*<(\w+|!)[^>]*>/,
12 tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
13 rootNodeRE = /^(?:body|html)$/i,
14
15 // special attributes that should be get/set via method calls
16 methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],
17
18 adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
19 table = document.createElement('table'),
20 tableRow = document.createElement('tr'),
21 containers = {
22 'tr': document.createElement('tbody'),
23 'tbody': table, 'thead': table, 'tfoot': table,
24 'td': tableRow, 'th': tableRow,
25 '*': document.createElement('div')
26 },
27 readyRE = /complete|loaded|interactive/,
28 classSelectorRE = /^\.([\w-]+)$/,
29 idSelectorRE = /^#([\w-]*)$/,
30 tagSelectorRE = /^[\w-]+$/,
31 toString = {}.toString,
32 zepto = {},
33 camelize, uniq,
34 tempParent = document.createElement('div')
35
36 zepto.matches = function(element, selector) {
37 if (!element || element.nodeType !== 1) return false
38 var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector ||
39 element.oMatchesSelector || element.matchesSelector
40 if (matchesSelector) return matchesSelector.call(element, selector)
41 // fall back to performing a selector:
42 var match, parent = element.parentNode, temp = !parent
43 if (temp) (parent = tempParent).appendChild(element)
44 match = ~zepto.qsa(parent, selector).indexOf(element)
45 temp && tempParent.removeChild(element)
46 return match
47 }
48
49 function isFunction(value) { return toString.call(value) == "[object Function]" }
50 function isObject(value) { return value instanceof Object }
51 function isPlainObject(value) {
52 return isObject(value) && value != window && value.__proto__ == Object.prototype
53 }
54 function isArray(value) { return value instanceof Array }
55 function likeArray(obj) { return typeof obj.length == 'number' }
56
57 function compact(array) { return filter.call(array, function(item){ return item != null }) }
58 function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }
59 camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
60 function dasherize(str) {
61 return str.replace(/::/g, '/')
62 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
63 .replace(/([a-z\d])([A-Z])/g, '$1_$2')
64 .replace(/_/g, '-')
65 .toLowerCase()
66 }
67 uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }
68
69 function classRE(name) {
70 return name in classCache ?
71 classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
72 }
73
74 function maybeAddPx(name, value) {
75 return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value
76 }
77
78 function defaultDisplay(nodeName) {
79 var element, display
80 if (!elementDisplay[nodeName]) {
81 element = document.createElement(nodeName)
82 document.body.appendChild(element)
83 display = getComputedStyle(element, '').getPropertyValue("display")
84 element.parentNode.removeChild(element)
85 display == "none" && (display = "block")
86 elementDisplay[nodeName] = display
87 }
88 return elementDisplay[nodeName]
89 }
90
91 function children(element) {
92 return 'children' in element ?
93 slice.call(element.children) :
94 $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })
95 }
96
97 // `$.zepto.fragment` takes a html string and an optional tag name
98 // to generate DOM nodes nodes from the given html string.
99 // The generated DOM nodes are returned as an array.
100 // This function can be overriden in plugins for example to make
101 // it compatible with browsers that don't support the DOM fully.
102 zepto.fragment = function(html, name, properties) {
103 if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
104 if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
105 if (!(name in containers)) name = '*'
106
107 var nodes, dom, container = containers[name]
108 container.innerHTML = '' + html
109 dom = $.each(slice.call(container.childNodes), function(){
110 container.removeChild(this)
111 })
112 if (isPlainObject(properties)) {
113 nodes = $(dom)
114 $.each(properties, function(key, value) {
115 if (methodAttributes.indexOf(key) > -1) nodes[key](value)
116 else nodes.attr(key, value)
117 })
118 }
119 return dom
120 }
121
122 // `$.zepto.Z` swaps out the prototype of the given `dom` array
123 // of nodes with `$.fn` and thus supplying all the Zepto functions
124 // to the array. Note that `__proto__` is not supported on Internet
125 // Explorer. This method can be overriden in plugins.
126 zepto.Z = function(dom, selector) {
127 dom = dom || []
128 dom.__proto__ = arguments.callee.prototype
129 dom.selector = selector || ''
130 return dom
131 }
132
133 // `$.zepto.isZ` should return `true` if the given object is a Zepto
134 // collection. This method can be overriden in plugins.
135 zepto.isZ = function(object) {
136 return object instanceof zepto.Z
137 }
138
139 // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
140 // takes a CSS selector and an optional context (and handles various
141 // special cases).
142 // This method can be overriden in plugins.
143 zepto.init = function(selector, context) {
144 // If nothing given, return an empty Zepto collection
145 if (!selector) return zepto.Z()
146 // If a function is given, call it when the DOM is ready
147 else if (isFunction(selector)) return $(document).ready(selector)
148 // If a Zepto collection is given, juts return it
149 else if (zepto.isZ(selector)) return selector
150 else {
151 var dom
152 // normalize array if an array of nodes is given
153 if (isArray(selector)) dom = compact(selector)
154 // Wrap DOM nodes. If a plain object is given, duplicate it.
155 else if (isObject(selector))
156 dom = [isPlainObject(selector) ? $.extend({}, selector) : selector], selector = null
157 // If it's a html fragment, create nodes from it
158 else if (fragmentRE.test(selector))
159 dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
160 // If there's a context, create a collection on that context first, and select
161 // nodes from there
162 else if (context !== undefined) return $(context).find(selector)
163 // And last but no least, if it's a CSS selector, use it to select nodes.
164 else dom = zepto.qsa(document, selector)
165 // create a new Zepto collection from the nodes found
166 return zepto.Z(dom, selector)
167 }
168 }
169
170 // `$` will be the base `Zepto` object. When calling this
171 // function just call `$.zepto.init, which makes the implementation
172 // details of selecting nodes and creating Zepto collections
173 // patchable in plugins.
174 $ = function(selector, context){
175 return zepto.init(selector, context)
176 }
177
178 function extend(target, source, deep) {
179 for (key in source)
180 if (deep && isPlainObject(source[key])) {
181 if (!isPlainObject(target[key])) target[key] = {}
182 extend(target[key], source[key], deep)
183 }
184 else if (source[key] !== undefined) target[key] = source[key]
185 }
186
187 // Copy all but undefined properties from one or more
188 // objects to the `target` object.
189 $.extend = function(target){
190 var deep, args = slice.call(arguments, 1)
191 if (typeof target == 'boolean') {
192 deep = target
193 target = args.shift()
194 }
195 args.forEach(function(arg){ extend(target, arg, deep) })
196 return target
197 }
198
199 // `$.zepto.qsa` is Zepto's CSS selector implementation which
200 // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
201 // This method can be overriden in plugins.
202 zepto.qsa = function(element, selector){
203 var found
204 return (element === document && idSelectorRE.test(selector)) ?
205 ( (found = element.getElementById(RegExp.$1)) ? [found] : [] ) :
206 (element.nodeType !== 1 && element.nodeType !== 9) ? [] :
207 slice.call(
208 classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
209 tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
210 element.querySelectorAll(selector)
211 )
212 }
213
214 function filtered(nodes, selector) {
215 return selector === undefined ? $(nodes) : $(nodes).filter(selector)
216 }
217
218 $.contains = function(parent, node) {
219 return parent !== node && parent.contains(node)
220 }
221
222 function funcArg(context, arg, idx, payload) {
223 return isFunction(arg) ? arg.call(context, idx, payload) : arg
224 }
225
226 function setAttribute(node, name, value) {
227 value == null ? node.removeAttribute(name) : node.setAttribute(name, value)
228 }
229
230 // access className property while respecting SVGAnimatedString
231 function className(node, value){
232 var klass = node.className,
233 svg = klass && klass.baseVal !== undefined
234
235 if (value === undefined) return svg ? klass.baseVal : klass
236 svg ? (klass.baseVal = value) : (node.className = value)
237 }
238
239 // "true" => true
240 // "false" => false
241 // "null" => null
242 // "42" => 42
243 // "42.5" => 42.5
244 // JSON => parse if valid
245 // String => self
246 function deserializeValue(value) {
247 var num
248 try {
249 return value ?
250 value == "true" ||
251 ( value == "false" ? false :
252 value == "null" ? null :
253 !isNaN(num = Number(value)) ? num :
254 /^[\[\{]/.test(value) ? $.parseJSON(value) :
255 value )
256 : value
257 } catch(e) {
258 return value
259 }
260 }
261
262 $.isFunction = isFunction
263 $.isObject = isObject
264 $.isArray = isArray
265 $.isPlainObject = isPlainObject
266
267 $.inArray = function(elem, array, i){
268 return emptyArray.indexOf.call(array, elem, i)
269 }
270
271 $.camelCase = camelize
272 $.trim = function(str) { return str.trim() }
273
274 // plugin compatibility
275 $.uuid = 0
276 $.support = { }
277 $.expr = { }
278
279 $.map = function(elements, callback){
280 var value, values = [], i, key
281 if (likeArray(elements))
282 for (i = 0; i < elements.length; i++) {
283 value = callback(elements[i], i)
284 if (value != null) values.push(value)
285 }
286 else
287 for (key in elements) {
288 value = callback(elements[key], key)
289 if (value != null) values.push(value)
290 }
291 return flatten(values)
292 }
293
294 $.each = function(elements, callback){
295 var i, key
296 if (likeArray(elements)) {
297 for (i = 0; i < elements.length; i++)
298 if (callback.call(elements[i], i, elements[i]) === false) return elements
299 } else {
300 for (key in elements)
301 if (callback.call(elements[key], key, elements[key]) === false) return elements
302 }
303
304 return elements
305 }
306
307 $.grep = function(elements, callback){
308 return filter.call(elements, callback)
309 }
310
311 if (window.JSON) $.parseJSON = JSON.parse
312
313 // Define methods that will be available on all
314 // Zepto collections
315 $.fn = {
316 // Because a collection acts like an array
317 // copy over these useful array functions.
318 forEach: emptyArray.forEach,
319 reduce: emptyArray.reduce,
320 push: emptyArray.push,
321 sort: emptyArray.sort,
322 indexOf: emptyArray.indexOf,
323 concat: emptyArray.concat,
324
325 // `map` and `slice` in the jQuery API work differently
326 // from their array counterparts
327 map: function(fn){
328 return $($.map(this, function(el, i){ return fn.call(el, i, el) }))
329 },
330 slice: function(){
331 return $(slice.apply(this, arguments))
332 },
333
334 ready: function(callback){
335 if (readyRE.test(document.readyState)) callback($)
336 else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false)
337 return this
338 },
339 get: function(idx){
340 return idx === undefined ? slice.call(this) : this[idx]
341 },
342 toArray: function(){ return this.get() },
343 size: function(){
344 return this.length
345 },
346 remove: function(){
347 return this.each(function(){
348 if (this.parentNode != null)
349 this.parentNode.removeChild(this)
350 })
351 },
352 each: function(callback){
353 emptyArray.every.call(this, function(el, idx){
354 return callback.call(el, idx, el) !== false
355 })
356 return this
357 },
358 filter: function(selector){
359 if (isFunction(selector)) return this.not(this.not(selector))
360 return $(filter.call(this, function(element){
361 return zepto.matches(element, selector)
362 }))
363 },
364 add: function(selector,context){
365 return $(uniq(this.concat($(selector,context))))
366 },
367 is: function(selector){
368 return this.length > 0 && zepto.matches(this[0], selector)
369 },
370 not: function(selector){
371 var nodes=[]
372 if (isFunction(selector) && selector.call !== undefined)
373 this.each(function(idx){
374 if (!selector.call(this,idx)) nodes.push(this)
375 })
376 else {
377 var excludes = typeof selector == 'string' ? this.filter(selector) :
378 (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
379 this.forEach(function(el){
380 if (excludes.indexOf(el) < 0) nodes.push(el)
381 })
382 }
383 return $(nodes)
384 },
385 has: function(selector){
386 return this.filter(function(){
387 return isObject(selector) ?
388 $.contains(this, selector) :
389 $(this).find(selector).size()
390 })
391 },
392 eq: function(idx){
393 return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)
394 },
395 first: function(){
396 var el = this[0]
397 return el && !isObject(el) ? el : $(el)
398 },
399 last: function(){
400 var el = this[this.length - 1]
401 return el && !isObject(el) ? el : $(el)
402 },
403 find: function(selector){
404 var result
405 if (this.length == 1) result = $(zepto.qsa(this[0], selector))
406 else result = this.map(function(){ return zepto.qsa(this, selector) })
407 return result
408 },
409 closest: function(selector, context){
410 var node = this[0]
411 while (node && !zepto.matches(node, selector))
412 node = node !== context && node !== document && node.parentNode
413 return $(node)
414 },
415 parents: function(selector){
416 var ancestors = [], nodes = this
417 while (nodes.length > 0)
418 nodes = $.map(nodes, function(node){
419 if ((node = node.parentNode) && node !== document && ancestors.indexOf(node) < 0) {
420 ancestors.push(node)
421 return node
422 }
423 })
424 return filtered(ancestors, selector)
425 },
426 parent: function(selector){
427 return filtered(uniq(this.pluck('parentNode')), selector)
428 },
429 children: function(selector){
430 return filtered(this.map(function(){ return children(this) }), selector)
431 },
432 contents: function() {
433 return this.map(function() { return slice.call(this.childNodes) })
434 },
435 siblings: function(selector){
436 return filtered(this.map(function(i, el){
437 return filter.call(children(el.parentNode), function(child){ return child!==el })
438 }), selector)
439 },
440 empty: function(){
441 return this.each(function(){ this.innerHTML = '' })
442 },
443 // `pluck` is borrowed from Prototype.js
444 pluck: function(property){
445 return $.map(this, function(el){ return el[property] })
446 },
447 show: function(){
448 return this.each(function(){
449 this.style.display == "none" && (this.style.display = null)
450 if (getComputedStyle(this, '').getPropertyValue("display") == "none")
451 this.style.display = defaultDisplay(this.nodeName)
452 })
453 },
454 replaceWith: function(newContent){
455 return this.before(newContent).remove()
456 },
457 wrap: function(structure){
458 var func = isFunction(structure)
459 if (this[0] && !func)
460 var dom = $(structure).get(0),
461 clone = dom.parentNode || this.length > 1
462
463 return this.each(function(index){
464 $(this).wrapAll(
465 func ? structure.call(this, index) :
466 clone ? dom.cloneNode(true) : dom
467 )
468 })
469 },
470 wrapAll: function(structure){
471 if (this[0]) {
472 $(this[0]).before(structure = $(structure))
473 var children
474 // drill down to the inmost element
475 while ((children = structure.children()).length) structure = children.first()
476 $(structure).append(this)
477 }
478 return this
479 },
480 wrapInner: function(structure){
481 var func = isFunction(structure)
482 return this.each(function(index){
483 var self = $(this), contents = self.contents(),
484 dom = func ? structure.call(this, index) : structure
485 contents.length ? contents.wrapAll(dom) : self.append(dom)
486 })
487 },
488 unwrap: function(){
489 this.parent().each(function(){
490 $(this).replaceWith($(this).children())
491 })
492 return this
493 },
494 clone: function(){
495 return this.map(function(){ return this.cloneNode(true) })
496 },
497 hide: function(){
498 return this.css("display", "none")
499 },
500 toggle: function(setting){
501 return this.each(function(){
502 var el = $(this)
503 ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide()
504 })
505 },
506 prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },
507 next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },
508 html: function(html){
509 return html === undefined ?
510 (this.length > 0 ? this[0].innerHTML : null) :
511 this.each(function(idx){
512 var originHtml = this.innerHTML
513 $(this).empty().append( funcArg(this, html, idx, originHtml) )
514 })
515 },
516 text: function(text){
517 return text === undefined ?
518 (this.length > 0 ? this[0].textContent : null) :
519 this.each(function(){ this.textContent = text })
520 },
521 attr: function(name, value){
522 var result
523 return (typeof name == 'string' && value === undefined) ?
524 (this.length == 0 || this[0].nodeType !== 1 ? undefined :
525 (name == 'value' && this[0].nodeName == 'INPUT') ? this.val() :
526 (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result
527 ) :
528 this.each(function(idx){
529 if (this.nodeType !== 1) return
530 if (isObject(name)) for (key in name) setAttribute(this, key, name[key])
531 else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))
532 })
533 },
534 removeAttr: function(name){
535 return this.each(function(){ this.nodeType === 1 && setAttribute(this, name) })
536 },
537 prop: function(name, value){
538 return (value === undefined) ?
539 (this[0] && this[0][name]) :
540 this.each(function(idx){
541 this[name] = funcArg(this, value, idx, this[name])
542 })
543 },
544 data: function(name, value){
545 var data = this.attr('data-' + dasherize(name), value)
546 return data !== null ? deserializeValue(data) : undefined
547 },
548 val: function(value){
549 return (value === undefined) ?
550 (this[0] && (this[0].multiple ?
551 $(this[0]).find('option').filter(function(o){ return this.selected }).pluck('value') :
552 this[0].value)
553 ) :
554 this.each(function(idx){
555 this.value = funcArg(this, value, idx, this.value)
556 })
557 },
558 offset: function(coordinates){
559 if (coordinates) return this.each(function(index){
560 var $this = $(this),
561 coords = funcArg(this, coordinates, index, $this.offset()),
562 parentOffset = $this.offsetParent().offset(),
563 props = {
564 top: coords.top - parentOffset.top,
565 left: coords.left - parentOffset.left
566 }
567
568 if ($this.css('position') == 'static') props['position'] = 'relative'
569 $this.css(props)
570 })
571 if (this.length==0) return null
572 var obj = this[0].getBoundingClientRect()
573 return {
574 left: obj.left + window.pageXOffset,
575 top: obj.top + window.pageYOffset,
576 width: obj.width,
577 height: obj.height
578 }
579 },
580 css: function(property, value){
581 if (arguments.length < 2 && typeof property == 'string')
582 return this[0] && (this[0].style[camelize(property)] || getComputedStyle(this[0], '').getPropertyValue(property))
583
584 var css = ''
585 for (key in property)
586 if (!property[key] && property[key] !== 0)
587 this.each(function(){ this.style.removeProperty(dasherize(key)) })
588 else
589 css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
590
591 if (typeof property == 'string')
592 if (!value && value !== 0)
593 this.each(function(){ this.style.removeProperty(dasherize(property)) })
594 else
595 css = dasherize(property) + ":" + maybeAddPx(property, value)
596
597 return this.each(function(){ this.style.cssText += ';' + css })
598 },
599 index: function(element){
600 return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])
601 },
602 hasClass: function(name){
603 return emptyArray.some.call(this, function(el){
604 return this.test(className(el))
605 }, classRE(name))
606 },
607 addClass: function(name){
608 return this.each(function(idx){
609 classList = []
610 var cls = className(this), newName = funcArg(this, name, idx, cls)
611 newName.split(/\s+/g).forEach(function(klass){
612 if (!$(this).hasClass(klass)) classList.push(klass)
613 }, this)
614 classList.length && className(this, cls + (cls ? " " : "") + classList.join(" "))
615 })
616 },
617 removeClass: function(name){
618 return this.each(function(idx){
619 if (name === undefined) return className(this, '')
620 classList = className(this)
621 funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
622 classList = classList.replace(classRE(klass), " ")
623 })
624 className(this, classList.trim())
625 })
626 },
627 toggleClass: function(name, when){
628 return this.each(function(idx){
629 var newName = funcArg(this, name, idx, className(this))
630 ;(when === undefined ? !$(this).hasClass(newName) : when) ?
631 $(this).addClass(newName) : $(this).removeClass(newName)
632 })
633 },
634 scrollTop: function(){
635 if (!this.length) return
636 return ('scrollTop' in this[0]) ? this[0].scrollTop : this[0].scrollY
637 },
638 position: function() {
639 if (!this.length) return
640
641 var elem = this[0],
642 // Get *real* offsetParent
643 offsetParent = this.offsetParent(),
644 // Get correct offsets
645 offset = this.offset(),
646 parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()
647
648 // Subtract element margins
649 // note: when an element has margin: auto the offsetLeft and marginLeft
650 // are the same in Safari causing offset.left to incorrectly be 0
651 offset.top -= parseFloat( $(elem).css('margin-top') ) || 0
652 offset.left -= parseFloat( $(elem).css('margin-left') ) || 0
653
654 // Add offsetParent borders
655 parentOffset.top += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0
656 parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0
657
658 // Subtract the two offsets
659 return {
660 top: offset.top - parentOffset.top,
661 left: offset.left - parentOffset.left
662 }
663 },
664 offsetParent: function() {
665 return this.map(function(){
666 var parent = this.offsetParent || document.body
667 while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static")
668 parent = parent.offsetParent
669 return parent
670 })
671 }
672 }
673
674 // for now
675 $.fn.detach = $.fn.remove
676
677 // Generate the `width` and `height` functions
678 ;['width', 'height'].forEach(function(dimension){
679 $.fn[dimension] = function(value){
680 var offset, Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() })
681 if (value === undefined) return this[0] == window ? window['inner' + Dimension] :
682 this[0] == document ? document.documentElement['offset' + Dimension] :
683 (offset = this.offset()) && offset[dimension]
684 else return this.each(function(idx){
685 var el = $(this)
686 el.css(dimension, funcArg(this, value, idx, el[dimension]()))
687 })
688 }
689 })
690
691 function traverseNode(node, fun) {
692 fun(node)
693 for (var key in node.childNodes) traverseNode(node.childNodes[key], fun)
694 }
695
696 // Generate the `after`, `prepend`, `before`, `append`,
697 // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
698 adjacencyOperators.forEach(function(operator, operatorIndex) {
699 var inside = operatorIndex % 2 //=> prepend, append
700
701 $.fn[operator] = function(){
702 // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
703 var nodes = $.map(arguments, function(n){ return isObject(n) ? n : zepto.fragment(n) }),
704 parent, copyByClone = this.length > 1
705 if (nodes.length < 1) return this
706
707 return this.each(function(_, target){
708 parent = inside ? target : target.parentNode
709
710 // convert all methods to a "before" operation
711 target = operatorIndex == 0 ? target.nextSibling :
712 operatorIndex == 1 ? target.firstChild :
713 operatorIndex == 2 ? target :
714 null
715
716 nodes.forEach(function(node){
717 if (copyByClone) node = node.cloneNode(true)
718 else if (!parent) return $(node).remove()
719
720 traverseNode(parent.insertBefore(node, target), function(el){
721 if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&
722 (!el.type || el.type === 'text/javascript') && !el.src)
723 window['eval'].call(window, el.innerHTML)
724 })
725 })
726 })
727 }
728
729 // after => insertAfter
730 // prepend => prependTo
731 // before => insertBefore
732 // append => appendTo
733 $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){
734 $(html)[operator](this)
735 return this
736 }
737 })
738
739 zepto.Z.prototype = $.fn
740
741 // Export internal API functions in the `$.zepto` namespace
742 zepto.uniq = uniq
743 zepto.deserializeValue = deserializeValue
744 $.zepto = zepto
745
746 return $
747})()
748
749// If `$` is not yet defined, point it to `Zepto`
750window.Zepto = Zepto
751'$' in window || (window.$ = Zepto)