Skip to content

Commit

Permalink
Super commit for SuperSelect
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlaCrandall committed Jan 16, 2015
1 parent 2c70e16 commit 9ed6988
Show file tree
Hide file tree
Showing 3 changed files with 366 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/superSelect.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!-- Super Select -->
<span ng-keydown="onKeydown( $event )" class="super-select">

<!-- Select -->
<select class="realSelect"
ng-keyup="onKeyup( $event )"
ng-focus="onSelectFocus()"
ng-model="selectModel"
ng-options="val as text for ( val, text ) in selectData">
</select>
<!-- End Select -->

<!-- Select -->
<select class="fakeSelect"
ng-model="fakeModel"
ng-options="val as text for ( val, text ) in selectData">
</select>
<!-- End Select -->

<!-- Bootstrap Dropdown -->
<div is-open="status.isOpen" class="btn-group dropdown-container" dropdown on-toggle="onOpen()">

<!-- Toggle -->
<span class="button-span">
<button type="button"
class="btn btn-primary dropdown-toggle"
dropdown-toggle
ng-disabled="disabled">
{{selectData[selectModel]}}
</button>
<span class="caret"></span>
</span>

<!-- End Toggle -->

<!-- Dropdown Menu -->
<ul class="dropdown-menu" role="menu">
<li class="search-option"
ng-repeat="(val, text) in selectData"
ng-attr-data-option="{{val}}"
ng-click="selectOption(val)">
<a href="#" ng-bind="text"></a>
</li>
</ul>
<!-- End Dropdown Menu -->

</div>
<!-- End Bootstrap Dropdown -->

</span>
<!-- End Super Select -->
252 changes: 252 additions & 0 deletions src/superSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
var superSelect = angular.module( 'superSelect', [] );

superSelect.directive( 'superSelect', function( ){
return {

restrict: 'A',
templateUrl: 'src/superSelect.html',
scope: {
selectData: '=',
selectModel: '=',
selectLabel: '@'
},
controller: [ '$scope', '$element', '$timeout', '$window',

function( $scope, $element, $timeout, $window ) {

$scope.fakeModel = '';

$scope.status = {
isOpen: false,
currentVal: null
}

var KeyCodes = {
BACKSPACE : 8,
TABKEY : 9,
RETURNKEY : 13,
ESCAPE : 27,
SPACEBAR : 32,
LEFTARROW : 37,
UPARROW : 38,
RIGHTARROW : 39,
DOWNARROW : 40,
},
menuContainer = angular.element( document.querySelector( '#superSelect_dropdownHolder' ) );


$scope.selectOption = function( val ) {
$scope.selectModel = val;
}

$scope.onKeyup = function( $event ) {

if( !$scope.status.isOpen ) {

$timeout( function () {
$element.find( 'button' )[0].focus();
} );
}
}

$scope.onKeydown = function( $event ) {

var e = $event,
nextTab;

switch ( e.keyCode ) {

case KeyCodes.TABKEY:

if( $scope.status.isOpen ) {

$event.preventDefault();
return;
}
break;

//Make sure the spacebar doesn't activate the select
case KeyCodes.SPACEBAR:
break;

case KeyCodes.ESCAPE:

$target.blur();
break;

case KeyCodes.UPARROW:

if( !$scope.status.isOpen ) {

$scope.status.isOpen = true;
$scope.status.currentVal = $scope.selectModel;

} else {

nextTab = - 1;
}
break;

case KeyCodes.RETURNKEY:

if( $scope.status.isOpen ) {

$timeout( function () {
$element.find( 'button' )[0].focus();
}, 100);
}
break;

case KeyCodes.DOWNARROW:

if( !$scope.status.isOpen ) {

$scope.status.isOpen = true;
$scope.status.currentVal = $scope.selectModel;

} else {

nextTab = 1;
}
break;

default:

if( !$scope.status.isOpen ) {

$element[0].querySelector( '.realSelect' ).focus();

}
else {

$element[0].querySelector( '.fakeSelect' ).focus();
}

break;
}

setFocus( nextTab );
}

$scope.onOpen = function() {
$scope.status.currentVal = $scope.selectModel;
if( $scope.fakeModel == '' ){
$scope.fakeModel = $scope.selectModel;
}

$timeout(function () {

var dropdownContainer = angular.element($element[0].querySelector( '.dropdown-container' ));


if( !$scope.status.isOpen ) {

var menu = menuContainer.children();
dropdownContainer.append( menu );
}
else {

var menu = angular.element($element[0].querySelectorAll( '.dropdown-menu' ));

var boundingRect = menu[0].getBoundingClientRect();

var isUp = isNearBottom( boundingRect );

if( isUp ) {

dropdownContainer.addClass( 'dropup' );

$timeout( function () {
setMenuPosition( menu[ 0 ] );
dropdownContainer.removeClass( 'dropup' );
});
}
else {

setMenuPosition( menu[ 0 ] );
}



}
});
}


menuContainer.on( 'keydown', $scope.onKeydown );

isNearBottom = function ( boundingRect ) {

var windowHeight = $window.innerHeight,
scrollTop = document.body.scrollTop;

if( boundingRect.bottom > windowHeight + scrollTop ) {
return true;
}

return false;
}

var setMenuPosition = function ( menu ) {
var boundingRect = menu.getBoundingClientRect();
menuContainer.append( menu );
menuContainer.css({
'top' : boundingRect.top + 'px',
'left' : boundingRect.left + 'px'
})

setFocus( 0 );
}


var setFocus = function( nextTab ) {

$timeout( function () {

var currentOption = $element[0].querySelector( '.fakeSelect option[value="' + $scope.status.currentVal + '"]' ),
next = null;

if( nextTab > 0 ) {

next = currentOption.nextSibling;
}
else if( nextTab < 0 ) {

next = currentOption.previousSibling;
}
else {

next = $element[0].querySelector( '.fakeSelect option[value="' + $element[0].querySelector( '.fakeSelect' ).value + '"]' );;
}

if( next ) {

$scope.fakeModel = $scope.status.currentVal = next.value;

var dropdownContainer = $element[0].querySelector( '.dropdown-container' ),
optString = '[data-option="' + $scope.status.currentVal + '"] a',
menuOption = menuContainer[0].querySelector( optString ) || dropdownContainer.querySelector( optString );

if ( menuOption ) {

menuOption.focus();
}

}

});

}


} ],

compile : function ( element, attrs ) {

if( !!attrs.selectLabel ) {

angular.element( element[0].querySelector( '.dropdown-menu' ) ).attr( 'aria-labelledby', attrs.selectLabel );
}
}
}
})
63 changes: 63 additions & 0 deletions styles/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
.super-select {
position: relative;
}

.super-select select {
position:absolute;
top:0;
right:100%;
opacity:0;
}

.super-select .dropdown-container {
display:inline-block
}

.super-select .dropdown-container.open .dropdown-toggle,
.super-select .dropdown-toggle,
.super-select .dropdown-toggle:hover,
.super-select .dropdown-toggle:focus {
background-color: #FFF;
border-radius: 0;
box-shadow: none;
font-size: 16px;
color: #232D31;
padding: 0;
}

.super-select .button-span {
background-color: #FFF;
border: 2px solid #CDD6D3;
border-radius: 2px;
padding: 6px;
}

.super-select .dropdown-toggle {
text-overflow: ellipsis;
width: 60px;
overflow: hidden;
border: none;
}


.super-select .dropdown-toggle .caret {
position: absolute;
right: 4px;
top: 55%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
}

.super-select .dropdown-toggle:focus {
border-color: #C5d9b0;
}

#superSelect_dropdownHolder {
position: absolute;
z-index: 9999999973;
}

#superSelect_dropdownHolder .dropdown-menu {
display: block;
position: static;
}

0 comments on commit 9ed6988

Please sign in to comment.