Skip to content

Commit

Permalink
fix(uiSref): cancel transition if preventDefault() has been called
Browse files Browse the repository at this point in the history
  • Loading branch information
romario333 committed Mar 18, 2014
1 parent b97a01d commit 2e6d916
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
6 changes: 5 additions & 1 deletion src/stateDirectives.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,14 @@ function $StateRefDirective($state, $timeout) {
var button = e.which || e.button;
if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) {
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
$timeout(function() {
var transition = $timeout(function() {
$state.go(ref.state, params, options);
});
e.preventDefault();

e.preventDefault = function() {
$timeout.cancel(transition);
};
}
});
}
Expand Down
42 changes: 36 additions & 6 deletions test/stateDirectivesSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,25 @@ describe('uiStateRef', function() {
});

describe('links', function() {
var timeoutFlush;

beforeEach(inject(function($rootScope, $compile) {
beforeEach(inject(function($rootScope, $compile, $timeout) {
el = angular.element('<a ui-sref="contacts.item.detail({ id: contact.id })">Details</a>');
scope = $rootScope;
scope.contact = { id: 5 };
scope.$apply();

$compile(el)(scope);
scope.$digest();

timeoutFlush = function() {
try {
$timeout.flush();
} catch (e) {
// Angular 1.0.8 throws 'No deferred tasks to be flushed' if there is nothing in queue.
// Behave as Angular >=1.1.5 and do nothing in such case.
}
}
}));

it('should generate the correct href', function() {
Expand All @@ -107,18 +117,18 @@ describe('uiStateRef', function() {
expect(el.attr('href')).toBe('#/contacts/3');
}));

it('should transition states when left-clicked', inject(function($state, $stateParams, $document, $q, $timeout) {
it('should transition states when left-clicked', inject(function($state, $stateParams, $document, $q) {
expect($state.$current.name).toEqual('');

triggerClick(el);
$timeout.flush();
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('contacts.item.detail');
expect($stateParams).toEqual({ id: "5" });
}));

it('should transition when given a click that contains no data (fake-click)', inject(function($state, $stateParams, $document, $q, $timeout) {
it('should transition when given a click that contains no data (fake-click)', inject(function($state, $stateParams, $document, $q) {
expect($state.current.name).toEqual('');

triggerClick(el, {
Expand All @@ -128,7 +138,7 @@ describe('uiStateRef', function() {
altKey: undefined,
button: undefined
});
$timeout.flush();
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('contacts.item.detail');
Expand All @@ -139,7 +149,9 @@ describe('uiStateRef', function() {
expect($state.$current.name).toEqual('');
triggerClick(el, { ctrlKey: true });

timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('');
expect($stateParams).toEqual({ id: "5" });
}));
Expand All @@ -148,6 +160,7 @@ describe('uiStateRef', function() {
expect($state.$current.name).toEqual('');

triggerClick(el, { metaKey: true });
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('');
Expand All @@ -158,6 +171,7 @@ describe('uiStateRef', function() {
expect($state.$current.name).toEqual('');

triggerClick(el, { shiftKey: true });
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('');
Expand All @@ -168,17 +182,33 @@ describe('uiStateRef', function() {
expect($state.$current.name).toEqual('');

triggerClick(el, { button: 1 });
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('');
expect($stateParams).toEqual({ id: "5" });
}));

it('should not transition states when element has target specified', inject(function($state, $stateParams, $document, $q, $timeout) {
it('should not transition states when element has target specified', inject(function($state, $stateParams, $document, $q) {
el.attr('target', '_blank');
expect($state.$current.name).toEqual('');

triggerClick(el);
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('');
expect($stateParams).toEqual({ id: "5" });
}));

it('should not transition states if preventDefault() is called in click handler', inject(function($state, $stateParams, $document, $q) {
expect($state.$current.name).toEqual('');
el.bind('click', function(e) {
e.preventDefault();
});

triggerClick(el);
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('');
Expand Down

0 comments on commit 2e6d916

Please sign in to comment.