Rating Widget
I read an article comparing React vs Angular. I implemented the MVC design pattern in Javascript for this widget to show that there's lots of frameworks out there.
by Joey Guerra
HTML
<section>
<h1>Ratings</h1>
<h2>Clickable Rating<span id='clickable-rating'></span></h2>
<div id='fundooRating'>
<ul class='rating'>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
</ul>
</div>
<h2>Readonly rating</h2>
<div id='readonlyRating'>
<ul class='rating'>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
<li>★</li>
</ul>
</div>
</section>
CSS
.rating{
color: #a9a9a9;
margin: 0;
padding: 0;
}
ul.rating {
display: inline-block;
}
.rating li {
list-style-type: none;
display: inline-block;
padding: 1px;
text-align: center;
font-weight: bold;
cursor: pointer;
}
.rating .selected {
color: #21568b;
}
JavaScript
const makeKeyValueObservable = observable => {
let cached = Object.assign({}, observable)
let proxied = {}
let observers = {}
const everyKeyObservers = []
const changed = (key, old, value) => {
if(everyKeyObservers.length > 0) {
everyKeyObservers.forEach(o=>{
if(o.update) o.update(key, old, value)
else o(key, old, value)
})
}
if(!observers[key]) return
observers[key]?.forEach(o=>{
if(o.update) o.update(key, old, value)
else o(key, old, value)
})
}
const api = {
observe(key, observer){
if(typeof key == 'function') {
everyKeyObservers.push(key)
return
}
if(!observers[key]) observers[key] = []
observers[key].push(observer)
},
stopObserving(key, observer){
if(typeof key == 'function') {
const i = everyKeyObservers.findIndex(o => o === key)
if(i == -1) return
everyKeyObservers.splice(i, 1)
return
}
if(!observers[key]) return
const i = observers[key].findIndex(o => o === observer)
if(i == -1) return
observers[key].splice(i, 1)
},
release(){
console.log('observable releasing')
everyKeyObservers.length = 0
Object.keys(observers).forEach(key => {
observers[key].length = 0
})
}
}
const makeProxy = obj => {
let p = new Proxy(obj, {
get(target, prop, receiver){
return obj[prop]
},
set(target, prop, value){
if(undefined == target[prop] && Array.isArray(value)) {
value = new ObservableArray(...value)
} else if(undefined == target[prop] && typeof value == 'object') {
value = makeKeyValueObservable(value)
}
const old = obj[prop]
obj[prop] = value
...