jQuery response()函数由于变量范围不返回任何结果 [英] jQuery response() function doesn't return any results because of the variable scope

查看:106
本文介绍了jQuery response()函数由于变量范围不返回任何结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的问题是,由于变量范围的原因,我无法从jQuery UI Autocomplete表单获得任何结果.让我告诉你.

The problem I encountered is I can't get any results from the jQuery UI Autocomplete form because of the variable scope. Let me show you.

// TAKE A CLOSE LOOK AT THIS METHOD
select: function(e, ui) {

$('#instant-search').text(ui.item.label);
$("#search").autocomplete("option", "source",
  function(request, response) {
    getAutocompleteResults(function(d) {
      // DOESN'T WORK response(d);
    });
    // WORKS BUT IT SHOULD BE A DYNAMIC ARRAY FROM THE "D" OBJECT
    // response(["anarchism", "anarchist black cross", "black rose (symbolism)", "communist symbolism", "political symbolism"]);
  });

$("#search").autocomplete("search", ui.item.label);

为了返回结果,我必须在getAutocompleteResults(function(d) { ... });函数之外使用函数response([...]);.

In order to return results I have to use a function response([...]); outside the getAutocompleteResults(function(d) { ... }); function.

但是,源应该是动态的,而不是静态数组.换句话说:

However, the source should be dynamic and not like the static array. In other words:

函数response(d);应该返回一个对象,该对象包含一些属性(标题,值,提取).我必须使用response(d);访问它们,但是,此功能在getAutocompleteResults(function(d) { ... });函数内部不起作用.我该如何实现?

The function response(d); should return an object, which contains a few properties (title, value, extract). I have to access them by using response(d);, however, this function doesn't work inside getAutocompleteResults(function(d) { ... }); function. How can I achieve this?

有一小段代码,但是,主要问题是select方法.您可以在整个代码块的中间找到它.我把它注释掉了.

There is a small snippet of code, however, the main problem is the select method. You can find this in the middle of the whole code block. I commented it out.

$(function() {
  $("html").removeClass("no-js");
  var autocompleteResults = [{
    title: [],
    extract: [],
    pageId: []
  }];

  var capitalizeFirstLetter = function(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  };

  var changeText2 = function(e) {
    var request = $("input").val() + String.fromCharCode(e.which);
    $("#instant-search").text(request);

    var getAutocompleteResults = function(callback) {
      $.ajax({
        url: "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrlimit=6&prop=extracts&origin=*&pilimit=max&exintro&explaintext&exsentences=1&gsrsearch=" +
          $("#instant-search").text(),
        beforeSend: function() {
          $(".loading").show();
        },
        success: function(d) {
          $(".loading").hide();
          autocompleteResults[0].title = [];
          autocompleteResults[0].extract = [];
          autocompleteResults[0].pageId = [];

          if (d.hasOwnProperty("query")) {
            if (d.query.hasOwnProperty("pages")) {
              $.each(d.query.pages, function(i) {
                autocompleteResults[0].title.push(d.query.pages[i].title);

                autocompleteResults[0].extract.push(d.query.pages[i].extract);
                autocompleteResults[0].pageId.push(d.query.pages[i].pageid);
              });
            }
          }

          if (!autocompleteResults[0].length) {
            $(".ui-autocomplete").hide();
          }


          autocompleteResults[0].title.sort(function(a, b) {
            var nameA = a.toUpperCase();
            var nameB = b.toUpperCase();
            if (nameA < nameB) {
              return -1;
            }
            if (nameA > nameB) {
              return 1;
            }

            return 0;
          });

          autocompleteResults[0].title = autocompleteResults[0].title.map(
            function(i) {
              return i.toLowerCase();
            }
          );

          callback(autocompleteResults[0]);
        },
        datatype: "json",
        cache: false
      });
    };

    $("#search").autocomplete({
      source: function(request, response) {
        getAutocompleteResults(function(d) {
          var results = [],
            filteredAutocompleteResults = [];

          filteredAutocompleteResults = d.title.filter(function(i) {
            return (
              i !=
              $("#instant-search")
              .text()
              .toLowerCase()
            );
          });

          for (var i = 0; i < d.title.length; i++) {
            results[i] = {
              label: filteredAutocompleteResults[i],
              extract: d.extract[i],
              pageId: d.pageId[i]
            };
          }

          if (results.length == 5) {
            response(results);
          } else {
            response(results.slice(0, 5));
          }
        });
      },
      response: function() {
        if ($("#instant-search").text()) {
          $("table").css("display", "table");
          $(".wikisearch-container").css("margin-top", 100);
        }
      },
      close: function() {
        if (!$(".ui-autocomplete").is(":visible")) {
          $(".ui-autocomplete").show();
        }
      },
      appendTo: ".input",
      focus: function(e) {
        e.preventDefault();
      },
      delay: 0,












      // TAKE A CLOSE LOOK AT THIS METHOD
      select: function(e, ui) {

        $('#instant-search').text(ui.item.label);
        $("#search").autocomplete("option", "source",
          function(request, response) {
            getAutocompleteResults(function(d) {
              // DOESN'T WORK response(d);
            });
            // WORKS BUT IT SHOULD BE A DYNAMIC ARRAY FROM THE "D" OBJECT
            // response(["anarchism", "anarchist black cross", "black rose (symbolism)", "communist symbolism", "political symbolism"]);
          });

        $("#search").autocomplete("search", ui.item.label);










        // EVERYTHING SHOULD BE FINE BELOW THIS LINE

        if ($(".search-results").css("opacity") != 1) {
          $(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
          $(".search-results p").text(ui.item.extract);
          $(".search-results a").prop(
            "href",
            "https://en.wikipedia.org/?curid=" + ui.item.pageId
          );
          $(".search-results").css("opacity", 1);
        } else if (
          $(".search-results h4")
          .text()
          .toLowerCase() != ui.item.label
        ) {
          $(".search-results").css("opacity", 0);
          setTimeout(function() {
            $(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
            $(".search-results p").text(ui.item.extract);
            $(".search-results a").prop(
              "href",
              "https://en.wikipedia.org/?curid=" + ui.item.pageId
            );
            $(".search-results").css("opacity", 1);
          }, 500);
        }
      },
      create: function() {
        $(this).data("ui-autocomplete")._renderItem = function(ul, item) {
          return $("<li>")
            .append(
              '<div class="ui-menu-item-wrapper"><div class="autocomplete-first-field"><i class="fa fa-search" aria-hidden="true"></i></div><div class="autocomplete-second-field three-dots">' +
              item.label +
              "</div></div>"
            )
            .appendTo(ul);
        };
      }
    });
  };


  var changeText1 = function(e) {
    if (
      /[-a-z0-90áãâäàéêëèíîïìóõôöòúûüùçñ!@#$%^&*()_+|~=`{}\[\]:";'<>?,.\s\/]+/gi.test(
        String.fromCharCode(e.which)
      )
    ) {
      $("input").on("keypress", changeText2);
    }


    // DONT TOUCH THIS AREA, IT HAS NOTHING TO DO WITH THE PROBLEM
    var getInputSelection = function(input) {
      var start = 0,
        end = 0;
      input.focus();
      if (
        typeof input.selectionStart == "number" &&
        typeof input.selectionEnd == "number"
      ) {
        start = input.selectionStart;
        end = input.selectionEnd;
      } else if (document.selection && document.selection.createRange) {
        var range = document.selection.createRange();
        if (range) {
          var inputRange = input.createTextRange();
          var workingRange = inputRange.duplicate();
          var bookmark = range.getBookmark();
          inputRange.moveToBookmark(bookmark);
          workingRange.setEndPoint("EndToEnd", inputRange);
          end = workingRange.text.length;
          workingRange.setEndPoint("EndToStart", inputRange);
          start = workingRange.text.length;
        }
      }
      return {
        start: start,
        end: end,
        length: end - start
      };
    };

    switch (e.key) {
      case "Backspace":
      case "Delete":
        e = e || window.event;
        var keyCode = e.keyCode;
        var deleteKey = keyCode == 46;
        var sel, deletedText, val;
        val = this.value;
        sel = getInputSelection(this);
        if (sel.length) {
          // 0 kai paprastai trini po viena o 1 ar daugiau kai select su pele trini
          $("#instant-search").text(
            val.substr(0, sel.start) + val.substr(sel.end)
          );
        } else {
          $("#instant-search").text(
            val.substr(0, deleteKey ? sel.start : sel.start - 1) +
            val.substr(deleteKey ? sel.end + 1 : sel.end)
          );
        }
        break;
      case "Enter":
        if ($("#instant-search").text()) {
          console.log("Redirecting...");
        }
        break;
    }

    if (!$("#instant-search").text()) {
      $("table, .ui-autocomplete").hide();
      $(".wikisearch-container").css("margin-top", "");
    }

    if (
      $(".ui-menu-item-wrapper").hasClass("ui-state-active") &&
      (e.key == "ArrowRight" || e.key == "ArrowLeft")
    ) {
      $(".ui-autocomplete").autocomplete(""); // Error metas console ir taip neturėtų būti bet nežinau kaip padaryti kad pasirinkus elementą su <-- ar --> nepadarytų tik vieno rezultato todėl paliekam laikinai ;)
    }
  };

  $("input").on("keydown", changeText1);

  $("input").on("input", function(e) {
    $("#instant-search").text($("#search").val());
  });

});

html,
body {
  height: 100%;
  width: 100%;
}

body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  background-image: url("http://www.part.lt/img/96816a00ec1fb87adc4ca8a04365b2b5719.jpg");
  background-size: cover;
  background-position: 100%;
}

.v-container {
  display: table;
  height: 100%;
  width: 100%;
}

.v-content {
  display: table-cell;
  vertical-align: middle;
}

.text-center {
  text-align: center;
}

.input {
  overflow: hidden;
  white-space: nowrap;
}

.input input#search {
  width: calc(100% - 30px);
  height: 50px;
  border: none;
  font-size: 10pt;
  float: left;
  color: #4f5b66;
  padding: 0 15px;
  outline: none;
}

.ui-autocomplete {
  list-style: none;
  background-color: #fff;
  -webkit-user-select: none;
  user-select: none;
  padding: 0;
  margin: 0;
  width: 100% !important;
  top: auto !important;
  display: table;
  table-layout: fixed;
}

.ui-helper-hidden-accessible {
  display: none;
}

.autocomplete-first-field {
  width: 15%;
  display: inline-block;
}

.autocomplete-second-field {
  width: 85%;
  display: inline-block;
  text-align: left;
  vertical-align: middle;
}

.three-dots {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

table {
  width: 100%;
  border-spacing: 0;
  border-collapse: collapse;
  display: none;
  table-layout: fixed;
}

table tr {
  background-color: #fff;
  -webkit-user-select: none;
  user-select: none;
}

tr:first-child {
  background-color: #ffc800;
  color: #fff;
}

table td,
.ui-menu-item-wrapper {
  padding: 10px 0;
}

td:nth-child(2) {
  width: 85%;
  text-align: left;
}

.ui-menu-item,
table {
  cursor: pointer;
}

:focus {
  outline: 0;
}

a {
  text-decoration: none;
  color: #fff;
  position: relative;
}

a:before {
  content: "";
  position: absolute;
  width: 100%;
  height: 0.0625rem;
  bottom: 0;
  left: 0;
  background-color: #fff;
  visibility: hidden;
  -webkit-transform: scaleX(0);
  transform: scaleX(0);
  -webkit-transition: all 0.3s ease-in-out 0s;
  transition: all 0.3s ease-in-out 0s;
}

a:hover:before {
  visibility: visible;
  -webkit-transform: scaleX(1);
  transform: scaleX(1);
}

.search-results {
  background: #fff;
  margin-top: 50px;
  border-left: 5px solid #0ebeff;
  opacity: 0;
  -webkit-transition: opacity 1s;
  transition: opacity 1s;
}

.search-results h4,
.search-results p {
  margin: 0;
  padding: 10px;
  text-align: left;
}

.search-results a {
  color: #0ebeff;
  display: inline-block;
  margin: 1rem 0;
}

.search-results a:before {
  background-color: #0ebeff;
}

.wikisearch-container {
  width: 65%;
  margin: 0 auto;
}


/* Loading animation */

@keyframes lds-eclipse {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
    transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

@-webkit-keyframes lds-eclipse {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
    transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

.loading {
  position: relative;
  top: 9.5px;
  right: 15px;
  pointer-events: none;
  display: none;
}

.lds-eclipse {
  -webkit-animation: lds-eclipse 1s linear infinite;
  animation: lds-eclipse 1s linear infinite;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  margin-left: auto;
  box-shadow: 0.08rem 0 0 #0ebeff;
}

@media (max-width: 71.875em) {
  .wikisearch-container {
    width: 75%;
  }
}

@media (max-width: 50em) {
  .wikisearch-container {
    width: 85%;
  }
}

@media (max-width: 17.96875em) {
  .wikisearch-container {
    width: 100%;
  }
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<html class="no-js">
<div class="v-container">
  <div class="v-content text-center">
    <div class="wikisearch-container">
      <div class="input">
        <input type="text" id="search" placeholder="Search...">
        <div class="loading">
          <div class="lds-eclipse"></div>
        </div>
        <button class="icon"><i class="fa fa-search"></i></button>
        <table>
          <tr>
            <td class="fa fa-search">
              <td id="instant-search" class="three-dots"></td>
          </tr>
        </table>
      </div>
      <div class="search-results">
        <h4></h4>
        <p></p>
        <a target="_blank">Click here for more</a>
      </div>
    </div>
  </div>
</div>

编辑1 进行一些更改之后,结果将显示在ajax调用之前.仅在ajax成功完成后才能使用response()(使用success回调进行了尝试,但::)无效?

EDIT 1 After some changes, the results are shown, however, before the ajax call. How can I use response() only after the ajax was successfully completed (tried using success callback, didn't work :()?

完整的项目代码: https://codepen.io/Kestis500/pen/zRONyw ?editors = 0010 .

在这里您可以逐步查看其外观:

Here you can see step by step how it looks like:

  1. 重新加载页面时的外观:
  2. 让我们尝试输入"a":
  3. 我们取得了一些成果.好的,让我们尝试单击无政府主义象征主义"元素:
  4. 结果应类似于无政府主义象征主义"搜索.但是,它返回"a"搜索的结果.如果我们按下"fraktur"元素怎么办?
  5. 现在,它显示了我们先前搜索的无政府主义象征主义"结果.但是,它应返回"fraktur"搜索的元素.
  1. How it looks like when you just reloaded the page:
  2. Let's try entering "a":
  3. We've got some results. Ok, let's try to click on the "anarchist symbolism" element:
  4. Results should look like "anarchist symbolism" search. However, it returns the result of the "a" search. What if we pressed "fraktur" element?
  5. Now it shows our previous search "anarchist symbolism" results. However, it should return elements of the "fraktur" search.

编辑2 我已经修复了许多问题,并从代码中删除了一些真正意义不大的问题.但是,ajax调用的情况仍然相同.

EDIT 2 I've fixed many things and removed some really non sense things from my code. However, the situation with the ajax call is still the same.

https://codepen.io/Kestis500/pen/pazppP?editors=0110

有什么想法吗?

编辑3 修复了ajax延迟(现在ajax请求将仅在上一个ajax调用之后发送).

EDIT 3 Fixed ajax lag (now the ajax request will be sent only after the previous ajax call).

https://codepen.io/Kestis500/pen/JpPLON?editors=0110

推荐答案

我必须首先解决您的Ajax调用中的一些问题.然后,我们收集结果并构建一个应返回到response()的数组.这将填充自动完成".

I had to first fix a few things in your Ajax call. We then collect the results and build an array that should be returned to response(). This will populate the AutoComplete.

首先,我们将检查HTML.缺少一些结束标签.

First we will examine the HTML. There was some closing tags missing.

HTML

<div class="v-container">
  <div class="v-content text-center">
    <div class="wikisearch-container">
      <div class="input ui-front">
        <input type="text" id="search" placeholder="Search...">
        <div class="loading">
          <div class="lds-eclipse"></div>
        </div>
        <button class="icon">
          <i class="fa fa-search"></i>
        </button>
        <table>
          <tr>
            <td class="fa fa-search"></td>
            <td id="instant-search" class="three-dots"></td>
          </tr>
        </table>
      </div>
      <div class="search-results">
        <h4></h4>
        <p></p>
        <a target="_blank">Click here for more</a>
      </div>
    </div>
  </div>
</div>

您可以看到table,并且所有单元格现在都具有正确的结束标记.

You can see the table and it's cells all have the proper closing tags now.

我没有对您的CSS或样式进行任何更改.

I didn't make any changes to your CSS or Style.

JavaScript

$(function() {
  var capitalizeFirstLetter = function(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  };
  $("#search").autocomplete({
    source: function(request, response) {
      var results = [];
      $.ajax({
        url: "https://en.wikipedia.org/w/api.php",
        data: {
          format: "json",
          action: "query",
          generator: "search",
          gsrlimit: 6,
          prop: "extracts|pageimages",
          origin: "*",
          pilimit: "max",
          exintro: false,
          explaintext: false,
          exsentences: 1,
          gsrsearch: request.term
        },
        beforeSend: function() {
          $(".loading").show();
        },
        success: function(d) {
          $(".loading").hide();
          if (d.query.pages) {
            $.each(d.query.pages, function(k, v) {
              console.log(k, v.title, v.extract, v.pageid);
              results.push({
                label: v.title,
                value: "https://en.wikipedia.org/?curid=" + v.pageid,
                title: v.title,
                extract: v.extract,
                pageId: v.pageid
              });
            });
            response(results);
          }
        },
        datatype: "json",
        cache: false
      });
      response(results);
    },
    close: function() {
      if (!$(".ui-autocomplete").is(":visible")) {
        $(".ui-autocomplete").show();
      }
    },
    focus: function(e) {
      e.preventDefault();
      return false;
    },
    delay: 0,
    select: function(e, ui) {
      if ($(".search-results").css("opacity") != 1) {
        $(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
        $(".search-results p").text(ui.item.extract);
        $(".search-results a").prop(
          "href",
          ui.item.value
        );
        $(".search-results").css("opacity", 1);
      } else if (
        $(".search-results h4")
        .text()
        .toLowerCase() != ui.item.label
      ) {
        $(".search-results").css("opacity", 0);
        setTimeout(function() {
          $(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
          $(".search-results p").text(ui.item.extract);
          $(".search-results a").prop(
            "href",
            ui.item.value
          );
          $(".search-results").css("opacity", 1);
        }, 500);
      }
      return false;
    }
  }).autocomplete("instance")._renderItem = function(ul, item) {
    var $item = $("<li>");
    var $wrap = $("<div>").appendTo($item);
    var $field1 = $("<div>", {
      class: "autocomplete-first-field"
    }).appendTo($wrap);
    $("<i>", {
      class: "fa fa-search",
      "aria-hidden": true
    }).appendTo($field1);
    $("<div>", {
      class: "autocomplete-second-field three-dots"
    }).html(item.label).appendTo($wrap);
    return $item.appendTo(ul);
  };
});

有很多要修复和改进的地方.

There was a lot of things to fix and improve.

让我们从Ajax开始.您正在调用MediaWiki API并期待一些结果.当呼叫返回时,它将生成有关pilimit的警告.深入研究API文档,这是特定于pageimages属性调用的参数.要解决此问题,prop值必须为extracts|pageimages.现在,我得到了一组干净的结果.

Let's start with the Ajax. You're making a call to a MediaWiki API and expecting some results. When the call would come back, it would generate warnings about pilimit. Digging into the API docs, this is a parameter specific to the pageimages properties call. To fix this, the prop value had to be extracts|pageimages. Now I get a clean set of results.

您可以看到我破坏了数据,以便可以更轻松地进行更改并查看要发送给API的参数.您的方法没什么问题,我只是发现它更容易使用.

You can see I broke out the data so that I could more easily make changes and see what parameters I was sending to the API. Nothing wrong with your method, I just find this a lot easier to work with.

这一切都在我们填充source时在.autocomplete()内部发生.当我们将function用作source时,它必须遵循一些准则:

This is all happening inside .autocomplete() when we are populating the source. When we use function as a source, it has to follow a few guidelines:

  • 我们在
  • 中传递requestresponse
  • 结果必须位于数组中
  • 该数组可以包含对象,只要它们至少包含{ label, value }
  • 我们的结果数组必须传递给response函数.
  • we pass a request and response in
  • results must be in an array
  • the array can contain objects, as long as they contain at least { label, value }
  • our results array must be passed to response function.

一个简单的例子:

$(selector).autocomplete({
  source: function(req, resp){
    var q = req.term;
    // The Request is an object that contains 1 index: term
    // request.term will contain the content of our search
    var results = [];
    // An array to store the results
    $.getJSON("myapi.php", {query: q}, function(data){
      $.each(data, function(key, val){
        // iterate over the result data and populate our result array
        results.push({
          label: data.name,
          value: data.url
        });
        resp(results);
      });
    });
  }
});

您可以随意排序或过滤结果;只要您最终将它们传递给response.

You can sort or filter the results all you like; as long as you pass them to response in the end.

使用focusselect回调,您想返回false.此处对此进行了更多讨论: http://jqueryui.com/autocomplete/#custom-data

With your focus and select callbacks, you want to return false. This is discussed more here: http://jqueryui.com/autocomplete/#custom-data

我们还看到了渲染菜单项的一个很好的例子.我转向制作jQuery对象而不是原始HTML.您会做最适合自己的事情.

We also see a good example of rendering the menu item. I switched over to making jQuery objects versus raw HTML. You do what works best for you.

工作示例: https://jsfiddle.net/Twisty/vr6gv2aw/4/

希望这会有所帮助.

这篇关于jQuery response()函数由于变量范围不返回任何结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆