懒惰的<option>加载

时间:2017-02-19 11:54:01

标签: jquery lazy-loading visibility

假设我有这样的选择:

<select size="4">
  <option id="1">Please wait ...</option>
  <option id="2">Please wait ...</option>
  <option id="3">Please wait ...</option>
  <option id="4">Please wait ...</option>
  <option id="5">Please wait ...</option>
</select>

我应该看到一个包含右侧滚动条的4个元素的列表。

我现在要做的是如果选项以某种方式显示(滚动和/或初始化),则通过ajax加载文本。

编辑:

最后,由于巨大的元数据传输,我不会加载它们。这是我必须上传的请求(发送到服务器):

huge upload for small download

对于单个元素的延迟加载,这是不可接受的。

5 个答案:

答案 0 :(得分:4)

我很抱歉我的英语不好,但是当我理解这个问题时,我可以提出这个解决方案:

$(document).ready(function(){
  $('select').on('scroll', function(){
    var sel = $(this);
    var lasto = sel.find('option:last');
    var s = sel.position().top + sel.height();
    var o = lasto.height() + lasto.position().top - 4;
    setTimeout(function(){
      if(o < s){console.log('We need AJAX!');}
    }, 2200);
  });
});

Link

答案 1 :(得分:3)

以下是您的工作方式:

只有在元素可见时才会加载。

&#13;
&#13;
function loadSelect() {
  elementsDisplayed = Math.ceil(($(this).scrollTop() + Number($(this).css("padding-top").slice(0,-2))) / $(this).find("option:first").height() + parseFloat($(this).attr("size")));

  $(this).find("option").slice(0,elementsDisplayed).not(".loaded").each(function () {
    $(this).addClass("loaded"); //prevents spam reloading certain elements

    /*$.post("fetch.php", {
              dataId : $(this).attr("id")
          }, function (data) {
              //Yay, we are now loaded
          });*/

    console.log("Loading : " + $(this).attr("id"));
  });
}

$("select").on("scroll", loadSelect);

loadSelect.bind($("select"))();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select size="4" style="padding:14px">
  <option id="1">Please wait ...</option>
  <option id="2">Please wait ...</option>
  <option id="3">Please wait ...</option>
  <option id="4">Please wait ...</option>
  <option id="5">Please wait ...</option>
  <option id="6">Please wait ...</option>
  <option id="7">Please wait ...</option>
  <option id="8">Please wait ...</option>
  <option id="9">Please wait ...</option>
  <option id="10">Please wait ...</option>
</select>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以将元素/选项传递给下面的函数以检查元素是否可见并执行AJAX函数调用。

function isVisible(element) {
  var bx = element.getBoundingClientRect();
  var viewh = Math.max(document.documentElement.clientHeight, window.innerHeight);
  return !(bx.bottom < 0 || bx.top - viewHeight >= 0);
}

执行就像

if(isVisible(document.getElementById("select_id")))
{
/* Execute your ajax call here */
}

答案 3 :(得分:1)

您可以尝试this。它并没有真正使用选择。它使用JS重新创建它的行为。你应该尝试jsfiddle,因为它有http请求的问题。

ajax加载元素的处理尚未解决,很容易修复。

function loadMoreItems() {
  var requestStr = "http://randomword.setgetgo.com/get.php";
  alert("load triggered")
  $.ajax({
    type: "GET",
    url: requestStr,
    dataType: "jsonp",
    jsonpCallback: 'RandomWordComplete'
  });
};

function RandomWordComplete(data) {
  var op = $("li.option.last")
  op.removeClass("last")
  var li = $("<li>"+data.Word+"</li>")
  li.addClass("option")
  li.addClass("last")
  li.data("value", op.data("value") + 1)
  $("#select").append(li)
  li.slideDown()
}

$("document").ready(function() {
  $(".option").click(function() {
    $(".option").slideDown();
  });

  $(".option:not(.selected)").click(function() {
    $(".option:not(.selected)").slideUp();

    $(".option.selected").text($(this).text())
    $("#selectVal").val($(this).data("value"))
  });

  $("#select").scroll(function() {
    var div = $(this);
    if (div[0].scrollHeight - div.scrollTop() == div.height()) {
      loadMoreItems();
    }

  });
});
li {
  list-style: none
}

.option {
  display: none;
  margin: 10px 0
}

.option:first-child {
  display: block
}

.option:not(.selected):hover {
  background: red
}

#select {
  border: 1px solid black;
  width: 180px;
  cursor: pointer;
  max-height: 60px;
  overflow: auto
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="select">
  <li class="option selected">--</li>
  <li class="option" data-value="0">Spain</li>
  <li class="option last" data-value="1">Portugal</li>

</ul>
<input id="selectVal" type="hidden" value="" />

答案 4 :(得分:0)

这样的东西可能对你有用,它基本上只是检查选项的偏移量,但也确保你没有发送多个ajax请求

$(function () {

  var api = 'https://jsonplaceholder.typicode.com'
  var url = api + '/posts/1'

  var select = $('select')
  var option = select.find('option')
  var selectTop = select.offset().top
  var selectHeight = select.height()
  var inview, optionTop

  select.on('scroll', function () {
    option.each(function () {

      var _this = $(this)

      optionTop = _this.offset().top
      inview = optionTop >= selectTop && optionTop < selectTop + selectHeight

      // check that the option element is in range
      if (inview) {

        // don't send multiple requests if already triggered
        if (
          _this.attr('data-status') !== 'success'
          && _this.attr('data-status') !== 'loading'
          && _this.attr('data-status') !== 'error'
        ) {
          _this.attr('data-status', 'loading')
          _this.text('Loading ...')
          $.ajax({
            url: url,
            method: 'GET',
            success: function ajaxSuccess(resp) {
              _this.attr('data-status', 'success')
              _this.text(resp.title)
            },
            error: function ajaxError(xhr) {
              _this.attr('data-status', 'error')
              _this.text('Error ...')
              console.log(xhr.responseText)
            }
          })
        }
      }
    })
  })

  // bootstrap
  select.triggerHandler('scroll')
})

请参阅JSFiddle here,它加载速度快,您可以注释掉triggerHandler以防止它在页面加载时发送请求

编辑:我也更新了选项元素的ID,因为ids不应以数字开头