1/** 2 * Thim-content-slider 3 * 4 * @author ThimPress 5 */ 6; 7(function ($) { 8 $.thimContentSlider = function (el, options) { 9 this.$el = $(el).addClass('thim-content-slider'); 10 this.$items = []; 11 this.options = $.extend({}, $.fn.thimContentSlider.defaults, options); 12 var root = this, 13 $win = $(window), 14 $doc = $(document), 15 $body = $(document.body), 16 containerWidth = 0, 17 updateTimer = null, 18 playTimer = null, 19 midElement = 0, 20 activeElement = 0, 21 viewPortWidth = 0, 22 scrolling = false, 23 currentItem = 0, 24 maxItems = 0, 25 ratio = this.options.activeItemRatio || 2.5, 26 activeItemPadding = this.options.activeItemPadding, 27 itemWidth = 0, 28 midItemWidth = 0, 29 itemsVisible = this.options.itemsVisible || 7, 30 midPosition = 0, 31 rtl = this.options.rtl, 32 navDuration = 250, 33 touch = {}, 34 isTouch = "ontouchstart" in window || window.navigator.msMaxTouchPoints, 35 events = { 36 start: isTouch ? 'touchstart' : 'mousedown', 37 move : isTouch ? 'touchmove' : 'mousemove', 38 end : isTouch ? 'touchend' : 'mouseup' 39 }, 40 _speed = '', 41 _showContent = true; 42 43 //console.log(JSON.stringify(this.options)); 44 function createItem(args) { 45 var $item = $(' \ 46 <li> \ 47 <div class="slide-content" style="margin: ' + _opt('itemPadding') + 'px;"> \ 48 ' + args.image + ' \ 49 </div> \ 50 </li> \ 51 '); 52 return $item; 53 } 54 55 function parseItems() { 56 var itemType = typeof root.options.items, 57 $items = null; 58 if (itemType == 'string') { 59 $items = $(root.options.items); 60 } else if (itemType == 'object') { 61 $items = $(root.options.items).children(); 62 } 63 if ($items) { 64 root.options.items = []; 65 $items.each(function () { 66 var $item = $(this), 67 $img = $item.find(root.options.imageSelector + ':first'), 68 $url = $img.parent(); 69 root.options.items.push({ 70 image : $img.wrapAll('<div>').parent().html(), 71 url : $url.is('a') ? $url.attr('href') : '', 72 content: $item.find(root.options.contentSelector) 73 }); 74 }); 75 } 76 //console.log(JSON.stringify(root.options.items)); 77 } 78 79 function createHTML() { 80 var $html = $(' \ 81 <div class="slides-wrapper"> \ 82 <ul class="scrollable"></ul> \ 83 </div> \ 84 <a href="prev" class="control-nav prev"></a> \ 85 <a href="next" class="control-nav next"></a> \ 86 <div class="slides-content f"></div> \ 87 <div class="slides-nav"></div>\ 88 '), 89 items = root.options.items; 90 root.$el.html($html); 91 root.$slidesWrapper = root.$el.find('.slides-wrapper'); 92 root.$scrollable = root.$el.find('.scrollable').css({ 93 marginTop : -_opt('itemPadding'), 94 marginBottom: -_opt('itemPadding') 95 }); 96 root.$slideContent = root.$el.find('.slides-content'); 97 root.$slideNav = root.$el.find('.slides-nav'); 98 for (var i = 0, n = items.length; i < n; i++) { 99 var $item = createItem({image: items[i].image}), 100 $content = $('<div class="slide-content" />').append(items[i].content); 101 root.$scrollable.append($item); 102 root.$slideContent.append($content); 103 root.$slideNav.append('<div class="item_nav"></div>'); 104 } 105 root.$items = root.$scrollable.children(); 106 107 itemsVisible = _opt('itemsVisible') <= _opt('items').length ? _opt('itemsVisible') : _opt('items').length; 108 109 if( itemsVisible > 2 ) { 110 if(!rtl) 111 midElement = Math.floor(itemsVisible / 2); 112 }else{ 113 //midElement = 0; 114 } 115 //midElement = 0; 116 117 activeElement = midElement; 118 maxItems = root.$items.length; 119 currentItem = activeElement; 120 121 root.$el 122 .on('click', '.control-nav', _controlNav) 123 .on('click', '.scrollable > li', _controlNav) 124 .on('click', '.slides-nav > .item_nav', _controlNav); 125 126 if (root.options.mouseWheel) { 127 root.$el 128 .on('mousewheel', function (e, t, n, r) { 129 e.preventDefault(); 130 if (t != -1) _prevItem(); 131 else _nextItem(); 132 }); 133 } 134 135 if (root.options.autoPlay) { 136 _autoPlay(); 137 } 138 139 if (root.options.pauseOnHover) { 140 root.$el.hover(function () { 141 _pause(); 142 }, function () { 143 _restart(); 144 }); 145 } 146 147 root.$scrollable 148 .bind(events.start, _touchStart) 149 .bind(events.move, _touchMove) 150 .bind(events.end, _touchEnd) 151 152 _initNav(); 153 root.$slideContent.children().eq(activeElement).css({opacity: 1}).addClass('current').siblings().removeClass('current'); 154 root.$slideNav.children().eq(activeElement).addClass('current').siblings().removeClass('current'); 155 } 156 157 function _touchStart() { 158 // TODO: 159 } 160 161 function _touchMove() { 162 // TODO: 163 } 164 165 function _touchEnd() { 166 // TODO: 167 } 168 169 function _showNav() { 170 if(rtl) {
171 var $nav = root.$nav, 172 navHeight = $nav.height(), 173 right = _opt('controlNav') == 'behind' ? (containerWidth - midItemWidth) / 2 - navHeight + 20 : 20; 174 $nav.show(); 175 $nav.first().css({ 176 right : right, 177 opacity: 0 178 }).stop().animate({ 179 opacity: 1, 180 right : right - 20 181 }, navDuration); 182 $nav.last().css({ 183 left : right, 184 opacity: 0 185 }).stop().animate({ 186 opacity: 1, 187 left : right - 20 188 }, navDuration); 189 } else { 190 var $nav = root.$nav, 191 navHeight = $nav.height(), 192 left = _opt('controlNav') == 'behind' ? (containerWidth - midItemWidth) / 2 - navHeight + 20 : 20; 193 $nav.show(); 194 $nav.first().css({ 195 left : left, 196 opacity: 0 197 }).stop().animate({ 198 opacity: 1, 199 left : left - 20 200 }, navDuration); 201 $nav.last().css({ 202 right : left, 203 opacity: 0 204 }).stop().animate({ 205 opacity: 1, 206 right : left - 20 207 }, navDuration); 208 } 209 } 210 211 function _hideNav() { 212 var $nav = root.$nav; 213 if(rtl) { 214 $nav.first().stop().animate({ 215 opacity: 0, 216 right : '+=20' 217 }, navDuration); 218 } else { 219 $nav.first().stop().animate({ 220 opacity: 0, 221 left : '+=20' 222 }, navDuration); 223 } 224 $nav.last().stop().animate({ 225 opacity: 0, 226 right : '+=20' 227 }, navDuration); 228 } 229 230 function _initNav() { 231 var $nav = root.$el.find('.control-nav') 232 root.$el.hover(function () { 233 root.$el.addClass('hover'); 234 //_showNav(); 235 }, function () { 236 root.$el.removeClass('hover'); 237 //_hideNav(); 238 }); 239 root.$nav = $nav; 240 } 241 242 function updateNav() { 243 var navHeight = root.$nav.height(), 244 css = { 245 top : (midItemWidth - _opt('itemPadding') * 2) / 2, 246 marginTop: -navHeight / 2 247 }; 248 if (_opt('controlNav') == 'behind') { 249 250 } 251 root.$nav.css(css); 252 } 253 254 function _getItemOffset(item) { 255 if (item.hasClass('mid-item')) { 256 return 0; 257 } 258 var itemIndex = root.$items.index(item), 259 midIndex = root.$items.index(root.$items.filter('.mid-item')), 260 offset = itemIndex - midIndex; 261 return offset; 262 } 263 264 function _controlNav(e) { 265 e.preventDefault(); 266 var nav = $(this).attr('href'); 267 switch (nav) { 268 case 'prev': 269 _prevItem(); 270 break; 271 case 'next': 272 _nextItem(); 273 break; 274 default: 275 var $item = $(e.target); 276 if (!$item.is('li')) { 277 $item = $item.closest('li'); 278 } 279 _move(_getItemOffset($item)); 280 281 } 282 } 283 284 function _animateDone(dir, callback) { 285 if (dir == 'prev') { 286 root.$items.last().remove(); 287 } else { 288 root.$items.first().remove(); 289 } 290 _getItems(); 291 root.$items.eq(midElement).addClass('mid-item').siblings().removeClass('mid-item'); 292 if (_showContent) { 293 root.$slideContent.children().eq(currentItem).stop().show().animate({opacity: 1}).siblings().hide(); 294 } 295 scrolling = false;
296 _restart(); 297 if (root.$el.hasClass('hover')) { 298 //_showNav(); 299 } 300 $.isFunction(callback) && callback.apply(root); 301 } 302 303 function _move(offset) { 304 if (offset == 0) { 305 _speed = ''; 306 _showContent = true; 307 return; 308 } else if (Math.abs(offset) == 1) { 309 _showContent = true; 310 } else { 311 _showContent = false; 312 } 313 //_hideNav(); 314 _speed = 250; 315 var dir = offset < 0 ? _prevItem : _nextItem; 316 dir.call(this, function () { 317 _move(offset < 0 ? offset + 1 : offset - 1); 318 }) 319 } 320 321 function _prevItem(callback) { 322 if (scrolling) return; 323 _pause(); 324 //_hideNav(); 325 scrolling = true; 326 root.$slideContent.children().eq(currentItem).stop().animate({opacity: 0}); 327 currentItem--; 328 if (currentItem < 0) { 329 currentItem = maxItems - 1; 330 } 331 var itemPadding = _opt('itemPadding'), 332 top = parseInt( ( midItemWidth - itemWidth ) / 2 ), 333 start = 0, 334 end = root.$items.length, 335 count = 0, 336 _done = function () { 337 count++; 338 if (count == end) { 339 _animateDone('prev', callback); 340 } 341 }; 342 var $clone = root.$items.last().clone(); 343 if(rtl) { 344 $clone.insertBefore(root.$items.first()).css({ 345 right: parseInt(root.$items.first().css('right')) - itemWidth 346 }); 347 } else { 348 $clone.insertBefore(root.$items.first()).css({ 349 left: parseInt(root.$items.first().css('left')) - itemWidth 350 }); 351 } 352 _getItems(); 353 root.$el.find('.mid-item').removeClass('mid-item'); 354 root.$items.eq(activeElement + 1).addClass('mid-item'); 355 //root.$slideNav.find('.current').removeClass('current'); 356 //root.$slideNav.eq(activeElement + 1).addClass('current'); 357 if(rtl) { 358 for (var i = start; i <= end; i++) { 359 var animation = { 360 right : midPosition - ( activeElement - i ) * itemWidth, 361 width: itemWidth, 362 top : top 363 } 364 if (i < activeElement) { 365 animation.right -= activeItemPadding; 366 } else if (i == activeElement) { 367 animation.right = midPosition; 368 animation.top = 0; 369 animation.width = midItemWidth 370 } else if (i == activeElement + 1) { 371 animation.right = midPosition + midItemWidth + activeItemPadding; 372 animation.top = top; 373 animation.width = itemWidth 374 } else { 375 animation.right += (midItemWidth - itemWidth) + activeItemPadding; 376 } 377 root.$items.eq(i).stop().show().animate(animation, _speed, _done); 378 } 379 } else { 380 for (var i = start; i <= end; i++) { 381 var animation = { 382 left : midPosition - ( activeElement - i ) * itemWidth, 383 width: itemWidth, 384 top : top 385 } 386 if (i < activeElement) { 387 animation.left -= activeItemPadding; 388 } else if (i == activeElement) { 389 animation.left = midPosition; 390 animation.top = 0; 391 animation.width = midItemWidth 392 } else if (i == activeElement + 1) { 393 animation.left = midPosition + midItemWidth + activeItemPadding; 394 animation.top = top; 395 animation.width = itemWidth 396 } else { 397 animation.left += (midItemWidth - itemWidth) + activeItemPadding; 398 } 399 root.$items.eq(i).stop().show().animate(animation, _speed, _done); 400 } 401 } 402 } 403 404 function _nextItem(callback) { 405 if (scrolling) return; 406 _pause(); 407 //_hideNav(); 408 scrolling = true; 409 root.$slideContent.children().eq(currentItem).stop().animate({opacity: 0}); 410 currentItem++; 411 if (currentItem >= maxItems) { 412 currentItem = 0; 413 } 414 var itemPadding = _opt('itemPadding'), 415 top = parseInt( ( midItemWidth - itemWidth ) / 2 ), 416 start = 0, 417 end = root.$items.length, 418 count = 0, 419 _done = function () { 420 count++; 421 if (count == end) { 422 _animateDone('next', callback); 423 } 424 }; 425 var $clone = root.$items.first().clone(); 426 if(rtl) {
427 $clone.insertAfter(root.$items.last()).css({ 428 right: parseInt(root.$items.last().css('right')) + itemWidth 429 }); 430 } else { 431 $clone.insertAfter(root.$items.last()).css({ 432 left: parseInt(root.$items.last().css('left')) + itemWidth 433 }); 434 } 435 _getItems(); 436 root.$el.find('.mid-item').removeClass('mid-item'); 437 root.$items.eq(activeElement + 1).addClass('mid-item'); 438 if(rtl) { 439 for (var i = start; i <= end; i++) { 440 var animation = { 441 right : midPosition - ( activeElement - i ) * itemWidth, 442 width: itemWidth, 443 top : top 444 } 445 if (i < activeElement) { 446 animation.right -= itemWidth + activeItemPadding; 447 } else if (i == activeElement) { 448 animation.right -= itemWidth + activeItemPadding; 449 animation.top = top; 450 animation.width = itemWidth; 451 } else if (i == activeElement + 1) { 452 animation.right = midPosition; 453 animation.top = 0; 454 animation.width = midItemWidth; 455 } else { 456 animation.right = midPosition + midItemWidth + ( i - activeElement - 2 ) * itemWidth + activeItemPadding 457 } 458 root.$items.eq(i).stop().show().animate(animation, _speed, _done); 459 } 460 } else { 461 for (var i = start; i <= end; i++) { 462 var animation = { 463 left : midPosition - ( activeElement - i ) * itemWidth, 464 width: itemWidth, 465 top : top 466 } 467 if (i < activeElement) { 468 animation.left -= itemWidth + activeItemPadding; 469 } else if (i == activeElement) { 470 animation.left -= itemWidth + activeItemPadding; 471 animation.top = top; 472 animation.width = itemWidth; 473 } else if (i == activeElement + 1) { 474 animation.left = midPosition; 475 animation.top = 0; 476 animation.width = midItemWidth; 477 } else { 478 animation.left = midPosition + midItemWidth + ( i - activeElement - 2 ) * itemWidth + activeItemPadding 479 } 480 root.$items.eq(i).stop().show().animate(animation, _speed, _done); 481 } 482 } 483 } 484 485 function _getItems() { 486 root.$items = root.$scrollable.children(); 487 } 488 489 function _opt(key) { 490 return root.options[key]; 491 } 492 493 function _autoPlay() { 494 playTimer && clearTimeout(playTimer); 495 playTimer = setTimeout(function () { 496 _autoPlay(); 497 _nextItem(); 498 }, _opt('pauseTime')) 499 } 500 501 function _pause() { 502 playTimer && clearTimeout(playTimer); 503 } 504 505 function _restart() { 506 if (_opt('autoPlay')) { 507 _autoPlay(); 508 } 509 } 510 511 function calculate(args) { 512 root.$scrollable.css("width", ""); 513 args = $.extend({ 514 itemPadding : _opt('itemPadding'), 515 itemMaxWidth: _opt('itemMaxWidth'), 516 itemsVisible: itemsVisible, 517 itemMinWidth: _opt('itemMinWidth') 518 }, args || {}); 519 containerWidth = root.$el.width(); 520 midItemWidth = parseInt( args.itemMaxWidth + 2 * args.itemPadding ); 521 itemWidth = parseInt( midItemWidth / ratio ); 522 523 524 if( args.itemsVisible > 2) { 525 viewPortWidth = itemWidth * ( args.itemsVisible - 1 ) + midItemWidth + 2 * activeItemPadding; 526 }else{ 527 viewPortWidth = itemWidth * ( args.itemsVisible - 1 ) + midItemWidth + activeItemPadding; 528 } 529 530 //console.log( viewPortWidth , containerWidth, midItemWidth, itemWidth ); 531 532 if (viewPortWidth > containerWidth) { 533 var mod = viewPortWidth - containerWidth, 534 dx = mod / ( args.itemsVisible + ratio - 1 ); 535 if (midItemWidth - dx * ratio < args.itemMinWidth) { 536 if (args.itemsVisible - 2 >= 1) { 537 args.itemsVisible -= 2; 538 calculate({ 539 itemsVisible: args.itemsVisible, 540 }); 541 return; 542 } 543 } else { 544 midItemWidth -= dx * ratio; 545 itemWidth -= dx; 546 } 547 viewPortWidth = containerWidth;//??? 548 } else { 549 root.$scrollable.width(viewPortWidth); 550 } 551 //if( args.itemsVisible ) 552 if( args.itemsVisible > 2 ) { 553 if(!rtl) 554 midPosition = parseInt( ( viewPortWidth - midItemWidth ) / 2 ); 555 }else{ 556 557 } 558 559 } 560 561 function _update() { 562 calculate(); 563 updateNav(); 564 var itemPadding = _opt('itemPadding'); 565 root.$scrollable.height(midItemWidth); 566 var left = 0, 567 top = parseInt( ( midItemWidth - itemWidth ) / 2 ), 568 start = 0, 569 end = root.$items.length - 1; 570 root.$items.hide(); 571 for (var i = start; i <= end; i++) { 572 root.$items.eq(i).show(); 573 if (i == activeElement) { 574 if(rtl) { 575 root.$items.eq(i) 576 .css({ 577 right : parseInt( midPosition ), 578 width: parseInt( midItemWidth ), 579 }) 580 .addClass('mid-item') 581 .find('.slide-content').css({ 582 margin: itemPadding 583 }); 584 } else { 585 root.$items.eq(i) 586 .css({ 587 left : parseInt( midPosition ), 588 width: parseInt( midItemWidth ), 589 }) 590 .addClass('mid-item') 591 .find('.slide-content').css({ 592 margin: itemPadding 593 }); 594 } 595 } else { 596 if(rtl) { 597 right = midPosition - ( activeElement - i ) * itemWidth; 598 if (i > activeElement) { 599 right += ( midItemWidth - itemWidth ) + activeItemPadding; 600 } else { 601 right -= activeItemPadding; 602 } 603 //itemWidth_new = parseInt( midItemWidth / ratio ); 604 root.$items.eq(i).css({ 605 width: parseInt( itemWidth ), 606 right : parseInt( right ), 607 top : parseInt( top ) 608 }).removeClass('mid-item'); 609 //midItemWidth = itemWidth_new; 610 } else { 611 left = midPosition - ( activeElement - i ) * itemWidth; 612 if (i > activeElement) { 613 left += ( midItemWidth - itemWidth ) + activeItemPadding; 614 } else { 615 left -= activeItemPadding; 616 } 617 root.$items.eq(i).css({ 618 width: parseInt( itemWidth ), 619 left : parseInt( left ), 620 top : parseInt( top ) 621 }).removeClass('mid-item'); 622 } 623 } 624 } 625 } 626 627 function update(force) { 628 if (force) { 629 _update(); 630 } else { 631 updateTimer && clearTimeout(updateTimer); 632 updateTimer = setTimeout(function () { 633 _update(); 634 }, 350) 635 } 636 } 637
638 function init() { 639 parseItems(); 640 createHTML(); 641 $win.on('resize.thim-content-slider', function () { 642 update(); 643 }).trigger('resize.thim-content-slider'); 644 _update(); 645 } 646 647 // global function 648 this.pause = _pause; 649 this.restart = _restart; 650 this.prev = _prevItem; 651 this.next = _nextItem; 652 this.update = _update; 653 this.move = _move; 654 655 init(); 656 } 657 658 $.fn.thimContentSlider = function (opt) { 659 var method = false, 660 args = []; 661 if (arguments.length > 0) { 662 if (typeof arguments[0] == 'string') { 663 method = arguments[0]; 664 for (var i = 1; i < arguments.length; i++) { 665 args[i - 1] = arguments[i]; 666 } 667 } 668 } 669 return $.each(this, function () { 670 var $el = $(this), 671 contentSlider = $el.data('thim-content-slider'); 672 if (!contentSlider) { 673 contentSlider = new $.thimContentSlider(this, opt); 674 $el.data('thim-content-slider', contentSlider); 675 } 676 if (method) { 677 if ($.isFunction(contentSlider[method])) { 678 return contentSlider[method].apply(contentSlider, args); 679 } 680 throw 'Method thimContentSlider.' + method + '() does not exists'; 681 } else { 682 return $el; 683 } 684 }); 685 } 686 687 $.fn.thimContentSlider.defaults = { 688 items : [ 689 { 690 image: '', // thumb of user or product 691 url : '', // full image of user or product to display in the light-box 692 html : '' // the content to display beside item 693 } 694 ], 695 itemMaxWidth : 200, 696 itemMinWidth : 150, 697 itemsVisible : 7, 698 itemPadding : 10, 699 activeItemRatio : 2, 700 activeItemPadding: 0, 701 mouseWheel : true, 702 autoPlay : true, 703 pauseTime : 3000, 704 pauseOnHover : true, 705 imageSelector : 'img', 706 contentSelector : '.content', 707 controlNav : 'behind' 708 } 709})(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.