After clicking the button below, a counter will be appended to this page's title in the browser and the number will increment on each subsequent button push.
+
+
+
+
+
+
+
+
+
diff --git a/extensions/amp-bind/0.1/bind-impl.js b/extensions/amp-bind/0.1/bind-impl.js
index d9567df6492a..c87cf31dcaba 100644
--- a/extensions/amp-bind/0.1/bind-impl.js
+++ b/extensions/amp-bind/0.1/bind-impl.js
@@ -23,13 +23,13 @@ import {ChunkPriority, chunk} from '../../../src/chunk';
import {Services} from '../../../src/services';
import {deepMerge, dict} from '../../../src/utils/object';
import {dev, user} from '../../../src/log';
+import {elementByTag, iterateCursor, waitForBodyPromise} from '../../../src/dom';
import {filterSplice} from '../../../src/utils/array';
import {getMode} from '../../../src/mode';
import {installServiceInEmbedScope} from '../../../src/service';
import {invokeWebWorker} from '../../../src/web-worker/amp-worker';
import {isArray, isObject, toArray} from '../../../src/types';
import {isFiniteNumber} from '../../../src/types';
-import {iterateCursor, waitForBodyPromise} from '../../../src/dom';
import {map} from '../../../src/utils/object';
import {parseJson, recursiveEquals} from '../../../src/json';
import {reportError} from '../../../src/error';
@@ -161,7 +161,8 @@ export class Bind {
*/
this.initializePromise_ =
this.viewer_.whenFirstVisible().then(() => bodyPromise).then(body => {
- return this.initialize_(body);
+ return this.initialize_(
+ body, elementByTag(ampdoc.getHeadNode(), 'title'));
});
/** @private {Promise} */
@@ -282,14 +283,19 @@ export class Bind {
/**
* Scans the ampdoc for bindings and creates the expression evaluator.
* @param {!Node} rootNode
+ * @param {Node} titleNode
* @return {!Promise}
* @private
*/
- initialize_(rootNode) {
+ initialize_(rootNode, titleNode) {
dev().fine(TAG, 'Scanning DOM for bindings and macros...');
+ const nodes = [rootNode];
+ if (titleNode) {
+ nodes.push(titleNode);
+ }
let promise = Promise.all([
this.addMacros_(),
- this.addBindingsForNodes_([rootNode])]
+ this.addBindingsForNodes_(nodes)]
).then(() => {
// Listen for DOM updates (e.g. template render) to rescan for bindings.
rootNode.addEventListener(AmpEvents.DOM_UPDATE, this.boundOnDomUpdate_);
@@ -868,6 +874,9 @@ export class Bind {
switch (property) {
case 'text':
element.textContent = String(newValue);
+ if (tag === 'TITLE') {
+ this.localWin_.document.title = String(newValue);
+ }
// Setting `textContent` on TEXTAREA element only works if user
// has not interacted with the element, therefore `value` also needs
// to be set (but `value` is not an attribute on TEXTAREA)
diff --git a/extensions/amp-bind/0.1/test/integration/test-bind-impl.js b/extensions/amp-bind/0.1/test/integration/test-bind-impl.js
index 5f8266e45048..02de5773a295 100644
--- a/extensions/amp-bind/0.1/test/integration/test-bind-impl.js
+++ b/extensions/amp-bind/0.1/test/integration/test-bind-impl.js
@@ -368,6 +368,16 @@ describe.configure().ifNewChrome().run('Bind', function() {
});
});
+ it('should update document title for elements', () => {
+ const element = createElement(
+ env, container, '[text]="\'a\' + \'b\' + \'c\'"', 'title');
+ element.value = 'foo';
+ return onBindReadyAndSetState(env, bind, {}).then(() => {
+ expect(element.value).to.equal('abc');
+ expect(env.win.document.title).to.equal('abc');
+ });
+ });
+
it('should support binding to CSS classes with strings', () => {
const element = createElement(env, container, '[class]="[\'abc\']"');
expect(toArray(element.classList)).to.deep.equal([]);
diff --git a/validator/validator-main.protoascii b/validator/validator-main.protoascii
index b022e73851f2..ce34abe4df2a 100644
--- a/validator/validator-main.protoascii
+++ b/validator/validator-main.protoascii
@@ -120,6 +120,7 @@ tags: {
tags: {
tag_name: "TITLE"
spec_name: "title"
+ attrs: { name: "[text]" }
}
# 4.2.3 the base element
tags: {