123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- // Copyright 2006 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview Implementation of a progress bar.
- *
- * @author arv@google.com (Erik Arvidsson)
- * @see ../demos/progressbar.html
- */
- goog.provide('goog.ui.ProgressBar');
- goog.provide('goog.ui.ProgressBar.Orientation');
- goog.require('goog.a11y.aria');
- goog.require('goog.asserts');
- goog.require('goog.dom');
- goog.require('goog.dom.TagName');
- goog.require('goog.dom.classlist');
- goog.require('goog.events');
- goog.require('goog.events.EventType');
- goog.require('goog.ui.Component');
- goog.require('goog.ui.RangeModel');
- goog.require('goog.userAgent');
- /**
- * This creates a progress bar object.
- * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
- * @constructor
- * @extends {goog.ui.Component}
- */
- goog.ui.ProgressBar = function(opt_domHelper) {
- goog.ui.Component.call(this, opt_domHelper);
- /** @type {?HTMLDivElement} */
- this.thumbElement_;
- /**
- * The underlying data model for the progress bar.
- * @type {goog.ui.RangeModel}
- * @private
- */
- this.rangeModel_ = new goog.ui.RangeModel;
- goog.events.listen(
- this.rangeModel_, goog.ui.Component.EventType.CHANGE, this.handleChange_,
- false, this);
- };
- goog.inherits(goog.ui.ProgressBar, goog.ui.Component);
- goog.tagUnsealableClass(goog.ui.ProgressBar);
- /**
- * Enum for representing the orientation of the progress bar.
- *
- * @enum {string}
- */
- goog.ui.ProgressBar.Orientation = {
- VERTICAL: 'vertical',
- HORIZONTAL: 'horizontal'
- };
- /**
- * Map from progress bar orientation to CSS class names.
- * @type {!Object<string, string>}
- * @private
- */
- goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_ = {};
- goog.ui.ProgressBar
- .ORIENTATION_TO_CSS_NAME_[goog.ui.ProgressBar.Orientation.VERTICAL] =
- goog.getCssName('progress-bar-vertical');
- goog.ui.ProgressBar
- .ORIENTATION_TO_CSS_NAME_[goog.ui.ProgressBar.Orientation.HORIZONTAL] =
- goog.getCssName('progress-bar-horizontal');
- /**
- * Creates the DOM nodes needed for the progress bar
- * @override
- */
- goog.ui.ProgressBar.prototype.createDom = function() {
- this.thumbElement_ = this.createThumb_();
- this.setElementInternal(this.getDomHelper().createDom(
- goog.dom.TagName.DIV,
- goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[this.orientation_],
- this.thumbElement_));
- this.setValueState_();
- this.setMinimumState_();
- this.setMaximumState_();
- };
- /** @override */
- goog.ui.ProgressBar.prototype.enterDocument = function() {
- goog.ui.ProgressBar.superClass_.enterDocument.call(this);
- this.attachEvents_();
- this.updateUi_();
- var element = this.getElement();
- goog.asserts.assert(element, 'The progress bar DOM element cannot be null.');
- // state live = polite will notify the user of updates,
- // but will not interrupt ongoing feedback
- goog.a11y.aria.setRole(element, 'progressbar');
- goog.a11y.aria.setState(element, 'live', 'polite');
- };
- /** @override */
- goog.ui.ProgressBar.prototype.exitDocument = function() {
- goog.ui.ProgressBar.superClass_.exitDocument.call(this);
- this.detachEvents_();
- };
- /**
- * This creates the thumb element.
- * @private
- * @return {HTMLDivElement} The created thumb element.
- */
- goog.ui.ProgressBar.prototype.createThumb_ = function() {
- return this.getDomHelper().createDom(
- goog.dom.TagName.DIV, goog.getCssName('progress-bar-thumb'));
- };
- /**
- * Adds the initial event listeners to the element.
- * @private
- */
- goog.ui.ProgressBar.prototype.attachEvents_ = function() {
- if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
- goog.events.listen(
- this.getElement(), goog.events.EventType.RESIZE, this.updateUi_, false,
- this);
- }
- };
- /**
- * Removes the event listeners added by attachEvents_.
- * @private
- */
- goog.ui.ProgressBar.prototype.detachEvents_ = function() {
- if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
- goog.events.unlisten(
- this.getElement(), goog.events.EventType.RESIZE, this.updateUi_, false,
- this);
- }
- };
- /**
- * Decorates an existing HTML DIV element as a progress bar input. If the
- * element contains a child with a class name of 'progress-bar-thumb' that will
- * be used as the thumb.
- * @param {Element} element The HTML element to decorate.
- * @override
- */
- goog.ui.ProgressBar.prototype.decorateInternal = function(element) {
- goog.ui.ProgressBar.superClass_.decorateInternal.call(this, element);
- goog.dom.classlist.add(
- goog.asserts.assert(this.getElement()),
- goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[this.orientation_]);
- // find thumb
- var thumb = goog.dom.getElementsByTagNameAndClass(
- null, goog.getCssName('progress-bar-thumb'), this.getElement())[0];
- if (!thumb) {
- thumb = this.createThumb_();
- this.getElement().appendChild(thumb);
- }
- this.thumbElement_ = /** @type {!HTMLDivElement} */ (thumb);
- };
- /**
- * @return {number} The value.
- */
- goog.ui.ProgressBar.prototype.getValue = function() {
- return this.rangeModel_.getValue();
- };
- /**
- * Sets the value
- * @param {number} v The value.
- */
- goog.ui.ProgressBar.prototype.setValue = function(v) {
- this.rangeModel_.setValue(v);
- if (this.getElement()) {
- this.setValueState_();
- }
- };
- /**
- * Sets the state for a11y of the current value.
- * @private
- */
- goog.ui.ProgressBar.prototype.setValueState_ = function() {
- var element = this.getElement();
- goog.asserts.assert(element, 'The progress bar DOM element cannot be null.');
- goog.a11y.aria.setState(element, 'valuenow', this.getValue());
- };
- /**
- * @return {number} The minimum value.
- */
- goog.ui.ProgressBar.prototype.getMinimum = function() {
- return this.rangeModel_.getMinimum();
- };
- /**
- * Sets the minimum number
- * @param {number} v The minimum value.
- */
- goog.ui.ProgressBar.prototype.setMinimum = function(v) {
- this.rangeModel_.setMinimum(v);
- if (this.getElement()) {
- this.setMinimumState_();
- }
- };
- /**
- * Sets the state for a11y of the minimum value.
- * @private
- */
- goog.ui.ProgressBar.prototype.setMinimumState_ = function() {
- var element = this.getElement();
- goog.asserts.assert(element, 'The progress bar DOM element cannot be null.');
- goog.a11y.aria.setState(element, 'valuemin', this.getMinimum());
- };
- /**
- * @return {number} The maximum value.
- */
- goog.ui.ProgressBar.prototype.getMaximum = function() {
- return this.rangeModel_.getMaximum();
- };
- /**
- * Sets the maximum number
- * @param {number} v The maximum value.
- */
- goog.ui.ProgressBar.prototype.setMaximum = function(v) {
- this.rangeModel_.setMaximum(v);
- if (this.getElement()) {
- this.setMaximumState_();
- }
- };
- /**
- * Sets the state for a11y of the maximum valiue.
- * @private
- */
- goog.ui.ProgressBar.prototype.setMaximumState_ = function() {
- var element = this.getElement();
- goog.asserts.assert(element, 'The progress bar DOM element cannot be null.');
- goog.a11y.aria.setState(element, 'valuemax', this.getMaximum());
- };
- /**
- *
- * @type {goog.ui.ProgressBar.Orientation}
- * @private
- */
- goog.ui.ProgressBar.prototype.orientation_ =
- goog.ui.ProgressBar.Orientation.HORIZONTAL;
- /**
- * Call back when the internal range model changes
- * @param {goog.events.Event} e The event object.
- * @private
- */
- goog.ui.ProgressBar.prototype.handleChange_ = function(e) {
- this.updateUi_();
- this.dispatchEvent(goog.ui.Component.EventType.CHANGE);
- };
- /**
- * This is called when we need to update the size of the thumb. This happens
- * when first created as well as when the value and the orientation changes.
- * @private
- */
- goog.ui.ProgressBar.prototype.updateUi_ = function() {
- if (this.thumbElement_) {
- var min = this.getMinimum();
- var max = this.getMaximum();
- var val = this.getValue();
- var ratio = (val - min) / (max - min);
- var size = Math.round(ratio * 100);
- if (this.orientation_ == goog.ui.ProgressBar.Orientation.VERTICAL) {
- // Note(arv): IE up to version 6 has some serious computation bugs when
- // using percentages or bottom. We therefore first set the height to
- // 100% and measure that and base the top and height on that size instead.
- if (goog.userAgent.IE && goog.userAgent.VERSION < 7) {
- this.thumbElement_.style.top = '0';
- this.thumbElement_.style.height = '100%';
- var h = this.thumbElement_.offsetHeight;
- var bottom = Math.round(ratio * h);
- this.thumbElement_.style.top = h - bottom + 'px';
- this.thumbElement_.style.height = bottom + 'px';
- } else {
- this.thumbElement_.style.top = (100 - size) + '%';
- this.thumbElement_.style.height = size + '%';
- }
- } else {
- this.thumbElement_.style.width = size + '%';
- }
- }
- };
- /**
- * This is called when we need to setup the UI sizes and positions. This
- * happens when we create the element and when we change the orientation.
- * @private
- */
- goog.ui.ProgressBar.prototype.initializeUi_ = function() {
- var tStyle = this.thumbElement_.style;
- if (this.orientation_ == goog.ui.ProgressBar.Orientation.VERTICAL) {
- tStyle.left = '0';
- tStyle.width = '100%';
- } else {
- tStyle.top = tStyle.left = '0';
- tStyle.height = '100%';
- }
- };
- /**
- * Changes the orientation
- * @param {goog.ui.ProgressBar.Orientation} orient The orientation.
- */
- goog.ui.ProgressBar.prototype.setOrientation = function(orient) {
- if (this.orientation_ != orient) {
- var oldCss =
- goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[this.orientation_];
- var newCss = goog.ui.ProgressBar.ORIENTATION_TO_CSS_NAME_[orient];
- this.orientation_ = orient;
- // Update the DOM
- var element = this.getElement();
- if (element) {
- goog.dom.classlist.swap(element, oldCss, newCss);
- this.initializeUi_();
- this.updateUi_();
- }
- }
- };
- /**
- * @return {goog.ui.ProgressBar.Orientation} The orientation of the
- * progress bar.
- */
- goog.ui.ProgressBar.prototype.getOrientation = function() {
- return this.orientation_;
- };
- /** @override */
- goog.ui.ProgressBar.prototype.disposeInternal = function() {
- this.detachEvents_();
- goog.ui.ProgressBar.superClass_.disposeInternal.call(this);
- this.thumbElement_ = null;
- this.rangeModel_.dispose();
- };
- /**
- * @return {?number} The step value used to determine how to round the value.
- */
- goog.ui.ProgressBar.prototype.getStep = function() {
- return this.rangeModel_.getStep();
- };
- /**
- * Sets the step value. The step value is used to determine how to round the
- * value.
- * @param {?number} step The step size.
- */
- goog.ui.ProgressBar.prototype.setStep = function(step) {
- this.rangeModel_.setStep(step);
- };
|