Skip to content

Commit 60e699e

Browse files
Merge pull request react-bootstrap#262 from smbecker/master
Add 'target' attribute to NavItem
2 parents 67ef392 + b5d93a5 commit 60e699e

13 files changed

Lines changed: 147 additions & 14 deletions

src/Button.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ var Button = React.createClass({
1212
block: React.PropTypes.bool,
1313
navItem: React.PropTypes.bool,
1414
navDropdown: React.PropTypes.bool,
15-
componentClass: React.PropTypes.node
15+
componentClass: React.PropTypes.node,
16+
href: React.PropTypes.string,
17+
target: React.PropTypes.string
1618
},
1719

1820
getDefaultProps: function () {
@@ -34,7 +36,7 @@ var Button = React.createClass({
3436
return this.renderNavItem(classes);
3537
}
3638

37-
renderFuncName = this.props.href || this.props.navDropdown ?
39+
renderFuncName = this.props.href || this.props.target || this.props.navDropdown ?
3840
'renderAnchor' : 'renderButton';
3941

4042
return this[renderFuncName](classes);

src/ListGroupItem.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ var ListGroupItem = React.createClass({
1515
disabled: React.PropTypes.any,
1616
header: React.PropTypes.node,
1717
onClick: React.PropTypes.func,
18-
eventKey: React.PropTypes.any
18+
eventKey: React.PropTypes.any,
19+
href: React.PropTypes.string,
20+
target: React.PropTypes.string
1921
},
2022

2123
getDefaultProps: function () {
@@ -30,7 +32,7 @@ var ListGroupItem = React.createClass({
3032
classes['active'] = this.props.active;
3133
classes['disabled'] = this.props.disabled;
3234

33-
if (this.props.href || this.props.onClick) {
35+
if (this.props.href || this.props.target || this.props.onClick) {
3436
return this.renderAnchor(classes);
3537
} else {
3638
return this.renderSpan(classes);
@@ -85,7 +87,7 @@ var ListGroupItem = React.createClass({
8587
handleClick: function (e) {
8688
if (this.props.onClick) {
8789
e.preventDefault();
88-
this.props.onClick(this.props.eventKey, this.props.href);
90+
this.props.onClick(this.props.eventKey, this.props.href, this.props.target);
8991
}
9092
}
9193
});

src/MenuItem.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ var MenuItem = React.createClass({
88
divider: React.PropTypes.bool,
99
href: React.PropTypes.string,
1010
title: React.PropTypes.string,
11+
target: React.PropTypes.string,
1112
onSelect: React.PropTypes.func,
12-
eventKey: React.PropTypes.any
13+
eventKey: React.PropTypes.any
1314
},
1415

1516
getDefaultProps: function () {
@@ -21,13 +22,13 @@ var MenuItem = React.createClass({
2122
handleClick: function (e) {
2223
if (this.props.onSelect) {
2324
e.preventDefault();
24-
this.props.onSelect(this.props.eventKey);
25+
this.props.onSelect(this.props.eventKey, this.props.href, this.props.target);
2526
}
2627
},
2728

2829
renderAnchor: function () {
2930
return (
30-
<a onClick={this.handleClick} href={this.props.href} title={this.props.title} tabIndex="-1">
31+
<a onClick={this.handleClick} href={this.props.href} target={this.props.target} title={this.props.title} tabIndex="-1">
3132
{this.props.children}
3233
</a>
3334
);

src/NavItem.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ var NavItem = React.createClass({
1212
disabled: React.PropTypes.bool,
1313
href: React.PropTypes.string,
1414
title: React.PropTypes.string,
15-
eventKey: React.PropTypes.any
15+
eventKey: React.PropTypes.any,
16+
target: React.PropTypes.string
1617
},
1718

1819
getDefaultProps: function () {
@@ -27,6 +28,7 @@ var NavItem = React.createClass({
2728
active,
2829
href,
2930
title,
31+
target,
3032
children,
3133
...props } = this.props,
3234
classes = {
@@ -39,6 +41,7 @@ var NavItem = React.createClass({
3941
<a
4042
href={href}
4143
title={title}
44+
target={target}
4245
onClick={this.handleClick}
4346
ref="anchor">
4447
{ children }
@@ -52,7 +55,7 @@ var NavItem = React.createClass({
5255
e.preventDefault();
5356

5457
if (!this.props.disabled) {
55-
this.props.onSelect(this.props.eventKey, this.props.href);
58+
this.props.onSelect(this.props.eventKey, this.props.href, this.props.target);
5659
}
5760
}
5861
}

src/PageItem.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ var classSet = require('./utils/classSet');
55
var PageItem = React.createClass({
66

77
propTypes: {
8+
href: React.PropTypes.string,
9+
target: React.PropTypes.string,
810
disabled: React.PropTypes.bool,
911
previous: React.PropTypes.bool,
1012
next: React.PropTypes.bool,
@@ -32,6 +34,7 @@ var PageItem = React.createClass({
3234
<a
3335
href={this.props.href}
3436
title={this.props.title}
37+
target={this.props.target}
3538
onClick={this.handleSelect}
3639
ref="anchor">
3740
{this.props.children}
@@ -45,7 +48,7 @@ var PageItem = React.createClass({
4548
e.preventDefault();
4649

4750
if (!this.props.disabled) {
48-
this.props.onSelect(this.props.eventKey, this.props.href);
51+
this.props.onSelect(this.props.eventKey, this.props.href, this.props.target);
4952
}
5053
}
5154
}

src/SplitButton.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var SplitButton = React.createClass({
1414
pullRight: React.PropTypes.bool,
1515
title: React.PropTypes.node,
1616
href: React.PropTypes.string,
17+
target: React.PropTypes.string,
1718
dropdownTitle: React.PropTypes.node,
1819
onClick: React.PropTypes.func,
1920
onSelect: React.PropTypes.func,
@@ -50,6 +51,8 @@ var SplitButton = React.createClass({
5051
className={joinClasses(this.props.className, 'dropdown-toggle')}
5152
onClick={this.handleDropdownClick}
5253
title={null}
54+
href={null}
55+
target={null}
5356
id={null}>
5457
<span className="sr-only">{this.props.dropdownTitle}</span>
5558
<span className="caret" />
@@ -80,7 +83,7 @@ var SplitButton = React.createClass({
8083
}
8184

8285
if (this.props.onClick) {
83-
this.props.onClick(e);
86+
this.props.onClick(e, this.props.href, this.props.target);
8487
}
8588
},
8689

src/SubNav.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ var SubNav = React.createClass({
1717
disabled: React.PropTypes.bool,
1818
href: React.PropTypes.string,
1919
title: React.PropTypes.string,
20-
text: React.PropTypes.node
20+
text: React.PropTypes.node,
21+
target: React.PropTypes.string
2122
},
2223

2324
getDefaultProps: function () {
@@ -31,7 +32,7 @@ var SubNav = React.createClass({
3132
e.preventDefault();
3233

3334
if (!this.props.disabled) {
34-
this.props.onSelect(this.props.eventKey, this.props.href);
35+
this.props.onSelect(this.props.eventKey, this.props.href, this.props.target);
3536
}
3637
}
3738
},
@@ -101,6 +102,7 @@ var SubNav = React.createClass({
101102
<a
102103
href={this.props.href}
103104
title={this.props.title}
105+
target={this.props.target}
104106
onClick={this.handleClick}
105107
ref="anchor">
106108
{this.props.text}

test/ButtonSpec.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ describe('Button', function () {
6464
assert.equal(instance.getDOMNode().getAttribute('href'), href);
6565
});
6666

67+
it('Should output an anchor if called with a target', function () {
68+
var target = '_blank';
69+
var instance = ReactTestUtils.renderIntoDocument(
70+
<Button target={target}>
71+
Title
72+
</Button>
73+
);
74+
assert.equal(instance.getDOMNode().nodeName, 'A');
75+
assert.equal(instance.getDOMNode().getAttribute('target'), target);
76+
});
77+
6778
it('Should call onClick callback', function (done) {
6879
var doneOp = function () {
6980
done();

test/ListGroupItemSpec.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,15 @@ describe('ListGroupItem', function () {
7979
);
8080
ReactTestUtils.Simulate.click(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
8181
});
82+
83+
it('Should call "onClick" with target attribute', function (done) {
84+
function handleClick(key, href, target) {
85+
assert.equal(target, '_blank');
86+
done();
87+
}
88+
var instance = ReactTestUtils.renderIntoDocument(
89+
<ListGroupItem onClick={handleClick} eventKey='2' href="#link" target='_blank'>Item</ListGroupItem>
90+
);
91+
ReactTestUtils.Simulate.click(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
92+
});
8293
});

test/MenuItemSpec.jsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,31 @@ describe('MenuItem', function () {
8383
assert(instance.getDOMNode().className.match(/\bdropdown-header\b/), 'Has no header class');
8484
assert.equal(instance.getDOMNode().innerHTML, 'Title');
8585
});
86+
87+
it('Should set target attribute on anchor', function () {
88+
var instance = ReactTestUtils.renderIntoDocument(
89+
<MenuItem target="_blank">
90+
Title
91+
</MenuItem>
92+
);
93+
94+
var anchor = ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a');
95+
assert.equal(anchor.getDOMNode().getAttribute('target'), '_blank');
96+
});
97+
98+
it('Should call `onSelect` with target attribute', function (done) {
99+
function handleSelect(key, href, target) {
100+
assert.equal(href, 'link');
101+
assert.equal(target, '_blank');
102+
done();
103+
}
104+
var instance = ReactTestUtils.renderIntoDocument(
105+
<MenuItem onSelect={handleSelect} target="_blank" href="link">
106+
Title
107+
</MenuItem>
108+
);
109+
ReactTestUtils.Simulate.click(ReactTestUtils.findRenderedDOMComponentWithTag(instance, 'a'));
110+
});
86111
});
87112

88113

0 commit comments

Comments
 (0)