Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions src/rating/docs/demo.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
<div ng-controller="RatingDemoCtrl">
<h4>Default</h4>
<rating value="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>

<button class="button small alert" ng-click="rate = 0" ng-disabled="isReadonly">Clear</button>
<button class="button small" ng-click="isReadonly = ! isReadonly">Toggle Readonly</button>
<button type="button" class="button small alert" ng-click="rate = 0" ng-disabled="isReadonly">Clear</button>
<button type="button" class="button small" ng-click="isReadonly = ! isReadonly">Toggle Readonly</button>
<hr />

<h4>Custom icons</h4>
<div ng-init="x = 5">
<rating value="x" max="15" state-on="'fa-check-circle'" state-off="'fa-check-circle-o'"></rating>
<b>(<i>Rate:</i> {{x}})</b>
</div>
<div ng-init="y = 2">
<rating value="y" rating-states="ratingStates"></rating>
<b>(<i>Rate:</i> {{y}})</b>
</div>
<div ng-init="x = 5"><rating ng-model="x" max="15" state-on="'fa-check-circle'" state-off="'fa-check-circle-o'"></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>
8 changes: 6 additions & 2 deletions src/rating/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ It uses Font Awesome icons (http://fontawesome.io/) by default.

#### `<rating>` ####

* `value` <i class="fa fa-eye"></i>
* `ng-model` <i class="fa fa-eye"></i>
:
The current rate.

* `max`
_(Defaults: 5)_ :
Changes the number of icons.

* `readonly`
* `readonly` <i class="fa fa-eye"></i>
_(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
88 changes: 58 additions & 30 deletions src/rating/rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,70 +3,98 @@ angular.module('mm.foundation.rating', [])
.constant('ratingConfig', {
max: 5,
stateOn: null,
stateOff: null
stateOff: null,
titles : ['one', 'two', 'three', 'four', 'five']
})

.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) {
.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) {
var ngModelCtrl = { $setViewValue: angular.noop };

this.init = function(ngModelCtrl_) {
ngModelCtrl = ngModelCtrl_;
ngModelCtrl.$render = this.render;

ngModelCtrl.$formatters.push(function(value) {
if (angular.isNumber(value) && value << 0 !== value) {
value = Math.round(value);
}
return value;
});

this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max;
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;

this.createRateObjects = function(states) {
var defaultOptions = {
stateOn: this.stateOn,
stateOff: this.stateOff
};
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);
};

for (var i = 0, n = states.length; i < n; i++) {
states[i] = angular.extend({ index: i }, defaultOptions, states[i]);
}
return states;
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, title: this.getTitle(i) }, states[i]);
}
return states;
};

// Get objects used in template
$scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange));
this.getTitle = function(index) {
if (index >= this.titles.length) {
return index + 1;
} else {
return this.titles[index];
}
};

$scope.rate = function(value) {
if ( $scope.value !== value && !$scope.readonly ) {
$scope.value = value;
if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {
ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value);
ngModelCtrl.$render();
}
};

$scope.enter = function(value) {
if ( ! $scope.readonly ) {
$scope.val = value;
if (!$scope.readonly) {
$scope.value = value;
}
$scope.onHover({value: value});
};

$scope.reset = function() {
$scope.val = angular.copy($scope.value);
$scope.value = ngModelCtrl.$viewValue;
$scope.onLeave();
};

$scope.$watch('value', function(value) {
$scope.val = value;
});
$scope.onKeydown = function(evt) {
if (/(37|38|39|40)/.test(evt.which)) {
evt.preventDefault();
evt.stopPropagation();
$scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));
}
};

$scope.readonly = false;
if ($attrs.readonly) {
$scope.$parent.$watch($parse($attrs.readonly), function(value) {
$scope.readonly = !!value;
});
}
this.render = function() {
$scope.value = ngModelCtrl.$viewValue;
};
}])

.directive('rating', function() {
return {
restrict: 'EA',
require: ['rating', 'ngModel'],
scope: {
value: '=',
readonly: '=?',
onHover: '&',
onLeave: '&'
},
controller: 'RatingController',
templateUrl: 'template/rating/rating.html',
replace: true
replace: true,
link: function(scope, element, attrs, ctrls) {
var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
ratingCtrl.init( ngModelCtrl );
}
};
});
Loading