Cannot get YouTube video to play inside a Windows.Forms.WebBrowser control - winforms

I tried to simpliy assign the following getting started HTML code to the DocumentText property of the WebBrowser control.
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
</body>
</html>
This gives me the following script error at runtime:
It turns out that even the following simplified code produces the same error:
webBrowser1.DocumentText = "<!DOCTYPE html><html><body><script src='https://www.youtube.com/iframe_api'></script></body></html>";
So it looks like the WebBrowser control is not able to load the iframe-API. What could be the problem here? Or how could I investigate this error further?

I found the solution for WebBrowser. First we have to force WebBrowser running with the latest IE which we have on our machine like this.
Second I have to stream HTML through ASP.NET Web API and Katana like this, using WebBrowser to navigate to http://localhost:xxxx/api/xxxx
Setting DocumentText won't work because WebBrowser has many security limitations when loading html locally.
The other simple solution is just use other browser engine like Gecko or CefSharp.

Related

Shaka Player Start Video in full screen

I have the basic shaka player code. I want to start the video on full screen. Please tell me if it is possible.
HTML
<!DOCTYPE html>
<html style="height:100%">
<head>
<!-- Shaka Player compiled library: -->
<script src="dist/shaka-player.compiled.js"></script>
<!-- Your application source: -->
<script src="myapp.js"></script>
</head>
<body style="height:100%">
<video id="video"
width="100%"
height="100%"
poster="//shaka-player-demo.appspot.com/assets/poster.jpg"
controls autoplay></video>
</body>
</html>
myapp.js
// myapp.js
var manifestUri =
'./asd.mp4';
function initApp() {
// Install built-in polyfills to patch browser incompatibilities.
shaka.polyfill.installAll();
// Check to see if the browser supports the basic APIs Shaka needs.
if (shaka.Player.isBrowserSupported()) {
// Everything looks good!
initPlayer();
} else {
// This browser does not have the minimum set of APIs we need.
console.error('Browser not supported!');
}
}
function initPlayer() {
// Create a Player instance.
var video = document.getElementById('video');
var player = new shaka.Player(video);
// Attach player to the window to make it easy to access in the JS console.
window.player = player;
// Listen for error events.
player.addEventListener('error', onErrorEvent);
// Try to load a manifest.
// This is an asynchronous process.
player.load(manifestUri).then(function() {
// This runs if the asynchronous load is successful.
console.log('The video has now been loaded!');
}).catch(onError); // onError is executed if the asynchronous load fails.
}
function onErrorEvent(event) {
// Extract the shaka.util.Error object from the event.
onError(event.detail);
}
function onError(error) {
// Log the error.
console.error('Error code', error.code, 'object', error);
}
document.addEventListener('DOMContentLoaded', initApp);
I did this using the below code
player.load(manifestUri).then(function() {
// This runs if the asynchronous load is successful.
console.log('The video has now been loaded!');
video.requestFullscreen().catch(err => {
console.log(err)
});
}).catch(onError); // onError is executed if the asynchronous load fails.
Please let me know if there is a better solution

How to call Google Cloud Endpoints with AngularJs when the page Loads, to get user information(PICTURE, NAME..)

I am trying to make a post request using Google Cloud Endpoints and AngularJS when the page loads so I can get the user information and fill the profile picture, profile description and so on...
I am able to run requests when pressing a button or something like that but can't call the google endpoints automatically when the page loads and that is whats I am trying to achieve.
Below is the HTML part where the {{userPicture}} should've been loaded in the angular script:
(HTML)
<div class="form-group">
<label class="col-sm-3 control-label">Profile image</label>
<div class="col-sm-9" ng-controller='initController'>
<img src="{{userPicture}}" class="user-image-profile" alt="User Image">
</div>
</div>
(ANGULAR)
controllers.initController = function($scope, $http){
$scope.userForm = {
"userEmail" : $.cookie('auth')
};
gapi.client.igardenendpoints.getProfile($scope.userForm).execute(function(resp) {
$scope.$apply(function () {
if (resp.error) {
$scope.backmessage.messagetext = "GetProfile Error!"
console.log("error");
} else {
if (resp.userEmail == "TEMPLATE"){
$scope.backmessage.messagetext = "Error please try again!"
}else{
$scope.userPicture = 'https://filiperebollo1986.appspot.com/serve?blob-key=' + resp.profilePicKey;
}
}
});
});
}
error
I also tried to use the following:
$scope.initData = function () {
gapi.client.igardenendpoints.getProfile($scope.userForm)...........
}
and run the function at the end of the controller, like:
$scope.initData();
But both does not work, any help on that?
I will not be able to help you in 100% as I'm not using Google Cloud, but will try to do my best.
First of all, to get the data it's usually better to use services rather than do it in the controller.
But anyway, your problem seems to be different. In your HTML did you include your script and client API?
I was able to fix my problem and bellow is the solution:
The problem was that at the moment of my call, the script may not have been loaded once I was using the "ng-app" directive directly on the body TAG.
Now I am injecting the angular module dinamicaly just after my API loading:
function googleOnLoadCallback(){
var apisToLoad = 1; // must match number of calls to gapi.client.load()
var gCallback = function() {
if (--apisToLoad == 0) {
//Manual bootstraping of the application
var $injector = angular.bootstrap(document, ['authModule']);
console.log('Angular bootstrap complete ' + gapi);
};
};
gapi.client.load('igardenendpoints', 'v12', gCallback, '//' + window.location.host + '/_ah/api');
}
</script>
<script src="https://apis.google.com/js/client.js?onload=googleOnLoadCallback"></script>
And now It is working!!!!
The only problem now is that when the page loads it appears the {{example}} in the page, is it possible to avoid the {{}} to appear?

Marionette layout view -- why is a template necessary

In spite of reading the marionette docs several times over, I am still not able to fully comprehend some aspects of it correctly.
I am creating a layout view 'AppLayout' as below:
var AppLayoutView = Marionette.LayoutView.extend({
regions: {
headerRegion: "#ecp_header",
bodyRegion: "#ecp_layout_region"
},
...
The html snippet for my app is having the two dom nodes for above defined regions:
<div id="ecp_header"></div>
<div class="container" id="ecp_layout_region">
<div class="row" id="ecp_body">
...
in app.js, my calling code is like this..
ECPApp.on('start', function() {
require(['controller_cp', 'header_view'], function(ControllerCP, HeaderView) {
console.log("On start event executing...");
// create a event aggregator vent object and attach to app.
ECPApp.vent = new Backbone.Wreqr.EventAggregator();
var appLayoutView = new AppLayoutView();
appLayoutView.render();
//appLayoutView.showLayout();
//$('div.toolbar > ul > li:first > a').tab('show');
if (Backbone.history) Backbone.history.start();
});
This gives me error Cannot render the template since it is null or undefined.
I thought that the default render() behavior of layout always looks for a template, so I rolled out my own version of render, as below:
render: function() {
var $self = this;
/* if no session exists, show welcome page */
var promise = ECPApp.request('entities:session');
promise.done(function(data) {
if (data.result==0) {
console.log('Valid session exists. Showing home page...!');
$self.showHome();
} else {
console.log('No session exists. Showing welcome page...!');
$self.showWelcome();
}
}).fail(function(status) {
console.log('No session exists. Showing welcome page...!');
$self.showWelcome();
});
return $self;
},
showWelcome: function() {
var self = this;
require(['header_view', 'welcome_view'],
function(HeaderView, WelcomeView) {
var headerView = new HeaderView();
var welcomeView = new WelcomeView();
self.bodyRegion.show(welcomeView);
});
}
This time, I get another error saying, An "el" #ecp_layout_region must exist in DOM. However I am sure that the element is existing in the DOM, as I can see it by checking in the debug console window. Running $('#ecp_layout_region') shows a valid element.
Marionette layout view is pretty confusing. Going forward I need multiple nested views. I am stuck here.
How is your template located? Is your template wrapped by <script type = “text/template”> tag?
It may look like this:
Inside your html, in head section:
<script type = “text/template” id="yourLayout">
<div id="ecp_header"></div>
<div class="container" id="ecp_layout_region">...</div>
</script>
And in Layout definition:
var AppLayoutView = Marionette.LayoutView.extend({
template: '#yourLayout'
...
});

window.addeventlistener in firefox does not fire event on http status 302

I am trying to get an authentication script working. It has been supplied by my company, as it is what they are using in other systems. I am having an odd inconsistent behavior between chrome and firefox v19 (what is standard in our desktop environments currently).
The process is pretty simple: we create an iframe, which is pointed to a SAML service. I have an angularJS SPA that is waiting for that SAML service to respond with a JSON object that will tell my app if the user is authenticated or not. Then we either run our app (using angular.bootstrap(document, ['mySPA']); or do something else if unauthorized.
The code in question is this:
(function createIframe() {
var iframe = document.createElement("iframe");
setAttributes(iframe, {
"name": "auth",
"id": "myFrame",
"src": "https://api.SAML2AuthService",
"height": "0",
"width": "0",
"border": "0"
});
document.body.appendChild(iframe);
// Create IE + others compatible event handler
authEventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
authEvent = window[authEventMethod];
authMessageEvent = authEventMethod == "attachEvent" ? "onmessage" : "message";
})();
// Listen to auth iframe message
authEvent(authMessageEvent, function (e) {
var authorized = false;
for (var i = 0; i < 2; i++) {
Authentication = Auth.getInstance();
if (e.data !== null) {
data = e.data;
if (data.isAuthorized === "true" && data.authorizationToken !== null) {
Authentication.isAuthorized = e.data.isAuthorized;
Authentication.principal = e.data.principal;
Authentication.description = e.data.description;
Authentication.authorizationToken = e.data.authorizationToken;
authorized = true;
break;
}
}
}
if (!authorized) {
console.log("Unauthorized");
}
}, false);
Then, we call:
angular.element(document).ready(function() {
angular.module( 'mySPA', []
...
});
angular.bootstrap(document, ['associateDesktop']);
});
However, for reasons beyond my control, the SAML service performs a redirect to get the actual credentials. My browser's debug console shows these as HTTP Status 302, then (I assume) redirected and returned to me as HTTP Status 200.
Specifically, my question is that the AuthEvent event that I attach to window is not always getting fired off. In chrome, if I clear all browsing data (cookies, etc) the authEvent fires, and I get authenticated (or not) as I would expect. In Firefox, if I clear all cached data, the authEvent never gets fired. Am I attaching the event wrong? Does Firefox not call an event like this for a 302? Does angular's ready() function do something I'm not expecting (being impatient)?
Thanks in advance!
This same code now works in FF 19. I changed nothing, and I ended up finding out after-the-fact that the service was returning some slightly malformed data that apparently chrome was able to handle gracefully but firefox wasn't. That malformed data has been fixed, so now the code works. I no longer have access to the original (allegedly bad) content that was being sent to the browser, so I can't post it here to show a helpful bug and solution.
However, I wanted to at least record that the above code works fine, and post a simpler version here so anyone looking for code that can be used has something to go if. Sorry I can't give a better answer of what the actual issue was.
Parent html
<html>
<script>
var authEvent = function(event) {
// debugger;
var div = document.getElementById("response");
div.innerHTML = event.data.message;
};
if (window.addEventListener) {
window.addEventListener("message", authEvent, false);
}
else {
window.attachEvent("onmessage", authEvent);
}
</script>
<body>
<iframe src="frame.html"></iframe>
<br /><br /><br />
<div id="response">No response...</div>
</body>
iFrame html
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script>
var authResponse = {
"message": "Iframe called parent successfully!"
};
window.onload = function() {
parent.postMessage(authResponse,"*");
};
</script>
</head>
<body>
Child iFrame....
</body>
</html>

Sencha with phonegap Native open external link

I have deployed a native app android + ios with sencha touch + phonegap.
If we click a link inside the app it opens inside the app and we cannot go out.
Does someone now how it is posible to let links open into the phone browser?
window.open("yoururl", '_blank');
The phonegap version I used was 2.9.0 if I am not mistaken.
I had the same problem and solved it as follows:
Embed the JQuery javascript file in your project. In my case it was:
<script type="text/javascript" charset="utf-8" src="js/jquery-1.10.2.min.js"></script>
Then I wrote the following function, which I called in the onDeviceReady function:
function enableHttpLinks() {
$('.externalLink').click(function(e) {
e.preventDefault();
url = $(this).attr("href");
window.open(url, '_system');
});
}
In order for this function to work, you have a assign the class externalLink to all the links you want to open in the device browser, as shown below:
your link title
good luck...
Just add this function inside "launch" function, in the app.js like this:
launch: function() {
// Destroy the #appLoadingIndicator element
//Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('yourApp.view.Main'));
// Voila :
Ext.Viewport.element.dom.addEventListener('click', function (e) {
if (e.target.tagName !== 'A') {
return;
};
var url = e.target.getAttribute('href');
var containsHttp = new RegExp('http\\b');
//if href value begins with 'http'
if(containsHttp.test(url)) {
e.preventDefault();
window.open(url, "_system"); // For iOS
navigator.app.loadUrl(url, {openExternal: true}); //For Android
}
else {
return;
}
}, false);
}, //...
Then you can build for android and iOS at the same time.

Resources