Ketone Cops

July 30, 2008

Postback occurring after Cancel clicked

Filed under: ASP.NET 2.0,Javascript,programming — delroger @ 10:06 pm

It’s quite common to use a Javascript function when you want a website user to confirm that they want to delete a file (for instance) or a database record. In ASP.NET, you would add code to OnClientClick for a button (for example), along the lines of:

return confirm(‘Are you sure?’);

This can also be done in the code-behind under Page_Load or Page_PreRender as buttonname.Attributes.Add(“onclick”,”return confirm(‘Are you sure?’)”)

Similarly, you can also call a javascript function that does much the same thing, such as:

function confirm_delete()
    {
        if (confirm(“Are you sure?”)==true)
            return true;
        else
            return false;
    }

…and use:

 return confirm_delete(); 

for the onclick/onclientclick.

This would appear in the actual webpage as an OnClick event for the button. When the button is clicked, the user would see a javascript confirm window, with ‘Are you sure?’ and an OK and a Cancel button. Clicking OK would continue to process any code for the button; clicking Cancel would stop further processing.

It’s also common to find a lot of people have problems with this not working, and in the majority of cases it is because a javascript function is called that returns true or false, but the ‘return’ is missing. Using the example above, if you simply said

confirm(‘Are you sure?’); or confirm_delete();

without the ‘return’, the page would still postback, whatever had been clicked.

Today, I found that even with the ‘return’, postback was still occurring on a webpage I had created; in this case, a file delete still took place even when I clicked the ‘Cancel’ button and a value of false was being returned. 

So, just in case anyone else finds the same thing, this may well be a bug in Internet Explorer 7 (though I have not yet had chance to check this). The solution is to add some extra code to the return confirm, like this:

if (confirm(‘Are you sure?’) == false) {event.returnValue=false; return false; }else{ return true;};

It seems as though we have to specifically set the event.returnValue to be false to prevent further processing and postback.  This took me a few hours to work out, so hopefully this solution may save someone from wasting a similar amount of time, because it doesn’t seem to be very well documented so far.  And if it does help you, please leave a message and say ‘hi’!

July 7, 2008

Referencing page from Class file in App_Code

Filed under: ASP.NET 2.0,programming — delroger @ 1:02 pm

If you need to reference the Page control from a Class file (for instance, for adding a ClientScript) without passing the Page instance as a parameter to a Function or Sub, you can use the following: 

Dim pg As Page = HttpContext.Current.Handler 

You can then use this instance just as you would in the code-behind of the page itself.

For instance, I use this code to create Javascript alerts on my webpages:

Public Shared Sub CreateMessageAlert(ByRef clientScript As System.Web.UI.ClientScriptManager, ByVal strMessage As String, ByVal strKey As String)
 Dim context As HttpContext = HttpContext.Current
 Dim strScript As String = “”
 If (Not clientScript.IsStartupScriptRegistered(strKey)) Then
clientScript.RegisterStartupScript(context.GetType(), strKey, strScript)
 End If
End Sub

(This code was based on some found elsewhere – apologies for not referencing exactly where, since there are a few examples floating around and I don’t remember where I first saw it!)

From a Class file in the App_Code folder, this could then be called like so:

Dim newGuid As Guid = Guid.NewGuid()
Dim pg As Page = HttpContext.Current.Handler
CreateMessageAlert(pg.ClientScript, “Your message here”, newGuid.ToString())

Button event firing twice in ASP.NET

Filed under: ASP.NET 2.0,programming — delroger @ 12:42 pm

I’d got a File Upload control on one of my webpages which was causing a strange problem: when a user clicked the button to upload a file, the button’s click event was firing twice, so the file uploaded twice and a database insert query happened twice.

I’d initially thought that the Page_Load event was occurring twice, since this is quite well documented if, for instance, you have <img src=”#”>.  Debugging the code demonstrated that this was not happening; the Page_Load only fired once, while the btnUpload_Click fired twice.

The problem turned out to be that the code for my button was as follows:

<asp:Button ID=”btnUpload” runat=”server” OnClick=”btnUpload_Click” Text=”Upload File” />

 There are essentially two events for the button: both runat=”server” and OnClick fire the same event, hence everything happening twice.  The solution is simply to remove the OnClick command. 

But why was this happening in the first place? I think it is because I originally had an AJAX UpdatePanel on the page and the control had been part of that initially: the OnClick was created when the File Upload control was dragged into the UpdatePanel; after removing the UpdatePanel, the OnClick still remained.

March 26, 2008

Ajax, an update panel and opening a new window

Filed under: Ajax,ASP.NET 2.0,programming,UpdatePanel — delroger @ 1:51 pm

Since this post is getting quite a few views, just thought I’d add a quick summary of this article if you don’t want to read it all. So here you go: if you want to open a new window from the code-behind page when your function or sub is being called from an AJAX Update Panel, you can do it like this (here your Update Panel is called UpdatePanel1 and you’re opening a PDF)…

ScriptManager.RegisterClientScriptBlock(Me.UpdatePanel1, Me.UpdatePanel1.GetType(), "AnyScriptNameYouLike", "window.open('http://www.yourwebsite.com/YourFolder/YourDocumentOrWebpage.pdf');", True)

And here’s the rest of the original post…

I recently found a problem when using an Ajax Update Panel when I wanted to open a PDF document from the code-behind page.  Without the Ajax, I could simply have added a Response.Write with a javascript window.open function, or I could have used a Literal and written the javascript in much the same way, like this:

Response.Write("<script language='javascript'> window.open('http://website/folder/newdocument.pdf'); </script>")

or this (assuming a Literal control called ltlOpenPdf):

ltlOpenPdf.Text = "<script language=""javascript"">window.open('http://website/folder/newdocument.pdf');</script>"

However, the Response.Write is forbidden in Ajax and produces an error, while the Literal apparently did nothing at all.

Finally I worked out that I could open the new document by using a RegisterClientScriptBlock, most importantly passing the Update Panel as the first parameter where the Page is expected, and the Update Panel’s type as the second parameter, as you will see below.

The Update Panel is called UpdatePanel1. A new PDF has been created and saved to a folder called ‘pdffolder’ and the name of the PDF is dynamically created. The root of the website is also being added dynamically so that it will work equally on the development and the production server. (In reality, the name of the folder that contains the PDFs is also dynamically set, captured from the web.config file using System.Configuration.ConfigurationManager.AppSettings)

Dim docGuid As String = Guid.NewGuid().ToString()
'Do pdf creation stuff here...
Dim sb As StringBuilder = New StringBuilder("")
Dim strRoot As String
strRoot = Request.Url.GetLeftPart(UriPartial.Authority)
sb.Append("window.open('" + strRoot + "/pdffolder/" + docGuid + ".pdf" + "');")
ScriptManager.RegisterClientScriptBlock(Me.UpdatePanel1, Me.UpdatePanel1.GetType(), "NewClientScript", sb.ToString(), True)

The only thing to watch out for with this is that it may be classified as a popup by some blockers and prevented from opening, but then that’s almost inevitable with a window created in code.

February 6, 2008

Monitor mandatory text fields in ASP.NET 2.0

Filed under: ASP.NET 2.0 — delroger @ 1:19 pm
Tags: , ,

I wanted to create an easy way to programmatically monitor textfields in a webpage form and highlight them if they were empty, not to force input or disallow saves and updates, but just to highlight for the website user that the field needed to be filled in eventually.

First, an acknowledgement: I’d been using the ‘ClientSidePage’ method for checking ‘dirty’ data from here and decided to use similar techniques.

The ClientSidePage inherits from the System.Web.UI.Page base class; your webpages then need to inherit from the ClientSidePage class.

The class has two protected strings, which set the colours for highlighting textfields or reverting to the normal background colour. In this case, I’m using a lovely pinkish colour for highlighting, reverting to white if text is entered in the textbox.

Protected HighlightedColour As String = "#f8e0e0"
Protected NormalColour As String = "white"

The class contains a Public Sub called WatchForEmpties that takes a web control as a parameter and adds attributes for onkeyup and onfocus. Both onkeyup and onfocus invoke a javascript called HighlightIfEmpty, which passes the control as a parameter.

The control is added to an array of all the controls on the page that are being monitored. Finally, javascripts are registered for highlighting the empty textboxes and for setting the initial colours for all textboxes that are part of the array of controls.

The class file now looks like this:

Imports Microsoft.VisualBasic

Public Class MonitoringPage
Inherits System.Web.UI.Page
Protected HighlightedColour As String = "#f8e0e0"
Protected NormalColour As String = "white"

Public Sub WatchForEmpties(ByVal wc As WebControl)
  If wc Is Nothing Then Exit Sub
  Dim strFocus As String = wc.Attributes("onfocus")
  If Not strFocus Is Nothing Then
    wc.Attributes("onfocus") = strFocus & "HighlightIfEmpty(this);"
  Else
    wc.Attributes("onfocus") = "javascript:HighlightIfEmpty(this);"
  End If
  Dim strKeyup As String = wc.Attributes("onkeyup")
  If Not strKeyup Is Nothing Then
    wc.Attributes("onkeyup") = strKeyup & "HighlightIfEmpty(this);"
  Else
    wc.Attributes("onkeyup") = "javascript:HighlightIfEmpty(this);"
  End If
  Page.ClientScript.RegisterArrayDeclaration("WatchForEmptiesIDs", """" & wc.ClientID & """")
  WatchForEmptiesOnPageLoad()
End Sub

Private Sub WatchForEmptiesOnPageLoad()
  If Not Page.ClientScript.IsStartupScriptRegistered("HighlightIfEmptyScript") Then
  Dim t As Type
  t = Me.GetType()
  Page.ClientScript.RegisterStartupScript(t, "HighlightIfEmptyScript", _
  "<script language=""JavaScript"">" & Environment.NewLine & _
  " HighlightIfEmpty(Object);" & Environment.NewLine & _
  "</script>")

  Page.ClientScript.RegisterClientScriptBlock(t, "HighlightIfEmptyFunction", _
  "<script language=""JavaScript""">" & Environment.NewLine & _
  " function HighlightIfEmpty(Object) " & Environment.NewLine & _
  "   { " & Environment.NewLine & _
  "     if (Object) " & Environment.NewLine & _
  "     { " & Environment.NewLine & _
  "       var re = /\s/g; " & Environment.NewLine & _
  "       RegExp.multiline = true; " & Environment.NewLine & _
  "       var str;" & Environment.NewLine & _
  "       if (Object.value == null) " & Environment.NewLine & _
  "       { " & Environment.NewLine & _
  "       } " & Environment.NewLine & _
  "       else " & Environment.NewLine & _
  "       { " & Environment.NewLine & _
  "         if (Object.value.length > 0) " & Environment.NewLine & _
  "         { " & Environment.NewLine & _
  "           str = Object.value.replace(re, '');" & Environment.NewLine & _
  "         } " & Environment.NewLine & _
  "         else " & Environment.NewLine & _
  "         { " & Environment.NewLine & _
  "           str = '';" & Environment.NewLine & _
  "         } " & Environment.NewLine & _
  "         if (str.length > 0) " & Environment.NewLine & _
  "         { " & Environment.NewLine & _
  "           return Object.style.backgroundColor = '" & NormalColour & "'; " & Environment.NewLine & _
  "         } " & Environment.NewLine & _
  "         else " & Environment.NewLine & _
  "         { " & Environment.NewLine & _
  "           return Object.style.backgroundColor = '" & HighlightedColour & "'; " & Environment.NewLine & _
  "         } " & Environment.NewLine & _
  "       } " & Environment.NewLine & _
  "     } " & Environment.NewLine & _
  "   } " & Environment.NewLine & _
  "</script>")
  End If

  If Not Page.ClientScript.IsStartupScriptRegistered("WatchForEmptiesAssignment") Then
    Dim t As Type
    t = Me.GetType() '? typeOf(Page)
    Page.ClientScript.RegisterStartupScript(t, "WatchForEmptiesAssignment", _
    "  <script language=""JavaScript"">" & Environment.NewLine & _
    "   SetColoursForEmptyBoxes();" & Environment.NewLine & _
    "  </script>")

    Page.ClientScript.RegisterClientScriptBlock(t, "WatchForEmptiesAssignmentFunction", _
    "  <script language=""JavaScript"">" & Environment.NewLine & _
    "   function SetColoursForEmptyBoxes() { " & Environment.NewLine & _
    "     for (var i = 0; i < WatchForEmptiesIDs.length; i++) {" & Environment.NewLine & _
    "     var elem = document.getElementById(WatchForEmptiesIDs[i]);" & Environment.NewLine & _
    "     HighlightIfEmpty(elem); " & Environment.NewLine & _
    "     }" & Environment.NewLine & _
    "   }" & Environment.NewLine & _
    "</script>")
  End If
End Sub

End Class

If you want to use the monitoring functions in your webpages, they need to inherit this class rather than System.Web.UI.Page

So, in your code-behind page, instead of:

Partial Class Default
  Inherits System.Web.UI.Page
...
End Class

you should have:

Partial Class Default
  Inherits MonitoringPage
...
End Class

To then monitor a textbox that needs to have input, you just need to have a page prerender sub that calls WatchForEmpties, passing in the name of the textbox, like this:

Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
  WatchForEmpties(Me.Textbox1)
End Sub

When the box has an empty string or no text, it will be highlighted. If any text is present, the box will revert back to a white background.

« Previous PageNext Page »

Blog at WordPress.com.