Skip to content

Commit ac37698

Browse files
committed
[added] 'Responsive embed' component
1 parent 4005c21 commit ac37698

10 files changed

+627
-0
lines changed

Diff for: docs/assets/TheresaKnott_castle.svg

+451
Loading

Diff for: docs/client.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import './assets/logo.png';
77
import './assets/favicon.ico';
88
import './assets/thumbnail.png';
99
import './assets/thumbnaildiv.png';
10+
import './assets/TheresaKnott_castle.svg';
1011

1112
import 'codemirror/mode/htmlmixed/htmlmixed';
1213
import 'codemirror/mode/javascript/javascript';

Diff for: docs/examples/.eslintrc

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"PanelGroup",
4949
"Popover",
5050
"ProgressBar",
51+
"ResponsiveEmbed",
5152
"Row",
5253
"SplitButton",
5354
"Tab",

Diff for: docs/examples/ResponsiveEmbed.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const responsiveEmbedInstance = (
2+
<div style={{width: 660, height: 'auto'}}>
3+
<ResponsiveEmbed a16by9>
4+
<embed type="image/svg+xml" src="/assets/TheresaKnott_castle.svg" />
5+
</ResponsiveEmbed>
6+
</div>
7+
);
8+
9+
React.render(responsiveEmbedInstance, mountNode);

Diff for: docs/src/ComponentsPage.js

+14
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,19 @@ const ComponentsPage = React.createClass({
807807
<ReactPlayground codeText={Samples.PageHeader} />
808808
</div>
809809

810+
{/* Responsive embed */}
811+
<div className="bs-docs-section">
812+
<h1 className="page-header"><Anchor id="responsive-embed">Responsive embed</Anchor></h1>
813+
814+
<p>Allow browsers to determine video or slideshow dimensions based on the width of their containing block by creating an intrinsic ratio that will properly scale on any device.</p>
815+
<p>You don't need to include <code>frameborder="0"</code> in your <code>iframe</code>s.</p>
816+
<p className="bg-warning">Either <b>16by9</b> or <b>4by3</b> aspect ratio via <code>a16by9</code> or <code>a4by3</code> attribute must be set.</p>
817+
<ReactPlayground codeText={Samples.ResponsiveEmbed} />
818+
819+
<h3><Anchor id="responsive-embed-props">Props</Anchor></h3>
820+
<PropTable component="ResponsiveEmbed"/>
821+
</div>
822+
810823
{/* Wells */}
811824
<div className="bs-docs-section">
812825
<h1 className="page-header"><Anchor id="wells">Wells</Anchor></h1>
@@ -977,6 +990,7 @@ const ComponentsPage = React.createClass({
977990
<NavItem href="#badges" key={20}>Badges</NavItem>
978991
<NavItem href="#jumbotron" key={21}>Jumbotron</NavItem>
979992
<NavItem href="#page-header" key={22}>Page Header</NavItem>
993+
<NavItem href="#responsive-embed" key={31}>Responsive embed</NavItem>
980994
<NavItem href="#wells" key={23}>Wells</NavItem>
981995
<NavItem href="#glyphicons" key={24}>Glyphicons</NavItem>
982996
<NavItem href="#tables" key={25}>Tables</NavItem>

Diff for: docs/src/ReactPlayground.js

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const Panel = require('../../src/Panel');
4848
const PanelGroup = require('../../src/PanelGroup');
4949
const Popover = require('../../src/Popover');
5050
const ProgressBar = require('../../src/ProgressBar');
51+
const ResponsiveEmbed = require('../../src/ResponsiveEmbed');
5152
const Row = require('../../src/Row');
5253
const SplitButton = require('../../src/SplitButton');
5354
const Tab = require('../../src/Tab');

Diff for: docs/src/Samples.js

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export default {
108108
MenuItem: require('fs').readFileSync(__dirname + '/../examples/MenuItem.js', 'utf8'),
109109
ImageResponsive: require('fs').readFileSync(__dirname + '/../examples/ImageResponsive.js', 'utf8'),
110110
ImageShape: require('fs').readFileSync(__dirname + '/../examples/ImageShape.js', 'utf8'),
111+
ResponsiveEmbed: require('fs').readFileSync(__dirname + '/../examples/ResponsiveEmbed.js', 'utf8'),
111112

112113
Overlay: require('fs').readFileSync(__dirname + '/../examples/Overlay.js', 'utf8'),
113114
OverlayCustom: require('fs').readFileSync(__dirname + '/../examples/OverlayCustom.js', 'utf8')

Diff for: src/ResponsiveEmbed.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React, { PropTypes, cloneElement } from 'react';
2+
import warning from 'react/lib/warning';
3+
import classNames from 'classnames';
4+
5+
class ResponsiveEmbed extends React.Component {
6+
render() {
7+
const { bsClass, className, a16by9, a4by3, ...props } = this.props;
8+
warning(!(!a16by9 && !a4by3), '`a16by9` or `a4by3` attribute must be set.');
9+
warning(!(a16by9 && a4by3), 'Either `a16by9` or `a4by3` attribute can be set. Not both.');
10+
11+
const aspectRatio = {
12+
'embed-responsive-16by9': a16by9,
13+
'embed-responsive-4by3': a4by3
14+
};
15+
16+
return (
17+
<div className={classNames(bsClass, aspectRatio)}>
18+
{cloneElement(
19+
this.props.children,
20+
{
21+
...props,
22+
className: classNames(className, 'embed-responsive-item')
23+
}
24+
)}
25+
</div>
26+
);
27+
}
28+
}
29+
30+
ResponsiveEmbed.defaultProps = {
31+
bsClass: 'embed-responsive',
32+
a16by9: false,
33+
a4by3: false
34+
};
35+
36+
ResponsiveEmbed.propTypes = {
37+
/**
38+
* bootstrap className
39+
* @private
40+
*/
41+
bsClass: PropTypes.string,
42+
/**
43+
* This component accepts only one child element
44+
*/
45+
children: PropTypes.element.isRequired,
46+
/**
47+
* 16by9 aspect ratio
48+
*/
49+
a16by9: PropTypes.bool,
50+
/**
51+
* 4by3 aspect ratio
52+
*/
53+
a4by3: PropTypes.bool
54+
};
55+
56+
export default ResponsiveEmbed;

Diff for: src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export Panel from './Panel';
5252
export PanelGroup from './PanelGroup';
5353
export Popover from './Popover';
5454
export ProgressBar from './ProgressBar';
55+
export ResponsiveEmbed from './ResponsiveEmbed';
5556
export Row from './Row';
5657
export SafeAnchor from './SafeAnchor';
5758
export SplitButton from './SplitButton';

Diff for: test/ResponsiveEmbedSpec.js

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import React from 'react';
2+
import ReactTestUtils from 'react/lib/ReactTestUtils';
3+
import ResponsiveEmbed from '../src/ResponsiveEmbed';
4+
import { shouldWarn } from './helpers';
5+
6+
describe('ResponsiveEmbed', () => {
7+
it('should contain `embed-responsive` class', () => {
8+
let instance = ReactTestUtils.renderIntoDocument(
9+
<ResponsiveEmbed a16by9>
10+
<div />
11+
</ResponsiveEmbed>
12+
);
13+
14+
let instanceClassName = React.findDOMNode(instance).className;
15+
assert.ok(instanceClassName, 'embed-responsive');
16+
});
17+
18+
it('should warn if neither `a16by9` nor `a4by3` attribute is set', () => {
19+
ReactTestUtils.renderIntoDocument(
20+
<ResponsiveEmbed>
21+
<div />
22+
</ResponsiveEmbed>
23+
);
24+
25+
shouldWarn('`a16by9` or `a4by3` attribute must be set.');
26+
});
27+
28+
it('should warn about both `a16by9` or `a4by3` attributes set', () => {
29+
ReactTestUtils.renderIntoDocument(
30+
<ResponsiveEmbed a16by9 a4by3>
31+
<div />
32+
</ResponsiveEmbed>
33+
);
34+
35+
shouldWarn('Either `a16by9` or `a4by3` attribute can be set. Not both.');
36+
});
37+
38+
it('should add `embed-responsive-item` class to child element', () => {
39+
const instance = ReactTestUtils.renderIntoDocument(
40+
<ResponsiveEmbed a16by9>
41+
<div />
42+
</ResponsiveEmbed>
43+
);
44+
45+
let child = React.findDOMNode(instance).firstChild;
46+
assert.ok(child.className.match(/\bembed-responsive-item\b/));
47+
});
48+
49+
it('should add custom classes to child element', () => {
50+
const instance = ReactTestUtils.renderIntoDocument(
51+
<ResponsiveEmbed a16by9 className='custom-class'>
52+
<div />
53+
</ResponsiveEmbed>
54+
);
55+
56+
let child = React.findDOMNode(instance).firstChild;
57+
assert.ok(child.className.match(/\bcustom-class\b/));
58+
});
59+
60+
it('should pass custom attributes to child element', () => {
61+
const instance = ReactTestUtils.renderIntoDocument(
62+
<ResponsiveEmbed a16by9 style={{color: 'white'}}>
63+
<div />
64+
</ResponsiveEmbed>
65+
);
66+
67+
let child = React.findDOMNode(instance).firstChild;
68+
assert.equal(child.style.color, 'white');
69+
});
70+
71+
it('should add `embed-responsive-16by9` class with `a16by9` attribute set', () => {
72+
const instance = ReactTestUtils.renderIntoDocument(
73+
<ResponsiveEmbed a16by9>
74+
<div />
75+
</ResponsiveEmbed>
76+
);
77+
78+
let wrapper = React.findDOMNode(instance);
79+
assert.ok(wrapper.className.match(/\bembed-responsive-16by9\b/));
80+
});
81+
82+
it('should add `embed-responsive-4by3` class with `a4by3` attribute set', () => {
83+
const instance = ReactTestUtils.renderIntoDocument(
84+
<ResponsiveEmbed a4by3>
85+
<div />
86+
</ResponsiveEmbed>
87+
);
88+
89+
let wrapper = React.findDOMNode(instance);
90+
assert.ok(wrapper.className.match(/\bembed-responsive-4by3\b/));
91+
});
92+
});

0 commit comments

Comments
 (0)