better software through user-centered design

Archive for the ‘Javascript and jQuery’ Category

Yeoman with Express API Server

 

After playing around with Yeoman the other day I was pretty darn impressed. Ease of use and efficiency in web tools often forces the sacrifice of customizability and full control Yeoman offers all of the above. Once I realized how powerful it was and how cool liverefresh and watch works from the generated app, I wondered if I could use it to fire up my Express Node API server as well. It turns out, you can…

When a default app is generated using the standard method (yo webapp), Yeoman generates a Grunt file and sets up a working app that can be generated and running in seconds. It it not the typical Hello World where the first thing you do is tear out the crappy generated code because you have a better way. You simply generate and start building out your app…personal or enterprise level!

Once the app is generated the default Gruntfile.js uses connect to host the index.html and static resources. Express uses Connect under the covers but I wanted the routing and middleware goodness Express provides. It took some doing, but basically I use grunt to build and fire up my website, as well as startup up my Express API application at the same time.  Since Grunt is so flexible, allowing you to configure each task independently, locally it fires them up together, but in production grunt will do nothing with the API application as it will live on multiple servers behind a load balancer.

Here is my Gruntfile.js contents. Note that this is the default generated grunt file that I simple swapped internal connect usage for external Express app: gist.github.com/zachariahtimothy/5454976

Next order of business is setting up Express to be an API only application that exports in such a way Grunt can use it:

gist.github.com/zachariahtimothy/5455017

You may call this file app.js but in my specific instance I am using app.js to start Grunt up within Webstorm.

Note that I used Yeoman 1.0 to generate the application.

 

So there you are, in under 5 minutes you could have a fully usable and ready for development frontend and backend api platform. Let me know what you think or any issues you see with what I found.

Advertisements

How To Export Email List from cPanel with JavaScript

This is a sort of weird post, but recently I ran into an issue where I needed to transfer a bucket of email addresses from one hosting account to another.  In this case I am using Siteground as my host, and I was switching from one basic hosting account to another.  With the ultra low-priced plan you get cPanel access but no SSH or migration tools whatsoever.  There is an email account and email forwarder import tool, but no export, only showing you your email account on the screen.  The combination of laziness and geekiness overwhelmed me so I used the Firebug command line and wrote a script to export the data I needed to be imported into Excel and then uploaded to cPanel.

UPDATE: Since WordPress does not support code formatting, I put these scripts both in a Gist: gist.github.com/zachariahtimothy/5455126

Code and steps taken to complete this task for Email Addresses:

  1. Login to cPanel on old account and click on “Email Accounts” under the Mail Section.
  2. Change the results per page to be the max.  In my case, this showed me all email account.
  3. Bring up Firebug command line and input the following code:
    var rows = $("#table_email_accts tr.dt_info_row"),
    returnString = "";
    rows.each(function(i, item){
    var tdList = [];
    $(item).find('td:eq(0)').each(function(s, subItem){
    tdList.push($(subItem).text());
    });
    returnString += tdList + "\n";
    });
    console.log(returnString);

    This code may need tweaking for your cPanel version, but you should now see a list of the email addresses you desire in the Firebug console.
  4. Create a new text document in the directory of your choosing.  Copy and paste the email addresses inro the file and save as a csv.
  5. Create a new Excel spreadsheet with 3 columns and add the labels “Address”, “Password”, and “Quota”.
  6. On the data tab choose “From Text” under Get External Data.  Select the text (csv) file you just created and open.
  7. This will import the email addresses into the first column so all that needs to be done is add the passwords and email quota.
  8. All that is left is to click the Import Addresses/Forwarders link, upload the spreadsheet and follow the on-screen instructions.

Code and steps taken to complete this task for Email Forwarders:

  1. Login to cPanel on old account and click on “Forwarders” under the Mail Section.
  2. Change the results per page to be the max.  In my case, this showed me all forwarders.
  3. Bring up Firebug command line and input the following code:
    var rows = $(“#mailtbl tbody tr”),
    returnString = “”;
    rows.each(function(i, item){
    var tdList = [];
    $(item).find(‘td.truncate’).each(function(s,subItem){
    tdList.push($(subItem).text());
    });
    returnString += tdList + “\n”;
    });
    console.log(returnString);
    This code may need tweaking for your cPanel version, but you should now see a list of the email forwarders you desire in the Firebug console.
  4. Create a new text document in the directory of your choosing.  Copy and paste the email addresses into the file and save as a csv.
  5. Create a new Excel spreadsheet with 2 columns and add the labels “From Address”, and “To Address”.
  6. On the data tab choose “From Text” under Get External Data.  Select the text (csv) file you just created and open.  Make sure you select Delimited and comma as the delimitation type.
  7. This will import the from address in the first column and to address in the second.
  8. All that is left is to click the Import Addresses/Forwarders link, upload the spreadsheet and follow the on-screen instructions.

That is it for migrating email addresses and forwarders over to new accounts.  It is not that complex, but maybe it will save you 20 minutes of your life someday.  Note that if your version of cPanel does not have jQuery installed, you can use FireQuery to inject it.

JavaScript Structure in an MVC Application

There are several approaches to organizing code in any application.  With the Model View Controller (MVC) pattern, much of the code is organized for you by convention alone, specially if you are using ASP.Net MVC.

In an effort to follow the conventions and patters set forth by MVC, I started thinking about how to pull the JavaScript out of my views, that is, I want my JS code organized in a pattern satisfactory with the file structure of MVC.  One thing I love about MVC, is that when I look at a controller, I know almost exactly where to look to find the view, and vice versa.  The Solution Explorer screenshot shows my take on how to organize JS code in such a matter.

JS Namespace and Class Setup

The App.js initializes the namespacing and classing that will be used to organize the client-side, and more importantly prevents that pesky global namespace from becoming cluttered.  It sounds pretty hard core talking about namespacing and classing on the client-side right?  It is.  It is highly technical and complex to….ok well maybe it is just a series of objects, that looks and feels like C#’s namespacing/classing at runtime. Note that this is accessed using the dot notation (MYAPPLICATION.App.Ajax.PostForm();).  In this case I split the “App” code away from the “View” code.

 I chose to do this simply because that is how the C# project namespacing was setup in the project structure.

The Ajax, Form, and Utilities classes are just infrastructure code that I use to post forms, create pdf’s, override default behavior using prototype, setup default jQuery UI functionality, etc.  Read more about submitting MVC forms using jQuery if you dare.

MYAPPLICATION.Views{} is simply an object that allows me to organize my JS code similar to how the views are generated.  There are two advantages I have found that instantly save me time; 1) I can look at a view in the VS Solution Explorer and know exactly where to find the associated JS, and 2) I can look at a url route and know exactly where the JS for that page lives.   Another big benefit is it helps keep the JS out of the view.  This leaves only 1 line of code in the view itself, which is required to instantiate the JS for said view:

<script>
    MYAPPLICATION.Views.History.Index.Init({ orderDetailGridUrl: '@Url.Action("OrderDetailGrid", "History", null)' });
</script>

Note that if you use Firebug (which you should be), it makes debugging a bunch easier as well because you can select the appropriate script file (which Firebug organizes by Controller thanks to our file structure) versus scrolling through the markup on the script tab and trying to find the right line, YUCK.

 Then all the History code lives in one file, and is loaded after the MYAPPLICATION.App{} code so it can utilize all utilities and ajax goodness already written.

MYAPPLICATION.Views.History = {
    Index: {
        Init: function (options) {
            // History index page code goes here...

        }, ///end Index.Init()
    }
};

So far there have been no drawbacks to this approach because you can still use other JS patterns that work well with this setup.  I have used the JS module pattern in other applications and instantiated them the same way as shown here.

MVC3 and jQuery Form Submit

MVC3’s model binding support is fantastic! The software our team develops is search/results based so staying on a single page to display a grid is important. There are many jQuery based element serializers, but I wrote my own because I wanted something extremely basic and simple and hey, why not since it is so easy! Before we look at the serializer, let’s look at how we use jQuery to submit our form so the Post does not render a new page.

jQuery Form Post (link to code example)

Now that we bound our function to the form submit event, we can serialize our form. The serializer function is very basic but works great. It uses the jquery data() to include stored data to bind to the model. This can be really handy for non-form elements and custom client-side functionality. Basically any information you want to head back to the server, just add like so:

$("#myForm").data("ToPost", { SelectedGridIds: [1, 14, 922] });

The serializer function will automatically add the “ToPost” data objects to the JSON object to be returned to the server.

jQuery Form Serializer (link to code example)

Now my Post function has stopped default event propagation, and serialized the data I need, now we just need to post it. You can use your favorite ajax post method, but I prefer to use the wrapper function I created. It uses jQuery do make the actual post (which I also prefer).

Implementation:

First, we need a quick little jQuery plugin to manage all our “Form” operations:
//Creates a jQuery accessor for NRPC.Form object.
//Example: $('form').Form('Post', {options});
// Decorate each class with the jQuery self-executing function to prevent IE from blowing up in debug mode.
(function ($) { 

$.fn.Form = function (method) {
if (MyNamespace.Form[method]) {
return MyNamespace.Form[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return MyNamespace.Form.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on MyNamespace.Form');
}
};

})(jQuery);

Sweet, now when the page loads, all we have to do is register the form post with $(“form”).Form(‘Post’);.

Here is a real-world implementation:

$("form#Search").Form('Post', {
targetId: 'divGrid',
onAjaxSuccess: function (resultGridHtml) {
var gridResult = $(resultGridHtml)[0];
$("#divGrid").html(gridResult);
}
});

JavaScript Ajax Wrapper

This is a simple wrapper for keeping consistency in ajax calls. This happens to use jQuery ajax but the key to the wrapper is that the internal functionality can be re-written or a new library utilized across the board. I have always liked this idea but now cherish it due to recent dealings with ExtJS and their complete lack of backwards compatibility on every release.

MyNamespace.Ajax = {
//Setup ajax default properties
Defaults: {
type: ‘POST’,
url: ”,
contentType: ‘application/json; charset=utf-8’,
dataType: ‘json’,
success: function (result) { },
error: function () { }
},

// Global Post for any Ajax calls.
// This is meant to be a wrapper for the jQuery $.ajax method and should not be circumvented without great reason.
Post: function (options) {
options = $.extend(this.Defaults, options);
//Serialize the json object if it has not already been done.
if (options.data && typeof (options.data) == “object”) {
options.data = JSON.stringify(options.data);
}

$.ajax({
type: options.type,
url: options.url,
contentType: options.contentType,
dataType: options.dataType,
data: options.data,
success: function (result) {
if (options.success) {
options.success.apply(this, Array.prototype.slice.call(arguments));
}
},
complete: function (request, status) {
if (options.complete) {
options.complete.apply(this, Array.prototype.slice.call(arguments));
}
},
error: function (request, typeText) {
MyNamespace.Utilities.LogError(request.responseText);
if (options.error) {
options.error.apply(this, Array.prototype.slice.call(arguments));
}
}
});
}
};

jQuery Form Post

This is a wrapper for submitting forms. I use this with ASP.Net MVC and specifically with MVC3 because the serialized data will automatically bind to the model.
Post Dependencies: JSON2.js by Douglas Crockford, Serialize Function by me, Ajax Wrapper by me

/// Posts existing form via ajax. Automagically binds your form elements to the view model.
Post: function (options) {

var defaults = {

onSubmit: null, /// function to run before default validation occurs (used for custom validation)
onAjaxSuccess: null, /// function to run when ajax returns successful
onAjaxComplete: null, /// function to run on ajax completion
onAjaxError: null, /// function to run when ajax returns error
targetId: '' /// id of the element to dump the results in

}, json = {}, formObject = $(this);

this.submit(function (event) {

try {
/// Prevent form from submitting
event.preventDefault();

/// Use the OnSubmit even to run any custom validations you may have.
if (options.onSubmit) {
var onSubmitResult = options.onSubmit.apply(this, Array.prototype.slice.call(arguments));
if (onSubmitResult !== undefined && onSubmitResult === false) {
return onSubmitResult;
}
}

/// Check if form is valid and stop submit if it is not.
if (!$(this).valid()) { return false; }

if (options.targetId && !$("#" + options.targetId).is(":empty")) {
$("#" + options.targetId).empty();
}

/// Serialize form elements and associated data options
json = formObject.Form('Serialize', options);

MyNamespace.Ajax.Post({
url: formObject.attr('action'),
type: formObject.attr('method'),
dataType: 'html',
data: JSON.stringify(json),
success: function (result) {
try {
if (options.onAjaxSuccess) {
options.onAjaxSuccess.apply(this, Array.prototype.slice.call(arguments));
}
} catch (error) {
MyNamespace.Utilities.LogError(error);
}
},
complete: function (XMLHttpRequest, textStatus) {
try {
if (options.onAjaxComplete) {
options.onAjaxComplete.apply(this, Array.prototype.slice.call(arguments));
}
} catch (error) {
MyNamespace.Utilities.LogError(error);
}
},
error: function(error){
MyNamespace.Utilities.LogError(error);
try {
if (options.onAjaxError) {
options.onAjaxError.apply(this, Array.prototype.slice.call(arguments));
}
} catch(error){
MyNamespace.Utilities.LogError(error);
}
}
});

} catch (error) {
MyNamespace.Utilities.LogError(error);
}

});
return this;

} //end Post

jQuery Form Serializer

This serializer is an example of how we can use form elements and jQuery data() to manipulate page data and let MVC3 automatically bind it to the model. Note the compensation for MVC3’s handling of checkboxes and checkbox logic.

/// Walks through form and creates JSON object from input elements and optional data elements.
/// These objects are able to be bound to the view model by MVC 3.
Serialize: function (options) {
var returnJson = {};

this.find(‘:input’).each(function (i) {
var item = $(this);
if (item.attr(“name”)) {
//this logic compensates for MVC3 adding a hidden after every checkbox.
if (!returnJson[item.attr(“name”)] || (returnJson[item.attr(“name”)] && !item.attr(“type”) == ‘hidden’)) {
if (item.attr(“type”) == “checkbox”) {
returnJson[item.attr(‘name’)] = item.is(“:checked”);
} else {
returnJson[item.attr(‘name’)] = item.val();
}
}
}
});

/// Add data() elements to json object if exists.
/// You can attach data elements to the form to add to the post to get model bound.
/// Example: $(“#MyForm”).data(“ToPost”, {MyobjKey: ‘myvalue’}, {MyArray: []});
if (this.data(“ToPost”)) {
$.each(this.data(“ToPost”), function (key, value) {
returnJson[key] = value;
});
}

return returnJson;
}, ///end SerializeForm

%d bloggers like this: