Skip to content

BYO iframe #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"presets": ["env"]
"presets": ["env"],
"plugins": ["transform-object-rest-spread"]
}
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ npm install --save react-responsive-embed
Then in your app import `ResponsiveEmbed` and in JSX flavour you might do:

```html
<ResponsiveEmbed src='https://www.youtube.com/embed/2yqz9zgoC-U' allowfullscreen />
<ResponsiveEmbed>
<iframe src='https://www.youtube.com/embed/2yqz9zgoC-U' frameborder="0" allowfullscreen />
</ResponsiveEmbed>
```

Which'd give you an `iframe` element pointing at the `src` and any other props.
Expand All @@ -23,25 +25,29 @@ preserve a **16:9** aspect ratio like so:

```html
<div style="position:relative;height:0;overflow:hidden;max-width:100%;padding-bottom:56.25%;">
<iframe src="https://www.youtube.com/embed/2yqz9zgoC-U"
style="position:absolute;top:0;left:0;width:100%;height:100%;"
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;",
src="https://www.youtube.com/embed/2yqz9zgoC-U"
frameborder="0"
allowfullscreen></iframe>
</div>
```

Pass in a `ratio` prop to pick a different one. Any ratio will do:
Pass a `ratio` property to pick a different one. Any ratio will do:

```html
<ResponsiveEmbed src='https://www.youtube.com/embed/2yqz9zgoC-U' ratio='4:3' />
<ResponsiveEmbed ratio='4:3'>
<iframe src='https://www.youtube.com/embed/2yqz9zgoC-U' allowfullscreen />
</ResponsiveEmbed>
```

`frameborder="0"` is applied by default.
`frameborder="0"` is applied to the child element for you.

You can pass any child element to ResponsiveEmbed. It doesn't have to be an
iframe.

## Browserify / Webpack / Other?

**This module is just a function**. It's been babelified so it'll work with
**This module is just a function**. It's been babelified so it'll work with
whatever your set up is. Use browserify or webpack or any other npm module
consuming bundle whizzbang; ResponsiveEmbed don't mind.

Expand Down
36 changes: 20 additions & 16 deletions docs/components/Page.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import ResponsiveEmbed from '../../index'
import ResponsiveEmbed from '../../src/index'
import Head from './head'

const Page = () => (
Expand All @@ -17,24 +17,28 @@ const Page = () => (
<a href='https://github.com/tableflip/react-responsive-embed'>React ResponsiveEmbed</a>
</h1>
<p>
You want to embed a YouTube or other `iframe` style embedded content, and you'd
like it to take up the available width, and retain it's aspect ratio.
You want to embed a YouTube or other `iframe` style embedded content, and you'd
like it to take up the available width, and retain it's aspect ratio.
</p>
<p>
Much like the <a href='https://v4-alpha.getbootstrap.com/utilities/responsive-helpers/' target='_blank'>Bootstrap responsive embed helpers</a> of old, but for react.
Much like the <a href='https://v4-alpha.getbootstrap.com/utilities/responsive-helpers/' target='_blank'>Bootstrap responsive embed helpers</a> of old, but for react.
</p>
<pre style={{color: '#FEFEFE', background: '#4A4A4A', padding: 20}}>
<code>
&lt;ResponsiveEmbed ratio='16:9' src='https://www.youtube.com/embed/2yqz9zgoC-U' /&gt;
</code>
</pre>
<ResponsiveEmbed ratio='16:9' src='https://www.youtube.com/embed/2yqz9zgoC-U' />
<pre className='m-t-3' style={{color: '#FEFEFE', background: '#4A4A4A', padding: 20}}>
<code>
&lt;ResponsiveEmbed ratio='4:3' src='https://www.youtube.com/embed/mM5_T-F1Yn4' /&gt;
</code>
</pre>
<ResponsiveEmbed ratio='4:3' src='https://www.youtube.com/embed/mM5_T-F1Yn4' />
<code className='m-t-3' style={{color: '#FEFEFE', background: '#4A4A4A', padding: 20, display:'block'}}>
&lt;ResponsiveEmbed ratio='16:9'&gt;
<br/>&nbsp;&nbsp;&lt;iframe src='https://www.youtube.com/embed/2yqz9zgoC-U' /&gt;
<br/>&lt;/ResponsiveEmbed&gt;
</code>
<ResponsiveEmbed ratio='16:9'>
<iframe src='https://www.youtube.com/embed/2yqz9zgoC-U' />
</ResponsiveEmbed>
<code className='m-t-3' style={{color: '#FEFEFE', background: '#4A4A4A', padding: 20, display:'block'}}>
&lt;ResponsiveEmbed ratio='4:3'&gt;
<br/>&nbsp;&nbsp;&lt;iframe src='https://www.youtube.com/embed/mM5_T-F1Yn4' /&gt;
<br/>&lt;/ResponsiveEmbed&gt;
</code>
<ResponsiveEmbed ratio='4:3'>
<iframe src='https://www.youtube.com/embed/mM5_T-F1Yn4' />
</ResponsiveEmbed>
<p className='m-t-3'>
<a href='https://github.com/tableflip/react-responsive-embed'>https://github.com/tableflip/react-responsive-embed</a>
</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@
.tracked {
letter-spacing: 0.5px;
}
</style></head><body><div style="max-width:800px;margin:0 auto;"><header class="m-b-1"><a class="tracked text-decoration-none" href="https://tableflip.io"><img src="https://tableflip.io/img/tableflip.min.svg" style="width:38px;vertical-align:-14px;"/><strong>TABLEFLIP</strong></a></header><h1><a href="https://github.com/tableflip/react-responsive-embed">React ResponsiveEmbed</a></h1><p>You want to embed a YouTube or other `iframe` style embedded content, and you&#x27;d like it to take up the available width, and retain it&#x27;s aspect ratio.</p><p>Much like the <a href="https://v4-alpha.getbootstrap.com/utilities/responsive-helpers/" target="_blank">Bootstrap responsive embed helpers</a> of old, but for react.</p><pre style="color:#FEFEFE;background:#4A4A4A;padding:20px;"><code>&lt;ResponsiveEmbed ratio=&#x27;16:9&#x27; src=&#x27;https://www.youtube.com/embed/2yqz9zgoC-U&#x27; /&gt;</code></pre><div style="position:relative;height:0;overflow:hidden;max-width:100%;padding-bottom:56.25%;"><iframe frameborder="0" src="https://www.youtube.com/embed/2yqz9zgoC-U" style="position:absolute;top:0;left:0;width:100%;height:100%;"></iframe></div><pre class="m-t-3" style="color:#FEFEFE;background:#4A4A4A;padding:20px;"><code>&lt;ResponsiveEmbed ratio=&#x27;4:3&#x27; src=&#x27;https://www.youtube.com/embed/mM5_T-F1Yn4&#x27; /&gt;</code></pre><div style="position:relative;height:0;overflow:hidden;max-width:100%;padding-bottom:75%;"><iframe frameborder="0" src="https://www.youtube.com/embed/mM5_T-F1Yn4" style="position:absolute;top:0;left:0;width:100%;height:100%;"></iframe></div><p class="m-t-3"><a href="https://github.com/tableflip/react-responsive-embed">https://github.com/tableflip/react-responsive-embed</a></p><footer class="m-t-3"><a class="tracked text-decoration-none" href="https://tableflip.io"><img src="https://tableflip.io/img/tableflip.min.svg" style="width:38px;vertical-align:-14px;"/><strong>TABLEFLIP</strong></a></footer></div></body></html>
</style></head><body><div style="max-width:800px;margin:0 auto;"><header class="m-b-1"><a class="tracked text-decoration-none" href="https://tableflip.io"><img src="https://tableflip.io/img/tableflip.min.svg" style="width:38px;vertical-align:-14px;"/><strong>TABLEFLIP</strong></a></header><h1><a href="https://github.com/tableflip/react-responsive-embed">React ResponsiveEmbed</a></h1><p>You want to embed a YouTube or other `iframe` style embedded content, and you&#x27;d like it to take up the available width, and retain it&#x27;s aspect ratio.</p><p>Much like the <a href="https://v4-alpha.getbootstrap.com/utilities/responsive-helpers/" target="_blank">Bootstrap responsive embed helpers</a> of old, but for react.</p><code class="m-t-3" style="color:#FEFEFE;background:#4A4A4A;padding:20px;display:block;">&lt;ResponsiveEmbed ratio=&#x27;16:9&#x27;&gt;<br/>  &lt;iframe src=&#x27;https://www.youtube.com/embed/2yqz9zgoC-U&#x27; /&gt;<br/>&lt;/ResponsiveEmbed&gt;</code><div style="position:relative;overflow:hidden;max-width:100%;height:0;padding-bottom:56.25%;"><iframe src="https://www.youtube.com/embed/2yqz9zgoC-U" frameborder="0" style="position:absolute;top:0;left:0;width:100%;height:100%;"></iframe></div><code class="m-t-3" style="color:#FEFEFE;background:#4A4A4A;padding:20px;display:block;">&lt;ResponsiveEmbed ratio=&#x27;4:3&#x27;&gt;<br/>  &lt;iframe src=&#x27;https://www.youtube.com/embed/mM5_T-F1Yn4&#x27; /&gt;<br/>&lt;/ResponsiveEmbed&gt;</code><div style="position:relative;overflow:hidden;max-width:100%;height:0;padding-bottom:75%;"><iframe src="https://www.youtube.com/embed/mM5_T-F1Yn4" frameborder="0" style="position:absolute;top:0;left:0;width:100%;height:100%;"></iframe></div><p class="m-t-3"><a href="https://github.com/tableflip/react-responsive-embed">https://github.com/tableflip/react-responsive-embed</a></p><footer class="m-t-3"><a class="tracked text-decoration-none" href="https://tableflip.io"><img src="https://tableflip.io/img/tableflip.min.svg" style="width:38px;vertical-align:-14px;"/><strong>TABLEFLIP</strong></a></footer></div></body></html>
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"devDependencies": {
"ava": "^0.17.0",
"babel-cli": "^6.22.2",
"babel-plugin-transform-object-rest-spread": "^6.22.0",
"babel-preset-env": "^1.1.8",
"react-addons-test-utils": "^15.0",
"react-dom": "^15.0",
Expand All @@ -25,9 +26,9 @@
"engines": {
"node": ">=6.0"
},
"directories": {
"doc": "docs",
"test": "test"
"ava": {
"require": ["babel-register"],
"babel": "inherit"
},
"repository": {
"type": "git",
Expand Down
53 changes: 25 additions & 28 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,48 @@
const React = require('react')
const PropTypes = React.PropTypes
const div = React.createElement.bind(React, 'div')
const iframe = React.createElement.bind(React, 'iframe')

const divStyle = {
position: 'relative',
height: 0,
overflow: 'hidden',
maxWidth: '100%'
}

const iframeStyle = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%'
}

/*
* Turn `16:9` into `9 / 16` into `56.25%`
* Turn `4:3` into `3 / 4` into `75%`
* Turns a ratio into a percentage
* Turns `16:9` into `9 / 16` into `56.25%`
* Turns `4:3` into `3 / 4` into `75%`
*/
const ratioToPercent = (ratio) => {
const [w, h] = ratio.split(':').map((num) => Number(num))
return `${(h / w) * 100}%`
}

/*
* Usage: <ResponsiveEmbed src='ace youtube video' ratio='4:3' />
* Usage:
* <ResponsiveEmbed ratio='4:3'>
* <iframe src='ace youtube video' />
* </ResponsiveEmbed>
*/
const ResponsiveEmbed = (props) => {
const paddingBottom = ratioToPercent(props.ratio)
const style = Object.assign({}, divStyle, {paddingBottom})
const iframeProps = Object.assign({frameBorder: 0}, props, {style: iframeStyle})
return div({style},
iframe(iframeProps)
const ResponsiveEmbed = ({ratio, style, children, ...props}) => {
const containerStyle = {
position: 'relative',
overflow: 'hidden',
maxWidth: '100%',
height: 0,
paddingBottom: ratioToPercent(ratio),
...style
}
return React.createElement('div', {style: containerStyle, ...props},
React.cloneElement(children, {frameBorder: 0, style: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%'
}})
)
}

ResponsiveEmbed.defaultProps = {
src: 'https://www.youtube.com/embed/dQw4w9WgXcQ',
ratio: '16:9'
}

ResponsiveEmbed.propTypes = {
src: PropTypes.string,
children: PropTypes.element.isRequired,
ratio: (props, propName, componentName) => {
if (!/\d+:\d+/.test(props[propName])) {
return new Error(
Expand Down
30 changes: 13 additions & 17 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,33 @@ const ResponsiveEmbed = require('../src/index')

test('ResponsiveEmbed renders OK', (t) => {
const src = 'https://www.youtube.com/embed/zc1g_hSuxVE'
const element = React.createElement(ResponsiveEmbed, {src})
const background = 'hotpink'
const className = 'whizzbang'
const element = React.createElement(
ResponsiveEmbed,
{style: {background}, className},
React.createElement('iframe', {src})
)
const renderer = ReactTestUtils.createRenderer()
renderer.render(element)
const root = renderer.getRenderOutput()
const child = root.props.children

t.plan(4)
t.plan(6)
t.is(root.type, 'div', 'Root element is a div')
t.is(root.props.style.paddingBottom, '56.25%', 'Aspect ratio of 16x9 is manifest as a paddingBottom style of 56.25%')
t.is(root.props.style.background, background, 'Custom styles are preserved')
t.is(root.props.className, className, 'Custom className is preserved')
t.is(child.type, 'iframe', 'Child element is an iframe')
t.is(child.props.src, src, 'Provided `src` is used')
})

test('ResponsiveEmbed renders other ratios', (t) => {
const src = 'https://www.youtube.com/embed/zc1g_hSuxVE'
const ratio = '1.43:1' // imax
const element = React.createElement(ResponsiveEmbed, {src, ratio})
const element = React.createElement(ResponsiveEmbed, {ratio},
React.createElement('iframe', {src})
)
const renderer = ReactTestUtils.createRenderer()
renderer.render(element)
const root = renderer.getRenderOutput()
Expand All @@ -33,17 +43,3 @@ test('ResponsiveEmbed renders other ratios', (t) => {
t.is(child.type, 'iframe', 'Child element is an iframe')
t.is(child.props.src, src, 'Provided `src` is used')
})

test('ResponsiveEmbed renders with default props', (t) => {
const element = React.createElement(ResponsiveEmbed)
const renderer = ReactTestUtils.createRenderer()
renderer.render(element)
const root = renderer.getRenderOutput()
const child = root.props.children

t.plan(4)
t.is(root.type, 'div', 'Root element is a div')
t.is(root.props.style.paddingBottom, '56.25%', 'Aspect ratio of 16x9 is manifest as a paddingBottom style of 56.25%')
t.is(child.type, 'iframe', 'Child element is an iframe')
t.is(child.props.src, 'https://www.youtube.com/embed/dQw4w9WgXcQ', 'Default `src` is used')
})