videojs doesn't load when change state with ui-router - angularjs

I am working on a project with videojs that must work on Firefox and IE 11, and is built with a angular-ui-router. One of the states has a video player, and on the first time loading, videojs properly generates the content. However, if you navigate away from that state and come back, videojs content isn't generated and the default html5 video element is displayed. Is there a way to deal with this problem? In addition, (more often in IE 11), videojs will sometimes randomly fail to generate the content on the first page load. I can't figure out if the problems are related, or what is even causing the problem because there are no errors in the console log.
I'm not sure what code will even be relevant to post. Here is the html for the video:
<video controls preload data-setup="{}" class="video-js vjs-default-skin vjs-big-play-centered full-video" poster="img/CollaborationPoster.png">
<source ng-repeat="src in video.srcs" ng-src="{{src.url | trustUrl}}" type="{{src.mimeType}}"/>
</video>
In addition I have:
window.VIDEOJS_NO_DYNAMIC_STYLE = true;
At the start of my app. However, the problem still exists if I get rid of this.
Feel free to ask for any other code that could help diagnose the problem
(NOTE: I am also open to suggestions on using a different framework/etc for the video component. videojs has been very frustrating overall)
EDIT: In case it's relevant, 'full-video' is the only custom class for the video and its styling is:
.full-video {
width: 100%;
height: auto;
}

I have the same problem, and I find a way to solve it.
Add this code in your controller may help you.
$scope.$on('$destroy', function () {
video.dispose();
});
Video is the player object created by videojs() function.
Can look at this discussion for more infomation.
angular single page app, videoJS ready function only fires on page load

I assume you are using some form of routing? Perhaps you need to reload the controller/directive/component.

Related

protractor test for a video tag

I am fairly new to front end land, so bear with me... I have an HTML page with an embedded video through an HTML video tag like so:
<video id=... class=...>
<source src=... type="video/mp4">
</video>
This video resets back to the beginning when it is done playing. Now I would like to test this using protractor. Currently I can get the element, but I do not know how to play/pause the video, see how far along the video is, etc. from a protractor test. I can get the element through element(by.id('<id>')) and I can do the normal stuff like seeing if it is visible, click on it, etc. but have no idea how to get at the guts of the element.
UPDATE:
The issue with this is that the controls are provided by the browser as my video tag specifies the 'controls' attribute. That means the play/pause button is not part of the DOM and hence why I cannot get to it. Also, the browser is the one that sends an event to say that the video has ended. So, in order for me to test that the video resets after it has ended, I would need to hit the play button which is not listed as a DOM object. Is there a way to trigger an 'ended' event without playing the video? Or can I trigger it by setting the currentTime attribute to the duration attribute somehow?
you can't select play/pause controls by selectors , instead you can add a button by your own and add HTML audio/video events to it . So that you can automate using that button.
button.onclick = function () {
(videoSelector).play/pause();
}
To play the video you will have to select the 'play' button from the 'DOM' rather than the video tag by id say element(by.css('<.class of play button>'))
and if its present in the callback of isPresent() add the click event. To give a complete answer it will be good to have a snapshot of the 'DOM' at the time when video is played.
The best option i found at the moment is using plain javascript to automate the
execution of pausing, playing, etc. adding the following code either in a page object or a spec:
browser.executeScript(function () {
var video = document.getElementById('video');
video.play();
});

Mozilla Web Extensions: Insert UI component into page

I am writing a Web Extension for Firefox that needs to insert a substantial amount of additional functionality inside pages retrieved using certain URLs.
I was able to quickly create a content script that is called whenever a certain page is opened thanks to the tutorial at Mozilla's web site, but now I'm stuck on actually inserting html fragment into the page.
I've been at it for hours but to no avail. Here's what I've considered and tried:
iframe didn't work as apparently some security policy doesn't allow using iframes pointing to local resources and the last comment here even tells that I'm supposed to use panel instead of iframe
Using Panel doesn't work for me for two reasons:
I couldn't find a way to open a Panel using my own custom code (the sample by the link above fails with ReferenceError: require is not defined)
I'm guessing that I can open a panel in a Web Extension only by using a bowserAction but that would put the button on the toolbar while I need it in the page itself
According to documentation I can have only one Panel instance open for the whole browser and it would automatically close upon interacting with any other browser element
Lastly I thought about just loading html from a resource file packed into the extension and feeding it into the page using innerHTML but I couldn't find any API to load text from a resource
Just using DOM API doesn't work for me since it would take forever to code creation of all the elements
I can't believe I didn't notice it for so long, but I finally got it all working as I need. While doing that I even came up with an alternative approach, so here goes.
But first here's the main reason why I dismissed all other possible approaches besides using iframe:
I needed the UI elements added by extension to use their own UI styles and wanted to take advantage of modern frameworks (e.g. jQuery and Bootstrap) and I didn't want to run into problems of conflicting CSS and JavsScript later.
And I actually noticed early on that CSS in the page that I'm embedding into do override Bootstrap styles.
Preferably I also didn't want to affect century old markup of the page that I'm embedding into.
Option A - IFRAME with external source file
In the end it turned out that the only thing I was missing is the web_accessible_resources setting in the manifest.json. Once I added the html file used as source for the iframe into that list, it all just started working.
// manifest.json:
{
"manifest_version": 2,
...
"web_accessible_resources": [
"data/my.html"
],
"content_scripts": [
{
"matches": ["*://*"],
"js": ["js/my.js"]
}
]
}
// js/my.js
var addonFrame = document.createElement ("IFRAME");
addonFrame.style = "position: absolute; bottom: 0; right: 0; width: 150px; height: 38px;";
addonFrame.frameBorder = "0";
addonFrame.src = chrome.extension.getURL ("data/my.html");
document.body.appendChild (addonFrame);
Option B - IFRAME with inline HTML in JS
Before I finally got the first approach working, my experimentation led me to another working approach - inserting HTML into the iframe directly in the content script.
// js/my.js
var addonFrame = document.createElement ("IFRAME");
addonFrame.style = "position: absolute; bottom: 0; right: 0; width: 150px; height: 38px;";
addonFrame.frameBorder = "0";
var addonHtml = "<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta charset='UTF-8'>\n\
<title>Title of the document</title>\n\
</head>\n\
<body>\n\
...\n\
</body>\n\
</html>";
addonFrame.src = 'data:text/html;charset=utf-8,' + encodeURI (addonHtml);
document.body.appendChild (addonFrame);
Even though I ended up using option A in the end, let me outline some pros and cons:
Option A is obviously more canon: view (html) is clearly separated from behavior (js) and all files have content appropriate for their type (except for small exception of building iframe element in JS).
So it should be easier to support going forward.
Option A doesn't allow to use inline scripts in the frame (https://developer.chrome.com/extensions/contentSecurityPolicy). This makes prototyping harder but ultimately should be a plus.
For some reason that is still unclear to me, I cannot use # in the inserted html in option B.
Option B makes doing ajax calls from the add-on frame to the original server easier since the frame source is considered to be from the same domain as the original web page.
In option A, I had to use Window.postMessage in the frame in order to ask my content script inserted into the original page to make an ajax request and give me back the response (the second part was especially hard since there's nothing like jQuery or Prototype available there).

$modal causes page to freeze in IE11

I use the following code snippet to show a simple modal:
$modal({
title: 'My Title',
template: 'path/to/my/simple.modal.html',
show: true,
scope: $scope
});
After closing the modal some parts of my webpage do not react to any events. In all other browsers this is working fine.
It's also really strange that I am not able to inspect some of the elements after closing the modal, all elements are shown as one single element (when using the Inspector-Tools in IE). After found one inspectable item, all the other items are getting inspectable as well. After inspecting for some moments, there is no freezed part again ... it's a really strange behaviour.
Does anybody else have this behaviour ?
I am using Angular 1.5 and Angular-Strap 2.3.7.
Thanks in advance !
Sad, that there were no further hints on this.
I looked in the angular-strap bug-list for a solution and found one :
Just call $destroy(); after hiding the modal did the trick for me.
Best !
I Know this question is answered. but this is for share some info on that same issue.
Recently I also came across with that issue. In my case the reason was a CSS attribute Display:block. So after I turn the value from block to none my freezing error went off and it worked like a charm. So first right after you get that error check in Inspection whether the resulting div where the modal is loaded has a style = "Display:block" in it. If so remove it by a script or etc.
Hope this will help to improve this question.

AngularJS enter animation not playing on first run

I'm having trouble running enter animation first time the page is loaded. I think this is an old problem having to do with this issue.
You can see my problem here.
The strange thing is that when I put the templates in seperate files (and not as text/ng-template) the animation works flawlessly as you can see here.
Since my application will work on file URI scheme I have to use text/ng-template.
Any workarounds? I couldn't find one that fits.
I was able to fix the issue with the dirty hack down this page.
Added ng-if to my ng-view's container
<div ng-if="true" ng-view></div>
along with:
$rootElement.data("$$ngAnimateState").running = false;
in my first controller.
And here is the working demo.
Thank you.

Can I place ui-view on the body tag?

I'm working on an app whose header's styling and UI options will change depending upon the state a user is currently in. For example, if a user clicks the Upload, Edit Profile, Create Playlist or Create Gallery buttons in the main menu, this will cause the following changes to the header:
the header's background to change color
the site logo will have CSS3 animation applied to it to make it slide into a new position
a specific message (depending on what state the user is in) in a word bubble will appear next to the logo
a Cancel button will manifest on the right edge of the header
This means there will be no static element on my site so logic tells me that I should place ui-view in my body tag thus making it look like this:
<body ng-app="app" ui-view>
I have never seen that used before anywhere so I've my doubts. Any ideas?
I'm not sure if this will or will not work technically, but I believe you should avoid it because:
It would require all your templates to include an outermost <body> tag which makes them less reusable
It's generally an unusual thing to do, and that comes with a cost, and I see no particular benefit to this, so IMHO the cost/benefit analysis says stick with what is conventional: use <div>s.
I suspect this may in fact work, but typically the tag with ng-app stays in place for the entire lifecycle of the app. There's a chance you may hit some weird errors if you swap out the tag containing ng-app. Thus many people put ng-app on the very first <html> tag and call it done.
But it's your app and the effort to try both approaches is very low, so just try them out and see (and let us know what you learn). I don't think you need to wait for stackoverflow answer from authority to test 2 slightly different HTML structures with your app.
No, please do not do that!
Having ui-view inside of the body tag may render many JS plugins/libraries unusable, especially in case if they dynamically add some HTML tags to document.body. In such cases, navigation to another view will reinitialize document.body and thus disregard previously added HTML tags.
E.g. this is the case with Firebase and Angular.js (AngularFire). I hope everybody who has come across the error
Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
will get to see this post. Just make sure you haven't added ui-view attribute to your body tag.

Resources