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

Posted

技术标签:

【中文标题】jQuery UI 自动完成鼠标点击选择不传递值【英文标题】:jQuery UI Autocomplete mouse click selection not passing value 【发布时间】:2018-06-24 09:06:27 【问题描述】:

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

这是正在发生的事情:

    用户键入整个选择。值按预期分配和传递。 用户键入部分选择并使用键盘下拉到所需的选择,然后按回车键。值按预期分配和传递。 用户键入部分选择并单击想要的选择。只有在他们点击时输入的句段才会被传递。

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

这是插件内部的,所以我会尽力解释并显示相关代码。当我说它被传递时,它是在 PHP 变量 $thisVAR 中传递的。

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

这是创建字段时创建 js 的 PHP:

$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'];

【问题讨论】:

那是一大堆代码让我们费力地通过...... ;) 即便如此,它似乎并没有揭示为什么会发生这种情况。几乎就像您在某处有第二次点击事件......覆盖了 .autocomplete 内置的内容。 是的...对不起。我只是认为最好把它全部扔在那里,而不是询问“x”的分配位置等问题;) @IncredibleHat 同意,但什么都没有。 我见过其他类似的问题,他们不得不使用select 事件来捕获鼠标点击事件。我也试过了,但结果没有变化。 它被其他东西所包含。使用 console.log(jQuery().jquery) 虽然返回 2.1.3。 【参考方案1】:

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

我使用以下数据进行测试并对您的 HTML 做了一些假设。如果您要返回一个对象,我怀疑您是,它必须至少包含 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 服务器托管在另一个域中或在您的 Web 服务器之外的另一个 API 下时才有用。由于 PHP 正在生成 javascript 代码,而 AJAX 正在调用 PHP Self,我认为没有理由使用 JSONP。

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

如果没有返回结果,则生成错误警报 根据用户输入自动填充城市、州和国家 国家可以使用也可以不使用缩写

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

工作示例: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文件中定义和存储各种函数;通过&lt;script&gt; 添加它们,然后通过 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 脚本来获取发布给它们的数据然后返回数据。

希望对您有所帮助。

【讨论】:

谢谢。这是一些很好的信息。今天早上我将通过它,看看我可以适应使用什么。您假设我无法摆脱使用 PHP 来创建 JS 是正确的,因为其中大部分是插件格式的使用。大量和跨上下文使用的原因之一是因为字段是根据配置期间的选择动态创建的。 ...继续 此外,City、State 和 Country 数据来自位于 3 个不同表中的单独数据源。幸运的是,我可以将它们与查询结合起来,但每个字段都调用服务器端 PHP 文件中的单独方法。 ;) 感谢您的彻底回答。非常感谢。这里有一些很棒的信息。【参考方案2】:

肯定有更好的方法来做到这一点,但我能够通过添加一个带有小插件的单独 js 文件来实现我所需要的,该插件声明了“全局”变量,以便在新数据之后的更改事件中进行修改从 ajax 请求返回。我想我只是想对一个文件做太多事情。 :(

【讨论】:

以上是关于jQuery UI 自动完成鼠标点击选择不传递值的主要内容,如果未能解决你的问题,请参考以下文章

jQuery UI 自动完成:如何让 TAB 选择列表中的第一个选项?

jQuery自动完成选择:功能不起作用

jQuery-ui 自动完成,选择第一项

JQuery UI 自动完成不结果显示在结果框中

自动选择单一匹配jQuery UI自动完成组合框

选择 jQuery UI 自动完成后清除表单字段