Posts tagged ‘jquery’

I recently started writing a webpage where I wanted some information pre-loaded, without the delay of making an ajax call! What I had was the classic case of the content of one drop down list being controlled by another drop down list.

So, in my controller I loaded up all the data into my model …

public class MyController : Controller
{
    private readonly IMyRepository _myRepository;

    public MyController(IMyRepository myRepository)
    {
        _myRepository = myRepository;
    }

    [HttpGet]
    public ActionResult MyAction()
    {
        var parentList = _myRepository
            .GetParentList()
            .ToList()
            .Select(x => new SelectListItem
                              {
                                  Value = x.ID.ToString(),
                                  Text = x.Description,
                                  Selected = false
                              })
            .ToList();

        var childList = _myRepository
            .GetChildList()
            .ToList()
            .AsQueryable();

         var model = new MyViewModel
                         {
                             ParentList = parentList,
                             ChildList = childList
                         };

        return View(model);
    }
}

The GetChildList() method returns a list of items which have a ParentID

This is what my view looks like …

@model MyViewModel

<div class="MyViewClass">
    <h2>Parent/Child Example using jQuery Linq</h2>

    <label for="ParentList">Parent Item</label>
    @Html.DropDownListFor(model => model.ParentList, null, "Please select a Parent item ...", new { @class = "test" })

    <label for="ChildList">Child Item</label>
    <select id="ChildList"></select>
</div>

and finally, here is the javascript (which is also in the view) …

var children;
$(document).ready(function() {
    children = @Html.Raw(Json.Encode(Model.ChildList)) ;

    $('#ParentList').change(ParentChanged);
});

function ParentChanged() {
    var parentID = parseInt($('#ParentList').val(), 10);
    var childItems = $.Enumerable.From(children)
        .Where(function(x) { return x.ParentID == parentID })
        .Select(function(x) { return { value: x.ID, text: x.Description } })
        .ToArray();
    var html = "<option id='-1'>(All Items)</option>";
    $.each(childItems, function(index, value) {
        html += "<option value='" + value.value + "'>" + value.text + "</option>";
    });
    $('#ChildList').empty().html(html);
}

So, all the work is done in the web browser. The dataset is relatively small so shouldn’t cause any memory issues. Obviously for larger datasets using ajax is the way to go, but for this particular case this solution works great.

I am in the process of writing a website which has quite a few graphics in them, so I figured it would be nice to just have them all in one PNG file. Which has the nice side effect of reducing the number of requests to my web server.

I came up with (what I think) is a nice piece of javascript and jQuery code to display the images…

HTML

This is the html, which is pretty simple. For the sake of completeness, I have left in a little d-pad imagemap which forms part of the page. The script doesn’t do anything with the imagemap part of the page.

<div class="commands">
    <span class="command back"></span>
    <span class="command info"></span>

    <map id="d-pad" name="d-pad">
        <area shape="circle" coords="200,200,80" onclick="Command('ok');" />
        <area shape="rect" coords="158,14,244,104" onclick="Command('up');" />
        <area shape="rect" coords="158,290,244,380" onclick="Command('down');" />
        <area shape="rect" coords="14,150,102,238" onclick="Command('left');" />
        <area shape="rect" coords="296,150,386,238" onclick="Command('right');" />
    </map>
    <image class="dpad" src='<%= ResolveUrl("~/Content/Images/d-pad.jpg") %>' alt="Site map" usemap="#d-pad">
        <span class="command play"></span>
        <span class="command pause"></span>
        <span class="command stop"></span>
        <span class="command volup"></span>
        <span class="command voldown"></span>
        <span class="command volmute"></span>
    </image>
</div>

The Javascript

Firstly, I set the css for all my “buttons”. The reason for doing the background-image this way is to work around a bug in safari on the iPad.

$(document).ready(function () {
    var buttonsFilename = '< %=ResolveUrl("~/Content/Images/Buttons.png") %>';

    $('.commands .command').css({
        background: 'url(' + buttonsFilename + ')',
        width: '55px',
        height: '55px',
        display: 'inline-block',
        'margin-right': '30px'
    });

Next I set up an array of x-offsets for my images. I got these numbers by loading up my image in Paint.NET and placing my cursor on the left of the desired bit of the image and prefixing a minus sign on the front. All my “buttons” are the same size, so I can set the width and height attributes here too.

var offsets = {
    play: -357,
    pause: -488,
    stop: -425,
    volup: -75,
    voldown: -9,
    volmute: -146,
    back: -888,
    info: -1016
};

The next step is to look through each of the command elements and set the background-position and also wire up a click event handler. It simply uses the index of the array. All javascript objects are effectively associative arrays, so I can simply iterate through the offsets object using the index to find the command element based on the css class. I can also use the index to pass in to the Command javascript function.

$.each(offsets, function (index, value) {
    $('.commands .' + index)
        .css('background-position', value + 'px -2px')
        .click(function () {
            Command(index);
        });
    });
});

The Javascript (in it’s entirety)

function Command(command) {
    $.ajax({
        url: '< %=ResolveUrl("~/Home/Command/")%>',
        type: 'POST',
        data: {
            command: command
        }
    });
}

$(document).ready(function () {
    var buttonsFilename = '< %=ResolveUrl("~/Content/Images/Buttons.png") %>';

    $('.commands .command').css({
        background: 'url(' + buttonsFilename + ')',
        width: '55px',
        height: '55px',
        display: 'inline-block',
        'margin-right': '30px'
    });

    var offsets = {
        play: -357,
        pause: -488,
        stop: -425,
        volup: -75,
        voldown: -9,
        volmute: -146,
        back: -888,
        info: -1016
    };

    $.each(offsets, function (index, value) {
        $('.commands .' + index)
            .css('background-position', value + 'px -2px')
            .click(function () {
                Command(index);
            });
    });
});

So, I can now easily add new buttons into my page by tacking them on the end of my wide image and adding the name to the offsets object.