Надежно изменить название страницы в истории браузера с помощью JavaScript

Можно ли изменить название страницы в истории браузера через JavaScript после загрузки страницы? Должен быть кросс-браузер (конечно) и работать с браузерами, которые не поддерживают API истории HTML5, моим основным целевым браузером является Chrome.

Я пробовал ряд подходов, но никто из них, похоже, не работает надежно. Вот что я пробовал в прошлом (history.js):

<html>
    <head>
        <title>Standard title</title>
        <script src="https://rawgit.com/browserstate/history.js/master/scripts/bundled-uncompressed/html4%2Bhtml5/native.history.js"></script>
    </head>
    <body>
        <script>
            window.setTimeout(function(){
                document.title = "My custom title";
                History.replaceState({}, "My custom title", window.location.href);
            }, 3000);
        </script>
    </body>
</html>

Если я загружу страницу истории в Chrom в течение 3 секунд после загрузки страницы, я вижу Standard title, через 3 секунды я получаю My custom title.

Зачем мне это нужно: у меня есть приложение только для JavaScript (Angular 1), которое работает в разных средах (dev, test, production). Я хотел бы отобразить заголовок вроде MyApp (<environmentName>), но я не хочу создавать отдельные версии моего приложения для каждой среды. Вместо этого приложение может запрашивать информацию об окружающей среде из бэкэнд через AJAX и обновлять заголовок страницы. Все это прекрасно работает (заголовок страницы обновляется), но история браузера по-прежнему показывает "стандартное" название.

Есть ли способ изменить название страницы в истории браузера?

Ответ 1

Короткий ответ: похоже, вы не можете хранить разные записи за один и тот же URL в Chrome.

Отказ от ответственности. Я просто наткнулся на этот вопрос и не имел никакого предыдущего опыта. Тем не менее, вопрос был настолько ясным и интересным, что я не мог не поэкспериментировать:

Прежде всего, я согласен с тем, что записи истории (т.е. названия страниц), показанные на вкладке истории, НЕ так надежны (возможно, ошибка или кеш).

Поэтому я решаю, что я буду искать файл базы данных для истории Chrome, например, используя Браузер DB для SQLite.

К моему удивлению, в истории Chrome хранится только одна версия (последняя) названия для каждого URL-адреса. И когда я делаю History.replaceState({}, "My custom title", window.location.href);, заголовок обновляется в базе данных.

Однако метод @Bekim не изменит заголовок в базе данных.

Ответ 2

Проблема заключается в том, что второй параметр replaceState(), параметр title, в настоящее время игнорируется практически всеми исполняющими браузерами. Тем не менее, учитывается третий параметр pushState, url. К сожалению, он не работает с replaceState (по крайней мере, не в Chrome или Edge, согласно моим тестам).

С учетом этого, с клиентской стороны, вы можете использовать одно из следующих обходных решений, в зависимости от вашего вкуса:

history.pushState({}, "", "my-custom-appendix");
history.pushState({}, "", "#my-custom-appendix");

В Chrome это создаст дополнительные записи с заголовком, например http://myurl/my-custom-appendix или http://myurl/#my-custom-appendix (соответственно). Я считаю, что это самое близкое, что вы можете получить от клиента, и побочным эффектом является то, что вы получите новую запись истории в истории браузера - для каждого посещения вашего приложения вы, по существу, увидите (в увеличении порядка отметки времени ):

Вы увидите URL как заголовок, даже если у вас есть второй параметр, установленный в непустую строку (по крайней мере, то, что происходит на моем конце).


Для более надежного подхода вам нужно будет использовать простой препроцессор AFAIK на стороне сервера, например PHP.

Ответ 3

Что самое легкое когда-либо

document.title = "My App " +environmentName;

История немедленно обновит название нового документа.


чтобы проверить его положительно, попробуйте выполнить эти несколько шагов.

1st Скопируйте в консоль следующую команду и выполните:

name = '{ "location": ["http://stackoverflow.com/questions/12689408/how-can-jquery-window-location-hash-replace","http://stackoverflow.com/questions/12978739/is-there-a-javascript-api-to-browser-history-information-limited-to-current-dom","http://stackoverflow.com/questions/24653265/angular-browser-history-back-without-reload-previous-page"],"title" : ["Page 1", "Page 2", "Page 3"]}';

    document.title = "Where We've Started";

2nd Скопировать. Вставьте следующее в консоль и выполните 3 раза

nm = JSON.parse(name);
location = nm.location[0]; 

3rd Как только место загрузится, выполните следующие

nm = JSON.parse(name);
document.title = nm.title[0];

каждый раз, увеличивая индекс массива, как в:

location = nm.location[1];
document.title = nm.title[1];

(максимальный индекс равен 3, например, номер 2)
Затем нажмите и удерживайте кнопку "Назад", чтобы отобразить последние записи истории, все в порядке и обновлено, чтобы отразить новый заголовок документа.

Предупреждение. Если script не запущен после того, как вы вернулись к заданной записи истории, заголовок страницы вернется, как и ожидалось, к существующему жестко закодированному названию документа. Но так как эти имена контроля истории будут питаться script на всех страницах, они также будут продолжать отражать предоставленные живые документы. Здесь люди обманываются, возвращаясь к жестко закодированной странице в истории. И подумайте: "Черт, что-то пошло не так!"

Рисунок 1.: Конец результата Демо-кода, выполненного в отдельном/новом окне. Изображение конечного результата

введите описание изображения здесь

Ответ 4

Относится к angularjs: -

добавить метод запуска после модуля:

.run(function ($ rootScope) {

$rootScope.$on('$stateChangeSuccess', function (evt, toState) {
    window.document.title = toState.title + ' - example.com';
});

});

Ваше состояние: -

.state('productDetail', {

    title: 'Details of selected product',
    url: '/Detail.html',
    templateUrl: '/product-details.html',
    controller: 'ProductDetailsCtrl'

  })

.state( 'categoryManager', {

    title: 'Category Manager',
    url: '/category-Manager.html',
    templateUrl: 'categoryManager.html',
    controller: 'categoryManagerCtrl'

  });

это изменит название в соответствии с вашим состоянием.

Ответ 5

Firefox 52. Trivial:

document.title = 'CoolCmd';

Chrome 57 требует некоторой магии. Этот вариант также работает для Firefox 52. Он не добавляет лишних записей в историю браузера.

// HACK Do not change the order of these two lines!
history.replaceState(null, '');
document.title = 'CoolCmd';

MS Edge 14.14393 не позволяет изменить название документа в истории. Он даже не добавляет к истории адреса, указанные history.pushState()! LOL

Я не тестировал Safari...

Ответ 6

Вы можете использовать document.write() для написания правильного названия для документа на первом месте, пока он все еще загружается. Но для этого потребуется синхронный запрос на сервер:

<head>
  <script>
  (function () {
    // Get title using sync request.
    var title = "Value from server";
    document.write("<title>"+ title + "</title>");
  })();
  </script>
</head>

Страница, которая включает отрезки сверху, появится с заголовком "Значение от сервера" в истории браузера.