define(function(require, exports, module) { 'use strict'; /** * Dependencies */ var debug = require('debug')('view:zoom-bar'); var View = require('view'); var bind = require('lib/bind'); var orientation = require('lib/orientation'); /** * Locals */ var lastTouch = null; var clamp = function(value, minimum, maximum) { return Math.min(Math.max(value, minimum), maximum); }; module.exports = View.extend({ name: 'zoom-bar', initialize: function() { this.render(); this._orientation = orientation.get(); // Amount (%) to adjust the Zoom Bar by when tapping the min/max indicators this.zoomBarIndicatorInterval = 10; // Amount of inactivity time (in milliseconds) to hide the Zoom Bar this.zoomBarInactivityTimeout = 3000; }, render: function() { this.el.innerHTML = this.template(); this.els.maxIndicator = this.find('.zoom-bar-max-indicator'); this.els.minIndicator = this.find('.zoom-bar-min-indicator'); this.els.inner = this.find('.zoom-bar-inner'); this.els.track = this.find('.zoom-bar-track'); this.els.scrubber = this.find('.zoom-bar-scrubber'); // Clean up delete this.template; debug('rendered'); return this.bindEvents(); }, bindEvents: function() { bind(this.els.scrubber, 'touchstart', this.onTouchStart); bind(this.els.scrubber, 'touchmove', this.onTouchMove); bind(this.els.scrubber, 'touchend', this.onTouchEnd); bind(this.els.maxIndicator, 'click', this.onIncrement); bind(this.els.minIndicator, 'click', this.onDecrement); orientation.on('orientation', this.setOrientation); return this; }, template: function() { return '
' + '
' + '
' + '
' + '
' + '
'; }, onTouchStart: function(evt) { lastTouch = evt.touches[0]; this.resetInactivityTimeout(); this.setScrubberActive(true); this._innerHeight = this.els.inner.offsetHeight; evt.stopPropagation(); }, onTouchMove: function(evt) { if (!lastTouch) { return; } var touch = evt.touches[0]; var deltaX = lastTouch.pageX - touch.pageX; var deltaY = lastTouch.pageY - touch.pageY; var scale = 100 / this._innerHeight; deltaX *= scale; deltaY *= scale; switch (this._orientation) { case 0: this.setValue(this._value + deltaY, true); break; case 90: this.setValue(this._value + deltaX, true); break; case 180: this.setValue(this._value - deltaY, true); break; case 270: this.setValue(this._value - deltaX, true); break; } lastTouch = touch; }, onTouchEnd: function(evt) { if (!lastTouch) { return; } lastTouch = null; this.resetInactivityTimeout(); this.setScrubberActive(false); }, onIncrement: function(evt) { this.setValue(this._value + this.zoomBarIndicatorInterval, true); this.flashScrubberActive(); evt.stopPropagation(); }, onDecrement: function(evt) { this.setValue(this._value - this.zoomBarIndicatorInterval, true); this.flashScrubberActive(); evt.stopPropagation(); }, _orientation: 0, setOrientation: function(orientation) { var el = this.el; el.classList.remove('zooming'); // Force ZoomBar to hide *immediately* on orientation change window.requestAnimationFrame(function() { el.style.transitionDuration = '0ms'; window.requestAnimationFrame(function() { el.style.transitionDuration = ''; }); }); this._orientation = orientation; }, _value: 0, setValue: function(value, emitChange) { this.resetInactivityTimeout(); var lastValue = this._value; this._value = clamp(value, 0, 100); if (this._value === lastValue) { return; } if (this._value === 0) { this.els.minIndicator.classList.add('active'); } else { this.els.minIndicator.classList.remove('active'); } if (this._value === 100) { this.els.maxIndicator.classList.add('active'); } else { this.els.maxIndicator.classList.remove('active'); } var self = this; window.requestAnimationFrame(function() { self.els.track.style.top = (100 - self._value) + '%'; self.els.scrubber.style.bottom = self._value + '%'; }); if (emitChange) { this.emit('change', this._value); } }, setScrubberActive: function(active) { window.clearTimeout(this._scrubberTimeout); if (active) { this.els.scrubber.classList.add('active'); } else { this.els.scrubber.classList.remove('active'); } }, flashScrubberActive: function() { this.setScrubberActive(true); var self = this; this._scrubberTimeout = window.setTimeout(function() { self.setScrubberActive(false); }, 150); }, resetInactivityTimeout: function() { window.clearTimeout(this._inactivityTimeout); this.show(); var self = this; this._inactivityTimeout = window.setTimeout(function() { self.hide(); }, this.zoomBarInactivityTimeout); }, show: function() { this.el.classList.add('zooming'); }, hide: function() { this.el.classList.remove('zooming'); } }); });