Skip to content

Instantly share code, notes, and snippets.

@ninetails
Created April 30, 2014 22:57
Show Gist options
  • Save ninetails/1d7ddc5f91c19b63c95a to your computer and use it in GitHub Desktop.
Save ninetails/1d7ddc5f91c19b63c95a to your computer and use it in GitHub Desktop.
iOS wheel select like in HTML5
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8">
<title>Test</title>
<style>
body {
font: 400 12px/16px Arial, Helvetica, Sans-serif;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
a {
color: inherit;
text-decoration: none;
}
.container {
overflow: hidden;
*zoom: 1;
display: block;
float: left;
position: relative;
width: 57px;
}
.container .wheel {
background-image: -webkit-linear-gradient(#aaaaaa, #eeeeee 20%, #eeeeee 80%, #aaaaaa);
background-image: -webkit-gradient(linear, left top, left bottom, from(#aaaaaa), color-stop(20%, #eeeeee), color-stop(80%, #eeeeee), to(#aaaaaa));
background-image: linear-gradient(#aaaaaa, #eeeeee 20%, #eeeeee 80%, #aaaaaa);
border: 1px solid #aaaaaa;
border-radius: 5px;
height: 90px;
overflow: hidden;
margin: 0 5px;
width: 45px;
}
.container .wheel ul {
position: absolute;
width: 45px;
top: 30px;
}
.container .wheel li {
color: #333333;
display: block;
text-align: center;
}
.container .wheel li a {
display: block;
padding: 7px 0;
}
.container .glass {
background: rgba(255, 255, 255, 0.5);
border: 1px solid #aaaaaa;
border-radius: 5px;
display: block;
height: 20px;
position: absolute;
top: 33px;
width: 55px;
}
</style>
</head>
<body>
<div class="container">
<div class="wheel">
<ul>
<li value="2014-04-25">
<a href="#">25.abr</a>
</li>
<li value="2014-04-26">
<a href="#">26.abr</a>
</li>
<li value="2014-04-27">
<a href="#">27.abr</a>
</li>
<li value="2014-04-28">
<a href="#">28.abr</a>
</li>
<li value="2014-04-29">
<a href="#">29.abr</a>
</li>
<li value="2014-04-30">
<a href="#">30.abr</a>
</li>
<li value="2014-05-01">
<a href="#">01.mai</a>
</li>
<li value="2014-05-02">
<a href="#">02.mai</a>
</li>
<li value="2014-05-03">
<a href="#">03.mai</a>
</li>
<li value="2014-05-04">
<a href="#">04.mai</a>
</li>
<li value="2014-05-05">
<a href="#">05.mai</a>
</li>
</ul>
</div>
<div class="glass"></div>
</div>
<div class="content">
<ul>
<li value="2014-04-25">25 abr</li>
<li value="2014-04-26">26 abr</li>
<li value="2014-04-27">27 abr</li>
<li value="2014-04-28">28 abr</li>
<li value="2014-04-29">29 abr</li>
<li value="2014-04-30">30 abr</li>
<li value="2014-05-01">01 mai</li>
<li value="2014-05-02">02 mai</li>
<li value="2014-05-03">03 mai</li>
<li value="2014-05-04">04 mai</li>
<li value="2014-05-05">05 mai</li>
</ul>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
(function ($) {
var wheel = {
$el: $('.wheel'),
item_height: 0,
total: 0,
v: 0,
y: 0,
last: null,
get_list: function () {
return this.$el.children('ul');
},
get_top: function () {
return this.get_list().offset().top - this.$el.offset().top;
},
get_step: function () {
var wh = this.$el.outerHeight();
if (this.y < 0.5 * wh && this.get_top() >= this.item_height || this.y > 0.5 * wh && this.get_top() <= (-1) * (this.total - 2) * this.item_height) {
return '+=0';
}
if (this.y < 0.40 * wh) {
return '+=' + this.item_height + 'px';
}
if (this.y > 0.60 * wh) {
return '-=' + this.item_height + 'px';
}
return '+=0';
},
get_duration: function () {
var wh = this.$el.outerHeight();
if (this.y < 0.10 * wh || this.y > 0.90 * wh) {
return 300;
}
if (this.y < 0.30 * wh || this.y > 0.70 * wh) {
return 500;
}
return 1000;
},
move: function () {
this.get_list().stop().animate({top: this.get_step()}, {duration: this.get_duration(), complete: $.proxy(this.move, this)});
this.select_date();
},
stop: function () {
var top = Math.round(this.get_top() / this.item_height) * this.item_height;
this.get_list().stop().animate({top: top}, 'fast', 'swing', $.proxy(this.select_date, this));
},
mousewheel: function (e) {
var e = window.event || e, // old IE support
delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))),
step = (-1) * delta * this.item_height,
top;
if (! this.get_list().is(':animated')) {
if (delta < 0 && this.get_top() >= this.item_height || delta > 0 && this.get_top() <= (-1) * (this.total - 2) * this.item_height) {
step = 0;
}
if (step !== 0) {
step = (step < 0 ? '-=' : '+=') + Math.abs(step) ;
} else {
step = '+=0';
}
this.get_list().animate({top: step}, {duration: 500, complete: $.proxy(this.select_date, this)});
}
},
select_date: function () {
var idx = (-1) * (parseInt(this.get_top() / this.item_height, 10) - 1),
value = this.$el.find('li').eq(idx).attr('value');
if (this.last !== idx) {
$( '.content li:visible' ).hide();
if ($( ".content li[value='" + value + "']" ).length > 0) {
$( ".content li[value='" + value + "']" ).show();
}
this.last = idx;
}
},
set_start_date: function (date) {
var items = this.$el.find('li'),
list = this.get_list(),
item_height = this.item_height,
callback = $.proxy(this.select_date, this);
items.each(function (idx) {
if ($(this).data('date').toDateString() == date.toDateString() || $(this).data('date') > date || $(this).is(':last-child')) {
list.css('top', (item_height - $(this).offset().top + $(this).parent().offset().top) + 'px');
callback();
return false;
}
}) ;
},
prepare: function () {
var glass = this.$el.siblings('.glass').get(0),
has_touch = !!("ontouchstart" in window) || window.navigator.msMaxTouchPoints > 0;
$( '.content li:visible' ).hide();
this.item_height = this.$el.find('li:first').outerHeight();
this.total = this.$el.find('li').length;
this.$el.find('li').each(function(){
$(this).data('date', new Date($(this).attr('value') + 'T00:00:00-0300'));
});
this.set_start_date(new Date());
// muda velocidade
this.$el.bind('mousemove', $.proxy(function(e) {
this.set_mouse_y(e);
}, this));
// mouse wheel
if (glass.addEventListener) {
glass.addEventListener('mousewheel', $.proxy(this.mousewheel, this), false);
glass.addEventListener('DOMMouseScroll', $.proxy(this.mousewheel, this), false);
} else {
glass.attachEvent('onmousewheel', $.proxy(this.mousewheel, this));
}
// hover ou touch
if (!has_touch) {
// hover
this.$el.hover($.proxy(function(e) {
this.set_mouse_y(e);
this.move();
}, this), $.proxy(function(e) {
this.set_mouse_y(e);
this.stop();
}, this));
} else {
// touch
var start_y, last_y, touch_top;
this.$el.bind('touchstart', $.proxy(function(e) {
e.preventDefault();
start_y = e.originalEvent.touches[0].pageY;
touch_top = this.get_top();
}, this));
this.$el.bind('touchmove', $.proxy(function(e) {
e.preventDefault();
last_y = e.originalEvent.touches[0].pageY;
this.get_list().css('top', touch_top - start_y + last_y);
}, this));
this.$el.bind('touchend', $.proxy(function(e) {
var top = Math.round((touch_top - start_y + last_y) / this.item_height) * this.item_height;
top = Math.max(top, (-1) * (this.total - 2) * this.item_height);
top = Math.min(top, this.item_height);
e.preventDefault();
this.get_list().stop().animate({top: top}, 'fast', 'swing', $.proxy(this.select_date, this));
}, this));
}
},
touch_drag: function(e) {
this.get_list().css('top', (item_height - $(this).offset().top + $(this).parent().offset().top) + 'px');
},
set_mouse_y: function (e) {
this.y = e.pageY - this.$el.offset().top;
}
} ;
$(function () {
wheel.prepare();
});
}).apply(this, [jQuery]);
</script>
</body></html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment