	(function( ) {
		jQuery.widget( "ui.combobox", {
                        options: {
                          formelementid: '',
                          wildcards: '',
                          size: 5,
                          minlength: 2,
                          multiple: 0,
                          textarea: 1,
                          defvalue: '?',
                          listall: 1,
                          showitems: 8,
                          jsonprop: '',
                          jsonparam: '',
                          jsonupdate: '',
                          jsonpath: ''
                        },
			_create: function() {
                                odata = {'values': []};
                                var done_selected = new Array();
                                var options = this.options;
                                if (options.jsonupdate != '') {
                                   var params = options.jsonupdate.split(",",2);
                                   targetid = params[0];
                                }
                                var formelementid = options.formelementid;
				var self = this,
					select = this.element.hide(),
					selected = select.children( ":selected" ),
					value = selected.val() ? selected.text() : options.defvalue;
                                var busy = jQuery ( "<img id='busyimg"+options.formelementid+"' src='/w/images/busy.gif' style='display:none'>" )
                                        .insertBefore( select )
                                if ((options.multiple == 1) && (options.textarea == 1))
                                   in_type = '<textarea class=grow_autocomplete id='+options.formelementid+'_ta rows=1 cols='+options.size+'></textarea>';
                                else 
                                   in_type = '<input size='+options.size+'>';
				var input = jQuery( in_type )
					.insertAfter( select )
					.val( value )
					.autocomplete({
						delay: 750,
                                                autoFill: true,
                                                cacheLength: 100,
						minLength: options.minlength,
						source: function( request, response ) {
                                                        request.term = extractLast( request.term );
							var matcher = new RegExp( jQuery.ui.autocomplete.escapeRegex(request.term), "i" );
                                                        if (options.jsonprop == '') {
							  response( select.children( "option" ).map(function() {
								var text = jQuery( this ).text();
                                                                var disab = jQuery( this ).attr('disabled');
								if ( !disab && this.value && ( !request.term || matcher.test(text) ) )
									return {
										label: text.replace(
											new RegExp(
												"(?![^&;]+;)(?!<[^<>]*)(" +
												jQuery.ui.autocomplete.escapeRegex(request.term) +
												")(?![^<>]*>)(?![^&;]+;)", "gi"
											), "<strong>$1</strong>" ),
										value: text,
										option: this
									};
							  }) );
                                                        } else {
                                                          if ((request.term.indexOf('*')==-1) && (request.term.indexOf('?')==-1)) {
                                                           if (options.jsonprop.indexOf("!!")>-1) { // nary condition is not value but id of form element which contains that value!
                                                              var propcond = options.jsonprop.split("!!");
                                                              var propcondp = propcond[1].split(":");
                                                              var parval = jQuery('#'+propcondp[1]).val();
                                                              if (parval != undefined && parval != '?' && parval != '*' && parval != 'any')
                                                                 termstring = propcond[0]+'!!'+propcondp[0]+":'"+parval+"';filter:"+request.term;
                                                              else
                                                                 termstring = propcond[0]+";filter:"+request.term;
                                                           } else
                                                             termstring = options.jsonprop+';filter:'+request.term;

                                                           var addpars = options.jsonparam.split(";");
                                                           for (i=0; i < addpars.length; i++) {
                                                              var param = addpars[i].split(":");
                                                              var parval = jQuery('#'+param[1]).val();
                                                              if (parval != undefined && parval != '?' && parval != '*' && parval != 'any')
                                                                 termstring += ';'+param[0]+':'+parval;
                                                           }
                                                            
                                                           document.getElementById('busyimg'+options.formelementid).style.display = 'inline'; 
                                                           jQuery.ajax({
                                                             url: options.jsonpath+'/includes/SQFT_Json.php',
                                                             dataType: "json",
                                                             data: { term: termstring },
                                                             error: function (XMLHttpRequest, textStatus, errorThrown) { alert("ERR:"+textStatus+' ('+termstring+')'); },
                                                             success: function (data) {
                                                                        if (data.values.length > options.showitems) {
                                                                           odata = new Array();
                                                                           odata.values = data.values; // save just in case it will be needed for a cache
                                                                           data.values = data.values.slice(0,options.showitems);
                                                                           more = new Array({'label':'...','value':''});
                                                                           data.values = data.values.concat(more);
                                                                        }

                                                                        if (data != null) {
                                                                          response( jQuery.map(data.values, function (item) {
                                                                              return {
                                                                                     label: item.label.replace(
                                                                                        new RegExp(
                                                                                                "(?![^&;]+;)(?!<[^<>]*)(" +
                                                                                                jQuery.ui.autocomplete.escapeRegex(request.term) +
                                                                                                ")(?![^<>]*>)(?![^&;]+;)", "gi"
                                                                                            ), "<strong>$1</strong>" ),
                                                                                     value: item.value
                                                                              }
                                                                          }));
                                                                        }
                                                                       }
                                                           });
                                                          } else {
                                                            document.getElementById('busyimg'+options.formelementid).style.display = 'none';
                                                            if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
                                                               input.autocomplete( "close" );
                                                               return false;
                                                            }
                                                          }
                                                        }
						},
                                                focus: function() {
                                                       if ( options.multiple == 10)
				                          return false;
			                        },
						select: function( event, ui ) {
                                                      if (options.jsonprop == '') {
                                                        if ( options.multiple == 1 ) {
 	                                                   var terms = split( this.value );
				                           terms.pop();
				                           terms.push( ui.item.value );
				                           terms.push( "" );
				                           this.value = terms.join( '°' );
                                                           ui.item.option.selected = true;
                                                           self._trigger( "selected", event, {
                                                                item: ui.item.option
                                                           });
                                                           jQuery('#'+options.formelementid+'_ta').trigger('elasticupdate');
				                           return false;
                                                        } else {
                                                          done_selected[formelementid] = ui.item.option;
							  ui.item.option.selected = true;
							  self._trigger( "selected", event, {
								item: ui.item.option
							  });
                                                        }
                                                      } else {
                                                         v = document.getElementById(options.formelementid);
                                                         for (i=v.options.length-1;i>=0;i--)
                                                             {
                                                             v.remove(i);
                                                             }  
                                                         var optn = document.createElement("OPTION");
                                                         optn.text = ui.item.label;
                                                         optn.value = ui.item.value;
                                                         v.options.add(optn);
                                                         v.options[0].selected = true;
                                                         done_selected[formelementid] = ui.item.value;
                                                         item: ui.item.value;
                                                      }
                                                      if (options.jsonupdate != '') {
                                                         var params = options.jsonupdate.split(",",2);
                                                         targetid = params[0];
                                                         if (params[1].indexOf("!!")>-1)
                                                            termstring = params[1]+":'"+ui.item.value+"'";
                                                         else
                                                            termstring = params[1];
                                                         
                                                         v = document.getElementById(targetid);

                                                         document.getElementById('busyimg'+options.formelementid).style.display = 'inline';
                                                         jQuery.ajax({
                                                             url: "http://mbw.molgen.mpg.de/w/SQFT_json.php",
                                                             dataType: "json",
                                                             data: { term: termstring },
                                                             error: function (XMLHttpRequest, textStatus, errorThrown) { alert("ERR:"+textStatus+' ('+termstring+')'); },
                                                             success: function (data) {
                                                                        if (data != null) {
                                                                          jQuery.map(data.values, function (item) {
                                                                               for (i=v.options.length-1;i>=1;i--) // keep first ? or *
                                                                                   {
                                                                                   if (item.value == v.options[i].value) {
                                                                                       v.options[i].disabled = false; 
                                                                                   } else {
                                                                                       v.options[i].disabled = true;
                                                                                       }
                                                                                   }
 
                                                                          });
                                                                        }
                                                                        document.getElementById('busyimg'+options.formelementid).style.display = 'none';
                                                                       }
                                                           });
                                                      }
						},
						change: function( event, ui ) {
                                                      jQuery(this).val(jQuery(this).val());
                                                      if ((options.jsonupdate != '') && (typeof done_selected[formelementid] !== undefined || done_selected[formelementid]) ) {
                                                         if (done_selected[formelementid] != jQuery(this).val()) { // enable all options previously disabled after selection
                                                            done_selected[formelementid] = false;
                                                            v = document.getElementById(targetid);
                                                            for (i=v.options.length-1;i>=0;i--) 
                                                                {
                                                                v.options[i].disabled = false;
                                                                }
                                                         }
                                                      }
                                                       
                                                      if (options.jsonprop == '') {
							if ( !ui.item ) {
                                                                var matchval = jQuery(this).val().replace('°','|');
                                                                var matchvala = jQuery(this).val().split('°');
                                                                var matchvals = '';
                                                                jQuery.each(matchvala, function(index, value) {
                                                                   if (value != '') {
                                                                      if (matchvals == '')
                                                                         matchvals += jQuery.ui.autocomplete.escapeRegex(value);
                                                                      else
                                                                         matchvals += '|'+jQuery.ui.autocomplete.escapeRegex(value);
                                                                   }
                                                                });
								var matcher = new RegExp( "^" + matchvals + "$", "i" ),
								valid = false;
								select.children( "option" ).each(function() {
                                                                        this.selected = false;
									if ( this.value.match( matcher ) ) {
										this.selected = valid = true;
									} else {
                                                                        }
								});

                                                                if ( options.wildcards != '' ) {
                                                                  var matchw = new RegExp( options.wildcards , "i");
                                                                  if ( this.value.match ( matchw ) ) {
                                                                    this.selected = valid = true;
                                                                    return false;
                                                                  }
                                                                }

								if ( !valid ) {
									jQuery( this ).val( orgval );
									select.val( "" );
									return false;
								}
							}
                                                     } else {
                                                         var aval = jQuery(this).val();
                                                         if (aval == '') {
                                                            aval = '?';
                                                            jQuery(this).val(aval);
                                                         }
                                                         v = document.getElementById(options.formelementid);
                                                         for (i=v.options.length-1;i>=0;i--)
                                                             {
                                                             v.remove(i);
                                                             }
                                                         var optn = document.createElement("OPTION");
                                                         optn.text = aval;
                                                         optn.value = aval;
                                                         v.options.add(optn);
                                                         v.options[0].selected = true;
                                                         done_selected[formelementid] = false;
                                                         item: aval;
                                                     }
						}
					})
					.addClass( "ui-widget ui-widget-content ui-corner-left" );

                                var orgval = input.val();

				input.data( "autocomplete" )._renderItem = function( ul, item ) {
                                        document.getElementById('busyimg'+options.formelementid).style.display = 'none'; 
					return jQuery( "<li></li>" )
						.data( "item.autocomplete", item )
						.append( "<a>" + item.label + "</a>" )
						.appendTo( ul );
				};

                                if (options.listall == 1) {
				 jQuery( "<button>&nbsp;</button>" )
					.attr( "tabIndex", -1 )
					.attr( "title", "Show All Items" )
					.insertAfter( input )
					.button({
						icons: {
							primary: "ui-icon-triangle-1-s"
						},
						text: false
					})
					.removeClass( "ui-corner-all" )
					.addClass( "ui-corner-right ui-button-icon" )
					.click(function() {
						if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
							input.autocomplete( "close" );
							return false;
						}

                                                var oml = input.autocomplete( "option", "minLength" );
                                                input.autocomplete( "option", "minLength", 0 );
						input.autocomplete( "search", "" );
						input.focus();
                                                input.autocomplete( "option", "minLength", oml );
                                                return false;
					});
                                  }
			 }
		});
	})( jQuery );

	function split( val ) {
		return val.split( /°\s*/ );
	}
	function extractLast( term ) {
		return split( term ).pop();
	}

	jQuery(function() {
                if (jQuery) {
		   jQuery( "#combobox" ).combobox();
		   jQuery( "#toggle" ).click(function() {
			jQuery( "#combobox" ).toggle();
		   });
                }
	});

