Load jQuery Accordion from AJAX call

Today I needed to load a massive amount of text into dropped-down section on the page. And it was unlikely that users will expand that section, so no point in loading a huge load of data until it is needed. That is AJAX is for, isn’t it?

Here is the HTML for the Accordion:

<div class="accordion-ajax" data-url='/path/to/get/text/from'>
    <div class='accordion-head'>
       This is visible text to be presented for clicking
    </div>
    <div><!--This is required: it will be filled in with body of accordion when it is expanded--></div>
</div>

And here is the JavaScript code:

    $('.accordion-ajax').accordion({
        collapsible: true,
        active: false,
        clearStyle: true,
        autoHeight: false,
        header: '.accordion-head',          // point to the class that is used as a header
        heightStyle: 'content',
        icons: false,
        beforeActivate: function (event, ui) {
            var self = $(this); 

            // this bit is tricky. Make sure you have no empty space in the body of drop-down 
            if (ui.newPanel.html() == '') {         
                // taking data-url parameter from accordion header div
                // and load the returned contents into the accordion body.
                // presuming HTML is returned. 
                ui.newPanel.load(self.data('url'));
            }
        }
    }); 

See more details on API in jQuery Accordion API

jQuery Unobtrusive Validation of dates in Chrome: US vs GB format

UPDATE 31 Jan 2013: We have encountered this issue after we have updated our MVC3 project to MVC5. A year ago we have moved MVC3 to MVC4. And suddenly Chrome started to insist on incorrect date format, but everywhere else we have set Globalise locale to be en-Gb. The only other alternative was to disable date validations which can also work – I trust server side validation more than I trust JavaScript ;-)


Today I came across the magical problem in Chrome – it ignores locale information for date format. So it always uses US format: “mm/dd/yyyy”. But largest part of the world is not using this messed up month-first approach (wink-wink).

Continue reading

Ellipsis on long text in the table.

Sometimes you would like to shorten your long text in the HTML table. Here is the way to go with css and jQuery: css:

<table>
  <tr>
    <td class="ellipsis">
      Some very long text that you would like to be shortened
    </td>
  </tr>
</table>

CSS:

td.ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 300px
}

jQuery:

$('.ellipsis').each(function (index) {
    var $this = $(this);
    var titleVal = $this.text();
    if (titleVal != '') {
        $this.attr('title', $.trim(titleVal));
    }
});

ASP.Net MVC: Autosave drop-down with notification

I did spend quite a time figuring out jQuery verbs to do just what I needed. So I’ll share this with my blog and possible readers. On my view I had a model written out, some other stuff, but here I’m only interested in DropDown and JavaScript bits:

@Html.DropDownListFor(m => model.tagId, new SelectList(ViewBag.Tags, "Value", "Text", model.tagId), new {@class = "document-category", data_id = model.modelId})

where

ViewBag.Tags was populated in controller like this:

ViewBag.Tags = _tagRepository.All
    .OrderBy(t => t.Name)
    .Select(t => new { Text = t.Name, Value = t.TagId.ToString() })
    .OrderBy(t => t.Text)
    .ToList();

Back to the view. Added JavaScript like this one:

$(document).on("change", ".document-category", function () {
    var select = $(this);
    $.ajax({
        type: "POST",
        url: "@(Url.Action("Action", "Controller"))",
        data: { id: select.data("id"), 
        tagId: $("option:selected", select).val()},
        error: function () {
            select.after("Error occurred");
        },
        success: function (data) {
            if (data.Success === true) {
                select.after(function () {
                    return $('<div> Saved </div>').delay(1000).fadeOut(1000);
                });
            } else {
                select.after("Error occurred");
            }
        }
    });
});

The very first line can be replaced by $(".document-category").change(function(){ but this time I had to deal with other java-script library that was stripping-bare my stuff. On the other end of the ajax request you need to put controller action:

[HttpPost]
public virtual JsonResult Action(int id, int? tagId)
{
        //blah, do some update stuff
    return Json(new {Success = true, Message = "Updated"});
}