(Updated this post after some refactoring discussions with my good friend Frank from over at DuhJones.com)
If you’re a twitterer, you’ve seen the notification drop-downs they use. Basically it’s a bar, full-screen width, which contains a notification message. It slides down from the top of the screen, stays put for a few seconds, then disappears. Shiny.
This post is all about accomplishing that very thing in .NET with jQuery.
(Click here to see an example of the markup, CSS, and jQuery on jsFiddle. This will show you the effect, and the rest of this post will show you how get it all wired up in .NET)
Here Are Our Basic Requirements
- Show a slide-down notification area using jQuery
- Use jQuery .slidedown effect if possible (no extra libraries)
- Slide from top of screen (like Twitter does)
- Should slide over other elements on page, not move them down.
- Make call to client-side function from code behind (essentially pop the notification from the code-behind)
- Pass a custom message from the code behind to the slide-down notification
- Based on conditions set in the code-behind, give the notification area a custom CSS (background green for success, red for failure, something like that)
So requirements in hand, I think we are ready to go.
The Bacon
Hey what goes better with toast smothered in jQuery and ASP.NET, than bacon right? Maybe I’m just hungry but I needed a title for this section and bacon came to mind.
Here are the highlights on how this comes together or you can just jump to the full-code-listing at the end of this post to see it all.
First The Markup
This is the body content we’ll be using. The alertmsg div is our target and we’ll be modifying that with javascript generated from our code-behind. That’s why at this point, it has nothing in it. We’ll fill it in later.
[html]
</pre>
<form id=”form1″>
<div id=”wrapper”>
<div id=”alertmsg”></div>
<div id=”header”>
Header area</div>
<div id=”menu”>
Menu area</div>
<div id=”mainContent”>
Text generated at <a href=”http://baconipsum.com/” target=”_blank”>Bacon ipsum</a>. For even more bacon,
try the <a href=”http://bacontoday.com/bacon-explosion/” target=”_blank”>Bacon Explosion</a>! dolor sit amet
boudin pancetta hamburger strip steak. Tenderloin ball tip t-bone, capicola rump turkey frankfurter
pork loin fatback ham hock tongue venison chuck swine. Short ribs venison bacon jerky, pancetta
meatloaf shoulder andouille sirloin biltong spare ribs hamburger beef pork. Tail tenderloin ball
tip corned beef frankfurter sirloin cow. Leberkas tail pig pastrami shankle boudin rump spare
ribs turkey short loin ball tip shank brisket.
<div id=”control-area”>
<div>
<input type=”button” value=”Run client side only” />
<input id=”Message” type=”text” /></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
</form>
<pre>
[/html]
With our markup firmly in place, let’s build some styles.
The CSS
As you can see our CSS initially loads our alertmsg div as display: none. That’s exactly what we want for now, because after the postback, we will stuff modified CSS and javascript into the browser totally modifying reality as we know it. Ah, the sheer power!
[css]
[/css]
Well gosh, we have markup and CSS .. so, tired yet? No? Good because that was the easy part of course. Now let’s do the magic in the code-behind, which will do real magic in the client later.
The Code Behind
I don’t want to drag this post out but I just hate it when things aren’t explained very well in a technical blog post.
So for this entire example we’ll be creating some client-side functions from the code-behind and assigning some CSS to elements in the markup.
To get things rolling let’s begin with some class level vars.
[csharp]
private ClientScriptManager _cs;
private Type _cstype;
private string _message;
private string _style;
[/csharp]
The last two vars are simply strings that contain our class we’ll assign to the div and the message it will contain ( and yes I acknowledge that we could use enumerations, etc for the CSS classes but it’s just a demo dudes and dudettes )
The var _cs gives us access to the client script manager which is the little doohickey that will allow us to force-feed javascript to the browser during our postbacks (nom nom nom).
_csType is just the type of client script we’re going to look for before registering our scripts to the page. What I mean by that is, when we’re sending our javascript from the code-behind to the browser, we want to check to see if a script block of that type is already registered in the page and only do it if it’s not already there.
That prevents problems as you can imagine and here at Retromorrow we’re all about problems .. preventing them I mean.
Now face front class! More important things await.
Page_Load
Nothing fancy to see here. We’re initializing the vars we just discussed and calling our one method which will register the javascript function DoClick() for one of our buttons.
[csharp]
public void Page_Load(Object sender, EventArgs e)
{
_cs = Page.ClientScript;
_cstype = GetType();
SetupBasicScript();
}
private void SetupBasicScript()
{
// Define the name and type of the client scripts on the page.
String csname2 = “ButtonClickScript”;
// Check to see if the client script is already registered.
if (!_cs.IsClientScriptBlockRegistered(_cstype, csname2))
{
StringBuilder cstext2 = new StringBuilder();
cstext2.Append(“function DoClick() {“);
cstext2.Append(Environment.NewLine);
cstext2.Append(“form1.Message.value=’Text from client script.’;}”);
cstext2.Append(Environment.NewLine);
cstext2.Append(Environment.NewLine);
_cs.RegisterStartupScript(_cstype, csname2, cstext2.ToString(), true);
}
}
[/csharp]
What this does is register this script with the page, if it doesn’t already exist, enabling our basic html button to run some javascript.
That’s all fine and dandy if all you have to worry about is the client side. However what if you want the decision to do an alert to be based solely on server-side code?
That is our next step.
The Basic Alert Box (from the server side)
So we have our model for sending javascript back to the browser. Now how do we use that with server-side controls? Here is a snippet for that.
[csharp]
protected void Button3Click(object sender, EventArgs e)
{
ShowNotificationBasic(“Alert from the server side.”);
}
private void ShowNotificationBasic(string message)
{
// Define the name and type of the client scripts on the page.
String csname1 = “PopupScript”;
if (String.IsNullOrEmpty(message) == true)
{
return;
}
// Check to see if the startup script is already registered.
if (!_cs.IsStartupScriptRegistered(_cstype, csname1))
{
String cstext1 = “alert(‘” + message + “‘);”;
_cs.RegisterStartupScript(_cstype, csname1, cstext1, true);
}
}
[/csharp]
What is going on here?
The Button3Click event is wired up to a server side button. It simply calls our method which in turn creates a javascript alert, pushing that back down to the client during the postback.
Now on to the main event. Putting this all together into something more twittery.
The More Complicated (and cooler) Alert (also from the server side)
Here is what you came for. Apologies for the lengthy post too. There is a bit to this and I wanted to explain this pretty well. And heck in 6 months, I’ll have likely forgotten how to do this so I needed the documentation! 🙂
So let’s start with this. We’ve got a button event, referencing buttons in our markup, for both a failed message and a success message.
[csharp]
protected void Button4Click(object sender, EventArgs e)
{
SetStatus(“Toast with jQuery smells good when you’re hungry for succcess.”, “alert-msg-success”);
}
protected void Button1Click(object sender, EventArgs e)
{
SetStatus(“Sometimes you burn the toast and you need a failure style. You’re welcome.”, “alert-msg-failed”);
}
public void SetStatus(string message, string style)
{
_message = message;
_style = style;
}
[/csharp]
As you can see we also have a SetStatus method that simply sets our class vars for both the message and style. Now we need a method that uses those vars in order to send some javascript back to the browser.
These vars are used in the following method which is what actually, creates our javascript, which fills out our div and modifies the div’s class.
[csharp]
private void ShowNotificationPopDown(string message, string messagestyle)
{
// Define the name and type of the client scripts on the page.
String csname1 = “ToasterScript”;
// Show no message if nothing is set.
if (String.IsNullOrEmpty(message) == true && string.IsNullOrEmpty(messagestyle) == true)
{
return;
}
// Check to see if the startup script is already registered.
if (!_cs.IsStartupScriptRegistered(_cstype, csname1))
{
StringBuilder cstext1 = new StringBuilder();
cstext1.Append(“$(document).ready(function() {“);
cstext1.Append(Environment.NewLine);
cstext1.Append(“var $alertdiv = $(‘#alertmsg’);”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“$alertdiv.removeClass(‘alertmsg’).addClass(‘”);
cstext1.Append(messagestyle);
cstext1.Append(“‘);”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“$alertdiv.text(\”” + message + “\”);”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“$alertdiv.bind(‘click’, function() {“);
cstext1.Append(Environment.NewLine);
cstext1.Append(“$(this).slideUp(200);”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“});”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“$(\”#alertmsg\”).slideDown(\”slow\”);”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“setTimeout(function() { $alertdiv.slideUp(200); }, 3000);”);
cstext1.Append(Environment.NewLine);
cstext1.Append(“});”);
_cs.RegisterStartupScript(_cstype, csname1, cstext1.ToString(), true);
}
// Reset the vars after the toast pops so that we don’t get double-hit.
// Only one slice of toast for you, all those carbs are bad anyway.
_message = string.Empty;
_style = string.Empty;
}
[/csharp]
The ShowNotificationPopDown method is called in the Pre_Render event so that we can get all our elements set for how they will appear when the page actually renders in the browser.
[csharp]
public void Page_PreRender(Object sender, EventArgs e)
{
ShowNotificationPopDown(_message, _style);
}
[/csharp]
So our method is called, before the page renders, using the variables we set as the postback happened. In the method as you can see above, we write out a function that does not run until the document is ready.
At that time, we show our div with the specified class, and let our jQuery do it’s work. The function targets our alertdiv, changing it’s CSS and running the jQuery slideUp animation on it.
Well that’s about it.
That satisfies all our requirements.
In closing, this was clearly not all production code but it should get you close if you’re needing some yummy toast smeared with jQuery and ASP.net.
Feel free to comment on this. I love doing tuts like this one. If you have examples of sites that do instructions like this better, please feel free to share. I want posts like this to be exceptional and I’m always looking for ways to get better at this wordcraft!
Thanks for stopping by!