(function($) {
    $.extend(String.prototype, {
        toInt: function() {
            return parseInt(this.replace('px', ''), 10);
        }
    });
    
    $.extend(Function.prototype, {
        wrap: function(wrapper) {
            var __method = this;
            return function() {
                var a = [$.proxy(__method, this)].concat(Array.prototype.slice.call(arguments));
                return wrapper.apply(this, a);
            };
        }
    });
    
    $.extend(window, {
        jconfirm: function(content, callback) {
            var options;
            
            if ($.isPlainObject(content)) {
                options = content;
            } else {
                options = { content: content, callback: callback };
            }
            
            options = $.extend({
                title: 'Confirmation',
                yes: 'Yes',
                no: 'No'
            }, options);
            
            $('<div/>').html(options.content).dialog({
                modal: true,
                resizable: false,
                dialogClass: 'ui-dialog-confirm',
                closeOnEscape: false,
                width: 350,
                title: options.title,
                buttons: new function() {
                    buttons = {};
                    
                    buttons[options.yes] = function() {
                        $(this).dialog('destroy').remove();
                        callback();
                    };
                    buttons[options.no] = function() {
                        $(this).dialog('destroy').remove();
                    };
                    
                    return buttons;
                }
            });
        }
    });
    
    $.extend($.expr[':'], {
        inview: function(a) {
            var scrolltop = $(window).scrollTop();
            var elementTop = $(a).offset().top;
            var elementBottom = elementTop + $(a).outerHeight();
            
            // If scrolled past || not yet passed
            if ((scrolltop > elementTop) || (scrolltop + $(window).height() < elementBottom)) {
                return false;
            } else {
                return true;
            }
        }
    });
    
    $.extend($.fn, {
        dattr: function(attribute, value) {
            return value ? $(this).attr('data-' + attribute, value) : $(this).attr('data-' + attribute);
        },
        getPosition: function() {
            var el = $(this);
            var position = el.offset();
            return {
                top: position.top,
                left: position.left,
                height: el.innerHeight(),
                width: el.innerWidth()
            };
        },
        numbersOnly: function() {
            return $(this).bind('keypress', function(e) {
                //if the letter is not digit then display error and don't type anything
                if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57))
                {
                    if ($(this).next('.msg').length == 0) {
                        $(this).after('<span/>').next().addClass('msg').text('Digits Only').show().fadeOut(1200, function() { $(this).remove(); });
                    }
                    return false;
                }
            });
        },
        multibind: function() {
            var namespace = '';
            var hash = arguments[0];
            if (typeof(hash) == 'string') {
                namespace = hash;
                hash = arguments[1];
            }

            var eventName = function(name) {
                return (namespace == '') ? name : [name, namespace].join('.');
            };

            return this.each(function() {
                for (method in hash) {
                    $(this).bind(eventName(method), hash[method]);
                }
            });
        },
        
        loading: function(mode) {
            if (mode === true) { mode = 'show'; }
            if (mode === false) { mode = 'hide'; }

            var mode = mode || 'show';
            return this.each(function() {
                switch(mode) {
                    case 'show':
                    $(this).children().hide();
                    $(this).find('div.loading').remove();
                    $(this).append('<div class="loading"/>');
                    break;

                    case 'hide':
                    $(this).children().show();
                    $(this).find('div.loading').remove();
                    break;
                }
            });
        },
        
        disableMouse: function() {
            return this.each(function() {
                var overlay = $(this).data('disableOverlay');
                if (!overlay) {
                    var element = $(this), zIndex = element.css('z-index');
                    if (zIndex == 'auto') { zIndex = 0; }
                    var overlay = $('<div/>').css($.extend(element.position(), {
                        position: 'absolute',
                        width: element.outerWidth(),
                        height: element.outerHeight(),
                        zIndex: zIndex + 1
                    })).insertAfter(element);
                
                    element.bind('remove', function() {
                        element.enableMouse();
                    });
                
                    element.data('disableOverlay', overlay);
                }
            });
        },
        
        enableMouse: function() {
            return this.each(function() {
                var overlay = $(this).data('disableOverlay');
                if (overlay) {
                    $(this).removeData('disableOverlay');
                    overlay.remove();
                }
            });
        },
        
        unwrap: function(expr) {
            return this.each(function() {
                $(this).parents(expr).eq(0).after(this).remove();
            });
        }
    });
    
    $.extend($, {
        extractParam: function(url, name) {
            var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(url);
            return results[1] || 0;
        },
        submit: function(type, url, params) {
            // $.submit('/path/to/submit')
            if (!url) {
                url = type;
            // $.submit('/path/to/submit', { foo: 'bar' })
            } else if ($.isPlainObject(url)) {
                params = url;
                url = type;
            }

            var form = $('<form/>', { action: url, method: 'post' });
            params = $.extend(params, { _method: type });
            $.each(params, function(name, value) {
                // Support for array values
                $.each($.makeArray(value), function(i, value) {
                    // Needs to be this format to work in IE
                    $('<input type="hidden" name="' + name + '" />').val(value).appendTo(form);
                });
            });

            form.appendTo('body').hide().trigger('submit');
        }
    });
    
    $.extend($.event.special, {
        contentchange: {
            add: function(event) {
                var delay = event.data && event.data.delay || 300;
                var lastValue = this.value;
                var el = this;
                var timer;
                var originalHandler = event.handler;
                
                event.handler = function(event) {
                    window.clearTimeout(timer);
                    timer = window.setTimeout(function() {
                        if (el.value != lastValue) {
                            originalHandler.apply(el, arguments);
                            lastValue = el.value;
                        }
                    }, delay);
                };
            },
            setup: function() {
                $(this).bind('keyup', $.event.special.contentchange.handler);
            },
            teardown: function() {
                $(this).unbind('keyup', $.event.special.contentchange.handler);
            },
            handler: function(event) {
                event.type = 'contentchange';
                $.event.handle.apply(this, arguments);
            }
        }
    });
    
})(jQuery);