|
| 1 | +var Meter = function (element) { |
| 2 | + this.rootEl = element; |
| 3 | + this.fillEl = element.querySelector('.fill'); |
| 4 | + |
| 5 | + // set up min, max, and current value |
| 6 | + var min = element.getAttribute('aria-valuemin'); |
| 7 | + var max = element.getAttribute('aria-valuemax'); |
| 8 | + var value = element.getAttribute('aria-valuenow'); |
| 9 | + this._update(parseFloat(min), parseFloat(max), parseFloat(value)); |
| 10 | +}; |
| 11 | + |
| 12 | +/* Private methods */ |
| 13 | + |
| 14 | +// returns a number representing a percentage between 0 - 100 |
| 15 | +Meter.prototype._calculatePercentFill = function (min, max, value) { |
| 16 | + if (typeof min !== 'number' || typeof max !== 'number' || typeof value !== 'number') { |
| 17 | + return 0; |
| 18 | + } |
| 19 | + |
| 20 | + return 100 * (value - min) / (max - min); |
| 21 | +}; |
| 22 | + |
| 23 | +// returns an hsl color string between red and green |
| 24 | +Meter.prototype._getColorValue = function (percent) { |
| 25 | + // red is 0deg, green is 120deg in hsl |
| 26 | + // if percent is 100, hue should be red, and if percent is 0, hue should be green |
| 27 | + var hue = (percent / 100) * (0 - 120) + 120; |
| 28 | + |
| 29 | + return 'hsl(' + hue + ', 100%, 40%)'; |
| 30 | +}; |
| 31 | + |
| 32 | +// no return value; updates the meter element |
| 33 | +Meter.prototype._update = function (min, max, value) { |
| 34 | + // update fill width |
| 35 | + if (min !== this.min || max !== this.max || value !== this.value) { |
| 36 | + var percentFill = this._calculatePercentFill(min, max, value); |
| 37 | + this.fillEl.style.width = percentFill + '%'; |
| 38 | + this.fillEl.style.color = this._getColorValue(percentFill); |
| 39 | + } |
| 40 | + |
| 41 | + // update aria attributes |
| 42 | + if (min !== this.min) { |
| 43 | + this.min = min; |
| 44 | + this.rootEl.setAttribute('aria-valuemin', min + ''); |
| 45 | + } |
| 46 | + |
| 47 | + if (max !== this.max) { |
| 48 | + this.max = max; |
| 49 | + this.rootEl.setAttribute('aria-valuemax', max + ''); |
| 50 | + } |
| 51 | + |
| 52 | + if (value !== this.value) { |
| 53 | + this.value = value; |
| 54 | + this.rootEl.setAttribute('aria-valuenow', value + ''); |
| 55 | + } |
| 56 | +}; |
| 57 | + |
| 58 | +/* Public methods */ |
| 59 | + |
| 60 | +// no return value; modifies the meter element based on a new value |
| 61 | +Meter.prototype.setValue = function (value) { |
| 62 | + if (typeof value !== 'number') { |
| 63 | + value = parseFloat(value); |
| 64 | + } |
| 65 | + |
| 66 | + if (!isNaN(value)) { |
| 67 | + this._update(this.min, this.max, value); |
| 68 | + } |
| 69 | +}; |
| 70 | + |
| 71 | +/* Code for example page */ |
| 72 | + |
| 73 | +window.addEventListener('load', function () { |
| 74 | + // helper function to randomize example meter value |
| 75 | + function getRandomValue (min, max) { |
| 76 | + var range = max - min; |
| 77 | + return Math.floor((Math.random() * range) + min); |
| 78 | + } |
| 79 | + |
| 80 | + // init meters |
| 81 | + var meterEls = document.querySelectorAll('[role=meter]'); |
| 82 | + var meters = []; |
| 83 | + Array.prototype.slice.call(meterEls).forEach(function (meterEl) { |
| 84 | + meters.push(new Meter(meterEl)); |
| 85 | + }); |
| 86 | + |
| 87 | + // randomly update meter values |
| 88 | + |
| 89 | + // returns an id for setInterval |
| 90 | + function playMeters () { |
| 91 | + return window.setInterval(function () { |
| 92 | + meters.forEach(function (meter) { |
| 93 | + meter.setValue(Math.random() * 100); |
| 94 | + }); |
| 95 | + }, 5000); |
| 96 | + } |
| 97 | + |
| 98 | + // start meters |
| 99 | + var updateInterval = playMeters(); |
| 100 | + |
| 101 | + // play/pause meter updates |
| 102 | + var playButton = document.querySelector('.play-meters'); |
| 103 | + playButton.addEventListener('click', function () { |
| 104 | + var isPaused = playButton.classList.contains('paused'); |
| 105 | + |
| 106 | + if (isPaused) { |
| 107 | + updateInterval = playMeters(); |
| 108 | + playButton.classList.remove('paused'); |
| 109 | + playButton.innerHTML = 'Pause Updates'; |
| 110 | + } |
| 111 | + else { |
| 112 | + clearInterval(updateInterval); |
| 113 | + playButton.classList.add('paused'); |
| 114 | + playButton.innerHTML = 'Start Updates'; |
| 115 | + } |
| 116 | + }); |
| 117 | +}); |
0 commit comments