Pass GeckoFX DOM elements to JavaScript navigation calls - c#

using GeckoFX web browser, is it possible to pass a GeckoElement through JavaScript like this,
WebBrowser.Navigate("javascript:void("+ele.DomObject+".onclick())");
I'm selecting the DOM element through JavaScript (this works fine) atm, but i have the element in c#.

Unfortunately elements can't be passed to javascript like that.
However, the WebBrowser.Navigate call is unnecessary and causes an unneeded loss of page variables.
For the sake of completeness I've posted a snippet - long winded for this occasion ;) - that injects javascript and then calls it from an automated button click via a button.click() handler without the need to navigate the browser to run it all.
DOM.GeckoScriptElement script = Document.CreateElement("script").AsScriptElement();
script.Type = "text/javascript";
script.Text = "function doAlert(){ alert('My alert - fired by automating a button click on the [Automated Button]'); }";
Document.Body.AppendChild(script);
script = Document.CreateElement("script").AsScriptElement();
script.Type = "text/javascript";
script.Text = "function callDoAlert(id){ var el = document.getElementById(id); el.click(); }";
Document.Body.AppendChild(script);
DOM.GeckoInputElement button = Document.CreateElement("input").AsInputElement();
button.Type = "button";
button.Id = "myButton";
button.Value = "Automated Button";
button.SetAttribute("onclick", "javascript:doAlert();");
Document.Body.AppendChild(button);
DOM.GeckoInputElement button2 = Document.CreateElement("input").AsInputElement();
button2.Type = "button";
button2.Id = "myOtherButton";
button2.Value = "Press Me";
button2.SetAttribute("onclick", "javascript:document.getElementById('myButton').click();");
Document.Body.AppendChild(button2);
//uncomment to fully automate without the <webbrowser>.Navigate("javascript:.."); hack
//button2.click();
I'm not sure this snippet will help you, directly, as it's mainly focused on using the GFXe build of the control but, I'm sure it will point you in a better direction than the
WebBrowser.Navigate("javascript:hack.goesHere()"); trick.

You can do this with the following:
WebBrowser.Navigate("javascript:void(document.getElementById('"+button.Id+"').click())");

Related

Dynamic ModalPopupExtender not firing the OK Click event

ASP.NET 4.7.2 Web Forms c# VS 2019
I am trying to use a modalpopupextender to prompt for new data for foreign key fields. Like the form itself, the MPE is built on the fly in code -- in this case the click handler for the hidden button that the Javascript fires off to build and show the MPE.
I read every single article on SO and the ASP forums and tried everything I saw there. No joy. I get the popup perfectly. Hitting OK closes the popup, but never fires the OK Event.
Here is the code:
//Building the form, we do this in OnInit:
// AJAX Update Panel
UpdatePanel PUP = new UpdatePanel()
{
ID = "PUP",
};
PlaceHolder.Controls.Add(PUP);
// HiddenField containing the field name to permit
// creating the correct modalpopup.
HiddenField HFPopupField = new HiddenField()
{
ID = "HF_POPUP"
};
PUP.ContentTemplateContainer.Controls.Add(HFPopupField);
// Create Hidden button to track the popup
Button BPopup = new Button()
{
ID = "BPOPUP",
UseSubmitBehavior = false
};
BPopup.Click += BPopup_Click;
BPopup.Attributes.Add("style", "display: none;");
PUP.ContentTemplateContainer.Controls.Add(BPopup);
// And create the background panel for the popup.
Panel PnlPopup = new Panel()
{
ID = "PNLPOPUP",
CssClass = "MpeBackground"
};
PnlPopup.Attributes.Add("style", "display: none;");
PUP.ContentTemplateContainer.Controls.Add(PnlPopup);
/// Event handler for hidden button.
protected void BPopup_Click(object sender, EventArgs e)
{
[snip -- code to get the dataset that is being filled]
UpdatePanel PUP = Placeholder.FindControlRecursive("PUP");
Table T = new Table()
{
CssClass = "PopupTbl"
};
TableRow TRTitle = new TableRow();
TableCell TCTitle = new TableCell()
{
CssClass = "PopupTitle",
ColumnSpan = 2
};
Label LPopTitle = new Label()
{
Text = [title of the popup]
};
TCTitle.Controls.Add(LPopTitle);
TRTitle.Cells.Add(TCTitle);
DataRow drData = null;
// Add Fields, and also the cancel and Add buttons
foreach (DataColumn DC in dsColumns.Tables[0].Columns)
{
TableRow TRColumn = [create a tablerow with 2 columns, a prompt and the input field]
if (TRColumn != null)
{
T.Rows.Add(TRColumn);
[snip]
}
} // end of foreach(DataColumn DC in dsColumns.Tables[0].Columns)
PnlWindow.Controls.Add(T);
TableRow TRButtons = new TableRow();
TableCell TCButtons = new TableCell()
{
ColumnSpan = 2,
CssClass="PopupButtons"
};
Button MPEBOK = new Button()
{
ID = "MPE" + sFieldName + "_MPEBOK",
Text = "OK",
CausesValidation = false,
UseSubmitBehavior = false
};
MPEBOK.Click += MPEBOK_Clicked;
TCButtons.Controls.Add(MPEBOK);
LiteralControl LCB = new LiteralControl()
{
Text = " "
};
TCButtons.Controls.Add(LCB);
//************************************************************
//*** Postback Trigger ***
//************************************************************
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger()
{
ControlID = MPEBOK.ID,
EventName = "click"
};
PUP.Triggers.Add(trigger);
//************************************************************
//*** Cancel Button ***
//************************************************************
Button MPEBuhBye = new Button()
{
ID = "MPE" + sFieldName + "_BUHBYE",
Text = "Cancel",
UseSubmitBehavior = false
};
TCButtons.Controls.Add(MPEBuhBye);
TRButtons.Cells.Add(TCButtons);
T.Rows.Add(TRButtons);
PnlPopup.Controls.Add(PnlWindow);
AjaxControlToolkit.ModalPopupExtender MPE = new AjaxControlToolkit.ModalPopupExtender()
{
ID = "MPE" + sFieldName,
PopupControlID = "PNLPOPUP",
TargetControlID = "BPOPUP",
BackgroundCssClass = "MpeBackground"
};
// Add the MPE to the UpdatePanel.
PUP.ContentTemplateContainer.Controls.Add(MPE);
// Show the modal popup extender.
MPE.Show();
}
protected void MPEBOK_Clicked(object sender, EventArgs e)
{
[snip - this never fires]
}
I cannot find out what is happening here. Can anyone see something hinky?
Thanks
John.
You can't add a server side button or inject a server side button into the page DOM.
When you drag a asp.net button onto the form, BOTH the "mypage.cs" and mypage.desinger.cs ARE updated. The wire up of the button occurs at design time, and you would have to modify mypage.desinger.cs ALSO and ADD a button event stub.
So you can't do this.
A compromise would be to also add some js and have that HTML button execute a .click() method of a hidden asp.net button you drop into that page (that would give you the post back, and the running behind of a separate button event code stub.
This event resolution occurs at compile time - not at page render time. You have to drop that button onto the page.
I suppose you could adopt a standard that you always place right below that "div" on the page the button (hidden with style=none. And then as noted, have your injected code along with some js execute a click on the hidden button. Or just have the js button code execute a __doPostback("some value") and pick this up in the page on-load event, and then call the routine (function) from on-page load event.
I think better would be to use a jQuery.UI dialog, as that dialog CAN say load + use another different web page into a “div” on the existing page. So you layout, make, and create the nice looking popup form as a separate web page. jQuery is able to remove the “form” and additonal tags out of that page load, and then inject it into the existing page. (that code would be rather hard to re-produce). so jQuery.UI is able to pop up that separate page. however, the buttons on that loaded page (into that div) of course can't really run any code behind in the current page. However, the buttons CAN run local js in the current page. Thus the actions of this injected page would be local to each page. But the popup would not be directly calling a code behind stub.
Now, to adopt jQuery.UI, then you also have to of course adopt jQuery. So that is two extra libraries you need. (but, jQuery you likely already have).
However, I suppose the whole point of using the ajax toolkit is to avoid jQuery.ui in the first place. To be fair, before jQuery.ui came along, that tool kit was REALLY impressive, and gave asp.net folks a REAL leg up on the competition. (and it tends to be MUCH less wiring up then say using jQuery.UI
So the AjaxToolkit in its heyday was impressive. Now, it of course showing its age, but I still use the kit, and this is especially the case for the AjaxFileUploader. And yes I do use the popups – even to this day. However, I find now that jQuery.UI dialogs are more flexible, and would be better in this case (because you want a on-the fly setup).
Also, having code behind buttons in even the jQuery.UI dialog, or in this case the ajax popup? Well, only the action button can run code behind. The cancel button of course will just dismiss the dialog. However, any button in the dialog that WILL run code behind? Well, that's ok, since you have a page post back, and it actually the page postback that BLOWS out the dialog anyway.

ASP.NET:adding controls Dynamicly afther post back with diffrent data

i got a page where the admin can edit some photos i pull from flickr so all the controls are added Dynamiclly.
i have few controls i add to a panel and then add the panel to Form.Controls.
all the data thay are holding come from flickr.
my problem is that, afther a post back the list change and the controls are loading, BUT the Text Box's keep that same data befor the post back even though i get the data from flickr every time.
what wierd for my that if i do this with less textbox every thing work fine.
the list are about 10+ pictures and this numbers can change in the future.
(sorry for the messy code im pretty new to programming)
here is the code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
RadioButtonList1.AutoPostBack = true;
selectedSetID = getSelectedSetId(RadioButtonList1.SelectedItem.Text);
photoSet = new MyPhotoSet(selectedSetID);
photo = new FlickerImages[photoSet.Count];
for (int j = 0; j < photo.Length; j++)
{
photo[j] = new FlickerImages(photoSet.MediumURLS[j], photoSet.ThumbnailURLS[j], photoSet.Titles[j], photoSet.Descreption[j], photoSet.PhotosID[j]);
panel = photo[j].GetPanelWithEditControls(j);
button = new Button();
button.ID = "sendDataButton" + j;
button.Text = "send data";
button.Click += button_Click;
panel.Controls.Add(button);
Form.Controls.Add(panel);
}
}
else
{
//here is the post back,
every thing load fine.
adding and removing the controls but if the textbox's load in the same place, it hold the same data befor the post back.
RadioButtonList1.AutoPostBack = true;
selectedSetID = getSelectedSetId(RadioButtonList1.SelectedItem.Text);
photoSet = new MyPhotoSet(selectedSetID);
photo = new FlickerImages[photoSet.Count];
for (int i = 0; i < photo.Length; i++)
{
photo[i] = new FlickerImages(photoSet.MediumURLS[i], photoSet.ThumbnailURLS[i], photoSet.Titles[i], photoSet.Descreption[i], photoSet.PhotosID[i]);
panel = photo[i].GetPanelWithEditControls(i);
button = new Button();
button.ID = "sendDataButton" + i;
button.Text = "send data";
button.Click += button_Click;
panel.Controls.Add(button);
Form.Controls.Add(panel);
}
}
}
(sorry for my english)
Instead of putting your control generation in Page_Load, put it in Page_Init.
Since you mentioned that you're pretty new to ASP.NET, I strongly recommend reading up on the Page Lifecycle.
As an ASP.NET developer, it's very important that you understand how and when certain things happen on the server in between the time the server receives a request for an aspx page, and the time the page is output to be rendered by the browser.
The short explanation for why I suggest putting the code in Page_Init is how the runtime deals with dynamically created controls and Viewstate. The Viewstate contains any changes made by the user of your web app. In the page lifecycle, you'll notice that the application of Viewstate values happen before Page_Load, but after Page_Init.
This means that if your code in in Page_Load, then the controls are generated from Viewstate, updated with what the user put in, but then your own code in page_Load is re-generating those controls with the default values. There's nothing that happens after this event that can re-load the user's input.
(Hopefully that makes sense. If not, the page I linked to may explain it better.)
There's another article on here that addresses the subject from a different angle, but still should be very helpful for you.
And there's the ultra-short version here.
And finally, (saving the best for last) one of the most comprehensive articles on the subject that explains things in plain English can be found here.

How can i call java script function(in .cs) in the OnClientClick of the link button?

I write script like this in my .cs file :
StringBuilder script = new StringBuilder();
script.Append("<script type=\"text/javascript\"> function submitform(){");
script.Append(" document.forms['" + ((HtmlGenericControl)frm).Attributes["id"] + "'].submit();} </");
script.Append("script>");
How can i call this function in the OnClientClick of my link button ?
LinkButton hl_process = new LinkButton();
hl_process.OnClientClick = ""
Edit1:
protected Control CreateCommForm()
{
HtmlGenericControl frm = new HtmlGenericControl("form");
frm.Attributes.Add("id", "sal");
frm.Attributes.Add("method", "post");
frm.Attributes.Add("action", "https://------");
/////////////////////////////////////////
HtmlGenericControl hdn_sal_a = new HtmlGenericControl("input");
hdn_sal_a.Attributes.Add("id", "hdn_sal_a");
hdn_sal_a.Attributes.Add("name", "hdn_sal_a");
hdn_sal_a.Attributes.Add("type", "hidden");
hdn_sal_a.Attributes.Add("value", Session["emp_num"].ToString());
/////////////////////////////////////////
HtmlGenericControl hdn_sal_b = new HtmlGenericControl("input");
hdn_sal_b.Attributes.Add("id", "hdn_sal_b");
hdn_sal_b.Attributes.Add("name", "hdn_sal_b");
hdn_sal_b.Attributes.Add("type", "hidden");
hdn_sal_b.Attributes.Add("value", Session["user_name"].ToString());
frm.Controls.Add(hdn_sal_a);
frm.Controls.Add(hdn_sal_b);
column1.Controls.Add(frm);
return frm;
}
separate the concerns The Visual part your application shouldn't be affected if you move your app to java or ruby. that's what separate of concerns is.
write the client script in the client, not in the cs file:
$('#<%= hl_process.ClientID %>').click(function(){
...
$('#formId').submit();
// if the button inside the form:
this.form.submit(); // HTML5
// Or:
$(this).closest('form').submit();
// if the button not inside the form :
var class = $(this).attr('class');
$('form.' + class).submit();
});
Use jquery to bind to the click event instead of doing this on the server side:
Submit Me
then in javascript something like:
<script type="text/javascript">
$('.blah').click(function() {
document.forms[0].submit();
});
</script>
Edit:
While you can generate UI elements with codebehind it's not quite the asp.net way. Use repeaters if you must repeat the generation of controls. Actually, creating multiple forms is not the asp.net way either, as it assumes only one form running at the server context and everything else binds to an event on submission. Anyways, it seems you're still learning asp.net and probably coming form PHP or something similar.
To accommodate your request, I'd advice to stay away from from generating JS on the server side. Give different class names to your forms and use the same method above. You don't need a LinkButton to submit the form, a simple anchor <a> fits the bill.
You can use the ClientID property (if you don't use classes), but you must first attach the parent control to the page for the algorithm to kick in.
So, your code would be something like:
protected Control CreateCommForm()
{
...
column1.Controls.Add(frm);
HtmlGenericControl a = new HtmlGenericControl("a");
a.Attributes["onclick"] = "$('#" + frm.ClientID + "').submit();";
a.InnerText = "Submit me";
frm.Controls.Add(a);
return frm;
}
The alternative way (better separation of concerns)
protected Control CreateCommForm()
{
...
column1.Controls.Add(frm);
HtmlGenericControl a = new HtmlGenericControl("a");
a.Attributes["class"] = "submitter";
a.InnerText = "Submit me";
frm.Controls.Add(a);
return frm;
}
And in javascript we find the parent form and submit it (this can be in a static js file):
<script type="text/javascript">
$('.submitter').click(function(
$(this).parents('form').submit();
));
</script>

Javascript is not called on radiobutton list index change

I have written code for javascript but it is not called any how. I tried to call both form html side and also by assigning attribute from page load event but it is not at all called.
This is the code for my javascript.
function rdbantiplatelet_onClick(thiscontrol, trName) {
alert('hi');
var RB1 = thiscontrol;
var radio = RB1.getElementsByTagName("input");
var trDose = document.getElementById(trName.toString());
// var RB1 = document.getElementById("<%=this.rdbantiplatelet.ClientID%>");
// var radio = RB1.getElementsByTagName("input");
// var tblAntiplatelet = document.getElementById("<%=tblAntiplatelet.ClientID %>");
for (var i = 0; i < radio.length; i++){
if (radio[i].checked){
trDose.style.display = "";
return true;
}
else{
trDose.style.display = "none";
return true;
}
}
return false;
}
This is the code to call javascript written in page_load event..
rdbantiplatelet.Attributes.Add("OnClick", "return rdbantiplatelet_onClick(this,'" + trDose.ClientID.ToString() + "');");
Try an alert() first to make sure your onclick is firing, then try your rdbantiplatelet_onClick() function:
rdbantiplatelet.Attributes.Add("OnClick", "alert('I am working');");
First of all for your reference here is a list of standard html events
http://www.w3schools.com/tags/ref_eventattributes.asp
try adding something like this to the html radiobutton element
onchange="alert('on change fired');"
and
onclick="alert(' on click fired');
so you can make sure you are picking up the right event.
Once you have the right event then replace the alert call to your method
which would be something like this
onchange="rdbantiplatelet_onClick(this, this.parent.id)"
...you might have to change the 'this.parent.id'
Make sure you are running through a good web browser for development FireFox with the firebug plug-in is great for this stuff.
You are add click event to html table that holds radiobuttons. Use script below:
foreach (ListItem item in rdbantiplatelet.Items)
{
item.Attributes.Add("onclick", "return foobar(this);");
}

How to programmatically click on text input in WebBrowser using C#

I have opened a website using WebBrowser. Now I would like to programmatically click input text (textbox) field. I can not use focus because this website uses JS to unlock this field only if it's clicked and I've tried also this:
Object obj = ele.DomElement;
System.Reflection.MethodInfo mi = obj.GetType().GetMethod("click");
mi.Invoke(obj, new object[0]);
But it returns mi = null. How to do this so it will work?
Very similar to my answer on your other question.
Get an HtmlElement respresentative of your textbox, and call HtmlElement.InvokeMember("click") on it.
If you can, use:
webbrowser1.Navigate("javascript:document.forms[0].submit()")
or something similar. For me, it's been much easier and more accurate.
To fill-up a text field on a webpage:
string code ="";
code = code + "var MyVar=document.getElementById('tbxFieldNameOnWebPage');if(MyVar != null) MyVar.value = 'SOMEVALUE';";
domDocument.parentWindow.execScript(code, "JScript");
Then To Click a button on a webpage:
code = "";
code = "var SignupFree = document.getElementsByTagName('button')[1];";
code = (code + " SignupFree.click();");
domDocument.parentWindow.execScript(code, "JScript");
you can also use document.getElementById('buttonID'); instead of document.getElementsByTagName('button')[1]; but an id must be provided for this button on that particular webpage.
Use InvokeMethhod on HtmlElement or Browser.InvokeScript function.

Categories

Resources