How to disable sound on flashplayer in my custom application? - qt

I use Qt QWebView component which uses flash-player for video playback. How to disable sound on flashplayer executed inside of my QWebView?
One approach that I consider is to execute some javascript code for disabling sound on player, but when to execute it? For example next code disable sound if run it on 1 second after call "load":
page.mainFrame().evaluateJavaScript("""
var mute_all_tags=function(tag){
var elems = document.getElementsByTagName(tag);
for(var i = 0; i < elems.length; i++){
elems[i].muted=true;
//alert(elems[i]);
}
}
mute_all_tags("video");
mute_all_tags("audio");
""")
Earlier calls don't stop sound. Calls on QWebView.loadFinished stops sound but for that moment some sound already issued , how can i stop sound immediately?

It sounds like you are loading external pages (i.e. 3rd-party sites) with HTML5 video or Flash video into your QWebView. Also, keeping the videos muted right from the start with absolutely no audio seems like the critical feature you are seeking.
Solution 1
Your page.mainFrame().evaluateJavaScript("...") seems to be the easiest solution, but there will be a lag before this script is executed.
Solution 2
An alternative is to scrape the target website, then using regex or something similar change all the <video> tags to add the mute property e.g. <video controls muted>. Do something analogous for any <embed> tags too. Then, load this modified HTML into the web view with the setHtml() method, also setting the base url, and possibly the referer header. Then the HTML will render with your videos muted from the start.
Solution 3
Another idea might be to intercept media URLs with Qt itself (e.g. .mp4, .mov), and initially hold them in a paused queue, call your page.mainFrame().evaluateJavaScript("...") to programmatically mute the <video> and <audio> tags, then allow the queue to proceed when the evaluateJavaScript() call returns. The media, if auto-playing, should start muted.

Please fix your code to following :
page.mainFrame().evaluateJavaScript("var mute_all_tags=function(tag){var elems = document.getElementsByTagName(tag);for(var i = 0; i < elems.length; i++){elems[i].muted=true;}}mute_all_tags('video');mute_all_tags('audio');")
The String in your code is not valid :
You are adding double quotes to string without Concatenation .
You are using double quotes inside double quotes which is a mess.

Related

Print Friendly Page

So I would like to be able to have a print button for entries in our database so users can print an entry via a print friendly "form".
My thought was to create a separate page, add labels and have those labels pull the relevant information.
I know I can add the open widget information via this code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.TestPrint);
But I'm running into a few problems:
I can't get the page to open in a new window. Is this possible?
window.open(app.pages.TestPrint);
Just gives me a blank page. Does the browser lose the widget source once the new window opens?
I can't get the print option (either onClick or onDataLoad) to print JUST the image (or widget). I run
window.print();
And it includes headers + scroll bars. Do I need to be running a client side script instead?
Any help would be appreciated. Thank you!
To get exactly what you'd want you'd have to do a lot of work.
Here is my suggested, simpler answer:
Don't open up a new tab. If you use showPage like you mention, and provide a "back" button on the page to go back to where you were, you'll get pretty much everything you need. If you don't want the back to show up when you print, then you can setVisibility(false) on the button before you print, then print, then setVisibility(true).
I'll give a quick summary of how you could do this with a new tab, but it's pretty involved so I can't go into details without trying it myself. The basic idea, is you want to open the page with a full URL, just like a user was navigating to it.
You can use #TestPrint to indicate which page you want to load. You also need the URL of your application, which as far as I can remember is only available in a server-side script using the Apps Script method: ScriptApp.getService().getUrl(). On top of this, you'll probably need to pass in the key so that your page knows what data to load.
So given this, you need to assemble a url by calling a server script, then appending the key property to it. In the end you want a url something like:
https://www.script.google.com/yourappaddress#TestPage?key=keyOfYourModel.
Then on TestPage you need to read the key, and load data for that key. (You can read the key using google.script.url).
Alternatively, I think there are some tricks you can play by opening a blank window and then writing directly to its DOM, but I've never tried that, and since Apps Script runs inside an iframe I'm not sure if it's possible. If I get a chance I'll play with it and update this answer, but for your own reference you could look here: create html page and print to new tab in javascript
I'm imagining something like that, except that your page an write it's html content. Something like:
var winPrint = window.open('', '_blank', 'left=0,top=0,width=800,height=600,toolbar=0,scrollbars=0,status=0');
winPrint.document.write(app.pages.TestPage.getElement().innerHTML);
winPrint.document.close();
winPrint.focus();
winPrint.print();
winPrint.close();
Hope one of those three options helps :)
So here is what I ended up doing. It isn't elegant, but it works.
I added a Print Button to a Page Fragment that pops up when a user edits a database entry.
Database Edit Button code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showDialog(app.pageFragments.FragmentName);
That Print Button goes to a different (full) Page and closes the Fragment.
Print Button Code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.ModelName_Print);
app.closeDialog();
I made sure to make the new Print Page was small enough so that Chrome fits it properly into a 8.5 x 11" page (728x975).
I then created a Panel that fills the page and populated the page with Labels
#datasource.item.FieldName
I then put the following into the onDataLoad for the Panel
window.print();
So now when the user presses the Print Button in the Fragment they are taken to this new page and after the data loads they automatically get a print dialog.
The only downside is that after printing the user has to use a back button I added to return to the database page.
1.
As far as I know, you cannot combine window.open with app.pages.*, because
window.open would require url parameter at least, while app.pages.* is essentially an internal routing mechanism provided by App Maker, and it returns page object back, suitable for for switching between pages, or opening dialogs.
2.
You would probably need to style your page first, so like it includes things you would like to have printed out. To do so please use #media print
ex: We have a button on the page and would like to hide it from print page
#media print {
.app-NewPage-Button1 {
display : none;
}
}
Hope it helps.
1. Here is how it is done, in a pop up window, without messing up the current page (client script):
function print(widget, title){
var content=widget.getElement().innerHTML;
var win = window.open('', 'printWindow', 'height=600,width=800');
win.document.write('<head><title>'+title+'/title></head>');
win.document.write('<body>'+content+'</body>');
win.document.close();
win.focus();
win.print();
win.close();
}
and the onclick handler for the button is:
print(widget.root.descendants.PageFragment1, 'test');
In this example, PageFragment1 is a page fragment on the current page, hidden by adding a style with namehidden with definition .hidden{display:none;} (this is different than visible which in App Maker seems to remove the item from the DOM). Works perfectly...
2. You cannot open pages from the app in another tab. In principle something like this would do it:
var w=window.parent.parent;
w.open(w.location.protocol+'//'+w.location.host+w.location.pathname+'#PrintPage', '_blank');
But since the app is running in frame nested two deep from the launching page, and with a different origin, you will not be able to access the url that you need (the above code results in a cross origin frame access error). So you would have to hard code the URL, which changes at deployment, so it gets ugly very fast. Not that you want to anyway, the load time of an app should discourage you from wanting to do that anyway.

How can I inject JavaScript file into a WebEngineView page?

I'm adding a script tag to a web page once it's fully loaded in a WebEngineView, but it's silently failing somehow.
I inject the script by invoking webview.runJavaScript with this code:
var s = document.createElement('script');
s.src = "qrc:/jquery-2.1.4.min.js";
document.body.appendChild(s);
That's perfectly standard and to a certain extent it works as expected, i.e., if I view the html source of the page, the script tag has indeed been appended to the body.
The problem is that the script isn't being downloaded, or isn't being evaluated, or something. All I know is in the above example the jQuery functions aren't available. If I load a small JavaScript test file with one global variable, that variable's not available either. Changing the url to http instead of qrc and pointing it to a web server makes no difference.
Injecting an img tag works fine; the image is loaded and displayed.
But JavaScript is broken somehow. Does anyone know how to fix this?
The problem had to do with the asynchronous nature of QML and JavaScript.
I was inserting a script tag to inject jQuery, and then I was calling a function to de-conflict my inserted version of jQuery from whatever version of jQuery might already be in the original page.
But I believe the webview had not finished parsing the inserted jQuery library before my de-conflicting function was called, so it failed. (I'm not very experienced with browser programming or I might have suspected this from the beginning.)
The solution was to insert a script tag with a small bit of JavaScript that inserts jQuery and then sets a timeout to wait 200ms before calling the de-conflict function. Like so:
function insertAuhJQuery(){
var s = document.createElement("script");
s.src = "qrc:/jquery-2.1.4.min.js";
document.body.appendChild(s);
window.setTimeout(deConflictJQuery, 200);
}
function deConflictJQuery(){
auh = {};
auh.$ = jQuery.noConflict(true);
}
insertAuhJQuery()
That works reliably and is acceptable for my purpose.

Can not display base64 encoded images in an HTML fragment in WinJS app

I'm writing a WinJS app that takes an HTML fragment the user has copied to the clipboard, replaces their
Later, when I go to display the .html, I create an iFrame element (using jQuery $(''), and attempt to source the .html into it, and get the following error
0x800c001c - JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement. For more information, see http://go.microsoft.com/fwlink/?LinkID=247104.
I don't get the exception if I don't base64 encoded the images, i.e. leave them intact and can display iframes on the page with the page showing images.
If I take the html after subbing the urls for base64 and run it through toStaticHTML, it removes the src= attribute completely from the tags.
I know the .html with the encoded pngs is right b/c I can open it in Chrome and it displays fine.
My question is I'm trying to figure out why it strips the src= attributes from the tags and how to fix it, for instance, creating the iframe without using jquery and some MS voodoo, or a different technique to sanitize the HTML?
So, a solution I discovered (not 100% convinced it the best and am still looking for something a little less M$ specific) is the MS Webview
http://msdn.microsoft.com/en-us/library/windows/apps/bg182879.aspx#WebView
I use some code like below (where content is the html string with base64 encoded images)
var loadHtmlSuccess = function (content) {
var webview = document.createElement("x-ms-webview");
webview.navigateToString(content);
assetItem.append(webview);
}
I believe you want to use execUnsafeLocalFunction. For example:
var target = document.getElementById('targetDIV');
MSApp.execUnsafeLocalFunction(function () {
target.innerHTML = content}
);

Javascript-Caching Video Player

I've got the following Javascript for creating the HTML of video player. I use Javascript because this is the only way I can tell the player which video to play.
function createPlayer(videoSource){
document.writeln("<div id=\"player\">");
document.writeln("<object width=\"489\" height=\"414\" >");
document.writeln("<param name=\"player\" value=\"bin-debug/FlexPlayer.swf\">");
//etc
The problem is FlexPlayer.swf is loading every time and I need to cache this SWF file. Maybe I should use Javascript constructor but don't know how in this case. Any code help will be greatly appreciated.
If you're video player is in flex (and I'm guessing that it is with the flex tag and the bin-debug folder) - you should just call into the flex app in order to set the video.
You can allow flex and javascript to communicate with each other, without having to embed different versions of it in the HTML! It's awesome, check it out...
In your flex app, after it is initialized you can add something like this :
ExternalInterface.addCallback( 'playVideoFromJS' , playVideo );
What the above does is expose a function named "playVideoFromJS" that can be called in your javascript that will execute the 'playVideo' funciton in the flex app! Neat!
Then add a function like so somewhere in your flex app:
public function playVideo ( videoToPlay : String ) : void {
...play video code here
}
Then in javascript, you can actually call your flex function playVideo!
myFlexAppName.playVideoFromJS( 'myvideoofile.flv' );
More information on ExternalInterface here :
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6#addCallback()

ASP.NET How can I write a message on the screen without the end user removing it?

I have written a ASP.NET program for a customer, I want to add a message similar to "Preview version, ABD Consulting" on the master.master page, I had thought to use Response.write but it messes up the look of the page as it seems to move page elemets. If I use a label the customer can remove it from the Master.master file, any suggestions? The customer is in a different country so I want to ensure I'm paid.
Many thanks
Serve it on your own server. If it's a preview, they shouldn't have access to the code anyway.
There is nothing you can do unless you host it or control the web server it runs on. Nothing you do in code will matter if they are smart enough. They can write their on HTTP Handlers and replace anything they want.
If you programmatically write out the label during the OnPrerender or Render of the page then the client will not be able to remove it. If you then randomize the ID given to the element, they will find it incredibly hard to apply any javascript functions or CSS styles to it, especially if you directly add the styles to it.
Something like this (pseudo code):
HtmlGenericControl label = new HtmlGenericControl("div");
label.ID = Guid.NewGuid().ToString();
label.InnerText = "My copyright or ownership text";
label.Style.Add(HtmlTextWriterStyle.Height, "50px");
label.Style.Add(HtmlTextWriterStyle.Width, "100px");
if you then absolutely position it, it should always show up. Note that it isn't totally untouchable and fool proof, but you want to just make it hard enough that the client doesn't try to remove it.
Obfuscate it in a dll and use the Current Context to write a pretty div like the one that StackOverflow.com uses on top.
I'm with George and Rick - don't let them have the source and serve it up from a server you control. In addition, I'd created a background image that says "Demo". This will remind that they need to pay up.

Resources