JQuery-UI给出" TypeError:n未定义"并且" ui.item未定义"

时间:2017-01-17 10:06:16

标签: jquery-ui

我正在使用自动填充功能从多个来源获取建议,并将其显示为UI中的一个列表。当我打字时,建议显示出来,但当我将鼠标悬停在建议上时,我收到错误" TypeError:n未定义"。当我点击建议时出现错误" ui.item未定义"。

HTML页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuery Autocomplete with Multiple Search Engines Suggestions</title>

<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript">
$.widget( "custom.catcomplete", $.ui.autocomplete, {
    _renderMenu: function( ul, items ) {
        var self = this, currentCategory = "";
        $.each( items, function( index, item ) {
            if ( item.category != currentCategory ) {
                ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
                currentCategory = item.category;
            }
            self._renderItem( ul, item );
        });
    }
});

$(function(){ //page load
    $("#q").focus(); //set focus to search field
    $("#q").catcomplete({
        source:"suggest.php",
        minLength:2,
        delay:10,
        select: function(event, ui) { 
            window.location.assign(ui.item.searchUrl + ui.item.label);
            //document.getElementById("q").value = ui.item.label
            //$("#q").val(ui.item.value);
            //$("#searchform").submit();
        }
    });
});
</script>
<style type="text/css">
.ui-autocomplete-category {
    font-weight: bold;
    font-size: 1em;
    padding: .2em .2em;
    margin: .4em 0 .2em;
    line-height: 1.5;
    color: #069;
    border-bottom: 2px solid #069;
}
li.ui-autocomplete-category {
    list-style-type: none;
}
</style>
</head>
<body>
    <form id="searchform" name="form1" method="get" action="http://www.google.com/search">
        Search: 
        <input name="q" id="q" type="text" size="40" />
        <input name="submit" type="submit" value="Search" />
    </form>
</body>
</html>

PHP脚本:

<?php
//Search term
$term = $_REQUEST['term'];
//Search Engine array
$searchEngines = array(
    "Google" => array("http://suggestqueries.google.com/complete/search?output=firefox&client=firefox&q=", "http://www.google.com/search?q="),
    //"Bing" => array("http://api.bing.com/osjson.aspx?query=", "http://www.bing.com/search?q="),
    //"Yahoo" => array("http://ff.search.yahoo.com/gossip?output=fxjson&command=", "http://search.yahoo.com/search?p="),
    "Wikipedia" => array("http://en.wikipedia.org/w/api.php?action=opensearch&search=", "http://en.wikipedia.org/w/index.php?title=Special%3ASearch&search="),
    //"Ebay" => array("http://anywhere.ebay.com/services/suggest/?q=", "http://shop.ebay.com/i.html?_nkw="),
    "Amazon" => array("http://completion.amazon.com/search/complete?search-alias=aps&client=amazon-search-ui&mkt=1&q=", "http://www.amazon.com/s/field-keywords=")

);

//Combine Search Results
$searchArray = array();
foreach($searchEngines as $engine => $urls){
    $url = $urls[0] . rawurlencode($term);
    try{
        //$json = file_get_contents($url);
        $json = get_url_contents($url);
        $array = json_decode($json);
        $array = $array[1]; //$array[1] contains result list
        if(count($array) > 0){
            $array = getFormattedArray($array, $engine, $urls[1]);
            $searchArray = array_merge($searchArray, $array );
        }
    } catch (Exception $e){ /* Skip the exception */ }
}

//Output JSON
header('content-type: application/json; charset=utf-8');
echo json_encode($searchArray); //Convert array to JSON object

//Format array to add category (search engine name)
function getFormattedArray($array, $engine, $searchUrl){
    $newArray = array();
    foreach($array as $a){
        $newArray[] = array('label' => $a, 'searchUrl' => $searchUrl, 'category' => $engine);
    }
    return $newArray;
}

//Read URL contents
function get_url_contents($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    $ip=rand(0,255).'.'.rand(0,255).'.'.rand(0,255).'.'.rand(0,255);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("REMOTE_ADDR: $ip", "HTTP_X_FORWARDED_FOR: $ip"));
    curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/".rand(3,5).".".rand(0,3)." (Windows NT ".rand(3,5).".".rand(0,2)."; rv:2.0.1) Gecko/20100101 Firefox/".rand(3,5).".0.1");
    $html = curl_exec($ch);
    curl_close($ch);
    return $html;
}
?>

1 个答案:

答案 0 :(得分:1)

我暂时将其添加为评论,而不是答案,我计划在完成此问题时对其进行更新。

首先,我能够在此处复制您的代码和错误:https://jsfiddle.net/xatu48sc/2/

我正在使用常规(非缩小)版本。我在第5836行遇到了错误:

5826    item = ui.item.data( "ui-autocomplete-item" );
5827    if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5828
5829        // use value to match what will end up in the input, if it was a key event
5830        if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5831            this._value( item.value );
5832        }
5833    }
5834
5835    // Announce the value in the liveRegion
5836    label = ui.item.attr( "aria-label" ) || item.value;
5837    if ( label && $.trim( label ).length ) {
5838        this.liveRegion.children().hide();
5839        $( "<div>" ).text( label ).appendTo( this.liveRegion);
5840    }

我看到的错误是:

  

TypeError:item is undefined jquery-ui.js(第5836行,第13栏)

这告诉我们item未定义,因此item.value未定义,因此我将代码包含在启动之前。这将指向我们返回您的自定义小部件以呈现类别。

当我将其与https://jqueryui.com/autocomplete/#categories处的示例进行比较时,我可以看到许多不同之处。没有_create方法,在_renderMenu方法中,没有为项目定义li

这里的某个地方就是问题所在。

我还发现只有没有类别的项目才会抛出此错误。

<强>更新

我通过使用文本比较网站在您的代码中发现了该问题。这是问题所在:

self._renderItem( ul, item );

示例页面中的命令是:

li = that._renderItemData( ul, item );

它没有使用_renderItem(),但似乎是未记录的扩展点:_renderItemData()

基于此:Difference between jQuery autocomplete renderItem and renderItemData您正在使用扩展点。

当我对您的代码进行微小更改时,它可以正常运行:

$.widget("custom.catcomplete", $.ui.autocomplete, {
  _renderMenu: function(ul, items) {
    var self = this, currentCategory = "";
    $.each(items, function(index, item) {
      var li;
      if (item.category != currentCategory) {
        ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>");
        currentCategory = item.category;
      }
      li = self._renderItemData(ul, item);
    });
  }
});

工作示例:https://jsfiddle.net/xatu48sc/6/

我怀疑两者之间存在范围问题。如果这不好并且你真的想使用_renderItem()那么我可以调查一下。使用_renderItemData()确实有效。