1/* 2Plugin Name: BrowserSelector 3Written by: Crivos - (http://www.crivos.com) 4Version: 0.1 5*/ 6 7(function($) { 8 $.extend({ 9 10 browserSelector: function() { 11 12 var u = navigator.userAgent, 13 ua = u.toLowerCase(), 14 is = function (t) { 15 return ua.indexOf(t) > -1; 16 }, 17 g = 'gecko', 18 w = 'webkit', 19 s = 'safari', 20 o = 'opera', 21 h = document.documentElement, 22 b = [(!(/opera|webtv/i.test(ua)) && /msie\s(\d)/.test(ua)) ? ('ie ie' + parseFloat(navigator.appVersion.split("MSIE")[1])) : is('firefox/2') ? g + ' ff2' : is('firefox/3.5') ? g + ' ff3 ff3_5' : is('firefox/3') ? g + ' ff3' : is('gecko/') ? g : is('opera') ? o + (/version\/(\d+)/.test(ua) ? ' ' + o + RegExp.jQuery1 : (/opera(\s|\/)(\d+)/.test(ua) ? ' ' + o + RegExp.jQuery2 : '')) : is('konqueror') ? 'konqueror' : is('chrome') ? w + ' chrome' : is('iron') ? w + ' iron' : is('applewebkit/') ? w + ' ' + s + (/version\/(\d+)/.test(ua) ? ' ' + s + RegExp.jQuery1 : '') : is('mozilla/') ? g : '', is('j2me') ? 'mobile' : is('iphone') ? 'iphone' : is('ipod') ? 'ipod' : is('mac') ? 'mac' : is('darwin') ? 'mac' : is('webtv') ? 'webtv' : is('win') ? 'win' : is('freebsd') ? 'freebsd' : (is('x11') || is('linux')) ? 'linux' : '', 'js']; 23 24 c = b.join(' '); 25 h.className += ' ' + c; 26 27 } 28 29 }); 30})(jQuery); 31 32/* 33Plugin Name: smoothScroll for jQuery. 34Written by: Crivos - (http://www.crivos.com) 35Version: 0.1 36 37Based on: 38 39 SmoothScroll v1.2.1 40 Licensed under the terms of the MIT license. 41 42 People involved 43 - Balazs Galambosi (maintainer) 44 - Patrick Brunner (original idea) 45 - Michael Herf (Pulse Algorithm) 46 47*/ 48(function($) { 49 $.extend({ 50 51 smoothScroll: function() { 52 53 // Scroll Variables (tweakable) 54 var defaultOptions = { 55 56 // Scrolling Core 57 frameRate : 150, // [Hz] 58 animationTime : 700, // [px] 59 stepSize : 80, // [px] 60 61 // Pulse (less tweakable) 62 // ratio of "tail" to "acceleration" 63 pulseAlgorithm : true, 64 pulseScale : 8, 65 pulseNormalize : 1, 66 67 // Acceleration 68 accelerationDelta : 20, // 20 69 accelerationMax : 1, // 1 70 71 // Keyboard Settings 72 keyboardSupport : true, // option 73 arrowScroll : 50, // [px] 74 75 // Other 76 touchpadSupport : true, 77 fixedBackground : true, 78 excluded : "" 79 }; 80 81 var options = defaultOptions; 82 83 // Other Variables 84 var isExcluded = false; 85 var isFrame = false; 86 var direction = { x: 0, y: 0 }; 87 var initDone = false; 88 var root = document.documentElement; 89 var activeElement; 90 var observer; 91 var deltaBuffer = [ 120, 120, 120 ]; 92 93 var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32, 94 pageup: 33, pagedown: 34, end: 35, home: 36 }; 95 96 97 /*********************************************** 98 * INITIALIZE 99 ***********************************************/ 100 101 /** 102 * Tests if smooth scrolling is allowed. Shuts down everything if not. 103 */ 104 function initTest() { 105 106 var disableKeyboard = false; 107 108 // disable keys for google reader (spacebar conflict) 109 if (document.URL.indexOf("google.com/reader/view") > -1) { 110 disableKeyboard = true; 111 } 112 113 // disable everything if the page is blacklisted 114 if (options.excluded) { 115 var domains = options.excluded.split(/[,\n] ?/); 116 domains.push("mail.google.com"); // exclude Gmail for now 117 for (var i = domains.length; i--;) { 118 if (document.URL.indexOf(domains[i]) > -1) { 119 observer && observer.disconnect(); 120 removeEvent("mousewheel", wheel); 121 disableKeyboard = true; 122 isExcluded = true; 123 break; 124 } 125 } 126 } 127 128 // disable keyboard support if anything above requested it 129 if (disableKeyboard) { 130 removeEvent("keydown", keydown); 131 } 132 133 if (options.keyboardSupport && !disableKeyboard) { 134 addEvent("keydown", keydown); 135 } 136 } 137 138 /** 139 * Sets up scrolls array, determines if frames are involved. 140 */ 141 function init() { 142 143 if (!document.body) return; 144 145 var body = document.body; 146 var html = document.documentElement; 147 var windowHeight = window.innerHeight; 148 var scrollHeight = body.scrollHeight; 149 150 // check compat mode for root element 151 root = (document.compatMode.indexOf('CSS') >= 0) ? html : body; 152 activeElement = body; 153 154 initTest(); 155 initDone = true; 156 157 // Checks if this script is running in a frame 158 if (top != self) { 159 isFrame = true; 160 } 161 162 /** 163 * This fixes a bug where the areas left and right to 164 * the content does not trigger the onmousewheel event 165 * on some pages. e.g.: html, body { height: 100% } 166 */ 167 else if (scrollHeight > windowHeight && 168 (body.offsetHeight <= windowHeight || 169 html.offsetHeight <= windowHeight)) { 170 171 // DOMChange (throttle): fix height 172 var pending = false;
173 var refresh = function () { 174 if (!pending && html.scrollHeight != document.height) { 175 pending = true; // add a new pending action 176 setTimeout(function () { 177 html.style.height = document.height + 'px'; 178 pending = false; 179 }, 500); // act rarely to stay fast 180 } 181 }; 182 html.style.height = 'auto'; 183 setTimeout(refresh, 10); 184 185 var config = { 186 attributes: true, 187 childList: true, 188 characterData: false 189 }; 190 191 observer = new MutationObserver(refresh); 192 observer.observe(body, config); 193 194 // clearfix 195 if (root.offsetHeight <= windowHeight) { 196 var underlay = document.createElement("div"); 197 underlay.style.clear = "both"; 198 body.appendChild(underlay); 199 } 200 } 201 202 // gmail performance fix 203 if (document.URL.indexOf("mail.google.com") > -1) { 204 var s = document.createElement("style"); 205 s.innerHTML = ".iu { visibility: hidden }"; 206 (document.getElementsByTagName("head")[0] || html).appendChild(s); 207 } 208 // facebook better home timeline performance 209 // all the HTML resized images make rendering CPU intensive 210 else if (document.URL.indexOf("www.facebook.com") > -1) { 211 var home_stream = document.getElementById("home_stream"); 212 home_stream && (home_stream.style.webkitTransform = "translateZ(0)"); 213 } 214 // disable fixed background 215 if (!options.fixedBackground && !isExcluded) { 216 body.style.backgroundAttachment = "scroll"; 217 html.style.backgroundAttachment = "scroll"; 218 } 219 } 220 221 222 /************************************************ 223 * SCROLLING 224 ************************************************/ 225 226 var que = []; 227 var pending = false; 228 var lastScroll = +new Date; 229 230 /** 231 * Pushes scroll actions to the scrolling queue. 232 */ 233 function scrollArray(elem, left, top, delay) { 234 235 delay || (delay = 1000); 236 directionCheck(left, top); 237 238 if (options.accelerationMax != 1) { 239 var now = +new Date; 240 var elapsed = now - lastScroll; 241 if (elapsed < options.accelerationDelta) { 242 var factor = (1 + (30 / elapsed)) / 2; 243 if (factor > 1) { 244 factor = Math.min(factor, options.accelerationMax); 245 left *= factor; 246 top *= factor; 247 } 248 } 249 lastScroll = +new Date; 250 } 251 252 // push a scroll command 253 que.push({ 254 x: left, 255 y: top, 256 lastX: (left < 0) ? 0.99 : -0.99, 257 lastY: (top < 0) ? 0.99 : -0.99, 258 start: +new Date 259 }); 260 261 // don't act if there's a pending queue 262 if (pending) { 263 return; 264 } 265 266 var scrollWindow = (elem === document.body); 267 268 var step = function (time) { 269 270 var now = +new Date; 271 var scrollX = 0; 272 var scrollY = 0; 273 274 for (var i = 0; i < que.length; i++) { 275 276 var item = que[i]; 277 var elapsed = now - item.start; 278 var finished = (elapsed >= options.animationTime); 279 280 // scroll position: [0, 1] 281 var position = (finished) ? 1 : elapsed / options.animationTime; 282 283 // easing [optional] 284 if (options.pulseAlgorithm) { 285 position = pulse(position); 286 } 287 288 // only need the difference 289 var x = (item.x * position - item.lastX) >> 0; 290 var y = (item.y * position - item.lastY) >> 0; 291 292 // add this to the total scrolling 293 scrollX += x; 294 scrollY += y; 295 296 // update last values 297 item.lastX += x; 298 item.lastY += y; 299 300 // delete and step back if it's over 301 if (finished) { 302 que.splice(i, 1); i--; 303 } 304 } 305 306 // scroll left and top 307 if (scrollWindow) { 308 window.scrollBy(scrollX, scrollY); 309 } 310 else { 311 if (scrollX) elem.scrollLeft += scrollX; 312 if (scrollY) elem.scrollTop += scrollY; 313 } 314 315 // clean up if there's nothing left to do 316 if (!left && !top) { 317 que = []; 318 } 319 320 if (que.length) { 321 requestFrame(step, elem, (delay / options.frameRate + 1)); 322 } else { 323 pending = false; 324 } 325 }; 326 327 // start a new queue of actions 328 requestFrame(step, elem, 0); 329 pending = true; 330 } 331 332 333 /*********************************************** 334 * EVENTS 335 ***********************************************/ 336 337 /** 338 * Mouse wheel handler. 339 * @param {Object} event 340 */ 341 function wheel(event) { 342 343 if (!initDone) { 344 init(); 345 } 346 347 var target = event.target; 348 var overflowing = overflowingAncestor(target); 349 350 // use default if there's no overflowing 351 // element or default action is prevented 352 if (!overflowing || event.defaultPrevented || 353 isNodeName(activeElement, "embed") || 354 (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) { 355 return true; 356 } 357 358 var deltaX = event.wheelDeltaX || 0; 359 var deltaY = event.wheelDeltaY || 0; 360 361 // use wheelDelta if deltaX/Y is not available 362 if (!deltaX && !deltaY) { 363 deltaY = event.wheelDelta || 0; 364 } 365 366 // check if it's a touchpad scroll that should be ignored 367 if (!options.touchpadSupport && isTouchpad(deltaY)) { 368 return true; 369 } 370 371 // scale by step size 372 // delta is 120 most of the time
373 // synaptics seems to send 1 sometimes 374 if (Math.abs(deltaX) > 1.2) { 375 deltaX *= options.stepSize / 120; 376 } 377 if (Math.abs(deltaY) > 1.2) { 378 deltaY *= options.stepSize / 120; 379 } 380 381 scrollArray(overflowing, -deltaX, -deltaY); 382 event.preventDefault(); 383 } 384 385 /** 386 * Keydown event handler. 387 * @param {Object} event 388 */ 389 function keydown(event) { 390 391 var target = event.target; 392 var modifier = event.ctrlKey || event.altKey || event.metaKey || 393 (event.shiftKey && event.keyCode !== key.spacebar); 394 395 // do nothing if user is editing text 396 // or using a modifier key (except shift) 397 // or in a dropdown 398 if ( /input|textarea|select|embed/i.test(target.nodeName) || 399 target.isContentEditable || 400 event.defaultPrevented || 401 modifier ) { 402 return true; 403 } 404 // spacebar should trigger button press 405 if (isNodeName(target, "button") && 406 event.keyCode === key.spacebar) { 407 return true; 408 } 409 410 var shift, x = 0, y = 0; 411 var elem = overflowingAncestor(activeElement); 412 var clientHeight = elem.clientHeight; 413 414 if (elem == document.body) { 415 clientHeight = window.innerHeight; 416 } 417 418 switch (event.keyCode) { 419 case key.up: 420 y = -options.arrowScroll; 421 break; 422 case key.down: 423 y = options.arrowScroll; 424 break; 425 case key.spacebar: // (+ shift) 426 shift = event.shiftKey ? 1 : -1; 427 y = -shift * clientHeight * 0.9; 428 break; 429 case key.pageup: 430 y = -clientHeight * 0.9; 431 break; 432 case key.pagedown: 433 y = clientHeight * 0.9; 434 break; 435 case key.home: 436 y = -elem.scrollTop; 437 break; 438 case key.end: 439 var damt = elem.scrollHeight - elem.scrollTop - clientHeight; 440 y = (damt > 0) ? damt+10 : 0; 441 break; 442 case key.left: 443 x = -options.arrowScroll; 444 break; 445 case key.right: 446 x = options.arrowScroll; 447 break; 448 default: 449 return true; // a key we don't care about 450 } 451 452 scrollArray(elem, x, y); 453 event.preventDefault(); 454 } 455 456 /** 457 * Mousedown event only for updating activeElement 458 */ 459 function mousedown(event) { 460 activeElement = event.target; 461 } 462 463 464 /*********************************************** 465 * OVERFLOW 466 ***********************************************/ 467 468 var cache = {}; // cleared out every once in while 469 setInterval(function () { cache = {}; }, 10 * 1000); 470 471 var uniqueID = (function () { 472 var i = 0; 473 return function (el) { 474 return el.uniqueID || (el.uniqueID = i++); 475 }; 476 })(); 477 478 function setCache(elems, overflowing) { 479 for (var i = elems.length; i--;) 480 cache[uniqueID(elems[i])] = overflowing; 481 return overflowing; 482 } 483 484 function overflowingAncestor(el) { 485 var elems = []; 486 var rootScrollHeight = root.scrollHeight; 487 do { 488 var cached = cache[uniqueID(el)]; 489 if (cached) { 490 return setCache(elems, cached); 491 } 492 elems.push(el); 493 if (rootScrollHeight === el.scrollHeight) { 494 if (!isFrame || root.clientHeight + 10 < rootScrollHeight) { 495 return setCache(elems, document.body); // scrolling root in WebKit 496 } 497 } else if (el.clientHeight + 10 < el.scrollHeight) { 498 overflow = getComputedStyle(el, "").getPropertyValue("overflow-y"); 499 if (overflow === "scroll" || overflow === "auto") { 500 return setCache(elems, el); 501 } 502 } 503 } while (el = el.parentNode); 504 } 505 506 507 /*********************************************** 508 * HELPERS 509 ***********************************************/ 510 511 function addEvent(type, fn, bubble) { 512 window.addEventListener(type, fn, (bubble||false)); 513 } 514 515 function removeEvent(type, fn, bubble) { 516 window.removeEventListener(type, fn, (bubble||false)); 517 } 518 519 function isNodeName(el, tag) { 520 return (el.nodeName||"").toLowerCase() === tag.toLowerCase(); 521 } 522 523 function directionCheck(x, y) { 524 x = (x > 0) ? 1 : -1; 525 y = (y > 0) ? 1 : -1; 526 if (direction.x !== x || direction.y !== y) { 527 direction.x = x; 528 direction.y = y; 529 que = []; 530 lastScroll = 0; 531 } 532 } 533 534 var deltaBufferTimer; 535 536 function isTouchpad(deltaY) { 537 if (!deltaY) return; 538 deltaY = Math.abs(deltaY) 539 deltaBuffer.push(deltaY); 540 deltaBuffer.shift(); 541 clearTimeout(deltaBufferTimer); 542 var allEquals = (deltaBuffer[0] == deltaBuffer[1] && 543 deltaBuffer[1] == deltaBuffer[2]); 544 var allDivisable = (isDivisible(deltaBuffer[0], 120) && 545 isDivisible(deltaBuffer[1], 120) && 546 isDivisible(deltaBuffer[2], 120)); 547 return !(allEquals || allDivisable); 548 } 549 550 function isDivisible(n, divisor) { 551 return (Math.floor(n / divisor) == n / divisor); 552 } 553 554 var requestFrame = (function () { 555 return window.requestAnimationFrame || 556 window.webkitRequestAnimationFrame || 557 function (callback, element, delay) { 558 window.setTimeout(callback, delay || (1000/60)); 559 }; 560 })(); 561 562 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; 563 564 565 /*********************************************** 566 * PULSE 567 ***********************************************/ 568 569 /** 570 * Viscous fluid with a pulse for part and decay for the rest. 571 * - Applies a fixed force over an interval (a damped acceleration), and 572 * - Lets the exponential bleed away the velocity over a longer interval 573 * - Michael Herf, http://stereopsis.com/stopping/ 574 */ 575 function pulse_(x) { 576 var val, start, expx; 577 // test 578 x = x * options.pulseScale; 579 if (x < 1) { // acceleartion 580 val = x - (1 - Math.exp(-x)); 581 } else { // tail 582 // the previous animation ended here: 583 start = Math.exp(-1); 584 // simple viscous drag 585 x -= 1; 586 expx = 1 - Math.exp(-x); 587 val = start + (expx * (1 - start)); 588 }
589 return val * options.pulseNormalize; 590 } 591 592 function pulse(x) { 593 if (x >= 1) return 1; 594 if (x <= 0) return 0; 595 596 if (options.pulseNormalize == 1) { 597 options.pulseNormalize /= pulse_(1); 598 } 599 return pulse_(x); 600 } 601 602 addEvent("mousedown", mousedown); 603 addEvent("mousewheel", wheel); 604 addEvent("load", init); 605 606 } 607 608 }); 609})(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.