Skip to content
This repository has been archived by the owner on Jul 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #88 from yahoo/undefinedURL
Browse files Browse the repository at this point in the history
use current title/url as default for pushState/replaceState
  • Loading branch information
lingyan committed Mar 30, 2015
2 parents 6a3e90c + 3041d84 commit 7d05353
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 69 deletions.
30 changes: 10 additions & 20 deletions lib/History.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

var EVENT_POPSTATE = 'popstate';

function isUndefined(v) {
return v === undefined;
}

/**
* This only supports pushState for the browsers with native pushState support.
* For other browsers (mainly IE8 and IE9), it will refresh the page upon pushState()
Expand Down Expand Up @@ -74,16 +78,9 @@ History.prototype = {
pushState: function (state, title, url) {
var win = this.win;
if (this._hasPushState) {
try {
// not calling pushState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
win.history.pushState.apply(win.history, arguments);
} catch (error) {
// firefox 35 requires 3 args for pushState
if (arguments.length < 3) {
win.history.pushState(state, title, url);
}
}
title = isUndefined(title) ? win.document.title : title;
url = isUndefined(url) ? win.location.href : url;
win.history.pushState(state, title, url);
this.setTitle(title);
} else if (url) {
win.location.href = url;
Expand All @@ -100,16 +97,9 @@ History.prototype = {
replaceState: function (state, title, url) {
var win = this.win;
if (this._hasPushState) {
try {
// not calling pushState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
win.history.replaceState.apply(win.history, arguments);
} catch (error) {
// firefox 35 requires 3 args for replaceState
if (arguments.length < 3) {
win.history.replaceState(state, title, url);
}
}
title = isUndefined(title) ? win.document.title : title;
url = isUndefined(url) ? win.location.href : url;
win.history.replaceState(state, title, url);
this.setTitle(title);
} else if (url) {
win.location.replace(url);
Expand Down
65 changes: 48 additions & 17 deletions tests/unit/lib/History-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,25 @@ describe('History', function () {

describe('pushState', function () {
it ('has pushState', function () {
var history = new History({win: windowMock.HTML5});
var win = _.extend(windowMock.HTML5, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new History({win: win});

history.pushState({foo: 'bar'});
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal(undefined);
expect(testResult.pushState.url).to.equal(undefined);
expect(testResult.pushState.title).to.equal('current title');
expect(testResult.pushState.url).to.equal('/currentUrl');

history.pushState({foo: 'bar'}, 't');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal(undefined);
expect(testResult.pushState.url).to.equal('/currentUrl');

history.pushState({foo: 'bar'}, 't', '/url');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
Expand All @@ -172,17 +180,25 @@ describe('History', function () {
expect(windowMock.HTML5.document.title).to.equal('tt');
});
it ('has pushState, Firefox', function () {
var history = new History({win: windowMock.Firefox});
var win = _.extend(windowMock.Firefox, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new History({win: win});

history.pushState({foo: 'bar'});
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal(undefined);
expect(testResult.pushState.url).to.equal(undefined);
expect(testResult.pushState.title).to.equal('current title');
expect(testResult.pushState.url).to.equal('/currentUrl');

history.pushState({foo: 'bar'}, 't');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal(undefined);
expect(testResult.pushState.url).to.equal('/currentUrl');

history.pushState({foo: 'bar'}, 't', '/url');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
Expand All @@ -208,17 +224,25 @@ describe('History', function () {

describe('replaceState', function () {
it ('has pushState', function () {
var history = new History({win: windowMock.HTML5});
var win = _.extend(windowMock.HTML5, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new History({win: win});

history.replaceState({foo: 'bar'});
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal(undefined);
expect(testResult.replaceState.url).to.equal(undefined);
expect(testResult.replaceState.title).to.equal('current title');
expect(testResult.replaceState.url).to.equal('/currentUrl');

history.replaceState({foo: 'bar'}, 't');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal(undefined);
expect(testResult.replaceState.url).to.equal('/currentUrl');

history.replaceState({foo: 'bar'}, 't', '/url');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
Expand All @@ -233,17 +257,25 @@ describe('History', function () {
expect(windowMock.HTML5.document.title).to.equal('tt');
});
it ('has pushState, Firefox', function () {
var history = new History({win: windowMock.Firefox});
var win = _.extend(windowMock.Firefox, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new History({win: win});

history.replaceState({foo: 'bar'});
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal(undefined);
expect(testResult.replaceState.url).to.equal(undefined);
expect(testResult.replaceState.title).to.equal('current title');
expect(testResult.replaceState.url).to.equal('/currentUrl');

history.replaceState({foo: 'bar'}, 't');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal(undefined);
expect(testResult.replaceState.url).to.equal('/currentUrl');

history.replaceState({foo: 'bar'}, 't', '/url');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
Expand All @@ -256,7 +288,6 @@ describe('History', function () {
replace: function(url) {
testResult.locationReplace = {url: url};
}

}
});
var history = new History({win: win});
Expand Down
57 changes: 45 additions & 12 deletions tests/unit/utils/HistoryWithHash-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,20 @@ describe('HistoryWithHash', function () {

describe('pushState', function () {
it ('useHashRoute=false; has pushState', function () {
var history = new HistoryWithHash({win: windowMock.HTML5});
var win = _.extend(windowMock.HTML5, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new HistoryWithHash({win: win});

history.pushState({foo: 'bar'});
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal(undefined);
expect(testResult.pushState.url).to.equal(undefined);
expect(testResult.pushState.title).to.equal('current title');
expect(testResult.pushState.url).to.equal('/currentUrl');

history.pushState({foo: 'bar'}, 't', '/url');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
Expand All @@ -195,12 +203,20 @@ describe('HistoryWithHash', function () {
expect(windowMock.HTML5.document.title).to.equal('tt');
});
it ('useHashRoute=false; has pushState; Firefox', function () {
var history = new HistoryWithHash({win: windowMock.Firefox});
var win = _.extend(windowMock.Firefox, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new HistoryWithHash({win: win});

history.pushState({foo: 'bar'});
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal(undefined);
expect(testResult.pushState.url).to.equal(undefined);
expect(testResult.pushState.title).to.equal('current title');
expect(testResult.pushState.url).to.equal('/currentUrl');

history.pushState({foo: 'bar'}, 't', '/url');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
Expand Down Expand Up @@ -282,12 +298,21 @@ describe('HistoryWithHash', function () {

describe('replaceState', function () {
it ('useHashRouter=false; has pushState', function () {
var history = new HistoryWithHash({win: windowMock.HTML5});
// var history = new HistoryWithHash({win: windowMock.HTML5});
var win = _.extend(windowMock.HTML5, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new HistoryWithHash({win: win});

history.replaceState({foo: 'bar'});
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal(undefined);
expect(testResult.replaceState.url).to.equal(undefined);
expect(testResult.replaceState.title).to.equal('current title');
expect(testResult.replaceState.url).to.equal('/currentUrl');

history.replaceState({foo: 'bar'}, 't', '/url');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
Expand All @@ -302,12 +327,20 @@ describe('HistoryWithHash', function () {
expect(windowMock.HTML5.document.title).to.equal('tt');
});
it ('useHashRouter=false; has pushState; Firefox', function () {
var history = new HistoryWithHash({win: windowMock.Firefox});
var win = _.extend(windowMock.Firefox, {
'document': {
title: 'current title'
},
location: {
href: '/currentUrl'
}
});
var history = new HistoryWithHash({win: win});

history.replaceState({foo: 'bar'});
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal(undefined);
expect(testResult.replaceState.url).to.equal(undefined);
expect(testResult.replaceState.title).to.equal('current title');
expect(testResult.replaceState.url).to.equal('/currentUrl');

history.replaceState({foo: 'bar'}, 't', '/url');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
Expand Down
30 changes: 10 additions & 20 deletions utils/HistoryWithHash.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
/*global window */
'use strict';

function isUndefined(v) {
return v === undefined;
}

/**
* @class HistoryWithHash
* @constructor
Expand Down Expand Up @@ -136,16 +140,9 @@ HistoryWithHash.prototype = {
}
} else {
if (this._hasPushState) {
try {
// not calling pushState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
history.pushState.apply(history, arguments);
} catch (error) {
// firefox 35 requires 3 args for pushState
if (arguments.length < 3) {
history.pushState(state, title, url);
}
}
title = isUndefined(title) ? win.document.title : title;
url = isUndefined(url) ? win.location.href : url;
history.pushState(state, title, url);
this.setTitle(title);
} else if (url) {
location.href = url;
Expand Down Expand Up @@ -182,16 +179,9 @@ HistoryWithHash.prototype = {
}
} else {
if (this._hasPushState) {
try {
// not calling replaceState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
history.replaceState.apply(history, arguments);
} catch (error) {
// firefox 35 requires 3 args for replaceState
if (arguments.length < 3) {
history.replaceState(state, title, url);
}
}
title = isUndefined(title) ? win.document.title : title;
url = isUndefined(url) ? win.location.href : url;
history.replaceState(state, title, url);
this.setTitle(title);
} else if (url) {
location.replace(url);
Expand Down

0 comments on commit 7d05353

Please sign in to comment.