import Ember from 'ember'; import C from 'ui/utils/constants'; function clientX(event) { if ( typeof event.clientX !== 'undefined' ) { return event.clientX; } var orig = event.originalEvent; if ( orig ) { if ( typeof orig.clientX !== 'undefined' ) { return orig.clientX; } if ( orig.touches && orig.touches.length ) { return orig.touches[0].clientX; } } return 0; } export default Ember.Component.extend({ classNames: ['slider'], classNameBindings: ['disabled','active'], disabled: false, value: null, // Bind something to this to get the value valueMin: 0, // The smallest and biggest value is allowed to be valueMax: 100, scaleMin: null, // The smallest and biggest values shown on the display. If these are not equal to valueMin/max then there will be scaleMax: null, // a part of the slider that the user can't select, e.g. if you want to show 0 but have a minimum value of 1. step: 1, // Increment active: false, dragFn: null, upFn: null, didInsertElement: function() { this._super(); this.valueChanged(); }, willDestroyElement: function() { $('BODY').off('mousemove', this.get('dragFn')); $('BODY').off('mouseup', this.get('upFn')); }, _scaleMin: function() { var min = this.get('scaleMin'); if ( min === null ) { min = this.get('valueMin'); } return min; }.property('scaleMin','valueMin'), _scaleMax: function() { var min = this.get('scaleMax'); if ( min === null ) { min = this.get('valueMax'); } return min; }.property('scaleMax','valueMax'), percent: function() { var cur = this.get('value'); var min = Math.min(this.get('_scaleMin'), this.get('valueMin')); var max = Math.max(this.get('_scaleMax'), this.get('valueMax')); return (((cur-min)/(max-min))*100).toFixed(3); }.property('value','valueMin','valueMax','_scaleMin','_scaleMax'), alignValue: function(val) { var step = this.get('step'); var min = this.get('valueMin'); var max = this.get('valueMax'); // Subtract out the minimum so that modulus will work for // determining how close val is to a valid step val -= min; var diff = val % step; if ( diff >= step/2 ) { val = val - diff + step; } else if ( diff > 0 ) { val = val - diff; } // Add the minimum back in val += min; // Make sure the value is within range // (if `max` is not an increment of `step` it's your problem..) val = Math.max(min, Math.min(val, max)); return val; }, pointToValue: function(screenX) { var $elem = this.$(); var offset = $elem.offset(); var width = $elem.outerWidth(); var x = screenX - offset.left; var percent = Math.max(0, Math.min(x/width , 1)); var min = this.get('_scaleMin'); var max = this.get('_scaleMax'); var rawValue = min + (percent * (max-min)); var aligned = this.alignValue(rawValue); return aligned; }, click: function(event) { console.log('click',event); if ( this.get('disabled') ) { return false; } var value = this.pointToValue(clientX(event)); this.set('value', value); this.$('.slider-handle').focus(); }, mouseDown: function(event) { console.log('drag start'); if ( this.get('disabled') ) { return false; } this.set('active',true); if ( !this.get('dragFn') ) { this.set('dragFn', this.drag.bind(this)); } if ( !this.get('upFn') ) { this.set('upFn', this.mouseUp.bind(this)); } $('BODY').on('mousemove', this.get('dragFn')); $('BODY').on('mouseup', this.get('upFn')); this.drag(event); }, drag: function(event) { console.log('drag'); event.preventDefault(); if ( this.get('disabled') ) { return false; } var value = this.pointToValue(clientX(event)); console.log('drag', clientX(event), value); this.set('value', value); }, mouseUp: function(/*event*/) { $('BODY').off('mousemove', this.get('dragFn')); $('BODY').off('mouseup', this.get('upFn')); console.log('drag end'); this.set('active',false); }, keyDown: function(event) { var handled = false; switch ( event.which ) { case C.KEY_LEFT: this.decrementProperty('value', this.get('step')); handled = true; break; case C.KEY_RIGHT: this.incrementProperty('value', this.get('step')); handled = true; break; case C.KEY_UP: this.set('value', this.get('valueMax')); handled = true; break; case C.KEY_DOWN: this.set('value', this.get('valueMin')); handled = true; break; } if ( handled ) { event.preventDefault(); } }, valueChanged: function() { var orig = this.get('value'); var value = Math.max(this.get('valueMin'), Math.min(orig, this.get('valueMax'))); if ( orig !== value ) { this.set('value', value); return; } var percent = this.get('percent'); this.$('.slider-bar').css('width', percent+'%'); this.$('.slider-handle').css('left', percent+'%'); }.observes('value','valueMin','valueMax','percent'), });