Skip to content

Instantly share code, notes, and snippets.

@patrickgalbraith
Last active September 19, 2018 12:05
Show Gist options
  • Save patrickgalbraith/feaf3642545137bb0ebba76d14cbbfe7 to your computer and use it in GitHub Desktop.
Save patrickgalbraith/feaf3642545137bb0ebba76d14cbbfe7 to your computer and use it in GitHub Desktop.
Auto Height React Native WebView with custom link handling
/*
Copyright 2017 Patrick Galbraith
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import React, { Component } from 'react'
import {
View,
Dimensions,
WebView
} from 'react-native'
// Based on https://github.com/scazzy/react-native-webview-autoheight
// Made a number of changes mainly to support custom link actions
const injectedScript = function() {
function addEvent(obj, type, fn) {
if (obj.addEventListener)
obj.addEventListener(type, fn, false);
else if (obj.attachEvent)
obj.attachEvent('on' + type, function() { return fn.apply(obj, [window.event]);});
}
function waitForBridge() {
if (window.postMessage.length !== 1){
setTimeout(waitForBridge, 200)
} else {
let height = 0
if(document.documentElement.clientHeight > document.body.clientHeight) {
height = document.documentElement.clientHeight
} else {
height = document.body.clientHeight
}
postMessage(JSON.stringify({ height: height }))
// Intercept all link clicks
for(var i=0, a=document.getElementsByTagName('a'), l=a.length; i<l; ++i) {
addEvent(a[i], 'click', function(e) {
postMessage(JSON.stringify({href: this.href}))
e.returnValue = false
if (e.preventDefault)
e.preventDefault()
return false
})
}
}
}
waitForBridge()
}
export default class AutoHeightWebView extends Component {
state = {
webViewHeight: Number
}
static defaultProps = {
autoHeight: true,
}
constructor (props: Object) {
super(props)
this.state = {
webViewHeight: this.props.defaultHeight
}
this._onMessage = this._onMessage.bind(this)
}
_onMessage(e) {
const data = JSON.parse(e.nativeEvent.data)
if (data.height) {
this.setState({
webViewHeight: parseInt(data.height)
})
} else if (data.href && this.props.onLinkPress) {
this.props.onLinkPress(data.href)
}
}
render () {
const _w = this.props.width || Dimensions.get('window').width
const _h = this.props.autoHeight ? this.state.webViewHeight : this.props.defaultHeight
return (
<WebView
injectedJavaScript={'(' + String(injectedScript) + ')();'}
scrollEnabled={this.props.scrollEnabled || false}
onMessage={this._onMessage}
javaScriptEnabled={true}
automaticallyAdjustContentInsets={true}
{...this.props}
style={[{width: _w}, this.props.style, {height: _h}]}
/>
)
}
}
@Gowtham03
Copy link

injectedJavaScript={const meta = document.createElement('meta'); meta.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, user-scalable=0'); meta.setAttribute('name', 'viewport'); document.getElementsByTagName('head')[0].appendChild(meta); }
scalesPageToFit={false}

@Gowtham03
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment