1/* 2* MultiSlider | MIT License 3* 4* Copyright (c) 2017 Trevor Blackman 5* http://www.multislider.info 6* 7*/ 8 9(function($){ 10 11 // ==== BEGINS PLUGGIN ==== 12 $.fn.multislider = function(data, callback){ 13 14 // ==== CACHE DOM ==== 15 var $multislider = $(this); 16 var $msContent = $multislider.find('.MS-content'); 17 var $msRight = $multislider.find('button.MS-right'); 18 var $msLeft = $multislider.find('button.MS-left'); 19 var $imgFirst = $msContent.find('.item:first'); 20 21 // === DETERMINE ACTION ==== 22 // string = method | object or nothing is to initialize 23 if(typeof data === 'string'){ 24 getStringArgs(data); 25 return $multislider; 26 } else if (typeof data === 'object' || typeof data ==='undefined'){ 27 init(); 28 } 29 30 // ==== PLUGGIN VARIABLES ==== 31 var $imgLast, 32 totalWidth, 33 numberVisibleSlides, 34 animateDistance, 35 animateSlideRight, 36 animateSlideLeft, 37 defaults, 38 settings, 39 animateDuration, 40 autoSlideInterval; 41 42 // = INITIALIZE = 43 function init(){ 44 minifyContent(); // minify html 45 createSettings(); // merge defaults and user provided options 46 saveData(); // add data object to DOM el with reference to animation functions, allows for methods to reference at any time 47 selectAnimations(); // choose default animation 48 } 49 50 51 // ==== EVENT HANDLERS ==== 52 $msRight.on('click', animateSlideLeft); 53 $msLeft.on('click', animateSlideRight); 54 $multislider.on('click','.MS-right, .MS-left', resetInterval); 55 $(window).on('resize', findItemWidth); 56 57 58 // ==== FUNCTIONS (for days...) ==== 59 // ================================= 60 61 function pauseAbove(){ 62 if (window.innerWidth > settings.pauseAbove){ $multislider.addClass('ms-PAUSE'); } 63 $(window).on('resize',function(){ 64 if (window.innerWidth > settings.pauseAbove){ 65 $multislider.addClass('ms-PAUSE'); 66 } else { 67 $multislider.removeClass('ms-PAUSE'); 68 } 69 }); 70 } 71 72 function pauseBelow(){ 73 if (window.innerWidth < settings.pauseBelow){ $multislider.addClass('ms-PAUSE'); } 74 $(window).on('resize',function(){ 75 if (window.innerWidth < settings.pauseBelow){ 76 $multislider.addClass('ms-PAUSE'); 77 } else { 78 $multislider.removeClass('ms-PAUSE'); 79 } 80 }); 81 } 82 83 // used if method is called after initialization 84 function getStringArgs(str){ 85 if (typeof $multislider.data(str) !== 'undefined'){ 86 $multislider.data(str)(); 87 } else { 88 console.error("Multislider currently only accepts the following methods: next, prev, pause, play"); 89 } 90 } 91 92 // saves data object to DOM element 93 function saveData(){ 94 $multislider.data({ 95 "pause":function(){ $multislider.addClass('ms-PAUSE'); }, 96 "unPause":function(){ $multislider.removeClass('ms-PAUSE'); }, 97 "continuous":function(){ $multislider.removeClass('ms-PAUSE'); continuousLeft(); }, 98 "next":function(){ overRidePause(singleLeft); }, 99 "nextAll":function(){ overRidePause(allLeft); }, 100 "prev":function(){ overRidePause(singleRight); }, 101 "prevAll":function(){ overRidePause(allRight); }, 102 "settings":settings 103 }); 104 } 105 106 // used when calling 'next', 'prev' methods 107 function overRidePause(animation){ 108 if ($multislider.hasClass('ms-PAUSE')){ 109 $multislider.removeClass('ms-PAUSE'); 110 animation(); 111 $multislider.addClass('ms-PAUSE'); 112 } else { 113 animation(); 114 } 115 resetInterval(); 116 } 117 118 // CRITICAL for items to be perfectly side-by-side without floating them 119 function minifyContent(){ 120 $msContent.contents().filter(function(){ 121 return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); 122 }).remove(); 123 } 124 125 // updated options with defaults, measure slide widths for animation calculations, carry out setting implementations 126 function createSettings() { 127 defaults = settings || { 128 continuous: false, // endless scrolling with no pauses 129 slideAll: false, // slide all visible slides, or just one at a time 130 // autoSlide: true, // DEPRECATED 131 interval: 2000, // time bewteen slide animation, 0 or 'false' prevents auto-sliding 132 duration: 500, // duration of slide animation 133 hoverPause: false, // pause slideshow on hover 134 pauseAbove: null, // pause above specified screen width 135 pauseBelow: null // pause below specified screen width 136 }; 137 138 settings = $.extend({},defaults,data); 139 140 findItemWidth(); 141 animateDuration = settings.duration; 142 143 if (settings.hoverPause){pauseHover();} 144 // autoSlide is being depricated | Feb 2 2017 145 if (settings.continuous !== true && settings.interval !== 0 && settings.interval !== false && settings.autoSlide !== false){autoSlide();} 146 if (settings.pauseAbove !== null && typeof settings.pauseAbove === 'number'){ pauseAbove(); } 147 if (settings.pauseBelow !== null && typeof settings.pauseBelow === 'number'){ pauseBelow(); } 148 } 149 150 // determine between single and multi-slide animations 151 function selectAnimations () { 152 if (settings.continuous){ 153 settings.autoSlide = false;
154 continuousLeft(); 155 } else if (settings.slideAll){ 156 animateSlideRight = $multislider.data('prevAll'); 157 animateSlideLeft = $multislider.data('nextAll'); 158 } else { 159 animateSlideRight = $multislider.data('prev'); 160 animateSlideLeft = $multislider.data('next'); 161 } 162 } 163 164 // measure slide width, for animation calculations 165 function findItemWidth(){ 166 reTargetSlides(); 167 animateDistance = $imgFirst.width(); 168 var left = parseInt($msContent.find('.item:first').css('padding-left')); 169 var right = parseInt($msContent.find('.item:first').css('padding-right')); 170 if (left !== 0){animateDistance += left;} 171 if (right !== 0){animateDistance += right;} 172 } 173 174 // recursive auto-slide loop 175 function autoSlide() { 176 autoSlideInterval = setInterval(function(){ 177 if (!$multislider.hasClass('ms-PAUSE')){ 178 animateSlideLeft(); 179 } 180 }, settings.interval); 181 } 182 183 function resetInterval() { 184 if (settings.interval !== 0 && settings.interval !== false && settings.continuous !== true){ 185 clearInterval(autoSlideInterval); 186 autoSlide(); 187 } 188 } 189 190 // target first and last visible slides before each new animation 191 function reTargetSlides(){ 192 $imgFirst = $msContent.find('.item:first'); 193 $imgLast = $msContent.find('.item:last'); 194 } 195 196 // prevent animation firing if multislider is currently animating 197 // all animations pass through this function, which emits events, and adds/removes animating class 198 function isItAnimating(callback){ 199 if(!$multislider.hasClass('ms-animating') && 200 !$multislider.hasClass('ms-HOVER') && 201 !$multislider.hasClass('ms-PAUSE')){ 202 $multislider.trigger('ms.before.animate'); // event! 203 $multislider.addClass('ms-animating'); 204 callback(); //callback is animation 205 } 206 } 207 208 // update multislider at the end of each animation 209 function doneAnimating() { 210 if($multislider.hasClass('ms-animating')){ 211 $multislider.removeClass('ms-animating'); 212 $multislider.trigger('ms.after.animate'); // event! 213 } 214 } 215 216 // logic for pausing and restarting the multislider on hover 217 function pauseHover() { 218 // continuous scroll pause slightly different 219 if(settings.continuous){ 220 $msContent.on('mouseover',function(){ 221 doneAnimating(); 222 $msContent.children('.item:first').stop(); 223 }); 224 $msContent.on('mouseout',function(){ 225 continuousLeft(); 226 }); 227 } else { 228 // regular animation pausing 229 $msContent.on('mouseover',function(){ 230 $multislider.addClass('ms-HOVER'); 231 }); 232 $msContent.on('mouseout',function(){ 233 $multislider.removeClass('ms-HOVER'); 234 }); 235 } 236 } 237 238 // calculate remaining animation, if stopped mid-animation and resuming 239 function midAnimateResume(){ 240 animateDuration = settings.duration; 241 var currentMargin = parseFloat($msContent.find('.item:first').css("margin-left")); 242 var percentageRemaining = 1-(currentMargin/-(animateDistance-1)); 243 animateDuration = percentageRemaining*animateDuration; 244 } 245 246 // determine how many slides need to be moved over, if slideAll is true 247 function calcNumSlidesToMove(){ 248 totalWidth = $msContent.width(); // total width of .MS-content containing all visible slides 249 numberVisibleSlides = Math.floor(totalWidth/animateDistance); // number of (visible) slides needed to be moved in each animation 250 } 251 252 253 // ==== ANIMATION FUNCTIONS ==== 254 // ============================= 255 function continuousLeft () { 256 isItAnimating(function(){ 257 reTargetSlides(); 258 midAnimateResume(); 259 $imgFirst.animate( 260 {marginLeft: -(animateDistance+1)}, 261 { 262 duration: animateDuration, 263 easing: "linear", 264 complete: function(){ 265 $imgFirst.insertAfter($imgLast).removeAttr("style"); 266 doneAnimating(); 267 continuousLeft (); 268 } 269 } 270 ); 271 }); 272 } 273 274 function allLeft(){ 275 isItAnimating(function(){ 276 reTargetSlides(); 277 calcNumSlidesToMove(); 278 279 var $clonedItemSet = $msContent.children('.item').clone(); 280 var filteredClones = $clonedItemSet.splice(0, numberVisibleSlides); 281 282 $msContent.append(filteredClones); 283 284 $imgFirst.animate( 285 {marginLeft: -totalWidth}, { 286 duration: animateDuration, 287 easing: "swing", 288 complete: function(){ 289 $($msContent.children('.item').splice(0,numberVisibleSlides)).remove(); 290 doneAnimating(); 291 } 292 } 293 ); 294 }); 295 } 296 297 function allRight() { 298 isItAnimating(function(){ 299 reTargetSlides(); 300 calcNumSlidesToMove(); 301 302 var numberTotalSlides = $msContent.children('.item').length; 303 var $clonedItemSet = $msContent.children('.item').clone(); 304 var filteredClones = $clonedItemSet.splice(numberTotalSlides-numberVisibleSlides,numberTotalSlides); 305 306 $($(filteredClones)[0]).css('margin-left',-totalWidth); // give clone array negative margin before preppending
307 $msContent.prepend(filteredClones); 308 309 reTargetSlides(); 310 311 $imgFirst.animate( 312 { 313 marginLeft: 0 314 }, { 315 duration: animateDuration, 316 easing: "swing", 317 complete: function(){ 318 numberTotalSlides = $msContent.find('.item').length; 319 $($msContent.find('.item').splice(numberTotalSlides-numberVisibleSlides,numberTotalSlides)).remove(); 320 $imgFirst.removeAttr('style'); 321 doneAnimating(); 322 } 323 } 324 ); 325 }); 326 } 327 328 function singleLeft(){ 329 findItemWidth(); 330 isItAnimating(function(){ 331 reTargetSlides(); 332 $imgFirst.animate( 333 { 334 marginLeft: -animateDistance 335 }, { 336 duration: animateDuration, 337 easing: "swing", 338 complete: function(){ 339 $imgFirst.detach().removeAttr('style').appendTo($msContent); 340 doneAnimating(); 341 } 342 } 343 ); 344 }); 345 346 } 347 348 function singleRight(){ 349 findItemWidth(); 350 isItAnimating(function(){ 351 reTargetSlides(); 352 $imgLast.css('margin-left',-animateDistance).prependTo($msContent); 353 $imgLast.animate( 354 { 355 marginLeft: 0 356 }, { 357 duration: animateDuration, 358 easing: "swing", 359 complete: function(){ 360 $imgLast.removeAttr("style"); 361 doneAnimating(); 362 } 363 } 364 ); 365 }); 366 367 } 368 return $multislider; 369 } 370})(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.