Permalink
Browse files

feat(select): add support for bootstrap-select

  • Loading branch information...
1 parent 00a084e commit ebf395e22fd7412278e401bb89afbedecc7924b3 @dancras dancras committed Mar 31, 2013
View
@@ -13,6 +13,7 @@
"jquery": ">= 1.8.0",
"bootstrap": ">= 2.2.0",
"bootstrap-datepicker": ">= 1.0.0",
- "bootstrap-timepicker": ">= 0.2.2"
+ "bootstrap-timepicker": ">= 0.2.2",
+ "bootstrap-select": "latest"
}
}
View
@@ -0,0 +1,38 @@
+
+angular.module('$strap.directives')
+
+.directive('bsSelect', function() {
+ 'use strict';
+
+ return {
+
+ scope: true,
+
+ link: function (scope, element, attrs) {
+
+ var previousClasses = element.attr('class');
+
+ var syncClasses = function () {
+ var currentClasses = element.attr('class');
+ element.next().removeClass(previousClasses).addClass(currentClasses).removeClass('ng-scope');
+ previousClasses = element.attr('class');
+ };
+
+ // Watch for changes to the length of our select element
+ scope.$watch(function () {
+ return element[0].length;
+ }, function () {
+ element.selectpicker('render');
+ });
+
+ // Watch for changes to the model value
+ scope.$watch(attrs.ngModel, function () {
+ element.selectpicker('render');
+ syncClasses();
+ });
+
+ }
+
+ };
+
+});
View
@@ -18,6 +18,7 @@ files = [
'vendor/bootstrap-datepicker.js',
//'vendor/bootstrap-datepicker.fr.js',
'vendor/bootstrap-timepicker.js',
+ 'vendor/bootstrap-select.js',
'src/common.js',
'src/directives/*.js',
'test/unit/directives/*Spec.js'
@@ -0,0 +1,120 @@
+'use strict';
+
+describe('select directive', function () {
+
+ var fixture;
+ var element;
+ var currentScope;
+ var bootstrapSelect;
+ var menu;
+
+ beforeEach(module('$strap.directives'));
+
+ beforeEach(function () {
+ var body = angular.element('body');
+ fixture = angular.element('<div></div>');
+ fixture.appendTo(body);
+ });
+
+ afterEach(function () {
+ fixture.remove();
+ });
+
+ beforeEach(inject(function ($compile, $rootScope) {
+
+ element = angular.element('<select bs-select ng-model="model.item" ng-options="i.id as i.name for i in items"></select>');
+ element.appendTo(fixture);
+
+ currentScope = $rootScope;
+
+ $rootScope.model = {
+ item: 2
+ };
+
+ $rootScope.items = [
+ {
+ id: 1,
+ name: 'item 1'
+ },
+ {
+ id: 2,
+ name: 'item 2'
+ }
+ ];
+
+ $compile(element)($rootScope, false);
+ $rootScope.$digest();
+
+ bootstrapSelect = element.siblings('.bootstrap-select');
+ menu = bootstrapSelect.find('ul[role=menu]');
+
+ }));
+
+ it('initialises bootstrap select on the element', function () {
+ expect(bootstrapSelect.length).toBe(1);
+ });
+
+ it('adds every item to the bootstrap select menu', function () {
+ expect(menu.children().length).toBe(2);
+ });
+
+ it('updates the bootstrap select menu when items are changed', function () {
+
+ currentScope.items.push({
+ id: 3,
+ name: 'item 3'
+ });
+ currentScope.$apply();
+
+ expect(menu.children().length).toBe(3);
+ });
+
+ it('selects the correct item by default', function () {
+ expect(menu.find('.selected').text()).toBe('item 2');
+ });
+
+ it('updates the scope when a new item is selected', function () {
+
+ menu.find('li a').first().click();
+
+ expect(currentScope.model.item).toBe(1);
+ });
+
+ it('updates bootstrap select when the model changes', function () {
+
+ currentScope.model.item = 1;
+ currentScope.$apply();
+
+ expect(menu.find('.selected').text()).toBe('item 1');
+ });
+
+ it('does not add ng-scope class to bootstrap select element', function () {
+ expect(bootstrapSelect.hasClass('ng-scope')).toBe(false);
+ });
+
+ it('adds new classes from original element when the model changes', function () {
+
+ element.addClass('dummy');
+
+ currentScope.model.item = 1;
+ currentScope.$apply();
+
+ expect(bootstrapSelect.hasClass('dummy')).toBe(true);
+ });
+
+ it('syncs classes removed from original element when the model changes', function () {
+
+ element.addClass('dummy');
+
+ currentScope.model.item = 1;
+ currentScope.$apply();
+
+ element.removeClass('dummy');
+
+ currentScope.model.item = 2;
+ currentScope.$apply();
+
+ expect(bootstrapSelect.hasClass('dummy')).toBe(false);
+ });
+
+});
View
@@ -0,0 +1,156 @@
+.clearfix:after {
+ visibility: hidden;
+ display: block;
+ font-size: 0;
+ content: " ";
+ clear: both;
+ height: 0;
+}
+
+.bootstrap-select.btn-group, .bootstrap-select.btn-group[class*="span"] {
+ float:none;
+ display: inline-block;
+ margin-bottom: 10px;
+ margin-left:0;
+}
+
+.input-append .bootstrap-select.btn-group {
+ margin-left: -1px;
+}
+
+.input-prepend .bootstrap-select.btn-group {
+ margin-right: -1px;
+}
+
+.bootstrap-select {
+ width: 220px;
+}
+
+.bootstrap-select .btn {
+ width: 100%;
+}
+
+.bootstrap-select .btn:focus {
+ outline: thin dotted #333333 !important;
+ outline: 5px auto -webkit-focus-ring-color !important;
+ outline-offset: -2px;
+}
+
+.bootstrap-select.btn-group .btn .filter-option {
+ overflow:hidden;
+ position:absolute;
+ left:12px;
+ right:25px;
+ text-align:left;
+}
+
+.bootstrap-select.btn-group .btn .caret {
+ position:absolute;
+ right:12px;
+}
+
+.bootstrap-select.btn-group > .disabled, .bootstrap-select.btn-group .dropdown-menu li.disabled > a {
+ cursor: not-allowed;
+}
+
+.bootstrap-select.btn-group[class*="span"] .btn {
+ width:100%;
+}
+
+.bootstrap-select.btn-group .dropdown-menu {
+ min-width:100%;
+ -moz-box-sizing:border-box;
+ -webkit-box-sizing:border-box;
+ box-sizing:border-box;
+}
+
+.bootstrap-select.btn-group .dropdown-menu dt {
+ display:block;
+ padding:3px 20px;
+ cursor:default;
+}
+
+.bootstrap-select.btn-group .div-contain {
+ overflow:hidden;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li > a.opt {
+ padding-left:35px;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li > a {
+ min-height:20px;
+}
+
+bootstrap-select.btn-group .dropdown-menu li > a {
+ min-height:20px;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li small {
+ padding-left:0.5em;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li:not(.disabled) > a:hover small {
+ color: #64b1d8;
+ color:rgba(255,255,255,0.4);
+}
+
+.bootstrap-select.btn-group .dropdown-menu li > dt small {
+ font-weight:normal;
+}
+
+
+.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a i.check-mark {
+ display:inline-block;
+ position: absolute;
+ right: 20px;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li a i.check-mark {
+ display: none;
+}
+
+.bootstrap-select.btn-group.show-tick .dropdown-menu li a .pull-left {
+ margin-right: 34px;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li small {
+ padding-left:0.5em;
+}
+
+.bootstrap-select.btn-group .dropdown-menu li:not(.disabled) > a:hover small, .bootstrap-select.btn-group .dropdown-menu li:not(.disabled) > a:focus small {
+ color: #64b1d8;
+ color:rgba(255,255,255,0.4);
+}
+
+.bootstrap-select.btn-group .dropdown-menu li > dt small {
+ font-weight:normal;
+}
+
+
+.bootstrap-select.btn-group.show-menu-arrow .dropdown-menu {
+ overflow-y:visible !important;
+}
+
+.bootstrap-select.btn-group.show-menu-arrow .dropdown-menu::after {
+ position: absolute;
+ top: -6px;
+ left: 10px;
+ display: inline-block;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid white;
+ border-left: 6px solid transparent;
+ content: '';
+}
+
+.bootstrap-select.btn-group.show-menu-arrow .dropdown-menu::before {
+ position: absolute;
+ top: -7px;
+ left: 9px;
+ display: inline-block;
+ border-right: 7px solid transparent;
+ border-bottom: 7px solid #CCC;
+ border-left: 7px solid transparent;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ content: '';
+}
Oops, something went wrong.

0 comments on commit ebf395e

Please sign in to comment.