﻿// jQuery EditableSpan Plugin
//
// Version 1.0
//
// Benoît BEGUIN
// the 24th of April 2010: first version
// Feb 2011: add 'onTabOrEnterKey' option
//
if (jQuery) (function () {
    $.extend($.fn, {
        editableSpan: function (o) {
            // Defaults
            if (o.className == undefined) o.className = ""; // adds this className to displayed value (not input)
            if (o.inputWidth == undefined) o.inputWidth = $(this).css("width"); // adds input width param - by default same as span (not input)
            if (o.inputClassName == undefined) o.inputClassName = ""; // adds this className to input field (not displayed value)
            if (o.noDataDisplay == undefined) o.noDataDisplay = "---"; // text displayed if no data has been set on input field
            if (o.fieldType == undefined) o.fieldType = "INPUT"; // field type. Can be one of these options: INPUT / DATE / AUTOCOMPLETE / DROPBOX
            if (o.fieldType == "AUTOCOMPLETE" && o.autocompleteList == undefined) o.fieldType = "INPUT"; // if field type is AUTOCOMPLETE, autocompleteList must be set - if not, set filed type to INPUT
            if (o.fieldType == "DROPBOX" && o.dropBoxDataList == undefined) o.fieldType = "INPUT"; // if field type is DROPBOX, dropBoxDataList must be set - if not, set filed type to INPUT
            if (o.externInputId == undefined) o.externInputId = ""; // allows update of extern inputs -> value will be set into this input too
            if (o.onChange != undefined && typeof o.onChange != "function") o.onChange = null; // callback: on data change, call onChange method with 2 params: [initial span elt], [new value]
            if (o.onTabOrEnterKey != undefined && typeof o.onTabOrEnterKey != "function") o.onTabOrEnterKey = null; // callback: on Tab / Enter or Return key pressed, call onTabOrEnterKey method with
            if ($(this).text() == "") { $(this).html(o.noDataDisplay); } // If no text set on span - set it to noDataDisplay parameter

            // Add specified className to element
            $(this).addClass(o.className).attr('editableSpan', 'true');
            // Bind mousedown event: convert span into input
            $(this).mousedown(function (e) {
                if (!o.dateField) {
                    $('#jeditablespanid').datepicker('hide');
                }
                $('#jeditablespanid').blur().unbind().remove();
                $('[editableSpan=true]').show();
                if (o.fieldType != "DROPBOX") { // Add input field
                    var inputElt = $(this).after($('<input type="text" id="jeditablespanid"/>')
							.val(($(this).text() != o.noDataDisplay) ? $(this).text() : "")).next();
                }
                else { // DropBox - not input but "select" field
                    var inputElt = $(this).after($('<select id="jeditablespanid"/>')).next();
                }
                inputElt.css("width", o.inputWidth).addClass(o.inputClassName);
                // If date field
                if (o.fieldType == "DATE") {
                    inputElt.datepicker({
                        onClose: function (dateText, inst) {
                            $(this).prev().html(($(this).val() != "") ? $(this).val() : o.noDataDisplay);
                            $(this).prev().show();
                            if (o.externInputId != "") {
                                $(":input:#" + o.externInputId).val($(this).prev().text());
                            }
                            if (o.onChange != undefined && typeof o.onChange == "function") {
                                o.onChange($(this).prev(), $(this).prev().text());
                            }
                            $(this).remove();
                        }
                    });
                }
                // If autocomplete field
                else if (o.fieldType == "AUTOCOMPLETE") {
                    if (inputElt.val() == "") {
                        inputElt.val("____");
                        setTimeout("$('#jeditablespanid').val('');", 20);
                    }
                    var autoCompleteList = (typeof(this.autocompleteList) != "undefined" ? this.autocompleteList : o.autocompleteList);
                    inputElt.autocomplete(autoCompleteList, { mustMatch: true, max: 10, minChars: 0, matchContains: true })
				            .result(function (ev, autoCompleteData) {
				                if (autoCompleteData != undefined) {
				                    $(this).prev().html(autoCompleteData[0]);
				                    $(this).prev().show();
				                    if (o.externInputId != "") {
				                        $(":input:#" + o.externInputId).val(autoCompleteData[0]);
				                    }
				                    if (o.onChange != undefined && typeof o.onChange == "function") {
				                        o.onChange($(this).prev(), autoCompleteData);
				                    }
				                    $(this).remove();
				                }
				            })
				            .blur(function () { // onblur: close input - no change
				                if ($(this).val() == "____") { return; }
				                $(this).prev().show();
				                $(this).hide();
				            });
                }
                // If dropbox field
                else if (o.fieldType == "DROPBOX") {
                    // add select elements (first: no data display, then data list parameter)
                    inputElt.append("<option value=''>" + o.noDataDisplay + "</option>");
                    var dropBoxDataList = (typeof (this.dropBoxDataList) != "undefined" ? this.dropBoxDataList : o.dropBoxDataList);
                    $.each(dropBoxDataList, function (i, optionData) {
                        inputElt.append("<option value='" + optionData[1] + "' " + (optionData[0] == inputElt.prev().text() ? "selected='selected'" : "") + ">" + optionData[0] + "</option>");
                    });
                    inputElt.click();
                    // bind change and blur events
                    inputElt.change(function () {
                        $(this).unbind('blur');
                        $(this).prev().html(($(this).val() != "") ? $("#" + $(this)[0].id + " :selected").text() : o.noDataDisplay);
                        $(this).prev().show();
                        if (o.externInputId != "") {
                            $(":input:#" + o.externInputId).val($(this).prev().text());
                        }
                        if (o.onChange != undefined && typeof o.onChange == "function") {
                            o.onChange($(this).prev(), eval("['" + $(this).prev().text() + "', '" + $(this).val() + "']"));
                        }
                        $(this).remove();
                    }).blur(function () { $(this).change(); });
                }
                // Normal field
                else {
                    inputElt.blur(function () {
                        $(this).unbind('blur');
                        $(this).prev().html(($(this).val() != "") ? $(this).val() : o.noDataDisplay);
                        $(this).prev().show();
                        if (o.externInputId != "") {
                            $(":input:#" + o.externInputId).val($(this).prev().text());
                        }
                        if (o.onChange != undefined && typeof o.onChange == "function") {
                            o.onChange($(this).prev(), $(this).prev().text());
                        }
                        $(this).remove();
                    });
                }
                checkKeys(inputElt, o.onTabOrEnterKey);
                $(this).hide();
                e.stopPropagation();
                setTimeout("$('#jeditablespanid').focus().select();", 20);
            });
            return ($(this));
        }
    });
})(jQuery);

function checkKeys(el, onTabOrEnterKey) {
	if (onTabOrEnterKey) {
	    $(el).keyz({"enter return tab": onTabOrEnterKey});
	}
    else {
    	$(el).keyz({"enter return tab": function(ctl,sft,alt,ev) {
            var editableSpans = $("[editableSpan=true]");
            currentSpanNumber = editableSpans.index($(this).prev()[0]);
            var newSpanElt = editableSpans[currentSpanNumber + 1];
            if (sft) { newSpanElt = editableSpans[currentSpanNumber - 1]; }
            // If element found - send click event
            if (newSpanElt != null) {
                setTimeout(function () { $(newSpanElt).mousedown(); }, 50);
                ev.preventDefault();
                return false;
            }
        }});
    }
	// No specific behavior for Esc key
    $(el).keyz({"esc": function(ctl,sft,alt,ev) {
                $(el).prev().show();
                $(el).hide();
            }});
}
