Created
April 30, 2014 22:57
-
-
Save ninetails/1d7ddc5f91c19b63c95a to your computer and use it in GitHub Desktop.
iOS wheel select like in HTML5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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