Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(rating): add title support for stars
Browse files Browse the repository at this point in the history
- Add support for adding titles to stars

Closes #3621
  • Loading branch information
lepit31 authored and wesleycho committed Jul 31, 2015
1 parent a69f66f commit 713c848
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 9 deletions.
4 changes: 2 additions & 2 deletions src/rating/docs/demo.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div ng-controller="RatingDemoCtrl">
<h4>Default</h4>
<rating ng-model="rate" max="max" readonly="isReadonly" on-hover="hoveringOver(value)" on-leave="overStar = null"></rating>
<rating ng-model="rate" max="max" readonly="isReadonly" on-hover="hoveringOver(value)" on-leave="overStar = null" titles="['one','two','three']" ></rating>
<span class="label" ng-class="{'label-warning': percent<30, 'label-info': percent>=30 && percent<70, 'label-success': percent>=70}" ng-show="overStar && !isReadonly">{{percent}}%</span>

<pre style="margin:15px 0;">Rate: <b>{{rate}}</b> - Readonly is: <i>{{isReadonly}}</i> - Hovering over: <b>{{overStar || "none"}}</b></pre>
Expand All @@ -12,4 +12,4 @@ <h4>Default</h4>
<h4>Custom icons</h4>
<div ng-init="x = 5"><rating ng-model="x" max="15" state-on="'glyphicon-ok-sign'" state-off="'glyphicon-ok-circle'"></rating> <b>(<i>Rate:</i> {{x}})</b></div>
<div ng-init="y = 2"><rating ng-model="y" rating-states="ratingStates"></rating> <b>(<i>Rate:</i> {{y}})</b></div>
</div>
</div>
4 changes: 4 additions & 0 deletions src/rating/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Rating directive that will take care of visualising a star rating bar.
_(Defaults: false)_ :
Prevent user's interaction.

* `titles`
_(Defaults: ["one", "two", "three", "four", "five"])_ :
An array of Strings defining titles for all icons

* `on-hover(value)`
:
An optional expression called when user's mouse is over a particular icon.
Expand Down
22 changes: 17 additions & 5 deletions src/rating/rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ angular.module('ui.bootstrap.rating', [])
.constant('ratingConfig', {
max: 5,
stateOn: null,
stateOff: null
stateOff: null,
titles : ['one', 'two', 'three', 'four', 'five']
})

.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) {
Expand All @@ -22,19 +23,30 @@ angular.module('ui.bootstrap.rating', [])

this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;
this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;

var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles ;
this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?
tmpTitles : ratingConfig.titles;

var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) :
new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max );
$scope.range = this.buildTemplateObjects(ratingStates);
};

this.buildTemplateObjects = function(states) {
for (var i = 0, n = states.length; i < n; i++) {
states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]);
states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);
}
return states;
};


this.getTitle = function(index) {
if (index >= this.titles.length) {
return index + 1;
} else {
return this.titles[index];
}
};

$scope.rate = function(value) {
if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) {
ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value);
Expand Down Expand Up @@ -84,4 +96,4 @@ angular.module('ui.bootstrap.rating', [])
ratingCtrl.init( ngModelCtrl );
}
};
});
});
53 changes: 53 additions & 0 deletions src/rating/test/rating.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ describe('rating directive', function () {
return state;
}

function getTitles() {
var stars = getStars();
return stars.toArray().map(function(star) {
return angular.element(star).attr('title');
});
}

function triggerKeyDown(keyCode) {
var e = $.Event('keydown');
e.which = keyCode;
Expand Down Expand Up @@ -273,4 +280,50 @@ describe('rating directive', function () {
expect(getState('on', 'off')).toEqual([true, true, true, true, true, false, false, false, false, false]);
});
});

describe('Default title', function() {
it('should return the default title for each star', function() {
expect(getTitles()).toEqual(['one', 'two', 'three', 'four', 'five']);
});
});

describe('shows different title when `max` attribute is greater than the titles array ', function() {
var originalConfig = {};
beforeEach(inject(function(ratingConfig) {
$rootScope.rate = 5;
angular.extend(originalConfig, ratingConfig);
ratingConfig.max = 10;
element = $compile('<rating ng-model="rate"></rating>')($rootScope);
$rootScope.$digest();
}));
afterEach(inject(function(ratingConfig) {
// return it to the original state
angular.extend(ratingConfig, originalConfig);
}));

it('should return the default title for each star', function() {
expect(getTitles()).toEqual(['one', 'two', 'three', 'four', 'five', '6', '7', '8', '9', '10']);
});
});

describe('shows custom titles ', function() {
it('should return the custom title for each star', function() {
$rootScope.titles = [44,45,46];
element = $compile('<rating ng-model="rate" titles="titles"></rating>')($rootScope);
$rootScope.$digest();
expect(getTitles()).toEqual(['44', '45', '46', '4', '5']);
});
it('should return the default title if the custom title is empty', function() {
$rootScope.titles = [];
element = $compile('<rating ng-model="rate" titles="titles"></rating>')($rootScope);
$rootScope.$digest();
expect(getTitles()).toEqual(['one', 'two', 'three', 'four', 'five']);
});
it('should return the default title if the custom title is not an array', function() {
element = $compile('<rating ng-model="rate" titles="test"></rating>')($rootScope);
$rootScope.$digest();
expect(getTitles()).toEqual(['one', 'two', 'three', 'four', 'five']);
});
});

});
4 changes: 2 additions & 2 deletions template/rating/rating.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">
<i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')">
<i ng-repeat="r in range track by $index" ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')" ng-attr-title="{{r.title}}" >
<span class="sr-only">({{ $index < value ? '*' : ' ' }})</span>
</i>
</span>
</span>

0 comments on commit 713c848

Please sign in to comment.