1(function($) { 2 3$.jScrollPaneCusel = { 4 active : [] 5}; 6$.fn.jScrollPaneCusel = function(settings) 7{ 8 settings = $.extend({}, $.fn.jScrollPaneCusel.defaults, settings); 9 10 var rf = function() { return false; }; 11 12 return this.each( 13 function() 14 { 15 var $this = $(this); 16 var cuselWid = this.parentNode.offsetWidth; 17 18 19 // Switch the element's overflow to hidden to ensure we get the size of the element without the scrollbars [http://plugins.jquery.com/node/1208] 20 $this.css('overflow', 'hidden'); 21 var paneEle = this; 22 if ($(this).parent().is('.jScrollPaneContainer')) { 23 var currentScrollPosition = settings.maintainPosition ? $this.position().top : 0; 24 var $c = $(this).parent(); 25 var paneWidth = cuselWid; 26 var paneHeight = $c.outerHeight(); 27 var trackHeight = paneHeight; 28 $('>.jScrollPaneTrack, >.jScrollArrowUp, >.jScrollArrowDown', $c).remove(); 29 $this.css({'top':0}); 30 } else { 31 var currentScrollPosition = 0; 32 this.originalPadding = $this.css('paddingTop') + ' ' + $this.css('paddingRight') + ' ' + $this.css('paddingBottom') + ' ' + $this.css('paddingLeft'); 33 this.originalSidePaddingTotal = (parseInt($this.css('paddingLeft')) || 0) + (parseInt($this.css('paddingRight')) || 0); 34 35 36 var paneWidth = cuselWid; 37 var paneHeight = $this.innerHeight(); 38 var trackHeight = paneHeight; 39 $this 40 .wrap("<div class='jScrollPaneContainer'></div>") 41 .parent().css({'height':paneHeight+'px', 'width':paneWidth+'px'}); 42 if(!window.navigator.userProfile) /* for ie6 ne umenshaem width block na tolshinu bordera */ 43 { 44 var borderWid = parseInt($(this).parent().css("border-left-width"))+parseInt($(this).parent().css("border-right-width")); 45 paneWidth-=borderWid; 46 $(this) 47 .css("width",paneWidth+"px") 48 .parent().css("width",paneWidth+"px"); 49 50 } 51 // deal with text size changes (if the jquery.em plugin is included) 52 // and re-initialise the scrollPane so the track maintains the 53 // correct size 54 $(document).bind( 55 'emchange', 56 function(e, cur, prev) 57 { 58 $this.jScrollPaneCusel(settings); 59 } 60 ); 61 62 } 63 64 65 if (settings.reinitialiseOnImageLoad) { 66 // code inspired by jquery.onImagesLoad: http://plugins.jquery.com/project/onImagesLoad 67 // except we re-initialise the scroll pane when each image loads so that the scroll pane is always up to size... 68 // TODO: Do I even need to store it in $.data? Is a local variable here the same since I don't pass the reinitialiseOnImageLoad when I re-initialise? 69 var $imagesToLoad = $.data(paneEle, 'jScrollPaneImagesToLoad') || $('img', $this); 70 var loadedImages = []; 71 72 if ($imagesToLoad.length) { 73 $imagesToLoad.each(function(i, val) { 74 $(this).bind('load', function() { 75 if($.inArray(i, loadedImages) == -1){ //don't double count images 76 loadedImages.push(val); //keep a record of images we've seen 77 $imagesToLoad = $.grep($imagesToLoad, function(n, i) { 78 return n != val; 79 });
80 $.data(paneEle, 'jScrollPaneImagesToLoad', $imagesToLoad); 81 settings.reinitialiseOnImageLoad = false; 82 $this.jScrollPaneCusel(settings); // re-initialise 83 } 84 }).each(function(i, val) { 85 if(this.complete || this.complete===undefined) { 86 //needed for potential cached images 87 this.src = this.src; 88 } 89 }); 90 }); 91 }; 92 } 93 94 var p = this.originalSidePaddingTotal; 95 96 var cssToApply = { 97 'height':'auto', 98 'width':paneWidth - settings.scrollbarWidth - settings.scrollbarMargin - p + 'px' 99 } 100 101 if(settings.scrollbarOnLeft) { 102 cssToApply.paddingLeft = settings.scrollbarMargin + settings.scrollbarWidth + 'px'; 103 } else { 104 cssToApply.paddingRight = settings.scrollbarMargin + 'px'; 105 } 106 107 $this.css(cssToApply); 108 109 var contentHeight = $this.outerHeight(); 110 var percentInView = paneHeight / contentHeight; 111 112 if (percentInView < .99) { 113 var $container = $this.parent(); 114 115 $container.append( 116 $('<div class="jScrollPaneTrack"></div>').css({'width':settings.scrollbarWidth+'px'}).append( 117 $('<div class="jScrollPaneDrag"></div>').css({'width':settings.scrollbarWidth+'px'}).append( 118 $('<div class="jScrollPaneDragTop"></div>').css({'width':settings.scrollbarWidth+'px'}), 119 $('<div class="jScrollPaneDragBottom"></div>').css({'width':settings.scrollbarWidth+'px'}) 120 ) 121 ) 122 ); 123 124 var $track = $('>.jScrollPaneTrack', $container); 125 var $drag = $('>.jScrollPaneTrack .jScrollPaneDrag', $container); 126 127 128 if (settings.showArrows) { 129 130 var currentArrowButton; 131 var currentArrowDirection; 132 var currentArrowInterval; 133 var currentArrowInc; 134 var whileArrowButtonDown = function() 135 { 136 if (currentArrowInc > 4 || currentArrowInc%4==0) { 137 positionDrag(dragPosition + currentArrowDirection * mouseWheelMultiplier); 138 } 139 currentArrowInc ++; 140 }; 141 var onArrowMouseUp = function(event) 142 { 143 $('html').unbind('mouseup', onArrowMouseUp); 144 currentArrowButton.removeClass('jScrollActiveArrowButton'); 145 clearInterval(currentArrowInterval); 146 }; 147 var onArrowMouseDown = function() { 148 $('html').bind('mouseup', onArrowMouseUp); 149 currentArrowButton.addClass('jScrollActiveArrowButton'); 150 currentArrowInc = 0; 151 whileArrowButtonDown(); 152 currentArrowInterval = setInterval(whileArrowButtonDown, 100); 153 }; 154 $container 155 .append( 156 $('<div></div>') 157 .attr({'class':'jScrollArrowUp'}) 158 .css({'width':settings.scrollbarWidth+'px'}) 159 .bind('mousedown', function() 160 { 161 currentArrowButton = $(this); 162 currentArrowDirection = -1; 163 onArrowMouseDown(); 164 this.blur(); 165 return false; 166 }) 167 .bind('click', rf), 168 $('<div></div>') 169 .attr({'class':'jScrollArrowDown'}) 170 .css({'width':settings.scrollbarWidth+'px'}) 171 .bind('mousedown', function() 172 { 173 currentArrowButton = $(this); 174 currentArrowDirection = 1; 175 onArrowMouseDown(); 176 this.blur(); 177 return false; 178 }) 179 .bind('click', rf) 180 ); 181 var $upArrow = $('>.jScrollArrowUp', $container); 182 var $downArrow = $('>.jScrollArrowDown', $container); 183 if (settings.arrowSize) { 184 trackHeight = paneHeight - settings.arrowSize - settings.arrowSize; 185 $track 186 .css({'height': trackHeight+'px', top:settings.arrowSize+'px'}) 187 } else { 188 var topArrowHeight = $upArrow.height(); 189 settings.arrowSize = topArrowHeight; 190 trackHeight = paneHeight - topArrowHeight - $downArrow.height(); 191 $track 192 .css({'height': trackHeight+'px', top:topArrowHeight+'px'}) 193 } 194 } 195 196 var $pane = $(this).css({'position':'absolute', 'overflow':'visible'}); 197 198 var currentOffset; 199 var maxY; 200 var mouseWheelMultiplier; 201 // store this in a seperate variable so we can keep track more accurately than just updating the css property.. 202 var dragPosition = 0; 203 var dragMiddle = percentInView*paneHeight/2; 204 205 // pos function borrowed from tooltip plugin and adapted... 206 var getPos = function (event, c) { 207 var p = c == 'X' ? 'Left' : 'Top'; 208 return event['page' + c] || (event['client' + c] + (document.documentElement['scroll' + p] || document.body['scroll' + p]
208)) || 0; 209 }; 210 211 var ignoreNativeDrag = function() { return false; }; 212 213 var initDrag = function() 214 { 215 ceaseAnimation(); 216 currentOffset = $drag.offset(false); 217 currentOffset.top -= dragPosition; 218 maxY = trackHeight - $drag[0].offsetHeight; 219 mouseWheelMultiplier = 2 * settings.wheelSpeed * maxY / contentHeight; 220 }; 221 222 var onStartDrag = function(event) 223 { 224 initDrag(); 225 dragMiddle = getPos(event, 'Y') - dragPosition - currentOffset.top; 226 $('html').bind('mouseup', onStopDrag).bind('mousemove', updateScroll); 227 if ($.browser.msie) { 228 $('html').bind('dragstart', ignoreNativeDrag).bind('selectstart', ignoreNativeDrag); 229 } 230 return false; 231 }; 232 var onStopDrag = function() 233 { 234 $('html').unbind('mouseup', onStopDrag).unbind('mousemove', updateScroll); 235 dragMiddle = percentInView*paneHeight/2; 236 if ($.browser.msie) { 237 $('html').unbind('dragstart', ignoreNativeDrag).unbind('selectstart', ignoreNativeDrag); 238 } 239 }; 240 var positionDrag = function(destY) 241 { 242 destY = destY < 0 ? 0 : (destY > maxY ? maxY : destY); 243 dragPosition = destY; 244 $drag.css({'top':destY+'px'}); 245 var p = destY / maxY; 246 $pane.css({'top':((paneHeight-contentHeight)*p) + 'px'}); 247 $this.trigger('scroll'); 248 if (settings.showArrows) { 249 $upArrow[destY == 0 ? 'addClass' : 'removeClass']('disabled'); 250 $downArrow[destY == maxY ? 'addClass' : 'removeClass']('disabled'); 251 } 252 }; 253 var updateScroll = function(e) 254 { 255 positionDrag(getPos(e, 'Y') - currentOffset.top - dragMiddle); 256 }; 257 258 var dragH = Math.max(Math.min(percentInView*(paneHeight-settings.arrowSize*2), settings.dragMaxHeight), settings.dragMinHeight); 259 260 $drag.css( 261 {'height':dragH+'px'} 262 ).bind('mousedown', onStartDrag); 263 264 var trackScrollInterval; 265 var trackScrollInc; 266 var trackScrollMousePos; 267 var doTrackScroll = function() 268 { 269 if (trackScrollInc > 8 || trackScrollInc%4==0) { 270 positionDrag((dragPosition - ((dragPosition - trackScrollMousePos) / 2))); 271 } 272 trackScrollInc ++; 273 }; 274 var onStopTrackClick = function() 275 { 276 clearInterval(trackScrollInterval); 277 $('html').unbind('mouseup', onStopTrackClick).unbind('mousemove', onTrackMouseMove); 278 }; 279 var onTrackMouseMove = function(event) 280 { 281 trackScrollMousePos = getPos(event, 'Y') - currentOffset.top - dragMiddle; 282 }; 283 var onTrackClick = function(event) 284 { 285 initDrag(); 286 onTrackMouseMove(event); 287 trackScrollInc = 0; 288 $('html').bind('mouseup', onStopTrackClick).bind('mousemove', onTrackMouseMove); 289 trackScrollInterval = setInterval(doTrackScroll, 100); 290 doTrackScroll(); 291 }; 292 293 $track.bind('mousedown', onTrackClick); 294 295 $container.bind( 296 'mousewheel', 297 function (event, delta) { 298 initDrag(); 299 ceaseAnimation(); 300 var d = dragPosition; 301 positionDrag(dragPosition - delta * mouseWheelMultiplier); 302 var dragOccured = d != dragPosition; 303 return false; 304 } 305 ); 306 307 var _animateToPosition; 308 var _animateToInterval; 309 function animateToPosition() 310 { 311 var diff = (_animateToPosition - dragPosition) / settings.animateStep; 312 if (diff > 1 || diff < -1) { 313 positionDrag(dragPosition + diff); 314 } else { 315 positionDrag(_animateToPosition); 316 ceaseAnimation(); 317 } 318 } 319 var ceaseAnimation = function() 320 { 321 if (_animateToInterval) { 322 clearInterval(_animateToInterval); 323 delete _animateToPosition; 324 } 325 }; 326 var scrollTo = function(pos, preventAni) 327 { 328 if (typeof pos == "string") { 329 $e = $(pos, $this); 330 if (!$e.length) return; 331 pos = $e.offset().top - $this.offset().top; 332 } 333 $container.scrollTop(0); 334 ceaseAnimation(); 335 var destDragPosition = -pos/(paneHeight-contentHeight) * maxY; 336 if (preventAni || !settings.animateTo) { 337 positionDrag(destDragPosition); 338 } else { 339 _animateToPosition = destDragPosition; 340 _animateToInterval = setInterval(animateToPosition, settings.animateInterval); 341 } 342 }; 343 $this[0].scrollTo = scrollTo; 344 345 $this[0].scrollBy = function(delta) 346 { 347 var currentPos = -parseInt($pane.css('top')) || 0; 348 scrollTo(currentPos + delta); 349 }; 350 351 initDrag(); 352 353 scrollTo(-currentScrollPosition, true); 354 355 // Deal with it when the user tabs to a link or form element within this scrollpane 356 $('*', this).bind(
357 'focus', 358 function(event) 359 { 360 var $e = $(this); 361 362 // loop through parents adding the offset top of any elements that are relatively positioned between 363 // the focused element and the jScrollPaneContainer so we can get the true distance from the top 364 // of the focused element to the top of the scrollpane... 365 var eleTop = 0; 366 367 while ($e[0] != $this[0]) { 368 eleTop += $e.position().top; 369 $e = $e.offsetParent(); 370 } 371 372 var viewportTop = -parseInt($pane.css('top')) || 0; 373 var maxVisibleEleTop = viewportTop + paneHeight; 374 var eleInView = eleTop > viewportTop && eleTop < maxVisibleEleTop; 375 if (!eleInView) { 376 var destPos = eleTop - settings.scrollbarMargin; 377 if (eleTop > viewportTop) { // element is below viewport - scroll so it is at bottom. 378 destPos += $(this).height() + 15 + settings.scrollbarMargin - paneHeight; 379 } 380 scrollTo(destPos); 381 } 382 } 383 ) 384 385 386 if (location.hash) { 387 scrollTo(location.hash); 388 } 389 390 // use event delegation to listen for all clicks on links and hijack them if they are links to 391 // anchors within our content... 392 $(document).bind( 393 'click', 394 function(e) 395 { 396 $target = $(e.target); 397 if ($target.is('a')) { 398 var h = $target.attr('href'); 399 if (h.substr(0, 1) == '#') { 400 scrollTo(h); 401 } 402 } 403 } 404 ); 405 406 $.jScrollPaneCusel.active.push($this[0]); 407 408 } else { 409 $this.css( 410 { 411 'height':paneHeight+'px', 412 'width':paneWidth-this.originalSidePaddingTotal+'px', 413 'padding':this.originalPadding 414 } 415 ); 416 // remove from active list? 417 $this.parent().unbind('mousewheel'); 418 } 419 420 } 421 ) 422}; 423$.fn.jScrollPaneRemoveCusel = function() 424{ 425 $(this).each(function() 426 { 427 $this = $(this); 428 var $c = $this.parent(); 429 if ($c.is('.jScrollPaneContainer')) { 430 $this.css( 431 { 432 'top':'', 433 'height':'', 434 'width':'', 435 'padding':'', 436 'overflow':'', 437 'position':'' 438 } 439 ); 440 $this.attr('style', $this.data('originalStyleTag')); 441 $c.after($this).remove(); 442 } 443 }); 444} 445 446$.fn.jScrollPaneCusel.defaults = { 447 scrollbarWidth : 10, 448 scrollbarMargin : 5, 449 wheelSpeed : 18, 450 showArrows : false, 451 arrowSize : 0, 452 animateTo : false, 453 dragMinHeight : 1, 454 dragMaxHeight : 99999, 455 animateInterval : 100, 456 animateStep: 3, 457 maintainPosition: true, 458 scrollbarOnLeft: false, 459 reinitialiseOnImageLoad: false 460}; 461 462// clean up the scrollTo expandos 463$(window) 464 .bind('unload', function() { 465 var els = $.jScrollPaneCusel.active; 466 for (var i=0; i<els.length; i++) { 467 els[i].scrollTo = els[i].scrollBy = null; 468 } 469 } 470); 471 472})(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.