make nav keyboard accessible
This commit is contained in:
parent
7d449e63b9
commit
087f319a8a
2 changed files with 108 additions and 16 deletions
|
@ -12,10 +12,15 @@ class Nav extends React.PureComponent {
|
|||
this.state = {
|
||||
dropdownOpen: 'none'
|
||||
};
|
||||
this.handleFocus = this.handleFocus.bind(this);
|
||||
this.handleBlur = this.handleBlur.bind(this);
|
||||
this.clearHideTimeout = this.clearHideTimeout.bind(this);
|
||||
}
|
||||
|
||||
isUserOwner() {
|
||||
return this.props.project.owner && this.props.project.owner.id === this.props.user.id;
|
||||
setDropdown(dropdown) {
|
||||
this.setState({
|
||||
dropdownOpen: dropdown
|
||||
});
|
||||
}
|
||||
|
||||
toggleDropdown(dropdown) {
|
||||
|
@ -30,6 +35,26 @@ class Nav extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
isUserOwner() {
|
||||
return this.props.project.owner && this.props.project.owner.id === this.props.user.id;
|
||||
}
|
||||
|
||||
handleFocus(dropdown) {
|
||||
this.clearHideTimeout();
|
||||
this.setDropdown(dropdown);
|
||||
}
|
||||
|
||||
clearHideTimeout() {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
handleBlur() {
|
||||
this.timer = setTimeout(this.setDropdown.bind(this, 'none'), 10);
|
||||
}
|
||||
|
||||
render() {
|
||||
const navDropdownState = {
|
||||
file: classNames({
|
||||
|
@ -62,7 +87,8 @@ class Nav extends React.PureComponent {
|
|||
<li className={navDropdownState.file}>
|
||||
<button
|
||||
onClick={this.toggleDropdown.bind(this, 'file')}
|
||||
onBlur={this.toggleDropdown.bind(this, 'none')}
|
||||
onBlur={this.handleBlur}
|
||||
onFocus={this.clearHideTimeout}
|
||||
>
|
||||
<span className="nav__item-header">File</span>
|
||||
<InlineSVG src={triangleUrl} />
|
||||
|
@ -81,6 +107,8 @@ class Nav extends React.PureComponent {
|
|||
this.props.newProject();
|
||||
}
|
||||
}}
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
New
|
||||
</button>
|
||||
|
@ -95,37 +123,57 @@ class Nav extends React.PureComponent {
|
|||
this.props.showErrorModal('forceAuthentication');
|
||||
}
|
||||
}}
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</li> }
|
||||
{ this.props.project.id && this.props.user.authenticated &&
|
||||
<li className="nav__dropdown-item">
|
||||
<button onClick={this.props.cloneProject}>
|
||||
<button
|
||||
onClick={this.props.cloneProject}
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Duplicate
|
||||
</button>
|
||||
</li> }
|
||||
{ this.props.project.id &&
|
||||
<li className="nav__dropdown-item">
|
||||
<button onClick={this.props.showShareModal}>
|
||||
<button
|
||||
onClick={this.props.showShareModal}
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Share
|
||||
</button>
|
||||
</li> }
|
||||
{ this.props.project.id &&
|
||||
<li className="nav__dropdown-item">
|
||||
<button onClick={() => this.props.exportProjectAsZip(this.props.project.id)}>
|
||||
<button
|
||||
onClick={() => this.props.exportProjectAsZip(this.props.project.id)}
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
</li> }
|
||||
{ this.props.user.authenticated &&
|
||||
<li className="nav__dropdown-item">
|
||||
<Link to={`/${this.props.user.username}/sketches`}>
|
||||
<Link
|
||||
to={`/${this.props.user.username}/sketches`}
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Open
|
||||
</Link>
|
||||
</li> }
|
||||
<li className="nav__dropdown-item">
|
||||
<Link
|
||||
to="/p5/sketches"
|
||||
onFocus={this.handleFocus.bind(this, 'file')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Examples
|
||||
</Link>
|
||||
|
@ -133,7 +181,11 @@ class Nav extends React.PureComponent {
|
|||
</ul>
|
||||
</li>
|
||||
<li className={navDropdownState.edit}>
|
||||
<button onClick={this.toggleDropdown.bind(this, 'edit')}>
|
||||
<button
|
||||
onClick={this.toggleDropdown.bind(this, 'edit')}
|
||||
onBlur={this.handleBlur}
|
||||
onFocus={this.clearHideTimeout}
|
||||
>
|
||||
<span className="nav__item-header">Edit</span>
|
||||
<InlineSVG src={triangleUrl} />
|
||||
</button>
|
||||
|
@ -151,7 +203,11 @@ class Nav extends React.PureComponent {
|
|||
</ul>
|
||||
</li>
|
||||
<li className={navDropdownState.sketch}>
|
||||
<button onClick={this.toggleDropdown.bind(this, 'sketch')}>
|
||||
<button
|
||||
onClick={this.toggleDropdown.bind(this, 'sketch')}
|
||||
onBlur={this.handleBlur}
|
||||
onFocus={this.clearHideTimeout}
|
||||
>
|
||||
<span className="nav__item-header">Sketch</span>
|
||||
<InlineSVG src={triangleUrl} />
|
||||
</button>
|
||||
|
@ -169,7 +225,11 @@ class Nav extends React.PureComponent {
|
|||
</ul>
|
||||
</li>
|
||||
<li className={navDropdownState.help}>
|
||||
<button onClick={this.toggleDropdown.bind(this, 'help')}>
|
||||
<button
|
||||
onClick={this.toggleDropdown.bind(this, 'help')}
|
||||
onBlur={this.handleBlur}
|
||||
onFocus={this.clearHideTimeout}
|
||||
>
|
||||
<span className="nav__item-header">Help</span>
|
||||
<InlineSVG src={triangleUrl} />
|
||||
</button>
|
||||
|
@ -186,10 +246,16 @@ class Nav extends React.PureComponent {
|
|||
href="https://p5js.org/reference/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onFocus={this.handleFocus.bind(this, 'help')}
|
||||
onBlur={this.handleBlur}
|
||||
>Reference</a>
|
||||
</li>
|
||||
<li className="nav__dropdown-item">
|
||||
<Link to="/about">
|
||||
<Link
|
||||
to="/about"
|
||||
onFocus={this.handleFocus.bind(this, 'help')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
About
|
||||
</Link>
|
||||
</li>
|
||||
|
@ -216,6 +282,8 @@ class Nav extends React.PureComponent {
|
|||
<button
|
||||
className="nav__item-header"
|
||||
onClick={this.toggleDropdown.bind(this, 'account')}
|
||||
onBlur={this.handleBlur}
|
||||
onFocus={this.clearHideTimeout}
|
||||
>
|
||||
My Account
|
||||
</button>
|
||||
|
@ -226,22 +294,38 @@ class Nav extends React.PureComponent {
|
|||
<InlineSVG src={triangleUrl} />
|
||||
</li>
|
||||
<li className="nav__dropdown-item">
|
||||
<Link to={`/${this.props.user.username}/sketches`}>
|
||||
<Link
|
||||
to={`/${this.props.user.username}/sketches`}
|
||||
onFocus={this.handleFocus.bind(this, 'account')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
My sketches
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav__dropdown-item">
|
||||
<Link to={`/${this.props.user.username}/assets`}>
|
||||
<Link
|
||||
to={`/${this.props.user.username}/assets`}
|
||||
onFocus={this.handleFocus.bind(this, 'account')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
My assets
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav__dropdown-item">
|
||||
<Link to={`/${this.props.user.username}/account`}>
|
||||
<Link
|
||||
to={`/${this.props.user.username}/account`}
|
||||
onFocus={this.handleFocus.bind(this, 'account')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Settings
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav__dropdown-item">
|
||||
<button onClick={this.props.logoutUser} >
|
||||
<button
|
||||
onClick={this.props.logoutUser}
|
||||
onFocus={this.handleFocus.bind(this, 'account')}
|
||||
onBlur={this.handleBlur}
|
||||
>
|
||||
Log out
|
||||
</button>
|
||||
</li>
|
||||
|
|
|
@ -152,6 +152,14 @@ class PreviewFrame extends React.Component {
|
|||
doc.srcDoc = '';
|
||||
}
|
||||
|
||||
addLoopProtect(sketchDoc) {
|
||||
const scriptsInHTML = sketchDoc.getElementsByTagName('script');
|
||||
const scriptsInHTMLArray = Array.prototype.slice.call(scriptsInHTML);
|
||||
scriptsInHTMLArray.forEach((script) => {
|
||||
script.innerHTML = loopProtect(script.innerHTML); // eslint-disable-line
|
||||
});
|
||||
}
|
||||
|
||||
injectLocalFiles() {
|
||||
const htmlFile = this.props.htmlFile.content;
|
||||
let scriptOffs = [];
|
||||
|
@ -227,7 +235,7 @@ class PreviewFrame extends React.Component {
|
|||
scriptOffs = getAllScriptOffsets(sketchDocString);
|
||||
const consoleErrorsScript = sketchDoc.createElement('script');
|
||||
consoleErrorsScript.innerHTML = hijackConsoleErrorsScript(JSON.stringify(scriptOffs));
|
||||
// sketchDoc.head.appendChild(consoleErrorsScript);
|
||||
this.addLoopProtect(sketchDoc);
|
||||
sketchDoc.head.insertBefore(consoleErrorsScript, sketchDoc.head.firstElement);
|
||||
|
||||
return `<!DOCTYPE HTML>\n${sketchDoc.documentElement.outerHTML}`;
|
||||
|
|
Loading…
Reference in a new issue