Skip to content

Commit

Permalink
inabox-lite: setup input mode classes. (ampproject#25404)
Browse files Browse the repository at this point in the history
* inabox-lite: reuse code to toggle body classes based on user input.

* Rename

* Add test
  • Loading branch information
lannka authored Nov 4, 2019
1 parent abcfae6 commit a34a0ab
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 28 deletions.
4 changes: 4 additions & 0 deletions src/inabox/inabox-resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {Observable} from '../observable';
import {Pass} from '../pass';
import {READY_SCAN_SIGNAL} from '../service/resources-interface';
import {Resource, ResourceState} from '../service/resource';
import {Services} from '../services';
import {dev} from '../log';
import {registerServiceBuilderForDoc} from '../service';

Expand Down Expand Up @@ -58,6 +59,9 @@ export class InaboxResources {

/** @const @private {!InaboxMutator} */
this.mutator_ = new InaboxMutator(ampdoc, this);

const input = Services.inputFor(this.win);
input.setupInputModeClasses(ampdoc);
}

/** @override */
Expand Down
31 changes: 31 additions & 0 deletions src/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ export class Input {
}
}

/**
* See https://github.com/ampproject/amphtml/blob/master/spec/amp-css-classes.md#input-mode-classes
* @param {!./service/ampdoc-impl.AmpDoc} ampdoc
*/
setupInputModeClasses(ampdoc) {
this.onTouchDetected(detected => {
this.toggleInputClass_(ampdoc, 'amp-mode-touch', detected);
}, true);
this.onMouseDetected(detected => {
this.toggleInputClass_(ampdoc, 'amp-mode-mouse', detected);
}, true);
this.onKeyboardStateChanged(active => {
this.toggleInputClass_(ampdoc, 'amp-mode-keyboard-active', active);
}, true);
}

/**
* Whether the touch input has been detected.
* @return {boolean}
Expand Down Expand Up @@ -154,6 +170,21 @@ export class Input {
return this.keyboardStateObservable_.add(handler);
}

/**
* @param {!./service/ampdoc-impl.AmpDoc} ampdoc
* @param {string} clazz
* @param {boolean} on
* @private
*/
toggleInputClass_(ampdoc, clazz, on) {
ampdoc.waitForBodyOpen().then(body => {
const vsync = Services./*OK*/ vsyncFor(this.win);
vsync.mutate(() => {
body.classList.toggle(clazz, on);
});
});
}

/**
* @param {!Event} e
* @private
Expand Down
30 changes: 2 additions & 28 deletions src/service/resources-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ export class ResourcesImpl {
// No promise means that there's no problem.
remeasure();
}
this.monitorInput_();
const input = Services.inputFor(this.win);
input.setupInputModeClasses(this.ampdoc);

// Safari 10 and under incorrectly estimates font spacing for
// `@font-face` fonts. This leads to wild measurement errors. The best
Expand Down Expand Up @@ -317,33 +318,6 @@ export class ResourcesImpl {
return this.ampdoc;
}

/** @private */
monitorInput_() {
const input = Services.inputFor(this.win);
input.onTouchDetected(detected => {
this.toggleInputClass_('amp-mode-touch', detected);
}, true);
input.onMouseDetected(detected => {
this.toggleInputClass_('amp-mode-mouse', detected);
}, true);
input.onKeyboardStateChanged(active => {
this.toggleInputClass_('amp-mode-keyboard-active', active);
}, true);
}

/**
* @param {string} clazz
* @param {boolean} on
* @private
*/
toggleInputClass_(clazz, on) {
this.ampdoc.waitForBodyOpen().then(body => {
this.vsync_.mutate(() => {
body.classList.toggle(clazz, on);
});
});
}

/** @override */
getResourceForElement(element) {
return Resource.forElement(element);
Expand Down
42 changes: 42 additions & 0 deletions test/unit/test-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import {Input} from '../../src/input';
import {installTimerService} from '../../src/service/timer-impl.js';
import {stubService} from '../../testing/test-helper';

describe('Input', () => {
let sandbox;
Expand Down Expand Up @@ -216,3 +217,44 @@ describe('Input', () => {
expect(kbActive).to.equal(undefined);
});
});

describes.realWin('test-input.js setupInputModeClasses', {amp: false}, env => {
let ampdoc;
let input;
let body;

beforeEach(() => {
body = env.win.document.body;
ampdoc = {
waitForBodyOpen: () => Promise.resolve(body),
};
stubService(env.sandbox, env.win, 'vsync', 'mutate').callsFake(func => {
func();
});
input = new Input(env.win);
input.setupInputModeClasses(ampdoc);
});

it('should add amp-mode-mouse class to body when mouseConfirmed', async () => {
expect(body).to.not.have.class('amp-mode-mouse');
input.mouseConfirmed_();
await new Promise(setTimeout);
expect(body).to.have.class('amp-mode-mouse');
});

it('should add amp-mode-keyboard-active class to body when onKeyDown', async () => {
expect(body).to.not.have.class('amp-mode-keyboard-active');
simulateKeyDown();
await new Promise(setTimeout);
expect(body).to.have.class('amp-mode-keyboard-active');
});

function simulateKeyDown() {
const event = new /*OK*/ KeyboardEvent('keydown', {
'keyCode': 65,
'which': 65,
bubbles: true,
});
env.win.document.body.dispatchEvent(event);
}
});

0 comments on commit a34a0ab

Please sign in to comment.