jQuery UI 自动完成鼠标单击选择不传递值

jQuery UI Autocomplete mouse click selection not passing value

我在 PHP 页面中使用 jQuery UI Autocomplete 进行定位服务。这一个特别是使用远程 JSONP 数据源类型。我遇到的问题很奇怪,而且只以一种方式发生。

这是正在发生的事情:

  1. 用户输入了整个选择。该值已按预期分配和传递。
  2. 用户键入部分选择并使用键盘下拉到所需的选择并按下回车键。该值已按预期分配和传递。
  3. 用户键入部分选择并单击所需的选择。只有在他们单击之前键入的段才会被传递。

换句话说,如果用户键入 Location,则传递 Location。如果用户输入 Loca 并使用键盘下拉到 Location,则传递 Location。但是,如果用户键入 Loca 并使用鼠标单击 Location,则会传递 Loca

这是一个插件内部,所以我会尽我所能解释并显示相关代码。当我说它正在传递时,它是在 PHP 变量 $thisVAR.

中传递的

我只是想不通为什么该值作为类型段而不是分配的完整值传递。

下面是PHP创建字段时创建的js:

$js .= "$( function(){";
$js .= "$('.error').hide();";
$js .= "var rollbackValue = '';";
$js .= "$('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').keyup(function(){";
$js .= "rollbackValue = $(this).val().slice(0,-1);";
$js .= "});";
$js .= "$('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').autocomplete({";
$js .= "source: function( request, response ){";
$js .= "$.ajax({";
$js .= "url: '" . $thisURL . "',";
$js .= "dataType: 'jsonp',";
$js .= "data: {";
$js .= "term: request.term,";
$js .= "dependents: '". $thisVAR . "',";
$js .= "field: '". $config->settings['field_name'] . "_" . $suggestiveFieldArray . "',";
$js .= "fieldSettings: " . json_encode($fieldSettings);
$js .= "},";
$js .= "success: function( data ) {";
if( $fieldSettings['allow_other_countries'] == 'n' ){
    $js .= "if (!data || !Object.keys(data).length){";
    $js .= "$('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').prev('.error')";
    if( !empty($fieldSettings['custom_error']) ){
        $js .= ".html('" . $customError . "')";
    }else{
        $js .= ".html('Sorry, there were no available records found starting with `<span style=\"text-transform: capitalize;\">' + request.term + '</span>`.')";
    }
    $js .= ".fadeIn('slow', function(){ $(this).delay(2500).fadeOut('slow'); });";
    $js .= "$('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').val(rollbackValue);";
    $js .= "} else {";
    $js .= "    response( data );";
    $js .= "}";
}else{
    $js .= "response( data );";
}
$js .= "},";
$js .= "minLength: 0";
$js .= "});";
$js .= "}";
$js .= "});";
$js .= "});";

相当于js中的以下内容(更易读):

$( function(){
    $('.error').hide();
    var rollbackValue = '';
    $('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').keyup(function(){
        rollbackValue = $(this).val().slice(0,-1);
    });
    $('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').autocomplete({
        source: function( request, response ){
            $.ajax({
                url: '" . $thisURL . "',
                dataType: 'jsonp',
                data: {
                    term: request.term,
                    dependents: '". $thisVAR . "',
                    field: '". $config->settings['field_name'] . "_" . $suggestiveFieldArray . "',
                    fieldSettings: " . json_encode($fieldSettings);
                },
                success: function( data ) {
                    if ( !data || !Object.keys(data).length ){
                        $('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').prev('.error')
                        .html('Sorry, there were no available records found starting with `<span style=\"text-transform: capitalize;\">' + request.term + '</span>`.')
                        .fadeIn('slow', function(){ $(this).delay(2500).fadeOut('slow'); });
                        $('#" . $config->settings['field_name'] . "_" . $suggestiveFieldArray . "').val(rollbackValue);
                    } else {
                        response( data );
                    }
                },
                minLength: 0
            });
        }
    });
});

变量$thisVAR确定并设置在上面:

/**
 * Determine our variables for this field
 */
$thisVAR = ''; $abbr = '';
if( strpos($suggestiveFieldArray, 'city') !== false ) {
    /**
     * We need the state and country data
     */
    $thisVAR = "$myState|$myCountry";
    $abbr = ( $fieldSettings['abbreviations'] == 'y' ? "true" : "false" );
}elseif( strpos($suggestiveFieldArray, 'state') !== false ) {
    /**
     * We need the city and country data
     */
    $thisVAR = "$myCity|$myCountry";
    $abbr = ( $fieldSettings['abbreviations'] == 'y' ? "true" : "false" );
}elseif( strpos($suggestiveFieldArray, 'country') !== false ) {
    /**
     * We need the city and state data
     */
    $thisVAR = "$myCity|$myState";
    $abbr = ( $fieldSettings['abbreviations'] == 'y' ? "true" : "false" );
}

...$myCity$myState$myCountry 都是从字段值中提取的值。

/**
 * Associative Fields Values
 */
if($field['name'] == 'theField_city'){
    $myCity = $field['value'];
}elseif($field['name'] == 'theField_state'){
    $myState = $field['value'];
}elseif($field['name'] == 'theField_country'){
    $myCountry = $field['value'];
}

肯定有更好的方法,但我能够通过添加一个单独的 js 文件和一个小插件来实现我所需要的,该插件声明 "global" 变量在更改事件之后被修改新数据从 ajax 请求返回。我想我只是想对一个文件做太多事情。 :(

没有示例数据,我只能做一些猜测。为了让它更流畅,我会调整你的一些 id 属性以使用 - 而不是 _。次要偏好和需要考虑的事项。

我使用了以下数据进行测试,并对你的HTML做了一些假设。如果你正在 returning 一个对象,我怀疑你是,它必须至少包含一对 labelvalue

[{
  label: "San Jose, CA US",
  value: "San Jose",
  city: "San Jose",
  state: "California",
  stateAbbr: "CA",
  country: "United States"
}, {
  label: "Santa Clara, CA US",
  value: "Santa Clara",
  city: "Santa Clara",
  state: "California",
  stateAbbr: "CA",
  country: "United States"
}, {
  label: "Mountain View, CA US",
  value: "Mountain View",
  city: "Mountain View",
  state: "California",
  stateAbbr: "CA",
  country: "United States"
},
{
  label: "Springfield, OR US",
  value: "Springfield",
  city: "Springfield",
  state: "Oregon",
  stateAbbr: "OR",
  country: "United States"
},
{
  label: "Springfield, NY US",
  value: "Springfield",
  city: "Springfield",
  state: "New York",
  stateAbbr: "NY",
  country: "United States"
}];

我还建议使用 POST 而不是 GET,并使用 JSON 而不是 JSONP。如果您要发送单个术语或少量数据,您真的只想使用 GET。 POST 更适合大量数据,并且稍微安全一些。

JSONP 仅在您 PHP 服务器托管在另一个域中或托管在另一个 API 下而不是您的 Web 服务器时才有用。由于 PHP 正在生成 JavaScript 代码并且 AJAX 正在调用 PHP Self 我认为没有理由使用 JSONP.

在你的自动完成中,你似乎想要以下内容:

  • 如果没有结果 returned
  • ,则生成错误警报
  • 根据用户条目自动填充城市、州和国家/地区
  • 国家可能会也可能不会使用缩写

我假设如果他们开始输入城市名称并进行选择,它应该会填充相应的州和国家详细信息。

工作示例:https://jsfiddle.net/Twisty/5r1by1xp/

HTML

<div class="ui-widget">
  <ul>
    <li>
      <div class="error"></div>
      <label>City</label>
      <input type="text" id="fn-city" data-abbr="n" />
    </li>
    <li>
      <div class="error"></div>
      <label>State</label>
      <input type="text" id="fn-state" data-abbr="y" style="width: 2em;" />
    </li>
    <li>
      <div class="error"></div>
      <label>Country</label>
      <input type="text" id="fn-country" data-abbr="n" />
    </li>
  </ul>
</div>

CSS

.ui-widget ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui-widget ul li label {
  display: inline-block;
  width: 80px;
}

.ui-widget .error {
  font-size: 65%;
  color: red;
}

JavaScript

// Only used for example & jsFiddle
var myData = [{
  label: "San Jose, CA US",
  value: "San Jose",
  city: "San Jose",
  state: "California",
  stateAbbr: "CA",
  country: "United States"
}, {
  label: "Santa Clara, CA US",
  value: "Santa Clara",
  city: "Santa Clara",
  state: "California",
  stateAbbr: "CA",
  country: "United States"
}, {
  label: "Mountain View, CA US",
  value: "Mountain View",
  city: "Mountain View",
  state: "California",
  stateAbbr: "CA",
  country: "United States"
}, {
  label: "Springfield, OR US",
  value: "Springfield",
  city: "Springfield",
  state: "Oregon",
  stateAbbr: "OR",
  country: "United States"
}, {
  label: "Springfield, NY US",
  value: "Springfield",
  city: "Springfield",
  state: "New York",
  stateAbbr: "NY",
  country: "United States"
}];

$(function() {
  $('.error').hide();
  var rollbackValue = '';
  $("[id|='fn']").keyup(function() {
    rollbackValue = $(this).val().slice(0, -1);
  });
  $("[id|='fn']").focus(function() {
    $(this).addClass("activeField")
  }).blur(function() {
    $(this).removeClass("activeField");
  }).autocomplete({
    source: function(request, response) {
      var fnid = $(".activeField").attr("id");
      var dep = fnid.slice(fnid.indexOf("-") + 1);
      var term = request.term.toLowerCase();
      $.ajax({
        url: '/echo/json/',
        type: "POST",
        dataType: 'json',
        data: {
          json: JSON.stringify(myData),
          term: request.term,
          dependents: dep,
          field: fnid,
          fieldSettings: JSON.stringify({
            abbreviations: $("#" + fnid).data("abbr")
          })
        },
        success: function(data) {
          var results = [];
          $.each(data, function(k, v) {
            var depResult = v[dep].toLowerCase();
            if (depResult.indexOf(term) === 0) {
              results.push(v);
            }
          });
          if (results.length == 0) {
            console.log("No Results Found.");
            $("#" + fnid).parent().find(".error")
              .html('Sorry, there were no available records found starting with `<span style=\"text-transform: capitalize;\">' + term + '</span>`.')
              .fadeIn('slow', function() {
                $(this).delay(2500).fadeOut('slow');
              });
            $("#" + fnid).val(rollbackValue)
            ''
          }
          response(results);
        },
        minLength: 0
      });
    },
    select: function(e, ui) {
      $("#fn-city").val(ui.item.city);
      $("#fn-state").val(ui.item.stateAbbr);
      $("#fn-country").val(ui.item.country);
      return false;
    }
  });
});

我个人不会使用 PHP 来生成 JavaScript 本身。这是可以做到的,如果您使用模板并且大量数据不是静态的,您可能无法摆脱它太多。例如,您可以在一个 JS 文件中定义和存储各种函数;通过 <script> 添加它们,然后从 PHP:

传递东西给它们

JS

function makeAutoComplete(fID){
  var $field = $("#" + fID);
  $field.autocomplete();
}

PHP

$js = "<script src='myfunctions.js'></script>\r\n";
$js .= "<script>\r\n";
$js .= "makeAutoComplete('" . $config->settings['field_name'] . "-" . $suggestiveFieldArray . "')\r\n";
$js .= "</script>\r\n";

通过这种方式,您可以最大限度地减少交叉上下文的数量。它还使故障排除和测试变得容易得多。另外,我会将您的 PHP 脚本分开。可以制作小的 PHP 脚本,只获取发布给他们的数据,然后 return 数据。

希望对您有所帮助。