 
			
				10.07.2019, 06:31
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
			
			 
				Фабрика виджетов и autocomplite
			 
			
		
		
		
		Здравствуйте. 
Прикрутил себе autocomplite на основе комбобокса.
 https://jqueryui.com/autocomplete/#combobox
там идёт переопределение комбобокса и вот тут:
 
_removeIfInvalid: function( event, ui ) {
 
        // Selected an item, nothing to do
        if ( ui.item ) {
          return;
        }
 
        // Search for a match (case-insensitive)
        var value = this.input.val(),
          valueLowerCase = value.toLowerCase(),
          valid = false;
        this.element.children( "option" ).each(function() {
          if ( $( this ).text().toLowerCase() === valueLowerCase ) {
            this.selected = valid = true;
            return false;
          }
        });
 
        // Found a match, nothing to do
        if ( valid ) {
          return;
        }
 
        // Remove invalid value
        this.input
          .val( "" )
          .attr( "title", value + " didn't match any item" )
          .tooltip( "open" );
        this.element.val( "" );
        this._delay(function() {
          this.input.tooltip( "close" ).attr( "title", "" );
        }, 2500 );
        this.input.autocomplete( "instance" ).term = "";
      },
в случае неверного ввода (отсутствует в списке), поле ввода очищается и выводится сообщение. 
Хотел сделать вместо этого добавление нового элемента при помощи ajax.У меня это даже получилось, до того момента, пока на форме не появилось два комбобокса. Если переопределить в $.widjet(), то все комбобоксы будут вести себя одинаково. В случае с очисткой и выводом сообщения это хорошо. Но мне нужно выполнять разные ajax-запросы с различными параметрами для каждого комбобокса. 
Соответственно, мне необходимо переопределять эту функцию для каждого комбобокса, но как это сделать, ума не приложу. Натолкните на правильную мысль, пожалуйста.  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 08:08
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Misha_White, 
 в селекте в атрибуте data-url укажите ссылку.
 
<select class="combobox" data-url="http" >
 
this.url = this.element.data("url");
 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 08:56
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Да, с параметрами я уже сделал. Просто думал, что это похоже на костыли. 
Теперь вопрос о том же, но в другом.  
На форме есть combobox, в котором, при отсутствии значения выполняется функция добавления значения. И есть другой комбобокс, в котором необходимо использовать механизм по-умолчанию. т.е. как в примере. 
Можно, конечно, опять параметр передавать, типа флаг и исходя из этого параметра выполнять определённые действия... 
Но я думал, что можно как-то при создании экземпляра ($('#selector').combobox()) переопределять функцию, которая отрабатывала бы ввод...
 
код из примера:
 
this._on( this.input, {
          autocompleteselect: function( event, ui ) {
            ui.item.option.selected = true;
            this._trigger( "select", event, {
              item: ui.item.option
            });
          },
 
          autocompletechange: "_removeIfInvalid"
        });
autocompletechange: как-то подменять, может...  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 09:12
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Пока сделал так: 
$.widget( "custom.combobox", {
    options:{
     func:"_removeIfInvalid", //действие по умолчанию
     url:"/failajaxlink",
     ....//ещё параметры для формирования AJAX запроса и диалоговых окон.
    },
.....
  this._on( this.input, {
          autocompleteselect: function( event, ui ) {
            ui.item.option.selected = true;
            this._trigger( "select", event, {
              item: ui.item.option
            });
          },
 
          autocompletechange: this.options.func
        });
 
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось Misha_White, 10.07.2019 в 09:15.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 09:34
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		  
Не догоняю...   
т.е. я в options myFunc пишу код функции по умолчанию? и в случае необходимости предаю другую функцию при создании?
 
$.widget( "custom.combobox", {
    options:{
     myFunc:function( event, ui ) {
			// Selected an item, nothing to do
			if ( ui.item ) {
			     return;
				}
							 
		       // Search for a match (case-insensitive)
		        var value = this.input.val(),
	                valueLowerCase = value.toLowerCase(),
			valid = false;
			this.element.children( "option" ).each(function() {
					          if ( $( this ).text().toLowerCase() === valueLowerCase ) {
			     this.selected = valid = true;
			      return false;
			         }
						        });
							 
			// Found a match, nothing to do
			if ( valid ) {
			          return;
			        }
							 
			// Remove invalid value
			this.input
			         .val("")
			         .attr( "title", "\'"+value + "\' отсутсвует в справочнике. Для добавления обратитесь к Администратору" )
			         .tooltip( "open" );
			        this.element.val( "" );
			        this._delay(function() {
			        this.input.tooltip( "close" ).attr( "title", "" );
			        }, 2500 );
			        this.input.autocomplete( "instance" ).term = "";
							      },
    },
.....
  this._on( this.input, {
          autocompleteselect: function( event, ui ) {
            ui.item.option.selected = true;
            this._trigger( "select", event, {
              item: ui.item.option
            });
          },
  
          autocompletechange: "_removeIfInvalid"
        });
....
_removeIfInvalid: function( event, ui ) {
    this.options.myFunc.call(this, event, ui);
}
и затем:
 
$('#selector').combobox({myFunc:function( event, ui ) {
							    	  
							          // Selected an item, nothing to do
							          if ( ui.item ) {
							            return;
							          }
							   
							          // Search for a match (case-insensitive)
							          var value = this.input.val(),
							            valueLowerCase = value.toLowerCase(),
							            valid = false;
							          this.element.children( "option" ).each(function() {
							            if ( $( this ).text().toLowerCase() === valueLowerCase ) {
							              this.selected = valid = true;
							              return false;
							            }
							          });
							   
							          // Found a match, nothing to do
							          if ( valid ) {
							            return;
							          }
							   
							          // add invalid value
....
							          })
 
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось Misha_White, 10.07.2019 в 09:43.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 09:48
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		ага. Спасибо. 
Вот как-то так я изначально и хотел сделать, только не знал как    
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 10:53
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 Misha_White, 
если в функциях различаются только ajax-запросы с различными параметрами, то зачем две функции? 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 11:55
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 Есть комбобоксы без ajax'а. Т.е. поведение как в демке меня устраивает. 
А вот с ajax-ами я изначально сделал через параметры, теперь передал на передачу функции в виде параметра, как подсказал Rise, но опять же не уверен, что это правильно. 
 
Много дублирующегося кода получается. 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 12:15
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Misha_White, 
вариант с data-url 
два селекта, один с data-url, ввести несуществующее значение в оба, чтоб увидеть разницу 
строки 54 и 266
  
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Autocomplete - Combobox</title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <style>
        .custom-combobox {
            position: relative;
            display: inline-block;
        }
        .custom-combobox-toggle {
            position: absolute;
            top: 0;
            bottom: 0;
            margin-left: -1px;
            padding: 0;
        }
        .custom-combobox-input {
            margin: 0;
            padding: 5px 10px;
        }
  </style>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
        $(function() {
            $.widget("custom.combobox", {
                _create: function() {
                    this.wrapper = $("<span>")
                        .addClass("custom-combobox")
                        .insertAfter(this.element);
                    this.url = this.element.data("url");
                    this.element.hide();
                    this._createAutocomplete();
                    this._createShowAllButton();
                },
                _createAutocomplete: function() {
                    var selected = this.element.children(":selected"),
                        value = selected.val() ? selected.text() : "";
                    this.input = $("<input>")
                        .appendTo(this.wrapper)
                        .val(value)
                        .attr("title", "")
                        .addClass("custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left")
                        .autocomplete({
                            delay: 0,
                            minLength: 0,
                            source: $.proxy(this, "_source")
                        })
                        .tooltip({
                            classes: {
                                "ui-tooltip": "ui-state-highlight"
                            }
                        });
                    this._on(this.input, {
                        autocompleteselect: function(event, ui) {
                            ui.item.option.selected = true;
                            this._trigger("select", event, {
                                item: ui.item.option
                            });
                        },
                        autocompletechange: "_removeIfInvalid"
                    });
                },
                _createShowAllButton: function() {
                    var input = this.input,
                        wasOpen = false;
                    $("<a>")
                        .attr("tabIndex", -1)
                        .attr("title", "Show All Items")
                        .tooltip()
                        .appendTo(this.wrapper)
                        .button({
                            icons: {
                                primary: "ui-icon-triangle-1-s"
                            },
                            text: false
                        })
                        .removeClass("ui-corner-all")
                        .addClass("custom-combobox-toggle ui-corner-right")
                        .on("mousedown", function() {
                            wasOpen = input.autocomplete("widget").is(":visible");
                        })
                        .on("click", function() {
                            input.trigger("focus");
                            // Close if already visible
                            if (wasOpen) {
                                return;
                            }
                            // Pass empty string as value to search for, displaying all results
                            input.autocomplete("search", "");
                        });
                },
                _source: function(request, response) {
                    var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
                    response(this.element.children("option").map(function() {
                        var text = $(this).text();
                        if (this.value && (!request.term || matcher.test(text)))
                            return {
                                label: text,
                                value: text,
                                option: this
                            };
                    }));
                },
                _removeIfInvalid: function(event, ui) {
                    // Selected an item, nothing to do
                    if (ui.item) {
                        return;
                    }
                    console.log(this.url)
                    // Search for a match (case-insensitive)
                    var value = this.input.val(),
                        valueLowerCase = value.toLowerCase(),
                        valid = false;
                    this.element.children("option").each(function() {
                        if ($(this).text().toLowerCase() === valueLowerCase) {
                            this.selected = valid = true;
                            return false;
                        }
                    });
                    // Found a match, nothing to do
                    if (valid) {
                        return;
                    }
                    if (this.url) {
                        alert("$.ajax(this.url)");
                    }
                    // Remove invalid value
                    this.input
                        .val("")
                        .attr("title", value + " didn't match any item")
                        .tooltip("open");
                    this.element.val("");
                    this._delay(function() {
                        this.input.tooltip("close").attr("title", "");
                    }, 2500);
                    this.input.autocomplete("instance").term = "";
                },
                _destroy: function() {
                    this.wrapper.remove();
                    this.element.show();
                }
            });
            $(".combobox").combobox();
        });
  </script>
</head>
<body>
  <div class="ui-widget">
    <label>Your preferred programming language:</label> <select class="combobox test" data-url=
    "http">
      <option value="">
        Select one...
      </option>
      <option value="ActionScript">
        ActionScript
      </option>
      <option value="AppleScript">
        AppleScript
      </option>
      <option value="Asp">
        Asp
      </option>
      <option value="BASIC">
        BASIC
      </option>
      <option value="C">
        C
      </option>
      <option value="C++">
        C++
      </option>
      <option value="Clojure">
        Clojure
      </option>
      <option value="COBOL">
        COBOL
      </option>
      <option value="ColdFusion">
        ColdFusion
      </option>
      <option value="Erlang">
        Erlang
      </option>
      <option value="Fortran">
        Fortran
      </option>
      <option value="Groovy">
        Groovy
      </option>
      <option value="Haskell">
        Haskell
      </option>
      <option value="Java">
        Java
      </option>
      <option value="JavaScript">
        JavaScript
      </option>
      <option value="Lisp">
        Lisp
      </option>
      <option value="Perl">
        Perl
      </option>
      <option value="PHP">
        PHP
      </option>
      <option value="Python">
        Python
      </option>
      <option value="Ruby">
        Ruby
      </option>
      <option value="Scala">
        Scala
      </option>
      <option value="Scheme">
        Scheme
      </option>
    </select>
  </div>
  <div class="ui-widget">
    <label>Your preferred programming language:</label> <select class="combobox">
      <option value="">
        Select one...
      </option>
      <option value="ActionScript">
        ActionScript
      </option>
      <option value="AppleScript">
        AppleScript
      </option>
      <option value="Asp">
        Asp
      </option>
      <option value="BASIC">
        BASIC
      </option>
      <option value="C">
        C
      </option>
      <option value="C++">
        C++
      </option>
      <option value="Clojure">
        Clojure
      </option>
      <option value="COBOL">
        COBOL
      </option>
      <option value="ColdFusion">
        ColdFusion
      </option>
      <option value="Erlang">
        Erlang
      </option>
      <option value="Fortran">
        Fortran
      </option>
      <option value="Groovy">
        Groovy
      </option>
      <option value="Haskell">
        Haskell
      </option>
      <option value="Java">
        Java
      </option>
      <option value="JavaScript">
        JavaScript
      </option>
      <option value="Lisp">
        Lisp
      </option>
      <option value="Perl">
        Perl
      </option>
      <option value="PHP">
        PHP
      </option>
      <option value="Python">
        Python
      </option>
      <option value="Ruby">
        Ruby
      </option>
      <option value="Scala">
        Scala
      </option>
      <option value="Scheme">
        Scheme
      </option>
    </select>
  </div>
</body>
</html>
 
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось рони, 10.07.2019 в 12:20.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				10.07.2019, 18:53
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 17.02.2010 
					
					
					
						Сообщений: 16
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 Спасибо. Принцип понятен. Только мне ещё несколько параметров нужно передавать. Я так понимаю, это делается таким же Макаром? data-param1= и т.д. А внутри обращаться: this.param1 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
 
 |  
  |