/**
 * jQuery.seekAttention
 * Copyright (c) 2008 James Padolsey - jp(at)qd9(dot)co.uk | http://enhance.qd-creative.co.uk
 * Dual licensed under MIT and GPL.
 * Date: 17/09/08
 *
 * @projectDescription Focus user's attention towards elements
 * http://enhance.qd-creative.co.uk/demo/seekAttention/
 * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.5 and Safari 3. on Windows XP.
 *
 * @author James Padolsey
 * @version 1.0
 *
 * @id jQuery.seekAttention
 * @id jQuery.fn.seekAttention
 */
jQuery.fn.seekAttention = function(o){
    /* Default options: */
    var defaultOptions = {
        color: 'black',
        opacity: 0.7,
        hideOnClick: true,
        paddingTop: 0,
        paddingRight: 20,
        paddingBottom: 0,
        paddingLeft: 20,
        container: 'body'
    };
    // Checking that correct data type has been passed for each option:
    for (var i in o) {
        if(i!=='container') {
            if(o[i]&&o[i]!=='undefined') {
                if(typeof o[i] !== typeof defaultOptions[i]) {return;}
            }   
        } else {
            if(typeof o[i] !== 'object' && typeof o[i] !== 'string' ) {
                return;
            }
        }
    }
    var options = $.extend(defaultOptions,o);
    /* Make sure there are no remains of the last attention seeker: */
    $('.sa-overlay,.sa-pulse-overlay,div[class*="sa-blur"]').remove();
    function getHorPadding(elem) {
        if(elem===document) {return 0;}
        /* Get computed left and right padding of an element: */
        return parseInt($(elem).css('paddingLeft').replace('px',''),10) + parseInt($(elem).css('paddingRight').replace('px',''),10);
    }
    function getVerPadding(elem) {
        if(elem===document) {return 0;}
        /* Get computed top and bottom padding of an element: */
        return parseInt($(elem).css('paddingTop').replace('px',''),10) + parseInt($(elem).css('paddingBottom').replace('px',''),10);
    }
    function newBox(t,l,h,w,c) {
        /* Create new div and assign style props and a class then append to body: */
        $('<div/>').css({
            top: t+'px',
            left: l+'px',
            position: 'absolute',
            zIndex: 9999,
            height: h+'px',
            width: w+'px',
            background: options.color,
            opacity: 0,
            display: 'none'
        }).addClass(c||'sa-overlay').appendTo('body').show();
    }
    $(this).each(function(i){
        if(i>0) {return;}
        var containerIsDocument = (options.container==='body'||options.container===document) ? true : false;
        
        /* Retrieve all dimensions needed: */
        var container = (containerIsDocument) ? document : $(options.container);
        var containerHeight = $(container).height() + getVerPadding(container);
        var containerWidth = $(container).width() + getHorPadding(container);
        var containerTop = (containerIsDocument) ? 0 : $(container).offset().top;
        var containerLeft = (containerIsDocument) ? 0 : $(container).offset().left;
        var width = $(this).width() + getHorPadding(this) + options.paddingLeft + options.paddingRight;
        var height = $(this).height() + getVerPadding(this) + options.paddingTop + options.paddingBottom;
        var left = $(this).offset().left - options.paddingLeft;
        var top = $(this).offset().top - options.paddingTop;
        var right = containerWidth - (width+left);
        var bottom = containerHeight - (height+top);
        
        /* If the target element is not positioned within the "container" element then STOP: */
        if(left<containerLeft||top<containerTop||left>containerLeft+containerWidth||top>containerTop+containerHeight) {return;}
        
        /* Just encase the above assignments result in an invalid negative value: */
        right = (right.toString().indexOf('-')>-1) ? 0 : right;
        bottom = (bottom.toString().indexOf('-')>-1) ? 0 : bottom;
        top = (top.toString().indexOf('-')>-1) ? 0 : top;
        left = (left.toString().indexOf('-')>-1) ? 0 : left;
        
        /* We need five new boxes including the pulsing box */
        newBox(containerTop,containerLeft,containerHeight,left-containerLeft);
        newBox(containerTop,containerLeft+(left-containerLeft),top-containerTop,width);
        newBox(containerTop,(left-containerLeft)+containerLeft+width,containerHeight,containerWidth-(left-containerLeft)-width);
        newBox((top-containerTop)+containerTop+height,left,containerHeight-((top-containerTop))-height,width);
        /* The pulse box is needed regardless of whether you've set options.pulse to true/false: */
        newBox(top,left,height,width,'sa-cont-overlay');
        
        var hasScrolled = false;
        var scrolled = (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
        var viewportHeight = (parseInt($(window).height(),10)>window.innerHeight) ? window.innerHeight : parseInt($(window).height(),10);
        // Tests if target element is visible, if it's not then the page will scroll to it.
        if(top>(scrolled+viewportHeight)||top+height>(scrolled+viewportHeight)||top<scrolled) {
            var where = top-Math.round(viewportHeight/2);
            /* Smoothly scrolls page to position of target element: */
            $('html, body').animate({ scrollTop: where }, 1000);
            hasScrolled = true;
        }
        /* setTimeout - no point in starting the fading too soon */
        setTimeout(function(){
            {
                $('.sa-overlay').css({opacity:options.opacity});
                /* Wait 100 millisecs and then attach hover/click events (to avoid dblclick fury) */
                setTimeout(function(){attachEvents();},200);
            }
        },(hasScrolled) ? 1000 : 500);
        function attachEvents() {
            if(options.hideOnClick) {
                $('.sa-overlay,.sa-cont-overlay').click(function(){
                   $('.sa-overlay,.sa-cont-overlay').remove();
                });
            }   
        }
    });
};
