Converting HTML & Script Code of the YouGlish API to React Application - javascript

I have a React application which uses YouGlish Javascript API. In my application, I want to open a video screen by clicking a button that calls the YouGlish functions. Here is the Button implementation:
<div id="buttons">
<button id="youglish" onClick={() => YouglishWidget()} style={{ display: youglish ? 'block' : 'none'}}>YouGlish</button>
</div>
And the function, YouglishWidget(), which is called by button is:
export function YouglishWidget() {
console.log("YouglishWidget is called");
const tag = document.createElement('script');
tag.src = "https://youglish.com/public/emb/widget.js";
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var views = 0, curTrack = 0, totalTracks = 0;
function onFetchDone(event) {
console.log("onFetchDone is called");
if (event.totalResult == 0){
alert("No result found");
}
else totalTracks = event.totalResult;
}
function onVideoChange(event) {
curTrack = event.trackNumber;
views = 0;
}
function onCaptionConsumed(event) {
if (++views < 3) {
widget.replay();
} else if (curTrack < totalTracks) {
widget.next();
}
}
function onYouglishAPIReady() {
console.log("onYouglishAPIReady is called");
const widget = new YG.Widget("widget-1", {
width: 640,
components: 9,
events: {
onFetchDone: onFetchDone,
onVideoChange: onVideoChange,
onCaptionConsumed: onCaptionConsumed,
},
});
widget.fetch("courage", "english");
}
return (
<div id="widget-1"></div>
);
}
I tried to transform HTML & javascript code from the this URL (Javascript API Reference). When I click the button, nothing returns from YouglishWidget(). What should I do to return the screen when I click the button?
YouglishWidget() function returns nothing.

Related

Loading spinner in Vue.js from FileInput

I have a problem that I can't get my head around.
I am using Three.js in my web app and I want to add a loading spinner when I upload a file.
For that I created a component with the loading spinner, and display it with v-if when the file gets loaded.
Strangely enough, this does not work, even though the value "loading" is true when logged from within the function (when I log it after the file is loaded it is false again without changing it).
The code:
<template>
<div class="button-draw-container">
<input id="file-input" name="button-upload" type="file" #click="importFile"/>
</div>
<div v-if="loading" id="wrapper-loader">
<Loader/>
</div>
</template>
<script>
export default {
components: {
Loader
},
data() {
return {
loading: false,
}
},
methods: {
importFile() {
var fileInput = document.querySelector("#file-input");
var cores = [];
var outline;
fileInput.addEventListener("change", function(event) {
//This is the part that's not working
this.loading = true;
console.log(this.loading)
const reader = new FileReader();
reader.addEventListener("load", function(event) {
const contents = event.target.result;
const loader = new Rhino3dmLoader();
loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/three#0.138.2/examples/jsm/libs/rhino3dm/' );
loader.parse( contents, function( object ) {
for (let i = 0; i < object.children.length; i++) {
if(object.children[i].userData.attributes.layerIndex == 1) {
cores.push(object.children[i].geometry);
}
else if(object.children[i].userData.attributes.layerIndex == 2) {
outline = object.children[i].geometry;
}
}
} );
});
reader.readAsArrayBuffer( this.files[0] );
})
},
}
</script>
The problem was that the scope of "this" is within the function block, meaning that this is no longer a reference to the Vue instance.
Using an arrow function which has no lexical scope and changing the last line to reader.readAsArrayBuffer( fileInput.files[0] ); did the job.

Browser Full screen feature

Hi I have the below page where you simply click the button Full screen and the page browser takes up the full screen, the navigation controls are also hidden to - which is what I like. However if you page refresh (or in my case my page refreshes every 5 minutes) the navigation controls return and it is no longer the view as previous. How can I solve this so that when it refreshed the navigation etc doesn't return and it remains full screen?
<html>
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" />
<script src="screenfull.js"></script>
<script>
$(function () {
$('#supported').text('Supported/allowed: ' + !!screenfull.enabled);
if (!screenfull.enabled) {
return false;
}
$('#request').click(function () {
screenfull.request($('#container')[0]);
// does not require jQuery, can be used like this too:
// screenfull.request(document.getElementById('container'));
});
$('#exit').click(function () {
screenfull.exit();
});
function fullscreenchange() {
var elem = screenfull.element;
$('#status').text('Is fullscreen: ' + screenfull.isFullscreen);
if (elem) {
$('#element').text('Element: ' + elem.localName + (elem.id ? '#' + elem.id : ''));
}
if (!screenfull.isFullscreen) {
$('#external-iframe').remove();
document.body.style.overflow = 'hidden';
}
}
document.addEventListener(screenfull.raw.fullscreenchange, fullscreenchange);
// set the initial values
fullscreenchange();
});
</script>
<button id="request"><i class="fa fa-arrows-alt"></i> Request</button>
<button id="exit">Exit</button>
</body>
(function () {
'use strict';
var isCommonjs = typeof module !== 'undefined' && module.exports;
var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
var fn = (function () {
var val;
var valLength;
var fnMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// new WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
// old WebKit (Safari 5.1)
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror'
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError'
]
];
var i = 0;
var l = fnMap.length;
var ret = {};
for (; i < l; i++) {
val = fnMap[i];
if (val && val[1] in document) {
for (i = 0, valLength = val.length; i < valLength; i++) {
ret[fnMap[0][i]] = val[i];
}
return ret;
}
}
return false;
})();
var screenfull = {
request: function (elem) {
var request = fn.requestFullscreen;
elem = elem || document.documentElement;
// Work around Safari 5.1 bug: reports support for
// keyboard in fullscreen even though it doesn't.
// Browser sniffing, since the alternative with
// setTimeout is even worse.
if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
elem[request]();
} else {
elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
}
},
exit: function () {
document[fn.exitFullscreen]();
},
toggle: function (elem) {
if (this.isFullscreen) {
this.exit();
} else {
this.request(elem);
}
},
raw: fn
};
if (!fn) {
if (isCommonjs) {
module.exports = false;
} else {
window.screenfull = false;
}
return;
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: function () {
return Boolean(document[fn.fullscreenElement]);
}
},
element: {
enumerable: true,
get: function () {
return document[fn.fullscreenElement];
}
},
enabled: {
enumerable: true,
get: function () {
// Coerce to boolean in case of old WebKit
return Boolean(document[fn.fullscreenEnabled]);
}
}
});
if (isCommonjs) {
module.exports = screenfull;
} else {
window.screenfull = screenfull;
}
})();
Online Demo : https://plnkr.co/edit/zx0rXwXpJbWdMvh3HQ25?p=preview
Make onepage website (ajax) (no refresh) Use history pushstate to save all your links so you can use history navigation and change your URL. (most of time I use this approach.)
Or you can use localstorage to save state.
Theoretically You can store an indication of what was the previews state (full-screen / normal) in the browser storage.
Then on page load, read the stored value and activate full-screen if necessary.
However, modern browsers require this to be an interactive user action (not automatically via script on load)
If you try to automate this, you'll get these type of warnings in the browser's console:
Alternatives
Avoid full refreshes
Workaround using custom browser extension to restore the fullscreen state

Mixin functions only work in render()

For some reason, it appears that mixin functions in my code only work properly in render() function. It could be that I'm not calling them in the right manner outside of the render(), but shouldn't it be exactly the same way?
This way everything works fine (but I can't stick with this since I have to add some extra stuff to click handling, at the same time not altering the mixin):
var Row = React.createClass({
mixins: [someMixin]
},
render: function () {
var clickHandler = null;
var btn = null;
if (firstCase) {
clickHandler = this.order(this.props.name, this.props.else);
btn = (<a href="" onClick={clickHandler}>Order</a>);
} else if (secondCase) {
clickHandler = this.noOrder(this.props.name, this.props.else);
btn = (<a href="" onClick={clickHandler}>No order</a>);
}
return (
<div>
{btn}
</div>
);
}
});
But when I do the obvious and include the mixin functions in another function to handle the click - like this - everything fails and even 'test' is not printed in the console:
var Row = React.createClass({
mixins: [someMixin]
},
handleOrderClick(type) {
console.log('test');
if (type == 'order') {
this.order(this.props.name, this.props.else);
} else if (type == 'no-order') {
this.noOrder(this.props.name, this.props.else);
}
},
render: function () {
var clickHandler = null;
var btn = null;
if (firstCase) {
clickHandler = this.handleOrderClick('order');
btn = (<a href="" onClick={clickHandler}>Order</a>);
} else if (secondCase) {
clickHandler = this.handleOrderClick('no-order');
btn = (<a href="" onClick={clickHandler}>No order</a>);
}
return (
<div>
{btn}
</div>
);
}
});
EDIT:
order and noOrder functions look like this:
order: function (name, else) {
return function (event) {
event.preventDefault();
var term = name + '&&ยค%' + else;
Order.order(name, else, period, function (data) {
if (term === (global || window).MAIN_NAME + '.' + (global || window).MAIN) {
$(window).trigger('Name:update');
}
}.bind(this));
}.bind(this);
},
noOrder: function (name, else) {
return function (event) {
event.preventDefault();
if (!this.state.transferModalOpen) {
this.toggleTransferModal();
}
}.bind(this);
}
In order to use this.setState in handleOrderClick you'll have to use the bind method in your render method. Therefore handleOrderClick will become:
handleOrderClick(type, event) {
this.setState({foo: 'bar'});
if (type == 'order') {
this.order(this.props.name, this.props.else)(event);
} else if (type == 'no-order') {
this.noOrder(this.props.name, this.props.else)(event);
}
},
and your render method becomes:
render: function () {
var clickHandler = null;
var btn = null;
if (firstCase) {
clickHandler = this.handleOrderClick.bind(this, 'order');
btn = (<a href="" onClick={clickHandler}>Order</a>);
} else if (secondCase) {
clickHandler = this.handleOrderClick(this, 'no-order');
btn = (<a href="" onClick={clickHandler}>No order</a>);
}
return (
<div>
{btn}
</div>
);
}
You'll notice that the functions that are returned by this.order and this.noOrder are no longer returned by handleOrderClick, but are instead executed immediately. This should provide the effect you desire.
I've put the code in your example into a jsfiddle and it now seems to be working correctly. I've had to change the prop 'else' to 'alt' because 'else' is a reserved word. I've also just applied the mixin to the class directly for simplicity. I have simpilfied the order and noOrder functions as I don't have access to the Order object and we are only interested in them firing at the correct time. I've also added a second button that you can click to flip the cases so the other button is rendered, causing the component to render again. I've added a label that will display which function had been called when the button was last pressed.
for reference, you can find more information about the bind method here.
Hope this helps ^_^

Javascript click event callback not working

I am using javascript to handle click event.
The code is below :
function addClickEventListenerToAllAnchorTag() {
var anchors = document.getElementsByTagName("a");
for(var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
var guid = anchor.attributes.getNamedItem('GUID');
if(guid)
{
anchor.addEventListener("click", onClickLoginPopup);
}
}
}
Here I am fetching all anchor tags that has GUID attribute and adding click event listener to it.
But my callback function onClickLoginPopup never gets called.
function onClickLoginPopup(e) {
console.log('onClickLoginPopup');
e.preventDefault();
var host = window.location.hostname;
var url = this.href;
var guid = this.attributes.getNamedItem("GUID");
var mainPopup = document.getElementById('popupMain');
var popupPayment = document.getElementById('popupPayment');
if( mainPopup == null ) {
console.log(mainPopup);
}
else if(userID)
{
showSocialLoginPopup();
return false;
}
if(popupPayment !== null){
showPaymentPopup();
}
//articleLinkClickAction(guid);
return false;
}
Calling Code:
function mpwInit() {
addPopupContents();
addClickEventListenerToAllAnchorTag();
}
includeScripts();
window.onload = mpwInit;
When are you calling addClickEventListenerToAllAnchorTag function ? Have you logged the list of selected anchor elements ? Is it an empty array ? If it is an empty array then you JavaScript code is getting executed before the page loads.

Location.hash does not match history

I am experimenting with making a one page app with a header and an iframe for the content of the page. So... I made a little javaScript controller to do so. It takes an enter code hereobject named routes to handle clicks on some of the anchor tags which I want to trigger a change in the iFrames url. This is all working fine for me, but when I go to use the back button it does not seem to be aligned correctly.
this is where I got the idea: http://gtv-resources.googlecode.com/svn/trunk/examples/location-hash-html.html#3
here is the article that google has written on it: https://developers.google.com/tv/web/articles/location-hash-navigation
<script src="controller.js"></script>
<script>
var routes = {
"view":"viewFrame",
"index": {
"name": "main",
"location": "subpages/landing.html"
},
"paths": {
"about": "subpages/about.html",
"download": "subpages/download.html",
"main":"subpages/landing.html"
}
};
</script>
</head>
<body>
<ul>
<li><a class='handle' data-link='main'>Back To Main Page</a>
</li>
<li><a class='handle' data-link='about'>About</a>
</li>
<li><a class='handle' data-link='download'>Download</a>
</li>
</ul>
<iframe id="viewFrame" src="subpages/landing.html">
</body>
and my js file
window.onload = function() {
if (routes) {
var View = routes,
flag = true;
View.update = function(hashValue, flag) {
console.log('ok2')
var frame = document.getElementById('viewFrame');
frame.src = routes.paths[hashValue]
if (flag) {
View.setHash(hashValue);
}
};
View.getHash = function() {
return window.location.hash.substring(1);
}
View.setHash = function(str) {
flag = false;
window.location.hash = str;
}
window.onhashchange = function(e) {
if (flag) {
View.update(getLocationHash(), false);
} else {
flag = true;
}
};
var hashValue = View.getHash(),
handles = document.querySelectorAll('.handle');
for (var i = 0; i < handles.length; i++) {
console.log(handles[i]);
handles[i].addEventListener('click', evTrigger)
}
function evTrigger() {
console.log(this)
var link = this.getAttribute('data-link')
View.update(link, true)
}
if (hashValue == '') {
View.update(routes.index.name, true);
}
}
};
if you can interpret my madness I would be thankful for the help.

Categories

Resources