I'm trying to dynamically load the TokBox embed script in my React app when the user clicks a button. The script tag is being added to the DOM and successfully loading but it does not go on to download opentok.min.js and thus the video control never renders. Adding the code directly into index.html works fine however. What is different about loading the tag dynamically?
Snippit:
import Script from 'react-load-script';
...
render() {
return (
<div>
...
<div id="otEmbedContainer" style={{width:"300px", height:"300px"}}></div>
{this.state.showVideo &&
<Script
url='https://tokbox.com/embed/embed/ot-embed.js?embedId=MYEMBEDID&room=' + this.state.roomId
/>
}
</div>
)
);
Response from TokBox support:
It is noted that when you load embed dynamically. you need to fire following event also after the dynamic loading( this is required for embedded to be loaded as per current design).
var DOMContentLoaded_event = document.createEvent("Event")
DOMContentLoaded_event.initEvent("DOMContentLoaded", true, true)
window.document.dispatchEvent(DOMContentLoaded_event).
I haven't tried this because I switched to use the iframe solution for now but posting here for continuity.
Related
I have a test app with react-native-web-view rendering a local HTML file
for using JS, it works if I have the JS embedded in the HTML, but if I call it on a separate JS file it won't work...
in my App.tsx:
<WebView source={{uri: `${origin}/${file}`}} style={styles.webview} />
here is the embedded HTML:
<button type="button" onclick="alabama();">Play</button>
<button type="button" onclick="alert('Hello alabama')">music</button>
<script src="./chusa.js"></script>
chusa.js:
function alabama() {
alert('Hello alabama');
}
So, alert works, the function doesn't.
How can I call the script on a separate file?
React-Native Web WebView uses an iframe in replace of the webview component, so the issue is likely due the html file (e.g. the iframe) not having access to external files once mounted/created.
Possible Solution:
If you want the file to still be external, change it to a string and use back-quotes:
export const javascript = `alert("hello")`
Import js component. Something like:
import externalJS from "./filename"
The imported variable is a string and your html should also be a string, so you'll want to append the script string to the end of the html string. Something like this:
html = html.replace('</body>', '<script>${externalJS}</script></body>')
Use the new html string as the source via prop:
<WebView source={{ html: html }/>
Note: When you say "call" the script, if you are referring to calling a function after the web webview has been created without re-rendering, then that isn't possible at this time due when using the web webview instead of an actual webview component. This is actually an issue I am trying to resolve: How do I post a message to a iframe (not webview) in React-Native?
Hopefully this helps you with your issue.
I recently started on React and I'm using it in combination with Laravel as I would like to replace my jquery by react on a step by step migration.
In my tests, the render instructions are always packaged in the component .js file like this :
ReactDOM.render(<Calculator />, document.getElementById('tutorial'));
and the div <div id="tutorial"></div> is placed in a view.
My problem is that the view is dynamically generated by my php code and sometimes I need to render several component in one page so this approach is not working. Hence I would like to trigger the rendering from the view so something like :
<div id="tutorial" intruction_to_render_calculator_component_in_this_div></div>
How can I do that ?
been all over it recently in trying to find a solution... So here is the one I found :
In my component I put a loop to screen all elements asking to be mount based on an rComponent attribute :
var divs = document.querySelectorAll("[rComponent='Calculator']");
if (divs.length > 0) {
//document.querySelector("[rComponent='calculator']");
for (var i = 0; i < divs.length; ++i) {
ReactDOM.render(<Calculator />, divs[i]);
}
//ReactDOM.render(<Calculator />, document.getElementById('tutorial2'));
}
In my view I just need to put a rComponent in my div :
<div id="tutorial" rComponent="Calculator"></div>
<div id="tutorial2" rComponent="Calculator"></div>
pretty happy with this way of working though I think it might slow the scripts high time
I've a multiple page site. I created a single component enclosing all the texts/para/images. I've refered this component to all the multiple pages. I used a class name to hide/show the content to the respective pages via css. Problem is that the page load is slow. Since all contents are hidden using css they are still loaded making my site slow. Any help on this is much appreciated. Thanks
There are multiple things you can check.
Check the internet connectivity, I hope you have good internet connectivity to load the
page.
As you say there are multiple page with single component, check if you can move those into sub-component.
I am not sure how you're hiding those components use css property display:none if those are light weight.
you can use something like this:
<style type="text/css">
.hidden { display:none; }
</style>
render: function() {
return (
<div className={this.props.shouldHide ? 'hidden' : ''}>
This will be hidden if you set <tt>props.shouldHide</tt>
to something truthy.
</div>
);
}
// or in more modern JS and stateless react
const Example = props => <div className={props.shouldHide}/>Hello</div>
source
I am attempting to create a SPA using AngularJS as the main view for my website. I'm using ServiceStack on the server-side and can therefore cleanly serve HTML or JSON requests depending on what's accessing it. My main concern is the use of script blockers, preventing AngularJS from rendering the page properly. So far my main way of working is to render static pages, and inject a small script that redirects to the AngularJS-powered pages if it detects if Javascript is enabled. This works great since every URL works fine when the user begins at the static pages, but I've ran into a couple of snags.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
This causes the first page loaded to be loaded twice.
I'm looking for an alternative, but so far I haven't found any clean solutions. I was thinking about including the "?View=SPA" as a POST variable, but I'm still iffy on that implementation.
Any thoughts?
Instead of redirecting to an other page, I would implement both cases in the same HTML File as follows:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<style>.hideIfNoScript {display: none}</style>
</head>
<body ng-app ng-init="msg = 'hello world'">
<input class="hideIfNoScript" ng-model="msg" />
<p class="hideIfNoScript">{{msg}}</p>
<noscript>
<p>Content without javascript</p>
</noscript>
<script type="text/javascript">
var myEl = angular.element( document.querySelectorAll( '.hideIfNoScript' ) );
myEl.removeClass('hideIfNoScript');
</script>
</body>
</html>
The CSS Class hideIfNoScript in the head section makes sure that all HTML Tags with this class are never shown to the user, if javascript is disabled.
The noscript tag shows the alternative content.
If javascript is enabled, the little script at the end of the body section makes those elements visible. And in this case, the contents of the noscript tag are hidden.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
Hide those links by default:
a[href*='SPA'] { display: none; }
This causes the first page loaded to be loaded twice
Use a cookie on a browser-check page which loads the first page in an iframe or redirects to it to avoid this.
References
Track Non-JavaScript Visits In Google Analytics
Extjs prefers your app to be a single page app, but I'd still like to be able to do things like refresh my page and keep my current location in the app, and enter a url to get directly to a particular point in the app. Is there a solution for this?
Yes, I do the same in my app. You can use the Ext JS history mechanism to do so. Have a look at this example from Sencha.
You can listen to the history change event like this
Ext.History.on('change', function(token) {
// you navigate-to-target code goes here, e.g. change the viewport content
}
You can then initiate navigation by setting the browser hash to some navigation target
document.location.hash = yourNavigationToken;
This gives you also the ability to use deep-linking and forward/backward navigation with the browser buttons.
You need to init the history:
// The only requirement for this to work is that you must have a hidden field and
// an iframe available in the page with ids corresponding to Ext.History.fieldId
// and Ext.History.iframeId. See history.html for an example.
Ext.History.init();
and add an iframe and a hidden input field to your page, like in the example:
<form id="history-form" class="x-hide-display">
<input type="hidden" id="x-history-field" />
<iframe id="x-history-frame"></iframe>
</form>