Tag Archives: JavaScript

Error subclasses may lose their message property

You have probably already seen a code like this:

try {
  throw new Error('Oh, nooooo!');
} catch (e) {
  console.log(e.message);            // Oh, nooooo!
  console.log(e instanceof Error);   // true
}

If you create many of those blocks, sooner or later you will decide that you are going to use custom error classes, even in JavaScript. It may seem to be a great idea to implement them this way:

function OhNoooError() {
  Error.call(this, "Oh, nooooo!");
  this.name = "OhNoooError";
}

But you may be surprised by the results:

try {
  throw new OhNoooError();
} catch (e) {
  console.log(e.message);                 // undefined
  console.log(e instanceof OhNoooError);  // true
  console.log(e instanceof Error);        // false
}

So the error you catch is not a classic error (does not inherit from the Error base class), and it does not have a message property! Oh, nooooooooooo!

Here is one way to fix it:

OhNoooError.prototype = Object.create(Error.prototype);
OhNoooError.prototype.constructor = OhNoooError;

function OhNoooError() {
  this.message = "Oh, nooooo!";
  this.name = "OhNoooError";
}

And now you have a much nicer output:

try {
  throw new OhNoooError();
} catch (e) {
  console.log(e.message);                 // Oh, nooooo!
  console.log(e instanceof OhNoooError);  // true
  console.log(e instanceof Error);        // true
}

The point is that you have to set the message property explicitly in the derived class – even if you use the extends keyword in CoffeeScript to do the inheritance magic.

 

Technorati-címkék: ,
Advertisements

Using any file type in the file save picker

In Windows 8 you can easily configure the File Open Picker to allow the user to select a file with any type – just use the well-known asterisk:

var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.fileTypeFilter.replaceAll(["*"]);

You can try the same with the File Save Picker as well:

var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.fileTypeChoices.insert("Any", ["*"]);

However, this raises a runtime error:

0x80070057 – JavaScript runtime error: The parameter is incorrect.

WinRT information: This file picker does not allow the all files extension.

Fortunately there is a nice hack to force the File Save Picker to allow any file type:

savePicker.fileTypeChoices.insert("Any", ["."]);

Technorati-címkék: ,,,

Ajax file upload

Sometimes it would be useful to upload a file to a website while the rest of the page remains unchanged, so with Ajax. I’ve got bad news for you: the Level 1 version of the XMLHttpRequest object doesn’t support that, so if you must support older browsers, you need some tricks.

One of the most widely used tricks is using an iframe, however in that case the results from the server (for example the validation errors) are also delivered to the iframe. So if you work with a hidden iframe and you need the result in client-processable way in JavaScript, you have to dig it from the iframe. Fortunately the jQuery Form Plugin can help you to solve these issues.

First, create a view-model on the server, in which a HttpPostedFileBase property represents the uploaded file. I’ve also added a Name property for demonstration purposes:

public class UploadVM
{
    [Required( ErrorMessage = "Please enter a name!" )]
    public string Name { get; set; }

    [Attachment]
    public HttpPostedFileBase Attachment { get; set; }
}

The [Attachment] is the file validation attributed I presented in an earlier post. It checks whether the file is submitted, and also checks the extension and the size of the file.

For this model you can create a form that submits the file and the provided name:

@using( Html.BeginForm( "Index", "Home", FormMethod.Post, 
        new { id = "myForm", enctype = "multipart/form-data" } ) )
{
    <p>
        <label for="txtName">Name:</label>
        <input type="text" id="txtName" name="Name" />
    </p>

    <p>
        <label for="fupAttachment">File:</label>
        <input type="file" id="fupAttachment" name="Attachment" />
    </p>

    <p>
        <input type="submit" value="Upload" />
    </p>    

    <div id="errors"></div>
}

It’s important that the form must have an enctype attribute with multipart/form-data value, because that supports file upload. I also created a div with errors id, which will host the error messages.

This form posts to the Index action of the HomeController which can be implemented like this:

[HttpPost]
public ActionResult Index( UploadVM model )
{
  if( !this.ModelState.IsValid )
  {
    string firstError = ModelState.First( m => m.Value.Errors.Any() )
.Value.Errors[ 0 ].ErrorMessage;
return this.FileUploadFailure( firstError ); } // Process the file here string message = String.Format( "The file '{0}' is successfully uploaded.",
model.Name );
return this.FileUploadSuccess( message ); }

If there is any validation error in the view-model, the runtime adds them to the ModelState thanks to the attributes. Just as always the ModelState is check in the beginning of this method, and if there is any error an error message is returned, if not, then the file is processed and a success message is returned to the client.

The returned value is a JSON object, because that comes really handy on the client. But don’t forget, that it will land in an iframe, and not every browser tolerates an application/json result in iframes. Fortunately the jQuery Form Plugin supports a simple hack: just wrap the result into a <textarea> element and send it back in a text/html response, the plugin will do the rest.

To simplify (and standardize) this wrapping, you can create a custom result type:

public class FileUploadJsonResult : JsonResult
{
  public override void ExecuteResult( ControllerContext context )
  {
    this.ContentType = "text/html";
    context.HttpContext.Response.Write( "<textarea>" );
    base.ExecuteResult( context );
    context.HttpContext.Response.Write( "</textarea>" );
  }
}

You can also create extension methods for the Controller class to create these upload results just like any other result from the action methods:

public static FileUploadJsonResult FileUploadSuccess( 
this Controller controller, string successMessage = null ) { return new FileUploadJsonResult { Data = new { Success = true, Message = successMessage } }; } public static FileUploadJsonResult FileUploadFailure(
this Controller controller, string errorMessage ) { return new FileUploadJsonResult { Data = new { Success = false, Message = errorMessage } }; }

Here you can create a custom object with any structure in the Data property that will be delivered to the client in JSON. The code above just signals the result of the file upload in the Success property, and returns a detailed status message in the Message property that can be displayed by the browser.

So now you have fully functional server side: a form that POSTs to an action which validates the input, and if every field is valid, processes the values and returns a status in a JSON object.

Let’s implement the client side, of course with the jQuery Form Plugin. As its name implies, this is a jQuery plugin that you can apply to the jQuery object which wraps the form element (the $form in this case):

$form.ajaxForm({
    iframe: true,
    dataType: "json",
    beforeSubmit: function () {
// TODO
}, success: function (result) { // TODO
}, error: function () { // TODO
} });

You usually have to implement the following callback functions:

  • beforeSubmit: this is called before the POST is sent to the server. This is where you can display a “please wait” message, a progress indicator, or simply block the form controls using the jQuery BlockUI plugin.
  • success: this is called when the upload is completed successfully. At least in theory. In my experience this callback is also called when the server returns some low-level error. If there was no error, you receive the response from the server in the function parameter in JSON, but be prepared, that in case of error it can be undefined as well!
  • error: this is called when an error occurred during postback.

Here is an example of a working success callback implementation:

if (!result) {
  $errors.html('<div class="validation-summary-errors"><ul><li>Oooops....
</li></ul></div>'
); } else { $form.resetForm(); if (result.Success === true) { var message = result.Message; if (message && message.length > 0) { $errors.html( message ); } } else { $errors.html('<div class="validation-summary-errors"><ul><li>{0}
</li></ul></div>'
.format(result.Message)); } }

In this code the errors are displayed in a complex HTML fragment. The reason for that is that the same HTML fragment is generated by the standard ASP.NET MVC validation helpers, so with this code our Ajax errors will be rendered with the same style.

The format function acts like the String.Format method on the server and can be implemented like this:

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
    if (m === "{{") { return "{"; }
    if (m === "}}") { return "}"; }
    return args[n];
  });
};

If you return all ModelState errors from the server, you can render them in a loop.

You can download the full source code with tons of comment from the following link: http://sdrv.ms/10QQLSp

 

Technorati-címkék: ,

jQuery breaks with old IE versions

jquery-logoThe latest, 1.9 version of jQuery was released today, together with the beta of the 2.0 version. Although both versions share the same API (some features were removed from 2.0 as well as from 1.9), there are huge differences between them:

  • The 1.9 version – just like the previous versions – runs on Internet Explorer 6, 7 and 8, or as they say, on “oldIE”.
  • The 2.0 version will not run on oldIE. This decision results a simpler, faster and smaller library.

According to the Release Notes, both versions will be supported in the future, but I’m afraid that support will not last for ever. Sooner or later the 1.9 version will be deprecated, and new features will be implemented only in the 2.0 version.

Who loses more on this, IE or jQuery? Developers will switch to other libraries, or websites will render IE 6-7-8 obsolete?

 

Technorati-címkék: ,,

WinJS Tricks: Access is denied exception with multiple MessageDialogs

Using what you learned in the previous episodes of the WinJS Tricks Series about MessageDialogs and their custom buttons, you can write the following code, that displays two MessageDialogs in a sequence:

var dlg = new MessageDialog( 'First message' );

dlg.commands.append( new UICommand( 'OK', function() {
  new MessageDialog( 'Second message' ).showAsync().then( function() {
    // Do something useful here...
  } );
} ) );

dlg.showAsync();

The “only” problem with this code is that it unmerficully crashes your app without any notification. If you run your app in Debug mode you can get the following Access is denied exception:

MessageDialog-Access-denied

Do you see the bug? If not, you can learn why that happens and how to fix it from the next episode of the series:

(720p, full screen view recommended)

 

Technorati-címkék: ,,,,

WinJS Tricks Series: Custom MessageDialog buttons

In the last episode of the WinJS Tricks Series I showed you how you can create a simple message box in JavaScript in your Windows Store applications. In today’s episode we dive deeper and customize the buttons on the dialog, and you will learn how you can set the text, the keyboard hotkeys and the event handlers for your buttons.

Just like with message boxes, that are called message dialogs in Windows Store apps, buttons are not buttons any more, and button parameters are also have different names. Check the video to learn the new concepts:

(720p, full-screen view recommended)

Please rate or like the video if you are interested in the next episodes. Thanks!

 

Technorati-címkék: ,,,,

WinJS Tricks Series: Creating message boxes

Maybe you already heard, that you can create classic “rich client” applications in JavaScript for Windows 8. Whether it’s practical to choose JavaScript instead of C#, that’s another question, but it’s a fact, that there are problems which can be solved easier in JavaScript.

It’s a fact too, that in the beginning you won’t be productive when you create your Metro style applications in JavaScript, because the WinJS documentation is quite minimal. So I decided to start the WinJS Tricks Series to show you the solutions for problems that sooner or later you will face with when you are coding on WinJS. When you see the solution, it’s quite straightforward and logical, but without it, well….

So let’s take the simple task of popping up message boxes in WinJS! To save you some time, I tell you, that the classic alert doesn’t work. And there is no MessageBox class in WinJS. So what?

Let me introduce you to the world of message dialogs:

720p, full screen view recommended

If you are interested, please Like, so I will know. Thanks!

 

Technorati-címkék: ,,,,