﻿/// <reference path="../lib/jquery.js" />
/// <reference path="../lib/json2.js" />
/// <reference path="../lib/jquery.cookies.js" />
/// <reference path="../lib/jquery.form.js" />



// typeof extension

$.is = {
    Null: function(a) {
        return a === null;
    },
    Undefined: function(a) {
        return a === undefined;
    },
    nt: function(a) {
        return (a === null || a === undefined);
    },
    Function: function(a) {
        if(a===null) {return false;}
        return (typeof (a) === 'function') ? a.constructor.toString().match(/Function/) !== null : false;
    },
    String: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'string') ? true : (typeof (a) === 'object') ? a.constructor.toString().match(/string/i) !== null : false;
    },
    Array: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'object') ? a.constructor.toString().match(/array/i) !== null || a.length !== undefined : false;
    },
    Boolean: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'boolean') ? true : (typeof (a) === 'object') ? a.constructor.toString().match(/boolean/i) !== null : false;
    },
    Date: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'date') ? true : (typeof (a) === 'object') ? a.constructor.toString().match(/date/i) !== null : false;
    },
    HTML: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'object') ? a.constructor.toString().match(/html/i) !== null : false;
    },
    Number: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'number') ? true : (typeof (a) === 'object') ? a.constructor.toString().match(/Number/) !== null : false;
    },
    Object: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'object') ? a.constructor.toString().match(/object/i) !== null : false;
    },
    RegExp: function(a) {
        if (a === null) { return false; }  
        return (typeof (a) === 'function') ? a.constructor.toString().match(/regexp/i) !== null : false;
    }
};

$.type = {
    of: function(a) {
        for (var i in is) {
            if (is[i](a)) {
                return i.toLowerCase();
            }
        }
    }
};


// Prototype Extensions

JSON.zeroDate = new Date(-62135596800000);

JSON.reISODate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/;
JSON.reMsDate = /^\/Date\(([\-\d]*)\)\/$/;

JSON.parseWithDate = function(json) {
    return JSON.parse(json,function(key, value) {
        if (typeof value === 'string') {
            var a = JSON.reISODate.exec(value);
            if (a)
                return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
            a = JSON.reMsDate.exec(value);
            if (a) {
                return new Date(+a[1]);
            }
        }
        return value;
    });
};
JSON.dateStringToDate = function(dtString) {
    var a = JSON.reISODate.exec(dtString);
    if (a)
        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
    a = JSON.reMsDate.exec(dtString);
    if (a) {
        var b = a[1].split(/[-,.]/);
        return new Date(+b[0]);
    }
    return null;
};


$.getValueOrDefault = function(obj,key,def) {
    if (!$.is.Array(key)) {key = [key]}
    if (!$.is.Array(def)) {def = [def]}
    
    for(var i=0;i<key.length;i++) {
        if(obj[key[i]]!=null) {return obj[key[i]]}
    }

    for (var i = 0; i < def.length; i++) {
        if (def[i] != null) { return def[i] }
    }
    
    return null
};

$.createIfNotExists = function(obj,key,def) {
    if(def==null) {def = {}}
    return obj[key] = $.getValueOrDefault(obj,key,def)
};




// humanise
$.humanizeCamelCase = function(camelCase) {return camelCase.replace(/([A-Z]+)/g, " $1").replace(/^ /, "")};



// JQuery Extensions

$.keys = function(obj) {
        var a = [];
        $.each(obj, function(k) { a.push(k) });
        return a;
};




// timeago

(function($) {
    $.timeago = function(timestamp) {
        if (timestamp instanceof Date) return inWords(timestamp);
        else if (typeof timestamp == "string") return inWords($.timeago.parse(timestamp));
        else return inWords($.timeago.datetime(timestamp));
    };
    var $t = $.timeago;

    $.extend($.timeago, {
        settings: {
            refreshMillis: 60000,
            allowFuture: false,
            strings: {
                prefixAgo: null,
                prefixFromNow: null,
                suffixAgo: "ago",
                suffixFromNow: "from now",
                seconds: "less than a minute",
                minute: "about a minute",
                minutes: "%d minutes",
                hour: "about an hour",
                hours: "about %d hours",
                day: "1 day",
                days: "%d days",
                month: "about a month",
                months: "%d months",
                year: "about a year",
                years: "%d years",
                numbers: []
            }
        },
        inWords: function(distanceMillis) {
            var $l = this.settings.strings;
            var prefix = $l.prefixAgo;
            var suffix = $l.suffixAgo;
            if (this.settings.allowFuture) {
                if (distanceMillis < 0) {
                    prefix = $l.prefixFromNow;
                    suffix = $l.suffixFromNow;
                }
                distanceMillis = Math.abs(distanceMillis);
            }

            var seconds = distanceMillis / 1000;
            var minutes = seconds / 60;
            var hours = minutes / 60;
            var days = hours / 24;
            var years = days / 365;

            function substitute(stringOrFunction, number) {
                var string = $.isFunction(stringOrFunction) ? stringOrFunction(number) : stringOrFunction;
                var value = ($l.numbers && $l.numbers[number]) || number;
                return string.replace(/%d/i, value);
            }

            var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
            seconds < 90 && substitute($l.minute, 1) ||
            minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
            minutes < 90 && substitute($l.hour, 1) ||
            hours < 24 && substitute($l.hours, Math.round(hours)) ||
            hours < 48 && substitute($l.day, 1) ||
            days < 30 && substitute($l.days, Math.floor(days)) ||
            days < 60 && substitute($l.month, 1) ||
            days < 365 && substitute($l.months, Math.floor(days / 30)) ||
            years < 2 && substitute($l.year, 1) ||
            substitute($l.years, Math.floor(years));

            return $.trim([prefix, words, suffix].join(" "));
        },
        parse: function(iso8601) {
            var s = $.trim(iso8601);
            s = s.replace(/\.\d\d\d/, ""); // remove milliseconds
            s = s.replace(/-/, "/").replace(/-/, "/");
            s = s.replace(/T/, " ").replace(/Z/, " UTC");
            s = s.replace(/([\+-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00 -> -0400
            return new Date(s);
        },
        datetime: function(elem) {
            // jQuery's `is()` doesn't play well with HTML5 in IE
            var isTime = $(elem).get(0).tagName.toLowerCase() == "time"; // $(elem).is("time");
            var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
            return $t.parse(iso8601);
        }
    });

    $.fn.timeago = function(date) {
        
        var self = this;
        
        if(date) {
            self.each(function() {
                $(this).data("timeago",{datetime:date})
            });
        }
        
        self.each(refresh);

        var $s = $t.settings;
        if ($s.refreshMillis > 0) {
            setInterval(function() { self.each(refresh); }, $s.refreshMillis);
        }
        return self;
    };

    function refresh() {
        
        var data = prepareData(this);
        if (!isNaN(data.datetime)) {
            $(this).text(inWords(data.datetime));
        }
        return this;
    }

    function prepareData(element) {
        element = $(element);
        if (!element.data("timeago")) {
            element.data("timeago", { datetime: $t.datetime(element) });
            var text = $.trim(element.text());
            if (text.length > 0) element.attr("title", text);
        }
        return element.data("timeago");
    }

    function inWords(date) {
        return $t.inWords(distance(date));
    }

    function distance(date) {
        return (new Date().getTime() - date.getTime());
    }

    // fix for IE6 suckage
    document.createElement("abbr");
    document.createElement("time");

})(jQuery);

// I translate the coordiantes from a global context to
// a local context.
$.fn.globalToLocal = function(globalX, globalY) {
    // Get the position of the context element.
    var position = $(this).offset();

    // Return the X/Y in the local context.
    return ({
        x: Math.floor(globalX - position.left),
        y: Math.floor(globalY - position.top)
    });
};


// I translate the coordinates from a local context to
// a global context.
$.fn.localToGlobal = function(localX, localY) {
    // Get the position of the context element.
    var position = $(this).offset();

    // Return the X/Y in the local context.
    return ({
        x: Math.floor(localX + position.left),
        y: Math.floor(localY + position.top)
    });
};


$.topZIndex = function(selector) {
    /// <summary>
    /// 	Returns the highest (top-most) zIndex in the document
    /// 	(minimum value returned: 0).
    /// </summary>	
    /// <param name="selector" type="String" optional="true">
    /// 	(optional, default = "body *") jQuery selector specifying
    /// 	the elements to use for calculating the highest zIndex.
    /// </param>
    /// <returns type="Number">
    /// 	The minimum number returned is 0 (zero).
    /// </returns>

    return Math.max(0, Math.max.apply(null, $.map($(selector || "body *"),
		function(v) {
		    return parseInt($(v).css("z-index")) || null;
		}
	)));
};

$.fn.topZIndex = function(opt) {
    /// <summary>
    /// 	Increments the CSS z-index of each element in the matched set
    /// 	to a value larger than the highest current zIndex in the document.
    /// 	(i.e., brings all elements in the matched set to the top of the
    /// 	z-index order.)
    /// </summary>	
    /// <param name="opt" type="Object" optional="true">
    /// 	(optional) Options, with the following possible values:
    /// 	increment: (Number, default = 1) increment value added to the
    /// 		highest z-index number to bring an element to the top.
    /// 	selector: (String, default = "body *") jQuery selector specifying
    /// 		the elements to use for calculating the highest zIndex.
    /// </param>
    /// <returns type="jQuery" />

    // Do nothing if matched set is empty
    if (this.length === 0) {
        return this;
    }

    opt = $.extend({ increment: 1, selector: "body *" }, opt);

    // Get the highest current z-index value
    var zmax = $.topZIndex(opt.selector), inc = opt.increment;

    // Increment the z-index of each element in the matched set to the next highest number
    return this.each(function() {
        $(this).css("z-index", zmax += inc);
    });
};

// UniqueIndex

var _UNIQUEINDEX = 0;

$.uniqueIndex = function() {
    return _UNIQUEINDEX++;
};


// Synchronous HTTP request return javascript object
$.syncJSON = function(url, data, method) {
    var out;

    var relayOutput = function(data) {
        out = data;
    }

    $.ajax({
        type: method ? method : 'GET',
        url: url,
        dataType: 'json',
        success: relayOutput,
        data: data,
        async: false
    });

    return out;
};


$.fn.onEnterKey = function(func) {

    return $(this).keypress(function(e) {
    
        if(e.keyCode == 13) {
            func(e);
        }
    
    });

}

$.screen = function() {
    
    var body = $("body")
    
    return $('<div class="screen"/>')
            .css({
                position:"absolute"
                ,top:0
                ,left:0
            })
            .width(body.width())
            .height(body.height())
            .appendTo(body)
            .topZIndex()

}

// superInput plugin - ComboBox type control extends jQuery UI autocomplete

/*
    usage $([selector]).superInput(options);
    
    options:
    
        disabled - Boolean - Default:false
        delay - Integer - Default:300
        minLength - Integer - Default:1 (0 if select)
        source - String, Array, Callback - Default:none, must be specified
        
        emptyValue - String - Default:""
        allowEmptyValue - Boolean -  Default:true (false if select)
        placeholderClass - String -  Default:"superInput-placeholder"
        mustMatch - Boolean - Default:null (true if select)
        placeholder - String - Default:null
        placeholdFirst - Boolean - Default:false
        preventNothing - Boolean - Default:null
        
 */

// custom jQuery selector - required for mustMatch scenarios
$.expr[':'].textEquals = function(a, i, m) {
    return $(a).text().match("^" + m[3] + "$");
};

//override to extend $.fn.val for superInput support
//(function($) {
//    var originalVal = $.fn.val;
//    $.fn.val = function(value) {
//        if (typeof value == 'undefined') {
//            if (this[0].getValue) {
//                return this[0].getValue();
//            }
//        }
//        return originalVal.call(this, value);
//    };
//})(jQuery);

//extend $.fn.val
$.fn.getValue = function() {
    if (this[0].getValue) {
        return this[0].getValue();
    }
    return $(this).val();
};
$.fn.setValue = function(value) {
    return this.each(function() {
        if (this.setValue) {
            this.setValue(value);
        } 
        else {
            $(this).val(value);
        }
        $(this).trigger("valueSet");
    })
};


$.fn.superInput = function (options) {

    var out = this;


    /*
    
    Options:
    
    see jquery-ui autocomplete docs for basic options
    
    additional options:
    
    
    
    
    */




    this.each(function () {
        var settings = $.extend({ emptyValue: "", allowEmptyValue: true, placeholderClass: "superInput-placeholder", autocomplete: true }, options);
        var input = $(this)

        if (settings.delay == null) {
            if (typeof (settings.source) === "array") { settings.delay = 0 }
        }

        if ($(this).is("select")) {

            if (settings.mustMatch != false) { settings.mustMatch = true; }

            settings.minLength = 0;

            if (!settings.source) {

                if (settings.delay == null) { settings.delay = 0 }

                settings.source = $(this).getData()

                if (settings.placeholdFirst) {
                    var firstOption = settings.source.shift()
                    settings.placeholder = firstOption.label;
                    //settings.emptyValue = firstOption.value;
                }
            }

            if (!settings.placeholdFirst && settings.preventNothing != false) { settings.preventNothing = true }

            input = $('<input type="text"/>').attr("class", $(this).attr("class"))
            $(this).after(input)
            $(this).remove()
            input.val($(this).val());
            if ($(this).attr("name")) { input.attr("name", $(this).attr("name")); }
            if ($(this).attr("id")) { input.attr("id", $(this).attr("name")); }
            out = input;
        }

        var isPlaceholder = function () {

            return input.is("." + settings.placeholderClass)
        }


        if (settings.placeholder) {

            var showPlaceholder = function (force) {
                //console.log(settings.preventNothing, force)
                if (!settings.preventNothing || force) {
                    input.addClass(settings.placeholderClass);
                    input.val(settings.placeholder)
                }
            }

            var hideInstructions = function () {
                if (isPlaceholder()) {
                    input.removeClass(settings.placeholderClass);
                    input.val("");
                    if (settings.minLength == 0) {
                        //input.autocomplete("search");
                    }
                }
            }


            var checkValue = function (force) {
                //console.log("checking value", input.attr("value"));
                if (!input.attr("value") || input.attr("value") == settings.placeholder) { showPlaceholder(force == true) }
            }

            checkValue(true);

            input.change(checkValue);
            input.bind("valueSet", checkValue);
            input.blur(function () { setTimeout(checkValue, 300) });
            input.focus(hideInstructions);
            input.closest("form").submit(function () {

                if (isPlaceholder()) { input.val(settings.emptyValue); }

            })


        }


        if (settings.minLength == 0) {
            input.addClass("superInput-select");
            if (settings.alwaysShowDropArrow) {
                input.addClass("superInput-always-show-drop");
            }
            input.click(function (e) {
                var hitX = input.globalToLocal(e.pageX, e.pageY).x;
                var width = input.outerWidth();
                if (hitX > width - 20) {
                    input.autocomplete("search", "")
                }
            })
            input.mousemove(function (e) {
                var hitX = input.globalToLocal(e.pageX, e.pageY).x;
                var width = input.outerWidth();
                if (hitX > width - 20) {
                    input.css("cursor", "pointer")
                }
                else {
                    input.css("cursor", "text")
                }
            })
        }


        if (settings.mustMatch) {

            //            settings.change = function(event, ui) {
            //                //if the value of the textbox does not match a suggestion, clear its value
            //                if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) {
            //                    $(this).val('');
            //                }
            //            }
            //            input.keydown(function(e) {
            //                var keyCode = e.keyCode || e.which;
            //                //if TAB or RETURN is pressed and the text in the textbox does not match a suggestion, set the value of the textbox to the text of the first suggestion
            //                if ((keyCode == 9 || keyCode == 13) && ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0)) {
            //                    $(this).val($(".ui-autocomplete li:visible:first").text());
            //                }
            //            });

            input.change(function (event, ui) {


                if (input.autocomplete("widget").find("li:textEquals('" + $(this).val() + "')").size() == 0 && !isPlaceholder()) {
                    $(this).val(input.autocomplete("widget").find("li:first").text());
                }
            })

        }

        input[0].getValue = function () {

            var out = isPlaceholder() ? "" : input.attr("value");

            return out ? out : settings.emptyValue;
        }


        if (settings.autocomplete) {
            input.autocomplete(settings)

            input.bind("autocompleteselect", function (event, ui) {

                if (input.val() != ui.item.value) {
                    input.val(ui.item.value);

                    input.change();
                }
            });

            input.manageAutoComplete();
        }

        var currentValue = $(this).getValue();
        var checkValueChange = function () {
            var oldValue = currentValue;
            currentValue = $(this).getValue();
            if (oldValue != currentValue) {
                $(this).trigger("valueChanged")
            }
        }
        input.bind("valueSet change", checkValueChange);


        input.focus(function () {
            this.select();
        })

        if (settings.autocomplete) {
            input.bind("autocompleteopen", function () {
                input.autocomplete("widget").matchWidth(input);
            })
        }
    });

    return out;
};


$.fn.matchWidth= function(target) {

    return $(this).each(function() {
    
        var targetWidth = $(target).outerWidth()
        //;
        var border = parseInt($(this).css("border-left-width"));
        border += parseInt($(this).css("border-right-width"));
        var padding = parseInt($(this).css("padding-left"));
        padding += parseInt($(this).css("padding-right"));
        
        $(this).css("width",(targetWidth-border-padding)+"px");
        
    });

};


$.fn.customDialog=function(options) {
    
    if(options=="resize") {
       this.dialog("close")
       
//        var widget = this.dialog("widget");
//       
//        var dialogHeight = widget.height()
//        
//        while(this.height<this[0].scrollHeight) {
//            this.dialog("options","height
//        }
//        
//        return null;
    }
    
    
    var content = this;
    
    var settings = $.extend({
        
        modal:true,
        width:"auto",
        //resize:"auto",
        show:{
            effect:"scale",
            options:{},
            speed:500,
            complete:function() {
                $(this).children().css("visibility","visible").css("opacity",0.5).fadeTo(500,1);
                $(content).css("height",$(content).height()+"px").css("max-height", "none");
                
            }
        },
        maxHeightMargin:200
        
    },options)
    
    
    
    var contentMinWidth = parseInt($(content).css("min-width"))
    if(settings.minWidth==null && !isNaN(contentMinWidth))
    {
        settings.minWidth = contentMinWidth+25;
    }
    
    $(content).css("max-height",$(window).height()-settings.maxHeightMargin);
   
    var out = $(this).dialog(settings);
    
   
   
    $(content).dialog("widget").children().css("visibility", "hidden")
    

    $(content).bind("dialogbeforeclose", function() {
        $(content).dialog("widget").children().css("visibility", "hidden")
    })
    
                
    
    return out;
} ;


$.confirm = function (message, okAction, cancelAction, options, okLabel) {

    var messageP = $('<p class="message"></p>').html(message)

    var settings = {
        resizable: false
    };

    if (!options) { options = {}; }

    var closeDialog = function () { messageP.dialog("close") }

    if (!options.buttons) {
        settings.buttons = {};

        eval("settings.buttons[\"" + (okLabel ? okLabel : "Yes") + "\"] = okAction ? okAction : closeDialog");

        if (cancelAction != false) {
            settings.buttons["No"] = cancelAction ? cancelAction : closeDialog;
        }
    }

    settings = $.extend(settings, options)

    return messageP.customDialog(settings);

};

$.alert = function (message, okAction, options) {
    return $.confirm(message,okAction,false,options,"OK")
};



// Add options to <select/> elements
$.fn.addOptions=function(data, options) {

    var settings = $.extend({}, options);

    return this.each(function() {
        var select = $(this);
        $.each(data, function(i, val) {

            select.append($('<option/>').val(val).text(val));

        })
    })
};

// Return data from <select/> element
$.fn.getData = function() {
    var data = [];
    $(this).find("option").each(function() {
        data.push({ label: $(this).text(), value: $(this).val() });
    });
    return data;
};

// Clone an elements computed css attributes
$.fn.cloneCSS = function(source, attr) {

    var source = $(source);

    return this.each(function() {


        var attr = attr ? attr : ['font-family', 'font-size', 'font-weight', 'font-style', 'color',
            'text-transform', 'text-decoration', 'letter-spacing', 'word-spacing',
            'line-height', 'text-align', 'vertical-align', 'direction', 'background-color',
            'background-image', 'background-repeat', 'background-position',
            'background-attachment', 'opacity', 'width', 'height', 'top', 'right', 'bottom',
            'left', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
            'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
            'border-top-width', 'border-right-width', 'border-bottom-width',
            'border-left-width', 'border-top-color', 'border-right-color',
            'border-bottom-color', 'border-left-color', 'border-top-style',
            'border-right-style', 'border-bottom-style', 'border-left-style', 'position',
            'display', 'visibility', 'z-index', 'overflow-x', 'overflow-y', 'white-space',
            'clip', 'float', 'clear', 'cursor', 'list-style-image', 'list-style-position',
            'list-style-type', 'marker-offset'];

        var len = attr.length, obj = {};
        for (var i = 0; i < len; i++) { $(this).css(attr[i], source.css(attr[i])); }
    });
};

// As cloneCSS but without position attributes
$.fn.cloneStyle = function(source) {

    return $(this).cloneCSS(source, ['font-family', 'font-size', 'font-weight', 'font-style', 'color',
        'text-transform', 'text-decoration', 'letter-spacing', 'word-spacing',
        'line-height', 'text-align', 'vertical-align', 'direction', 'background-color',
        'background-image', 'background-repeat', 'background-position',
        'background-attachment', 'opacity', 'width', 'height', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
        'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
        'border-top-width', 'border-right-width', 'border-bottom-width',
        'border-left-width', 'border-top-color', 'border-right-color',
        'border-bottom-color', 'border-left-color', 'border-top-style',
        'border-right-style', 'border-bottom-style', 'border-left-style', 'overflow-x', 'overflow-y', 'white-space',
        'clip', 'float', 'clear', 'cursor', 'list-style-image', 'list-style-position',
        'list-style-type', 'marker-offset']);
};


$.fn.matchPosition = function(source) {
    return this.each(function() {
        var position = $(source).position();
        $(this).css({ "left": position.left + "px", "top": position.right + "px", position: "absolute" });
    });
};
   

// customised jQuery UI datpicker
$.fn.dateWidget = function(options) {

    var settings = $.extend({
        dateFormat: "dd/mm/yy"
        , showOn: "button"
        , constrainInput: true
        , firstDay: 1
        , showAnim: "fadeIn"
        , changeYear:true
        , yearRange:"-100:+100"
        
    }
    , options)
    
   
    
    return $(this).each(function() {
        this.getValue = function() {
            return $(this).datepicker("getDate")
        }
        this.setValue = function(value) {
            
            if(value==null || $.is.Date(value)) {$(this).datepicker("setDate",value)}
            else {$(this).val(value).change()}
        }
        
    }).datepicker(settings).change(function() {
        var val = $(this).val();
        if (!val) { val = null }
        $(this).datepicker("setDate", val);
    })
};

// customised jQuery UI spinner
$.fn.spinnerWidget = function (options) {

    var settings = $.extend({ min: 0, max: 100 }, options);
    return $(this).each(function () {

        var val = parseInt($(this).val())
        if (isNaN(val)) { val = 0 }
        $(this).val(val)

        this.getValue = function () {

            return parseFloat($(this).val());

        }

        $(this).addClass("spinner").spinner(settings);

        if ($.browser.msie) {
            var $this = $(this);
            var $parent = $this.closest("div.detail");
            var $buttons = $parent.find(".ui-spinner-buttons");

            $buttons.css("top", "6px");
            $buttons.css("left", "-11px");
        }
    })
};

// customised jQuery UI slider- use by replacing a standard input
$.fn.sliderWidget = function(options) {
    var settings = $.extend({ amountSuffix: "%" }, options);
    var out = $(this).wrap('<div class="ui-slider-container"></div>').parent().append('<div><a href="#" class="ui-slider-handle"><span class="amount"/></a></div>').find("div:last");
    
    var handle = out.find("a.ui-slider-handle")
    
    out.find(".ui-slider-handle").focus(formInputFocus).blur(formInputBlur)

    settings.slide = function(e, ui) {
        handle.closest(".ui-slider-container").find("input").val(ui.value);

        var amountDisplay = settings.amountDisplay ? settings.amountDisplay(ui.value) : ui.value;

        handle.find(".amount").text(amountDisplay);
    };

//    settings.change = function(e, ui) {
//        settings.slide(e, ui)
//    }

    return out.each(function() {

        var ui = $(this)
        var input = $(this).parent().find("input");
        $(this).slider(settings).slider("value", input.val())
        input[0].setValue=function(val) {
            $(input[0]).val(val);
            ui.slider("value",val)
            settings.slide(null,{value:val})
        };
        
        settings.slide(null,{value:input.val()})
        
    });
};


//flick autocomplete on and off to prevent loss of value when user browses back to page
$.fn.manageAutoComplete = function() {

    return this.each(function() {
        //todo:test this
//        $(this).bind("mousedown keypress click focus",function() { $(this).attr("autocomplete", "off") });
//        $(this).blur(function() { $(this).removeAttr("autocomplete") });

//        $(this).removeAttr("autocomplete");
    });
};


/*
 * Title Caps
 * 
 * Ported to JavaScript By John Resig - http://ejohn.org/ - 21 May 2008
 * Original by John Gruber - http://daringfireball.net/ - 10 May 2008
 * License: http://www.opensource.org/licenses/mit-license.php
 */
	
  
$.titleCaps = function(title){

    var lower = function(word) {
        return word.toLowerCase();
    }

    var upper = function(word) {
        return word.substr(0, 1).toUpperCase() + word.substr(1);
    }
    
    
    var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)";
    var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)";
	
	var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0;
	
	while (true) {
		var m = split.exec(title);

		parts.push( title.substring(index, m ? m.index : title.length)
			.replace(/\b([A-Za-z][a-z.'Õ]*)\b/g, function(all){
				return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all);
			})
			.replace(RegExp("\\b" + small + "\\b", "ig"), lower)
			.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){
				return punct + upper(word);
			})
			.replace(RegExp("\\b" + small + punct + "$", "ig"), upper));
		
		index = split.lastIndex;
		
		if ( m ) parts.push( m[0] );
		else break;
	}
	
	return parts.join("").replace(/ V(s?)\. /ig, " v$1. ")
		.replace(/(['Õ])S\b/ig, "$1s")
		.replace(/\b(AT&T|Q&A)\b/ig, function(all){
			return all.toUpperCase();
		});
};


$.fn.multipleInput = function (options) {
    //;

    var settings = $.extend({
        displayField: "Name",
        lookupOptions: [],
        type: "lookup"
    }, options);

    var newDiv = $(this).wrap('<div class="multiple-input"/>').parent().empty()[0];

    var data

    var displayField = settings.displayField;

    var resetDisplay = function () {
        var isDate = (settings.type == "date");

        $(newDiv).empty();

        // Create remove items 
        $.each(data, function (index, item) {
            var value = item[displayField];

            if (isDate) {
                value = $.datepicker.formatDate("dd/mm/yy", item[displayField]);
            }

            var itemLink = $('<a class="item" href="#" title="click to remove"/>').text(value);
            //if(index!=data.length-1) {itemLink.append(",")}
            itemLink.prepend('<span class="icon"></span)>');
            $(newDiv).append(itemLink)

            // Click to remove
            itemLink.click(function () {
                data.splice(index, 1)
                resetDisplay();
                return false;
            })
        });

        // Add icon

        var lookupOptions = settings.lookupOptions;
        var inputSource = []
        $.each(lookupOptions, function (optionIndex, option) {
            var val = option[displayField];
            for (var i = 0; i < data.length; i++) {
                if (data[i][displayField] == val) { return; }
            }
            inputSource.push(val);
        })

        if (inputSource.length > 0 || isDate) {
            var addLink = $('<a href="#" class="add" title="Click to add"></a>').appendTo(newDiv);


            addLink.click(function () {
                var input = $('<input type="text"/>')
                var linkPosition = addLink.offset()
                var inputDiv = $('<div class="add-multiple-input"/>').append(input).appendTo($("body")).css({ left: linkPosition.left + 20 + "px", top: linkPosition.top - 9 + "px" }).topZIndex();

                if (isDate) {
                    var visible = false;

                    input.dateWidget({
                        beforeShow: function () {
                            visible = true;
                        },
                        onClose: function (dateText) {
                            visible = false;

                            if (dateText != "") {
                                input.val(dateText);
                                input.blur();
                            }

                            input.datepicker("hide");
                        }
                    });

                    addLink.blur(function () {
                        setTimeout(function () {
                            if (!inputHasFocus) {
                                visible = false;

                                input.blur()
                            }
                        }, 500)
                    })
                    input.focus(function () {
                        inputHasFocus = true;
                    })
                    input.change(function () {
                        visible = false;

                        input.blur()
                    });
                    input.blur(function () {
                        if (!visible) {
                            addLink.unbind("keydown", tabHandler);
                            input.unbind("blur");
                            
                            var val = input.getValue();

                            if (val != null && val != "") {
                                var value = {};

                                value[displayField] = val;

                                data.push(value);
                                resetDisplay();
                            }

                            inputDiv.remove();
                        }
                    })
                }
                else {
                    input.superInput({ source: inputSource, minLength: 0, mustMatch: true, placeholder: "Add New Item" });

                    addLink.blur(function () {
                        setTimeout(function () {
                            if (!inputHasFocus) { input.blur() }
                        }, 500)
                    })
                    input.focus(function () {
                        inputHasFocus = true;
                    })
                    input.change(function () { input.blur() });
                    input.blur(function () {
                        addLink.unbind("keydown", tabHandler);
                        input.unbind("blur");
                        var val = input.getValue();
                        //;
                        for (var i = 0; i < lookupOptions.length; i++) {
                            if (lookupOptions[i][displayField] == val) {
                                data.push(lookupOptions[i])
                                resetDisplay();
                                break;
                            }
                        }

                        inputDiv.remove();
                    })
                }

                var inputHasFocus = false;
                var tabHandler = function (e) {
                    var keyCode = e.keyCode || e.which;

                    if (keyCode == 9) {
                        e.preventDefault();
                        input.focus();
                    }
                }

                addLink.keydown(tabHandler);

                return false;
            });
        }
    };

    this.setValue = function (value) {

        data = value
        resetDisplay()
    };

    this.getValue = function () {
        return data;
    };

    return $(newDiv);

}


$.fn.loading = function(options) {
    var settings = $.extend({
    //defaults here
    },options)
    
    return $(this).each(function() {
    
        $(this).addClass("loading");
    
    });        

};

$.fn.removeLoading = function(options) {
    var settings = $.extend({
        //defaults here
    }, options)

    return $(this).each(function() {

        $(this).removeClass("loading");

    });

};


$.fn.textareaAutoSize = function(options) {

    return $(this).each(function() {
    
        var settings = $.extend({
            //defaults here
        }, options);
        
        var textarea = this

        $(this).css("overflow", "hidden")
        
        //var lineHeight =  1//parseInt($(this).css("line-height"));
        
        var shrinkTimeout;
        var lineHeight = parseInt($(this).css("line-height"));
        var shrink = function() {
            $("body").height($("body").height())
            $(textarea).height(10);
            
            
            fit(true);
            $("body").css("height","auto");
        }
        
        var fit = function(dontShrink) {

            var adjustedHeight = textarea.clientHeight;

            
            if (!settings.maxHeight || settings.maxHeight > adjustedHeight) {
                adjustedHeight = Math.max(textarea.scrollHeight, adjustedHeight);
                if (settings.maxHeight)
                    adjustedHeight = Math.min(settings.maxHeight, adjustedHeight);
                if (adjustedHeight > textarea.clientHeight) {
                    textarea.style.height = adjustedHeight + "px";
                }
            }
            
            if(dontShrink!=true) {
                clearTimeout(shrinkTimeout)
                shrinkTimeout = setTimeout(shrink,500)
            }
            
        }

        
        
        
        $(this).keyup(fit);
        shrink();
        fit();
        
    
    })

}


$.fn.starWidget = function (options) {


    $(this).each(function () {

        var settings = $.extend({
        //defaults here
    }, options);


    var isInput = $(this).is("input");

    if (settings.disabled == null) {
        settings.disabled = !isInput
    };

    var value = isInput ? $(this).val() : $(this).text();

    if (isNaN(value)) value = 0;

    value = Math.round(value);

        var container = isInput ? $('<div/>').insertAfter($(this).css("display","none")) : $('<div/>').appendTo($(this).empty());

    container.addClass("star-container");

    var uniqueName = "generatedStar_" + $.uniqueIndex();

    for (var i = 0; i < 11; i++) {
        var newInput = $('<input type="radio"/>').attr({
            name: uniqueName,
            value: i,
            id: uniqueName + "_" + i
        });

        container.append(newInput);
    }
    container.stars(settings);

    this.setValue = function (val) {
        container.stars("select", val);
    };
    this.getValue = function () {
        return container.data("stars").options.value;
    };

    this.setValue(value);

    //console.log(this.getValue())
    //conole.log("Hello"+this.getValue())

});

//return $(this)

};
