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