Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
気の利いた入力コンポーネント
Search
ymrl
April 08, 2016
Technology
1.8k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
気の利いた入力コンポーネント
ymrl
April 08, 2016
More Decks by ymrl
See All by ymrl
たのしいtable / Fun table
ymrl
0
26
freeeのアクセシビリティの現在地 / freee's Current Position on Accessibility
ymrl
4
1.6k
全社でアクセシビリティに取り組む / Company-wide Accessibility Initiatives
ymrl
1
980
デザイナーがTSKaigiでWAI-ARIAの話をしてみて / Speaking as a Designer: WAI-ARIA at TSKaigi
ymrl
0
720
TypeScriptとReactで、WAI-ARIAの属性を正しく利用する / Fixing WAI-ARIA Typing in React with TypeScript
ymrl
1
970
がんばらないアクセシビリティ / Accessibility Without the Struggle
ymrl
0
1.1k
Webサイトのアクセシビリティにどう向き合う? / How Should We Approach Web Accessibility?
ymrl
0
190
いま求められるソフトウェアのアクセシビリティ / Essential Accessibility in Software Today
ymrl
1
1.7k
アクセシビリティを意識したプロダクトづくり / Creating Products with Accessibility in Mind
ymrl
0
24k
Other Decks in Technology
See All in Technology
紙 to デジタル
ichien178
0
470
Digital Credentials API × OpenID4VP ブラウザ完結型本人確認の実装知見(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
380
Microsoft MVP プログラムを紹介するから目指す人増えてくれ
tsubakimoto_s
0
160
PdMをやめて、 "プロダクトビルダー"という 働き方に変えました / PdM to Product Builder
shikichee
2
530
AI駆動開発はどこまで来たのか? ファインディの最新実態調査で読み解く現在地 Devin Con Tokyo
akiratom
4
2.2k
パスキーでドライブする アカウント統合(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
420
Hub & Spoke 環境のネットワークルーティングを分解してみる
tsuyataku
1
460
信頼性はSREだけのものじゃない
hkawaras
0
410
サイボウズ 開発本部採用ピッチ / Cybozu Engineer Recruit
cybozuinsideout
PRO
12
86k
internal/testlog で遊ぼう
rokuosan
0
430
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
20k
dbt と Snowflake と tag
kevinrobot34
2
310
Featured
See All Featured
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
280
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
510
Thoughts on Productivity
jonyablonski
76
5.3k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
4
520
Optimising Largest Contentful Paint
csswizardry
37
3.9k
Done Done
chrislema
186
16k
Producing Creativity
orderedlist
PRO
348
40k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
220
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
590
Raft: Consensus for Rubyists
vanstee
141
7.7k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Transcript
ؾͷར͍ͨ ೖྗίϯϙʔωϯτͷ !ZNSM
͜ͷεϥΠυຕ ͋ΔͷͰۦ͚Ͱ αϯϓϧίʔυ͜͜ɿ IUUQTHJUIVCDPNZNSMJOQVUDPNQPOFOUFYBNQMFT
୭ w !ZNSMʢ·͋Δʣ w ࣾձਓྺGSFFFྺ w 6*Λߟ͑Δͷͱ$44ॻ͘ͷ͕͖
ೖྗίϯϙʔωϯτ ʢ·͋ɺUFYUBSFBͱ͔͋Δ͚Ͳʣ
څ༩ܭࢉGSFFFͷͱ͋Δը໘
IUUQTXXXKSFBTUDPKQPUPOBEPDVNFOU@SFRVFTU
IUUQTUXJUUFSDPNZNSMTUBUVT
ආ͚ΒΕͳ͍িಥ w ։ൃऀࢹɿ͍ΖΜͳ߹͕͋ΜͶΜ w Ϣʔβʔࢹɿ։ൃऀͷ߹ͳΜͯΒΜ w Τϥʔ͕ग़ͯΠϥοͱͨ͘͠ͳ͍ w શ֯ͱ֯ͷ۠ผͳΜ͔ͯͭͳ͍ w
ͦͦͲ͏͍͏ܗࣜͰೖΕΔͷ͔Θ͔Βͳ͍
ؾΛޮ͔͍ͤͨ w શ֯֯ͷมͱ͔ϑϩϯτΤϯυͰͬͪΌ͑ w ॳΊͯͷϢʔβʔ͕໎ΘͣʹೖྗͰ͖Δ w ׳ΕͯΔϢʔβʔ͕ߴʹೖྗͰ͖Δ w ։ൃऀ͕΄͍͠ܗࣜΛ͑Δ͜ͱͰ͖Δʢ͔ʣ w
͔࣍ΒͦͷܗࣜͰೖΕͯΒ͑Δʢ͔ʣ
ؾΛར͔ͤͯΔྫ w શ֯ˠ͕֯ΔͷͰ*.&Φϯͷ··ೖྗ0, w ֹۚཝ͕Λ ʹͯ͘͠ΕΔ w ཝ͕Λʹͯ͘͠ΕΔ w ࣌ࠁཝͰΛʹͯ͘͠ΕΔ
w ༣ศ൪߸ཝͰϋΠϑϯ͕ࣗಈతʹิΘΕΔ
ʢ͓͞Β͍ʣ3FBDUͷ ೖྗίϯϙʔωϯτ
͜Μͳײ͡ class NormalInput extends React.Component { handleChange(e) { const value
= e.target.value; this.props.onChange(e, value); } render() { return( <input type="text" value={this.props.value} onChange={this.handleChange.bind(this)} /> ); } } ίϯϙʔωϯτʹ มߋ༰Λ௨͢Δ ͕͏͔͠Εͳ͍ͷͰ 4ZOUIFUJD&WFOUΛୈҰҾʹͯ͠Δ
͔ͭ͏ <NormalInput type="text" value={ this.state.value } onChange={(_e, value)=>this.setState({ value: value
})} />
શ֯ӳʹม͢Δ handleChange(e) { const value = e.target.value.replace(/[!-~]/g, (chr) => String.fromCharCode(chr.charCodeAt(0)
+ 0xFEE0) ); this.props.onChange(e, value); } ֯จࣈ͕͋ͬͨΒม͢Δ
ม͕ΔͱΧʔιϧ͕ ͍ͪΜޙΖʹ͍͘
͕มΘΔͱ͖ʹ ΧʔιϧҐஔΛͯ͋͛͠Δ componentWillUpdate() { const element = ReactDOM.findDOMNode(this); this.selectionStart =
element.selectionStart; this.selectionEnd = element.selectionEnd; } componentDidUpdate() { const element = ReactDOM.findDOMNode(this); if (element === document.activeElement) { element.setSelectionRange(this.selectionStart, this.selectionEnd); } } อ͓͍࣋ͯͨ͠ΧʔιϧҐஔΛ VQEBUFޙʹηοτ͢Δ VQEBUFલͷΧʔιϧҐஔΛอ͓࣋ͯ͘͠
͍͍ײ͡
ͻΒ͕ͳΛ ΧλΧφʹ͢Δ
handleChange(e) { const value = e.target.value.replace(/[ぁ-ゖ]/g, (chr) => String.fromCharCode(chr.charCodeAt(0) +
0x60) ); this.props.onChange(e, value); }
͍͋͠ڍಈʹͳΔ
ΧʔιϧҐஔͷ੍ޚ͍͠ w ຊޠೖྗ͕བྷΉ߹ͷڍಈ͕͋͘͠ͳΔ w มޙʹจࣈ͕มΘΔ߹ʹΑ͘Θ͔Μͳ͘ͳΔ w ఘΊͱ͍ͨ΄͏͕ແ w Χʔιϧ͕͋Δͱ͖ม͠ͳ͍Ͱ͓͘ w
ͬͱଞʹؤுΓ͍ͨ͜ͱͨ͘͞Μ͋Δ
CMVSͰม͞ΕΔ
class CoolKatakanaInput extends React.Component { constructor(props) { super(); this.state =
{ showValue: props.value }; } render() { return( <input type="text" value={this.state.showValue} onChange={this.handleChange.bind(this)} onBlur={this.handleBlur.bind(this)} /> ); } componentWillReceiveProps(props) { const element = ReactDOM.findDOMNode(this); if (element !== document.activeElement) { this.setState({ showValue: props.value}); } } ͞ΕͨQSPQTΛTUBUFʹίϐʔ දࣔʹTUBUFͷ΄͏Λ͏ ϑΥʔΧεͯ͠ͳ͍࣌ͷ QSPQTͷมԽදࣔʹଈ࣌ө
handleChange(e) { const inputValue = e.target.value; const value = inputValue.replace(/[ぁ-ゖ]/g,
(chr) => String.fromCharCode(chr.charCodeAt(0) + 0x60) ); this.setState({ showValue: inputValue}); this.props.onChange(e, value); } handleBlur() { this.setState({ showValue: this.props.value}); } ฤूதมͤͣʹදࣔ ϑΥʔΧε͕֎Εͨͱ͖ʹQSPQTΛ࠶ద༻
CMVSͰม͞ΕΔ
ؾͷར͍ͨײ͡ʹ͢ΔͨΊʹ w Ͱ͖Δ͔͗Γػցతʹม͢ΔʢͨΓલʣ w ೖྗϑΟʔϧυͷϥϕϧͰཉ͍͠ܗࣜΛ͑Δ w ࢯ໊ʢΧφʣʹΧλΧφͰೖΕͯ΄͍͠ؾ࣋ͪΛࠐΊΔ w αʔϏεͰೖྗܗࣜ౷Ұ͓ͯ͘͠ w
֯ɺಡΈԾ໊શ֯ΧλΧφͳͲ w Ͳ͏ͯ͠มͰ͖ͳ͍߹ͳͲଈ࣌ʹڭ͑ͯ͋͛Δ w ૹ৴͔ͯ͠ΒʮΤϥʔͰ͢ʯͰ͗͢
͔ͤͬ͘ྑ͍αʔϏε࡞ͬͯΔͷͳΒ ࡉ͔͍ͱ͜ΖؾΛར͔͍͖͍ͤͯͨͰ͢Ͷ