Draggable slider working

This commit is contained in:
Max Lynch
2014-03-01 15:52:47 -06:00
parent a0d60d5228
commit e538fa77c9
5 changed files with 141 additions and 33 deletions

View File

@@ -5,7 +5,7 @@ angular.module('ionic.ui.toggle', [])
// The Toggle directive is a toggle switch that can be tapped to change
// its value
.directive('ionToggle', function() {
.directive('ionToggle', ['$ionicGesture', '$timeout', function($ionicGesture, $timeout) {
return {
restrict: 'E',
@@ -36,30 +36,38 @@ angular.module('ionic.ui.toggle', [])
if(attr.ngTrueValue) input.attr('ng-true-value', attr.ngTrueValue);
if(attr.ngFalseValue) input.attr('ng-false-value', attr.ngFalseValue);
// return function link($scope, $element, $attr, ngModel) {
// var el, checkbox, track, handle;
return function($scope, $element, $attr) {
var el, checkbox, track, handle;
// el = $element[0].getElementsByTagName('label')[0];
// checkbox = el.children[0];
// track = el.children[1];
// handle = track.children[0];
el = $element[0].getElementsByTagName('label')[0];
checkbox = el.children[0];
track = el.children[1];
handle = track.children[0];
var ngModelController = angular.element(checkbox).controller('ngModel');
// $scope.toggle = new ionic.views.Toggle({
// el: el,
// track: track,
// checkbox: checkbox,
// handle: handle
// });
$scope.toggle = new ionic.views.Toggle({
el: el,
track: track,
checkbox: checkbox,
handle: handle,
onChange: function() {
if(checkbox.checked) {
ngModelController.$setViewValue(true);
} else {
ngModelController.$setViewValue(false);
}
$scope.$apply();
}
});
// ionic.on('drag', function(e) {
// console.log('drag');
// $scope.toggle.drag(e);
// }, handle);
// }
$scope.$on('$destroy', function() {
$scope.toggle.destroy();
});
};
}
};
});
}]);
})(window.ionic);

View File

@@ -1,7 +1,7 @@
describe('Ionic Toggle', function() {
var el, rootScope, compile;
beforeEach(module('ionic.ui.toggle'));
beforeEach(module('ionic'));
beforeEach(inject(function($compile, $rootScope) {
compile = $compile;
@@ -9,14 +9,21 @@ describe('Ionic Toggle', function() {
el = $compile('<ion-toggle ng-model="data.name"></ion-toggle>')($rootScope);
}));
/*
it('Should load', function() {
iit('Should load', function() {
var toggleView = el.isolateScope().toggle;
expect(toggleView).not.toEqual(null);
expect(toggleView.checkbox).not.toEqual(null);
expect(toggleView.handle).not.toEqual(null);
});
iit('Should destroy', function() {
var toggleView = el.isolateScope().toggle;
spyOn(toggleView, 'destroy');
el.isolateScope().$destroy();
expect(toggleView.destroy).toHaveBeenCalled();
});
/*
it('Should toggle', function() {
var toggle = el.isolateScope().toggle;
expect(toggle.val()).toBe(false);

View File

@@ -18,6 +18,7 @@
<div class="list">
<ion-toggle ng-model="myModel" ng-disabled="isDisabled">myModel ({{!!myModel}})</ion-toggle>
<ion-toggle ng-model="catModel" ng-disabled="isDisabled" ng-true-value="cats" ng-false-value="dogs">Cats or dogs? ({{catModel}})</ion-toggle>
<ion-toggle ng-model="isDisabled">Disable myModel ({{!!isDisabled}})</ion-toggle>
</div>
</div>
@@ -25,7 +26,9 @@
<script>
angular.module('toggleTest', ['ionic'])
.controller('TestCtrl', function($scope) {});
.controller('TestCtrl', function($scope) {
$scope.catModel = 'dogs';
});
</script>
</body>
</html>

View File

@@ -3,11 +3,41 @@
ionic.views.Toggle = ionic.views.View.inherit({
initialize: function(opts) {
var self = this;
this.el = opts.el;
this.checkbox = opts.checkbox;
this.track = opts.track;
this.handle = opts.handle;
this.openPercent = -1;
this.onChange = opts.onChange || function() {};
this.triggerThreshold = opts.triggerThreshold || 10;
this.dragStartHandler = function(e) {
self.dragStart(e);
};
this.dragHandler = function(e) {
self.drag(e);
};
this.holdHandler = function(e) {
self.hold(e);
};
this.releaseHandler = function(e) {
self.release(e);
};
this.dragStartGesture = ionic.onGesture('dragstart', this.dragStartHandler, this.el);
this.dragGesture = ionic.onGesture('drag', this.dragHandler, this.el);
this.dragHoldGesture = ionic.onGesture('hold', this.holdHandler, this.el);
this.dragReleaseGesture = ionic.onGesture('release', this.releaseHandler, this.el);
},
destroy: function() {
ionic.offGesture(this.dragStartGesture, 'dragstart', this.dragStartGesture);
ionic.offGesture(this.dragGesture, 'drag', this.dragGesture);
ionic.offGesture(this.dragHoldGesture, 'hold', this.holdHandler);
ionic.offGesture(this.dragReleaseGesture, 'release', this.releaseHandler);
},
tap: function(e) {
@@ -16,19 +46,52 @@
}
},
dragStart: function(e) {
this._dragInfo = {
width: this.el.offsetWidth,
left: this.el.offsetLeft,
right: this.el.offsetLeft + this.el.offsetWidth,
triggerX: this.el.offsetWidth / 2,
initialState: this.checkbox.checked
}
// Trigger hold styles
this.hold(e);
},
drag: function(e) {
if(!this._dragInfo) { return; }
var slidePageLeft = this.track.offsetLeft + (this.handle.offsetWidth / 2);
var slidePageRight = this.track.offsetLeft + this.track.offsetWidth - (this.handle.offsetWidth / 2);
var dx = e.gesture.deltaX;
if(e.pageX >= slidePageRight - 4) {
this.val(true);
} else if(e.pageX <= slidePageLeft) {
this.val(false);
var px = e.gesture.touches[0].pageX - this._dragInfo.left;
var mx = this._dragInfo.width - this.triggerThreshold;
// The initial state was on, so "tend towards" on
if(this._dragInfo.initialState) {
if(px < this.triggerThreshold) {
this.setOpenPercent(0);
} else if(px > this._dragInfo.triggerX) {
this.setOpenPercent(100);
}
} else {
this.setOpenPercent( Math.round( (1 - ((slidePageRight - e.pageX) / (slidePageRight - slidePageLeft) )) * 100) );
// The initial state was off, so "tend towards" off
if(px < this._dragInfo.triggerX) {
this.setOpenPercent(0);
} else if(px > mx) {
this.setOpenPercent(100);
}
}
},
hold: function(e) {
},
release: function(e) {
},
setOpenPercent: function(openPercent) {
// only make a change if the new open percent has changed
if(this.openPercent < 0 || (openPercent < (this.openPercent - 3) || openPercent > (this.openPercent + 3) ) ) {
@@ -46,10 +109,6 @@
}
},
release: function(e) {
this.val( this.openPercent >= 50 );
},
val: function(value) {
if(value === true || value === false) {
if(this.handle.style[ionic.CSS.TRANSFORM] !== "") {
@@ -57,6 +116,7 @@
}
this.checkbox.checked = value;
this.openPercent = (value ? 100 : 0);
this.onChange && this.onChange();
}
return this.checkbox.checked;
}

View File

@@ -0,0 +1,30 @@
describe('Toggle view', function() {
var element, toggle;
beforeEach(function() {
element = $('<div class="item item-toggle disable-pointer-events">' +
'<div>Cats</div>' +
'<label class="toggle enable-pointer-events">' +
'<input type="checkbox">' +
'<div class="track disable-pointer-events">' +
'<div class="handle"></div>' +
'</div>' +
'</label>' +
'</div>');
el = element[0].getElementsByTagName('label')[0];
checkbox = el.children[0];
track = el.children[1];
handle = track.children[0];
toggle = new ionic.views.Toggle({
el: el,
checkbox: checkbox,
track: track,
handle: handle
});
});
it('Should init', function() {
expect(toggle.el).not.toBe(undefined);
});
});