Showing posts with label jquery. Show all posts
Showing posts with label jquery. Show all posts

Tuesday, 21 February 2012

jQuery.NeatUpload – Examples refactored

jQuery.NeatUpload – Release 0.4

I’ve been using the jquery plugin for neatupload and the bugs keep coming up, well, that’s the developer’s life. Catching bugs is an ability that every developer must have and more than that, do not shame on, but be proud of.
This time I’ve improved the error handling when the server send as response some no comprehensive, for instance, there is a limit set in web.config for the maximum file size to upload and when the client attempts to send a file bigger than the limit, the server replies with some bizarre response.
As part of the mechanism implemented, it expects the HTML response for parse it and determine what to do, I mean, send information to the client indicating whether the request failed or not. Sometimes the HTML sent by the server was impossible to read because of some mysterious JavaScript error “Access denied”. I had no time for digging deeper in this matter, so I try-catch it and just a little extra setup in order to be consequent and ready. The release 0.4 can be downloaded here.

jQuery.NeatUpload – Examples refactored

In order to prepare for launch a new release of NeatUpload including these JavaScript features I’ve been doing some refactoring in the samples I published a few months ago. The first thing I’ll do is to apologize with the WebForms people, because I’ve let them in the road with the examples, just the part 1. Now the updated versions have both implementations WebForms and MVC3. Of course these new versions also have applied the bugfix mentioned above.
There’s something new in the web.config files, this time they are prepared for either IIS6 or IIS7+ and highly commented (well, this is questionable and relative to anyone’s need) every setting needed for set up NeatUpload even clarifying the confusing and inconsistent size units that Microsoft has implemented in both versions of IIS, they are in bytes and Kilobytes respectively.
Before describe what’s in these examples, I want to alert you about something that I’ve been dealing with many times and that has been cause of mysterious error in production scenarios. There is a setting in web.config that indicates the maximum time that IIS can wait before it shuts down the thread and return time out error. This is under and it’s expressed in seconds, this is especially useful when the files to be uploaded are really big.

What’s in the examples?

  • Default values: Shows how to use the minimum setup code and use the default values.
  • Changed Add and Upload texts: Shows how to change the texts for the elements that add and/or upload items rather than the default internal texts.
  • Changed Add and Upload elements: Shows how to change the default link for add and/or upload element by custom elements like buttons.
  • Custom cancel elements. Part 1: Shows how to change the cancel element by creating a simple new element inline and binding it to the internal click event.
  • Custom cancel elements. Part 2: Shows how to change the cancel element by cloning a complex element and binding it to the internal click event.
  • Start Upload Automatically: Show how to start automatically the upload without using a queue and adding one by one. This example uses just add element.
  • Show Progress Bar: Shows how to use a more cute visual feedback by styling up a progress bar that indicates the progress and changes the color if an error occurs.
  • Validating Data: Shows how to intercept the action of send the file to the server by performing validations to the associated data.
  • Sending extra Data: Shows how to send associated data along with the file by serializing it as JSON and how to receive it properly on the server.
à la prochaine mes amis!

Monday, 13 February 2012

Unobtrusive validation with dynamically created fields

Some time ago I started to take advantage of unobtrusive validation, one of the most important approaches for gaining cleanness in the resulting HTML. The way it works is, in a nutshell, as an adapter to the traditional jquery validation plugin, it searches through the HTML for every input element with data-val HTML5 attribute and value true, then it reads all possible validation rule, creates the rules element and finally calls to the validation plugin. This unobtrusive validation comes with the default template in MVC3 web projects using Visual Studio 2010.
Everything worked as expected when the entire HTML was generated from the server, I mean, as usually, using the HTML helpers such as @Html.TextBoxFor(...). Even if I’ve been working with AJAX, it worked as expected, just using a little tweak as I mentioned in this post.
Suddenly, a new scenario has arisen to the table. This time it’s necessary to validate elements dynamically created, client side only. When the page loads there are a lot of input with its data-* attributes properly rendered, but there is another set of input elements which will be created at runtime and therefore they must be validated as well. Until now there is no problem, isn’t it? Surprise if I tell it doesn’t work at all; it simply ignores these new elements created at runtime. But, what’s the difference? Previously I mentioned that it worked with AJAX, new content is added to the DOM. In fact, it works with AJAX. After digging a lot inside the source code and debugging, yes debugging and tracing! God bless these modern tools for doing this kind of work in JavaScript!
Long story short, the root of the problem is inside jquery validation plugin, and I think is not really a bug, but something that the plugin’s developer team did not think about. When the unobtrusive passes the data to the validator, this first checks in the internal cache using jQuery.data(...) and if anyone previously has passed the validation rules for this particular form, then it does nothing. What’s the problem? That is a good idea; do not perform the same task more than once. When using AJAX, in every test I’ve done there is an entirely new form that arrives from the server, this new form was not in the cache and that’s why it worked to me using AJAX. I show the exact code fragment where I found it.
 // check if a validator for this form was already created
 var validator = $.data(this[0], 'validator');
 if ( validator ) {
  return validator;
 }

 validator = new $.validator( options, this[0] );
 $.data(this[0], 'validator', validator);
 
But what if I add new elements dynamically to that form previously initialized with the validator plugin? That is not very bizarre, or maybe a little, anyway I think it should be considered. I found a quick and dirty workaround for solving my particular case. It consists in reset the internal validator’s cache by hand and then command unobtrusive to re-parse the form and Voilà!
 $.removeData(form[0], 'validator');
 $.validator.unobtrusive.parse(form);
 

I have prepared an example in order to demonstrate what I am saying is true. In the example I present a very simple login form using jquery validator and unobtrusive along with three buttons: (create new field, reset Validator Cache and Add new Form). How it works? The initial form is completely normal, just click the Login button and everything works as normal, the validators pop out with their messages. The code is here

Click the ‘create new field’ button and a new field appears and press Login again, this new field is not part of validation despite the fact it has properly configured the data-* attributes.

Now click the ‘reset Validator Cache’ button and click again Login button, Magic?! The new field is now part of the validation and we have a third validation message that wasn’t before.

Finally press the button ‘Add a new Form’ and an entire new form is created below, this form work as it should without remove anything from the cache.

I hope this experience which took me hours may help more people who wants to develop rich-client and a lot of JavaScript as today’s web application demands.

Wednesday, 1 February 2012

jQuery.NeatUpload - Release 0.3

A new bug has been detected in the jquery.neatupload plugin, the issue occurred if more than one tab opened in the same browser window tried to upload files in time overlapping. The effect was progress bars becoming crazy with the progress indications.
The cause was a naming collision with the postbackId parameter which identifies the current file being uploaded, the number always started by 1, so if two requests from the same browser send the same postbackId, the NeatUpload module doesn’t know who is who and the polls for display the progress show by moments the results of one and by moments the results of the other.
The solution, change the initialization value for the internal variable postbackId, this time helped by a random number and rounded for to eliminate the decimal comma separator, just esthetic. This change is applied to version 0.3 which can be downloaded here.

Thursday, 12 January 2012

Extending Unobtrusive AJAX behavior

One of the nice features that come with ASP.NET MVC 3.0 with no doubts is the addition of scripts for unobtrusive behavior regarding AJAX and validations. In this case I’ll refer to the AJAX mechanism using this technique. It allows you to write the least JavaScript code and achieve the partial update in a web page and it has a big plus, if JavaScript is disabled in the browser (or any other reason that prevents the js execution), no problem, everything continues working just without partial updates.
There are many scenarios where this is good enough for us and that’s all, write the server side code in the controller and the appropriate Html helpers using @Ajax setting up the target Id element to update after the remote call, maybe the “loading” element or even a confirm dialog in order to prevent unwanted post such as delete elements. The most classical example of this is the typical administration backend for any website where we have a list with a pager element at bottom (usually a table) and a form in another page with the details for edit the values.
Now, if you wish to make something a little different than previous example, the troubles start coming up. Imagine this simple scenario, a form with several fields ready to accomplish whatever task, if the operation succeeds then a partial update is performed below the form with more data to be entered and if the operation doesn’t succeed then another partial update is performed above the form showing the server errors. After this brief a little messy, the point is: there are more than one target id elements to update and only in the server this decision in taken; we don’t know how to specify the target id just declaring the Html helper.
My solution for this issue: conventions to the rescue!  I’ve made my own convention in this case. There is a script that is responsible of receiving all AJAX requests and inspects the content looking for the concrete target id and then it puts the content within the correct target id. I explain in detail, every partial view must have a hidden field with id = partialviewid and the value is the target id to be updated in the client. This solves the issue because we can have n partial views, each one referring to a different target, so in the controller it’s possible to do any sort of if-else statements and return the appropriate partial view in every case.
Let’s talk about the script that parses the content, it consists in a function that resides in a js file as any other and that is included by layout page after all unobtrusive formal scripts. It looks like this:
function receiveAjaxData(data) {

    var tempdiv = $("div[id=temporary-div-ajax]");
    if (!tempdiv.length) {
        $(document.body).append("<div id='temporary-div-ajax' style='display:none'></div>");
        tempdiv = $("div[id=temporary-div-ajax]");
    }

Here I ensure the temporary-div-ajax exists and is a body child, this is the place where the content that arrives from the server is put.
    tempdiv.html(data.responseText);
    var hidden = $("input[type=hidden][id=partialviewid]", tempdiv);
    var loadfunc = hidden.attr("data-function-load");

Then I find the hidden previously mentioned and if I had defined a function to execute is also grabbed here.
    if (hidden.length) {
        // Remove the hidden after to have taken its value
        var pvid = hidden.val();
        hidden.remove();

        // Place the content into the real target
        var destiny = $("#" + pvid);
        destiny.empty();
        destiny.append(tempdiv.children());
      
        // Re-parse the destiny node, in order to the validator work properly
        $.validator.unobtrusive.parse(destiny);

        // if function exists then evalute it
        if (loadfunc) {
            eval(loadfunc + "();");
        }
        return false;
    }
    return true;

If the hidden exists then proceed to place the content at real destiny, as you could have seen there is also the possibility of to specify the name of a function to be executed when the partial view is placed into the target, this is useful when we want to execute startup view-specific logic. One thing important here is the return value, if the result is true that means the jquery.unobtrusive engine continues as usually and if false then it stops and no more internal steps are executed.
How to use it? This question becomes usual, eh?
Include this script after all jquery.unobtrusive specific preferably in layout page.
In every partial view include:
<input id="partialviewid" type="hidden" name="partialviewid" value="target-id" />

In every Ajax action link or form, specify the AjaxOptions parameter
@Ajax.ActionLink("Create", "Create", null,
    new AjaxOptions { OnComplete = "receiveAjaxData"}
)

I hope this simple example to be useful for your day-to-day work without too much headache, till the next!

Friday, 30 December 2011

NeatUpload jQuery plugin – Examples – Part 3

In my last post I covered three scenarios where we changed the cancel the link element and start upload immediately. Well, let's continue tweaking, in this case the turn is for the user experience, I’ll show how to display a fancy progress bar while the upload operation is in progress, validate elements before send the file and even send extra data attached to the uploaded file. Let’s start.

Scenario 5 – Showing a fancy progress bar.

In all previous examples I have shown a simple number followed by a “%” symbol to indicate the progress, but I real life the user experience should be more than that, so all we are accustomed to is to see a progress bar increasing its size horizontally until the maximum width is reached, or tell me if I am crazy!? At least Graphical User Interfaces have used this pattern for years and it works. So if we intercept the moment when the file is added to the queue, it’s possible take the control and to construct everything necessary for display the progress. Let’s check the code:
<link href="@Url.Content("~/Content/progress.css")" rel="stylesheet" type="text/css" />

fnShowStatus: function (plugin, index, data) {
    $('table[id=tablequeue] > tbody > tr[data-neatupload-rowprog=' + index + '] div.progress-bar').width(data.PercentComplete + "%");
},
fnAddFile: function (plugin, filename, form, index) {
    var cancel = plugin.options.createCancelLink(plugin, index);
    var row1 = $("<tr data-neatupload-rowname='" + index + "' class='uploadItem-uploading'></tr>");
    var row2 = $("<tr data-neatupload-rowprog='" + index + "' class='uploadItem-uploading'></tr>");
    $('table[id=tablequeue] > tbody')
        .append(row1).append(row2);
    row1.append($("<td style='width: 80%'></td>")
        .append("<div class='uploading-video-name'>" + name + "</div>")
        .append("<div class='uploading-video-file-name'>" + filename + "</div>"))
    .append($("<td></td>"));
    row2.append($("<td></td>")
        .append($("<div class='barcontainer'></div>")
        .append("<div style='width: 0%' class='progress-bar'>")))
    .append($("<td class='cancel'></td>").append(cancel));
},
fnRemoveFile: function (plugin, index, reason, html) {
    var row1 = $('table[id=tablequeue] > tbody > tr[data-neatupload-rowname=' + index + ']');
    var row2 = $('table[id=tablequeue] > tbody > tr[data-neatupload-rowprog=' + index + ']');
    if (reason == "canceled") {
        row1.removeClass("uploadItem-uploading").addClass("uploadItem-canceled");
        row2.removeClass("uploadItem-uploading").addClass("uploadItem-canceled");
        $('div.progress-bar', row2).width("100%");
    }
    $("td.cancel", row2).html("<span>" + reason + "</span>");
}
<div>
    <table width="100%" class="uploadItem" id="tablequeue">
        <tbody>
        </tbody>
    </table>
</div>

The first this I remark here is the css inclusion, of course for achieve nice things it’s necessary a good inspiration, which I don’t have, I confess it, but something not so ugly it’s done with the css provided in the example, as usually you’re free to play with it.
Here is the same function we’ve overridden in last scenario, fnAddFile, which is executed right after the user clicks the button Add. The main idea with that amount of code is create tow table row for each file in the queue, the first for show the file name and the second the progress and the cancel element, previously discussed. Please note, we have used the internal function to create the cancel element whatever to be its implementation (overridden or default).
The function fnShowStatus this time with a little jquery magic finds the progress element and updates its width instead of write directly the percent value. Finally the function fnRemoveFile ad you can guess is responsible of remove the rows involved with the file to be removed, as an apart the parameters for this function: plugin is a reference to the plugin as usually, index is the identifier related to the current file in the queue, reason is a string indicating the reason of removing the current file (canceled or completed) and the html parameter give us the data returned by the server after finished the work. In this case we have checked if the reason is canceled then fill the width and a different color in the progress bar for tell to the user that that upload did not success.
At the end of the example we find a div with a table inside and this table has an id = tablequeue and an empty tbody, this is the placeholder for the rows created in runtime by the code previously explained.

Scenario 6 – Validating data before to perform the upload.

Sometimes we have a form with some data and the upload can be performed only if the form is consistent with some rules and even attach some data, but I let this for the next scenario. For verify these rules I understand (and I think you too) to validate the input fields. Surprisingly I’ve anticipated this kind of behavior and there is a function that may be overridden whose name is fnValidate and receives a plugin object reference as parameter. Inside this function body you are able to use any validation engine such as jquery.validate or whatever you want, for didactic purposes I just made a very simple validation.
(...)
fnValidate: function (plugin) {
    var valid = $("#name").val() && $("#age").val();
    if (!valid) alert("Incorrect Data!");
    return valid;
}
(...)
<div>
    <label for="name">Name</label>
    <input id="name" name="name" type="text" value="" />
</div>
<div>
    <label for="age">Age</label>
    <input id="age" name="age" type="text" value="" />
</div>

As you can see, all I’ve done is test if the value of the name and age fields are not empty, in case of at least one of them is empty an alert box is shown. The rest of the plugin expects if you override this function to return true if everything is ok and false if there is something wrong with the input data.

Scenario 7 – Start upload immediately.

Sometimes we have to send some data to the server attached to the file, for example metadata associated to the file being uploaded, for solve this issue we can make a little trick in the fnAddFile function before send the data. We can gather the data and helping with the JSON object which is capable of serialize any JavaScript object into a string, and then that string is added to the form that actually send to file to the server. Remember that each file sent to the server is an actual POST with an actual form. In this case that form is received by parameter and it’s simply to create a new element, the ideal form field is the hidden field for this task and that’s what I do in the following code.
fnAddFile: function (plugin, filename, form, index) {
    var name = $("input[id=name]").val();
    var age = $("input[id=age]").val();
    $("input[id=name]").val("");
    $("input[id=age]").val("");
    var data = JSON.stringify({ name: name, age: age });
    $("<input type='hidden' name='filedata' value='" + data + "' />")
         .appendTo(form);
},
fnRemoveFile: function (plugin, index, reason, html) {
    alert(html);
}

@Html.Hidden("upload-action", Url.Action("UploadFileExtraData"))

The function fnRemoveFile that we used in the previous scenario, this time just show up with an alert box the html parameter, with the data returned by the server in the controller action that receives the post with the files. Please note here that I show the hidden field which saves that action, and note that is different than the previous scenarios, this time there’s something to do also in server side.
[HttpPost]
public ActionResult UploadFileExtraData(FormCollection collection)
{
    var tempPath = Server.MapPath("~/_temp_upload/");
    var value = string.Empty;
    for (var i = 0; i < UploadModule.Files.Count; i++)
    {
        value = UploadModule.Files[i].FileName;
        UploadModule.Files[i].SaveAs(tempPath + value);
        var data = collection["filedata"];
        var serializer = new JavaScriptSerializer();
        var deserializeObject = (Dictionary<string, object>)serializer.DeserializeObject(data);
        var name = (string)deserializeObject["name"];
        var age = (string)deserializeObject["age"];
        value = "Name = " + name + ", Age = " + age;
    }
    return Content(value);
}
I just show the controller action code (sorry webforms people, but don’t worry it’s the same in essence), this time there is a bit more of code in server side than previously. First thing new is to get from the collection, well it’s the same that take it from Request.Form[“…”], the important thing here is that we follow a convention the name filedata must match with the name we gave to the hidden field we created on the fly in fnAddFile and that’s why I marked in yellow background. The rest is simply deseralize it with the .NET powerful tools for that and finally store in the variable value the demonstrative string with the values extracted from the metadata and returned to the client.
Well, I think it’s all for the moment regarding the jquery.neatupload plugin. I hope this information to be useful for you. Any comment, feedback or even suggestion for improve it will be welcome. I’ll come back with some ASP.NET MVC 3 tricky features soon.
So Happy New Year to every one!

Monday, 26 December 2011

I just moved to bitbucket.org hosting site

As any follower of the jquery plugin website, I have to say I am disappointed and at the same time I understand them, with that situation, there was no choice. If you don’t know what I am talking about, check this and come back to read.
Well, the fact is that in the meantime I just packed my bags and moved to bitbucket.org, I have to admit it, GitHub was a great candidate but if I had to choose between Git and Mercurial, I’d choose Mercurial, it’s something personal, I have nothing against Git, in fact I am a Phil Haack fan.
The new link for download the latest version of jquery.neatupload is https://bitbucket.org/abelperezok/jquery.neatupload/ of course, the previous link hosted in google docs still works, so don’t worry.

Friday, 16 December 2011

NeatUpload jQuery plugin – Examples – Part 2

In my last post I covered two scenarios where we changed the texts and the elements for the actions add and upload. Well, let's continue with these changes, in this case the turn is for the link of cancel operation. It's a bit more complex than the others, that's why I've let for another post, but no so hard to do.
Scenario 3 – Changing the cancel link.

Due to the fact the cancel link has a special function and is intended for call an internal function, it’s required that the custom cancel element to call sendCancel function on its click event. This function can be accessed through plugin parameter and options object. Let’s check the code:

@{
    // get the text from wherever i.e. some i18n service in the application
    var textAdd = "Add a file to upload list";
    var textUpload = "Start Upload";
    var textCancel = "Abort Operation";
}
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.neatupload.js")" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
    $(function() {
        $("#file1").neatupload({
            postDataUrl: $("input[type=hidden][id=upload-action]").val(),
            fnShowStatus: function (plugin, index, data) {
                $('span#progress-file').text(data.PercentComplete + "%");
            },
            textCancel: "@textCancel",
            selectorButtonAdd: "input[name=addfile]",
            selectorButtonUpload: "input[name=uploadfile]",
            createCancelLink: function (plugin, index) {
                var cancel = $('<div>' + plugin.options.textCancel + '</div>')
                        .click(function () {
                                                plugin.options.sendCancel(plugin, index);
                        });
                return cancel;
            }
        });
    });
</script>

@using(Html.BeginForm("UploadFile", "Home"))
{
    @Html.Hidden("upload-action", Url.Action("UploadFile"))
    <div>
        @Html.Label("newfield", "Select File: ")
        <div id="file1">
            place holder for the input -> file for upload
        </div>
        <input type="button" name="addfile" value="@textAdd" />
        <input type="button" name="uploadfile" value="@textUpload" />
    </div>
    <div>
        <span id="progress-file"></span>
    </div>
    <div>
        <input type="submit" value="save"/>
    </div>
}
Here is a new parameter introduced in the last release: createCancelLink, which corresponds to a function with 2 parameters: plugin and index.
·         plugin is a reference to the current plugin element and is used for access the functions with the current data.
·         index is the unique identifier for the current file being queued for upload.
In the example just created a “div” element with a custom text and set the click event to an anonymous function which calls to plugin.options.sendCancel(plugin, index); and that’s the key point, through plugin.options it’s possible access to functions declared as public in the plugin (as in any other jquery plugin). The current values of plugin and index are passed to sendCancel internal who is responsible for send a “cancel” message to the server and stops the internal frame (in case of upload is in progress).

Scenario 3.1 – Changing the cancel link using a more complex DOM element.
In the previous example I demonstrated how to change the element cancel, and that works will if this element is very simple (as in the example, of course), but what if we have an element previously created in the page? I suggest this code fragment for solve it.

(...)
createCancelLink: function (plugin, index) {
    var cancel = $("input[name=cancelupload]").clone();
    cancel.show().click(function () {
        plugin.options.sendCancel(plugin, index);
    });
    return cancel;
}
(...)
<input type="button" name="cancelupload" value="@textCancel" style="display: none" />

Here I have an input button named “cancelupload” hidden by default using inline style and this will be the element chosen for cancel. The first is get it via query (remember, we are using jquery so take all advantages) and make a clone, then show it and finally assign the click function for the event handler like the previous example.
Scenario 4 – Start upload immediately.
Sometimes we don’t want the user follow the two steps: add and upload, This is useful for applications where the user only upload one file at time, for example: attach a file in a webmail interface, set up a profile logo image, etc. I have a solution for that and I show you as follows:

fnAddFile: function (plugin, filename, form, index) {
    $(plugin.options.selectorButtonUpload).click();
}

I introduce you a new parameter fnAddFile, this is a function that is called when a new file is going to be added to the queue. By default this function renders a visual element where we can see the cancel element, the name of the file being queued and a placeholder for the progress element.

In this case I have overridden this default behavior and I just call the click event of upload button element using the plugin.options.selectorButtonUpload parameter previously explained, I know that could be called as a little dirty but I think is valid, if we already have defined a button and its click event with a lot of work done, why not call it and go? At least this is my concept of reuse of code.

Well, I think it’s all for today, in the next post I’ll talk the third group of scenarios for use this plugin, which include personalizing the user interface using a more cute progress bar and more use of the uploaded file in server side. I hope this information to be useful for you. The source code for this example is available here.

Thursday, 17 November 2011

jQuery.NeatUpload - Release 0.2

A small change in jquery.neatupload plugin
While I was trying to explain to my friend how to use the plugin, exactly how to change the element that represents the link for the cancel operation in the queue, I discovered that I had an internal function that should be linked to options object inside the plugin.That was the cause of a new release. This time will it be possible to call the sendCancel internal function and previously it wasn’t possible to make it.
So, this is a kind of change log for the release 0.2, which you can download here.
In the next post I’ll cover in detail how to change many other things while using jquery.neatupload beginning of course with the cancel stuff.

NeatUpload jQuery plugin – Examples – Part 1

Sorry for the delay but it’s been a busy month, well, in my previous post I promised some examples in different scenarios on how to use the plugin. So, let’s start with the simplest scenario:

Scenario 1 – Using default functionality and default visual appearance.
The basic structure is:
$(function() {
    $("#file1").neatupload({
        postDataUrl: "path/to/the/server/",
        fnShowStatus: function (plugin, index, data) {
            // handle the data progress values in order to make some visual feedback.
        }
    });
});

Here, we have the two essential parameters:
·         postDataUrl, the path for the elements in server side who is going to handle the POST.
·         fnShowStatus, in fact, this is not a required parameter but this function is ideal to keep visual feedback of uploading process, and here we have three parameters in the function:
o   The plugin object, available for call any function.
o   The file index, usually used for keep track on which file is, it is increased each time an upload in queued.
o   The data, JSON object with useful data for show on screen, such as: status, percent, speed, etc. Here is an example.
{
"Status":"Completed",
"BytesRead":806688,
"BytesTotal":806688,
"PercentComplete":100,
"BytesPerSec":12927672,
"Message":"",
"SecsRemaining":0,
"SecsElapsed":0,
"CurrentFileName":" picture01.jpg",
"ProcessingState":null,
"Files":
[
{
"ControlUniqueID":"fileField",
"FileName":"picture01.jpg",
"ContentType":"image/jpeg",
"ContentLength":806466
}
]
}

In the previous examples I’ve done something like this: 
$(function() {
        $("#file1").neatupload({
        postDataUrl: $("input[type=hidden][id=upload-action]").val(),
        fnShowStatus: function (plugin, index, data) {
            $('span#progress-file').text(data.PercentComplete + "%");
        }
    });
});

In this case, the only thing we are doing is get the percent complete each time the internal timer-scheduled poll returns a value and display it in a prepared span. That may look good, but What if I don’t like the add link or the upload link? Or what if I want change these texts?

Scenario 2 – Modifying the links ‘add’ and ‘upload’.
The last thing I want users to be is tied to defaults, let’s start by changing the texts for the actions add and upload. I’ll introduce you three new plugin parameters:
·         textAdd: Text for the link Add
·         textUpload: Text for the link Upload
·         textCancel: Text for the link Cancel
Sometimes we have to produce applications that are going to be viewed by people from different cultures and languages, so the static texts are not an option for these cases, and that’s why I let open the text for these links. In the example I use a simple way to change the texts, but I want you to realize the power of this choice.

@{
    // get the text from wherever i.e. some i18n service in the application
    var textAdd = "Add a file to upload list";
    var textUpload = "Start Upload";
    var textCancel = "Abort Operation";
}
(...)
<script type="text/javascript" defer="defer">
    $(function() {
        $("#file1").neatupload({
            postDataUrl: $("input[type=hidden][id=upload-action]").val(),
            fnShowStatus: function (plugin, index, data) {
                $('span#progress-file').text(data.PercentComplete + "%");
            },
            textAdd: "@textAdd",
            textUpload: "@textUpload",
            textCancel: "@textCancel"
        });
    });
</script>

Another way for changing these links and not just the texts is through other two parameters, this time they replace the entire ‘a’ element by whatever you specify to. They are:
·         selectorButtonAdd: jQuery selector indicating how to get the DOM element that will click for the add action.
·         selectorButtonUpload: jQuery selector indicating how to get the DOM element that will click for the upload action.

This time the parameters regarding the text for add and upload will be ignored, if you change the element, you are responsible for give them their own text using any strategy. So the example is as follows:
@{
    // get the text from wherever i.e. some i18n service in the application
    var textAdd = "Add a file to upload list";
    var textUpload = "Start Upload";
    var textCancel = "Abort Operation";
}
(...)
<script type="text/javascript" defer="defer">
    $(function() {
        $("#file1").neatupload({
            postDataUrl: $("input[type=hidden][id=upload-action]").val(),
            fnShowStatus: function (plugin, index, data) {
                $('span#progress-file').text(data.PercentComplete + "%");
            },
            textCancel: "@textCancel",
            selectorButtonAdd: "input[name=addfile]",
            selectorButtonUpload: "input[name=uploadfile]"
        });
    });
</script>
(...)
<input type="button" name="addfile" value="@textAdd" />
<input type="button" name="uploadfile" value="@textUpload" />

The source code is available here.