ballonizer 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/examples/ballonizer_app/config.ru +59 -0
- data/examples/ballonizer_app/index.html +159 -0
- data/examples/ballonizer_js_module/index.html +196 -0
- data/lib/assets/javascripts/ballonizer.js +482 -0
- data/lib/assets/stylesheets/ballonizer.css +78 -0
- data/lib/ballonizer.rb +201 -36
- data/spec/ballonizer_spec.rb +153 -2
- data/spec/javascripts/ballonizer_spec.js +568 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-with-anchor-in-image.html +163 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-with-ballons.html +163 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-without-ballons.html +163 -0
- data/spec/javascripts/fixtures/xkcd.css +191 -0
- data/spec/javascripts/helpers/jasmine-jquery.js +660 -0
- data/spec/javascripts/helpers/jquery.simulate-ext.js +32 -0
- data/spec/javascripts/helpers/jquery.simulate.drag-n-drop.js +583 -0
- data/spec/javascripts/helpers/jquery.simulate.js +328 -0
- data/spec/javascripts/support/jasmine.yml +99 -0
- data/vendor/assets/javascripts/jquery-2.0.1.js +8837 -0
- data/vendor/assets/javascripts/jquery-ui-1.10.3.custom.min.js +6 -0
- data/vendor/assets/javascripts/jquery.json-2.4.min.js +24 -0
- data/vendor/assets/stylesheets/ui-lightness/images/animated-overlay.gif +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/jquery-ui-1.10.3.custom.min.css +5 -0
- metadata +51 -3
@@ -0,0 +1,328 @@
|
|
1
|
+
/*!
|
2
|
+
* jQuery Simulate v0.0.1 - simulate browser mouse and keyboard events
|
3
|
+
* https://github.com/jquery/jquery-simulate
|
4
|
+
*
|
5
|
+
* Copyright 2012 jQuery Foundation and other contributors
|
6
|
+
* Released under the MIT license.
|
7
|
+
* http://jquery.org/license
|
8
|
+
*
|
9
|
+
* Date: Sun Dec 9 12:15:33 2012 -0500
|
10
|
+
*/
|
11
|
+
|
12
|
+
;(function( $, undefined ) {
|
13
|
+
|
14
|
+
var rkeyEvent = /^key/,
|
15
|
+
rmouseEvent = /^(?:mouse|contextmenu)|click/;
|
16
|
+
|
17
|
+
$.fn.simulate = function( type, options ) {
|
18
|
+
return this.each(function() {
|
19
|
+
new $.simulate( this, type, options );
|
20
|
+
});
|
21
|
+
};
|
22
|
+
|
23
|
+
$.simulate = function( elem, type, options ) {
|
24
|
+
var method = $.camelCase( "simulate-" + type );
|
25
|
+
|
26
|
+
this.target = elem;
|
27
|
+
this.options = options;
|
28
|
+
|
29
|
+
if ( this[ method ] ) {
|
30
|
+
this[ method ]();
|
31
|
+
} else {
|
32
|
+
this.simulateEvent( elem, type, options );
|
33
|
+
}
|
34
|
+
};
|
35
|
+
|
36
|
+
$.extend( $.simulate, {
|
37
|
+
|
38
|
+
keyCode: {
|
39
|
+
BACKSPACE: 8,
|
40
|
+
COMMA: 188,
|
41
|
+
DELETE: 46,
|
42
|
+
DOWN: 40,
|
43
|
+
END: 35,
|
44
|
+
ENTER: 13,
|
45
|
+
ESCAPE: 27,
|
46
|
+
HOME: 36,
|
47
|
+
LEFT: 37,
|
48
|
+
NUMPAD_ADD: 107,
|
49
|
+
NUMPAD_DECIMAL: 110,
|
50
|
+
NUMPAD_DIVIDE: 111,
|
51
|
+
NUMPAD_ENTER: 108,
|
52
|
+
NUMPAD_MULTIPLY: 106,
|
53
|
+
NUMPAD_SUBTRACT: 109,
|
54
|
+
PAGE_DOWN: 34,
|
55
|
+
PAGE_UP: 33,
|
56
|
+
PERIOD: 190,
|
57
|
+
RIGHT: 39,
|
58
|
+
SPACE: 32,
|
59
|
+
TAB: 9,
|
60
|
+
UP: 38
|
61
|
+
},
|
62
|
+
|
63
|
+
buttonCode: {
|
64
|
+
LEFT: 0,
|
65
|
+
MIDDLE: 1,
|
66
|
+
RIGHT: 2
|
67
|
+
}
|
68
|
+
});
|
69
|
+
|
70
|
+
$.extend( $.simulate.prototype, {
|
71
|
+
|
72
|
+
simulateEvent: function( elem, type, options ) {
|
73
|
+
var event = this.createEvent( type, options );
|
74
|
+
this.dispatchEvent( elem, type, event, options );
|
75
|
+
},
|
76
|
+
|
77
|
+
createEvent: function( type, options ) {
|
78
|
+
if ( rkeyEvent.test( type ) ) {
|
79
|
+
return this.keyEvent( type, options );
|
80
|
+
}
|
81
|
+
|
82
|
+
if ( rmouseEvent.test( type ) ) {
|
83
|
+
return this.mouseEvent( type, options );
|
84
|
+
}
|
85
|
+
},
|
86
|
+
|
87
|
+
mouseEvent: function( type, options ) {
|
88
|
+
var event, eventDoc, doc, body;
|
89
|
+
options = $.extend({
|
90
|
+
bubbles: true,
|
91
|
+
cancelable: (type !== "mousemove"),
|
92
|
+
view: window,
|
93
|
+
detail: 0,
|
94
|
+
screenX: 0,
|
95
|
+
screenY: 0,
|
96
|
+
clientX: 1,
|
97
|
+
clientY: 1,
|
98
|
+
ctrlKey: false,
|
99
|
+
altKey: false,
|
100
|
+
shiftKey: false,
|
101
|
+
metaKey: false,
|
102
|
+
button: 0,
|
103
|
+
relatedTarget: undefined
|
104
|
+
}, options );
|
105
|
+
|
106
|
+
if ( document.createEvent ) {
|
107
|
+
event = document.createEvent( "MouseEvents" );
|
108
|
+
event.initMouseEvent( type, options.bubbles, options.cancelable,
|
109
|
+
options.view, options.detail,
|
110
|
+
options.screenX, options.screenY, options.clientX, options.clientY,
|
111
|
+
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
|
112
|
+
options.button, options.relatedTarget || document.body.parentNode );
|
113
|
+
|
114
|
+
// IE 9+ creates events with pageX and pageY set to 0.
|
115
|
+
// Trying to modify the properties throws an error,
|
116
|
+
// so we define getters to return the correct values.
|
117
|
+
if ( event.pageX === 0 && event.pageY === 0 && Object.defineProperty ) {
|
118
|
+
eventDoc = event.relatedTarget.ownerDocument || document;
|
119
|
+
doc = eventDoc.documentElement;
|
120
|
+
body = eventDoc.body;
|
121
|
+
|
122
|
+
Object.defineProperty( event, "pageX", {
|
123
|
+
get: function() {
|
124
|
+
return options.clientX +
|
125
|
+
( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
|
126
|
+
( doc && doc.clientLeft || body && body.clientLeft || 0 );
|
127
|
+
}
|
128
|
+
});
|
129
|
+
Object.defineProperty( event, "pageY", {
|
130
|
+
get: function() {
|
131
|
+
return options.clientY +
|
132
|
+
( doc && doc.scrollTop || body && body.scrollTop || 0 ) -
|
133
|
+
( doc && doc.clientTop || body && body.clientTop || 0 );
|
134
|
+
}
|
135
|
+
});
|
136
|
+
}
|
137
|
+
} else if ( document.createEventObject ) {
|
138
|
+
event = document.createEventObject();
|
139
|
+
$.extend( event, options );
|
140
|
+
// standards event.button uses constants defined here: http://msdn.microsoft.com/en-us/library/ie/ff974877(v=vs.85).aspx
|
141
|
+
// old IE event.button uses constants defined here: http://msdn.microsoft.com/en-us/library/ie/ms533544(v=vs.85).aspx
|
142
|
+
// so we actually need to map the standard back to oldIE
|
143
|
+
event.button = {
|
144
|
+
0: 1,
|
145
|
+
1: 4,
|
146
|
+
2: 2
|
147
|
+
}[ event.button ] || event.button;
|
148
|
+
}
|
149
|
+
|
150
|
+
return event;
|
151
|
+
},
|
152
|
+
|
153
|
+
keyEvent: function( type, options ) {
|
154
|
+
var event;
|
155
|
+
options = $.extend({
|
156
|
+
bubbles: true,
|
157
|
+
cancelable: true,
|
158
|
+
view: window,
|
159
|
+
ctrlKey: false,
|
160
|
+
altKey: false,
|
161
|
+
shiftKey: false,
|
162
|
+
metaKey: false,
|
163
|
+
keyCode: 0,
|
164
|
+
charCode: undefined
|
165
|
+
}, options );
|
166
|
+
|
167
|
+
if ( document.createEvent ) {
|
168
|
+
try {
|
169
|
+
event = document.createEvent( "KeyEvents" );
|
170
|
+
event.initKeyEvent( type, options.bubbles, options.cancelable, options.view,
|
171
|
+
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
|
172
|
+
options.keyCode, options.charCode );
|
173
|
+
// initKeyEvent throws an exception in WebKit
|
174
|
+
// see: http://stackoverflow.com/questions/6406784/initkeyevent-keypress-only-works-in-firefox-need-a-cross-browser-solution
|
175
|
+
// and also https://bugs.webkit.org/show_bug.cgi?id=13368
|
176
|
+
// fall back to a generic event until we decide to implement initKeyboardEvent
|
177
|
+
} catch( err ) {
|
178
|
+
event = document.createEvent( "Events" );
|
179
|
+
event.initEvent( type, options.bubbles, options.cancelable );
|
180
|
+
$.extend( event, {
|
181
|
+
view: options.view,
|
182
|
+
ctrlKey: options.ctrlKey,
|
183
|
+
altKey: options.altKey,
|
184
|
+
shiftKey: options.shiftKey,
|
185
|
+
metaKey: options.metaKey,
|
186
|
+
keyCode: options.keyCode,
|
187
|
+
charCode: options.charCode
|
188
|
+
});
|
189
|
+
}
|
190
|
+
} else if ( document.createEventObject ) {
|
191
|
+
event = document.createEventObject();
|
192
|
+
$.extend( event, options );
|
193
|
+
}
|
194
|
+
|
195
|
+
if ( !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ) || (({}).toString.call( window.opera ) === "[object Opera]") ) {
|
196
|
+
event.keyCode = (options.charCode > 0) ? options.charCode : options.keyCode;
|
197
|
+
event.charCode = undefined;
|
198
|
+
}
|
199
|
+
|
200
|
+
return event;
|
201
|
+
},
|
202
|
+
|
203
|
+
dispatchEvent: function( elem, type, event ) {
|
204
|
+
if ( elem.dispatchEvent ) {
|
205
|
+
elem.dispatchEvent( event );
|
206
|
+
} else if ( elem.fireEvent ) {
|
207
|
+
elem.fireEvent( "on" + type, event );
|
208
|
+
}
|
209
|
+
},
|
210
|
+
|
211
|
+
simulateFocus: function() {
|
212
|
+
var focusinEvent,
|
213
|
+
triggered = false,
|
214
|
+
element = $( this.target );
|
215
|
+
|
216
|
+
function trigger() {
|
217
|
+
triggered = true;
|
218
|
+
}
|
219
|
+
|
220
|
+
element.bind( "focus", trigger );
|
221
|
+
element[ 0 ].focus();
|
222
|
+
|
223
|
+
if ( !triggered ) {
|
224
|
+
focusinEvent = $.Event( "focusin" );
|
225
|
+
focusinEvent.preventDefault();
|
226
|
+
element.trigger( focusinEvent );
|
227
|
+
element.triggerHandler( "focus" );
|
228
|
+
}
|
229
|
+
element.unbind( "focus", trigger );
|
230
|
+
},
|
231
|
+
|
232
|
+
simulateBlur: function() {
|
233
|
+
var focusoutEvent,
|
234
|
+
triggered = false,
|
235
|
+
element = $( this.target );
|
236
|
+
|
237
|
+
function trigger() {
|
238
|
+
triggered = true;
|
239
|
+
}
|
240
|
+
|
241
|
+
element.bind( "blur", trigger );
|
242
|
+
element[ 0 ].blur();
|
243
|
+
|
244
|
+
// blur events are async in IE
|
245
|
+
setTimeout(function() {
|
246
|
+
// IE won't let the blur occur if the window is inactive
|
247
|
+
if ( element[ 0 ].ownerDocument.activeElement === element[ 0 ] ) {
|
248
|
+
element[ 0 ].ownerDocument.body.focus();
|
249
|
+
}
|
250
|
+
|
251
|
+
// Firefox won't trigger events if the window is inactive
|
252
|
+
// IE doesn't trigger events if we had to manually focus the body
|
253
|
+
if ( !triggered ) {
|
254
|
+
focusoutEvent = $.Event( "focusout" );
|
255
|
+
focusoutEvent.preventDefault();
|
256
|
+
element.trigger( focusoutEvent );
|
257
|
+
element.triggerHandler( "blur" );
|
258
|
+
}
|
259
|
+
element.unbind( "blur", trigger );
|
260
|
+
}, 1 );
|
261
|
+
}
|
262
|
+
});
|
263
|
+
|
264
|
+
|
265
|
+
|
266
|
+
/** complex events **/
|
267
|
+
|
268
|
+
function findCenter( elem ) {
|
269
|
+
var offset,
|
270
|
+
document = $( elem.ownerDocument );
|
271
|
+
elem = $( elem );
|
272
|
+
offset = elem.offset();
|
273
|
+
|
274
|
+
return {
|
275
|
+
x: offset.left + elem.outerWidth() / 2 - document.scrollLeft(),
|
276
|
+
y: offset.top + elem.outerHeight() / 2 - document.scrollTop()
|
277
|
+
};
|
278
|
+
}
|
279
|
+
|
280
|
+
function findCorner( elem ) {
|
281
|
+
var offset,
|
282
|
+
document = $( elem.ownerDocument );
|
283
|
+
elem = $( elem );
|
284
|
+
offset = elem.offset();
|
285
|
+
|
286
|
+
return {
|
287
|
+
x: offset.left - document.scrollLeft(),
|
288
|
+
y: offset.top - document.scrollTop()
|
289
|
+
};
|
290
|
+
}
|
291
|
+
|
292
|
+
$.extend( $.simulate.prototype, {
|
293
|
+
simulateDrag: function() {
|
294
|
+
var i = 0,
|
295
|
+
target = this.target,
|
296
|
+
options = this.options,
|
297
|
+
center = options.handle === "corner" ? findCorner( target ) : findCenter( target ),
|
298
|
+
x = Math.floor( center.x ),
|
299
|
+
y = Math.floor( center.y ),
|
300
|
+
coord = { clientX: x, clientY: y },
|
301
|
+
dx = options.dx || ( options.x !== undefined ? options.x - x : 0 ),
|
302
|
+
dy = options.dy || ( options.y !== undefined ? options.y - y : 0 ),
|
303
|
+
moves = options.moves || 3;
|
304
|
+
|
305
|
+
this.simulateEvent( target, "mousedown", coord );
|
306
|
+
|
307
|
+
for ( ; i < moves ; i++ ) {
|
308
|
+
x += dx / moves;
|
309
|
+
y += dy / moves;
|
310
|
+
|
311
|
+
coord = {
|
312
|
+
clientX: Math.round( x ),
|
313
|
+
clientY: Math.round( y )
|
314
|
+
};
|
315
|
+
|
316
|
+
this.simulateEvent( target.ownerDocument, "mousemove", coord );
|
317
|
+
}
|
318
|
+
|
319
|
+
if ( $.contains( document, target ) ) {
|
320
|
+
this.simulateEvent( target, "mouseup", coord );
|
321
|
+
this.simulateEvent( target, "click", coord );
|
322
|
+
} else {
|
323
|
+
this.simulateEvent( document, "mouseup", coord );
|
324
|
+
}
|
325
|
+
}
|
326
|
+
});
|
327
|
+
|
328
|
+
})( jQuery );
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# src_files
|
2
|
+
#
|
3
|
+
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
4
|
+
# Default: []
|
5
|
+
#
|
6
|
+
# EXAMPLE:
|
7
|
+
#
|
8
|
+
# src_files:
|
9
|
+
# - lib/source1.js
|
10
|
+
# - lib/source2.js
|
11
|
+
# - dist/**/*.js
|
12
|
+
#
|
13
|
+
src_files:
|
14
|
+
- 'lib/assets/javascripts/*.js'
|
15
|
+
asset_paths:
|
16
|
+
- 'vendor/assets/javascripts'
|
17
|
+
- 'spec/javascripts/helpers'
|
18
|
+
# the helpers are defined as assets to be in the sprockets path and, this way,
|
19
|
+
# we can define the order to include them in the spec file (they need to be in
|
20
|
+
# a specific order and them need to be added after a file in the vendor, i.e
|
21
|
+
# jquery)
|
22
|
+
|
23
|
+
# stylesheets
|
24
|
+
#
|
25
|
+
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
26
|
+
# Default: []
|
27
|
+
#
|
28
|
+
# EXAMPLE:
|
29
|
+
#
|
30
|
+
# stylesheets:
|
31
|
+
# - css/style.css
|
32
|
+
# - stylesheets/*.css
|
33
|
+
#
|
34
|
+
# The order is important. DO NOT ALTER
|
35
|
+
stylesheets: ['vendor/assets/stylesheets/ui-lightness/*.css',
|
36
|
+
'lib/assets/stylesheets/*.css']
|
37
|
+
|
38
|
+
# helpers
|
39
|
+
#
|
40
|
+
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
41
|
+
# Default: ["helpers/**/*.js"]
|
42
|
+
#
|
43
|
+
# EXAMPLE:
|
44
|
+
#
|
45
|
+
helpers: ["helpers/jasmine-jquery.js"]
|
46
|
+
#
|
47
|
+
# THE OTHER HELPERS ARE INCLUDED IN THE asset_paths, SEE THE asset_paths FOR
|
48
|
+
# THE EXPLANATION
|
49
|
+
#
|
50
|
+
|
51
|
+
# spec_files
|
52
|
+
#
|
53
|
+
# Return an array of filepaths relative to spec_dir to include.
|
54
|
+
# Default: ["**/*[sS]pec.js"]
|
55
|
+
#
|
56
|
+
# EXAMPLE:
|
57
|
+
#
|
58
|
+
# spec_files:
|
59
|
+
# - **/*[sS]pec.js
|
60
|
+
#
|
61
|
+
spec_files:
|
62
|
+
- '/*[sS]pec.js'
|
63
|
+
|
64
|
+
# src_dir
|
65
|
+
#
|
66
|
+
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
67
|
+
# Default: project root
|
68
|
+
#
|
69
|
+
# EXAMPLE:
|
70
|
+
#
|
71
|
+
# src_dir: public
|
72
|
+
#
|
73
|
+
# src_dir IS LEFT BLANK BECAUSE STYLESHEETS PATH IS RELATIVE TO IT, BUT WE
|
74
|
+
# HAVE STYLESHEETS IN /vendor AND IN /lib
|
75
|
+
#
|
76
|
+
|
77
|
+
# spec_dir
|
78
|
+
#
|
79
|
+
# Spec directory path. Your spec_files must be returned relative to this path.
|
80
|
+
# Default: spec/javascripts
|
81
|
+
#
|
82
|
+
# EXAMPLE:
|
83
|
+
#
|
84
|
+
# spec_dir: spec/javascripts
|
85
|
+
#
|
86
|
+
spec_dir: 'spec/javascripts'
|
87
|
+
|
88
|
+
# spec_helper
|
89
|
+
#
|
90
|
+
# Ruby file that Jasmine server will require before starting.
|
91
|
+
# Returned relative to your root path
|
92
|
+
# Default spec/support/jasmine_helper.rb
|
93
|
+
#
|
94
|
+
# EXAMPLE:
|
95
|
+
#
|
96
|
+
# spec_helper: spec/support/jasmine_helper.rb
|
97
|
+
#
|
98
|
+
|
99
|
+
|