Skip to content

Commit

Permalink
feature(get/active-element): facility to obtain the currently active …
Browse files Browse the repository at this point in the history
…element
  • Loading branch information
rodneyrehm committed Sep 11, 2016
1 parent fd74412 commit 63cfb17
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* refactoring all unit and functional tests to use [BDD interface](https://theintern.github.io/intern/#interface-tdd) to improve clarity of a test's intent
* fixing [`ally.maintain.tabFocus`][ally/maintain|tab-focus] to also work with <kbd>Option Tab</kbd> in Safari for macOS - [issue #146](https://github.com/medialize/ally.js/issues/146)
* refactoring `element.prototype.matches` to `util/matches-element`
* adding [`ally.get.activeElement`][ally/get/active-element] - [issue #119](https://github.com/medialize/ally.js/issues/119)


## 1.2.0 - Adios DOMTokenList
Expand Down Expand Up @@ -325,6 +326,7 @@ Version `1.0.0` is a complete rewrite from the the early `0.0.x` releases, there
[ally/fix/pointer-focus-children]: http://allyjs.io/api/fix/pointer-focus-children.html
[ally/fix/pointer-focus-input]: http://allyjs.io/api/fix/pointer-focus-input.html
[ally/fix/pointer-focus-parent]: http://allyjs.io/api/fix/pointer-focus-parent.html
[ally/get/active-element]: http://allyjs.io/api/get/active-element.html
[ally/get/active-elements]: http://allyjs.io/api/get/active-elements.html
[ally/get/focus-target]: http://allyjs.io/api/get/focus-target.html
[ally/get/focus-redirect-target]: http://allyjs.io/api/get/focus-redirect-target.html
Expand Down
1 change: 1 addition & 0 deletions docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Especially when dealing with transitional user interfaces we need to know when a
Sometimes you need some DOM traversal utilities

* [`ally.get.insignificantBranches`](get/insignificant-branches.md) returns an array containing the branches of the DOM that do contain any of the target elements
* [`ally.get.activeElement`](get/active-element.md) identifies the element that has focus


## Values
Expand Down
57 changes: 57 additions & 0 deletions docs/api/get/active-element.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
layout: doc-api.html
tags: shadow-dom
---

# ally.get.activeElement

Identifies the element that currently has focus


## Description

This utility is a safeguard for `document.activeElement` presenting invalid references.


## Usage

```js
var element = ally.get.activeElement();

var iframeElement = ally.get.activeElement({
context: iframeDocument,
});
```

### Arguments


### Returns

[`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLElement).

### Throws


## Examples


## Changes

* Added in `v#master`.


## Notes


## Related resources

* [`ally.get.activeElements`](active-elements.md)


## Contributing

* [module source](https://github.com/medialize/ally.js/blob/master/src/get/active-element.js)
* [document source](https://github.com/medialize/ally.js/blob/master/docs/api/get/active-element.md)
* [unit test](https://github.com/medialize/ally.js/blob/master/test/unit/get.active-element.test.js)

1 change: 1 addition & 0 deletions docs/api/get/active-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Array of [`HTMLElement`](https://developer.mozilla.org/en/docs/Web/API/HTMLEleme

## Related resources

* [`ally.get.activeElements`](active-elements.md)
* [`ally.get.shadowHostParents`](shadow-host-parents.md) is used to identify an elements `ShadowHost` ancestry


Expand Down
2 changes: 2 additions & 0 deletions src/get/_get.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

// exporting modules to be included the UMD bundle

import activeElement from './active-element';
import activeElements from './active-elements';
import focusRedirectTarget from './focus-redirect-target';
import focusTarget from './focus-target';
Expand All @@ -9,6 +10,7 @@ import parents from './parents';
import shadowHostParents from './shadow-host-parents';
import shadowHost from './shadow-host';
export default {
activeElement,
activeElements,
focusRedirectTarget,
focusTarget,
Expand Down
32 changes: 32 additions & 0 deletions src/get/active-element.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

/*
create ally.get.activeElement()
wrapping ally.get.activeElements()
fix ally.get.activeElements()
https://github.com/jquery/jquery-ui/blob/ffcfb85c9818954adda69e73cf9ba76ea07b554c/ui/safe-active-element.js
*/

import getDocument from '../util/get-document';

export default function({ context } = {}) {
const _document = getDocument(context);
let activeElement;

try {
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
// see https://github.com/jquery/jquery-ui/blob/ffcfb85c9818954adda69e73cf9ba76ea07b554c/ui/safe-active-element.js#L15-L21
activeElement = _document.activeElement;
} catch (e) {
// ignore
}

// IE11 may return null instead of an element
// see https://github.com/jquery/jquery-ui/blob/ffcfb85c9818954adda69e73cf9ba76ea07b554c/ui/safe-active-element.js#L23-L28
// https://github.com/jquery/jquery-ui/blob/ffcfb85c9818954adda69e73cf9ba76ea07b554c/ui/safe-active-element.js#L30-L35
if (!activeElement || !activeElement.nodeType) {
activeElement = _document.body || _document.documentElement;
}

return activeElement;
}
1 change: 1 addition & 0 deletions test/helper/ally-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ define([], function() {
'visible',
],
get: [
'active-element',
'active-elements',
'focus-redirect-target',
'focus-target',
Expand Down
86 changes: 86 additions & 0 deletions test/unit/get.active-element.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
define(function(require) {
'use strict';

var bdd = require('intern!bdd');
var expect = require('intern/chai!expect');
var focusableFixture = require('../helper/fixtures/focusable.fixture');
var TestFrame = require('../helper/test-frame');
var getActiveElement = require('ally/get/active-element');

bdd.describe('get/active-element', function() {
var fixture;
var frame;

bdd.before(function() {
fixture = focusableFixture();

frame = new TestFrame([
/*eslint-disable indent */
'<!DOCTYPE html>',
'<html lang="en">',
'<head>',
'<meta charset="utf-8" />',
'<title>Framed Content</title>',
'</head>',
'<body>',
'<p id="target" tabindex="0">Hello World</p>',
'</body>',
'</html>',
/*eslint-enable indent */
].join(''));

return frame.initialize(document.body);
});

bdd.after(function() {
fixture.remove();
fixture = null;
frame.terminate();
frame = null;
});

bdd.it('should return the active element of the current document', function() {
var target = document.getElementById('tabindex-1');
target.focus();

var result = getActiveElement();
expect(result).to.equal(target);
});

bdd.it('should return the active element of the given document', function() {
var target = document.getElementById('tabindex-0');
target.focus();

var result = getActiveElement({
context: document,
});
expect(result).to.equal(target);
});

bdd.describe('for iframe', function() {
var target;

bdd.before(function() {
target = frame.document.getElementById('target');
target.focus();
});

bdd.it('should return the iframe as the active element in document', function() {
var result = getActiveElement({
context: document,
});

expect(result).to.equal(frame.element);
});

bdd.it('should return the active element within iframe', function() {
var result = getActiveElement({
context: frame.document,
});

expect(result).to.equal(target);
});
});

});
});

0 comments on commit 63cfb17

Please sign in to comment.