diff --git a/src/rating/docs/demo.html b/src/rating/docs/demo.html new file mode 100644 index 0000000000..24c229d4d5 --- /dev/null +++ b/src/rating/docs/demo.html @@ -0,0 +1,10 @@ +
+ + +
+
Rate: {{rate}}  - Readonly is: {{isReadonly}}
+ +
+ + +
\ No newline at end of file diff --git a/src/rating/docs/demo.js b/src/rating/docs/demo.js new file mode 100644 index 0000000000..efb7a88f43 --- /dev/null +++ b/src/rating/docs/demo.js @@ -0,0 +1,4 @@ +var RatingDemoCtrl = function ($scope) { + $scope.rate = 7; + $scope.isReadonly = false; +}; diff --git a/src/rating/docs/readme.md b/src/rating/docs/readme.md new file mode 100644 index 0000000000..fbcdfb268c --- /dev/null +++ b/src/rating/docs/readme.md @@ -0,0 +1,3 @@ +Rating directive that will take care of visualising a star rating bar. + +It also provides optional attribute `max` to vary the number of stars and `readonly` attribute to diasble user's interaction. \ No newline at end of file diff --git a/src/rating/rating.js b/src/rating/rating.js new file mode 100644 index 0000000000..7d623e1782 --- /dev/null +++ b/src/rating/rating.js @@ -0,0 +1,53 @@ +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5 +}) + +.directive('rating', ['ratingConfig', '$parse', function(ratingConfig, $parse) { + return { + restrict: 'EA', + scope: { + value: '=' + }, + templateUrl: 'template/rating/rating.html', + replace: true, + link: function(scope, element, attrs) { + + var maxRange = angular.isDefined(attrs.max) ? scope.$eval(attrs.max) : ratingConfig.max; + + scope.range = []; + for (var i = 1; i <= maxRange; i++) { + scope.range.push(i); + } + + scope.rate = function(value) { + if ( ! scope.readonly ) { + scope.value = value; + } + }; + + scope.enter = function(value) { + if ( ! scope.readonly ) { + scope.val = value; + } + }; + + scope.reset = function() { + scope.val = angular.copy(scope.value); + }; + scope.reset(); + + scope.$watch('value', function(value) { + scope.val = value; + }); + + scope.readonly = false; + if (attrs.readonly) { + scope.$parent.$watch($parse(attrs.readonly), function(value) { + scope.readonly = !!value; + }); + } + } + }; +}]); \ No newline at end of file diff --git a/src/rating/test/rating.spec.js b/src/rating/test/rating.spec.js new file mode 100644 index 0000000000..4d289c04ef --- /dev/null +++ b/src/rating/test/rating.spec.js @@ -0,0 +1,128 @@ +describe('rating directive', function () { + var $rootScope, element; + beforeEach(module('ui.bootstrap.rating')); + beforeEach(module('template/rating/rating.html')); + beforeEach(inject(function(_$compile_, _$rootScope_) { + $compile = _$compile_; + $rootScope = _$rootScope_; + $rootScope.rate = 3; + element = $compile('')($rootScope); + $rootScope.$digest(); + })); + + function getState(stars) { + var state = []; + for (var i = 0, n = stars.length; i < n; i++) { + state.push( (stars.eq(i).hasClass('icon-star') && ! stars.eq(i).hasClass('icon-star-empty')) ); + } + return state; + } + + it('contains the default number of icons', function() { + expect(element.find('i').length).toBe(5); + }); + + it('initializes the default star icons as selected', function() { + var stars = element.find('i'); + expect(getState(stars)).toEqual([true, true, true, false, false]); + }); + + it('handles correcty the click event', function() { + var stars = element.find('i'); + + var star2 = stars.eq(1); + star2.click(); + $rootScope.$digest(); + expect(getState(stars)).toEqual([true, true, false, false, false]); + expect($rootScope.rate).toBe(2); + + var star5 = stars.eq(4); + star5.click(); + $rootScope.$digest(); + expect(getState(stars)).toEqual([true, true, true, true, true]); + expect($rootScope.rate).toBe(5); + }); + + it('handles correcty the hover event', function() { + var stars = element.find('i'); + + var star2 = stars.eq(1); + star2.trigger('mouseover'); + $rootScope.$digest(); + expect(getState(stars)).toEqual([true, true, false, false, false]); + expect($rootScope.rate).toBe(3); + + var star5 = stars.eq(4); + star5.trigger('mouseover'); + $rootScope.$digest(); + expect(getState(stars)).toEqual([true, true, true, true, true]); + expect($rootScope.rate).toBe(3); + + element.trigger('mouseout'); + expect(getState(stars)).toEqual([true, true, true, false, false]); + expect($rootScope.rate).toBe(3); + }); + + it('changes the number of selected icons when value changes', function() { + $rootScope.rate = 2; + $rootScope.$digest(); + + var stars = element.find('i'); + expect(getState(stars)).toEqual([true, true, false, false, false]); + }); + + it('shows different number of icons when `max` attribute is set', function() { + element = $compile('')($rootScope); + $rootScope.$digest(); + + expect(element.find('i').length).toBe(7); + }); + + it('handles readonly attribute', function() { + $rootScope.isReadonly = true; + element = $compile('')($rootScope); + $rootScope.$digest(); + + var stars = element.find('i'); + expect(getState(stars)).toEqual([true, true, true, false, false]); + + var star5 = stars.eq(4); + star5.trigger('mouseover'); + $rootScope.$digest(); + expect(getState(stars)).toEqual([true, true, true, false, false]); + + $rootScope.isReadonly = false; + $rootScope.$digest(); + + star5.trigger('mouseover'); + $rootScope.$digest(); + expect(getState(stars)).toEqual([true, true, true, true, true]); + }); + +}); + +describe('setting ratingConfig', function() { + var $rootScope, element; + var originalConfig = {}; + beforeEach(module('ui.bootstrap.rating')); + beforeEach(module('template/rating/rating.html')); + beforeEach(inject(function(_$compile_, _$rootScope_, ratingConfig) { + $compile = _$compile_; + $rootScope = _$rootScope_; + $rootScope.rate = 5; + angular.extend(originalConfig, ratingConfig); + ratingConfig.max = 10; + element = $compile('')($rootScope); + $rootScope.$digest(); + })); + afterEach(inject(function(ratingConfig) { + // return it to the original state + angular.extend(ratingConfig, originalConfig); + })); + + it('should change number of icon elements', function () { + expect(element.find('i').length).toBe(10); + }); + +}); + diff --git a/template/rating/rating.html b/template/rating/rating.html new file mode 100644 index 0000000000..df902ca3c1 --- /dev/null +++ b/template/rating/rating.html @@ -0,0 +1,3 @@ + + +