File tree Expand file tree Collapse file tree 11 files changed +157
-35
lines changed Expand file tree Collapse file tree 11 files changed +157
-35
lines changed Original file line number Diff line number Diff line change 11import React , { cloneElement } from 'react' ;
22import BootstrapMixin from './BootstrapMixin' ;
33import classNames from 'classnames' ;
4-
4+ import SafeAnchor from './SafeAnchor' ;
55
66const ListGroupItem = React . createClass ( {
77 mixins : [ BootstrapMixin ] ,
@@ -51,12 +51,12 @@ const ListGroupItem = React.createClass({
5151
5252 renderAnchor ( classes ) {
5353 return (
54- < a
54+ < SafeAnchor
5555 { ...this . props }
5656 className = { classNames ( this . props . className , classes ) }
5757 >
5858 { this . props . header ? this . renderStructuredContent ( ) : this . props . children }
59- </ a >
59+ </ SafeAnchor >
6060 ) ;
6161 } ,
6262
Original file line number Diff line number Diff line change 11import React from 'react' ;
22import classNames from 'classnames' ;
3+ import SafeAnchor from './SafeAnchor' ;
34
45const MenuItem = React . createClass ( {
56 propTypes : {
@@ -15,7 +16,6 @@ const MenuItem = React.createClass({
1516
1617 getDefaultProps ( ) {
1718 return {
18- href : '#' ,
1919 active : false
2020 } ;
2121 } ,
@@ -29,9 +29,9 @@ const MenuItem = React.createClass({
2929
3030 renderAnchor ( ) {
3131 return (
32- < a onClick = { this . handleClick } href = { this . props . href } target = { this . props . target } title = { this . props . title } tabIndex = "-1" >
32+ < SafeAnchor onClick = { this . handleClick } href = { this . props . href } target = { this . props . target } title = { this . props . title } tabIndex = "-1" >
3333 { this . props . children }
34- </ a >
34+ </ SafeAnchor >
3535 ) ;
3636 } ,
3737
Original file line number Diff line number Diff line change 11import React from 'react' ;
22import classNames from 'classnames' ;
33import BootstrapMixin from './BootstrapMixin' ;
4+ import SafeAnchor from './SafeAnchor' ;
45
56const NavItem = React . createClass ( {
67 mixins : [ BootstrapMixin ] ,
@@ -15,12 +16,6 @@ const NavItem = React.createClass({
1516 target : React . PropTypes . string
1617 } ,
1718
18- getDefaultProps ( ) {
19- return {
20- href : '#'
21- } ;
22- } ,
23-
2419 render ( ) {
2520 let {
2621 disabled,
@@ -38,8 +33,7 @@ const NavItem = React.createClass({
3833 href,
3934 title,
4035 target,
41- onClick : this . handleClick ,
42- ref : 'anchor'
36+ onClick : this . handleClick
4337 } ;
4438
4539 if ( href === '#' ) {
@@ -48,9 +42,9 @@ const NavItem = React.createClass({
4842
4943 return (
5044 < li { ...props } className = { classNames ( props . className , classes ) } >
51- < a { ...linkProps } >
45+ < SafeAnchor { ...linkProps } >
5246 { children }
53- </ a >
47+ </ SafeAnchor >
5448 </ li >
5549 ) ;
5650 } ,
Original file line number Diff line number Diff line change 11import React from 'react' ;
22import classNames from 'classnames' ;
3+ import SafeAnchor from './SafeAnchor' ;
34
45const PageItem = React . createClass ( {
56
@@ -14,12 +15,6 @@ const PageItem = React.createClass({
1415 eventKey : React . PropTypes . any
1516 } ,
1617
17- getDefaultProps ( ) {
18- return {
19- href : '#'
20- } ;
21- } ,
22-
2318 render ( ) {
2419 let classes = {
2520 'disabled' : this . props . disabled ,
@@ -31,14 +26,13 @@ const PageItem = React.createClass({
3126 < li
3227 { ...this . props }
3328 className = { classNames ( this . props . className , classes ) } >
34- < a
29+ < SafeAnchor
3530 href = { this . props . href }
3631 title = { this . props . title }
3732 target = { this . props . target }
38- onClick = { this . handleSelect }
39- ref = "anchor" >
33+ onClick = { this . handleSelect } >
4034 { this . props . children }
41- </ a >
35+ </ SafeAnchor >
4236 </ li >
4337 ) ;
4438 } ,
Original file line number Diff line number Diff line change 1+ import React from 'react' ;
2+
3+ /**
4+ * Note: This is intended as a stop-gap for accessibility concerns that the
5+ * Bootstrap CSS does not address as they have styled anchors and not buttons
6+ * in many cases.
7+ */
8+ export default class SafeAnchor extends React . Component {
9+ constructor ( props ) {
10+ super ( props ) ;
11+
12+ this . handleClick = this . handleClick . bind ( this ) ;
13+ }
14+
15+ handleClick ( event ) {
16+ if ( this . props . href === undefined ) {
17+ event . preventDefault ( ) ;
18+ }
19+
20+ if ( this . props . onClick ) {
21+ this . props . onClick ( event ) ;
22+ }
23+ }
24+
25+ render ( ) {
26+ return (
27+ < a role = { this . props . href ? undefined : 'button' }
28+ { ...this . props }
29+ onClick = { this . handleClick }
30+ href = { this . props . href || '' } />
31+ ) ;
32+ }
33+ }
34+
35+ SafeAnchor . propTypes = {
36+ href : React . PropTypes . string ,
37+ onClick : React . PropTypes . func
38+ } ;
Original file line number Diff line number Diff line change @@ -4,6 +4,7 @@ import classNames from 'classnames';
44import ValidComponentChildren from './utils/ValidComponentChildren' ;
55import createChainedFunction from './utils/createChainedFunction' ;
66import BootstrapMixin from './BootstrapMixin' ;
7+ import SafeAnchor from './SafeAnchor' ;
78
89const SubNav = React . createClass ( {
910 mixins : [ BootstrapMixin ] ,
@@ -99,14 +100,13 @@ const SubNav = React.createClass({
99100
100101 return (
101102 < li { ...this . props } className = { classNames ( this . props . className , classes ) } >
102- < a
103+ < SafeAnchor
103104 href = { this . props . href }
104105 title = { this . props . title }
105106 target = { this . props . target }
106- onClick = { this . handleClick }
107- ref = "anchor" >
107+ onClick = { this . handleClick } >
108108 { this . props . text }
109- </ a >
109+ </ SafeAnchor >
110110 < ul className = "nav" >
111111 { ValidComponentChildren . map ( this . props . children , this . renderNavItem ) }
112112 </ ul >
Original file line number Diff line number Diff line change 11import React from 'react' ;
22import classSet from 'classnames' ;
33import BootstrapMixin from './BootstrapMixin' ;
4+ import SafeAnchor from './SafeAnchor' ;
45
56const Thumbnail = React . createClass ( {
67 mixins : [ BootstrapMixin ] ,
@@ -16,9 +17,9 @@ const Thumbnail = React.createClass({
1617
1718 if ( this . props . href ) {
1819 return (
19- < a { ...this . props } href = { this . props . href } className = { classSet ( this . props . className , classes ) } >
20+ < SafeAnchor { ...this . props } href = { this . props . href } className = { classSet ( this . props . className , classes ) } >
2021 < img src = { this . props . src } alt = { this . props . alt } />
21- </ a >
22+ </ SafeAnchor >
2223 ) ;
2324 }
2425 else {
Original file line number Diff line number Diff line change @@ -42,6 +42,7 @@ import Pager from './Pager';
4242import Popover from './Popover' ;
4343import ProgressBar from './ProgressBar' ;
4444import Row from './Row' ;
45+ import SafeAnchor from './SafeAnchor' ;
4546import SplitButton from './SplitButton' ;
4647import SubNav from './SubNav' ;
4748import TabbedArea from './TabbedArea' ;
@@ -97,6 +98,7 @@ export default {
9798 Popover,
9899 ProgressBar,
99100 Row,
101+ SafeAnchor,
100102 SplitButton,
101103 SubNav,
102104 TabbedArea,
Original file line number Diff line number Diff line change @@ -83,9 +83,9 @@ describe('Nav', function () {
8383 </ Nav >
8484 ) ;
8585
86- let items = ReactTestUtils . scryRenderedComponentsWithType ( instance , NavItem ) ;
86+ let items = ReactTestUtils . scryRenderedDOMComponentsWithTag ( instance , 'A' ) ;
8787
88- ReactTestUtils . Simulate . click ( items [ 1 ] . refs . anchor ) ;
88+ ReactTestUtils . Simulate . click ( items [ 1 ] ) ;
8989 } ) ;
9090
9191 it ( 'Should set the correct item active by href' , function ( ) {
Original file line number Diff line number Diff line change @@ -36,7 +36,7 @@ describe('PageItem', function () {
3636 it ( 'Should call "onSelect" when item is clicked' , function ( done ) {
3737 function handleSelect ( key , href ) {
3838 assert . equal ( key , 1 ) ;
39- assert . equal ( href , '#' ) ;
39+ assert . equal ( href , undefined ) ;
4040 done ( ) ;
4141 }
4242 let instance = ReactTestUtils . renderIntoDocument (
You can’t perform that action at this time.
0 commit comments