I have a list of dozens DIVs like
<div data-sort="7.5"></div>
<div data-sort="3.2"></div>
<div data-sort="2.15"></div>
<div data-sort="-1.78"></div>
<div data-sort="-2.39"></div>
and so on and I get new DIVs with an ajax request. I need to insert the new DIV so the order with "data-sort" remains intact in descending order.
It's not as optimal as can be, but I would just sort the divs each time the ajax request completes:
$("div").sort(function (prev, next) {
return parseInt(next.dataset.sort) - parseInt(prev.dataset.sort);
}).appendTo("body");
If that takes too long, you'll just have to cycle through the divs (via .each
?) and find the first one whose data-sort
is smaller.
The fastest algorithm to do this insertion (O(logN)
) would be to do a binary search for the values that the new item goes between. Assume that the list is already sorted first (if that's not done automatically, use one of the other answers here):
/**+
* Boilerplate to check first/last value
*/
var sortval = $new.data('sort');
var $first = $("div:first");
if (sortval >= $first.data('sort')) {
$new.insertBefore($first);
return;
}
var $last = $("div:last");
if (sortval <= $last.data('sort')) {
$new.insertAfter($last);
return;
}
/*-*/
//Fun stuff
var count = 0;
var $div = $("div");
do {
var index = parseInt($div.length / 2)
var $compare = $div.eq(index);
var compare = $compare.data('sort');
if (sortval === compare) {
break;
}
else if (sortval < compare) {
$div = $div.slice(index, $div.length);
}
else {
$div = $div.slice(0, index);
}
}
while ($div.length > 1);
if (sortval === compare || sortval > compare) { $new.insertBefore($compare); }
else { $new.insertAfter($compare); }
http://jsfiddle.net/ExplosionPIlls/SdjAy/1/
Maybe not elegant, but fast enough...
In your success
handler:
...
success: function(data) {
$(data).each(function(){
var $adiv = $(this);
var sortval = parseFloat($adiv.data("sort"));
var last = true;
$("div").each(function(){
if ($(this).data("sort") < sortval) {
$(this).prepend($adiv);
last = false;
return false;
}
});
if(last) {
$("div").last().append($adiv);
}
});
}
jsFiddle
You can use your custom logic also. Please try it.
Here is your HTML
<div id="dvBase">
<div data-sort="7.5">
</div>
<div data-sort="3.2">
</div>
<div data-sort="2.15">
</div>
<div data-sort="-1.78">
</div>
<div data-sort="-2.39">
</div>
</div>
<div id="tempDiv">
</div>
javascript code
var divToAdd = "<div data-sort=\"1.5\"></div>";
function getValue() {
$("#tempDiv").html(divToAdd);
var returnvalue = $("#tempDiv div").attr("data-sort");
$("#tempDiv").empty();
return returnvalue;
}
$(document).ready(function () {
var valueToadd = parseFloat(getValue());
var count = $("#dvBase >div[data-sort]").length;
$("#dvBase >div[data-sort]").each(function (index, obj) {
var value1 = parseFloat($(obj).attr("data-sort"));
if (index < count - 1) {
var value2 = parseFloat($(obj).next().attr("data-sort"));
if ((value1 == valueToadd || (valueToadd < value1 && valueToadd >= value2)) && $("#dvBase >div[data-sort]").length === count) {
$(obj).after(divToAdd);
}
} else {
if ($("#dvBase >div[data-sort]").length === count) {
$(obj).after(divToAdd);
}
}
});
});
I've solved it like this with help from the answers here:
$("div").each(function(i){
if(parseFloat($(this).data("weight"))<=weight){
$(newDiv).insertBefore(this);
return false;
}
else if (i == $(".post").length - 1) {
$(newDiv).insertAfter(this);
return false;
}
});
which seems to work ok and fast enough... anyone sees any flaws in it?