forked from barryclark/jekyll-now
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrating.js
More file actions
171 lines (152 loc) · 4.7 KB
/
rating.js
File metadata and controls
171 lines (152 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
(function() {
'use strict';
/**
* rating
*
* @description The rating component.
* @param {HTMLElement} el The HTMl element to build the rating widget on
* @param {Number} currentRating The current rating value
* @param {Number} maxRating The max rating for the widget
* @param {Function} callback The optional callback to run after set rating
* @return {Object} Some public methods
*/
function rating(el, currentRating, maxRating, callback) {
/**
* stars
*
* @description The collection of stars in the rating.
* @type {Array}
*/
var stars = [];
/**
* init
*
* @description Initializes the rating widget. Returns nothing.
*/
(function init() {
if (!el) { throw Error('No element supplied.'); }
if (!maxRating) { throw Error('No max rating supplied.'); }
if (!currentRating) { currentRating = 0; }
if (currentRating < 0 || currentRating > maxRating) { throw Error('Current rating is out of bounds.'); }
for (var i = 0; i < maxRating; i++) {
var star = document.createElement('li');
star.classList.add('c-rating__item');
star.setAttribute('data-index', i);
if (i < currentRating) { star.classList.add('is-active'); }
el.appendChild(star);
stars.push(star);
attachStarEvents(star);
}
})();
/**
* iterate
*
* @description A simple iterator used to loop over the stars collection.
* Returns nothing.
* @param {Array} collection The collection to be iterated
* @param {Function} callback The callback to run on items in the collection
*/
function iterate(collection, callback) {
for (var i = 0; i < collection.length; i++) {
var item = collection[i];
callback(item, i);
}
}
/**
* attachStarEvents
*
* @description Attaches events to each star in the collection. Returns
* nothing.
* @param {HTMLElement} star The star element
*/
function attachStarEvents(star) {
starMouseOver(star);
starMouseOut(star);
starClick(star);
}
/**
* starMouseOver
*
* @description The mouseover event for the star. Returns nothing.
* @param {HTMLElement} star The star element
*/
function starMouseOver(star) {
star.addEventListener('mouseover', function(e) {
iterate(stars, function(item, index) {
if (index <= parseInt(star.getAttribute('data-index'))) {
item.classList.add('is-active');
} else {
item.classList.remove('is-active');
}
});
});
}
/**
* starMouseOut
*
* @description The mouseout event for the star. Returns nothing.
* @param {HTMLElement} star The star element
*/
function starMouseOut(star) {
star.addEventListener('mouseout', function(e) {
if (stars.indexOf(e.relatedTarget) === -1) {
setRating(null, false);
}
});
}
/**
* starClick
*
* @description The click event for the star. Returns nothing.
* @param {HTMLElement} star The star element
*/
function starClick(star) {
star.addEventListener('click', function(e) {
e.preventDefault();
setRating(parseInt(star.getAttribute('data-index')) + 1, true);
});
}
/**
* setRating
*
* @description Sets and updates the currentRating of the widget, and runs
* the callback if supplied. Returns nothing.
* @param {Number} value The number to set the rating to
* @param {Boolean} doCallback A boolean to determine whether to run the
* callback or not
*/
function setRating(value, doCallback) {
if (value && value < 0 || value > maxRating) { return; }
if (doCallback === undefined) { doCallback = true; }
currentRating = value || currentRating;
iterate(stars, function(star, index) {
if (index < currentRating) {
star.classList.add('is-active');
} else {
star.classList.remove('is-active');
}
});
if (callback && doCallback) { callback(getRating()); }
}
/**
* getRating
*
* @description Gets the current rating.
* @return {Number} The current rating
*/
function getRating() {
return currentRating;
}
/**
* Returns the setRating and getRating methods
*/
return {
setRating: setRating,
getRating: getRating
};
}
/**
* Add to global namespace
*/
window.rating = rating;
})();