123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- /*
- Plugin Name: BrowserSelector
- Written by: Crivos - (http://www.crivos.com)
- Version: 0.1
- */
- (function($) {
- $.extend({
- browserSelector: function() {
- var u = navigator.userAgent,
- ua = u.toLowerCase(),
- is = function (t) {
- return ua.indexOf(t) > -1;
- },
- g = 'gecko',
- w = 'webkit',
- s = 'safari',
- o = 'opera',
- h = document.documentElement,
- 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'];
- c = b.join(' ');
- h.className += ' ' + c;
- }
- });
- })(jQuery);
- /*
- Plugin Name: smoothScroll for jQuery.
- Written by: Crivos - (http://www.crivos.com)
- Version: 0.1
- Based on:
- SmoothScroll v1.2.1
- Licensed under the terms of the MIT license.
- People involved
- - Balazs Galambosi (maintainer)
- - Patrick Brunner (original idea)
- - Michael Herf (Pulse Algorithm)
- */
- (function($) {
- $.extend({
- smoothScroll: function() {
- // Scroll Variables (tweakable)
- var defaultOptions = {
- // Scrolling Core
- frameRate : 150, // [Hz]
- animationTime : 700, // [px]
- stepSize : 80, // [px]
- // Pulse (less tweakable)
- // ratio of "tail" to "acceleration"
- pulseAlgorithm : true,
- pulseScale : 8,
- pulseNormalize : 1,
- // Acceleration
- accelerationDelta : 20, // 20
- accelerationMax : 1, // 1
- // Keyboard Settings
- keyboardSupport : true, // option
- arrowScroll : 50, // [px]
- // Other
- touchpadSupport : true,
- fixedBackground : true,
- excluded : ""
- };
- var options = defaultOptions;
- // Other Variables
- var isExcluded = false;
- var isFrame = false;
- var direction = { x: 0, y: 0 };
- var initDone = false;
- var root = document.documentElement;
- var activeElement;
- var observer;
- var deltaBuffer = [ 120, 120, 120 ];
- var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
- pageup: 33, pagedown: 34, end: 35, home: 36 };
- /***********************************************
- * INITIALIZE
- ***********************************************/
- /**
- * Tests if smooth scrolling is allowed. Shuts down everything if not.
- */
- function initTest() {
- var disableKeyboard = false;
- // disable keys for google reader (spacebar conflict)
- if (document.URL.indexOf("google.com/reader/view") > -1) {
- disableKeyboard = true;
- }
- // disable everything if the page is blacklisted
- if (options.excluded) {
- var domains = options.excluded.split(/[,\n] ?/);
- domains.push("mail.google.com"); // exclude Gmail for now
- for (var i = domains.length; i--;) {
- if (document.URL.indexOf(domains[i]) > -1) {
- observer && observer.disconnect();
- removeEvent("mousewheel", wheel);
- disableKeyboard = true;
- isExcluded = true;
- break;
- }
- }
- }
- // disable keyboard support if anything above requested it
- if (disableKeyboard) {
- removeEvent("keydown", keydown);
- }
- if (options.keyboardSupport && !disableKeyboard) {
- addEvent("keydown", keydown);
- }
- }
- /**
- * Sets up scrolls array, determines if frames are involved.
- */
- function init() {
- if (!document.body) return;
- var body = document.body;
- var html = document.documentElement;
- var windowHeight = window.innerHeight;
- var scrollHeight = body.scrollHeight;
- // check compat mode for root element
- root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
- activeElement = body;
- initTest();
- initDone = true;
- // Checks if this script is running in a frame
- if (top != self) {
- isFrame = true;
- }
- /**
- * This fixes a bug where the areas left and right to
- * the content does not trigger the onmousewheel event
- * on some pages. e.g.: html, body { height: 100% }
- */
- else if (scrollHeight > windowHeight &&
- (body.offsetHeight <= windowHeight ||
- html.offsetHeight <= windowHeight)) {
- // DOMChange (throttle): fix height
- var pending = false;
- var refresh = function () {
- if (!pending && html.scrollHeight != document.height) {
- pending = true; // add a new pending action
- setTimeout(function () {
- html.style.height = document.height + 'px';
- pending = false;
- }, 500); // act rarely to stay fast
- }
- };
- html.style.height = 'auto';
- setTimeout(refresh, 10);
- var config = {
- attributes: true,
- childList: true,
- characterData: false
- };
- observer = new MutationObserver(refresh);
- observer.observe(body, config);
- // clearfix
- if (root.offsetHeight <= windowHeight) {
- var underlay = document.createElement("div");
- underlay.style.clear = "both";
- body.appendChild(underlay);
- }
- }
- // gmail performance fix
- if (document.URL.indexOf("mail.google.com") > -1) {
- var s = document.createElement("style");
- s.innerHTML = ".iu { visibility: hidden }";
- (document.getElementsByTagName("head")[0] || html).appendChild(s);
- }
- // facebook better home timeline performance
- // all the HTML resized images make rendering CPU intensive
- else if (document.URL.indexOf("www.facebook.com") > -1) {
- var home_stream = document.getElementById("home_stream");
- home_stream && (home_stream.style.webkitTransform = "translateZ(0)");
- }
- // disable fixed background
- if (!options.fixedBackground && !isExcluded) {
- body.style.backgroundAttachment = "scroll";
- html.style.backgroundAttachment = "scroll";
- }
- }
- /************************************************
- * SCROLLING
- ************************************************/
- var que = [];
- var pending = false;
- var lastScroll = +new Date;
- /**
- * Pushes scroll actions to the scrolling queue.
- */
- function scrollArray(elem, left, top, delay) {
- delay || (delay = 1000);
- directionCheck(left, top);
- if (options.accelerationMax != 1) {
- var now = +new Date;
- var elapsed = now - lastScroll;
- if (elapsed < options.accelerationDelta) {
- var factor = (1 + (30 / elapsed)) / 2;
- if (factor > 1) {
- factor = Math.min(factor, options.accelerationMax);
- left *= factor;
- top *= factor;
- }
- }
- lastScroll = +new Date;
- }
- // push a scroll command
- que.push({
- x: left,
- y: top,
- lastX: (left < 0) ? 0.99 : -0.99,
- lastY: (top < 0) ? 0.99 : -0.99,
- start: +new Date
- });
- // don't act if there's a pending queue
- if (pending) {
- return;
- }
- var scrollWindow = (elem === document.body);
- var step = function (time) {
- var now = +new Date;
- var scrollX = 0;
- var scrollY = 0;
- for (var i = 0; i < que.length; i++) {
- var item = que[i];
- var elapsed = now - item.start;
- var finished = (elapsed >= options.animationTime);
- // scroll position: [0, 1]
- var position = (finished) ? 1 : elapsed / options.animationTime;
- // easing [optional]
- if (options.pulseAlgorithm) {
- position = pulse(position);
- }
- // only need the difference
- var x = (item.x * position - item.lastX) >> 0;
- var y = (item.y * position - item.lastY) >> 0;
- // add this to the total scrolling
- scrollX += x;
- scrollY += y;
- // update last values
- item.lastX += x;
- item.lastY += y;
- // delete and step back if it's over
- if (finished) {
- que.splice(i, 1); i--;
- }
- }
- // scroll left and top
- if (scrollWindow) {
- window.scrollBy(scrollX, scrollY);
- }
- else {
- if (scrollX) elem.scrollLeft += scrollX;
- if (scrollY) elem.scrollTop += scrollY;
- }
- // clean up if there's nothing left to do
- if (!left && !top) {
- que = [];
- }
- if (que.length) {
- requestFrame(step, elem, (delay / options.frameRate + 1));
- } else {
- pending = false;
- }
- };
- // start a new queue of actions
- requestFrame(step, elem, 0);
- pending = true;
- }
- /***********************************************
- * EVENTS
- ***********************************************/
- /**
- * Mouse wheel handler.
- * @param {Object} event
- */
- function wheel(event) {
- if (!initDone) {
- init();
- }
- var target = event.target;
- var overflowing = overflowingAncestor(target);
- // use default if there's no overflowing
- // element or default action is prevented
- if (!overflowing || event.defaultPrevented ||
- isNodeName(activeElement, "embed") ||
- (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
- return true;
- }
- var deltaX = event.wheelDeltaX || 0;
- var deltaY = event.wheelDeltaY || 0;
- // use wheelDelta if deltaX/Y is not available
- if (!deltaX && !deltaY) {
- deltaY = event.wheelDelta || 0;
- }
- // check if it's a touchpad scroll that should be ignored
- if (!options.touchpadSupport && isTouchpad(deltaY)) {
- return true;
- }
- // scale by step size
- // delta is 120 most of the time
- // synaptics seems to send 1 sometimes
- if (Math.abs(deltaX) > 1.2) {
- deltaX *= options.stepSize / 120;
- }
- if (Math.abs(deltaY) > 1.2) {
- deltaY *= options.stepSize / 120;
- }
- scrollArray(overflowing, -deltaX, -deltaY);
- event.preventDefault();
- }
- /**
- * Keydown event handler.
- * @param {Object} event
- */
- function keydown(event) {
- var target = event.target;
- var modifier = event.ctrlKey || event.altKey || event.metaKey ||
- (event.shiftKey && event.keyCode !== key.spacebar);
- // do nothing if user is editing text
- // or using a modifier key (except shift)
- // or in a dropdown
- if ( /input|textarea|select|embed/i.test(target.nodeName) ||
- target.isContentEditable ||
- event.defaultPrevented ||
- modifier ) {
- return true;
- }
- // spacebar should trigger button press
- if (isNodeName(target, "button") &&
- event.keyCode === key.spacebar) {
- return true;
- }
- var shift, x = 0, y = 0;
- var elem = overflowingAncestor(activeElement);
- var clientHeight = elem.clientHeight;
- if (elem == document.body) {
- clientHeight = window.innerHeight;
- }
- switch (event.keyCode) {
- case key.up:
- y = -options.arrowScroll;
- break;
- case key.down:
- y = options.arrowScroll;
- break;
- case key.spacebar: // (+ shift)
- shift = event.shiftKey ? 1 : -1;
- y = -shift * clientHeight * 0.9;
- break;
- case key.pageup:
- y = -clientHeight * 0.9;
- break;
- case key.pagedown:
- y = clientHeight * 0.9;
- break;
- case key.home:
- y = -elem.scrollTop;
- break;
- case key.end:
- var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
- y = (damt > 0) ? damt+10 : 0;
- break;
- case key.left:
- x = -options.arrowScroll;
- break;
- case key.right:
- x = options.arrowScroll;
- break;
- default:
- return true; // a key we don't care about
- }
- scrollArray(elem, x, y);
- event.preventDefault();
- }
- /**
- * Mousedown event only for updating activeElement
- */
- function mousedown(event) {
- activeElement = event.target;
- }
- /***********************************************
- * OVERFLOW
- ***********************************************/
- var cache = {}; // cleared out every once in while
- setInterval(function () { cache = {}; }, 10 * 1000);
- var uniqueID = (function () {
- var i = 0;
- return function (el) {
- return el.uniqueID || (el.uniqueID = i++);
- };
- })();
- function setCache(elems, overflowing) {
- for (var i = elems.length; i--;)
- cache[uniqueID(elems[i])] = overflowing;
- return overflowing;
- }
- function overflowingAncestor(el) {
- var elems = [];
- var rootScrollHeight = root.scrollHeight;
- do {
- var cached = cache[uniqueID(el)];
- if (cached) {
- return setCache(elems, cached);
- }
- elems.push(el);
- if (rootScrollHeight === el.scrollHeight) {
- if (!isFrame || root.clientHeight + 10 < rootScrollHeight) {
- return setCache(elems, document.body); // scrolling root in WebKit
- }
- } else if (el.clientHeight + 10 < el.scrollHeight) {
- overflow = getComputedStyle(el, "").getPropertyValue("overflow-y");
- if (overflow === "scroll" || overflow === "auto") {
- return setCache(elems, el);
- }
- }
- } while (el = el.parentNode);
- }
- /***********************************************
- * HELPERS
- ***********************************************/
- function addEvent(type, fn, bubble) {
- window.addEventListener(type, fn, (bubble||false));
- }
- function removeEvent(type, fn, bubble) {
- window.removeEventListener(type, fn, (bubble||false));
- }
- function isNodeName(el, tag) {
- return (el.nodeName||"").toLowerCase() === tag.toLowerCase();
- }
- function directionCheck(x, y) {
- x = (x > 0) ? 1 : -1;
- y = (y > 0) ? 1 : -1;
- if (direction.x !== x || direction.y !== y) {
- direction.x = x;
- direction.y = y;
- que = [];
- lastScroll = 0;
- }
- }
- var deltaBufferTimer;
- function isTouchpad(deltaY) {
- if (!deltaY) return;
- deltaY = Math.abs(deltaY)
- deltaBuffer.push(deltaY);
- deltaBuffer.shift();
- clearTimeout(deltaBufferTimer);
- var allEquals = (deltaBuffer[0] == deltaBuffer[1] &&
- deltaBuffer[1] == deltaBuffer[2]);
- var allDivisable = (isDivisible(deltaBuffer[0], 120) &&
- isDivisible(deltaBuffer[1], 120) &&
- isDivisible(deltaBuffer[2], 120));
- return !(allEquals || allDivisable);
- }
- function isDivisible(n, divisor) {
- return (Math.floor(n / divisor) == n / divisor);
- }
- var requestFrame = (function () {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- function (callback, element, delay) {
- window.setTimeout(callback, delay || (1000/60));
- };
- })();
- var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
- /***********************************************
- * PULSE
- ***********************************************/
- /**
- * Viscous fluid with a pulse for part and decay for the rest.
- * - Applies a fixed force over an interval (a damped acceleration), and
- * - Lets the exponential bleed away the velocity over a longer interval
- * - Michael Herf, http://stereopsis.com/stopping/
- */
- function pulse_(x) {
- var val, start, expx;
- // test
- x = x * options.pulseScale;
- if (x < 1) { // acceleartion
- val = x - (1 - Math.exp(-x));
- } else { // tail
- // the previous animation ended here:
- start = Math.exp(-1);
- // simple viscous drag
- x -= 1;
- expx = 1 - Math.exp(-x);
- val = start + (expx * (1 - start));
- }
- return val * options.pulseNormalize;
- }
- function pulse(x) {
- if (x >= 1) return 1;
- if (x <= 0) return 0;
- if (options.pulseNormalize == 1) {
- options.pulseNormalize /= pulse_(1);
- }
- return pulse_(x);
- }
- addEvent("mousedown", mousedown);
- addEvent("mousewheel", wheel);
- addEvent("load", init);
- }
- });
- })(jQuery);
|