PageSourceSearch

http://www.cnnb.com.cn/home/html/2020/ztlb/jquery.vm-carousel.js

js cnnb.com.cn collected 2026-10-02 04:40:23 UTC 13,422 bytes, 499 lines download raw bytes

1/* ========================================================================= *\
2	vmcarousel plugin by Vedmant
3\* ========================================================================= */
4
5(function ($, window, document, undefined) {
6	"use strict";
7
8	var pluginName = 'vmcarousel';
9
10	/**
11	 * Defaults
12	 *
13	 * @type {}
14	 */
15	var defaults = {
16		delay: 4000,
17		speed: 500,
18		autoplay: true,
19		items_to_show: 0, // 0 for auto calc
20		min_items_to_show: 2,
21		items_to_slide: 1,
22		dont_cut: true,
23		centered: false,
24		start_item: 0,
25		start_item_centered: false,
26		infinite: false,
27		changed_slide: $.noop()
28	};
29
30	/**
31	 * Plugin constructor
32	 *
33	 * @param element
34	 * @param options
35	 * @constructor
36	 */
37	function Plugin(element, options) {
38		this._name = pluginName;
39		this.element = element;
40		this.$element = $(element);
41		var data_options = parse_data_options(this.$element.data('options'));
42		this.options = $.extend({}, defaults, options);
43		this.options = $.extend({}, this.options, data_options);
44		this.init();
45	}
46
47	/**
48	 * Parse data-options attribute options
49	 *
50	 * @param data_options_raw
51	 * @returns {Array}
52	 */
53	function parse_data_options(data_options_raw) {
54		if (data_options_raw === undefined) return [];
55		var options = [];
56		data_options_raw.split(';').forEach(function (el) {
57			var pair = el.split(':');
58			if (pair.length == 2) options[pair[0].trim()] = pair[1].trim();
59		});
60		return options;
61	}
62
63
64	/**
65	 * Plugin functions
66	 */
67	Plugin.prototype = {
68
69			/**
70			 * Plugin init
71			 */
72			init: function () {
73				var that = this;
74
75				// Add class
76				this.$element.addClass('vmcarousel');
77
78				// Wrap
79				this.$viewport = this.$element.wrap('<div class="vmc-viewport"></div>').parent();
80				this.$container = this.$viewport.wrap('<div class="vmc-container"></div>').parent();
81
82				// Some initial procedures with slides
83				this.init_slides();
84
85				// Items vars
86				this.$orig_items = this.$element.find('>li');
87				this.$items = this.$orig_items;
88				this.orig_items_count = this.$orig_items.length;
89				this.items_count = this.$items.length;
90				this.orig_item_width = this.$items.outerWidth(true);
91				this.item_width = this.orig_item_width;
92
93				// Other vars
94				this.current_position = 0;
95
96				// Init functions
97				this.calc_variables();
98				this.init_infinite(this.options.start_item);
99				this.init_controls();
100				this.update_state();
101
102				// Reorder slides to make start item at the center
103				if (this.options.start_item_centered)
104					this.reorder_to_center(this.options.start_item);
105
106				// Initial set slide
107				if (!this.options.infinite)
108					this.set_slide(this.options.start_item);
109				else
110					this.set_active_infinite(this.options.start_item);
111
112				// Start timer
113				if (this.options.autoplay) this.start_timer();
114
115				// Window resize event
116				$(window).resize(function () {
117					that.resize()
118				});
119			},
120
121			/**
122			 * Calculate all needed variables
123			 */
124			calc_variables: function () {
125				this.viewport_width = this.$viewport.width();
126
127				// Calc items to show
128				this.items_to_show = this.options.items_to_show;
129				if (!this.options.items_to_show || (this.orig_item_width * this.items_to_show) > this.viewport_width) {
130					this.items_to_show = Math.floor(this.viewport_width / this.orig_item_width);
131				}
132
133				// Set odd number for centered type for not to cut items
134				if (this.options.centered && this.options.dont_cut) {
135					this.items_to_show = this.items_to_show % 2 ? this.items_to_show : this.items_to_show - 1;
136				}
137
138				// Min items to show
139				if (this.items_to_show < this.options.min_items_to_show) this.items_to_show = this.options.min_items_to_show;
140
141				// Calc item width for centered or dont_cut
142				if (this.options.centered || this.options.dont_cut) {
143					this.item_width = Math.floor(this.viewport_width / this.items_to_show);
144					if (this.item_width < this.orig_item_width) this.item_width = this.orig_item_width;
145					this.$items.width(this.item_width);
146					this.full_items_width = this.item_width * this.items_count;
147					this.$element.css({
148						width: this.full_items_width + 'px'
149					});
150				}
151
152				// Calc items to slide
153				this.items_to_slide = this.options.items_to_slide;
154				if (!this.options.items_to_slide)
155					this.items_to_slide = Math.floor(this.viewport_width / this.item_width);
156				if (this.items_to_slide > this.items_to_show) this.items_to_slide = this.items_to_show;
157
158				if (this.items_to_slide <= 0) this.items_to_slide = 1;
159
160				this.hide_controls = this.items_count <= this.items_to_show;
161
162				this.infinite_initial_margin = -this.item_width;
163				if (this.items_to_show % 2 == 0) this.infinite_initial_margin += this.item_width / 2;
164
165			},
166
167			/**
168			 * Update carousel state (clases, so on)
169			 */
170			update_state: function () {
171				this.$element.css({
172					transition: 'transform ' + this.options.speed / 1000 + 's'
173				});
174
175				if (this.hide_controls) this.$container.addClass('hide-control
175s');
176				else this.$container.removeClass('hide-controls');
177			},
178
179			/**
180			 * Set slides properties
181			 */
182			init_slides: function () {
183				this.$element.find('>li').each(function (i) {
184					$(this).attr('data-slide', i);
185				});
186			},
187
188			/**
189			 * Init controls
190			 */
191			init_controls: function () {
192				var that = this;
193
194				// Controls
195				this.$btn_left = this.$container.append('<a href="" class="vmc-arrow-left"></a>').find('.vmc-arrow-left');
196				this.$btn_right = this.$container.append('<a href="" class="vmc-arrow-right"></a>').find('.vmc-arrow-right');
197
198				// Bind controls
199				this.$btn_left.click(function (e) {
200					e.preventDefault();
201					that.slide_relative(-1);
202				});
203				this.$btn_right.click(function (e) {
204					e.preventDefault();
205					that.slide_relative(1);
206				});
207			},
208
209			/**
210			 * Reorder slider to place item at the center
211			 *
212			 * @param position
213			 */
214			reorder_to_center: function (position) {
215				// Dont reorder if 2 or less items
216				if (this.orig_items_count < 3) return;
217
218				// Calc shift times and direction
219				var shift_count = Math.floor(this.orig_items_count / 2) - position;
220				var dir = shift_count > 0 ? -1 : 1;
221
222				// Shift items
223				shift_count = Math.abs(shift_count);
224				for (var i = 0; i < shift_count; i++) this.switch_slides(dir);
225			},
226
227			/**
228			 * Move to exact slide
229			 *
230			 * @param slide
231			 */
232			set_slide: function (slide) {
233				var position = this.$element.find('>
233[data-slide="' + slide + '"]').index();
234
235				this.slide_relative(position);
236			},
237
238			/**
239			 * Slide n items forth or back
240			 *
241			 * @param offset
242			 */
243			slide_relative: function (offset) {
244				if (this.options.centered && this.options.infinite)
245					this.slide_relative_centered_infinite(offset);
246				else if (this.options.centered)
247					this.slide_relative_centered(offset);
248				else
249					this.slide_relative_left(offset);
250			},
251
252			/**
253			 * Slide n items forth or back for left mode
254			 *
255			 * @param offset
256			 */
257			slide_relative_left: function (offset) {
258				var new_position = this.current_position + (offset * this.items_to_slide);
259
260				// If now is ribbon tail on go back reverse to slide_count step
261				if (this.current_position == this.items_count && offset < 0) {
262					new_position = (Math.floor(this.items_count / this.items_to_slide) + offset) * this.items_to_slide;
263
264					// Show ribbon tail (last slide to right border)
265				} else if (new_position < 0 || (this.items_to_slide > (this.items_count - new_position) && new_position < this.items_count)) {
266					new_position = this.items_count - this.items_to_show;
267
268					// Scroll to beggining
269				} else if (new_position > (this.items_count - this.items_to_show)) {
270					new_position = 0;
271				}
272
273				var margin_left = -this.item_width * new_position;
274
275				// Animate slide
276				this.animate_slide(margin_left);
277
278				this.change_slide(new_position, new_position);
279			},
280
281			/**
282			 * Slide n items forth or back for centered mode
283			 *
284			 * @param offset
285			 */
286			slide_relative_centered: function (offset) {
287				var new_position = this.current_position + (offset * this.items_to_slide);
288
289				if (new_position < 0) {
290					new_position = this.items_count - 1;
291
292					// Scroll to beggining
293				} else if (new_position >= this.items_count) {
294					new_position = 0;
295				}
296
297				var margin_left = this.viewport_width / 2 - (this.item_width * (new_position + 1) - this.item_width / 2);
298
299				// Animate slide
300				this.animate_slide(margin_left);
301
302				var new_active_slide = this.$items.eq(new_position).attr('data-slide');
303
304				this.change_slide(new_position, new_active_slide);
305			},
306
307			/**
308			 * Init infinite carousel feature
309			 */
310			init_infinite: function (start_item) {
311				if (!this.options.infinite) return;
312
313				this.make_clones();
314
315				this.calc_variables();
316
317				this.$element.css("margin-left", this.infinite_initial_margin + "px");
318
319			},
320
321			/**
322			 * Make clones for infinite carousel
323			 */
324			make_clones: function () {
325				var times = 1;
326				if (this.items_count < this.items_to_show)
327					times = Math.ceil(this.items_to_show / this.items_count);
328
329				for (var i = 0; i < times; i++) {
330					this.$element.prepend(this.$orig_items.clone().addClass('vmc-clone'));
331				}
332
333				this.$items = this.$element.find('>li');
334				this.items_count = this.$items.length;
335			},
336
337			/**
338			 * Slide n items forth or back for centered mode with infinite mode
339			 *
340			 * @param offset
341			 */
342			slide_relative_centered_infinite: function (offset) {
343				var that = this;
344
345				// Only one item to slide
346				offset = offset < 0 ? -1 : 1;
347
348				var margin_left = this.infinite_initial_margin - this.item_width * offset;
349
350				//if(this.items_to_show % 2 == 0) margin_left += this.item_width / 2;
351
352				var new_position = Math.ceil(this.items_to_show / 2) + offset;
353
354				var new_active_slide = this.$items.eq(new_position).attr('data-slide');
355
356				this.animate_slide(margin_left, function (e) {
357
358					that.switch_slides(offset);
359
360					that.$element.css("margin-left", that.infinite_initial_margin + "px");
361
362				}, 'margin');
363
364				this.change_slide(new_position, new_active_slide);
365			},
366
367			/**
368			 * Place first slide at the end or last slide before first
369			 *
370			 * @param dir
371			 */
372			switch_slides: function (dir) {
373				var that = this;
374
375				// Switch last or first item
376				if (dir > 0) {
377					that.$items.last().after(that.$items.first());
378				} else {
379					that.$items.first().before(that.$items.last());
380				}
381
382				// Reload elements
383				that.$items = that.$element.find('>li');
384			},
385
386			/**
387			 * Set first active slide for infinite carousel
388			 *
389			 */
390			set_active_infinite: function (position) {
391				var center_position = Math.ceil(this.items_to_show / 2);
392
393				for (var i = 0; i < this.orig_items_count; i++) {
394					this.switch_slides(1);
395					if (this.$items.eq(center_position).attr('data-slide') == position) {
396						this.$items.eq(center_position).addClass('vmc_active');
397						return true;
398					}
399				}
400
401				return false;
402			},
403
404			/**
405			 * Change slide
406			 *
407			 * @param new_position
408			 * @param margin_left
409			 */
410			change_slide: function (new_position, new_active_slide) {
411				var that = this;
412
413				// Update current position
414				this.current_position = new_position;
415				// Add active class
416				this.$items.removeClass('vmc_active').eq(this.current_position).addClass('vmc_active');
417				// Restart timer
418				if (this.options.autoplay) this.start_timer();
419				// Call callback
420				if (typeof this.options.changed_slide === "function") {
421					this.options.changed_slide.call(this, new_active_slide);
422				}
423			},
424
425			/**
426			 * Slide animation
427			 *
428			 * @param margin_left
429			 */
430			animate_slide: function (margin_left, complete, type) {
431				var that = this;
432
433				if (type == undefined) type = 'css3';
434				if (complete == undefined) complete = $.noop();
435
436				if (Modernizr.csstransitions && type == 'css3') {
437					this.$element.css("transform", "translate3d(" + margin_left + "px,0px,0px)");
438					this.$element.one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', complete);
439				} else {
440					this.$element.stop(true).animate({
441						'margin-left': margin_left + 'px'
442					}, this.options.speed, 'swing', complete);
443				}
444			},
445
446			/**
447			 * Resize event
448			 */
449			resize: function () {
450				this.calc_variables();
451
452				this.update_state();
453
454				// Update slider position
455				this.slide_relative(0);
456			},
457
458			/**
459			 * Start timer
460			 */
461			start_timer: function () {
462				var that = this;
463				if (this.timer_id != 0) clearTimeout(this.timer_id);
464				this.timer_id = setTimeout(function () {
465					that.slide_relative(1);
466				}, this.options.delay);
467			},
468
469			/**
470			 * Stop timer
471			 */
472			stop_timer: function () {
473				clearTimeout(this.timer_id);
474				this.timer_id = 0;
475			}
476
477		} // Plugin.prototype
478
479	/**
480	 * Attach to Jquery
481	 *
482	 * @param options
483	 * @returns {*}
484	 */
485	$.fn[pluginName] = function (options) {
486		var args = [].slice.call(arguments, 1);
487		return this.each(function () {
488			if (!$.data(this, 'plugin_' + pluginName))
489				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
490			else if ($.isFunction(Plugin.prototype[options]))
491				$.data(this, 'plugin_' + pluginName)[options].apply($.data(this, 'plugin_' + pluginName), args);
492		});
493	}
494
495	// Auto init for tags with data-vmcarousel attribute
496	$('[data-vmcarousel]').vmcarousel();
497
498})(jQuery, window, document);
499<!--ecms sync check [sync_thread_id="3bcee7cc5a424330844ab778a62d31c1" sync_date="2019-12-05 11:12:16" check_sum="3bcee7cc5a424330844ab778a62d31c1]-->

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.