Archive

Archive for the ‘Spark View Engine’ Category

Reusable ‘Controls’ with Sprites, CSS, and Spark Partials

October 2, 2009 Comments off

I came across SilkSprite during some of my work with BluePrintCSS and fell in love.  I’ve used the FamFamSilk icons for ages and, with a current project, wanted to implement some instant CSS buttons and menu items using those icons.

So, with CSS-fu in hand, here’s how the button turned out.

First, creating a simple CSS button style:

.button

{

    display: inline-block;

    font-weight: bold;

    font: bold .85em/2.5em Verdana, Helvetica, sans-serif;

    text-decoration: none;

    text-indent: 10px;

    width: 150px;

    height: 2.5em;

    color: #555555;

    background-color: #EAEAD7;

    border: #CCCCCC solid 1px;

    -moz-border-radius: 5px;

    -webkit-border-radius: 5px;

}

 

.button:hover

{

    background-color: #F3F3E9;

    color: #737373;

    cursor: pointer;

}

This button is pretty simple and standard—nothing fancy.  The most important tag in there is display: inline-block as this allows our buttons to share the same row and not stack on top of each other (like float:left would cause).

Hover Off: CSS Button - Hover Off

Hover On: CSS Button - Hover On

Second, because I needed to include the icon INSIDE another container (the button), I modified the original SilkSprite ss_sprite and removed a bit of the extra padding.

.sprite

{

    display: inline-block;

    overflow: hidden;

    background-repeat: no-repeat;

    background-image: url(/content/img/sprites.png);

    padding-left: 25px;

    padding-top: 2px;

    height: 16px;

    max-height: 16px;

    vertical-align: middle;

}

The important thing to note here is the padding-top and the height attributes.  Until I’m lead into the light and improve my CSS-fu, I’m compensating for the font height differences by using padding-top.  e.g. I want the icon to truly show up in the “middle”… and vertical-align just wasn’t pushing it far enough.

We’ll come back to actually working with SilkSprite in a moment, let’s work up a quick Spark partial view to display our results.  Now, you could do this without the partial views—just replace my Spark variables with the actual text we’re passing to them.  I’ll provide both examples.

Our button needs three elements to be useful:

  1. An ID so that we can call it from jQuery or your client-side query engine of choice,
  2. A Sprite Name, such as ss_add, etc.  These are provided by SilkSprite.
  3. The button text.

So, knowing that, a basic button could be rendered using:

<div id=”my-button” class=”button”>

    <span class=”sprite ss_add” />Add Activity

</div>

We can simply substitute out the variable elements (id, sprite class, and text) and create a Spark partial view (named _styledButton.spark and located in the /Shared view folder).

<div id=”${id}class=”button”>

    <span class=”sprite ${sprite}“></span>${text}

</div>

In our views, it’s easy to create a button:

<styledButton text=”‘Add Activity‘” id=”‘my-button‘” sprite=”‘ss_page_add‘” />

Note: You need to surround your text with single quotes (‘text’) to inform the Spark engine that the information contained in your variables is a string.

Now, we have shiny, icon’d buttons:

Hover Off:

Hover On:

Categories: HTML, MVC, Spark View Engine

Populating Select Lists in ASP.NET MVC and jQuery

September 25, 2009 Comments off

I’ve been working the last bit to find the best way to create/populate select (option) lists using a mixture of ASP.NET MVC and jQuery.  What I’ve run into is that the “key” and “value” tags are not passed along when using Json(data).

Here’s what I’m trying to pull off in jQuery: building a simple select drop down list.

var dd_activities = “<select id=’dd_activities’>”;
var count = data.length;
for (var i = 0; i < count; i++) {
 dd_activities += “<option value='” + data[i].Key + “‘>” + data[i].Value + “</option>”;
}
dd_activities += “</select>”;

$(“#activities”).before(dd_activities);

Using some very basic key/value data:

[
 {“3″,”Text Value”},
 {“4″,”Another Text Value”},
 {“1″,”More boring values…”},
 {“2″,”Running out of values”},
 {“5″,”Last value…”}
]

Without any sort of name, I was at a loss on how to access the information, how to get it’s length, or anything.  FireBug was happy to order it up… but that didn’t help.
 
My first attempt was to use a custom object, but that just felt dirty—creating NEW objects simply to return Json data.
 
My second attempt matched the mentality of newing new anonymous Json objects and seemed to work like a champ:
 

[Authorize]

[CacheFilter(Duration = 20)]

public ActionResult GetActivitiesList()

{

    try

    {

        var results =

        _activityRepository

            .GetAll()

            .OrderBy(x => x.Target.Name).OrderBy(x => x.Name)

            .Select(x => new

                {

                    Key = x.Id.ToString(),

                    Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

                })

            .ToList();

 

        return Json(results);

    }

    catch (Exception ex)

    {

        return Json(ex.Message);

    }

}

 
Well, not beautiful, but returns a sexy Key/Value list that Json expects—and that populates our select list.
[
 {“Key”:”3″,”Value”:”Text Value”},
 {“Key”:”4″,”Value”:”Another Text Value”},
 {“Key”:”1″,”Value”:”More boring values…”},
 {“Key”:”2″,”Value”:”Running out of values”},
 {“Key”:”5″,”Value”:”Last value…”}
]
The next step was to get that out of the controller and into the data repository… pushing some of that logic back down to the database.
 

var criteria =

    Session.CreateCriteria<Activity>()

    .CreateAlias(“Target”, “Target”)

    .Add(Restrictions.Eq(“IsValid”, true))

    .AddOrder(Order.Asc(“Target.Name”))

    .AddOrder(Order.Asc(“Name”))

    .SetMaxResults(100);

 

var data = criteria.List<Activity>();

var result =

    data

        .Select(x => new

            {

                Key = x.Id.ToString(),

                Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

            })

        .ToList();

tx.Commit();

return result;

 
A bit of formatting, restrictions, push the ordering back to the database, and a tidy SQL statement is created.
 
The last touch is the return type.  Since we’re returning a “List” of anonymous types, the return type of GetActivitiesList() must be an IList.
 
That shrinks down my ActionResult to a single call.
 

try

 {

     return Json(_activityRepository.GetActivitiesList());

 }

 catch (Exception ex)

 {

     return Json(ex.Message);

 }

 
That works… and will work for now.  Though, I’ve marked it as a HACK in my code.  Why?  I’m honestly not sure yet.  Just a feeling.

Html.Grid Rendering as Plain Text?

September 23, 2009 1 comment

Notice: Stupid, stupid moment described ahead.  Proceed with caution.

I spent a good half hour trying to figure out why my MVCContrib Html.Grid<T> wasn’t rendering.  It wasn’t throwing an error, it was simply returning the HTML code as Plain Text.

  • The AutoMapper code looked good,
  • The Html.Grid<T> code looked good (it’d be templated off another page anyway and that page was working),
  • The view model code looked good.

So why was I being greeted with garble junk?

${Html.Grid(Model.Details) .Attributes(Id => “RoutineDetails”) .Columns(column => { column.For(c => this.Button(“EditDetail”).Value(“Edit”).Id(string.Format(“edit_{0}”, c.Id))).DoNotEncode(); column.For(c => c.Activity.Target.Name).Named(“Target Area”); column.For(c => c.Activity.Name).Named(“Activity”); column.For(c => c.Sets); column.For(c => c.Weight); column.For(c => c.Repetitions); column.For(c => c.Duration); })}

Html.Grid that is not… well, at least not properly.

Encoding issue? Maybe. Data issue? Perhaps.

No, the issue was typing too quick and not paying attention.

public ActionResult New()

 {

     var viewModel = BuildRoutineNewViewModel(new Routine());

     return View();

 }

Yeah, that’s the problem… right there.  I’d forgotten to pass the view model into the View.  Apparently the Html.Grid<T> helper simply panics if the model you’re reading from is empty or null—rather than throwing an error.

Oddly enough, this is one of those times I’d wish the screen would have lit up red.  Lessons learned.