PageSourceSearch

https://www.givewell.org/themes/gw_basic/scripts/lib/carousel/responsive-carousel.js?v=1.x

js givewell.org collected 2026-10-01 08:36:34 UTC 6,654 bytes, 233 lines download raw bytes

1/*
2 * responsive-carousel
3 * https://github.com/filamentgroup/responsive-carousel
4 *
5 * Copyright (c) 2012 Filament Group, Inc.
6 * Licensed under the MIT, GPL licenses.
7 */
8
9(function($) {
10
11	var pluginName = "carousel",
12		initSelector = "." + pluginName,
13		transitionAttr = "data-transition",
14		prevAttr = "data-prev",
15		prevTitleAttr = "data-prev-title",
16		nextAttr = "data-next",
17		nextTitleAttr = "data-next-title",
18		transitioningClass = pluginName + "-transitioning",
19		itemClass = pluginName + "-item",
20		activeClass = pluginName + "-active",
21		prevClass = pluginName + "-item-prev",
22		nextClass = pluginName + "-item-next",
23		inClass = pluginName + "-in",
24		outClass = pluginName + "-out",
25		navClass =  pluginName + "-nav",
26		prototype,
27		cssTransitionsSupport = (function(){
28			var prefixes = "webkit Moz O Ms".split( " " ),
29				supported = false,
30				property;
31
32			while( prefixes.length ){
33				property = prefixes.shift() + "Transition";
34
35				if ( property in document.documentElement.style !== undefined && property in document.documentElement.style !== false ) {
36					supported = true;
37					break;
38				}
39			}
40			return supported;
41		}()),
42		methods = {
43			_create: function(){
44				$( this )
45					.trigger( "beforecreate." + pluginName )
46					[ pluginName ]( "_init" )
47					[ pluginName ]( "_addNextPrev" )
48					.trigger( "create." + pluginName );
49			},
50
51			_init: function(){
52				var trans = $( this ).attr( transitionAttr );
53
54				if( !trans ){
55					cssTransitionsSupport = false;
56				}
57
58				$( this )
59					.addClass(
60						pluginName +
61						" " + ( trans ? pluginName + "-" + trans : "" ) + " "
62					)
63					.children()
64					.addClass( itemClass )
65					.first()
66					.addClass( activeClass );
67
68				$(this)[ pluginName ]( "_addNextPrevClasses" );
69				$( this ).data( pluginName + "data", "init"  );
70			},
71
72			_addNextPrevClasses: function(){
73				var $items = $( this ).find( "." + itemClass ),
74					$active = $items.filter( "." + activeClass ),
75					$next = $active.next( "." + itemClass ),
76					$prev = $active.prev( "." + itemClass );
77
78				if( !$next.length ){
79					$next = $items.first().not( "." + activeClass );
80				}
81				if( !$prev.length ){
82					$prev = $items.last().not( "." + activeClass );
83				}
84
85				$items.removeClass( prevClass + " " + nextClass );
86				$prev.addClass( prevClass );
87				$next.addClass( nextClass );
88
89			},
90
91			next: function(){
92				$( this )[ pluginName ]( "goTo", "+1" );
93			},
94
95			prev: function(){
96				$( this )[ pluginName ]( "goTo", "-1" );
97			},
98
99			goTo: function( num ){
100
101				var $self = $(this),
102					trans = $self.attr( transitionAttr ),
103					reverseClass = " " + pluginName + "-" + trans + "-reverse";
104
105				// clean up children
106				$( this ).find( "." + itemClass ).removeClass( [ outClass, inClass, reverseClass ].join( " " ) );
107
108				var $from = $( this ).find( "." + activeClass ),
109					prevs = $from.index(),
110					activeNum = ( prevs < 0 ? 0 : prevs ) + 1,
111					nextNum = typeof( num ) === "number" ? num : activeNum + parseFloat(num),
112					index = nextNum - 1,
113					carouselItems = $( this ).find( "." + itemClass ),
114					beforeGoto = "beforegoto." + pluginName,
115					$to = carouselItems.eq( index ),
116					reverse = ( typeof( num ) === "string" && !(parseFloat(num)) ) || nextNum > activeNum ? "" : reverseClass,
117					data;
118
119				$self.trigger( beforeGoto, data = {
120					$from: $from,
121					$to: $to,
122					direction: nextNum > activeNum ? "forward" : "backward"
123				});
124
125
126				// NOTE this is a quick hack to approximate the api that jQuery provides
127				//      without depending on the API (for use with similarly shaped apis)
128				if( data.isDefaultPrevented ) {
129					return;
130				}
131
132				if( !$to.length ){
133					$to = $( this ).find( "." + itemClass )[ reverse.length ? "last" : "first" ]();
134				}
135
136				if( cssTransitionsSupport ){
137					$self[ pluginName ]( "_transitionStart", $from, $to, reverse );
138				} else {
139					$to.addClass( activeClass );
140					$self[ pluginName ]( "_transitionEnd", $from, $to, reverse );
141				}
142
143				// added to allow pagination to track
144				$self.trigger( "goto." + pluginName, [ $to, index ] );
145			},
146
147			update: function(){
148				$(this).children().not( "." + navClass )
149					.addClass( itemClass )
150					.first()
151					.addClass( activeClass );
152
153				return $(this).trigger( "update." + pluginName );
154			},
155
156			_transitionStart: function( $from, $to, reverseClass ){
157				var $self = $(this);
158
159				$to.one( navigator.userAgent.indexOf( "AppleWebKit" ) > -1 ? "webkitTransitionEnd" : "transitionend otransitionend", function(){
160					$self[ pluginName ]( "_transitionEnd", $from, $to, reverseClass );
161				});
162
163				$(this).addClass( reverseClass );
164				$from.addClass( outClass );
165				$to.addClass( inClass );
166			},
167
168			_transitionEnd: function( $from, $to, reverseClass ){
169				$( this ).removeClass( reverseClass );
170				$from.removeClass( outClass + " " + activeClass );
171				$to.removeClass( inClass ).addClass( activeClass );
172				$( this )[ pluginName ]( "_addNextPrevClasses" );
173			},
174
175			_bindEventListeners: function(){
176				var $elem = $( this )
177					.bind( "click", function( e ){
178						var targ = $( e.target ).closest( "a[href='#next'],a[href='#prev']" );
179						if( targ.length ){
180							$elem[ pluginName ]( targ.is( "[href='#next']" ) ? "next" : "prev" );
181							e.preventDefault();
182						}
183					});
184
185				return this;
186			},
187
188			_addNextPrev: function(){
189				var $nav, $this = $( this ), $items, $active;
190
191				var prev = $( this ).attr( prevAttr ) || "Prev",
192					next = $( this ).attr( nextAttr ) || "Next",
193					prevTitle = $( this ).attr( prevTitleAttr) || "Previous",
194					nextTitle = $( this ).attr( nextTitleAttr) || "Next";
195
196				$nav = $("<nav class='"+ navClass +"'>" +
197					"<a href='#prev' class='prev' aria-hidden='true' title='" + prevTitle + "'>" + prev + "</a>" +
198					"<a href='#next' class='next' aria-hidden='true' title='" + nextTitle + "'>" + next + "</a>" +
199					"</nav>");
200
201				$this.trigger( "beforecreatenav." + pluginName, { $nav: $nav });
202
203				return $this.append( $nav )[ pluginName ]( "_bindEventListeners" );
204			},
205
206			destroy: function(){
207				// TODO
208			}
209		};
210
211	// Collection method.
212	$.fn[ pluginName ] = function( arrg, a, b, c ) {
213		return this.each(function() {
214
215			// if it's a method
216			if( arrg && typeof( arrg ) === "string" ){
217				return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
218			}
219
220			// don't re-init
221			if( $( this ).data( pluginName + "active" ) ){
222				return $( this );
223			}
224
225			// otherwise, init
226			$( this ).data( pluginName + "active", true );
227			$.fn[ pluginName ].prototype._create.call( this );
228		});
229	};
230
231	// add methods
232	prototype = $.extend( $.fn[ pluginName ].prototype, methods );
233}(jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.