compass-aurora 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/aurora.rb +11 -0
- data/stylesheets/_aurora-singularitygs.scss +4 -0
- data/stylesheets/_aurora-susy.scss +4 -0
- data/templates/project/_base.scss +28 -0
- data/templates/project/manifest.rb +75 -0
- data/templates/shared/_design.scss +9 -0
- data/templates/shared/_extendables.scss +6 -0
- data/templates/shared/_functions.scss +5 -0
- data/templates/shared/_ie-design.scss +9 -0
- data/templates/shared/_ie-layout.scss +9 -0
- data/templates/shared/_layout.scss +9 -0
- data/templates/shared/_mixins.scss +5 -0
- data/templates/shared/_print-design.scss +9 -0
- data/templates/shared/_print-layout.scss +9 -0
- data/templates/shared/_style-guide.scss +10 -0
- data/templates/shared/_variables.scss +5 -0
- data/templates/shared/aurora.info.erb +20 -0
- data/templates/shared/hammer.js +731 -0
- data/templates/shared/ie.scss +28 -0
- data/templates/shared/loader.js +4 -0
- data/templates/shared/modernizr-2.5.3.js +726 -0
- data/templates/shared/print.scss +28 -0
- data/templates/shared/style.scss +27 -0
- data/templates/shared/template.php.erb +11 -0
- data/templates/singularity/_base.scss +28 -0
- data/templates/singularity/manifest.rb +73 -0
- metadata +130 -0
data/lib/aurora.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'compass'
|
2
|
+
require 'toolkit'
|
3
|
+
require 'sassy-buttons'
|
4
|
+
|
5
|
+
extension_path = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
6
|
+
Compass::Frameworks.register('aurora', :path => extension_path)
|
7
|
+
|
8
|
+
module Aurora
|
9
|
+
VERSION = "0.1"
|
10
|
+
DATE = "2012-08-1"
|
11
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Base Partials
|
3
|
+
//
|
4
|
+
// These files will be shared across all three of your output
|
5
|
+
// CSS files. Generally included here are only Compass Extension
|
6
|
+
// imports and imports for variables, functions, mixins, and extendables.
|
7
|
+
////////////////////////
|
8
|
+
|
9
|
+
////////////////////////
|
10
|
+
// Compass Imports
|
11
|
+
//
|
12
|
+
// Aurora includes @import 'compass' so you don't need to.
|
13
|
+
////////////////////////
|
14
|
+
|
15
|
+
////////////////////////
|
16
|
+
// Compass Extensions
|
17
|
+
//
|
18
|
+
// Aurora includes Toolkit, Breakpoint, Respond-to, Sassy Buttons, and Susy
|
19
|
+
////////////////////////
|
20
|
+
@import 'aurora-susy';
|
21
|
+
|
22
|
+
////////////////////////
|
23
|
+
// Private Imports
|
24
|
+
////////////////////////
|
25
|
+
@import 'variables';
|
26
|
+
@import 'functions';
|
27
|
+
@import 'mixins';
|
28
|
+
@import 'extendables';
|
@@ -0,0 +1,75 @@
|
|
1
|
+
description "Responsive Web Design Kickstart"
|
2
|
+
|
3
|
+
# ERB ALL the Drupal files!
|
4
|
+
file '../shared/aurora.info.erb', :to => "#{options[:project_name] || File.basename(Compass.configuration.project_path)}.info", :erb => true
|
5
|
+
|
6
|
+
file '../shared/template.php.erb', :to => "template.php", :erb => true
|
7
|
+
|
8
|
+
# Stylesheets
|
9
|
+
file '../shared/style.scss', :like => :stylesheet, :media => 'screen, projection', :to => 'style.scss'
|
10
|
+
|
11
|
+
file '_base.scss', :like => :stylesheet, :to => 'partials/global/_base.scss'
|
12
|
+
file '../shared/_variables.scss', :like => :stylesheet, :to => 'partials/global/_variables.scss'
|
13
|
+
file '../shared/_functions.scss', :like => :stylesheet, :to => 'partials/global/_functions.scss'
|
14
|
+
file '../shared/_mixins.scss', :like => :stylesheet, :to => 'partials/global/_mixins.scss'
|
15
|
+
file '../shared/_extendables.scss', :like => :stylesheet, :to => 'partials/global/_extendables.scss'
|
16
|
+
|
17
|
+
file '../shared/_style-guide.scss', :like => :stylesheet, :to => 'partials/styleguide/_style-guide.scss'
|
18
|
+
|
19
|
+
file '../shared/_layout.scss', :like => :stylesheet, :to => 'partials/layout/_layout.scss'
|
20
|
+
file '../shared/_ie-layout.scss', :like => :stylesheet, :to => 'partials/layout/_ie-layout.scss'
|
21
|
+
file '../shared/_print-layout.scss', :like => :stylesheet, :to => 'partials/layout/_print-layout.scss'
|
22
|
+
|
23
|
+
file '../shared/_design.scss', :like => :stylesheet, :to => 'partials/design/_design.scss'
|
24
|
+
file '../shared/_ie-design.scss', :like => :stylesheet, :to => 'partials/design/_ie-design.scss'
|
25
|
+
file '../shared/_print-design.scss', :like => :stylesheet, :to => 'partials/design/_print-design.scss'
|
26
|
+
|
27
|
+
file '../shared/print.scss', :like => :stylesheet, :media => 'print', :to => 'print.scss'
|
28
|
+
file '../shared/ie.scss', :like => :stylesheet, :media => 'screen, projection', :condition => "lt IE 8", :to => 'ie.scss'
|
29
|
+
|
30
|
+
# JavaScript
|
31
|
+
file '../shared/hammer.js', :like => :javascript, :to => 'hammer.js'
|
32
|
+
file '../shared/loader.js', :like => :javascript, :to => 'loader.js'
|
33
|
+
file '../shared/modernizr-2.5.3.js', :like => :javascript, :to => 'modernizr-2.5.3.js'
|
34
|
+
|
35
|
+
help %Q{
|
36
|
+
Please contact Sam Richard with questions:
|
37
|
+
|
38
|
+
sam@snug.ug
|
39
|
+
}
|
40
|
+
|
41
|
+
welcome_message %Q{
|
42
|
+
|
43
|
+
Responsive Web Design Kickstart
|
44
|
+
|
45
|
+
Welcome to the Responsive Web Design Kickstart gem! Provided are the basic tools needed to kickstart a custom Responsive Web Design solution tailor made to your needs! Remember, tools and best practices are always changing, so keep up to date!
|
46
|
+
|
47
|
+
The following is included in this build:
|
48
|
+
Compass Extensions:
|
49
|
+
* Singularity
|
50
|
+
* Toolkit
|
51
|
+
* Respond-to
|
52
|
+
|
53
|
+
JavaScript:
|
54
|
+
* Modernizr Custom Build with all Standard features of 2.3.5 except html5shiv w/printshiv or Media Queries. Build your own from http://modernizr.com/download/ when you are ready for production
|
55
|
+
* Loader.js custom JavaScript file for holding conditional asset loading scripts thanks to Modernizr's yepnope (http://yepnopejs.com/). Comes with yepnope code for loading in Hammer.js, just make sure the path is correct from root.. Ready for production, but remember to minify and gzip!
|
56
|
+
* Hammer.js (http://eightmedia.github.com/hammer.js/) for awesome touch events. Ready for production, but remember to minify and gzip!
|
57
|
+
|
58
|
+
Include the following in your <head> tag:
|
59
|
+
|
60
|
+
<meta content='width=device-width, initial-scale=1.0' name='viewport' />
|
61
|
+
<meta content='IE=edge,chrome=1' http-equiv='X-UA-Compatible' />
|
62
|
+
<!--[if lt IE 9 ]> <script src="//ajax.googleapis.com/ajax/libs/chrome-frame/1.0.2/CFInstall.min.js"></script><script>window.attachEvent("onload",function(){CFInstall.check({mode:"overlay"})})</script> <![endif]-->
|
63
|
+
<!-- CSS -->
|
64
|
+
<link href='path/to/css/style.css?v=1' rel='stylesheet' />
|
65
|
+
<!-- All JavaScript at the bottom, except for Modernizr and Respond/Selectivizr for IE 8 and Below. -->
|
66
|
+
<script src='path/to/js/modernizr-2.5.3.js'></script>
|
67
|
+
|
68
|
+
Include the following, and all other JavaScript, including any JavaScript frameworks you may be using like jQuery, right before your closing </body> tag:
|
69
|
+
|
70
|
+
<!-- Javascript at the bottom for fast page loading -->
|
71
|
+
<script src='path/to/js/loader.js'></script>
|
72
|
+
|
73
|
+
|
74
|
+
}
|
75
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Design Partials
|
3
|
+
//
|
4
|
+
// Seperate your layout from design, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file.
|
7
|
+
//
|
8
|
+
// All styling, non box model properties go here
|
9
|
+
////////////////////////
|
@@ -0,0 +1,9 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// IE Design Partials
|
3
|
+
//
|
4
|
+
// Seperate your layout from design, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file. This is for Internet Explorer's Use.
|
7
|
+
//
|
8
|
+
// All styling, non box model properties go here
|
9
|
+
////////////////////////
|
@@ -0,0 +1,9 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// IE Layout Partials
|
3
|
+
//
|
4
|
+
// Seperate your layout from design, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file. This is for Internet Explorer's Use
|
7
|
+
//
|
8
|
+
// All box model properties go here
|
9
|
+
////////////////////////
|
@@ -0,0 +1,9 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Layout Partials
|
3
|
+
//
|
4
|
+
// Seperate your layout from design, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file.
|
7
|
+
//
|
8
|
+
// All box model properties go here
|
9
|
+
////////////////////////
|
@@ -0,0 +1,9 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Print Design Partials
|
3
|
+
//
|
4
|
+
// Seperate your layout from design, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file. This is for Printed files.
|
7
|
+
//
|
8
|
+
// All styling, non box model properties go here
|
9
|
+
////////////////////////
|
@@ -0,0 +1,9 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Print Layout Partials
|
3
|
+
//
|
4
|
+
// Seperate your layout from design, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file. This is for Print files.
|
7
|
+
//
|
8
|
+
// All box model properties go here
|
9
|
+
////////////////////////
|
@@ -0,0 +1,10 @@
|
|
1
|
+
////////////////////////
|
2
|
+
// Style Guide Partials
|
3
|
+
//
|
4
|
+
// Write a Style Guide for your website, building sub folders and partials
|
5
|
+
// in this folder, with everything being imported, in casading order,
|
6
|
+
// into this file.
|
7
|
+
//
|
8
|
+
// All Style Guide selectors should go in here, regardless of layout or design
|
9
|
+
// (but separating the two in here is a good idea).
|
10
|
+
////////////////////////
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% project_name = File.basename(Compass.configuration.project_path) %><% project_js = Compass.configuration.javascripts_dir %><% project_css = Compass.configuration.css_dir %>name = <%= project_name %>
|
2
|
+
description = <%= project_name %> theme based on the Aurora base theme.
|
3
|
+
core = 7.x
|
4
|
+
base theme = aurora
|
5
|
+
|
6
|
+
stylesheets[all][] = <%= project_css %>/style.css
|
7
|
+
stylesheets[print][] = <%= project_css %>/print.css
|
8
|
+
stylesheets-conditional[lt IE 9][all][] = <%= project_css %>/ie.css
|
9
|
+
|
10
|
+
regions[sidebar_first] = Primary Sidebar
|
11
|
+
regions[sidebar_second] = Secondary Sidebar
|
12
|
+
regions[content] = Content
|
13
|
+
regions[footer] = Footer
|
14
|
+
regions[header] = Header
|
15
|
+
regions[help] = Help
|
16
|
+
regions[highlighted] = Highlighted
|
17
|
+
|
18
|
+
settings[aurora_enable_chrome_frame] = 1
|
19
|
+
settings[aurora_min_ie_support] = 10
|
20
|
+
settings[aurora_footer_js] = 1
|
@@ -0,0 +1,731 @@
|
|
1
|
+
/*
|
2
|
+
* Hammer.JS
|
3
|
+
* version 0.6.1
|
4
|
+
* author: Eight Media
|
5
|
+
* https://github.com/EightMedia/hammer.js
|
6
|
+
*/
|
7
|
+
function Hammer(element, options, undefined)
|
8
|
+
{
|
9
|
+
var self = this;
|
10
|
+
|
11
|
+
var defaults = {
|
12
|
+
// prevent the default event or not... might be buggy when false
|
13
|
+
prevent_default : false,
|
14
|
+
css_hacks : true,
|
15
|
+
|
16
|
+
swipe : true,
|
17
|
+
swipe_time : 200, // ms
|
18
|
+
swipe_min_distance : 20, // pixels
|
19
|
+
|
20
|
+
drag : true,
|
21
|
+
drag_vertical : true,
|
22
|
+
drag_horizontal : true,
|
23
|
+
// minimum distance before the drag event starts
|
24
|
+
drag_min_distance : 20, // pixels
|
25
|
+
|
26
|
+
// pinch zoom and rotation
|
27
|
+
transform : true,
|
28
|
+
scale_treshold : 0.1,
|
29
|
+
rotation_treshold : 15, // degrees
|
30
|
+
|
31
|
+
tap : true,
|
32
|
+
tap_double : true,
|
33
|
+
tap_max_interval : 300,
|
34
|
+
tap_max_distance : 10,
|
35
|
+
tap_double_distance: 20,
|
36
|
+
|
37
|
+
hold : true,
|
38
|
+
hold_timeout : 500
|
39
|
+
};
|
40
|
+
options = mergeObject(defaults, options);
|
41
|
+
|
42
|
+
// some css hacks
|
43
|
+
(function() {
|
44
|
+
if(!options.css_hacks) {
|
45
|
+
return false;
|
46
|
+
}
|
47
|
+
|
48
|
+
var vendors = ['webkit','moz','ms','o',''];
|
49
|
+
var css_props = {
|
50
|
+
"userSelect": "none",
|
51
|
+
"touchCallout": "none",
|
52
|
+
"userDrag": "none",
|
53
|
+
"tapHighlightColor": "rgba(0,0,0,0)"
|
54
|
+
};
|
55
|
+
|
56
|
+
var prop = '';
|
57
|
+
for(var i = 0; i < vendors.length; i++) {
|
58
|
+
for(var p in css_props) {
|
59
|
+
prop = p;
|
60
|
+
if(vendors[i]) {
|
61
|
+
prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1);
|
62
|
+
}
|
63
|
+
element.style[ prop ] = css_props[p];
|
64
|
+
}
|
65
|
+
}
|
66
|
+
})();
|
67
|
+
|
68
|
+
// holds the distance that has been moved
|
69
|
+
var _distance = 0;
|
70
|
+
|
71
|
+
// holds the exact angle that has been moved
|
72
|
+
var _angle = 0;
|
73
|
+
|
74
|
+
// holds the diraction that has been moved
|
75
|
+
var _direction = 0;
|
76
|
+
|
77
|
+
// holds position movement for sliding
|
78
|
+
var _pos = { };
|
79
|
+
|
80
|
+
// how many fingers are on the screen
|
81
|
+
var _fingers = 0;
|
82
|
+
|
83
|
+
var _first = false;
|
84
|
+
|
85
|
+
var _gesture = null;
|
86
|
+
var _prev_gesture = null;
|
87
|
+
|
88
|
+
var _touch_start_time = null;
|
89
|
+
var _prev_tap_pos = {x: 0, y: 0};
|
90
|
+
var _prev_tap_end_time = null;
|
91
|
+
|
92
|
+
var _hold_timer = null;
|
93
|
+
|
94
|
+
var _offset = {};
|
95
|
+
|
96
|
+
// keep track of the mouse status
|
97
|
+
var _mousedown = false;
|
98
|
+
|
99
|
+
var _event_start;
|
100
|
+
var _event_move;
|
101
|
+
var _event_end;
|
102
|
+
|
103
|
+
var _has_touch = ('ontouchstart' in window);
|
104
|
+
|
105
|
+
|
106
|
+
/**
|
107
|
+
* option setter/getter
|
108
|
+
* @param string key
|
109
|
+
* @param mixed value
|
110
|
+
* @return mixed value
|
111
|
+
*/
|
112
|
+
this.option = function(key, val) {
|
113
|
+
if(val != undefined) {
|
114
|
+
options[key] = val;
|
115
|
+
}
|
116
|
+
|
117
|
+
return options[key];
|
118
|
+
};
|
119
|
+
|
120
|
+
|
121
|
+
/**
|
122
|
+
* angle to direction define
|
123
|
+
* @param float angle
|
124
|
+
* @return string direction
|
125
|
+
*/
|
126
|
+
this.getDirectionFromAngle = function( angle )
|
127
|
+
{
|
128
|
+
var directions = {
|
129
|
+
down: angle >= 45 && angle < 135, //90
|
130
|
+
left: angle >= 135 || angle <= -135, //180
|
131
|
+
up: angle < -45 && angle > -135, //270
|
132
|
+
right: angle >= -45 && angle <= 45 //0
|
133
|
+
};
|
134
|
+
|
135
|
+
var direction, key;
|
136
|
+
for(key in directions){
|
137
|
+
if(directions[key]){
|
138
|
+
direction = key;
|
139
|
+
break;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
return direction;
|
143
|
+
};
|
144
|
+
|
145
|
+
|
146
|
+
/**
|
147
|
+
* count the number of fingers in the event
|
148
|
+
* when no fingers are detected, one finger is returned (mouse pointer)
|
149
|
+
* @param event
|
150
|
+
* @return int fingers
|
151
|
+
*/
|
152
|
+
function countFingers( event )
|
153
|
+
{
|
154
|
+
// there is a bug on android (until v4?) that touches is always 1,
|
155
|
+
// so no multitouch is supported, e.g. no, zoom and rotation...
|
156
|
+
return event.touches ? event.touches.length : 1;
|
157
|
+
}
|
158
|
+
|
159
|
+
|
160
|
+
/**
|
161
|
+
* get the x and y positions from the event object
|
162
|
+
* @param event
|
163
|
+
* @return array [{ x: int, y: int }]
|
164
|
+
*/
|
165
|
+
function getXYfromEvent( event )
|
166
|
+
{
|
167
|
+
event = event || window.event;
|
168
|
+
|
169
|
+
// no touches, use the event pageX and pageY
|
170
|
+
if(!_has_touch) {
|
171
|
+
var doc = document,
|
172
|
+
body = doc.body;
|
173
|
+
|
174
|
+
return [{
|
175
|
+
x: event.pageX || event.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && doc.clientLeft || 0 ),
|
176
|
+
y: event.pageY || event.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && doc.clientTop || 0 )
|
177
|
+
}];
|
178
|
+
}
|
179
|
+
// multitouch, return array with positions
|
180
|
+
else {
|
181
|
+
var pos = [], src, touches = event.touches.length > 0 ? event.touches : event.changedTouches;
|
182
|
+
for(var t=0, len=touches.length; t<len; t++) {
|
183
|
+
src = touches[t];
|
184
|
+
pos.push({ x: src.pageX, y: src.pageY });
|
185
|
+
}
|
186
|
+
return pos;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
/**
|
192
|
+
* calculate the angle between two points
|
193
|
+
* @param object pos1 { x: int, y: int }
|
194
|
+
* @param object pos2 { x: int, y: int }
|
195
|
+
*/
|
196
|
+
function getAngle( pos1, pos2 )
|
197
|
+
{
|
198
|
+
return Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x) * 180 / Math.PI;
|
199
|
+
}
|
200
|
+
|
201
|
+
|
202
|
+
/**
|
203
|
+
* calculate the scale size between two fingers
|
204
|
+
* @param object pos_start
|
205
|
+
* @param object pos_move
|
206
|
+
* @return float scale
|
207
|
+
*/
|
208
|
+
function calculateScale(pos_start, pos_move)
|
209
|
+
{
|
210
|
+
if(pos_start.length == 2 && pos_move.length == 2) {
|
211
|
+
var x, y;
|
212
|
+
|
213
|
+
x = pos_start[0].x - pos_start[1].x;
|
214
|
+
y = pos_start[0].y - pos_start[1].y;
|
215
|
+
var start_distance = Math.sqrt((x*x) + (y*y));
|
216
|
+
|
217
|
+
x = pos_move[0].x - pos_move[1].x;
|
218
|
+
y = pos_move[0].y - pos_move[1].y;
|
219
|
+
var end_distance = Math.sqrt((x*x) + (y*y));
|
220
|
+
|
221
|
+
return end_distance / start_distance;
|
222
|
+
}
|
223
|
+
|
224
|
+
return 0;
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
/**
|
229
|
+
* calculate the rotation degrees between two fingers
|
230
|
+
* @param object pos_start
|
231
|
+
* @param object pos_move
|
232
|
+
* @return float rotation
|
233
|
+
*/
|
234
|
+
function calculateRotation(pos_start, pos_move)
|
235
|
+
{
|
236
|
+
if(pos_start.length == 2 && pos_move.length == 2) {
|
237
|
+
var x, y;
|
238
|
+
|
239
|
+
x = pos_start[0].x - pos_start[1].x;
|
240
|
+
y = pos_start[0].y - pos_start[1].y;
|
241
|
+
var start_rotation = Math.atan2(y, x) * 180 / Math.PI;
|
242
|
+
|
243
|
+
x = pos_move[0].x - pos_move[1].x;
|
244
|
+
y = pos_move[0].y - pos_move[1].y;
|
245
|
+
var end_rotation = Math.atan2(y, x) * 180 / Math.PI;
|
246
|
+
|
247
|
+
return end_rotation - start_rotation;
|
248
|
+
}
|
249
|
+
|
250
|
+
return 0;
|
251
|
+
}
|
252
|
+
|
253
|
+
|
254
|
+
/**
|
255
|
+
* trigger an event/callback by name with params
|
256
|
+
* @param string name
|
257
|
+
* @param array params
|
258
|
+
*/
|
259
|
+
function triggerEvent( eventName, params )
|
260
|
+
{
|
261
|
+
// return touches object
|
262
|
+
params.touches = getXYfromEvent(params.originalEvent);
|
263
|
+
params.type = eventName;
|
264
|
+
|
265
|
+
// trigger callback
|
266
|
+
if(isFunction(self["on"+ eventName])) {
|
267
|
+
self["on"+ eventName].call(self, params);
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
|
272
|
+
/**
|
273
|
+
* cancel event
|
274
|
+
* @param object event
|
275
|
+
* @return void
|
276
|
+
*/
|
277
|
+
|
278
|
+
function cancelEvent(event)
|
279
|
+
{
|
280
|
+
event = event || window.event;
|
281
|
+
if(event.preventDefault){
|
282
|
+
event.preventDefault();
|
283
|
+
event.stopPropagation();
|
284
|
+
}else{
|
285
|
+
event.returnValue = false;
|
286
|
+
event.cancelBubble = true;
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
|
291
|
+
/**
|
292
|
+
* reset the internal vars to the start values
|
293
|
+
*/
|
294
|
+
function reset()
|
295
|
+
{
|
296
|
+
_pos = {};
|
297
|
+
_first = false;
|
298
|
+
_fingers = 0;
|
299
|
+
_distance = 0;
|
300
|
+
_angle = 0;
|
301
|
+
_gesture = null;
|
302
|
+
}
|
303
|
+
|
304
|
+
|
305
|
+
var gestures = {
|
306
|
+
// hold gesture
|
307
|
+
// fired on touchstart
|
308
|
+
hold : function(event)
|
309
|
+
{
|
310
|
+
// only when one finger is on the screen
|
311
|
+
if(options.hold) {
|
312
|
+
_gesture = 'hold';
|
313
|
+
clearTimeout(_hold_timer);
|
314
|
+
|
315
|
+
_hold_timer = setTimeout(function() {
|
316
|
+
if(_gesture == 'hold') {
|
317
|
+
triggerEvent("hold", {
|
318
|
+
originalEvent : event,
|
319
|
+
position : _pos.start
|
320
|
+
});
|
321
|
+
}
|
322
|
+
}, options.hold_timeout);
|
323
|
+
}
|
324
|
+
},
|
325
|
+
|
326
|
+
// swipe gesture
|
327
|
+
// fired on touchend
|
328
|
+
swipe : function(event)
|
329
|
+
{
|
330
|
+
if(!_pos.move) {
|
331
|
+
return;
|
332
|
+
}
|
333
|
+
|
334
|
+
// get the distance we moved
|
335
|
+
var _distance_x = _pos.move[0].x - _pos.start[0].x;
|
336
|
+
var _distance_y = _pos.move[0].y - _pos.start[0].y;
|
337
|
+
_distance = Math.sqrt(_distance_x*_distance_x + _distance_y*_distance_y);
|
338
|
+
|
339
|
+
// compare the kind of gesture by time
|
340
|
+
var now = new Date().getTime();
|
341
|
+
var touch_time = now - _touch_start_time;
|
342
|
+
|
343
|
+
if(options.swipe && (options.swipe_time > touch_time) && (_distance > options.swipe_min_distance)) {
|
344
|
+
// calculate the angle
|
345
|
+
_angle = getAngle(_pos.start[0], _pos.move[0]);
|
346
|
+
_direction = self.getDirectionFromAngle(_angle);
|
347
|
+
|
348
|
+
_gesture = 'swipe';
|
349
|
+
|
350
|
+
var position = { x: _pos.move[0].x - _offset.left,
|
351
|
+
y: _pos.move[0].y - _offset.top };
|
352
|
+
|
353
|
+
var event_obj = {
|
354
|
+
originalEvent : event,
|
355
|
+
position : position,
|
356
|
+
direction : _direction,
|
357
|
+
distance : _distance,
|
358
|
+
distanceX : _distance_x,
|
359
|
+
distanceY : _distance_y,
|
360
|
+
angle : _angle
|
361
|
+
};
|
362
|
+
|
363
|
+
// normal slide event
|
364
|
+
triggerEvent("swipe", event_obj);
|
365
|
+
}
|
366
|
+
},
|
367
|
+
|
368
|
+
|
369
|
+
// drag gesture
|
370
|
+
// fired on mousemove
|
371
|
+
drag : function(event)
|
372
|
+
{
|
373
|
+
// get the distance we moved
|
374
|
+
var _distance_x = _pos.move[0].x - _pos.start[0].x;
|
375
|
+
var _distance_y = _pos.move[0].y - _pos.start[0].y;
|
376
|
+
_distance = Math.sqrt(_distance_x * _distance_x + _distance_y * _distance_y);
|
377
|
+
|
378
|
+
// drag
|
379
|
+
// minimal movement required
|
380
|
+
if(options.drag && (_distance > options.drag_min_distance) || _gesture == 'drag') {
|
381
|
+
// calculate the angle
|
382
|
+
_angle = getAngle(_pos.start[0], _pos.move[0]);
|
383
|
+
_direction = self.getDirectionFromAngle(_angle);
|
384
|
+
|
385
|
+
// check the movement and stop if we go in the wrong direction
|
386
|
+
var is_vertical = (_direction == 'up' || _direction == 'down');
|
387
|
+
if(((is_vertical && !options.drag_vertical) || (!is_vertical && !options.drag_horizontal))
|
388
|
+
&& (_distance > options.drag_min_distance)) {
|
389
|
+
return;
|
390
|
+
}
|
391
|
+
|
392
|
+
_gesture = 'drag';
|
393
|
+
|
394
|
+
var position = { x: _pos.move[0].x - _offset.left,
|
395
|
+
y: _pos.move[0].y - _offset.top };
|
396
|
+
|
397
|
+
var event_obj = {
|
398
|
+
originalEvent : event,
|
399
|
+
position : position,
|
400
|
+
direction : _direction,
|
401
|
+
distance : _distance,
|
402
|
+
distanceX : _distance_x,
|
403
|
+
distanceY : _distance_y,
|
404
|
+
angle : _angle
|
405
|
+
};
|
406
|
+
|
407
|
+
// on the first time trigger the start event
|
408
|
+
if(_first) {
|
409
|
+
triggerEvent("dragstart", event_obj);
|
410
|
+
|
411
|
+
_first = false;
|
412
|
+
}
|
413
|
+
|
414
|
+
// normal slide event
|
415
|
+
triggerEvent("drag", event_obj);
|
416
|
+
|
417
|
+
cancelEvent(event);
|
418
|
+
}
|
419
|
+
},
|
420
|
+
|
421
|
+
|
422
|
+
// transform gesture
|
423
|
+
// fired on touchmove
|
424
|
+
transform : function(event)
|
425
|
+
{
|
426
|
+
if(options.transform) {
|
427
|
+
if(countFingers(event) != 2) {
|
428
|
+
return false;
|
429
|
+
}
|
430
|
+
|
431
|
+
var rotation = calculateRotation(_pos.start, _pos.move);
|
432
|
+
var scale = calculateScale(_pos.start, _pos.move);
|
433
|
+
|
434
|
+
if(_gesture != 'drag' &&
|
435
|
+
(_gesture == 'transform' || Math.abs(1-scale) > options.scale_treshold || Math.abs(rotation) > options.rotation_treshold)) {
|
436
|
+
_gesture = 'transform';
|
437
|
+
|
438
|
+
_pos.center = { x: ((_pos.move[0].x + _pos.move[1].x) / 2) - _offset.left,
|
439
|
+
y: ((_pos.move[0].y + _pos.move[1].y) / 2) - _offset.top };
|
440
|
+
|
441
|
+
var event_obj = {
|
442
|
+
originalEvent : event,
|
443
|
+
position : _pos.center,
|
444
|
+
scale : scale,
|
445
|
+
rotation : rotation
|
446
|
+
};
|
447
|
+
|
448
|
+
// on the first time trigger the start event
|
449
|
+
if(_first) {
|
450
|
+
triggerEvent("transformstart", event_obj);
|
451
|
+
_first = false;
|
452
|
+
}
|
453
|
+
|
454
|
+
triggerEvent("transform", event_obj);
|
455
|
+
|
456
|
+
cancelEvent(event);
|
457
|
+
|
458
|
+
return true;
|
459
|
+
}
|
460
|
+
}
|
461
|
+
|
462
|
+
return false;
|
463
|
+
},
|
464
|
+
|
465
|
+
|
466
|
+
// tap and double tap gesture
|
467
|
+
// fired on touchend
|
468
|
+
tap : function(event)
|
469
|
+
{
|
470
|
+
// compare the kind of gesture by time
|
471
|
+
var now = new Date().getTime();
|
472
|
+
var touch_time = now - _touch_start_time;
|
473
|
+
|
474
|
+
// dont fire when hold is fired
|
475
|
+
if(options.hold && !(options.hold && options.hold_timeout > touch_time)) {
|
476
|
+
return;
|
477
|
+
}
|
478
|
+
|
479
|
+
// when previous event was tap and the tap was max_interval ms ago
|
480
|
+
var is_double_tap = (function(){
|
481
|
+
if (_prev_tap_pos &&
|
482
|
+
options.tap_double &&
|
483
|
+
_prev_gesture == 'tap' &&
|
484
|
+
(_touch_start_time - _prev_tap_end_time) < options.tap_max_interval)
|
485
|
+
{
|
486
|
+
var x_distance = Math.abs(_prev_tap_pos[0].x - _pos.start[0].x);
|
487
|
+
var y_distance = Math.abs(_prev_tap_pos[0].y - _pos.start[0].y);
|
488
|
+
return (_prev_tap_pos && _pos.start && Math.max(x_distance, y_distance) < options.tap_double_distance);
|
489
|
+
}
|
490
|
+
return false;
|
491
|
+
})();
|
492
|
+
|
493
|
+
if(is_double_tap) {
|
494
|
+
_gesture = 'double_tap';
|
495
|
+
_prev_tap_end_time = null;
|
496
|
+
|
497
|
+
triggerEvent("doubletap", {
|
498
|
+
originalEvent : event,
|
499
|
+
position : _pos.start
|
500
|
+
});
|
501
|
+
cancelEvent(event);
|
502
|
+
}
|
503
|
+
|
504
|
+
// single tap is single touch
|
505
|
+
else {
|
506
|
+
var x_distance = (_pos.move) ? Math.abs(_pos.move[0].x - _pos.start[0].x) : 0;
|
507
|
+
var y_distance = (_pos.move) ? Math.abs(_pos.move[0].y - _pos.start[0].y) : 0;
|
508
|
+
_distance = Math.max(x_distance, y_distance);
|
509
|
+
|
510
|
+
if(_distance < options.tap_max_distance) {
|
511
|
+
_gesture = 'tap';
|
512
|
+
_prev_tap_end_time = now;
|
513
|
+
_prev_tap_pos = _pos.start;
|
514
|
+
|
515
|
+
if(options.tap) {
|
516
|
+
triggerEvent("tap", {
|
517
|
+
originalEvent : event,
|
518
|
+
position : _pos.start
|
519
|
+
});
|
520
|
+
cancelEvent(event);
|
521
|
+
}
|
522
|
+
}
|
523
|
+
}
|
524
|
+
|
525
|
+
}
|
526
|
+
|
527
|
+
};
|
528
|
+
|
529
|
+
|
530
|
+
function handleEvents(event)
|
531
|
+
{
|
532
|
+
switch(event.type)
|
533
|
+
{
|
534
|
+
case 'mousedown':
|
535
|
+
case 'touchstart':
|
536
|
+
_pos.start = getXYfromEvent(event);
|
537
|
+
_touch_start_time = new Date().getTime();
|
538
|
+
_fingers = countFingers(event);
|
539
|
+
_first = true;
|
540
|
+
_event_start = event;
|
541
|
+
|
542
|
+
// borrowed from jquery offset https://github.com/jquery/jquery/blob/master/src/offset.js
|
543
|
+
var box = element.getBoundingClientRect();
|
544
|
+
var clientTop = element.clientTop || document.body.clientTop || 0;
|
545
|
+
var clientLeft = element.clientLeft || document.body.clientLeft || 0;
|
546
|
+
var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
|
547
|
+
var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
|
548
|
+
|
549
|
+
_offset = {
|
550
|
+
top: box.top + scrollTop - clientTop,
|
551
|
+
left: box.left + scrollLeft - clientLeft
|
552
|
+
};
|
553
|
+
|
554
|
+
_mousedown = true;
|
555
|
+
|
556
|
+
// hold gesture
|
557
|
+
gestures.hold(event);
|
558
|
+
|
559
|
+
if(options.prevent_default) {
|
560
|
+
cancelEvent(event);
|
561
|
+
}
|
562
|
+
break;
|
563
|
+
|
564
|
+
case 'mousemove':
|
565
|
+
case 'touchmove':
|
566
|
+
if(!_mousedown) {
|
567
|
+
return false;
|
568
|
+
}
|
569
|
+
_event_move = event;
|
570
|
+
_pos.move = getXYfromEvent(event);
|
571
|
+
|
572
|
+
if(!gestures.transform(event)) {
|
573
|
+
gestures.drag(event);
|
574
|
+
}
|
575
|
+
break;
|
576
|
+
|
577
|
+
case 'mouseup':
|
578
|
+
case 'mouseout':
|
579
|
+
case 'touchcancel':
|
580
|
+
case 'touchend':
|
581
|
+
if(!_mousedown || (_gesture != 'transform' && event.touches && event.touches.length > 0)) {
|
582
|
+
return false;
|
583
|
+
}
|
584
|
+
|
585
|
+
_mousedown = false;
|
586
|
+
_event_end = event;
|
587
|
+
|
588
|
+
var dragging = _gesture == 'drag';
|
589
|
+
|
590
|
+
// swipe gesture
|
591
|
+
gestures.swipe(event);
|
592
|
+
|
593
|
+
|
594
|
+
// drag gesture
|
595
|
+
// dragstart is triggered, so dragend is possible
|
596
|
+
if(dragging) {
|
597
|
+
triggerEvent("dragend", {
|
598
|
+
originalEvent : event,
|
599
|
+
direction : _direction,
|
600
|
+
distance : _distance,
|
601
|
+
angle : _angle
|
602
|
+
});
|
603
|
+
}
|
604
|
+
|
605
|
+
// transform
|
606
|
+
// transformstart is triggered, so transformed is possible
|
607
|
+
else if(_gesture == 'transform') {
|
608
|
+
triggerEvent("transformend", {
|
609
|
+
originalEvent : event,
|
610
|
+
position : _pos.center,
|
611
|
+
scale : calculateScale(_pos.start, _pos.move),
|
612
|
+
rotation : calculateRotation(_pos.start, _pos.move)
|
613
|
+
});
|
614
|
+
}
|
615
|
+
else {
|
616
|
+
gestures.tap(_event_start);
|
617
|
+
}
|
618
|
+
|
619
|
+
_prev_gesture = _gesture;
|
620
|
+
|
621
|
+
// trigger release event
|
622
|
+
triggerEvent("release", {
|
623
|
+
originalEvent : event,
|
624
|
+
gesture : _gesture
|
625
|
+
});
|
626
|
+
|
627
|
+
// reset vars
|
628
|
+
reset();
|
629
|
+
break;
|
630
|
+
}
|
631
|
+
}
|
632
|
+
|
633
|
+
|
634
|
+
// bind events for touch devices
|
635
|
+
// except for windows phone 7.5, it doesnt support touch events..!
|
636
|
+
if(_has_touch) {
|
637
|
+
addEvent(element, "touchstart touchmove touchend touchcancel", handleEvents);
|
638
|
+
}
|
639
|
+
// for non-touch
|
640
|
+
else {
|
641
|
+
addEvent(element, "mouseup mousedown mousemove", handleEvents);
|
642
|
+
addEvent(element, "mouseout", function(event) {
|
643
|
+
if(!isInsideHammer(element, event.relatedTarget)) {
|
644
|
+
handleEvents(event);
|
645
|
+
}
|
646
|
+
});
|
647
|
+
}
|
648
|
+
|
649
|
+
|
650
|
+
/**
|
651
|
+
* find if element is (inside) given parent element
|
652
|
+
* @param object element
|
653
|
+
* @param object parent
|
654
|
+
* @return bool inside
|
655
|
+
*/
|
656
|
+
function isInsideHammer(parent, child) {
|
657
|
+
// get related target for IE
|
658
|
+
if(!child && window.event && window.event.toElement){
|
659
|
+
child = window.event.toElement;
|
660
|
+
}
|
661
|
+
|
662
|
+
if(parent === child){
|
663
|
+
return true;
|
664
|
+
}
|
665
|
+
|
666
|
+
// loop over parentNodes of child until we find hammer element
|
667
|
+
if(child){
|
668
|
+
var node = child.parentNode;
|
669
|
+
while(node !== null){
|
670
|
+
if(node === parent){
|
671
|
+
return true;
|
672
|
+
};
|
673
|
+
node = node.parentNode;
|
674
|
+
}
|
675
|
+
}
|
676
|
+
return false;
|
677
|
+
}
|
678
|
+
|
679
|
+
|
680
|
+
/**
|
681
|
+
* merge 2 objects into a new object
|
682
|
+
* @param object obj1
|
683
|
+
* @param object obj2
|
684
|
+
* @return object merged object
|
685
|
+
*/
|
686
|
+
function mergeObject(obj1, obj2) {
|
687
|
+
var output = {};
|
688
|
+
|
689
|
+
if(!obj2) {
|
690
|
+
return obj1;
|
691
|
+
}
|
692
|
+
|
693
|
+
for (var prop in obj1) {
|
694
|
+
if (prop in obj2) {
|
695
|
+
output[prop] = obj2[prop];
|
696
|
+
} else {
|
697
|
+
output[prop] = obj1[prop];
|
698
|
+
}
|
699
|
+
}
|
700
|
+
return output;
|
701
|
+
}
|
702
|
+
|
703
|
+
|
704
|
+
/**
|
705
|
+
* check if object is a function
|
706
|
+
* @param object obj
|
707
|
+
* @return bool is function
|
708
|
+
*/
|
709
|
+
function isFunction( obj ){
|
710
|
+
return Object.prototype.toString.call( obj ) == "[object Function]";
|
711
|
+
}
|
712
|
+
|
713
|
+
|
714
|
+
/**
|
715
|
+
* attach event
|
716
|
+
* @param node element
|
717
|
+
* @param string types
|
718
|
+
* @param object callback
|
719
|
+
*/
|
720
|
+
function addEvent(element, types, callback) {
|
721
|
+
types = types.split(" ");
|
722
|
+
for(var t= 0,len=types.length; t<len; t++) {
|
723
|
+
if(element.addEventListener){
|
724
|
+
element.addEventListener(types[t], callback, false);
|
725
|
+
}
|
726
|
+
else if(document.attachEvent){
|
727
|
+
element.attachEvent("on"+ types[t], callback);
|
728
|
+
}
|
729
|
+
}
|
730
|
+
}
|
731
|
+
}
|