Click a link on WebView and open the url in a browser - react-native

My node version is: 10.6.0
My npm version is: 6.1.8
I am rendering a website under a WebView inside a react native app.
I need to open a URL outside the react native app when I touch a link.
My html file is like below
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" >
$(document).ready(function () {
$("#fb").click(function() {
window.postMessage("fbclicked");
});
});
</script>
</head>
<body>
<a id="fb" href="fb">Click Here</a>
</body>
</html>
What should i do in my react native App.js to open the link outside of the app.
Need help.
Thanks.

You need to use linking.
Linking.openURL(url).catch(err => console.error('An error occurred', err));
If URL is like http://, it's open the browser. Also if it's mailto: , open your email client . Etc...

Related

React Native: <script> tag not working in react-native-webview

I've created a simple html page and loading it into WebView :
const OurStoryHTML = require ('./test.html');
import { WebView } from "react-native-webview";
<WebView
source={OurStoryHTML}
originWhitelist={["*"]}
/>
My webpage contains the following tag:
<script async="async" src='http://www.youvisit.com/tour/Embed/js2'></script>
However, the script seems not to be loading in react-native-webview but works fine in the browser. Any workaround for this?
You must put double curly braces after source prop in WebView
source={{OurStoryHTML}}

Vue.js inject styles in <body> instead of <head> of index.html (webpack, HtmlWebpackPlugin)

Basically, I want achieve this index.html structure:
<html>
<head>
<!-- titles, metas and other "static" stuff -->
<link rel="preload/prefetch" ...> <!-- injected by webpack (ok) -->
<!-- By default compiled styles are injected here, in head, I want them in body -->
</head>
<body>
<div>
My static loading animation
All possible styling is inlined
It doesn't depend on anything!
It also could be anything, even just a plain "Loading..." text.
You still WON'T see it until all style's in head are loaded.
</div>
<div id="app">Vue application goes here</div>
<link rel="stylesheet" href="..."> <!-- Styles injected by webpack (WANTED!) -->
<script src="..."></script> <!-- Scripts injected by webpack (by default, OK) -->
</body>
The reason I want this, is that my html is completely capable of displaying initial loading animation to the user and I want it to render instantly as soon as index.html is loaded and not depend on any other resources. Really, I think this is everybody want, just to say...
But Vue by debault is configured to include it's compiled styles to the <head> tag, which blocks rendering of the page until these styles are loaded. I cannot find any docs of how I could change it.
Update: Pictures!
So, I've managed to manually simulate two variants:
styles are injected in <head> (default)
styles are injected in <body> (wanted)
Here are the pictures of the visual difference:
1) styles are injected in <head> (default):
2) styles are injected in <body> (wanted):
The label "html rendering starts" on pictures means that a user actually sees loading animation, defined completely inside html (small piece of svg and styling in my case, could be anything in general case) and doesn't depend on any other external resources for it to render.
Solution
vue.config.js
class InjectStylesInBody {
apply(compiler) {
compiler.hooks.compilation.tap('inject-styles-in-body', (compilation) => {
if (!compilation.hooks.htmlWebpackPluginAlterAssetTags) return;
compilation.hooks.htmlWebpackPluginAlterAssetTags.tap('inject-styles-in-body', function(pluginArgs) {
const { head, body } = pluginArgs;
head
.filter(asset => asset.tagName === 'link' && asset.attributes && asset.attributes.rel === 'stylesheet')
.forEach(asset => {
head.splice(head.indexOf(asset), 1);
body.push(asset);
});
});
});
}
}
module.exports = {
// ...
chainWebpack: config => {
// ...
config
.plugin('inject-styles-in-body')
.use(InjectStylesInBody)
;
// ...
}
// ...
};
Notes
Eventually, this has nothing to do with Vue.js. One could easily use this with other frameworks or with naked webpack.
It could be much easier if HtmlWebpackPlugin had some inject-css option for styles as it has for scripts.
See: https://github.com/jantimon/html-webpack-plugin/blob/e2c6990e94b298ff66bcd885c9a03a78221479f6/index.js#L548

pressKey Enter on contenteditable in Safari

I'm trying to use TestCafe to test a chatbot which uses a contenteditable div as the user-input. Have actually succeeded with Chrome and Firefox to press enter and pass the tests, but have not been able to get Safari to press enter. I realize that contenteditable does not support pressKey("enter") but I'm wondering why it works for both Chrome and Firefox and not Safari, and whether I can get it to work for Safari?
test("Able to send a message on enter keypress", async t => {
await t
.typeText(chatbot.userReply, "hi")
.pressKey("enter")
.expect(chatbot.transcriptMessages.find("li").withText("hi").count).eql(1)
})
It's difficult to say why this does not work in Safari without researching a working sample showing the problem. As far as I understand from your description, your contenteditable element has the keypress event handler, which sends a message on the enter press. I've prepared a sample project to demonstrate this approach, and it all operates correctly both Safari and Chrome:
Test page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="editor" contenteditable="true" style="width: 300px; height: 300px; border: 1px solid black;">test</div>
<script>
document.getElementById('editor').addEventListener('keypress', function() { alert('test') })
</script>
</body>
</html>
Test code:
fixture `test`
.page `../pages/index.html`;
test(`test`, async t => {
await t.click('#editor');
await t.pressKey('enter');
});
In a comment on this page you mentioned that this is in an iframe so you will need to do:
await t.switchToIframe(iframeSelector);
When switching back you can do:
await t.switchToMainWindow();

Unable to click button inside iframe with selenium webdriver (javascript)

I have a page that loads an iframe, but I get NoSuchElementError error messages.
My code:
driver.wait(until.ableToSwitchToFrame(0)).then((d) => {
//*** SLEEP HERE
const button = By.css(".button");
driver.wait(until.elementLocated(dropdownElem)).then((btn) => {
btn.click();
});
});
First I switch to the correct iframe, then I try to wait for the element to load inside the iframe.
If I insert a driver.sleep(1000); to the line //*** SLEEP HERE it works, otherwise it fails with:
NoSuchElementError: no such element: Unable to locate element: {"method":"css selector","selector":".button"
}
Why doesn't the driver.wait line waits for the element to become available?
I tested this on my local and it seems to have worked fine for a button within Iframe. Here is the code
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().usingServer().withCapabilities({'browserName': 'chrome' }).build();
driver.get('file:///Users/../sampleFiles/sample-iframe.html');
driver.wait(webdriver.until.ableToSwitchToFrame(0)).then((d) => {
//*** SLEEP HERE
const button = webdriver.By.css(".Button");
driver.wait(webdriver.until.elementLocated(button)).then((btn) => {
btn.click();
btn.getTagName().then((tag) => {
console.log(tag);
});
});
});
I get button on console
and Iframe HTML this is tested on is
<html lang="en"><head>
<meta charset="UTF-8">
<title>Example of HTML Iframe</title>
</head>
<body>
<iframe src="file:///Users/../sampleFiles/sample.html" width="300" height="200">
<html><head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
<button id="ButtonID" class="Button">Click Me!</button>
</body></html>
</iframe>
</body></html>
Check your driver.wait(until.elementLocated(dropdownElem)) line , seems theres a typo , change it to
driver.wait(until.elementLocated(button )) and try again

ReferenceError: videojs is not defined

I am using video.js (in CDN-Mode) and everything seems to work fine (with Firefox 26.0). The video is embedded and works fine. But when I want to access the video-Object, I'm getting the console-error:
ReferenceError: videojs is not defined on the code-line where I want to access the object:
var myPlayer = videojs('example_video_1');
Googling arround could not solve my problem. I saw implementations where users used: V as constructor instead of videojs but this did not solve my problem).
This is my script, where I want to access the object:
<script type="text/javascript">
$("#button1").on("click", function(){
console.log( "You clicked a paragraph!" );
var myPlayer = videojs('example_video_1');
});
</script>
This is my header
<link href="http://vjs.zencdn.net/4.5/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.5/video.js"></script>
<script language="javascript" type="text/javascript" src="js/jquery.js"></script>
And this is my video-declaration
<video id="example_video_1" class="video-js vjs-default-skin" controls
preload="auto" width="1270" height="720" poster="videos/search.png"
data-setup="{}">
<source src="videos/search.webm" type='video/webm'>
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video</p>
</video>
I would be happy for any kind of support.
A year and a half later and this issue occurred for me as well. I just installed it via npm install --save video.js and moved the file from the dist folder into my public scripts folder and it worked.
You must install or use from #videojs/http-streaming. I had same problem and solved by it.
I just made sure that the video.js file was the last attached script tag in the HTML. It worked for me.
import videojs from 'video.js';
try:
<script type="text/javascript">
$("#button1").on("click", function(){
console.log( "You clicked a paragraph!" );
var myPlayer = window.videojs('example_video_1');
});
</script>
add the event listener 'DOMContentLoaded' before calling the videojs object:
window.addEventListener('DOMContentLoaded', (event) => {
videojs('element-id', {
controls: true,
autoplay: false,
preload: 'auto'
});
});