PostBack not fireing in window.onbeforeunload with Firefox - asp.net

I have a main page that contains frames
function attachToTheSaveWhenLeave(sender) {
sender.onbeforeunload = function (ev) {
sender.Save();
};
}
<frameset cols="25%,75%">
<frame id ="Frame1" src="LeftFrame.aspx" />
<frame id ="frmTest" src="FrameContent.aspx" />
</frameset>
In one of the page contained by a frame(FrameContent.aspx), I need to know if the page is discarded in order to fire a PostBack and the server must save the changes made by the user
var isPostBack = false;
window.onload = function (ev) {
window.parent.attachToTheSaveWhenLeave(window);
}
function Save() {
if (!isPostBack)
$("input:submit")[0].click();
}
<form id="formFrame" runat="server" onsubmit="isPostBack=true;">
<div>
<asp:CheckBox ID="CheckBox1" runat="server" AutoPostBack="True" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
</form>
In IE the server receives the postback but with Firefox I have to use setTimeOut for this to work
function Save() {
if (!isPostBack)
setTimeout(function () {
$("input:submit")[0].click();
},1);
}
I do not like the solution I have found, and I do not understand the Firefox's behavior.
Can anyone explain to me why is Firefox behaving this way and if there is another way to do this?

Don't have an alternate for you, but Firefox appears to be behaving as documented (https://developer.mozilla.org/en-US/docs/Web/API/window.onbeforeunload). The point of onbeforeunload is just to put up a prompt when navigating away from a page.
Perhaps jquery.unload (http://api.jquery.com/unload/) or window.onunload is what you had in mind.

Related

ASP .NET - Submit on Enter - Prevent 'defaultbutton' when other button has focus

I have a search form consisting of the following...
<asp:Panel DefaultButton="btnSearch" ... >
[...search criteria fields...]
<asp:Button ID="btnReset" OnClick="btnReset_Click" ... />
<asp:Button ID="btnSearch" OnClick="btnSearch_Click" ... />
</asp:Panel>
The desired behaviour is that pressing the Enter key should invoke btnSearch_Click (which is working thanks to the DefaultButton attribute in the asp:panel)
The problem is that when btnReset has focus, pressing Enter should invoke btnReset_Click instead (which it doesn't - it's always btnSearch).
Is this easily achievable somehow, or am I going to have to hack up some bespoke JS to intercept .NET's defaultButton event handler?
Thanks in advance.
ETA: Here's a reusable solution I went with based on HenryChuang's accepted answer below.
Add a custom attribute preventDefaultButton to panels.
<asp:Panel DefaultButton="btnSearch" preventDefaultButton="btnReset" >
[...search criteria fields...]
<asp:Button ID="btnReset" OnClick="btnReset_Click" ... />
<asp:Button ID="btnSearch" OnClick="btnSearch_Click" ... />
</asp:Panel>
Run the following jQuery on pageload.
$("div[preventDefaultButton]").each(function () {
var div = $(this);
var keypressEvent = div.attr("onkeypress");
var btn = $("input[id$=" + div.attr("preventDefaultButton") + "]");
btn.on("focus", { div: div }, function (event) {
event.data.div.attr("onkeypress", "");
});
btn.on("blur", { div: div, keypressEvent: keypressEvent }, function (event) {
event.data.div.attr("onkeypress", event.data.keypressEvent);
});
});
see the panel generate html
<div id="yourPanelClientID" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'btnSearch')">
so, when btnReset onfocus we break onkeypress event of Panel, add below to btnReset,
remember when btnReset onblur, change Panel keypress to oringinal
onfocus="document.getElementById('yourPanelClientID').onkeypress = '';"
onblur="funA();"
function funA() {
document.getElementById('yourPanelClientID').onkeypress = function () { return WebForm_FireDefaultButton(event, "btnSearch") };
}
like this
<asp:Button ID="btnReset"
onfocus="document.getElementById('yourPanelClientID').onkeypress = '';"
onblur="funA();"
onclick="btnReset_Click" .../>
you need to change DefaultButton attribute of your panel but this will work for only one at a time, better way would be to have Javascript to capture enter event and process accordingly.
One way can be having multiple panels, have a look at http://www.jstawski.com/archive/2008/09/23/multiple-default-buttons.aspx

How to swallow the postback of a asp.net linkbutton control?

I have a page with a form containing an element. I have the click event being handled client side by a Jscript function, however, the page is still reloading whenever I click the LinkButton, can this be avoided?
aspx
<body>
<form>
<asp:LinkButton runat="server" ID="thing" OnClientClick="return SomeFunction()" Text="Some Operation" />
</form>
</body>
JScript
function SomeFunction() {
document.getElementById('someText').innerText = 'SomeMessage';
return false;
}
SomeButton.Attributes.Add("onclick", "javascript:SomeFunction(); return false;");
Update: since your updated code is assigned function in ASPX page, you can use this method -
<asp:LinkButton runat="server" ID="thing"
OnClientClick="javascript:SomeFunction(); return false;"
Text="Some Operation" />
OR
<asp:LinkButton runat="server" ID="thing"
OnClientClick="return SomeFunction()" Text="Some Operation" />
function SomeFunction() {
document.getElementById('someText').innerText = 'SomeMessage';
return false; /**** Required *****/
}
To have the return false; working, you will have to add return before the Method Name.
ex. <asp:LinkButtun ID="IDHere" runat="server" OnClientClick="return SomeFunction()" />

How to correct ASP.NET webform jquery reference being lost on partial postback

Within an asp.net webform I have some jquery that controls the positioning of elements on the page. Since this is a webform and some of these controls talk to the server to get jquery to work I have the controls nested in an AJAX UpdatePanel to prevent postbacks from resetting my controls.
aspx:
<asp:UpdatePanel ID="searchupdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div id="searchholder" >
<div id="searchoptions">
Close Advanced Search
<br />
Filters
</div>
<div id="search" class="searchcontainer">
<asp:TextBox ID="tbsearchterm" CssClass="watermark" runat="server" OnTextChanged="tbsearchterm_TextChanged" />
<div class="buttons">
<asp:LinkButton runat="server" Text="Search" class="button search-big" ID="btnSearch" OnClick="btnSearch_Click" />
<asp:LinkButton runat="server" Text="Fx" class="button left big" ID="btnOperators" />
<asp:LinkButton runat="server" Text="Save" class="button right big" ID="btnSave" />
</div>
</div>
<div id="divAdvSearch">
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
<div id="divBody">
<asp:UpdatePanel runat="server" UpdateMode="Always">
<ContentTemplate>
<div id="divSearchResults" visible="true" runat="server">
<uc:SearchResultsControl ID="SearchResultsControl" runat="server"></uc:SearchResultsControl>
</div>
</ContentTemplate>
</asp:UpdatePanel>
When the search button is clicked I modify the css class for the search control to reposition my search div layer which is the update panel "searchudpatepanel"
searchcontrol.js
$(function () {
$("#searchupdatePanel").addClass("searchmenubar");
$("#btnClose").hide();
});
$(function () {
$("#btnSearch").click(function () {
$(".searchmenubar").animate({ "margin-top": "5px" }, "fast");
$("#btnAdvanceSearch").show();
$("#btnFilters").show();
$("#btnClose").hide();
$("#divAdvSearch").hide();
alert("search");
});
});
The button click also calls serverside code to retrieve and populate the results within a user control called SearchResultsControl ( second update panel)
Where I am confused is when the searchResult Control is loaded with the results all references to the jquery classes are lost. As a result every div element that is hidden or button click that is called ceases to work. Working through this in debug I can see when the user control is called the Page_Load for the default.aspx file is invoked as second time. I assume this partial load is dropping reference to the js files I just don't know how to correct this.
I tried a test within the page load using IsStartupScriptRegistered to see if the js was getting called
string csname = "PopupScript";
Type cstype = this.GetType();
ClientScriptManager cs = Page.ClientScript;
if (!cs.IsStartupScriptRegistered(cstype, csname))
{
StringBuilder cstext1 = new StringBuilder();
cstext1.Append("<script type=text/javascript> alert('Hello World!') </");
cstext1.Append("script>");
cs.RegisterStartupScript(cstype, csname, cstext1.ToString());
}
Here on the initialization of the page I would see the pop up occur however when the UserControl was loaded I would pass through this a second time in the page load but the alert never displayed( I assume this is due to a partial load so the browser thinks the script is already registered).
The only other thing I can think of is I am overriding the rendering of the UserControl being loaded as it loads a custom result set.
protected override void Render(HtmlTextWriter htw)
{
if (IsPostBack)
{
QueryResponse qr = iu.GetSearchResults(SearchTerm);
int num = qr.TotalMatchesReturned;
SearchData sd = new SearchData();
htw.Write("<table style='width: 100%; height:100%'><tr ><td style='width: 50%'>");
htw.Write("<div id='divResultDetail' runat=server >");
htw.Write("<script type='text/javascript' src='../js/paging.js'></script><div id='pageNavPosition'></div><table id='results'>");
for (int i = 0; i < num; i++)
{
...edited for brevity.
Any suggestions or guidance as to why I am losing reference to the jquery functions? I am not using master pages so I haven't used the ASP ScriptManager.
This all worked fine prior to using UpdatePanels. I define "fine" as: the postback was reloading/registering the js files each time, so they were being reset (which was okay). However, now with some other changes needed I need to look at leveraging UpdatePanels.
Thanks for any suggestions or ideas.
You can use the live or delegate jQuery methods to get your handlers to be bound to any elements added to the page.
Alternatively, if you need some setup to always happen after every partial postback in addition to original page load, you can put it in a pageLoad method instead of document.ready. ASP.NET calls this on page load, and after every partial postback.
function pageLoad()
{
// Setup code here
}
Check this article for more:
http://encosia.com/document-ready-and-pageload-are-not-the-same/
You need to use delegate for the button click. It will assure that all elements present and future will be bound to the event handler.
http://api.jquery.com/delegate/
$("body").delegate("#btnSearch", "click", function () {
$(".searchmenubar").animate({ "margin-top": "5px" }, "fast");
$("#btnAdvanceSearch").show();
$("#btnFilters").show();
$("#btnClose").hide();
$("#divAdvSearch").hide();
alert("search");
});
You need to rebind the elements when the update panel finish updating. Like this,
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
$('#add').click(function () {
});
$('#addPrevious').click(function () {
});
});
Hope this helps.

Can I create an ASP.NET ImageButton that doesn't postback?

I'm trying to use the ImageButton control for client-side script execution only. I can specify the client-side script to execute using the OnClientClick property, but how do I stop it from trying to post every time the user clicks it? There is no reason to post when this button is clicked. I've set CausesValidation to False, but this doesn't stop it from posting.
I know this problem has already been answered but a simple solution is to return false from the HTML onclick method (i.e. the ASPX OnClientClick method) e.g.
<asp:ImageButton ID="ImageNewLink" runat="server"
ImageUrl="~/images/Link.gif" OnClientClick="DoYourStuff(); return false;" />
Returning false stops the browser from making the request back to the server i.s. stops the .NET postback.
Here's one way you could do it without conflicting with the postback functioning of other controls:
Define your button something like this:
<asp:Button runat="server" Text="Button" UseSubmitBehavior="false" OnClientClick="alert('my client script here');my" />
The "my" ending in the handler for OnClientClick is a way to alias asp.net's __doPostBack client event that forces the postback; we simply override the behavior by doing nothing similar to this script:
<script type="text/javascript">
function my__doPostBack(eventTarget, eventArgument) {
//Just swallow the click without postback of the form
}
</script>
Edit: Yeesh, I feel like I need to take a shower after some of the dirty tricks that I need to pull in order to get asp.net to do what I want.
Another solution would be to define a PostBackUrl that does nothing
<asp:imagebutton runat="server" PostBackUrl="javascript:void(0);" .../>
<image src="..." onclick="DoYourThing();" />
Use a server side Image control
<asp:Image runat="server" .../>
Pretty sure you can add the client onclick event to that.
Solution 1
<asp:ImageButton ID="btn" runat="server" ImageUrl="~/images/yourimage.jpg"
OnClientClick="return false;" />
OR
Solution 2
<asp:ImageButton ID="btn" runat="server" ImageUrl="~/images/yourimage.jpg"
OnClientClick="yourmethod(); return false;" />
In addition (solution 2), your javascript method may be in this form
<script type="text/javascript">
function yourmethod() {
__doPostBack (__EVENTTARGET,__EVENTARGUMENT); //for example __doPostBack ('idValue',3);
}
</script>
in code behind
protected void Page_Load(object sender, System.EventArgs e)
{
if (this.IsPostBack) {
string eventTarget = this.Request("__EVENTTARGET") == null ? string.Empty : this.Request("__EVENTTARGET");
string eventArgument = this.Request("__EVENTARGUMENT") == null ? string.Empty : this.Request("__EVENTARGUMENT");
}
}
This works Great for me:
Use OnClientClick to write your script and PostBackUrl="javascript:void(0);" to avoid postback.
<div class="close_but">
<asp:ImageButton ID="imgbtnEChartZoomClose" runat="server" ImageUrl="images/close.png" OnClientClick="javascript:zoomclosepopup();" PostBackUrl="javascript:void(0);" />
</div>
Use OnClientClick to write your script and PostBackUrl="javascript:void(0);" to avoid postback

OnClick vs OnClientClick for an asp:CheckBox?

Does anyone know why a client-side javascript handler for asp:CheckBox needs to be an OnClick="" attribute rather than an OnClientClick="" attribute, as for asp:Button?
For example, this works:
<asp:CheckBox runat="server" OnClick="alert(this.checked);" />
and this doesn't (no error):
<asp:CheckBox runat="server" OnClientClick="alert(this.checked);" />
but this works:
<asp:Button runat="server" OnClientClick="alert('Hi');" />
and this doesn't (compile time error):
<asp:Button runat="server" OnClick="alert('hi');" />
(I know what Button.OnClick is for; I'm wondering why CheckBox doesn't work the same way...)
That is very weird. I checked the CheckBox documentation page which reads
<asp:CheckBox id="CheckBox1"
AutoPostBack="True|False"
Text="Label"
TextAlign="Right|Left"
Checked="True|False"
OnCheckedChanged="OnCheckedChangedMethod"
runat="server"/>
As you can see, there is no OnClick or OnClientClick attributes defined.
Keeping this in mind, I think this is what is happening.
When you do this,
<asp:CheckBox runat="server" OnClick="alert(this.checked);" />
ASP.NET doesn't modify the OnClick attribute and renders it as is on the browser. It would be rendered as:
<input type="checkbox" OnClick="alert(this.checked);" />
Obviously, a browser can understand 'OnClick' and puts an alert.
And in this scenario
<asp:CheckBox runat="server" OnClientClick="alert(this.checked);" />
Again, ASP.NET won't change the OnClientClick attribute and will render it as
<input type="checkbox" OnClientClick="alert(this.checked);" />
As browser won't understand OnClientClick nothing will happen. It also won't raise any error as it is just another attribute.
You can confirm above by looking at the rendered HTML.
And yes, this is not intuitive at all.
Because they are two different kinds of controls...
You see, your web browser doesn't know about server side programming. it only knows about it's own DOM and the event models that it uses... And for click events of objects rendered to it. You should examine the final markup that is actually sent to the browser from ASP.Net to see the differences your self.
<asp:CheckBox runat="server" OnClick="alert(this.checked);" />
renders to
<input type="check" OnClick="alert(this.checked);" />
and
<asp:CheckBox runat="server" OnClientClick="alert(this.checked);" />
renders to
<input type="check" OnClientClick="alert(this.checked);" />
Now, as near as i can recall, there are no browsers anywhere that support the "OnClientClick" event in their DOM...
When in doubt, always view the source of the output as it is sent to the browser... there's a whole world of debug information that you can see.
You are right this is inconsistent. What is happening is that CheckBox doesn't HAVE an server-side OnClick event, so your markup gets rendered to the browser. http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.checkbox_events.aspx
Whereas Button does have a OnClick - so ASP.NET expects a reference to an event in your OnClick markup.
For those of you who got here looking for the server-side OnClick handler it is OnCheckedChanged
I was cleaning up warnings and messages and see that VS does warn about it:
Validation (ASP.Net): Attribute 'OnClick' is not a valid attribute of element 'CheckBox'. Use the html input control to specify a client side handler and then you won't get the extra span tag and the two elements.
Asp.net CheckBox is not support method OnClientClick.
If you want to add some javascript event to asp:CheckBox you have to add related attributes on "Pre_Render" or on "Page_Load" events in server code:
C#:
private void Page_Load(object sender, EventArgs e)
{
SomeCheckBoxId.Attributes["onclick"] = "MyJavaScriptMethod(this);";
}
Note: Ensure you don't set AutoEventWireup="false" in page header.
VB:
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
SomeCheckBoxId.Attributes("onclick") = "MyJavaScriptMethod(this);"
End Sub
You can do the tag like this:
<asp:CheckBox runat="server" ID="ckRouteNow" Text="Send Now" OnClick="checkchanged(this)" />
The .checked property in the called JavaScript will be correct...the current state of the checkbox:
function checkchanged(obj) {
alert(obj.checked)
}
You can assign function to all checkboxes then ask for confirmation inside of it. If they choose yes, checkbox is allowed to be changed if no it remains unchanged.
In my case I am also using ASP .Net checkbox inside a repeater (or grid) with Autopostback="True" attribute, so on server side I need to compare the value submitted vs what's currently in db in order to know what confirmation value they chose and update db only if it was "yes".
$(document).ready(function () {
$('input[type=checkbox]').click(function(){
var areYouSure = confirm('Are you sure you want make this change?');
if (areYouSure) {
$(this).prop('checked', this.checked);
} else {
$(this).prop('checked', !this.checked);
}
});
});
<asp:CheckBox ID="chk" AutoPostBack="true" onCheckedChanged="chk_SelectedIndexChanged" runat="server" Checked='<%#Eval("FinancialAid") %>' />
protected void chk_SelectedIndexChanged(Object sender, EventArgs e)
{
using (myDataContext db = new myDataDataContext())
{
CheckBox chk = (CheckBox)sender;
RepeaterItem row = (RepeaterItem) chk.NamingContainer;
var studentID = ((Label) row.FindControl("lblID")).Text;
var z = (from b in db.StudentApplicants
where b.StudentID == studentID
select b).FirstOrDefault();
if(chk != null && chk.Checked != z.FinancialAid){
z.FinancialAid = chk.Checked;
z.ModifiedDate = DateTime.Now;
db.SubmitChanges();
BindGrid();
}
gvData.DataBind();
}
}
One solution is with JQuery:
$(document).ready(
function () {
$('#mycheckboxId').click(function () {
// here the action or function to call
});
}
);

Resources