1 /* jQuery.twinkle 0.8.0 - http://larsjung.de/jquery-twinkle/ */
13 effectOptions
: undefined,
19 effectOptions
: undefined,
24 function TwinkleEvent(offX
, offY
, element
, posX
, posY
) {
26 this.offset
= {left
: offX
, top
: offY
};
27 this.element
= element
;
28 this.position
= {left
: posX
, top
: posY
};
32 function StopEvent(element
) {
34 this.element
= element
;
41 var running
= {}; // element => {id: handle}
43 function effectStarted(element
, id
, handle
) {}
44 function effectStopped(element
, id
) {}
46 this.add = function (effect
) {
48 if (!effects
[effect
.id
]) {
49 effects
[effect
.id
] = effect
;
54 this.remove = function (effect
) {
56 if (effects
[effect
]) {
57 delete effects
[effect
];
58 } else if (effect
.id
&& effects
[effect
.id
]) {
59 delete effects
[effect
.id
];
64 this.twinkle = function (event
, options
) {
66 var settings
= $.extend({}, defaults
, options
);
67 var effect
= effects
[settings
.effect
];
70 event
.element
= event
.element
|| 'body';
71 effect
.run(event
, settings
.effectOptions
, function () {
73 if ($.isFunction(settings
.callback
)) {
81 this.stop = function (event
, options
) {
83 var settings
= $.extend({}, stopDefaults
, options
);
84 var effect
= effects
[settings
.effect
];
87 event
.element
= event
.element
|| 'body';
88 effect
.stop(event
, settings
.effectOptions
, settings
.callback
);
93 this.twinkleAtElement = function (htmlElement
, options
) {
95 var settings
= $.extend({}, defaults
, options
);
96 var $htmlElement
= $(htmlElement
);
97 var offset
= $htmlElement
.offset();
98 var position
= $htmlElement
.position();
99 var width
= $htmlElement
.outerWidth(true);
100 var height
= $htmlElement
.outerHeight(true);
101 var offX
= offset
.left
+ width
* settings
.widthRatio
;
102 var offY
= offset
.top
+ height
* settings
.heightRatio
;
103 var posX
= position
.left
+ width
* settings
.widthRatio
;
104 var posY
= position
.top
+ height
* settings
.heightRatio
;
106 return this.twinkle(new TwinkleEvent(offX
, offY
, htmlElement
, posX
, posY
), options
);
109 this.twinkleAtElements = function (htmlElements
, options
) {
112 var settings
= $.extend({}, defaults
, options
);
113 var delay
= settings
.delay
;
114 var $htmlElements
= $(htmlElements
);
115 var size
= $htmlElements
.size();
117 $htmlElements
.each(function (idx
) {
119 var htmlElement
= this;
120 var opts
= $.extend({}, options
);
122 if (idx
!== size
- 1) {
123 delete opts
.callback
;
126 setTimeout(function () {
127 self
.twinkleAtElement(htmlElement
, opts
);
130 delay
+= settings
.gap
;
135 this.stopAtElement = function (htmlElement
, options
) {
137 var settings
= $.extend({}, defaults
, options
);
138 var $htmlElement
= $(htmlElement
);
139 var offset
= $htmlElement
.offset();
140 var position
= $htmlElement
.position();
141 var width
= $htmlElement
.outerWidth(true);
142 var height
= $htmlElement
.outerHeight(true);
143 var offX
= offset
.left
+ width
* settings
.widthRatio
;
144 var offY
= offset
.top
+ height
* settings
.heightRatio
;
145 var posX
= position
.left
+ width
* settings
.widthRatio
;
146 var posY
= position
.top
+ height
* settings
.heightRatio
;
148 return this.twinkle(new TwinkleEvent(offX
, offY
, htmlElement
, posX
, posY
), options
);
151 this.stopAtElements = function (htmlElements
, options
) {
154 var settings
= $.extend({}, stopDefaults
, options
);
155 var delay
= settings
.delay
;
156 var $htmlElements
= $(htmlElements
);
157 var size
= $htmlElements
.size();
159 $htmlElements
.each(function (idx
) {
161 var htmlElement
= this,
162 opts
= $.extend({}, options
);
164 if (idx
!== size
- 1) {
165 delete opts
.callback
;
168 self
.stopAtElement(htmlElement
, opts
);
178 http://larsjung.de/modplug
182 // This function is ment to be copied into your plugin file as a local
185 // `modplug` expects a string `namespace` and a configuration object
189 // statics: hash of functions,
190 // methods: hash of functions,
191 // defaultStatic: String/function,
192 // defaultMethod: String/function
195 // For more details see <http://larsjung.de/modplug>.
196 var modplug = function (namespace, options
) {
198 /*global jQuery: true */
200 // Some references to enhance minification.
201 var slice
= [].slice
,
206 // Save the initial settings.
207 settings
= extend({}, options
),
209 // Helper function to apply default methods.
210 applyMethod = function (obj
, args
, methodName
, methods
) {
212 // If `methodName` is a function apply it to get the actual
214 methodName
= isFn(methodName
) ? methodName
.apply(obj
, args
) : methodName
;
216 // If method exists then apply it and return the result ...
217 if (isFn(methods
[methodName
])) {
218 return methods
[methodName
].apply(obj
, args
);
221 // ... otherwise raise an error.
222 $.error('Method "' + methodName
+ '" does not exist on jQuery.' + namespace);
225 // This function gets exposed as `$.<namespace>`.
226 statics = function () {
228 // Try to apply a default method.
229 return applyMethod(this, slice
.call(arguments
), settings
.defaultStatic
, statics
);
232 // This function gets exposed as `$(selector).<namespace>`.
233 methods = function (method
) {
235 // If `method` exists then apply it ...
236 if (isFn(methods
[method
])) {
237 return methods
[method
].apply(this, slice
.call(arguments
, 1));
240 // ... otherwise try to apply a default method.
241 return applyMethod(this, slice
.call(arguments
), settings
.defaultMethod
, methods
);
244 // Adds/overwrites plugin methods. This function gets exposed as
245 // `$.<namespace>.modplug` to make the plugin extendable.
246 plug = function (options
) {
249 extend(statics
, options
.statics
);
250 extend(methods
, options
.methods
);
253 // Make sure that `$.<namespace>.modplug` points to this function
254 // after adding new methods.
255 statics
.modplug
= plug
;
258 // Save objects or methods previously registered to the desired namespace.
259 // They are available via `$.<namespace>.modplug.prev`.
261 statics
: $[namespace],
262 methods
: $.fn
[namespace]
265 // Init the plugin by adding the specified statics and methods.
268 // Register the plugin.
269 $[namespace] = statics
;
270 $.fn
[namespace] = methods
;
274 var twinkler
= new Twinkler();
277 twinkle: function (element
, left
, top
, options
) {
279 twinkler
.twinkle(new TwinkleEvent(0, 0, element
, left
, top
), options
);
282 add: function (effect
) {
284 twinkler
.add(effect
);
287 remove: function (effect
) {
289 twinkler
.remove(effect
);
294 twinkle: function (options
) {
296 twinkler
.twinkleAtElements(this, options
);
299 stop: function (options
) {
301 twinkler
.stopAtElements(this, options
);
305 defaultStatic
: 'twinkle',
306 defaultMethod
: 'twinkle'
317 function blockEvents(event
) {
319 event
.stopImmediatePropagation();
320 event
.preventDefault();
324 function animation(css
, event
, settings
, callback
) {
331 if (callback
instanceof Function
) {
340 left
: event
.position
.left
- settings
.radius
,
341 top
: event
.position
.top
- settings
.radius
,
342 width
: settings
.radius
* 2,
343 height
: settings
.radius
* 2,
346 settings
.duration
* 0.5,
356 .on('click dblclick mousedown mouseenter mouseover mousemove', blockEvents
);
357 $(event
.element
).after($dot
);
360 left
: event
.position
.left
- settings
.radius
* 0.5,
361 top
: event
.position
.top
- settings
.radius
* 0.5,
362 width
: settings
.radius
,
363 height
: settings
.radius
,
366 settings
.duration
* 0.5,
381 var splashDefaults
= {
382 color
: 'rgba(255,0,0,0.5)',
387 function SplashEffect() {
389 this.id
= 'splash-css';
391 this.run = function (event
, options
, callback
) {
393 var settings
= $.extend({}, splashDefaults
, options
);
395 position
: 'absolute',
398 borderRadius
: settings
.radius
,
399 backgroundColor
: settings
.color
,
400 boxShadow
: '0 0 30px ' + settings
.color
,
401 left
: event
.position
.left
,
402 top
: event
.position
.top
,
408 animation(css
, event
, settings
, callback
);
412 var dropsDefaults
= {
413 color
: 'rgba(255,0,0,0.5)',
421 function DropsEffect() {
423 this.id
= 'drops-css';
425 this.run = function (event
, options
, callback
) {
427 var settings
= $.extend({}, dropsDefaults
, options
);
429 position
: 'absolute',
432 borderRadius
: settings
.radius
,
433 border
: settings
.width
+ 'px solid ' + settings
.color
,
434 left
: event
.position
.left
,
435 top
: event
.position
.top
,
441 function setTimer(delay
, callback
) {
442 setTimeout(function () {
443 animation(css
, event
, settings
, callback
);
450 for (i
= 0; i
< settings
.count
; i
+= 1) {
451 setTimer(delay
, i
=== settings
.count
- 1 ? callback
: undefined);
452 delay
+= settings
.delay
;
457 function DropEffect() {
459 var drops
= new DropsEffect();
461 this.id
= 'drop-css';
463 this.run = function (event
, options
, callback
) {
465 drops
.run(event
, $.extend(options
, { count
: 1 }), callback
);
469 $.twinkle
.add(new SplashEffect()).add(new DropEffect()).add(new DropsEffect());
482 function Interpolator(values
) {
486 function equiDist(values
) {
488 var dist
= 1 / (values
.length
- 1);
492 for (i
= 0; i
< values
.length
; i
+= 1) {
493 points
.push({ x
: dist
* i
, y
: values
[i
] });
498 function interpolate(p1
, p2
, x
) {
500 var m
= (p2
.y
- p1
.y
) / (p2
.x
- p1
.x
);
501 var y
= p1
.y
+ m
* (x
- p1
.x
);
506 function findSection(x
) {
508 var i
, prev
, current
;
510 for (i
= 1; i
< points
.length
; i
+= 1) {
513 if (x
>= prev
.x
&& x
<= current
.x
) {
514 return [ prev
, current
];
521 points
= equiDist(values
);
523 this.get = function (x
) {
527 x
= Math
.max(0, Math
.min(1, x
));
528 secPts
= findSection(x
);
529 return interpolate(secPts
[0], secPts
[1], x
);
533 function scaleit(x
, scale
, offset
) {
536 offset
= offset
|| 0;
537 x
= (x
- offset
) / scale
;
538 return x
>= 0 && x
<= 1 ? x
: undefined;
541 Objects
.Interpolator
= Interpolator
;
542 Objects
.Interpolator
.scale
= scaleit
;
552 var context
= ctx
.getContext();
556 this.fill = function (fillStyle
) {
558 context
.fillStyle
= fillStyle
;
563 this.stroke = function (lineWidth
, strokeStyle
) {
565 context
.lineWidth
= lineWidth
;
566 context
.strokeStyle
= strokeStyle
;
571 this.draw = function (lineWidth
, strokeStyle
, fillStyle
) {
573 this.fill(fillStyle
);
574 this.stroke(lineWidth
, strokeStyle
);
578 this.circle = function (x
, y
, radius
) {
580 context
.arc(x
, y
, radius
, 0, 2 * Math
.PI
, false);
585 function Ctx(context
) {
587 if (!context
|| !context
.canvas
) {
589 } else if (!(this instanceof Ctx
)) {
590 return new Ctx(context
);
593 var width
= $(context
.canvas
).width();
594 var height
= $(context
.canvas
).height();
596 this.getContext = function () {
601 this.getWidth = function () {
606 this.getHeight = function () {
611 this.clear = function () {
613 this.resetTransform();
614 context
.clearRect(0, 0, width
, height
);
618 this.resetTransform = function () {
620 context
.setTransform(1, 0, 0, 1, 0, 0);
624 this.translate = function (x
, y
) {
626 context
.translate(x
, y
);
630 this.rotate = function (alpha
) {
632 context
.rotate(Math
.PI
* alpha
/ 180);
636 this.opacity = function (opacity
) {
638 context
.globalAlpha
= opacity
;
642 this.path = function () {
644 return new Path(this);
654 function CanvasEffect(twinkleEvent
, width
, height
, frame
, callback
) {
656 if (!(this instanceof Objects
.CanvasEffect
)) {
657 return new Objects
.CanvasEffect(twinkleEvent
, width
, height
, frame
, callback
);
660 var element
= twinkleEvent
.element
;
661 var x
= twinkleEvent
.position
.left
;
662 var y
= twinkleEvent
.position
.top
;
664 position
: 'absolute',
667 left
: x
- width
* 0.5,
668 top
: y
- height
* 0.5,
673 this.run = function (duration
, fps
) {
676 var frameCount
= duration
/ 1000 * fps
;
677 var delta
= 1 / frameCount
;
679 function setFrameTimer(fraction
) {
681 setTimeout(function () {
687 millis
: duration
* fraction
690 }, duration
* fraction
);
698 if (callback
instanceof Function
) {
703 function blockEvents(event
) {
705 event
.stopImmediatePropagation();
706 event
.preventDefault();
710 $canvas
= jQuery('<canvas />').attr('width', width
).attr('height', height
).css(css
);
711 jQuery(element
).after($canvas
);
712 $canvas
.on('click dblclick mousedown mouseenter mouseover mousemove', blockEvents
);
713 ctx
= new Objects
.Ctx($canvas
.get(0).getContext('2d'));
715 for (i
= 0; i
<= frameCount
; i
+= 1) {
716 setFrameTimer(i
* delta
);
719 setTimeout(cleanUp
, duration
);
723 Objects
.CanvasEffect
= CanvasEffect
;
732 color
: 'rgba(255,0,0,0.5)',
737 function SplashEffect() {
741 this.run = function (twinkleEvent
, options
, callback
) {
743 var settings
= $.extend({}, defaults
, options
);
744 var size
= settings
.radius
* 2;
745 var opacityIpl
= new Objects
.Interpolator([ 0.4, 1, 0 ]);
746 var radiusIpl
= new Objects
.Interpolator([ 0, settings
.radius
]);
748 function frame(frameEvent
) {
750 var radius
= radiusIpl
.get(frameEvent
.frac
);
751 var opacity
= opacityIpl
.get(frameEvent
.frac
);
752 var ctx
= frameEvent
.ctx
;
758 .circle(ctx
.getWidth() * 0.5, ctx
.getHeight() * 0.5, radius
)
759 .fill(settings
.color
);
762 new Objects
.CanvasEffect(twinkleEvent
, size
, size
, frame
, callback
).run(settings
.duration
, 25);
766 $.twinkle
.add(new SplashEffect());
775 color
: 'rgba(255,0,0,0.5)',
781 function DropEffect() {
785 this.run = function (twinkleEvent
, options
, callback
) {
787 var settings
= $.extend({}, defaults
, options
);
788 var size
= settings
.radius
* 2;
789 var opacityIpl
= new Objects
.Interpolator([ 0.4, 1, 0 ]);
790 var radiusIpl
= new Objects
.Interpolator([ 0, settings
.radius
]);
792 function frame(frameEvent
) {
794 var radius
= radiusIpl
.get(frameEvent
.frac
);
795 var opacity
= opacityIpl
.get(frameEvent
.frac
);
796 var ctx
= frameEvent
.ctx
;
802 .circle(ctx
.getWidth() * 0.5, ctx
.getHeight() * 0.5, radius
)
803 .stroke(settings
.width
, settings
.color
);
806 new Objects
.CanvasEffect(twinkleEvent
, size
, size
, frame
, callback
).run(settings
.duration
, 25);
810 $.twinkle
.add(new DropEffect());
819 color
: 'rgba(255,0,0,0.5)',
827 function DropsEffect() {
831 this.run = function (twinkleEvent
, options
, callback
) {
833 var settings
= $.extend({}, defaults
, options
);
834 var size
= settings
.radius
* 2;
835 var opacityIpl
= new Objects
.Interpolator([ 0.4, 1, 0 ]);
836 var radiusIpl
= new Objects
.Interpolator([ 0, settings
.radius
]);
837 var scale
= (settings
.duration
- (settings
.count
- 1) * settings
.delay
) / settings
.duration
;
838 var offset
= settings
.delay
/ settings
.duration
;
840 function frame(frameEvent
) {
842 var i
, frac
, radius
, opacity
;
843 var ctx
= frameEvent
.ctx
;
844 var width
= ctx
.getWidth();
845 var height
= ctx
.getHeight();
848 for (i
= 0; i
< settings
.count
; i
+= 1) {
849 frac
= Objects
.Interpolator
.scale(frameEvent
.frac
, scale
, offset
* i
);
851 if (frac
!== undefined) {
852 radius
= radiusIpl
.get(frac
);
853 opacity
= opacityIpl
.get(frac
);
857 .circle(width
* 0.5, height
* 0.5, radius
)
858 .stroke(settings
.width
, settings
.color
);
863 new Objects
.CanvasEffect(twinkleEvent
, size
, size
, frame
, callback
).run(settings
.duration
, 25);
867 $.twinkle
.add(new DropsEffect());
876 color
: 'rgba(255,0,0,0.5)',
881 function PulseEffect() {
885 this.run = function (twinkleEvent
, options
, callback
) {
887 var settings
= $.extend({}, defaults
, options
);
888 var size
= settings
.radius
* 2;
889 var opacityIpl
= new Objects
.Interpolator([ 0, 1, 0.6, 1, 0.6, 1, 0 ]);
890 var radiusIpl
= new Objects
.Interpolator([ 0, settings
.radius
, settings
.radius
* 0.6, settings
.radius
, settings
.radius
* 0.6, settings
.radius
, 0 ]);
892 function frame(frameEvent
) {
894 var radius
= radiusIpl
.get(frameEvent
.frac
),
895 opacity
= opacityIpl
.get(frameEvent
.frac
),
896 ctx
= frameEvent
.ctx
;
902 .circle(ctx
.getWidth() * 0.5, ctx
.getHeight() * 0.5, radius
)
903 .fill(settings
.color
);
906 new Objects
.CanvasEffect(twinkleEvent
, size
, size
, frame
, callback
).run(settings
.duration
, 25);
910 $.twinkle
.add(new PulseEffect());
919 color
: 'rgba(255,0,0,0.5)',
923 satellitesRadius
: 10,
927 function OrbitEffect() {
931 this.run = function (twinkleEvent
, options
, callback
) {
933 var settings
= $.extend({}, defaults
, options
);
934 var size
= settings
.radius
* 2;
935 var opacityIpl
= new Objects
.Interpolator([ 0.4, 1, 1, 0.4 ]);
936 var r
= settings
.radius
- settings
.satellitesRadius
;
937 var radiusIpl
= new Objects
.Interpolator([ 0, r
, r
, 0 ]);
939 function frame(frameEvent
) {
941 var radius
= radiusIpl
.get(frameEvent
.frac
);
942 var opacity
= opacityIpl
.get(frameEvent
.frac
);
943 var bog
= Math
.PI
* 2 * settings
.circulations
* frameEvent
.frac
;
944 var ctx
= frameEvent
.ctx
;
950 .translate(ctx
.getWidth() * 0.5, ctx
.getHeight() * 0.5);
953 for (i
= 0; i
< settings
.satellites
; i
+= 1) {
954 bog
+= Math
.PI
* 2 / settings
.satellites
;
955 x
= Math
.cos(bog
) * radius
;
956 y
= Math
.sin(bog
) * radius
;
957 ctx
.getContext().moveTo(x
, y
);
958 path
.circle(x
, y
, settings
.satellitesRadius
);
960 path
.fill(settings
.color
);
963 new Objects
.CanvasEffect(twinkleEvent
, size
, size
, frame
, callback
).run(settings
.duration
, 25);
967 $.twinkle
.add(new OrbitEffect());