Sunday, March 28, 2010

Different Approach to the Usual CSS Sprite to Reduce HTTP Requests




I just found this little tidbit today. If you ever have a problem with too many HTTP requests, this could be a solution for you over a CSS sprite. I’m using this approach for my CSS backgrounds that are simple small icons. I would not recommend this approach for anything much larger. FYI: IE8 limits URIs to max length of 32KB.

To help with this approach, you’ll need a couple tools. Here are the few I found:

Obviously, you can always write your own :)

So, this is what I wanted:

image

My original CSS looked like this:

a#createarticle {padding-left: 20px; background: url(/i/ico-addarticle.png) no-repeat center left}

This code will make two HTTP requests, one for the stylesheet and another for the icon. (assuming the above code is in a stylesheet, which in my case, it is)

To eliminate the additional HTTP request, I changed my CSS to look like this:

#createarticle {padding-left: 18px; background: url(data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBAQFBAYFBQYJBgUGCQsIBgYICwwKCgsKCgwQDAwMDAwMEAwODxAPDgwTExQUExMcGxsbHCAgICAgICAgICD/2wBDAQcHBw0MDRgQEBgaFREVGiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICD/wAARCAAQAA8DAREAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAQIHCP/EACUQAAICAQIEBwAAAAAAAAAAAAECAwQSAAUGERMhFCIjMTJSgf/EABYBAQEBAAAAAAAAAAAAAAAAAAAEBf/EABwRAQABBAMAAAAAAAAAAAAAAAARAQISIRMxQf/aAAwDAQACEQMRAD8A0nUoVpKMEhhjZ2jRmZkUkkqOZJI0DVl8NajEXlimOEkPIBQwQtknL2+HcaA0b1JKVdHsRo6xoGVnUEEL3BGgktniveJ6lafZbtmfjYSP19mJ6kYbEB/QzKqqKz4nH9+2TzXzqcprpHnXzt//2Q%3D%3D) no-repeat center left}

This might look intimidating, but it’s really pretty simple. You simply replace the “/i/ico-addarticle.png” in the first sample with the generated base64 from one of the tools mentioned above.

To get the base64, I used A Blue Star because I wanted to upload an image and get the base64, but you could also use the greywyvern.com and that’s what I’ll walk through now.

So I’ll grab an icon from famfamfam.com (which is where I get almost all my icons) and paste the URL on the greywyvern.com site.

Step 1: Grab URL
Paste it into the URI textbox on greywyvern.com like this:

image

Step 2: Generate Results
Click Submit Query & you’ll get this:

image

Step 3: Copy & Paste Results
Copy ALL the textarea and paste it into either the src of an img object or into the url of a CSS background attribute.

If you like your CSS to be readable and don’t want to deal with looking at base64, then I would stick to the CSS sprite, but I thought this method was cool. Especially for icons next to hrefs that don’t change a lot. However, I think the configuration for this is much simpler than a CSS sprite and having to deal with the different margins, widths, etc that come along with a CSS sprite :)

Thanks for reading!

kick it on DotNetKicks.com

Monday, March 15, 2010

Drag & Drop with MVC & jQuery AJAX




So my wife decided she’d like her clients to be able to order prints off her website via some type of code. Well I thought I’d start with the fun part. The selection of pictures being dragged over to a cart of some sort. I’ve never used anything like this and thought it’d be fun to learn.

So here’s where I’m at…i have a couple graphics that are draggable to a cart. Once the graphic is dropped, it does something like write to a db or something and then returns a success. Let’s look at the code because I stink at explaining stuff I think…

<style type="text/css">
.draggable { width: 100px; height: 100px; border: solid 1px #ccc; margin: .5em}
#imageboundary {width: 500px; height:500px; border: solid 1px #ccc}
#droppable {border: solid 1px #000; width: 150px; height: 150px}
</
style>
<
div class="result"></div>
<
div id="imageboundary">
<
div id="droppable">
<
ul id="cart"></ul>
</
div>
<
img class="draggable" id="1234" src="../../_a/i/bck-logo.gif" />
<
img class="draggable" id="123456789" src="../../_a/i/bck-required.gif" />
</
div>

So above is my sample HTML code, which is pretty simple I think. Here’s what I got…a few styles, a result box, a boundary for the drag, my cart, and two draggable images.

Okay, so I have a couple references to jquery & jquery.ui. Looks like this:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<
script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>

Okay, now I’m going to post the completed section as of right now, but I will be breaking it apart in sections further down.

<script type="text/javascript">
$(
function() {
$(
".draggable").draggable({ containment: '#imageboundary', revert: 'valid' });
$(
"#droppable").droppable({
drop:
function(event, ui) {
$.ajax({
type:
"POST",
url:
'/Home/AddToCart/' + $(ui.draggable).attr("id"),
success:
function(data) {
$(
'.result').html(data);
$(
"<li>" + $(ui.draggable).attr("id") + "</li>").appendTo($('ul#cart'));
}
});
}
});
});
</
script>

So…to make things draggable, we simply add this line:

$(".draggable").draggable({ containment: '#imageboundary', revert: 'valid' });

You can read more about this here.

To make a droppable box, it’s simply this:

        $("#droppable").droppable({
drop:
function(event, ui) {
$(
'.result').html($(ui.draggable).attr("id"));
}
});

Granted this is not exactly like the code above, but I wanted to simplify it so you could see what it would take to make something droppable. You can read more about this here.

Now to make the ajax call to my action on my controller  you do this:

    $("#droppable").droppable({
drop:
function(event, ui) {
$.ajax({
type:
"POST",
url:
'/Home/AddToCart/' + $(ui.draggable).attr("id"),
success:
function(data) {
$(
'.result').html(data);
$(
"<li>" + $(ui.draggable).attr("id") + "</li>").appendTo($('ul#cart'));
}
});
}
});

Okay, so on my HomeController I have an AddToCart action that looks like this right now:

        [AcceptVerbs(HttpVerbs.Post)]
public string AddToCart(string id)
{
if (string.IsNullOrEmpty(id))
return "Invalid id. Please press back or enable JavaScript.";

//Add to cart logic

return string.Format("Successfully added {0}.", id);
}

I’m just getting started with this little project, but I thought I’d share.

Thanks for reading!


Shout it

kick it on DotNetKicks.com

Friday, March 05, 2010

Contact Form with ASP.NET MVC, Castle Validation, & fluentHtml




Here’s another little tutorial for those of you new to MVC &/or fluentHtml. I figure I’ll do these little tutorials until I find a new project to work on. I do have a couple of ideas…so we’ll see how those turn out.

Let’s get started.

We’ll start with the view model class again like last week. By the way, if you’re not familiar with the way I setup my MVC projects, see this post.

public class ContactView
{
[
ValidateNonEmpty("Name")]
public string Name { get; set; }
[
ValidateNonEmpty("Email"), ValidateEmail("Valid Email")]
public string Email { get; set; }
public string Subject { get; set; }
[
ValidateNonEmpty("Message")]
public string Message { get; set; }
}

The ValidateNonEmpty and ValidateEmail are attributes from the Castle project and I’m passing in the error message I want displayed if invalid. Alrighty, let’s setup our controller action and the view (html).

Controller Action:

public class ContactController : Controller
{
public ActionResult Index()
{
return View(new ContactView());
}
}

View/HTML Markup

<%@ Page Title="Contact Us" Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="MvcContrib.FluentHtml.ModelViewPage<ContactView>" %>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<
h2>Contact Us</h2>
<% using(Html.BeginForm("Index", "Contact", FormMethod.Post)) {%>
<%
=Html.DivSuccessMessage("Message sent successfully!")%>
<%
=Html.DivValidationSummary("Please see the items below:")%>
<fieldset>
<
legend>Proposal Form</legend>
<%=this.TextBox(f => f.Name).Label("Name:")%>
<%
=this.TextBox(f => f.Email).Label("Email:")%>
<%
=this.TextBox(f => f.Subject).Label("Subject:")%>
<%
=this.TextArea(f => f.Message).Label("Message:")%>
<%
=Html.AntiForgeryToken() %>
<%
=this.SubmitButton("Send").Attr("accesskey", "S").Class("sb") %> All fields are required.
</
fieldset>
<% } %>
</asp:Content>

This is a simple form with fluentHtml. If you need a tutorial on fluentHtml, here’s a post on it. You should notice that this page inherits from the MvcContrib ModelViewPage with our ContactView from above being passed in. I typically create my own base page that inhertis from the MvcContrib one, but to make this post easier, I just inherit straight from their’s.

Okay, let’s get to the meet where we accept the post in the controller.

[AcceptVerbs(HttpVerbs.Post), ValidateModel(typeof(ContactView)), ValidateAntiForgeryToken]
public ActionResult Index(ContactView form)
{
if (!ModelState.IsValid)
return View(form);

try
{
var notificationService = DI.EmailNotificationService(new EmailNotification(form));
notificationService.Notify();

Success();
}
catch (NotificationException)
{
ModelState.AddModelError(
"notifyerror"
, "Unfortunately, something went wrong with the message delivery. Please try again.");
}

return View(form);
}

Okay, so we’re only accepting a post, we’re validating our model with a validation filter, and validating the anti-forgery token. I’m also accepting my ContactView model. If the model state isn’t valid, I return the model back to the view. Otherwise, I try to create a new instance of EmailNotificationService (which returns an INotificationService) then I call the Notify(). If I don’t receive a NotificationException, then I call Success() on my SmartController (which is what this controller inherits from) Success(); simply does this: ViewData["success"] = ""; You can read more about it in this post. If the Notify() bombs, we add a model error and then finally we return the form to the view. If you wanted to clear out the form, you’d put return View(new ContactView()) right after the Success() call.

So what does the INotificationService look like? Well, this:

public interface INotificationService
{
void Notify();
}

The implementation looks like this:

public class EmailNotificationService : INotificationService
{
private readonly IEmailNotification _emailNotification;

public EmailNotificationService(IEmailNotification emailNotification)
{
_emailNotification = emailNotification;
}

public void Notify()
{
using (var mail = new MailMessage())
{
mail.To.Add(_emailNotification.To);
mail.From =
new MailAddress(_emailNotification.From);
mail.Subject = _emailNotification.Subject;
mail.Body = _emailNotification.Body;
mail.IsBodyHtml =
true;

try
{
mail.Send();
}
catch (SmtpException)
{
throw new NotificationException();
}
}
}
}

NOTE: You can also try using AutoMapper to map to the MailMessage, but for whatever reason, it was not working out for me. I send Jimmy and email about it, but he’s busy enough and it’s not that big a deal to do the left=right thing every once in a while :)

My IEmailNotification looks like this:

public interface IEmailNotification
{
string To { get; }
string From { get; }
string Subject { get; }
string Body { get; }
}

I’ll show the implementation in a sec. First I wanted to show what the NotificationException looks like…

public class NotificationException : Exception
{
}

That’s it…I can adjust as needed, but for this…there’s no reason really. I just want to be able to catch the type in my controller. Yes you could do catch(SmtpException) in the controller, but what if your next implementation of INotificationService doesn’t use smtp and you have catch(SmtpException) spread all through your other code? It wouldn’t be a good thing. Let’s keep truckin…

Here’s the implementation of IEmailNotification:

public class EmailNotification : IEmailNotification
{
private readonly ContactView _view;

public EmailNotification(ContactView view)
{
_view = view;
}

public string To
{
get { return "email@email.com"; }
}

public string From
{
get { return _view.Email; }
}

public string Subject
{
get { return _view.Subject; }
}

public string Body
{
get { return _view.Message; }
}
}

You should pull email@email.com from some type of config file since it could potentially change often. What’s cool about this is that now I could have different versions for nighttime daytime or certain months or whatever…I don’t know why you’d ever do that, but it’s getting late and I can’t think of better examples :)

Anyhow…you can also customize the body here and not have to worry about formatting in your controller. You could do something like this for the Body:

public string Body
{
get
{
var body = new StringBuilder();
body.AppendFormat(
"Date Message Sent: {0}", DateTime.Now);
body.AppendFormat(
"Sent from IP: {0}", HttpContext.Current.Request.UserHostAddress);
body.AppendFormat(
"Browser Used: {0} v{1}", HttpContext.Current.Request.Browser.Browser,
HttpContext.Current.Request.Browser.Version);
return _view.Message;
}
}

I hope I didn’t leave anything out…if I did, please let me know!

Thanks for reading!


Shout it

kick it on DotNetKicks.com

Related Posts Plugin for WordPress, Blogger...