(function( $ ) { 
    var renderTemplate = function ( str, attrArr ) {
        if ( !attrArr ) return str;
        for ( var key in attrArr ) {
            str = str.replace("{" + key + "}", attrArr[key]);
        }
        return str;
    };
    

    // default templates
    var wrapTemplate = "<div class='{class}' style='{style}'>{content}</div>",
        optionsListTemplate = "<ul class='{class}' style='{style}'>{content}</ul>",
        optionTemplate = "<li class='{class}' style='{style}'>{content}</li>";

    // DOM manipulation
    $.fn.selectBox = function( opts ) {
        opts = opts || {};
        // defaults 
        opts = $.extend({
            boxTemplate             : wrapTemplate,
            boxClass                : "select-box-wrap",
            selectedTemplate        : wrapTemplate,
            selectedClass           : "select-box-selected",
            buttonTemplate 			: wrapTemplate,
            buttonClass    			: "select-box-button",
			buttonWidth				: 25,
            optionsListTemplate     : optionsListTemplate,
            optionListClass         : "select-box-option-list",
            optionTemplate          : optionTemplate,
            optionClass             : "select-box-option"
        }, opts );
        
		var onBlurList = function(e) {
			var trgt = e.target;
			var currentListElements = $( '.' + opts.optionListClass ).parent().find('*').andSelf();
			if(jQuery.inArray(trgt, currentListElements) < 0 ) {
				sSelectBox.find( '.' + opts.optionListClass ).hide();
			}
		}

		
        return this.each( function() {
            var selectBox = $(this),
                options = selectBox.find('option'),
                html = [],
				list = [],
                i = 0, 
				len = options.length,
                currentOption, 
				currentOptionClasses, 
                currentOptionContent,
				selectboxWidth,
				selectboxHeight,
				selectedWidth,
				selectedHeight;
				            
            // Hide original select box
            selectBox.css('display', 'none');
			selectboxWidth = selectBox.innerWidth(true);
			selectboxHeight = selectBox.innerHeight(true);
            selectedWidth = selectboxWidth - (parseInt(opts.buttonWidth) + 1);
			selectedHeight = selectBox.innerHeight(true) - 2; 

			// Selected 
            html.push(renderTemplate( opts.selectedTemplate, { 
                'class' : opts.selectedClass,
                content : options.filter(":selected").html(),
				'style' : 'width:' + selectedWidth + 'px; height:' + selectedHeight + 'px; line-height:' + selectedHeight + 'px'
            }));

			// Toggle Button
            html.push(renderTemplate( opts.buttonTemplate, { 
                'class' : opts.buttonClass,
				content : '',
				'style' : 'width:' + opts.buttonWidth + 'px; height:' + selectboxHeight + 'px;'
            }));
			
			
            // Options
            for ( ; i < len; i += 1 ) {
                currentOption = options[ i ];
                list.push( renderTemplate( opts.optionTemplate, {
                    "class" : opts.optionClass + " " + options[ i ].className,
                    content : options[ i ].innerHTML,
					'style' : 'width:100%; height:' + selectboxHeight + 'px;'
                } ) );
            }
            
            // Options List
            html.push(renderTemplate( opts.optionsListTemplate, { 
                'class' : opts.optionListClass,
                content : list.join(''),
				'style' : 'position:absolute; top:' + selectboxHeight + 'px; width:' + (selectboxWidth - 2) + 'px; display:none; '
            }));
			
			// SelectBox(Parent)
            html = renderTemplate( opts.boxTemplate, {
                'class' : opts.boxClass,
                content : html.join(''),
				'style' : 'width:' + selectboxWidth + 'px; height:' + selectboxHeight + 'px;'
            });
           
            // Insert pseudo-select box into DOM
            selectBox.after( html );
            sSelectBox = selectBox.next();
            
            // toggle drop-down
            sSelectBox
                .find( '.' + opts.buttonClass )
                .bind( 'click', function( e ) {
                    $(this).next().toggle();
                } );
				
			sSelectBox
				.find( '.' + opts.selectedClass )
				.bind( 'click', function( e ) {
                    $(this).next().next().toggle();
                } );
            
            // select option
            sSelectBox
                .find( '.' + opts.optionClass )
                .bind( 'click', function( e ) {
                    var thisOption = $(this);
                    thisOption.parent().parent()
                        .find( '.' + opts.selectedClass ) 
                        .html( thisOption.html() );
                    options.attr( 'selected', false );
                    options[ thisOption.index() ].selected = true;
					selectBox.change();
					thisOption.parent().toggle();
                } );
			
			$(document).bind('click', onBlurList);
			//sSelectBox.find( '.' + opts.optionListClass ).bind( 'blur', function (e) { $(this).hide(); });
        }); // this.each
    };// $.fn.selectBox
})(jQuery);

