diff --git a/plugins/CoreHome/angularjs/history/history.service.js b/plugins/CoreHome/angularjs/history/history.service.js index 555afba6b6cd96fe04d166aad7da3eec19611e7f..828217a5fa0b813e3fb9105adbe1027957a33b0b 100644 --- a/plugins/CoreHome/angularjs/history/history.service.js +++ b/plugins/CoreHome/angularjs/history/history.service.js @@ -25,6 +25,10 @@ return service; function init() { + if ($location.path() != '/') { + changePathToSearch(); + } + $rootScope.$on('$locationChangeSuccess', function () { loadCurrentPage(); }); @@ -32,9 +36,43 @@ loadCurrentPage(); } + // currently, the AJAX content URL is stored in $location.search(), but before it was stored in $location.path(). + // this function makes sure URLs like http://piwik.net/?...#/module=Whatever&action=whatever still work. + function changePathToSearch() { + var path = $location.path(); + if (!path + || path == '/' + ) { + return; + } + + var searchParams = broadcast.getValuesFromUrl('?' + path.substring(1)); + // NOTE: we don't need to decode the parameters since $location.path() will decode the string itself + + $location.search(searchParams); + $location.path(''); + } + function loadCurrentPage() { + var searchObject = $location.search(), + searchString = []; + for (var name in searchObject) { + if (!searchObject.hasOwnProperty(name)) { + continue; + } + + // if more than one query parameter of the same name is supplied, angular will return all of them as + // an array. we only want to use the last one, though. + if (searchObject[name] instanceof Array) { + searchObject[name] = searchObject[name][searchObject[name].length - 1]; + } + + searchString.push(name + '=' + encodeURIComponent(searchObject[name])); + } + searchString = searchString.join('&'); + // the location hash will have a / prefix, which broadcast.pageload doesn't want - broadcast.pageload($location.path().substring(1)); + broadcast.pageload(searchString); } function load(hash) { @@ -47,7 +85,15 @@ } } - $location.path(hash); + if (hash) { + $location.search(hash); + } else { + // NOTE: this works around a bug in angularjs. when unsetting the hash (ie, removing in the URL), + // angular will enter an infinite loop of digests. this is because $locationWatch will trigger + // $locationChangeStart if $browser.url() != $location.absUrl(), and $browser.url() will contain + // the '#' character and $location.absUrl() will not. so the watch continues to trigger the event. + $location.search('_='); + } setTimeout(function () { $rootScope.$apply(); }, 1); } diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js index 4b6ca7e9978761188937eff5bbeab0f0d3c9b305..706a8e59d59f856ccd1acb4737f17bb3a483bee3 100644 --- a/plugins/CoreHome/javascripts/broadcast.js +++ b/plugins/CoreHome/javascripts/broadcast.js @@ -215,7 +215,7 @@ var broadcast = { } if (disableHistory) { - var newLocation = window.location.href.split('#')[0] + '#' + currentHashStr; + var newLocation = window.location.href.split('#')[0] + '#?' + currentHashStr; // window.location.replace changes the current url without pushing it on the browser's history stack window.location.replace(newLocation); } diff --git a/plugins/Overlay/javascripts/Overlay_Helper.js b/plugins/Overlay/javascripts/Overlay_Helper.js index 13feff40827c8a8b96e85e1248499bb183efb208..e0681e7b454c4e48472936e3418f22bf3ec01b43 100644 --- a/plugins/Overlay/javascripts/Overlay_Helper.js +++ b/plugins/Overlay/javascripts/Overlay_Helper.js @@ -23,7 +23,7 @@ var Overlay_Helper = { getOverlayLink: function (idSite, period, date, link) { var url = 'index.php?module=Overlay&period=' + encodeURIComponent(period) + '&date=' + encodeURIComponent(date) + '&idSite=' + encodeURIComponent(idSite); if (link) { - url += '#l=' + Overlay_Helper.encodeFrameUrl(link); + url += '#?l=' + Overlay_Helper.encodeFrameUrl(link); } return url; } diff --git a/plugins/Overlay/javascripts/Piwik_Overlay.js b/plugins/Overlay/javascripts/Piwik_Overlay.js index b7f38a89b4532ae93ac55fdcb3c0dfb3f57d1f3d..4c780808064bf8e67d5e0e7a3f30a0eb4035cc93 100644 --- a/plugins/Overlay/javascripts/Piwik_Overlay.js +++ b/plugins/Overlay/javascripts/Piwik_Overlay.js @@ -111,9 +111,19 @@ var Piwik_Overlay = (function () { $fullScreenLink.show(); } + function getOverlayLocationFromHash(urlHash) { + var location = broadcast.getParamValue('l', urlHash); + + // angular will encode the value again since it is added as the fragment path, not the fragment query parameter, + // so we have to decode it again after getParamValue + location = decodeURIComponent(location); + + return location; + } + /** $.history callback for hash change */ function hashChangeCallback(urlHash) { - var location = broadcast.getParamValue('l', urlHash); + var location = getOverlayLocationFromHash(urlHash); location = Overlay_Helper.decodeFrameUrl(location); if (!updateComesFromInsideFrame) { @@ -243,7 +253,7 @@ var Piwik_Overlay = (function () { var locationParts = location.href.split('#'); var currentLocation = ''; if (locationParts.length > 1) { - currentLocation = broadcast.getParamValue('l', locationParts[1]); + currentLocation = getOverlayLocationFromHash(locationParts[1]); } var newLocation = Overlay_Helper.encodeFrameUrl(currentUrl); diff --git a/tests/UI/specs/UIIntegration_spec.js b/tests/UI/specs/UIIntegration_spec.js index 97e3afad93e451d970ab88e1bbc7200d19da63bc..1334a9dd19f80a74238fcb63c950f19cda673028 100644 --- a/tests/UI/specs/UIIntegration_spec.js +++ b/tests/UI/specs/UIIntegration_spec.js @@ -614,5 +614,28 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik? }, done); }); + // extra segment tests + it('should load the row evolution page correctly when a segment is selected', function (done) { + var url = "?module=CoreHome&action=index&idSite=1&period=year&date=2012-01-13#?module=CustomVariables&action=menuGetCustomVariables&idSite=1&period=year&date=2012-01-13"; + expect.page(url).contains('.ui-dialog > .ui-dialog-content > div.rowevolution:visible', 'segmented_rowevolution', function (page) { + page.click('.segmentationTitle'); + page.click('.segname:contains(From Europe)'); + page.mouseMove('table.dataTable tbody tr:first-child'); + page.mouseMove('a.actionRowEvolution:visible'); // necessary to get popover to display + page.click('a.actionRowEvolution:visible'); + }, done); + }); + + it('should load the segmented visitor log correctly when a segment is selected', function (done) { + var url = "?module=CoreHome&action=index&idSite=1&period=year&date=2012-01-13#?module=CustomVariables&action=menuGetCustomVariables&idSite=1&period=year&date=2012-01-13"; + expect.page(url).contains('.ui-dialog > .ui-dialog-content > div.dataTableVizVisitorLog:visible', 'segmented_visitorlog', function (page) { + page.click('.segmentationTitle'); + page.click('.segname:contains(From Europe)'); + + page.mouseMove('table.dataTable tbody tr:first-child'); + page.mouseMove('a.actionSegmentVisitorLog:visible'); // necessary to get popover to display + page.click('a.actionSegmentVisitorLog:visible'); + }, done); + }); }); \ No newline at end of file