2017-04-23 01:05:36 +02:00
|
|
|
|
import Inferno from 'inferno';
|
2018-02-22 07:47:39 +01:00
|
|
|
|
import { Component } from 'inferno';
|
2017-11-15 21:59:58 +01:00
|
|
|
|
import PropTypes from 'prop-types';
|
2017-04-23 01:05:36 +02:00
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
const phondueUsage = require('../../../vendor/KeyboardFire/phondue/usage.html');
|
2017-04-28 00:28:01 +02:00
|
|
|
|
const digraphs = require('../../../vendor/KeyboardFire/phondue/digraphs.json');
|
2017-04-27 22:33:25 +02:00
|
|
|
|
|
2017-07-26 06:11:33 +02:00
|
|
|
|
import { IPATable } from './IPATable';
|
2017-04-27 22:33:25 +02:00
|
|
|
|
|
2017-04-23 01:05:36 +02:00
|
|
|
|
export class IPAField extends Component {
|
2017-04-27 22:33:25 +02:00
|
|
|
|
/*
|
|
|
|
|
Modified from KeyboardFire's Phondue project (https://github.com/KeyboardFire/phondue)
|
|
|
|
|
to fit React/Inferno and Lexiconga
|
|
|
|
|
*/
|
2017-04-23 01:05:36 +02:00
|
|
|
|
constructor (props) {
|
|
|
|
|
super(props);
|
|
|
|
|
|
2017-11-15 21:59:58 +01:00
|
|
|
|
PropTypes.checkPropTypes({
|
|
|
|
|
value: PropTypes.string.isRequired,
|
|
|
|
|
id: PropTypes.string,
|
|
|
|
|
label: PropTypes.string,
|
|
|
|
|
helpText: PropTypes.string,
|
|
|
|
|
placeholder: PropTypes.string,
|
|
|
|
|
isDisplayOnly: PropTypes.bool,
|
|
|
|
|
onInput: PropTypes.func,
|
|
|
|
|
onChange: PropTypes.func,
|
|
|
|
|
}, props, 'prop', 'IPAField');
|
|
|
|
|
|
2017-04-23 01:05:36 +02:00
|
|
|
|
this.state = {
|
2017-07-26 06:11:33 +02:00
|
|
|
|
value: props.value || '',
|
|
|
|
|
doShowHelp: false,
|
|
|
|
|
doShowTable: false,
|
2017-04-23 01:05:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
this.field = null;
|
2017-04-26 07:13:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-19 06:27:16 +02:00
|
|
|
|
componentWillReceiveProps (nextProps) {
|
|
|
|
|
this.setState({
|
2017-07-26 06:11:33 +02:00
|
|
|
|
value: nextProps.value,
|
2017-05-19 06:27:16 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
showHelp () {
|
|
|
|
|
if (this.state.doShowHelp) {
|
|
|
|
|
return (
|
|
|
|
|
<div className='modal is-active'>
|
|
|
|
|
<div className='modal-background'
|
2017-07-26 06:11:33 +02:00
|
|
|
|
onClick={ () => this.setState({ doShowHelp: false }) } />
|
2017-04-27 22:33:25 +02:00
|
|
|
|
<div className='modal-card'>
|
2017-04-28 00:28:01 +02:00
|
|
|
|
<header className='modal-card-head'>
|
|
|
|
|
<h3 className='modal-card-title'>
|
|
|
|
|
IPA Shortcuts
|
|
|
|
|
</h3>
|
|
|
|
|
<button className='delete'
|
2017-07-26 06:11:33 +02:00
|
|
|
|
onClick={ () => this.setState({ doShowHelp: false }) } />
|
2017-04-28 00:28:01 +02:00
|
|
|
|
</header>
|
|
|
|
|
<section className='modal-card-body'>
|
2017-04-27 22:33:25 +02:00
|
|
|
|
|
|
|
|
|
<div className='content'
|
2017-07-26 06:11:33 +02:00
|
|
|
|
dangerouslySetInnerHTML={{
|
|
|
|
|
__html: phondueUsage,
|
|
|
|
|
}} />
|
2017-04-26 07:13:59 +02:00
|
|
|
|
|
2017-04-28 00:28:01 +02:00
|
|
|
|
</section>
|
2017-04-27 22:33:25 +02:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2017-04-26 07:13:59 +02:00
|
|
|
|
}
|
2017-04-23 01:05:36 +02:00
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
showTable () {
|
|
|
|
|
if (this.state.doShowTable) {
|
|
|
|
|
return (
|
2017-04-28 01:03:01 +02:00
|
|
|
|
<IPATable
|
2017-07-26 06:11:33 +02:00
|
|
|
|
value={ this.state.value }
|
2017-12-10 22:30:22 +01:00
|
|
|
|
close={ () => this.setState({ doShowTable: false }, () => this.field.focus()) }
|
2017-07-26 06:11:33 +02:00
|
|
|
|
update={ (newValue) => this.setState({ value: newValue }, this.field.focus()) } />
|
2017-04-27 22:33:25 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
2017-04-23 01:05:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
showButtons () {
|
|
|
|
|
if (!this.props.isDisplayOnly) {
|
2017-04-23 01:05:36 +02:00
|
|
|
|
return (
|
2017-04-27 22:33:25 +02:00
|
|
|
|
<div>
|
|
|
|
|
<div className='help'>
|
|
|
|
|
<a className='button is-small'
|
2017-07-26 06:11:33 +02:00
|
|
|
|
onClick={ () => this.setState({ doShowHelp: true }) }>
|
2017-04-27 22:33:25 +02:00
|
|
|
|
Field Help
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<a className='button is-small'
|
2017-07-26 06:11:33 +02:00
|
|
|
|
onClick={ () => this.setState({ doShowTable: true }) }>
|
2017-04-27 22:33:25 +02:00
|
|
|
|
Show IPA Table
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
2017-07-26 06:11:33 +02:00
|
|
|
|
{ this.showHelp() } { this.showTable() }
|
2017-04-23 01:05:36 +02:00
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
onInput (event) {
|
2017-07-26 06:11:33 +02:00
|
|
|
|
let val = event.target.value,
|
|
|
|
|
pos = this.field.selectionStart || val.length;
|
2017-04-26 07:13:59 +02:00
|
|
|
|
|
2017-04-27 22:33:25 +02:00
|
|
|
|
if (event.key) {
|
2017-07-26 06:11:33 +02:00
|
|
|
|
const key = event.key,
|
|
|
|
|
digraph = digraphs[val.substr(pos - 1, 1) + key];
|
2017-04-27 22:33:25 +02:00
|
|
|
|
|
|
|
|
|
if (digraph) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
val = val.slice(0, pos - 1) + digraph + val.slice(pos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (val !== this.state.value) {
|
|
|
|
|
this.setState({ value: val }, () => {
|
|
|
|
|
this.field.focus();
|
|
|
|
|
this.field.setSelectionRange(pos, pos);
|
2017-08-20 22:44:12 +02:00
|
|
|
|
|
|
|
|
|
if (this.props.onInput) {
|
|
|
|
|
this.props.onInput(this.state.value);
|
|
|
|
|
}
|
2017-04-27 22:33:25 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
2017-04-26 07:13:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-20 22:44:12 +02:00
|
|
|
|
onChange () {
|
|
|
|
|
if (this.props.onChange) {
|
|
|
|
|
this.props.onChange(this.state.value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-23 01:05:36 +02:00
|
|
|
|
render () {
|
|
|
|
|
return (
|
|
|
|
|
<div className='field'>
|
2017-08-20 22:44:12 +02:00
|
|
|
|
<label className='label' htmlFor={ this.props.id || null }>
|
|
|
|
|
{ this.props.label || 'Pronunciation' }
|
|
|
|
|
</label>
|
|
|
|
|
{
|
|
|
|
|
this.props.helpText
|
|
|
|
|
&& (
|
|
|
|
|
<p className='help'>
|
|
|
|
|
{ this.props.helpText }
|
|
|
|
|
</p>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
<div className='control'>
|
|
|
|
|
<input className='input' id={ this.props.id || null } type='text'
|
|
|
|
|
placeholder={ this.props.placeholder || '[prə.ˌnʌn.si.ˈeɪ.ʃən]' }
|
2017-07-26 06:11:33 +02:00
|
|
|
|
disabled={ !!this.props.isDisplayOnly }
|
|
|
|
|
ref={ (input) => this.field = input }
|
|
|
|
|
value={ this.state.value }
|
|
|
|
|
onInput={ (event) => this.onInput(event) }
|
|
|
|
|
onKeyDown={ (event) => this.onInput(event) }
|
2017-08-20 22:44:12 +02:00
|
|
|
|
onChange={ () => this.onChange() } />
|
|
|
|
|
</div>
|
2017-07-26 06:11:33 +02:00
|
|
|
|
{ this.showButtons() }
|
2017-04-23 01:05:36 +02:00
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|