if (!window.console || !console.firebug) {
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    
    for (var i = 0; i < names.length; ++i) {
        window.console[names[i]] = function() {}
    }
}


/**
 * @link     http://dhtmlkitchen.com/?category=/JavaScript/&date=2008/09/11/&entry=Function-prototype-bind
 * @param    {Object} context the 'this' value to be used.
 * @param    {arguments} [1..n] optional arguments that are
 *           prepended to returned function's call.
 * @return   {Function} a function that applies the original
 *           function with 'context' as the thisArg.
 */
Function.prototype.bind = function(context) {
    var ap, concat, args;
    var fn = this;
    var isPartial = arguments.length > 1;

    if (!isPartial) { // Strategy 1: just bind, not a partialApply
        return function() {
            if(arguments.length !== 0) {
                return fn.apply(context, arguments);
            } else {
                return fn.call(context); // faster in Firefox.
            }
        };
    } else { // Strategy 2: partialApply
        ap = Array.prototype,
        args = ap.slice.call(arguments, 1);
        concat = ap.concat;
        return function() {
            return fn.apply(context, arguments.length === 0 ? args : concat.apply(args, arguments));
        };
    }
};

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://crestidg.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // *     example 1: number_format(1234.5678, 2, '.', '');
    // *     returns 1: 1234.57

    var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
    var d = dec_point == undefined ? "," : dec_point;
    var t = thousands_sep == undefined ? "." : thousands_sep, s = n < 0 ? "-" : "";
    var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;

    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
}


var yuice = [];

(function($) {

    $.yuice = {};
    $.yuice.config = {};

    $.yuice.init = function() {
        if (yuice) {
            $.each(yuice, function(i, func) {
                try {
                    if (typeof func == 'function') {
                        func();
                    }
                } catch (e) {
                    alert('An error occurred! Please contact the website administrator.');
                    console.debug(i, func, e);
                }
            });
        }
    };

    $.yuice.load = function(url, successCallback, errorCallback) {
        var urls = (typeof url == 'object') ? url : [url];

        $(urls).each(function(i, url) {
            console.debug('load script (' + i + '): ' + url);

            jQuery.ajax({
                type: 'GET',
                dataType: 'script',
                url: url,
                async: false,
                global: false,
                data: null,
                success: function() {},
                complete: function() {}
            });

            console.debug('done');
        })
    }

    $.isObject = function (obj) {
        return Object.prototype.toString.call(obj) === "[object Object]";
    }

    $.block = function(options) {
        var overlay = $('#overlay');
        var defaults = {loader: false};

        options = $.extend({}, defaults, options || {});

        if (overlay.length == 0) {
            overlay = $('<div id="overlay"></div>').css('opacity', 0.4)
                                                   .appendTo('body');
        }

        overlay.removeClass('closing')
               .fadeIn('fast');
               //.css('cursor', (options.loader) ? 'wait' : 'auto');
    }

    $.unblock = function(options) {
        var overlay = $('#overlay').addClass('closing');
        var defaults = {timeout: 5};

        options = $.extend({}, defaults, options || {});

        setTimeout(function() {
            if (overlay.hasClass('closing')) {
                overlay.fadeOut('fast');
            }
        }, options.timeout);
    }

    $.loading = function(options) {
        if (options == false) {
            return;
        }

        var loading = $('#loading');
        var defaults = {message: $('body').data('lang.default').loading,
                        loader: true};

        options = $.extend({}, defaults, options || {});

        $.block(options);

        if (loading.length == 0) {
            loading = $('<div id="loading" class="window"></div>').appendTo('body');
        }

        loading.html(options.message).center().open({loading: options});
    }

    $.unloading = function(options) {
        if (options == false) {
            return;
        }

        $('#loading').close(options);
        $.unblock(options);
    }

})(jQuery);



(function($) {

    $.fn.buttonval = function(){
        if ($.browser.msie) { // ie workaround
            var label = $(this).text();
            $(this).text('');
            var value = $(this).val();
            $(this).text(label);
            return value;
        } else {
            return $(this).val();
        }
    };

    $.fn.floatval = function(){
        var value = $(this).val();

        value = value.replace(/([.,])([0-9]{0,2})$/g, '#$2');
        value = value.replace(/([.,])/g, '');
        value = value.replace(/(#)/g, '.');

        return parseFloat(value);
    };

    $.fn.idle = function(time){
        var elem = $(this);
        elem.queue(function(){
            setTimeout(function(){
                elem.dequeue();
            }, time);
        });
    };

    $.fn.disable = function() {
        return this.each(function() {
            $(this).addClass('disabled');
            $(this).attr('disabled', 'disabled');
            $(this).css('opacity', 0.7);
        });
    }

    $.fn.enable = function() {
        return this.each(function() {
            $(this).removeClass('disabled');
            $(this).removeAttr('disabled');
            $(this).css('opacity', 1);
        });
    }
    
    $.fn.plugin = function(storage, options, defaultsOrMethod, constructor) {
        return this.each(function() {
            var elem = $(this);
            var data = elem.data(storage);

            if (!data) { // new instance
                options = $.extend({}, defaultsOrMethod, options || {}); // new

                if (constructor) {
                    //console.debug('plugin.init', [this, storage, options]);
                    constructor.bind(elem)(options);
                }
            } else { // update
                options = $.extend({}, data, options || {}); // update
            }

            if (typeof defaultsOrMethod == 'function') {
                defaultsOrMethod.bind(elem)(options);
            }

            elem.data(storage, options);

            //console.debug('plugin', [this, storage, options]);
        });
    }

})(jQuery);



/**
 * overlay && tabs
 */
jQuery(function() {

    $.yuice.init();

    console.debug($.yuice.config);

    $('#langselector a:first').click(function() {
        if ($('#langselector li').not(':first').is(':visible')) {
            $('#langselector li').not(':first').slideUp(100);
        } else {
            $('#langselector li').not(':first').slideDown(100);
        }

        return false;
    });

    $('.ajax').live('click', function() {
        options         = {};
        options.loading = {type: 'default'};
        options.handler = 'link';
        options.element = $(this);
        options.url     = $(this).attr('href');
        $.ajax(options);

        return false;
    });

    $('div.window form:not(.nonajax) button[value="ok"]').live('click', function() {
        $(this).parents('form:first').submit();
        return false;
    });

    $('a.window-open, button.window-open').live('click', function() {
        $(this).open();
        return false;
    });

    $('a.window-close, button.window-close').live('click', function() {
        $(this).close();
        return false;
    });

    $('form:not(.nonajax)').livequery(function() {
        $(this).form();
    });

    $('input[title], textarea[title]').livequery(function() {
        $(this).example(function() {return $(this).attr('title');}, {className: 'example'})
    });

    $('.qtip').livequery(function() {
        $(this).qtip({style: {name: 'dark', tip: false, delay: 10, effect: {length: 50}}});
    });

    $('.truncatable').livequery(function() {
        var classNames = $(this).attr('class');
        var result = classNames.match(/(truncatable-)([0-9]+)/);
        var length = 150;

        if (result != null) {
            length = result[2];
        }

        $(this).truncate(length, {chars: /\s/, trail: ["... (<a href='#' class='truncate_show'>mehr</a>)", " (<a href='#' class='truncate_hide'>weniger</a>)"]});
    });

    $('div.multiselect').livequery(function() {
        var select = $('select', this);

        $(select[0]).multiselect({
            selected: $(select[1])
        });
    });

    $('#upload form a', this).live('click', function() {
        var a = $(this);

        if (a.hasClass('add')) {
            var clone = a.parent().clone().removeClass('first')[0];
            $('input', clone).replaceWith('<input type="file" name="file[]" />');
            $(clone).hide().insertAfter(a.parent()).slideDown('fast');
        }
        if (a.hasClass('delete')) {
            a.parent().slideUp('fast', function() {
                a.remove();
            });
        }

        a.parents('div.window:first').center();

        return false;
    });

    $('.selector').click(function() {
        var container = $(this).closest('.selectable-container');

        if (container.length > 0) {
            if ($(this).is('.all')) {
                $('input.selectable', container).attr('checked', 'checked');
            }
            if ($(this).is('.none')) {
                $('input.selectable', container).removeAttr('checked');
            }
        }

        return false;
    });

    /*
     upload:
     <form action="/registration#/registration/upload">
     */

    $.ajaxSetup({
        loading: {type: 'ajax', loader: true},
        dataType: 'json',
        type: 'POST',
        params: null,
        timeout: 10000,
        upload: true,
        async: true,
        global: true,
        element: null,
        data: null,
        beforeSend: function (xhr) {
            this.data = (this.dataType == 'json') ? $.toJSON(this.params) : this.params;
            this.onStart(this.element);
        },
        success: function (data, textStatus) {
            console.debug("ajax.success", arguments);

            /*var options = this;
            var error = $(data).attr('error');

            if (error) {
                $.each(error, function(type, data) {
                    options.onError(type, null, data);
                });
            }*/

            this.onSuccess(data, this.element);

            //$.yuice.load(data.attr('scripts'));
        },
        error: function (xhr, textStatus, errorThrown) { // typically only one of textStatus or errorThrown will have info
            console.debug("ajax.error", arguments);
            $.unloading(this.loading);
            this.onError(textStatus, errorThrown, xhr.responseBody, this.element);
        },
        complete: function (xhr, textStatus) {
            console.debug("ajax.complete", arguments);
            this.onComplete(xhr, textStatus, this.element);
        },
        onStart: function(element) {
            console.debug("ajax.onStart", arguments);
            $.loading(this.loading);
            return true;
        },
        onSuccess: function(data, element) {
            console.debug("ajax.onSuccess", arguments);
            $.unloading(this.loading);
            $(data).execute(element, null, null);
            return true;
        },
        onComplete: function(element) {
            console.debug("ajax.onComplete", arguments);
            return true;
        },
        onError: function(textStatus, errorThrown, response, element) {
            console.debug("ajax.onError", arguments);
            $.unloading(this.loading);
            switch (textStatus) {
                case 'nocontroller':
                    $.error('Controller nicht gefunden!');
                    break;
                case 'timeout':
                case 'parsererror':
                case 'notmodified':
                case 'error':
                case 'timeout':
                // no controller/404
                default:
                    $.error();
            }
            return true;
        }
    });



    $.execute.defaults.actions.thumbnail = function(data) {
    }

    $.execute.defaults.actions.file = function(data, type, element) {
        /*
        var form = $(element).data('form');

        if (form) {
            var formData = $(form).data('form.data') || {};

            if (formData) {
                var files = $(formData).attr('files') || {};
                $(files).attr(data.attr('id'), data);
                $(formData).attr('files', files);
            }

            $(form).attr('form.data', formData);
            console.debug('form.data', $(form).attr(form));
        }
        */
    }

    $.execute.defaults.actions.window = function(data, type, element) {
        data = $(data);

        var elem = $(data.attr('content'));
        var id = '#' + elem.attr('id');

        $(id).remove();
        $(elem).appendTo('body');
        $(id).open();

        $(':file', id).data('form', $(element).parents('form'));
    }

    $.execute.defaults.actions.replace = function(data, type, element) {
        var selector = data.attr('selector');
        var content = data.attr('content');

        $(selector).html(content);
    }

    $.execute.defaults.actions.remove = function(data, type, element) {
        var selector = data.attr('selector');
        var content = data.attr('content');

        $(selector).fadeOut('fast', function() {
            $(this).remove();
        });
    }

    $.execute.defaults.actions.prepend = function(data, type, element) {
        var selector = data.attr('selector');
        var content = data.attr('content');

        $(content).hide().prependTo(selector).fadeIn('slow');
    }

    $.execute.defaults.actions.append = function(data, type, element) {
        var selector = data.attr('selector');
        var content = data.attr('content');

        $(content).hide().appendTo(selector).fadeIn('slow');
    }

    $.execute.defaults.actions.success = function(data) {
        $.success(data[0]);
    }

    $.execute.defaults.actions.error = function(data) {
        $.error(data[0]);
    }

    $.execute.defaults.actions.confirm = function(data) {
    }

    $.execute.defaults.actions.form = function(data) {
        var form = $('form[name="' + data.attr('name') + '"]');
        
        $('ul.error', form).hide();
        $('ul.error li', form).remove();
        $('.error', form).not('ul').removeClass('error');

        $.each(data.attr('elements'), function(elementName, elementData) {
            var element = $('[name="' + elementName + '"]', form);

            if (element.size() == 0) { // e.g. multi select, named "field[]"
                element = $('[name="' + elementName + '[]"]', form);
            }

            var row = element.parents('dd:first');
            var ul = row.find('ul.error');

            $.each(elementData, function(type, typeData) {
                switch (type) {
                    case 'error':
                        if (element.is('.hide-error')) {
                            break;
                        }
                        if (typeData) {
                            element.addClass('error');
                            row.addClass('error');
                        }
                        break;
                    case 'messages':
                        $(typeData).each(function(i, message) {
                            $('<li />').html(message).appendTo(ul);
                        });
                        if ($('li', ul).size() > 0) {
                            ul.show();
                        }
                        break;
                }
            });
        });
    }

    $.execute.defaults.actions.location = function(data) {
        $.each(data[0], function(type, value) {
            switch (type) {
                case 'location':
                    if (value.match(/^#/)) {
                        location.hash = value;
                    } else {
                        location.href = value;
                    }
                    break;
            }
        });
    }

});







(function($) {

    $.crop = {
        defaults: {
            aspectRatio: null,
            //aspectRatio: 140/185, // 2/1.5 = 1.333333, thumb = 100 / 75
            minSize: [20, 20],
            allowSelect: false,
            keySupport: false,
            thumbnail: null,
            input: null,
            onChange: function(coords) {
                if (this.thumbnail) {
                    $('img', this.thumbnail).trigger('update', [[coords.w, coords.h, coords.x, coords.y]]);
                }
            }
        }
    }

    $.fn.crop = function(options) {
        return this.each(function() {
            options = $.extend({}, $.crop.defaults, options || {});

            var image = $(this);
            var thumbnail = $(options.thumbnail)
            var thumbnailWidth = thumbnail.width();
            var thumbnailHeight = thumbnail.height();
            var thumbnailImage = $('img', thumbnail);
            var thumbnailImageWidth = thumbnailImage.width();
            var thumbnailImageHeight = thumbnailImage.height();
            var thumbnailImageX = parseInt(thumbnailImage.css('marginLeft').replace(/px/, '')) * -1;
            var thumbnailImageY = parseInt(thumbnailImage.css('marginTop').replace(/px/, '')) * -1;
            var imageWidth = image.width();
            var imageHeight = image.height();
            var diffWidth = (imageWidth / thumbnailImageWidth);
            var diffHeight = (imageHeight / thumbnailImageHeight);

            if (options.aspectRatio == null) {
                options.aspectRatio = thumbnailWidth/thumbnailHeight;
            }

            options.image = image;
            options.setSelect = [thumbnailImageX * diffWidth,
                                 thumbnailImageY * diffHeight,
                                 (thumbnailImageX + thumbnailWidth) * diffWidth,
                                 (thumbnailImageY + thumbnailHeight) * diffHeight];

            $.Jcrop(image, options);
        });
    }


    // A method for quickly swapping in/out CSS properties to get correct calculations
    $.swap = function( elem, options, callback ) {
         var old = {};

         // Remember the old values, and insert the new ones
         for ( var name in options ) {
              old[ name ] = elem.style[ name ];
              elem.style[ name ] = options[ name ];
         }

         callback.call( elem );

         // Revert the old values
         for ( var name in options ) {
              elem.style[ name ] = old[ name ];
         }
    }



    $.getCropCoords = function(image, aspectRatio) {
        image = $(image);

        var orgWidth = image.width();
        var orgHeight = image.height();

        var width = orgWidth;
        var height = orgHeight;
        var ratio = aspectRatio;

        var newWidth = 0;
        var newHeight = 0;

        do {
            if (ratio >= 0) {
                newWidth = width;
                newHeight = parseInt(Math.ceil(width / ratio));
                width--;
            } else {
                newWidth = parseInt(Math.ceil(height / ratio));
                newHeight = height;
                height--;
            }
        } while (newWidth > orgWidth || newHeight > orgHeight);

        var xCenter = parseInt(Math.ceil(orgWidth-newWidth)/2);
        var yCenter = parseInt(Math.ceil(orgHeight-newHeight)/2);

        console.debug({orgWidth: orgWidth,
                       orgHeight: orgHeight,
                       newWidth: newWidth,
                       newHeight: newHeight,
                       xCenter: xCenter,
                       yCenter: yCenter});

        return [newWidth, newHeight, xCenter, yCenter];
    }

    $.fn.thumbnail = function(image, options) {
        return this.each(function() {
            options = $.extend({}, {
                aspectRatio: 4/3,
                coords: null,
                input: null,
                onChange: function(coords, element) {
                    if (this.input) {
                        var data = $(this.input).data('data');
                        data.file.crop = coords;
                    }
                }
            }, options || {});

            var container = $(this);
            image = $(image);

            if (options.coords == null) {
                options.coords = $.getCropCoords(image, options.aspectRatio);
            }

            options.width = image.width();
            options.height = image.height();

            function update(event, coords) {
                var rx = (container.width() / coords[0]);
                var ry = (container.height() / coords[1]);

                $(this).css({
                    width: Math.round(rx * options.width) + 'px',
                    height: Math.round(ry * options.height) + 'px',
                    marginLeft: '-' + Math.round(rx * coords[2]) + 'px',
                    marginTop: '-' + Math.round(ry * coords[3]) + 'px'
                });

                options.onChange.bind(options)(coords, this);
            }

            $('<img />').attr('src', image.attr('src'))
                        .appendTo(container)
                        .bind('update', options, update)
                        .trigger('update', [options.coords]);
        });
    }

    $.fn.disableEnter = function() {
        return this.each(function() {
           $(this).keydown(function(e) {
                if (e.keyCode == 13) {
                    $(this).blur();
                    e.preventDefault();
                    return false;
                }
                return true;
           });
        });
    }

    $.fn.inlineedit = function(options) {
        options = $.extend({}, {
            minLength: 1,
            maxLength: 255,
            fileExtension: false,
            onChange: function() {}
        }, options || {});

        return this.each(function() {
            $(this).click(function() {
                var container = $(this);

                if ($('input', container).length > 0) {
                    return;
                }

                var value = container.html();
                container.html('');

                var ext = value.match(/\.([a-z])+$/); // remove ´file extension
                value = value.replace(/\.([a-z])+$/, '');

                var input = $('<input type="text" />')
                    .attr('value', value)
                    .data('value', value)
                    .data('ext', ext)
                    .appendTo(container)
                    .autoGrowInput()
                    .focus();

                // handle blur event
                input.blur(function() {
                    var input = $(this);
                    var value = $.trim(input.val());
                    var ext = input.data('ext');

                    if (value.length == 0) {
                        value = input.data('value');
                    }

                    if (ext) {
                        value = value + ext[0];
                    }

                    options.onChange.bind(input)(value);
                    
                    input.remove();
                    container.html(value);
                }).disableEnter(); // ENTER blurs element, instead of submitting form
            })
        });
    }


    $.fn.autoGrowInput = function(options) {
        options = $.extend({
            maxWidth: 400,
            comfortZone: 20
        }, options);

        return this.filter('input:text').each(function() {
            var val = '';
            var input = $(this);
            var testSubject = $('<tester/>').css({
                position: 'absolute',
                width: 'auto',
                whiteSpace: 'nowrap',
                top: -9999,
                left: -9999,
                fontSize: input.css('fontSize'),
                fontFamily: input.css('fontFamily'),
                fontWeight: input.css('fontWeight'),
                letterSpacing: input.css('letterSpacing')
            });
            
            function check() {
                if (val === (val = input.val())) {
                    return;
                }

                // Enter new content into testSubject
                var escaped = val.replace(/&/g, '&amp;').replace(/\s/g,'&nbsp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                testSubject.html(escaped);

                // Calculate new width + whether to change
                var testerWidth = testSubject.width();

                input.width(testerWidth + options.comfortZone);
            }

            testSubject.insertAfter(input);

            $(this).bind('keyup keydown blur update focus', check);
        });
    };



    $.fn.multiselect = function(options) {
        var available = $(this);
        var selected = $(options.selected);

        // remove dummy entries (required for valid html)
        $('option.dummy', available).remove();
        $('option.dummy', selected).remove();

        // event
        function move() {
            var label = $(this).html();
            var value = $(this).attr('value');

            if (!$(this).is('.selected')) {
                $('<option />').html(label)
                               .attr('value', value)
                               .attr('selected', 'selected')
                               .addClass('selected')
                               .appendTo(selected)
                               .click(move);

                $(selected).selectsort();
            } else {
                $('<option />').html(label)
                               .attr('value', value)
                               .appendTo(available)
                               .click(move);

                $(available).selectsort();
            }

            $(this).remove();
        }

        // register click event to all options
        $('option[value!=""]', available).click(move);
        $('option', selected).addClass('selected').click(move);

        // select all - link
        available.next('a').click(function() {
            $('option', available).click();
            return false;
        });

        // deselect all - link
        selected.next('a').click(function() {
            $('option', selected).click();
            return false;
        });
    }

    $.fn.selectsort = function() {
        return this.each(function() {
            Array.prototype.sort.call(
                $('option', this),
                function(a,b) {
                  return $(a).text() > $(b).text() ? 1 : -1;
                }
            ).appendTo(this);
        });
    }
    
})(jQuery);






(function($) {

    $.execute = {
        defaults: {
            actions: {},
            errors: {}
        }
    }

    $.fn.execute = function(element, options, actions) {
        options = $.extend(true, $.execute.defaults, options || {});
        actions = actions || {};

        $(this).each(function() {
            $.each(this, function(type, data) {
                var callback;

                callback = $(actions).attr(type);

                if (!callback) {
                    callback = $(options.actions).attr(type);
                }

                if (callback) {
                    console.debug('execute', [type, data, element, options]);
                    callback($(data), type, element);
                }
            })
        });
    }

    $.fn.flatten = function(filter, dest) {
        filter = filter || []
        dest = dest || {}

        this.each(function() {
            $.each(this, function(key, value) {
                if ($.inArray(key, filter) == -1) {
                    if ($.isArray(value)) {

                    } else if ($.isObject(value)) {
                        $(value).flatten(filter, dest);
                    } else {
                        $(dest).attr(key, value);
                    }
                }
            });
        });

        return dest;
    }

})(jQuery);


