From 7a5b1d2be1b6865459af73c8f4da5d9944cd3c4e Mon Sep 17 00:00:00 2001 From: lingyan Date: Mon, 30 Mar 2015 11:48:43 -0700 Subject: [PATCH] use current title/url as default for pushState/replaceState --- lib/History.js | 30 ++++------- tests/unit/lib/History-test.js | 65 +++++++++++++++++------- tests/unit/utils/HistoryWithHash-test.js | 57 ++++++++++++++++----- utils/HistoryWithHash.js | 30 ++++------- 4 files changed, 113 insertions(+), 69 deletions(-) diff --git a/lib/History.js b/lib/History.js index f6027f3..e25989f 100644 --- a/lib/History.js +++ b/lib/History.js @@ -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() @@ -73,17 +77,10 @@ History.prototype = { */ pushState: function (state, title, url) { var win = this.win; + title = isUndefined(title) ? win.document.title : title; + url = isUndefined(url) ? win.location.href : url; 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); - } - } + win.history.pushState(state, title, url); this.setTitle(title); } else if (url) { win.location.href = url; @@ -99,17 +96,10 @@ History.prototype = { */ replaceState: function (state, title, url) { var win = this.win; + title = isUndefined(title) ? win.document.title : title; + url = isUndefined(url) ? win.location.href : url; 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); - } - } + win.history.replaceState(state, title, url); this.setTitle(title); } else if (url) { win.location.replace(url); diff --git a/tests/unit/lib/History-test.js b/tests/unit/lib/History-test.js index 23512bf..8cecd3a 100644 --- a/tests/unit/lib/History-test.js +++ b/tests/unit/lib/History-test.js @@ -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'}); @@ -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'}); @@ -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'}); @@ -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'}); @@ -256,7 +288,6 @@ describe('History', function () { replace: function(url) { testResult.locationReplace = {url: url}; } - } }); var history = new History({win: win}); diff --git a/tests/unit/utils/HistoryWithHash-test.js b/tests/unit/utils/HistoryWithHash-test.js index 9c90812..9748daa 100644 --- a/tests/unit/utils/HistoryWithHash-test.js +++ b/tests/unit/utils/HistoryWithHash-test.js @@ -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'}); @@ -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'}); @@ -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'}); @@ -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'}); diff --git a/utils/HistoryWithHash.js b/utils/HistoryWithHash.js index 674728e..5bc1d95 100644 --- a/utils/HistoryWithHash.js +++ b/utils/HistoryWithHash.js @@ -5,6 +5,10 @@ /*global window */ 'use strict'; +function isUndefined(v) { + return v === undefined; +} + /** * @class HistoryWithHash * @constructor @@ -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; @@ -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);