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.
@@ -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,4 @@
1
+ @import 'toolkit';
2
+ @import 'singularitygs';
3
+ @import 'respond-to';
4
+ @import "sassy-buttons"
@@ -0,0 +1,4 @@
1
+ @import 'toolkit';
2
+ @import 'susy';
3
+ @import 'respond-to';
4
+ @import "sassy-buttons"
@@ -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,6 @@
1
+ ////////////////////////
2
+ // Extendables Partials
3
+ //
4
+ // All of your extendable classes, ids, and silent extendables
5
+ // should go in this file.
6
+ ////////////////////////
@@ -0,0 +1,5 @@
1
+ ////////////////////////
2
+ // Functions Partials
3
+ //
4
+ // All of your functions should go in this file.
5
+ ////////////////////////
@@ -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,5 @@
1
+ ////////////////////////
2
+ // Mixins Partials
3
+ //
4
+ // All of your mixins should go in this file.
5
+ ////////////////////////
@@ -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,5 @@
1
+ ////////////////////////
2
+ // Variables Partials
3
+ //
4
+ // All of your variables should go in this file.
5
+ ////////////////////////
@@ -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
+ }