﻿/*
* Fallr v1.1.1 - jQuery Plugin
* Simple & elegant modal box jQuery plugin
*
* Copyright 2011 amatyr4n
* http://codecanyon.net/user/amatyr4n
*
* licensed under Envato licenses
* http://wiki.envato.com/support/legal-terms/licensing-terms/
*
* Any suggestions, bug report, or whatever feedback are welcome :)
*/

/*global jQuery:false, document:false, window:false */

; (function ($) {

    // define default properties
    var defaults = {
        buttons: {
            // object contains buttons definition
            button1: {
                text: 'OK',                 // default button text
                danger: false,                // is the button trigger dangerous action?
                onclick: function () {           // default button function 
                    $.fallr('hide');
                }
            }
        },
        icon: 'check',          // [string] icon displayed
        content: 'Hello',          // [string] fallr content
        position: 'top',            // [string] top/center/bottom
        closeKey: false,            // [bool] close fallr with ESC key
        closeOverlay: false,            // [bool] close fallr on overlay click
        useOverlay: true,             // [bool] should overlay be shown
        autoclose: false,            // [int] autoclose duration in miliseconds, false to disable
        easingDuration: 300,              // [int] animation duration
        easingIn: 'swing',          // [string] easing type when appear
        easingOut: 'swing',          // [string] easing type when disappear
        height: 'auto',           // [string] css value for exact height
        width: '360px',          // [string] css value for exact width
        zIndex: 1000001,              // [int] set z-index
        suppress: false             // [bool] suppress the return key
    },

        opts, // hold options settings. defined later
        timeoutId, // hold timeout id
        $w = $(window),

    // public methods        
        methods = {

            hide: function (options, callback, self) {

                // is it present?
                if (helpers.isActive()) {

                    // stop from animating
                    $('#fallr-wrapper').stop(true, true);

                    var $f = $('#fallr-wrapper'),
                        pos = $f.css('position'),   // fixed/absolute
                        yminpos = 0;

                    switch (opts.position) {
                        case 'bottom':
                        case 'center':
                            // get bottom of page coordinat
                            yminpos = ((pos === 'fixed') ? $w.height() : $f.offset().top + $f.height()) + 10;
                            break;
                        // case 'top': 
                        default:
                            // get top of page coordinat
                            yminpos = ((pos === 'fixed') ? (-1) * ($f.outerHeight()) : $f.offset().top) - 10;
                    }

                    // animate hide
                    $f.animate({
                        'top': (yminpos)
                    }, (opts.easingDuration || opts.duration), opts.easingOut, function () {
                        if ($.browser.msie) {
                            $('#fallr-overlay').css('display', 'none');
                        } else {
                            $('#fallr-overlay').fadeOut('fast');
                        }

                        // remove element
                        $f.remove();

                        // clear timeout
                        clearTimeout(timeoutId);

                        // execute callback
                        if (typeof callback === "function") {
                            callback.call(self);
                        }
                    });

                    $(document)
                        .unbind('keydown', helpers.enterKeyHandler)
                        .unbind('keydown', helpers.closeKeyHandler)
                        .unbind('keydown', helpers.tabKeyHandler);
                }
            },

            resize: function (options, callback, self) {

                var $f = $('#fallr-wrapper'),
                    newWidth = parseInt(options.width, 10),
                    newHeight = parseInt(options.height, 10),
                    diffWidth = Math.abs($f.outerWidth() - newWidth),
                    diffHeight = Math.abs($f.outerHeight() - newHeight);

                // only fire if present and have enough different size
                if (helpers.isActive() && (diffWidth > 5 || diffHeight > 5)) {

                    $f.animate({
                        'width': newWidth
                    }, function () {
                        $(this).animate({
                            'height': newHeight
                        }, function () {
                            helpers.fixPos();
                        });
                    });

                    $('#fallr').animate({
                        'width': newWidth - 94    // 94 = padding
                    }, function () {
                        $(this).animate({
                            'height': newHeight - 131  // e131 = padding+buttons
                        }, function () {
                            // execute callback
                            if (typeof callback === "function") {
                                callback.call(self);
                            }
                        });
                    });
                }
            },

            show: function (options, callback, self) {

                // check whether fallr is still present
                if (helpers.isActive()) {

                    $.error('Can\'t create new message with content: "' + options.content + '", past message with content "' + opts.content + '" is still active');

                } else {

                    opts = $.extend({}, defaults, options);

                    // create fallr instance
                    $('<div id="fallr-wrapper"></div>').appendTo('body');

                    var $f = $('#fallr-wrapper'),
                        $o = $('#fallr-overlay');

                    $f.css({
                        'width': opts.width,
                        'height': opts.height,
                        'position': 'absolute',
                        'top': '-9999px',
                        'left': '-9999px'     // show but don't display inside window
                    })
                        .html('<div id="fallr-icon"></div>'         // for icon
                                + '<div id="fallr"></div>'          // for content
                                + '<div id="fallr-buttons"></div>') // for buttons
                        .find('#fallr-icon')
                            .addClass('icon-' + opts.icon)
                            .end()
                        .find('#fallr')
                            .html(opts.content)
                            .css({
                                'height': (opts.height == 'auto') ? 'auto' : $f.height() - 131,       // 131 = padding+buttons
                                'width': $f.width() - 94                                             // 94 = padding
                            })
                            .end()
                        .find('#fallr-buttons')
                            .html(
                                (function () {
                                    var buttons = '';
                                    var i;
                                    for (i in opts.buttons) {
                                        if (opts.buttons.hasOwnProperty(i)) {
                                            buttons = buttons
                                                        + '<a href="#" class="fallr-button '
                                                        + (opts.buttons[i].danger ? 'fallr-button-danger' : '')
                                                        + '" id="fallr-button-' + i + '">'
                                                        + opts.buttons[i].text + '</a>';
                                        }
                                    }
                                    return buttons;
                                } ())
                             )
                            .find('.fallr-button')
                    //.addClass(opts.theme)
                                .bind('click', function () {
                                    var buttonId = $(this).attr('id').substring(13); // id="fallr-button-12345" -> buttonId="12345"
                                    if (typeof opts.buttons[buttonId].onclick === 'function' && opts.buttons[buttonId].onclick != false) {
                                        var scope = document.getElementById('fallr'); // content holder
                                        opts.buttons[buttonId].onclick.apply(scope);
                                    } else {
                                        methods.hide();
                                    }
                                    return false;
                                });

                    var showFallr = function () {

                        // must be shown somewhere to count it's size/position, but not inside window yet
                        $f.show();

                        var xpos = ($w.width() - $f.outerWidth()) / 2 + $w.scrollLeft(),
                                yminpos,
                                ymaxpos,

                        // if message wider than window viewport make it absolute 
                                pos = ($w.height() > $f.height() && $w.width() > $f.width()) ? 'fixed' : 'absolute';

                        switch (opts.position) {
                            case 'bottom':
                                yminpos = (pos === 'fixed') ? $w.height() : $w.scrollTop() + $w.height();
                                ymaxpos = yminpos - $f.outerHeight();
                                break;
                            case 'center':
                                yminpos = (pos === 'fixed') ? (-1) * $f.outerHeight() : $o.offset().top - $f.outerHeight();
                                ymaxpos = yminpos + $f.outerHeight() + (($w.height() - $f.outerHeight()) / 2);
                                break;
                            // case 'top': 
                            default:
                                ymaxpos = (pos === 'fixed') ? 0 : $w.scrollTop();
                                yminpos = ymaxpos - $f.outerHeight();
                        }

                        // animate show                            
                        $f.css({
                            'left': xpos,
                            'position': pos,
                            'top': yminpos,
                            'z-index': opts.zIndex + 1
                        })
                                .animate({
                                    'top': ymaxpos
                                }, opts.easingDuration, opts.easingIn, function () {
                                    if (typeof callback === "function") {
                                        // execute callback
                                        callback.call(self);
                                    }
                                    if (opts.autoclose) {
                                        timeoutId = setTimeout(methods.hide, opts.autoclose);
                                    }
                                });
                    };

                    if (opts.useOverlay) {
                        // show overlay
                        if ($.browser.msie && $.browser.version < 9) {
                            $o.css({
                                'display': 'block',
                                'z-index': opts.zIndex
                            });
                            showFallr();
                        } else {
                            $o.css({
                                'z-index': opts.zIndex
                            }).fadeIn(showFallr);
                        }
                    } else {
                        showFallr();
                    }

                    // Keydown handler
                    $(document)
                        .bind('keydown', helpers.enterKeyHandler)
                        .bind('keydown', helpers.closeKeyHandler)
                        .bind('keydown', helpers.tabKeyHandler);

                    $('#fallr-buttons').children().eq(-1).bind('focus', function () {
                        //console.log('tab pressed');
                        $(this).bind('keydown', helpers.tabKeyHandler);
                    });

                    $f.find(':input').bind('keydown', function (e) {
                        helpers.unbindKeyHandler();
                        if (opts.suppress == false) {
                            if (e.keyCode === 13) {
                                //$(this).parents('form').trigger('submit');
                                console.log(1);
                                $('.fallr-button').eq(0).trigger('click');
                            }
                        }
                    });
                }
            },

            set: function (options, callback, self) {
                for (var i in options) {
                    if (defaults.hasOwnProperty(i)) {
                        // change default props with given props
                        defaults[i] = options[i];
                        if (opts && opts[i]) {
                            opts[i] = options[i];
                        }
                    }
                }
                // execute callback
                if (typeof callback === "function") {
                    callback.call(self);
                }
            }
        },

        helpers = {

            blink: function () {
                $('#fallr-wrapper').fadeOut(150, function () {
                    $(this).fadeIn(150);
                });
            },

            fixPos: function () {
                var $f = $('#fallr-wrapper'),
                    pos = $f.css('position');
                if ($w.width() > $f.outerWidth() && $w.height() > $f.outerHeight()) {
                    var newLeft = ($w.width() - $f.outerWidth()) / 2,
                        newTop = $w.height() - $f.outerHeight();
                    switch (opts.position) {
                        case 'center':
                            newTop = newTop / 2;
                            break;
                        case 'bottom':
                            break;
                        default:
                            newTop = 0;
                    }
                    if (pos == 'fixed') {
                        $f.animate({
                            'left': newLeft
                        }, function () {
                            $(this).animate({
                                'top': newTop
                            });
                        });
                    } else {
                        $f.css({
                            'position': 'fixed',
                            'left': newLeft,
                            'top': newTop
                        });
                    }
                } else {
                    var newLeft = ($w.width() - $f.outerWidth()) / 2 + $w.scrollLeft();
                    var newTop = $w.scrollTop();
                    if (pos != 'fixed') {
                        $f.animate({
                            'left': newLeft
                        }, function () {
                            $(this).animate({
                                'top': newTop
                            });
                        });
                    } else {
                        $f.css({
                            'position': 'absolute',
                            'top': newTop,
                            'left': (newLeft > 0 ? newLeft : 0)
                        });
                    }
                }
            },

            isActive: function () {
                return !!($('#fallr-wrapper').length > 0);
            },

            enterKeyHandler: function (e) {
                // get Enter key
                if (e.keyCode === 13) {
                    $('#fallr-buttons').children().eq(0).focus();
                    helpers.unbindKeyHandler();
                }
            },

            tabKeyHandler: function (e) {
                // get Tab key
                if (e.keyCode === 9) {
                    $('#fallr-wrapper').find(':input, .fallr-button').eq(0).focus();
                    helpers.unbindKeyHandler();
                    e.preventDefault();
                }
            },

            closeKeyHandler: function (e) {
                // get ESC key
                if (e.keyCode === 27 && opts.closeKey) {
                    methods.hide();
                }
            },

            unbindKeyHandler: function () {
                $(document)
                    .unbind('keydown', helpers.enterKeyHandler)
                    .unbind('keydown', helpers.tabKeyHandler);
            }
        };

    // wait until DOM ready
    $(document).ready(function () {
        $('body').append('<div id="fallr-overlay"></div>');

        $('#fallr-overlay').bind('click', function () {
            if (opts.closeOverlay) {
                methods.hide();
            } else {
                helpers.blink();
            }
        });
    });

    $(window).resize(function () {
        if (helpers.isActive()) {
            helpers.fixPos();
        }
    });

    // pollute jQuery global namespace
    $.fallr = function (method, options, callback) {

        // set scope to window
        var self = window;

        if (typeof method === 'object') {
            options = method;
            method = 'show';
        }
        if (methods[method]) {
            if (typeof options === 'function') {
                callback = options;
                options = null;
            }
            methods[method](options, callback, self);
        } else {
            $.error('Method "' + method + '" does not exist in $.fallr');
        }
    };

} (jQuery));

