PageSourceSearch

https://tennenseikatsu.jp/static/lib/jquery-carousel-2/jquery-carousel.js?260929023659

js tennenseikatsu.jp collected 2026-10-03 23:26:49 UTC 27,484 bytes, 924 lines download raw bytes

1/**
2 * <div class="carousel2 prevent-anim">
3 *   <div class="carousel-contents">
4 *     <div class="carousel-content">content1</div>
5 *     <div class="carousel-content">content2</div>
6 *     <div class="carousel-content">content3</div>
7 *     :
8 *   </div>
9 * </div>
10 * 
11 * initialize:
12 * $('.carousel2').carousel2();
13 *   If carousel is already initialized, do nothing.
14 *   'reset' is re-initialize.
15 * 
16 * data-carousel-anim:(|crossfade|roll-horiz|roll-down|roll-up|slidein-left|slidein-right|slidein-down|slidein-up|turn-vert|turn-horiz|flip-up|flip-down|flip-right|flip-left)
17 *     default:roll-horiz
18 * data-carousel-duration:{anim duration:number} in ms
19 *     default:500
20 * data-carousel-autoanim: (none|{delay:number}ms,{interval:number}ms)
21 *     default:7000,3000
22 * data-carousel-nav:(none|below|below-point|below-manip|over|over-point|over-manip)
23 *     default:below
24 * data-carousel-navrel:(0|1)
25 *     default:1
26 * 
27 * $carousel.carouselw() : no effect (.carousel-valid)
28 * $carousel.carousel2(cmd, arg)
29 *   play,pause,rewind,stop : manipulate autoanim
30 *   reset : re-configure
31 *   destroy : stop autoanim and remove temp classes for save html
32 *   
33 *   connectsettings: connect :inputs for data-carousel-XXXX
34 *     argument:
35 *     {
36 *       anim: $input_for_anim,
37 *       duration: $input_for_duration,
38 *       autoanim: $input_for_autoanim,
39 *       nav: $input_for_nav
40 *       navrel: $input_for_navrel
41 *     }
42 */
43
44// console.error('jquery-carousel-2');
45
46$(function() {
47
48if ($('#carousel2-loaded')[0]){
49	console.error('juquery-carousel-2/jquery-carousel.js is already loaded.');
50	return;
51}
52var css_loaded = false;
53$('<div id="carousel2-loaded"></div>')
54	.appendTo('body')
55	.each(function(){ css_loaded = window.getComputedStyle(this,':before').content });
56
57if (!css_loaded) {
58	console.log('jquery-carousel2:load css');
59	$('<link></link>').attr({
60			rel:'stylesheet',
61			href:'/static/lib/jquery-carousel-2/jquery-carousel.css'
62		})
63		.appendTo('head');
64	/*
65	var css_href = $('script[src*="jquery-carousel.js"]').attr('src').replace('jqueyr-carousel.js', 'jquery-carousel.css');
66	if (!css_href) {
67		console.error('jquery-carousel.css is not found');
68	} else {
69		$('<link></link>').attr({
70				rel:'stylesheet',
71				href:css_href
72			})
73			.appendTo('head');
74	}
75	*/
76}
77
78
79if (!$.assureUniqId) {	
80	// unique id
81	$.fn.extend({
82	
83		assureUniqId: function(prefix, context) {
84			/**
85			 * assure all elements ids are unique.
86			 * if target element has already have unique id in context, no effect.
87			 * if it doesn't have id or not unique, new unique (in the world) id is assigned.
88			 * 'unique' is based on RFC4122 version4 and base62 encoded.
89			 */
90			// assign prefix + generated uuid(62) as elements id when it is not have id or id is not unique in context.
91			prefix = prefix || 'asuq-';
92			return $(this).each(function() {
93				var org_id = $(this).attr('id');
94				if (org_id) {
95					var $ids = $('[id]', context).filter(function() {
96							return this.id == org_id
97						});
98					if ($ids.length > 1) {
99						// duplicated id 
100						console.error('assureUniqId:duplicated id is found:' + org_id, $ids);
101						$(this).attr('data-duplicated-id', org_id);
102					} else {
103						// already have unique id in context
104						return;
105					}
106				}
107				$(this).attr('id', prefix + $.generateUUID4(62));
108			});
109		},
110	});
111	$.extend({
112		toBase: function(num, base) {
113			var chars, type = typeof base,
114				use_chars = false;
115			if (type == 'number') {
116				chars = '01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
117			} else if (type == 'string') {
118				chars = base;
119				base = chars.length;
120				use_chars = true;
121			} else {
122				throw new Error('invalid base (number or string):' + base);
123			}
124			if (base <= 36 && !use_chars) {
125				return Number(num).toString(base);
126			}
127			var is_negative = num < 0;
128			for (var str = '', num = Math.abs(num); num > 0; num = Math.floor(num / base)) {
129				str = chars[num % base] + str;
130			}
131			return (is_negative ? '-' : '') + str;
132		},
133	
134		generateUUID4: function(base) {
135			// based on http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
136			// version 4 (base = 16)
137			if (base < 2 || base > 62) {
138				throw new Error('invalid base (2 to 62):' + base);
139			}
140			base = base || 16;
141			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
142				var r = Math.random() * 16 | 0,
143					v = c == 'x' ? r : (r & 0x3 | 0x8);
144				return v.toString(16)
145			}).split('-').map(function(v) {
146				return $.toBase(parseInt(v, 16), base);
147			}).join('-');
148		},
149	});
150}
151
152// 'uncheck' event for input[type="radio"]
153$(document)
154	.on('click', 'input[type="radio"][name]', function(ev, data){
155		if (data && data.nofocus){
156			$(this).one('focus', function(ev){
157				ev.preventDefault();
158			});
159		}
160	})
161	.on('click change', 'input[type="radio"][name]', function(ev, data) {
162		var $this = $(this),
163			name = $this.attr('name'),
164			is_click = ev.type == 'click',
165			context = $this.closest('form')[0] || document;
166		if (!context._radio_prev || !context._radio_prev[name]) {
167			// initialize
168			if (is_click) {
169				// cancel first check
170				ev.preventDefault();
171				ev.stopPropagation();
172				ev.stopImmediatePropagation();
173				context._radio_prev = context._radio_prev || {};
174				setTimeout(function() {
175					// save default checked
176					var $group = $('input[type="radio"]', context).filter(function() {
177						return $(this).attr('name') == name;
178					});
179					context._radio_prev[name] = $group.filter(':checked');
180					// re-check this
181					$this
182						.one('focus', function(ev){ ev.preventDefault(); })
183						.trigger('click', data);
184				});
185			}
186		} else {
187			// change event
188			if (!is_click) {
189				context._radio_prev[name].trigger('uncheck');
190				context._radio_prev[name] = $this;
191			}
192		}
193	});
194
195
196// remove space chars between children
197if (!$.fn.spaceless) {
198	$.fn.spaceless = function() {
199		return $(this).contents().each(function() {
200			if (this.nodeType == 3) {
201				this.nodeValue = this.nodeValue.replace(/\s+/g, '');
202			}
203		})
204	};
205}
206
207if (!$.fn.isInVeiw) {
208	(function(){
209		
210		var VH = $(window).height();
211		$(window).on('resize', function(){
212			VH = $(window).height();
213		});
214		var ST = $(window).scrollTop(), LAST_ST = ST, SCROLLING_DOWN = false, SCROLLING_UP = false;
215		$(window).on('scroll', function(){
216			ST = $(window).scrollTop();
217			SCROLLING_DOWN = ST > LAST_ST;
218			SCROLLING_UP = ST < LAST_ST;
219			LAST_ST = ST;
220		});
221		
222		// offset, height再計算最小間隔ms
223		var METRICS_EXPIRE_MS = 100;
224		
225		$.fn.isInView = function(offset){
226			// offset = window position offset
227			offset = offset === undefined ? 0 : offset;
228			var $elm = $(this),
229				metrics = $(this).data('metrics'),
230				now = new Date().getTime();
231			if (!metrics || metrics.expire < now ) {
232				metrics = {
233					expire: now + METRICS_EXPIRE_MS,
234					offset:$elm.offset(),
235					height:$elm.outerHeight()
236				};
237				$elm.data('metrics', metrics);
238			}
239			
240			if (!metrics.offset || !metrics.height) {
241				return false;
242			}
243			
244			var et = metrics.offset.top, eb = et + metrics.height;
245			var ret = et < ST + VH + offset && eb > ST + offset && $elm.is(':visible');
246			
247			// parents scroll
248			
249			// check overflowed in parents
250			if (ret) {
251				var $p = $elm.parentsUntil('body').filter(function(){
252						return this.clientHeight != this.scrollHeight
253								&& $(this).css('overflow') != 'visible';
254					})
255					.each(function(){
256						
257						// DEBUG && console.log('isInView:checking hidden parent', this);
258						
259						var $c = $(this),
260							metrics = $c.data('metrics'),
261							now = new Date().getTime();
262						
263						if (!metrics || metrics.expire < now ) {
264							metrics = {
265								expire: now + METRICS_EXPIRE_MS,
266								offset:$c.offset(),
267								height:$c.outerHeight()
268							};
269							$c.data('metrics', metrics);
270						}
271						
272						var pt = metrics.offset.top,
273							pb = pt + metrics.height;
274						
275						if (et > pb || eb < pt ){
276							// hidden by parent scroll
277							
278							// DEBUG && console.log('isInView:hidden by parent', this);
279							
280							ret = false;
281							return false;
282						}
283					});
284			}
285			
286			// DEBUG && console.log('isInView:' + ret, $elm);
287			
288			return ret;
289		}
290		
291	})();
292	
293}
294
295/******* small support by js ******/
296$(document)
297	.on('uncheck.carousel2', '.carousel-valid > input[type="radio"]', function() {
298		// for CSS animation: set .prev-checked for last checked radio
299		var name = $(this).attr('name'),
300			$i = $(this),
301			context = $i.closest('form')[0] || document,
302			$is = $('input[type="radio"]', context).filter(function() {
303				return $(this).attr('name') == name;
304			});
305		$is.removeClass('prev-checked');
306		$(this).addClass('prev-checked');
307		
308		
309	})
310	.on('uncheck.carousel2', '.carousel-valid > input[type="radio"]', function(ev) {
311		// for reverse select
312		var $c = $(this).closest('.carousel-valid'),
313			anim_rev;
314		if ($c.is('.prevent-anim-rev')) {
315			anim_rev = false;
316			$c.removeClass('prevent-anim-rev')
317		} else if ($c.is('.force-anim-rev')) {
318			anim_rev = true;
319			$c.removeClass('force-anim-rev')
320		} else {
321			anim_rev = !($(this).nextAll(':checked')[0]);
322		}
323		$c.toggleClass('anim-rev', anim_rev);
324	})
325
326function getNextPrevLoop($carousel) {
327	var anim_type = ($carousel.attr('data-carousel-anim') || '').split('-'),
328		anim_v = !!((anim_type[1] || '').match(/^(down|up)$/)),
329		$inputs = $carousel.children('input[type="radio"]'),
330		$contents = $carousel.find('> .carousel-contents').children('.carousel-content'),
331		l = $inputs.length,
332		cur = $inputs.index($inputs.filter(':checked')),
333		next = (cur + l + 1) % l,
334		prev = (cur + l - 1) % l,
335		next_loop = next < cur,
336		prev_loop = prev > cur;
337	var ret = {
338		$carousel: $carousel,
339		anim: {
340			all: anim_type.join('-'),
341			type: anim_type[0], // crossfade, slidein, roll
342			direction: anim_type[1] || '', // left, right, down, up
343			is_vertical: (anim_type[1] || '').match(/^(down|up)$/),
344		},
345		prev: {
346			is_loop: prev_loop,
347			$input: $($inputs[prev]),
348			$content: $($contents[prev]),
349			w: $($contents[prev]).width(),
350			h: $($contents[prev]).height(),
351		},
352		cur: {
353			$input: $($inputs[cur]),
354			$content: $($contents[cur]),
355			w: $($contents[cur]).width(),
356			h: $($contents[cur]).height(),
357		},
358		next: {
359			is_loop: next_loop,
360			$input: $($inputs[next]),
361			$content: $($contents[next]),
362			w: $($contents[next]).width(),
363			h: $($contents[next]).height(),
364		},
365		toNext: function(loop) {
366			this.$carousel.toggleClass('prevent-anim-rev', this.next.is_loop);
367			// this.next.$input.trigger('click', { nofocus:true });
368			var $prev_input = this.$carousel.children('input[type="radio"]').removeClass('prev-checked')
369				.filter(':checked').addClass('prev-checked');
370			this.next.$input.prop('checked', true).trigger('change');
371			$prev_input.trigger('uncheck.carousel2');
372		},
373		toPrev: function(loop) {
374			this.$carousel.toggleClass('force-anim-rev', this.prev.is_loop);
375			// this.prev.$input.trigger('click', { nofocus:true });
376			var $prev_input = this.$carousel.children('input[type="radio"]').removeClass('prev-checked')
377				.filter(':checked').addClass('prev-checked');
378			this.prev.$input.prop('checked', true).trigger('change');
379			$prev_input.trigger('uncheck.carousel2');
380		}
381	};
382	// console.log(ret);
383	return ret;
384}
385
386// prev, next label
387$(document)
388	.on('click.carousel2', '.carousel-valid .carousel-nav-prev, .carousel-valid .carousel-nav-next', function(ev) {
389		// handle click previous / next area
390		var $carousel = $(this).closest('.carousel2'),
391			npl = getNextPrevLoop($carousel),
392			to_next = $(this).is('.carousel-nav-next'),
393			to_prev = !to_next;
394
395		// swap
396		if (($carousel.attr('data-carousel-anim') || '').match(/^roll-down$/)) {
397			to_next = [to_prev, to_prev = to_next][0];
398		}
399		to_next && npl.toNext();
400		to_prev && npl.toPrev();
401	});
402
403// mouse drag or swipe
404var _t, _o, THRESHOLD = 20;
405$(document)
406	.on('select.carousel2 selectstart.carousel2 dragstart.carousel2', '.carousel-valid  > .carousel-contents > .carousel-content', function(ev) {
407		ev.preventDefault();
408	})
409	// .on('click', '.carousel > .carousel-contents', function(ev){ _o = null; })
410	.on('mousedown.carousel2 touchstart.carousel2', '.carousel-valid > .carousel-contents', function(ev) {
411		// console.error('mousedown', ev);
412		if ((ev.type == 'mousedown' && ev.which != 1)||(ev.type == 'touchstart' && ev.originalEvent.touches[1])) {
413			return;
414		}
415		var t = ev.originalEvent.touches ? ev.originalEvent.touches[0] : ev;
416		var point = {
417			ox: t.pageX,
418			oy: t.pageY,
419			$carousel: $(this).parent()
420		};
421		_o = point;
422		// console.log(_o);
423		var nextprev = getNextPrevLoop(_o.$carousel);
424		$.extend(_o, nextprev);
425	})
426	.on('mousemove.carousel2 touchmove.carousel2', function(ev) {
427		if (!_o) {
428			return;
429		}
430		if ((ev.type == 'mousemove' && ev.which != 1)||(ev.type == 'touchmove' && ev.originalEvent.touches[1])) {
431			_o = null;
432			return;
433		}
434		// console.error('mousemove', ev);
435		var t = ev.originalEvent.touches ? ev.originalEvent.touches[0] : ev,
436			dx = t.pageX - _o.ox,
437			dy = t.pageY - _o.oy;
438		dx = Math.max(Math.min(dx, _o.cur.w), -_o.cur.w);
439		dy = Math.max(Math.min(dy, _o.cur.h), -_o.cur.h);
440
441		var d = _o.anim.is_vertical ? dy : dx,
442			to_next = d < 0,
443			to_prev = d > 0;
444
445		if (Math.abs(d) > THRESHOLD) {
446			if (_o.anim.direction == 'down' || _o.anim.direction == 'right') {
447				to_next = [to_prev, to_prev = to_next][0]; // swap
448			}
449			to_next && _o.toNext(true);
450			to_prev && _o.toPrev(true);
451			_o = null;
452		}
453	})
454	.on('mouseup.carousel2 touchend.carousel2', function(ev) {
455		_o = null;
456	});
457
458/********** control auto animation **********/
459$(document).on('mouseenter.carousel2 mouseleave.carousel2', '.carousel2.carousel-valid', function(ev){
460	$(this).toggleClass('hover', ev.type == 'mouseenter');
461});
462
463function doPlayCmd($c, cmd){
464	
465	var stat = $c.attr('data-carousel-autoanim-stat') || '';
466	
467	function play(stat){
468		// console.error('carousel:play:', $c);
469		$c.attr('data-carousel-autoanim-stat', 'playing');
470		var intervals = ($c.attr('data-carousel-autoanim') || '7000,3000').split(',');
471		var delay = parseInt(intervals[0], 10),
472			interval = parseInt(intervals[1], 10) || delay || 3000,
473			_t = $c.data('carousel-t');
474		clearTimeout(_t);
475		clearInterval(_t);
476		if (stat != 'pausing') {
477			var _t = setTimeout(function(){
478				var _t = $c.data('carousel-t');
479				clearTimeout(_t);
480				clearInterval(_t);
481				if (!$c.is('.hover') && $c.isInView()) {
482					getNextPrevLoop($c).toNext(true);
483				}
484				_t = setInterval(function(){
485					if (!$c.is('.hover') && $c.isInView()) {
486						getNextPrevLoop($c).toNext(true);
487					}
488				}, interval);
489				$c.data('carousel-t', _t);
490			}, delay);
491			$c.data('carousel-t', _t);
492		} else {
493			_t = setInterval(function(){
494				if (!$c.is('.hover') && $c.isInView()) {
495					getNextPrevLoop($c).toNext(true);
496				}
497			}, interval);
498			// getNextPrevLoop($c).toNext(true);
499			$c.data('carousel-t', _t);
500		}
501	}
502	function pause(stat){
503		// console.error('carousel:pause:', $c);
504		$c.attr('data-carousel-autoanim-stat', 'pausing');
505		var _t = $c.data('carousel-t');
506		clearTimeout(_t);
507		clearInterval(_t);
508		$c.removeData('carousel-t');
509	}
510	function stop(stat){
511		// console.error('carousel:stop:', $c);
512		$c.attr('data-carousel-autoanim-stat', 'stopped');
513		var _t = $c.data('carousel-t');
514		clearTimeout(_t);
515		clearInterval(_t);
516		$c.removeData('carousel-t');
517	}
518	function rewind(stat){
519		// console.error('carousel:rewind:', $c);
520		$c
521			.children('input[type="radio"]').removeClass('prev-checked')
522				.first().prop('checked', true).trigger('change').end()
523			.end()
524			.carousel2('reset', stat != 'playing');
525	}
526	function noeffect(stat){}
527	
528	var func = {
529		'':{
530			'play':play,
531			'stop':stop,
532			'pause':pause,
533			'rewind':rewind,
534		},
535		'playing':{
536			'play':noeffect,
537			'stop':stop,
538			'pause':pause,
539			'rewind':rewind,
540		},
541		'pausing':{
542			'play':play,
543			'stop':stop,
544			'pause':noeffect,
545			'rewind':rewind,
546		},
547		'stopped':{
548			'play':play,
549			'stop':noeffect,
550			'pause':noeffect,
551			'rewind':rewind,
552		}
553	}[stat][cmd];
554	if (func) {
555		func(stat);
556	} else {
557		console.error('carousel2:invalid stat and cmd:stat=' + stat + ':cmd=' + cmd);
558	}
559}
560
561$(document).on('click.carousel2', '.carousel-valid [data-carousel-cmd]', function(ev){
562	ev.preventDefault();
563	doPlayCmd($(this).closest('.carousel-valid'), $(this).attr('data-carousel-cmd'));
564});
565
566/*
567var ST = $(window).scrollTop(),
568	VH = $(window).height();
569$(window)
570	.on('resize', function() {
571		VH = $(window).height();
572	})
573	.on('scroll', function() {
574		ST = $(window).scrollTop();
575	});
576setInterval(function() {
577	$('.carousel-valid[data-carousel-autoanim][data-carousel-autoanim-cmd]').each(function() {
578		var $c = $(this),
579			cmd = $c.attr('data-carousel-autoanim-cmd');
580		doPlayCmd($c, cmd);
581		$c.removeAttr('data-carousel-autoanim-cmd');
582	});
583}, 100);
584*/
585
586var OPT = {
587	anim: 'roll-horiz', // '(|crolssfade|slidein-left|slidein-right|slidein-up|slidein-down|roll-horiz|roll-up|roll-down)'
588	autoanim: '7000,3000', // '<initial delay in ms>, <interval ms> )
589	duration: '500', // '<duration in ms>'
590	nav: 'under', // (null|false|''|'none'|'under'|'over') : position of point navigation
591	navrel: true, // true|false : use next/prev navigation
592};
593
594var ATTRS = ['anim', 'duration', 'autoanim' /* = delay,interval */, 'nav', 'navrel'];
595
596$.fn.carousel2 = function(opt, arg, args) {
597	opt = opt || {};
598	var cmd;
599	if (opt && typeof opt !== 'object') {
600		cmd = opt;
601		opt = null;
602	}
603	
604	return $(this).each(function() {
605		var $c = $(this);
606		
607		if (cmd) {
608			
609			console.log('carousel2():cmd:' + cmd, $c);
610			if (['play', 'stop', 'pause', 'rewind'].indexOf(cmd) >= 0) {
611				doPlayCmd($c, cmd);
612			} else if (cmd == 'destroy' || cmd == 'reset') {
613				$c.carousel2('stop')
614					.removeClass('carousel-valid hover prevent-anim prevent-anim-rev anim-rev')
615					.removeAttr('data-carouse-autoanim-stat')
616					.addClass('prevent-anim')
617					.find('>input[type="radio"]').removeClass('prev-checked')
618						.first().prop('checked', true).trigger('change').end().end();
619				if (cmd == 'reset') {
620					setTimeout(function(){
621						$c.carousel2();
622						if (arg && !$c.is('[data-carousel-autoanim="none"]')) {
623							// 'reset', true : pause at restart
624							setTimeout(function(){
625								$c.carousel2('pause');
626							});
627						}
628					});
629				}
630			} else if (cmd == 'next') {
631				getNextPrevLoop($c).toNext();
632			} else if (cmd == 'prev') {
633				getNextPrevLoop($c).toPrev();
634			} else if (cmd == 'settings') {
635				if (typeof arg === 'string') {
636					arg = { arg:arg2 };
637				}
638			} else if (cmd == 'connectsettings'){
639				if (typeof arg === 'string') {
640					arg = { arg:arg2 };
641				}
642				console.log('carousel2():connectsettings:', $c[0]);
643				$.each(arg, function(attr, $input){
644					if (!ATTRS.indexOf(attr) < 0) {
645						console.error('carousel2:connectsetting:' + attr + ' is not in ' + ATTRS.join(','));
646						return;
647					}
648					if (!$input.is(':input')) {
649						console.error('carousel2:connectsetting:$input is not :input');
650						return;
651					}
652					$input.data('carouselsetting', $input.data('carouselsetting')||[]);
653					var connected = $input.data('carouselsetting');
654					if (connected.indexOf($c[0]) >= 0){
655						console.log('carousel2():connectsettings:$input is already connected to .carousel2', $input[0], $c[0]);
656						return;
657					}
658					connected.push($c[0]);
659					$input.data('caroselsetting', connected);
660					
661					/* sync $c to $input
662					var setting = $c.attr('data-carousel-' + attr);
663					console.log('carousel2():connectsettings:' + attr + '=' + setting, $input[0]);
664					$input.val(setting);
665					*/
666					
667					$input.on('change.carousel2setting', function(ev){
668							$c.attr('data-carousel-' + attr, $(this).val())
669								.carousel2('reset');
670							var attrs = {};
671							$.each(ATTRS, function(attr, val){
672								attrs[attr] = val;
673							});
674							$c.addClass('setting-changed')
675								.trigger('changesetting', [attrs]);
676							setTimeout(function(){
677								$c.removeClass('setting-changed');
678							}, 1000);
679						})
680						.on('focus blur', function(ev){
681							var is_focus = (ev.type == 'focus'),
682								$this = $(this),
683								target_selector = {
684									anim:'.carousel-contents',
685									duration:'.carousel-contents',
686									autoanim:'.carousel-contents',
687									nav:'.carousel-nav',
688									navrel:'.carousel-nav-rel .carousel-nav-prev, .carousel-nav-rel .carousel-nav-next',
689								}[attr];
690							$c.toggleClass('setting-focused', is_focus);
691							if (target_selector) {
692								$c.find(target_selector).toggleClass('setting-focused', is_focus);
693							}
694						});
695				});
696			} else {
697				console.error('carousel2():invalid cmd:' + cmd);
698			}
699		
700		} else {
701			////// init
702			
703			if ($c.is('.carousel-invalid')) {
704				return;
705			}
706			
707			var _opt = $.extend({}, OPT, opt);
708			Object.keys(OPT).forEach(function(key) {
709				var opt_attr = $c.attr('data-carousel-' + key);
710				if (opt_attr !== undefined) {
711					_opt[key] = opt_attr;
712				}
713			});
714
715			var $contents = $c.children('.carousel-contents'),
716				$content = $contents.children('.carousel-content'),
717				$nav = $contents.next('.carousel-nav'),
718				$navrel = $contents.children('.carousel-nav-rel');
719
720			function hasValidStructure() {
721				return $content.length >= 2;
722			}
723			if (!hasValidStructure()) {
724				console.error('.carousel2 is not valid structure', $c);
725				$c.addClass('carousel-invalid');
726				return;
727			}
728			
729			$c.addClass('carousel-valid')
730				.addClass('prevent-anim')
731				.assureUniqId('carousel-')
732				.children('.carousel-contents').spaceless();
733			
734			var cid = $c.attr('id');
735			
736			console.log('$.carousel2():init:', _opt, $c);
737			
738			var _waits_d = $.Deferred(),
739				_waits_l = 0,
740				$waits = $c.find('img[src]:visible').filter(function(){
741						var has_size = !!($(this).height());
742						if (!has_size) {
743							_waits_l++;
744							return true;
745						}
746						return false;
747					})
748					.on('load error', function(ev){
749						_waits_l--;
750						if (_waits_l==0) {
751							_waits_d.resolve('all images are loaded');
752						}
753					});
754			if (!_waits_l) {
755				_waits_d.resolve('all images are already loaded');
756			} else {
757				$c.addClass('carousel-loading');
758				_waits_d.then(function(){
759					$c.removeClass('carousel-loading');
760				});
761				setTimeout(function(){
762					_waits_d.resolve('timeout');
763				}, 5000);
764			}
765			
766			if ($content.length >= min_dynamic_css_contents_num) {
767				max_dynamic_css_contents_num = $content.length;
768				makeDynamicCssForContents(min_dynamic_css_contents_num, max_dynamic_css_contents_num);
769				min_dynamic_css_contents_num = max_dynamic_css_contents_num + 1;
770			}
771			
772			$('#style-' + cid + '-duration').remove();
773			if (parseInt(duration, 10) != 500) {
774				$('<style></style>')
775					.attr('id', 'style-' + cid + '-duration')
776					.html('#' + cid + ' > .carousel-contents > .carousel-content { animation-duration:'+ _opt.duration + 'ms; ')
777					.appendTo('head');
778			}
779
780			var $i = $c.children('input[type="radio"]');
781
782			// make navigations
783			if (!_opt.nav) {
784				$nav.remove();
785			} else {
786				if (!($nav[0])) {
787					$nav = $('<div class="carousel-nav"></div>').insertAfter($contents);
788				}
789				if (!($nav.children('.carousel-nav-manip')[0])) {
790					$('<div class="carousel-nav-manip"><div class="carousel-nav-rewind" data-carousel-cmd="rewind"></div><div class="carousel-nav-stop" data-carousel-cmd="stop"></div><div class="carousel-nav-pause" data-carousel-cmd="pause"></div><div class="carousel-nav-play" data-carousel-cmd="play"></div></div>').appendTo($nav);
791				}
792			}
793			
794			if (!_opt.navrel) {
795				$navrel.remove();
796			} else if (!($navrel[0])) {
797				$navrel = $('<div class="carousel-nav-rel"><div class="carousel-nav-prev"></div><div class="carousel-nav-next"></div></div>').appendTo($contents);
798			}
799
800			// safe checked
801			var checked_idx = Math.max(0, $i.index($i.filter(':checked')));
802			
803			$i.remove();
804			$i = $();
805			$nav.children('label').remove();
806			
807			for (var i = $contents.children('.carousel-content').length; i; i--) {
808				var rid = cid + '-radio-' + i;
809				$i = $i.add(
810					$('<input type="radio">')
811					.attr({
812						id: rid,
813						name: cid + '-radio'
814					})
815					.css({
816						position:'absolute',
817						zIndex:-1,
818						width:'1px',
819						height:'1px',
820						overflow:'hidden',
821						opacity:0,
822					})
823					.prependTo($c)
824				);
825				$('<label></label>').attr('for', rid)
826					.prependTo($nav);
827			}
828			
829			// checked_idx = checked_idx < 0 ? 0 : checked_idx;
830			
831			// $($i.get(checked_idx)).prop('checked', true);
832			// has valid structure		
833
834			// animation duration
835			var duration = $c.attr('data-carousel-anim-duration');
836			if (duration) {
837				$('<style></style>').attr('id', 'style-duration-' + cid).html('#' + cid + ' .carousel-content { animation-duration:' + duration + 'ms; }').appendTo('head');
838			} else {
839				$('#style-duration-' + cid).remove();
840			}
841			
842			$i.one('change', function(){
843				$c.removeClass('prevent-anim');
844			});
845			
846			$i[checked_idx].checked = true;
847			
848			if (_opt.autoanim != 'none') {
849				_waits_d.then(function(res){
850					console.log('carousel2:auto animation start:' + res);
851					$c.carousel2('play');
852				});
853			}
854		}
855	});
856};
857
858// generate styles
859var min_dynamic_css_contents_num = 13, max_dynamic_css_contents_num = 20, tmpls, _template_loading_d;
860
861// load template css
862if (!window._jquery_carousel2_tmpls) {
863	window_jquery_carousel2_tmpls = 'loading';
864	_template_loading_d = $.Deferred();
865	$('script[src]').filter(function(){
866			return $(this).attr('src').indexOf('/jquery-carousel.js') >= 0
867		}).each(function(){
868			var url = $(this).attr('src').replace('/jquery-carousel.js', '/jquery-carousel.css');
869			// load as text
870			$.ajax({
871				type:'get',
872				url:url,
873				dataType:'text'
874			}).then(function(res){
875				if (res.substring(0, '.this-is-carousel2-stylesheet'.length) != '.this-is-carousel2-stylesheet' ){
876					return;
877				}
878				window._jquery_carousel2_tmpls = res.match(/\.carousel-template ([\u0000-\uffff]+?){([\u0000-\uffff]+?)}/mg).map(function(tmpl){
879					tmpl = tmpl.match(/^\.carousel-template ([\u0000-\uffff]+?){([\u0000-\uffff]+?)}$/m);
880					tmpl.shift();
881					return tmpl;
882				});
883				_template_loading_d.resolve();
884			});
885		});
886}
887
888function makeDynamicCssForContents(min_contents_num, max_contents_num) {
889	// make dynamic styles for carousel from stylesheet that have '.this-is-carousel-stylesheet' in first style.
890	// jquery-carousel.css located 
891	var i,l,s,r,t,c,rules = [], rules_dict = {}
892	var min_contents_num = min_contents_num == undefined ? min_dynamic_css_contents_num : min_contents_num;
893	var max_contents_num = max_contents_num == undefined ? max_dynamic_css_contents_num : max_contents_num;
894	
895	if (!window._jquery_carousel2_tmpls || window._jquery_carousel2_tmpls == 'loading') {
896		return _template_loading_d.then(function(){
897			makeDynamicCssForContents(min_contents_num, max_contents_num);
898		});
899	}
900	
901	var cssText = [];
902	window._jquery_carousel2_tmpls.forEach(function(tmpl) {
903		for (var t=[],i=min_contents_num,l=max_contents_num;i<=l;i++){
904			cssText.push(tmpl[0].split('(1)').join('(' + i + ')') + '{' + tmpl[1] + '}');
905		}
906	});
907	
908	
909	// console.log(cssText);
910	// $('#style-carousel-dynamic').remove();
911	var sid = 'style-carousel-dynamic-'+ min_contents_num +'-'+ max_contents_num;
912	$('<style></style>').attr('id', sid).html(cssText.join('\n')).appendTo('head');
913	console.log('$.carousel():extend dynamic css:#' + sid);
914	
915	var _d = $.Deferred();
916	_d.resolve();
917	return _d;
918}
919
920// makeDynamicCssForContents(min_dynamic_css_contents_num, max_dynamic_css_contents_num);
921
922$('.carousel2')
923	.carousel2();
924});

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.