diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md
new file mode 100644
index 0000000000000..eba149bf93a4c
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md
@@ -0,0 +1,34 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [change](./kibana-plugin-public.chromedoctitle.change.md)
+
+## ChromeDocTitle.change() method
+
+Changes the current document title.
+
+Signature:
+
+```typescript
+change(newTitle: string | string[]): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| newTitle | string | string[]
| |
+
+Returns:
+
+`void`
+
+## Example
+
+How to change the title of the document
+
+```ts
+chrome.docTitle.change('My application title')
+chrome.docTitle.change(['My application', 'My section'])
+
+```
+
diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md
new file mode 100644
index 0000000000000..3c6cfab486288
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md
@@ -0,0 +1,39 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md)
+
+## ChromeDocTitle interface
+
+APIs for accessing and updating the document title.
+
+Signature:
+
+```typescript
+export interface ChromeDocTitle
+```
+
+## Methods
+
+| Method | Description |
+| --- | --- |
+| [change(newTitle)](./kibana-plugin-public.chromedoctitle.change.md) | Changes the current document title. |
+| [reset()](./kibana-plugin-public.chromedoctitle.reset.md) | Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) |
+
+## Example 1
+
+How to change the title of the document
+
+```ts
+chrome.docTitle.change('My application')
+
+```
+
+## Example 2
+
+How to reset the title of the document to it's initial value
+
+```ts
+chrome.docTitle.reset()
+
+```
+
diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md
new file mode 100644
index 0000000000000..4b4c6f573e006
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [reset](./kibana-plugin-public.chromedoctitle.reset.md)
+
+## ChromeDocTitle.reset() method
+
+Resets the document title to it's initial value. (meaning the one present in the title meta at application load.)
+
+Signature:
+
+```typescript
+reset(): void;
+```
+Returns:
+
+`void`
+
diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md
new file mode 100644
index 0000000000000..71eda64c24646
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [docTitle](./kibana-plugin-public.chromestart.doctitle.md)
+
+## ChromeStart.docTitle property
+
+APIs for accessing and updating the document title.
+
+Signature:
+
+```typescript
+docTitle: ChromeDocTitle;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.md b/docs/development/core/public/kibana-plugin-public.chromestart.md
index bc41aa10cce8f..153e06d591404 100644
--- a/docs/development/core/public/kibana-plugin-public.chromestart.md
+++ b/docs/development/core/public/kibana-plugin-public.chromestart.md
@@ -16,6 +16,7 @@ export interface ChromeStart
| Property | Type | Description |
| --- | --- | --- |
+| [docTitle](./kibana-plugin-public.chromestart.doctitle.md) | ChromeDocTitle
| APIs for accessing and updating the document title. |
| [navControls](./kibana-plugin-public.chromestart.navcontrols.md) | ChromeNavControls
| [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. |
| [navLinks](./kibana-plugin-public.chromestart.navlinks.md) | ChromeNavLinks
| [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. |
| [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) | ChromeRecentlyAccessed
| [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. |
diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md
index 57ab8bedde95e..253e50f0f2c2e 100644
--- a/docs/development/core/public/kibana-plugin-public.md
+++ b/docs/development/core/public/kibana-plugin-public.md
@@ -32,6 +32,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. |
| [ChromeBadge](./kibana-plugin-public.chromebadge.md) | |
| [ChromeBrand](./kibana-plugin-public.chromebrand.md) | |
+| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. |
| [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | |
| [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. |
| [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | |
diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md
index 6a12b587085e1..b5942cc82941f 100644
--- a/src/core/MIGRATION.md
+++ b/src/core/MIGRATION.md
@@ -1111,6 +1111,7 @@ import { npStart: { core } } from 'ui/new_platform';
| `ui/notify` | [`core.notifications`](/docs/development/core/public/kibana-plugin-public.notificationsstart.md) and [`core.overlays`](/docs/development/core/public/kibana-plugin-public.overlaystart.md) | Toast messages are in `notifications`, banners are in `overlays`. May be combined later. |
| `ui/routes` | -- | There is no global routing mechanism. Each app [configures its own routing](/rfcs/text/0004_application_service_mounting.md#complete-example). |
| `ui/saved_objects` | [`core.savedObjects`](/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md) | Client API is the same |
+| `ui/doc_title` | [`core.chrome.docTitle`](/docs/development/core/public/kibana-plugin-public.chromedoctitle.md) | |
_See also: [Public's CoreStart API Docs](/docs/development/core/public/kibana-plugin-public.corestart.md)_
diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts
index 3775989c5126b..6f61ee9dc21ba 100644
--- a/src/core/public/chrome/chrome_service.mock.ts
+++ b/src/core/public/chrome/chrome_service.mock.ts
@@ -43,6 +43,13 @@ const createStartContractMock = () => {
get: jest.fn(),
get$: jest.fn(),
},
+ docTitle: {
+ change: jest.fn(),
+ reset: jest.fn(),
+ __legacy: {
+ setBaseTitle: jest.fn(),
+ },
+ },
navControls: {
registerLeft: jest.fn(),
registerRight: jest.fn(),
diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx
index 71279ad6fed03..87389d2c10f03 100644
--- a/src/core/public/chrome/chrome_service.tsx
+++ b/src/core/public/chrome/chrome_service.tsx
@@ -33,10 +33,11 @@ import { HttpStart } from '../http';
import { ChromeNavLinks, NavLinksService } from './nav_links';
import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed';
import { NavControlsService, ChromeNavControls } from './nav_controls';
+import { DocTitleService, ChromeDocTitle } from './doc_title';
import { LoadingIndicator, HeaderWrapper as Header } from './ui';
import { DocLinksStart } from '../doc_links';
-export { ChromeNavControls, ChromeRecentlyAccessed };
+export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle };
const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed';
@@ -82,6 +83,7 @@ export class ChromeService {
private readonly navControls = new NavControlsService();
private readonly navLinks = new NavLinksService();
private readonly recentlyAccessed = new RecentlyAccessedService();
+ private readonly docTitle = new DocTitleService();
constructor(private readonly params: ConstructorParams) {}
@@ -106,6 +108,7 @@ export class ChromeService {
const navControls = this.navControls.start();
const navLinks = this.navLinks.start({ application, http });
const recentlyAccessed = await this.recentlyAccessed.start({ http });
+ const docTitle = this.docTitle.start({ document: window.document });
if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) {
notifications.toasts.addWarning(
@@ -119,6 +122,7 @@ export class ChromeService {
navControls,
navLinks,
recentlyAccessed,
+ docTitle,
getHeaderComponent: () => (
@@ -259,6 +263,8 @@ export interface ChromeStart {
navControls: ChromeNavControls;
/** {@inheritdoc ChromeRecentlyAccessed} */
recentlyAccessed: ChromeRecentlyAccessed;
+ /** {@inheritdoc ChromeDocTitle} */
+ docTitle: ChromeDocTitle;
/**
* Sets the current app's title
diff --git a/src/core/public/chrome/doc_title/doc_title_service.test.ts b/src/core/public/chrome/doc_title/doc_title_service.test.ts
new file mode 100644
index 0000000000000..763e8c9ebd74a
--- /dev/null
+++ b/src/core/public/chrome/doc_title/doc_title_service.test.ts
@@ -0,0 +1,80 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DocTitleService } from './doc_title_service';
+
+describe('DocTitleService', () => {
+ const defaultTitle = 'KibanaTest';
+ const document = { title: '' };
+
+ const getStart = (title: string = defaultTitle) => {
+ document.title = title;
+ return new DocTitleService().start({ document });
+ };
+
+ beforeEach(() => {
+ document.title = defaultTitle;
+ });
+
+ describe('#change()', () => {
+ it('changes the title of the document', async () => {
+ getStart().change('TitleA');
+ expect(document.title).toEqual('TitleA - KibanaTest');
+ });
+
+ it('appends the baseTitle to the title', async () => {
+ const start = getStart('BaseTitle');
+ start.change('TitleA');
+ expect(document.title).toEqual('TitleA - BaseTitle');
+ start.change('TitleB');
+ expect(document.title).toEqual('TitleB - BaseTitle');
+ });
+
+ it('accepts string arrays as input', async () => {
+ const start = getStart();
+ start.change(['partA', 'partB']);
+ expect(document.title).toEqual(`partA - partB - ${defaultTitle}`);
+ start.change(['partA', 'partB', 'partC']);
+ expect(document.title).toEqual(`partA - partB - partC - ${defaultTitle}`);
+ });
+ });
+
+ describe('#reset()', () => {
+ it('resets the title to the initial value', async () => {
+ const start = getStart('InitialTitle');
+ start.change('TitleA');
+ expect(document.title).toEqual('TitleA - InitialTitle');
+ start.reset();
+ expect(document.title).toEqual('InitialTitle');
+ });
+ });
+
+ describe('#__legacy.setBaseTitle()', () => {
+ it('allows to change the baseTitle after startup', async () => {
+ const start = getStart('InitialTitle');
+ start.change('WithInitial');
+ expect(document.title).toEqual('WithInitial - InitialTitle');
+ start.__legacy.setBaseTitle('NewBaseTitle');
+ start.change('WithNew');
+ expect(document.title).toEqual('WithNew - NewBaseTitle');
+ start.reset();
+ expect(document.title).toEqual('NewBaseTitle');
+ });
+ });
+});
diff --git a/src/core/public/chrome/doc_title/doc_title_service.ts b/src/core/public/chrome/doc_title/doc_title_service.ts
new file mode 100644
index 0000000000000..9453abe54de66
--- /dev/null
+++ b/src/core/public/chrome/doc_title/doc_title_service.ts
@@ -0,0 +1,105 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { compact, flattenDeep, isString } from 'lodash';
+
+interface StartDeps {
+ document: { title: string };
+}
+
+/**
+ * APIs for accessing and updating the document title.
+ *
+ * @example
+ * How to change the title of the document
+ * ```ts
+ * chrome.docTitle.change('My application')
+ * ```
+ *
+ * @example
+ * How to reset the title of the document to it's initial value
+ * ```ts
+ * chrome.docTitle.reset()
+ * ```
+ *
+ * @public
+ * */
+export interface ChromeDocTitle {
+ /**
+ * Changes the current document title.
+ *
+ * @example
+ * How to change the title of the document
+ * ```ts
+ * chrome.docTitle.change('My application title')
+ * chrome.docTitle.change(['My application', 'My section'])
+ * ```
+ *
+ * @param newTitle The new title to set, either a string or string array
+ */
+ change(newTitle: string | string[]): void;
+ /**
+ * Resets the document title to it's initial value.
+ * (meaning the one present in the title meta at application load.)
+ */
+ reset(): void;
+
+ /** @internal */
+ __legacy: {
+ setBaseTitle(baseTitle: string): void;
+ };
+}
+
+const defaultTitle: string[] = [];
+const titleSeparator = ' - ';
+
+/** @internal */
+export class DocTitleService {
+ private document = { title: '' };
+ private baseTitle = '';
+
+ public start({ document }: StartDeps): ChromeDocTitle {
+ this.document = document;
+ this.baseTitle = document.title;
+
+ return {
+ change: (title: string | string[]) => {
+ this.applyTitle(title);
+ },
+ reset: () => {
+ this.applyTitle(defaultTitle);
+ },
+ __legacy: {
+ setBaseTitle: baseTitle => {
+ this.baseTitle = baseTitle;
+ },
+ },
+ };
+ }
+
+ private applyTitle(title: string | string[]) {
+ this.document.title = this.render(title);
+ }
+
+ private render(title: string | string[]) {
+ const parts = [...(isString(title) ? [title] : title), this.baseTitle];
+ // ensuring compat with legacy that might be passing nested arrays
+ return compact(flattenDeep(parts)).join(titleSeparator);
+ }
+}
diff --git a/src/core/public/chrome/doc_title/index.ts b/src/core/public/chrome/doc_title/index.ts
new file mode 100644
index 0000000000000..b070d01953f7a
--- /dev/null
+++ b/src/core/public/chrome/doc_title/index.ts
@@ -0,0 +1,20 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export * from './doc_title_service';
diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts
index 6e03f9e023983..b220a81f775f8 100644
--- a/src/core/public/chrome/index.ts
+++ b/src/core/public/chrome/index.ts
@@ -29,3 +29,4 @@ export {
export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links';
export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed';
export { ChromeNavControl, ChromeNavControls } from './nav_controls';
+export { ChromeDocTitle } from './doc_title';
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index 24201ff0253cb..7391cf7f9454c 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -45,6 +45,7 @@ import {
ChromeNavLink,
ChromeNavLinks,
ChromeNavLinkUpdateableFields,
+ ChromeDocTitle,
ChromeStart,
ChromeRecentlyAccessed,
ChromeRecentlyAccessedHistoryItem,
@@ -250,6 +251,7 @@ export {
ChromeNavLink,
ChromeNavLinks,
ChromeNavLinkUpdateableFields,
+ ChromeDocTitle,
ChromeRecentlyAccessed,
ChromeRecentlyAccessedHistoryItem,
ChromeStart,
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 11a1b5c0d1d9b..416fb13cbb73e 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -105,6 +105,16 @@ export interface ChromeBrand {
// @public (undocumented)
export type ChromeBreadcrumb = Breadcrumb;
+// @public
+export interface ChromeDocTitle {
+ // @internal (undocumented)
+ __legacy: {
+ setBaseTitle(baseTitle: string): void;
+ };
+ change(newTitle: string | string[]): void;
+ reset(): void;
+}
+
// @public (undocumented)
export type ChromeHelpExtension = (element: HTMLDivElement) => () => void;
@@ -186,6 +196,7 @@ export interface ChromeRecentlyAccessedHistoryItem {
// @public
export interface ChromeStart {
addApplicationClass(className: string): void;
+ docTitle: ChromeDocTitle;
getApplicationClasses$(): Observable;
getBadge$(): Observable;
getBrand$(): Observable;
diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap
index f59afc7165bab..286e60cca9712 100644
--- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap
+++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap
@@ -103,6 +103,13 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto
},
"chrome": Object {
"addApplicationClass": [MockFunction],
+ "docTitle": Object {
+ "__legacy": Object {
+ "setBaseTitle": [MockFunction],
+ },
+ "change": [MockFunction],
+ "reset": [MockFunction],
+ },
"getApplicationClasses$": [MockFunction],
"getBadge$": [MockFunction],
"getBrand$": [MockFunction],
@@ -659,6 +666,13 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto
},
"chrome": Object {
"addApplicationClass": [MockFunction],
+ "docTitle": Object {
+ "__legacy": Object {
+ "setBaseTitle": [MockFunction],
+ },
+ "change": [MockFunction],
+ "reset": [MockFunction],
+ },
"getApplicationClasses$": [MockFunction],
"getBadge$": [MockFunction],
"getBrand$": [MockFunction],
@@ -1203,6 +1217,13 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1
},
"chrome": Object {
"addApplicationClass": [MockFunction],
+ "docTitle": Object {
+ "__legacy": Object {
+ "setBaseTitle": [MockFunction],
+ },
+ "change": [MockFunction],
+ "reset": [MockFunction],
+ },
"getApplicationClasses$": [MockFunction],
"getBadge$": [MockFunction],
"getBrand$": [MockFunction],
@@ -1756,6 +1777,13 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1
},
"chrome": Object {
"addApplicationClass": [MockFunction],
+ "docTitle": Object {
+ "__legacy": Object {
+ "setBaseTitle": [MockFunction],
+ },
+ "change": [MockFunction],
+ "reset": [MockFunction],
+ },
"getApplicationClasses$": [MockFunction],
"getBadge$": [MockFunction],
"getBrand$": [MockFunction],
@@ -2300,6 +2328,13 @@ exports[`QueryBarInput Should render the given query 1`] = `
},
"chrome": Object {
"addApplicationClass": [MockFunction],
+ "docTitle": Object {
+ "__legacy": Object {
+ "setBaseTitle": [MockFunction],
+ },
+ "change": [MockFunction],
+ "reset": [MockFunction],
+ },
"getApplicationClasses$": [MockFunction],
"getBadge$": [MockFunction],
"getBrand$": [MockFunction],
@@ -2853,6 +2888,13 @@ exports[`QueryBarInput Should render the given query 1`] = `
},
"chrome": Object {
"addApplicationClass": [MockFunction],
+ "docTitle": Object {
+ "__legacy": Object {
+ "setBaseTitle": [MockFunction],
+ },
+ "change": [MockFunction],
+ "reset": [MockFunction],
+ },
"getApplicationClasses$": [MockFunction],
"getBadge$": [MockFunction],
"getBrand$": [MockFunction],
diff --git a/src/legacy/ui/public/doc_title/__tests__/doc_title.js b/src/legacy/ui/public/doc_title/__tests__/doc_title.js
index b4c3700e36f68..fa8b83f755957 100644
--- a/src/legacy/ui/public/doc_title/__tests__/doc_title.js
+++ b/src/legacy/ui/public/doc_title/__tests__/doc_title.js
@@ -20,7 +20,8 @@
import sinon from 'sinon';
import expect from '@kbn/expect';
import ngMock from 'ng_mock';
-import { setBaseTitle, docTitle } from '../doc_title';
+import { docTitle } from '../doc_title';
+import { npStart } from '../../new_platform';
describe('docTitle Service', function () {
let initialDocTitle;
@@ -30,20 +31,24 @@ describe('docTitle Service', function () {
beforeEach(function () {
initialDocTitle = document.title;
document.title = MAIN_TITLE;
- setBaseTitle(MAIN_TITLE);
+ npStart.core.chrome.docTitle.__legacy.setBaseTitle(MAIN_TITLE);
});
afterEach(function () {
document.title = initialDocTitle;
- setBaseTitle(initialDocTitle);
+ npStart.core.chrome.docTitle.__legacy.setBaseTitle(initialDocTitle);
});
- beforeEach(ngMock.module('kibana', function ($provide) {
- $provide.decorator('$rootScope', decorateWithSpy('$on'));
- }));
+ beforeEach(
+ ngMock.module('kibana', function ($provide) {
+ $provide.decorator('$rootScope', decorateWithSpy('$on'));
+ })
+ );
- beforeEach(ngMock.inject(function ($injector) {
- $rootScope = $injector.get('$rootScope');
- }));
+ beforeEach(
+ ngMock.inject(function ($injector) {
+ $rootScope = $injector.get('$rootScope');
+ })
+ );
describe('setup', function () {
it('resets the title when a route change begins', function () {
@@ -60,13 +65,11 @@ describe('docTitle Service', function () {
});
describe('#reset', function () {
- it('clears the internal state, next update() will write the default', function () {
+ it('clears the internal state', function () {
docTitle.change('some title');
- docTitle.update();
expect(document.title).to.be('some title - ' + MAIN_TITLE);
docTitle.reset();
- docTitle.update();
expect(document.title).to.be(MAIN_TITLE);
});
});
@@ -77,12 +80,6 @@ describe('docTitle Service', function () {
docTitle.change('some secondary title');
expect(document.title).to.be('some secondary title - ' + MAIN_TITLE);
});
-
- it('will write just the first param if the second param is true', function () {
- expect(document.title).to.be(MAIN_TITLE);
- docTitle.change('entire name', true);
- expect(document.title).to.be('entire name');
- });
});
function decorateWithSpy(prop) {
@@ -91,5 +88,4 @@ describe('docTitle Service', function () {
return $delegate;
};
}
-
});
diff --git a/src/legacy/ui/public/doc_title/doc_title.js b/src/legacy/ui/public/doc_title/doc_title.js
index 3692fd71f06cc..0edc55a0ac366 100644
--- a/src/legacy/ui/public/doc_title/doc_title.js
+++ b/src/legacy/ui/public/doc_title/doc_title.js
@@ -17,53 +17,28 @@
* under the License.
*/
-import _ from 'lodash';
+import { isArray } from 'lodash';
import { uiModules } from '../modules';
+import { npStart } from '../new_platform';
-let baseTitle = document.title;
+const npDocTitle = () => npStart.core.chrome.docTitle;
-// for karma test
-export function setBaseTitle(str) {
- baseTitle = str;
-}
-
-let lastChange;
-
-function render() {
- lastChange = lastChange || [];
-
- const parts = [lastChange[0]];
-
- if (!lastChange[1]) parts.push(baseTitle);
-
- return _(parts).flattenDeep().compact().join(' - ');
-}
-
-function change(title, complete) {
- lastChange = [title, complete];
- update();
+function change(title) {
+ npDocTitle().change(isArray(title) ? title : [title]);
}
function reset() {
- lastChange = null;
-}
-
-function update() {
- document.title = render();
+ npDocTitle().reset();
}
export const docTitle = {
- render,
change,
reset,
- update,
};
uiModules.get('kibana')
.run(function ($rootScope) {
// always bind to the route events
$rootScope.$on('$routeChangeStart', docTitle.reset);
- $rootScope.$on('$routeChangeError', docTitle.update);
- $rootScope.$on('$routeChangeSuccess', docTitle.update);
});