I'm loading a local HTML file into IE and expecting to receive a DocumentComplete event. It's never fired. I also tried NavigateComplete and ProgressChange but they aren't fired as well. Here is the code:
public void OnDocumentCompleted(object pdisp, ref object url)
{
Console.WriteLine("DocumentCompleted fired on url {0}!", url);
}
var IE = new InternetExplorer();
object Empty = 0;
IE.NavigateComplete2 += new DWebBrowserEvents2_NavigateComplete2EventHandler(e.OnNavigateComplete2);
IE.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(e.OnDocumentCompleted);
IE.ProgressChange += new DWebBrowserEvents2_ProgressChangeEventHandler(e.OnProgressChange);
var uri = new Uri("file://c:/iframeExample.html");
IE.Navigate(uri.AbsolutePath);
IE.Quit();
If I'm browsing to a page on the web, I do receive all events. So, why they are not fired for a local page?
Related
I have a web browser control in my application which contains the following link:
<html>
<body>
test
</body>
</html>
Each time I click on this link, it gets opened in a new window of IE instead of a new Tab. I tried loading this html directly in IE - then it correctly gets opened in new tabs.
I have also configured the IE setting to open links in new tabs instead of new windows.
Can anyone help me out to load the links from the web browser control in a new tab?
Thank you!
It would have been helpful if you had specified whether you were using Winforms or WPF for your web browser control or even what language you were using (C#, VB,F#, etc) but assuming you are using winforms and C# this solution would work.
You simply cancel the new window event and handle the navigation and tab stuff yourself.
Here is a fully working example.
using System.ComponentModel;
using System.Windows.Forms;
namespace stackoverflow2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.webBrowser1.NewWindow += WebBrowser1_NewWindow;
this.webBrowser1.Navigated += Wb_Navigated;
this.webBrowser1.DocumentText=
"<html>"+
"<head><title>Title</title></head>"+
"<body>"+
"<a href = 'http://www.google.com' target = 'abc' > test </a>"+
"</body>"+
"</html>";
}
private void WebBrowser1_NewWindow(object sender, CancelEventArgs e)
{
e.Cancel = true; //stop normal new window activity
//get the url you were trying to navigate to
var url= webBrowser1.Document.ActiveElement.GetAttribute("href");
//set up the tabs
TabPage tp = new TabPage();
var wb = new WebBrowser();
wb.Navigated += Wb_Navigated;
wb.Size = this.webBrowser1.Size;
tp.Controls.Add(wb);
wb.Navigate(url);
this.tabControl1.Controls.Add(tp);
tabControl1.SelectedTab = tp;
}
private void Wb_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
tabControl1.SelectedTab.Text = (sender as WebBrowser).DocumentTitle;
}
}
}
I have game server, FMS 4.5 on Windows, already working prefect, and client apps were created in old CS4, and all is perfect.
Now I want to create a mobile app in AS3, and have a problem with remote shared object, which is working perfect in old flash program.
When users are logged into app, I'm receiving an update with onSync method. But whenever remote shared object is updated, I'm not receiving updates.
for example, on client, where I have main_nc as netConnection object:
var ncu_so:SharedObject = SharedObject.getRemote("Zusers", main_nc.uri, false);
ncu_so.addEventListener(SyncEvent.SYNC, syncNCU);
ncu_so.client=this;
ncu_so.connect(main_nc);
private function syncNCU(e:SyncEvent):void {
........
//here I receive new info....
}
and sample on server...
application.onAppStart = function(){
this.Zusers_so = SharedObject.get( "Zusers", false );
...........
}
function sampleUserEnter(client) {
var t=new Object();
t.username=client.username;
application.Zusers_so.setProperty(client.id,t);
//this one call is synced with app
}
function sampleChangeName(client,newName) {
var t=application.Zusers_so.getProperty(client.id);
t.username=newName;
application.Zusers_so.setProperty(client.id,t);
//this IS NOT syncing with app
}
As I said, this code is working with old flash software, but wont update when using AS3. Any idea?
I found an easy solution. Not sure why it works but it works....
var ncu_so:SharedObject = SharedObject.getRemote("Zusers", main_nc.uri, false);
ncu_so.addEventListener(SyncEvent.SYNC, syncNCU);
//I add the listener for checking status
ncu_so.addEventListener(NetStatusEvent.NET_STATUS, statusNCU);
ncu_so.client=this;
ncu_so.connect(main_nc);
private function syncNCU(e:SyncEvent):void {
........
//here I receive new info....
}
//In function for NetStatus event, I just set a simple property
//which I do not use in the app..
//and sunchronization start working as usual after initial sync
private function statusNCU(ev:NetStatusEvent):void {
if (ev.info.code == "NetConnection.Connect.Success") {
ncu_so.setProperty("anyPropertyName",new Date());
}
}
I could reduce my problem on a small code snippet. The code creates dynamically an SC player iFrame and displays the ready status. If there is already an iFrame, it removes the old one and creates a new one (runable example on JSFIDDLE):
var player;
var playerId;
var iframe;
var printReady=
function(data)
{
document.getElementById("status").innerHTML = "Ready";
};
function createSoundCloudIframe()
{
document.getElementById("status").innerHTML = "Player not ready";
var contentDiv = document.getElementById("content");
// Remove last Iframe
if(iframe != null){
player.unbind(SC.Widget.Events.READY);
contentDiv.removeChild(iframe);
}
// Create a new Iframe
iframe = document.createElement("IFRAME");
iframe.id = playerId + "ScId";
iframe.src = "http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F41867062&show_artwork=true";
// Append Iframe
contentDiv.appendChild(iframe);
// Show ready status
player = SC.Widget(playerId + "ScId");
player.bind(SC.Widget.Events.READY, printReady);
playerId ++;
};
The code runs fine when it is executed the first time. But when you try it a second time a nullpointer exception (developer console) will be thrown in this method of api.js:
// Uncaught TypeError: Cannot read property 'parentWindow' of null
function s(a) {
return a.contentWindow || a.contentDocument.parentWindow
}
The method which causes the exeption is SC.Widget(iFrameId);
This problem is in my case not solvable with SC.Widget(iFrameId).load(url, options); function and a hiding of the iFrame:
I wrote a google-web-toolkit wrapper for the SC widget api and use this wrapper with other gwt mediaplayer wrappers in a much bigger project. In this project the exception is thrown repeatedly with a delay of milliseconds which slows down everything. The codesnippet above is only a pure javascript reduction of the problem.
I really need a workaround which removes and clean up all dead references in the api.js when the iFrame is removed! I'm looking for such a workaround for month.
I have an HTML5 website built using jQuery Mobile.
On my index.htm page I have an ahref. When I click on that link I run a function which does a tx.executeSql and the callback method is run which then navigates to the new page.
The works fine the first time.
If I navigate to more pages and then come back to the index.htm page, the functions are run when the link is clicked, however the callback on the tx.executeSql isn't ever run.
Any ideas would be greatly appreciated. I have used all different mechanisms for calling the functions from javascript to jquery, but it makes no difference.
To be clear - the first function called is setFeaturedRecruiter() - you can see the code below. The second time I come back here the "renderResults" callback function isn't run.
// when we click on the actual featured recruiter link we copy from this table to the featured recruiter table to overwrite its contents
function setFeaturedRecruiter() {
alert('setFeaturedRecruiter()');
retrieveActualFeaturedRecruiter();
return true;
}
function retrieveActualFeaturedRecruiter() {
alert('retrieveActualFeaturedRecruiter()');
db.transaction(function (tx) {
alert('select * from featuredRecruiterActual...');
tx.executeSql('SELECT * FROM featuredRecruiterActual', [], renderResults, pnetOnError);
});
}
pnetOnError = function (tx, e) {
alert('Something unexpected happened: ' + e.message);
}
function renderResults(tx, rs) {
alert('renderResults()');
var idNo;
var name;
var logo;
var totalAds;
for (var i = 0; i < rs.rows.length; i++) {
r = rs.rows.item(i);
idNo = r.idNo * 1;
name = r.name;
logo = r.logo;
totalAds = r.totalAds;
}
writeToFeaturedRecruiter(idNo, name, logo, totalAds);
}
I've worked around this problem by disabling ajax when navigating between pages. This was done by adding to the ahref tag: data-ajax="false". This caused the page to load correctly and overcomes the problem.
I'm looking for a way to play flash animated content once ( even as the user navigates to different HTML pages with similar flash content) and expire after a set amount of time or after the browser is closed.
I'm aware I could use a shared object for this but can't seem to find info about how to clear them at browser session end.
I am open to using javascript or PHP to assist .
your help is appreciated -
thanks -MW
Instead of using a SharedObject, you could create two simple server-side services: one that maintains the session, and one that exposes the session through a generated XML file that your flash application could use.
The first service would set some session variables and should be called whenever the video is played. It could look like this:
<?php
// start-video.php
session_start();
$_SESSION['hasWatchedVideo'] = true;
$_SESSION['watchedVideoAt'] = time();
?>
The second service is the one that generates the XML response based on the session. It might look like this:
<?php
// flash-config.php
session_start();
// set expiration to 5 min
define(VIDEO_TIMEOUT, 300);
$playVideo = "true";
if($_SESSION['hasWatchedVideo']
&& (time() - $_SESSION['watchedVideoAt']) < VIDEO_TIMEOUT) {
$playVideo = "false";
}
header("Content-Type: text/xml");
echo "<config><playVideo>{$playVideo}</playVideo></config>";
?>
Then from your Flash application, you could do this:
/**
* Called whenever the app is loaded.
*/
protected function init():void {
var u:URLLoader = new URLLoader();
u.addEventListener(Event.COMPLETE, onComplete);
u.load(new URLRequest("http://example.com/flash-config.php"));
}
/**
* Determines whether or not the video should play based on the
* config service response.
*/
protected function onComplete(e:Event):void {
var x:XML = new XML(e.target.data);
if(x.playVideo == 'true') {
playVideo();
}
}
/**
* Should be called either when the video starts playing. I just tied
* it to a user click here.
*/
protected function playVideo():void {
// call the service to update the session
var u:URLLoader = new URLLoader();
u.load(new URLRequest("http://example.com/start-video.php"));
// ... play video code ...
}
I think this approach gives you a bit more flexibility than using a SharedObject. Hope that helps.
UPDATE:
You could use a session cookie in the browser as well. Basically set the expiry date to '0' and the cookie will expire when the user closes the browser. (Note: when I tested this in Firefox, closing the tab was not enough to kill the cookie. The entire browser had to be closed.)
You can use ExternalInterface, or a utility library like this. Using the library, you could have code like this in your flash application:
function playVideo():void {
if(!CookieUtil.getCookie('playvideo')) {
CookieUtil.setCookie('playvideo', 'true', 0);
// ... play video code ...
}
}
Whenever the user closes the browser, the cookie will be cleared. Next time they visit your site, the video will play again. Not sure if this is more inline with what you're look for, but hope it helps.
I modified your code a tad so it will be killed on sesion end ...
the PHP ...
<?php
// flash_php_session_cookie.php
$cookie= "false";
if (isset($_COOKIE["cookie"]))
$cookie= "true";
else
setcookie("cookie", "true", 0);
echo "<config><cookie>{$cookie}</cookie></config>";
?>
the FLASH ...
// the folowing functions handle call coresponding PHP files to handle cookies ...
// re-configure these to the location of the swf ...
var flashConfigURL:String ="flash_php_session_cookie.php";
//Called whenever the app is loaded ...
function initCookieFunc():void {
var u:URLLoader = new URLLoader();
u.addEventListener(Event.COMPLETE, onComplete);
u.load(new URLRequest(flashConfigURL));
}
// Determines whether or not the cookie exists / (assumes theres a text field named T on the stage) ...
function onComplete(e:Event):void {
var x:XML = new XML(e.target.data);
if (x.cookie == 'false') {
T.appendText("cookie doesn't exist yet");
} else {
// cookie exists ...
T.appendText("cookie exists");
}
}
initCookieFunc();
I am going to keep a loose version of the "TIMEOUT"
version as well.
It's great to have an answer to this
Thanks again RJ for the invaluable code
-MW
You'll just have to expire the SharedObject yourself. It's not complicated.
This way your .swf will be completely self contained, not relying on anything external which IMO is a good thing.
package {
import flash.display.Sprite;
import flash.net.SharedObject;
import flash.net.SharedObjectFlushStatus;
public class SharedObjectExample extends Sprite {
private var _so:SharedObject;
private var _now:Date;
private var _last_played:Number;
private static const EXPIRE_TIME:Number = 1000 * 60 * 60 * 24; // 24hrs in msec
public function SharedObjectExample() {
// create a new date for the current time to compare against
_now = new Date;
// create a new shared object
_so = SharedObject.getLocal("application-name", "/");
// try read from the shared object
if (_so.data.last_played) _last_played = _now;
// if no value is set we play the video and set the current time
if (!_last_played) {
// play video here
_last_played = _now.time;
// check if the "cookie" has expired and it's time to play again
} else if ( _now.time - _last_played > EXPIRE_TIME) {
// play video here
_last_played = _now.time;
} else {
// do nothing
}
// and finally, save
saveValue();
}
private function saveValue(event:MouseEvent):void {
// i've removed the code that asks the user for permission if the request for storage is denied
_so.data.last_played = _last_played;
var flushStatus:String = null;
try {
flushStatus = _so.flush(1000);
} catch (error:Error) {
trace("Could not write SharedObject to disk");
}
}
}
}