问题
Assuming I have a select like this:
<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>
I should see a List of 4 elements having a scrollbar on the right.
What i like to do now is to load the text via ajax if the option becomes visible somehow (scrolling and/or initial).
EDIT:
At the end, I do not load them lazy because of the huge metadata transfer. This is the request I must upload (send to the server):
This is inacceptable for the lazy-load of single elements.
回答1:
I'm sorry for my bad English, but as I'm understanding this question I can present this solution:
$(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
回答2:
Here's how you do it:
It will only load when the element is visible.
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"))();
<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>
回答3:
You can pass the element/option to below funtion to check if the element is visible and to execute your AJAX function call.
function isVisible(element) {
var bx = element.getBoundingClientRect();
var viewh = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(bx.bottom < 0 || bx.top - viewHeight >= 0);
}
Execution will be like
if(isVisible(document.getElementById("select_id")))
{
/* Execute your ajax call here */
}
回答4:
You can try this. It doesn't really use a select. It recreates its behaviour using JS. You should try out of jsfiddle since it has problem with http requests.
The handling for the ajax loaded elements is not working yet, it is easy to fix.
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="" />
回答5:
something like this might work for you, it basically just checks the option's offsets, but also makes sure you're not sending multiple ajax requests
$(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')
})
see the JSFiddle here, it loads kind of fast, you could comment out the triggerHandler
to prevent it sending requests on page load
edit: also i updated the ids of the option elements since ids shouldn't start with a number
来源:https://stackoverflow.com/questions/42326897/lazy-option-loading