Browse Source

Fixes #61. Touch respones now 0ms responsive, "clickaway" event now

checks for touchmove allowing for user to scroll screen while keeping
dropdown open.

Adds examples for default values for dropdowns, all dropdown types now
support default values not just selection.
pull/258/head
jlukic 11 years ago
parent
commit
3266779a50
4 changed files with 174 additions and 96 deletions
  1. 63
      server/documents/modules/dropdown.html.eco
  2. 3
      server/files/stylesheets/semantic.css
  3. 193
      src/modules/dropdown.js
  4. 11
      src/modules/dropdown.less

63
server/documents/modules/dropdown.html.eco

@ -190,33 +190,19 @@ type : 'UI Module'
<h2 class="ui dividing header">Examples</h2>
<div class="form example">
<h4 class="ui header">Multiple Levels</h4>
<p>A dropdown menu can also contain sub menus inside of it</p>
My favorite animal breed is <div class="ui inline dropdown">
<input type="hidden" name="gender">
<div class="text">Shiba Inu</div>
<h4 class="ui header">Re-selecting values</h4>
<p>A dropdown will automatically select on page load any menu item that includes the currently value of <code>text</code> or your dropdown's hidden input value. This is used to preserve a user's selection on page navigation and will automatically remove and default text placeholder formatting.</p>
Current action: <div class="ui inline dropdown">
<div class="text">Hide</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item">
<i class="dropdown icon"></i>
Dogs
<div class="menu">
<div class="active item">Shiba Inu</div>
<div class="item">Poodle</div>
<div class="item">Labrador</div>
</div>
</div>
<div class="item">
<i class="dropdown icon"></i>
Cats
<div class="menu">
<div class="item">Aegean</div>
<div class="item">Balinese</div>
<div class="item">Persian</div>
</div>
</div>
<div class="item">Edit</div>
<div class="item">Remove</div>
<div class="item">Hide</div>
</div>
</div>
</div>
<div class="dropdown example">
@ -267,6 +253,37 @@ type : 'UI Module'
</div>
</div>
<div class="form example">
<h4 class="ui header">Multiple Levels</h4>
<p>A dropdown menu can also contain sub menus inside of it</p>
My favorite animal breed is <div class="ui inline dropdown">
<input type="hidden" name="gender">
<div class="text">Shiba Inu</div>
<i class="dropdown icon"></i>
<div class="menu">
<div class="item">
<i class="dropdown icon"></i>
Dogs
<div class="menu">
<div class="active item">Shiba Inu</div>
<div class="item">Poodle</div>
<div class="item">Labrador</div>
</div>
</div>
<div class="item">
<i class="dropdown icon"></i>
Cats
<div class="menu">
<div class="item">Aegean</div>
<div class="item">Balinese</div>
<div class="item">Persian</div>
</div>
</div>
</div>
</div>
</div>
<div class="hover example">
<h4 class="ui header">Menu</h4>
<p>A <a href="/collection/menu.html">menu</a> element can contain a dropdown</p>

3
server/files/stylesheets/semantic.css

@ -1320,6 +1320,9 @@ body.progress .ui.progress .bar {
#example .main.menu .github.item {
display: block;
}
#example .main.menu .github.item:before {
display: none;
}
#example .carbonad {
height: 135px;
}

193
src/modules/dropdown.js

@ -11,18 +11,19 @@
;(function ( $, window, document, undefined ) {
$.fn.dropdown = function(parameters) {
var
$allModules = $(this),
$document = $(document),
var
$allModules = $(this),
$document = $(document),
moduleSelector = $allModules.selector || '',
moduleSelector = $allModules.selector || '',
time = new Date().getTime(),
performance = [],
hasTouch = ('ontouchstart' in document.documentElement),
time = new Date().getTime(),
performance = [],
query = arguments[0],
methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
query = arguments[0],
methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse
;
@ -41,7 +42,6 @@ $.fn.dropdown = function(parameters) {
eventNamespace = '.' + namespace,
moduleNamespace = 'module-' + namespace,
isTouchDevice = ('ontouchstart' in document.documentElement),
$module = $(this),
$item = $module.find(selector.item),
@ -60,35 +60,19 @@ $.fn.dropdown = function(parameters) {
initialize: function() {
module.debug('Initializing dropdown', settings);
if(isTouchDevice) {
$module
.on('touchstart' + eventNamespace, module.event.test.toggle)
;
}
else if(settings.on == 'click') {
$module
.on('click' + eventNamespace, module.event.test.toggle)
;
}
else if(settings.on == 'hover') {
$module
.on('mouseenter' + eventNamespace, module.delay.show)
.on('mouseleave' + eventNamespace, module.delay.hide)
;
}
else {
$module
.on(settings.on + eventNamespace, module.toggle)
;
}
if(settings.action == 'updateForm') {
module.set.selected();
module.set.selected();
// no use detecting mouse events because touch devices emulate them
if(hasTouch) {
module.bind.touchEvents();
}
$item
.on('mouseenter' + eventNamespace, module.event.item.mouseenter)
.on('mouseleave' + eventNamespace, module.event.item.mouseleave)
.on(module.get.selectEvent() + eventNamespace, module.event.item.click)
module.bind.mouseEvents();
$document
.one('mousemove' + eventNamespace, module.set.hasMouse)
;
module.instantiate();
},
@ -111,13 +95,87 @@ $.fn.dropdown = function(parameters) {
;
},
event: {
bind: {
touchEvents: function() {
module.debug('Touch device detected binding touch events');
$module
.on('touchstart' + eventNamespace, module.event.test.toggle)
;
$item
.on('touchstart' + eventNamespace, module.event.item.mouseenter)
.on('touchstart' + eventNamespace, module.event.item.click)
;
},
mouseEvents: function() {
module.verbose('Mouse detected binding mouse events');
if(settings.on == 'click') {
$module
.on('click' + eventNamespace, module.event.test.toggle)
;
}
else if(settings.on == 'hover') {
$module
.on('mouseenter' + eventNamespace, module.delay.show)
.on('mouseleave' + eventNamespace, module.delay.hide)
;
}
else {
$module
.on(settings.on + eventNamespace, module.toggle)
;
}
$item
.on('mouseenter' + eventNamespace, module.event.item.mouseenter)
.on('mouseleave' + eventNamespace, module.event.item.mouseleave)
.on('click' + eventNamespace, module.event.item.click)
;
},
intent: function() {
module.verbose('Binding hide intent event to document');
if(hasTouch) {
$document
.on('touchstart' + eventNamespace, module.event.test.touch)
.on('touchmove' + eventNamespace, module.event.test.touch)
;
}
$document
.on('click' + eventNamespace, module.event.test.hide)
;
}
},
unbind: {
intent: function() {
module.verbose('Removing hide intent event from document');
if(hasTouch) {
$document
.off('touchstart' + eventNamespace)
;
}
$document
.off('click' + eventNamespace)
;
}
},
event: {
test: {
toggle: function(event) {
module.determine.intent(event, module.toggle);
event.preventDefault();
event.stopImmediatePropagation();
},
touch: function(event) {
module.determine.intent(event, function() {
if(event.type == 'touchstart') {
module.timer = setTimeout(module.hide, 50);
}
else if(event.type == 'touchmove') {
clearTimeout(module.timer);
}
});
event.stopPropagation();
},
hide: function(event) {
module.determine.intent(event, module.hide);
event.stopPropagation();
@ -138,6 +196,7 @@ $.fn.dropdown = function(parameters) {
module.verbose('Showing sub-menu', $currentMenu);
module.animate.show(false, $currentMenu);
}, settings.delay.show * 2);
event.preventDefault();
}
},
@ -170,6 +229,7 @@ $.fn.dropdown = function(parameters) {
;
module.determine.selectAction(text, value);
$.proxy(settings.onChange, element)(value, text);
event.preventDefault();
}
}
@ -219,24 +279,6 @@ $.fn.dropdown = function(parameters) {
}
},
bind: {
intent: function() {
module.verbose('Binding hide intent event to document');
$document
.on(module.get.selectEvent(), module.event.test.hide)
;
}
},
unbind: {
intent: function() {
module.verbose('Removing hide intent event from document');
$document
.off(module.get.selectEvent())
;
}
},
nothing: function() {},
changeText: function(text, value) {
@ -251,12 +293,6 @@ $.fn.dropdown = function(parameters) {
},
get: {
selectEvent: function() {
return (isTouchDevice)
? 'touchstart'
: 'click'
;
},
text: function() {
return $text.text();
},
@ -267,14 +303,25 @@ $.fn.dropdown = function(parameters) {
var
$selectedItem
;
value = value || $input.val();
$item
.each(function() {
if( $(this).data(metadata.value) == value ) {
$selectedItem = $(this);
}
})
;
value = value || module.get.value() || module.get.text();
if(value) {
$item
.each(function() {
var
$choice = $(this),
optionText = $choice.data(metadata.text) || $choice.text(),
optionValue = $choice.data(metadata.value) || optionText.toLowerCase()
;
if( optionValue == value || optionText == value ) {
$selectedItem = $(this);
return false;
}
})
;
}
else {
value = module.get.text();
}
return $selectedItem || false;
}
},
@ -343,7 +390,7 @@ $.fn.dropdown = function(parameters) {
can: {
click: function() {
return (isTouchDevice || settings.on == 'click');
return (hasTouch || settings.on == 'click');
},
show: function() {
return !$module.hasClass(className.disabled);
@ -722,8 +769,8 @@ $.fn.dropdown.settings = {
},
metadata: {
text : 'text',
value : 'value'
text : 'text',
value : 'value'
},
selector : {

11
src/modules/dropdown.less

@ -39,6 +39,10 @@
border-radius 0.1s ease,
width 0.2s ease
;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-moz-tap-highlight-color: rgba(0, 0, 0, 0);
tap-highlight-color: rgba(0, 0, 0, 0);
}
@ -179,6 +183,9 @@
.ui.vertical.menu .dropdown.item > .dropdown.icon {
content: "\f0da";
}
.ui.dropdown.icon.button > .dropdown.icon {
margin: 0em;
}
/*******************************
@ -205,6 +212,7 @@
box-shadow: none;
background-color: rgba(0, 0, 0, 0.04);
border-left: none;
border-color: transparent !important;
-webkit-box-shadow: none;
-moz-shadow: none;
@ -308,6 +316,9 @@
-moz-border-radius: 0.3125em !important;
border-radius: 0.3125em !important;
}
.ui.selection.dropdown select {
display: none;
}
.ui.selection.dropdown > .dropdown.icon {
float: right;

Loading…
Cancel
Save