List
by levchenko_d
HTML
<script src="https://beat.today/app/js/app.min.js"></script>
<div class="list-wrapper">
<div class="list-actions">
<a class="check-all">Select all</a>
<a class="uncheck-all">Deselect all</a>
<a class="delete">Delete selected</a>
<span class="check-counter">0</span>
<a class="append">Append</a>
<a class="prepend">Prepend</a>
</div>
<div class="list-empty __hide">
<p class="text">There are no list items</p>
</div>
<div class="list-waiting-data __hide">
<p class="text">Loading...</p>
</div>
<div class="load-more-indicator __hide">
<div class="text text-center">Loading more...</div>
</div>
<ul class="list bordered">
</ul>
</div>
<!-- <li class="list-item">
<div class="item-checker">
<input type="checkbox">
<i class="indicator"></i>
</div>
<div class="item-details">
<div class="prefix">a</div>
<div class="postfix" data-list-item-delete="true">X</div>
<div class="content">content</div>
</div>
</li>
<li class="list-item">
<div class="item-checker">
<input type="checkbox">
<i class="indicator"></i>
</div>
<div class="item-details">
<div class="prefix">a</div>
<div class="content">content</div>
</div>
</li>
<li class="list-item">
<div class="item-checker">
<input type="checkbox">
<i class="indicator"></i>
</div>
<div class="item-details">
<div class="prefix">a</div>
<div class="postfix" data-list-item-delete="true">X</div>
<div class="content">content</div>
</div>
</li>
<li class="list-item">
<div class="item-checker">
<input type="checkbox">
<i class="indicator"></i>
</div>
<div class="item-details">
<div class="postfix"...
SCSS
.__hide{
display: none !important;
}
*{
box-sizing: border-box;
}
.text-center{
text-align: center;
}
.list{
height: 300px;
overflow-y: scroll;
border: solid 1px silver;
}
.hidden{
visibility: hidden !important;
}
/* ------ IGNORE ABOVE ------ */
$blue: #2C9EE4;
$listBorder: #f2f2f2;
$listHoverBG: #f2f3f4;
$listActiveBG: #e6e8e9;
$fix_width: 40px;
$height: 40px;
$radius: 7px;
$bottom_spacing: 5px;
$content_padding_x: 10px;
$content_padding_y: 0;
$checker_width: 20px;
$indicator_size: 5px;
$indicator_active_size: 10px;
.list-actions{
border: solid 1px $listBorder;
margin-bottom: $bottom_spacing * 3;
padding: $content_padding_x;
}
.list-wrapper.selecting-list-items *{
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome and Opera */
}
.list-empty{
}
.list-wrapper .load-more-indicator{
padding: 10px;
}
.list {
margin: 0;
padding: 0;
.list-item {
list-style-type: none;
padding-bottom: $bottom_spacing;
.item-checker{
position: relative;
float: left;
width: $checker_width;
height: $height;
line-height: $height;
cursor: pointer;
input[type="checkbox"],
.indicator{
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
input[type="checkbox"]{
display: none;
z-index: 9;
opacity: 0;
cursor: pointer;
width: 100%;
height: 100%;
}
.indicator{
background: $listBorder;
width: $indicator_size;
height: $indicator_size;
border-radius:...
JavaScript
console.clear();
/*
Cluster thing.
invisibleA
----
| |
| | Visible
| |
----
invisibleB
onScroll down:
1. Find invisible doms until visible
2. Store them in clusterAStore with height and width value
3. Apply common height to insivleA
4. Remove invisible doms
5. Find new cluster in invisibleB by looping clusterBStore from the beggining until new elements will be invisible
onScroll up:
1. Find invisible doms until visible
2. Store them in clusterBStore with height and width value
3. Apply common height to insivleB
4. Remove invisible doms
5. Find new cluster in invisibleA by looping clusterAStore from the end until new elements will be invisible
In this case, first listLoad might be heavy, but no extra loops required.
Plus list items might be different height
*/
(function(){
App.supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
App.supportsPassive = true;
}
});
window.addEventListener("testPassive", null, opts);
window.removeEventListener("testPassive", null, opts);
} catch (e) {};
App.passiveEvent = App.supportsPassive ? {'passive': true} : false;
function setScrollTop(obj, position){
if(obj === document.body){
return document.body.scrollTop = position;
} else if(obj === window){
return window.scrollTo(0, position);
} else {
return obj.scrollTop = position;
}
}
App.setScrollTop = setScrollTop;
function getScrollHeight(obj){
var body = document.body,
html = document.documentElement;
if(obj === window || body || html){
return Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight
);
} else {
return obj.scrollHeight;
}
}
App.getScrollHeight = getScrollHeight;
App.async = {};
App.async.map = function(list, iteratee, callback, reverse){
var i...