Tuesday, September 16, 2014

jQuery "events-map" with jsTree or any jQuery object

I've been working with jsTree recently. It is an excellent jQuery plugin with great support from its developer Ivan Bozhanov. You can check out the jsTree site to learn all about it but I will just be using it for my example jQuery object instance here.

jsTree has several built-in and plugin events. In my case, I needed to make AJAX calls to WCF REST methods to update a back-end file system. So, I needed to attach event handlers to their corresponding events. 2 of the events were move_node and rename_node. The recommended way to attach was with jQuery's .on() method.

With just one event, you're fine just doing this:

 $('#jstree').on("move_node.jstree", function (e, data) {  
         $.get("/Main.svc/json/move/", {node_id: data.node.id, target_node_id: data.parent});  
         console.log(data.node.id + " moved");  
       }).jstree({...  

But, with multiple events, the cleanest way IMHO is to use the "events-map" syntax:

 $('#jstree').on({  
         "move_node.jstree": function (e, data) {  
           $.get("/Main.svc/json/move/", {node_id: data.node.id, target_node_id: data.parent});  
           console.log(data.node.id + " moved");  
         },  
         "rename_node.jstree": function (e, data) {  
           $.get("/Main.svc/json/update/", {node_id: data.node.id, text: data.node.text});  
           console.log(data.node.id + " renamed");  
         }  
       }  
     ).jstree({...

You can do this with bind() as well but since jQuery is moving away from bind() and recommending on(), we should do that.

Monday, August 11, 2014

Going the distance with the Google Maps JavaScript API

I recently had a client that wanted to calculate the distance between 2 of their locations and keep it consistent. These calculations were going to be used in travel expense reports and they didn't want mileage to vary based on the way the employee decided to calculate their mileage. I recommended that we write a small app that allows the employees to select their start and end locations and we provide the mileage from a single source. I recommended and we went with the:

Google Maps JavaScript API Directions Service


I saw a lot of recommendations for Distance Matrix but after vetting it, I felt that it would be simpler to pull what I needed from the DirectionsResult object from the DirectionsService.

I setup a Start dropdown and an End dropdown. On a dropdown change event I would update the mileage. It also updates the route shown on the map.

clip_image002

Inside my dropdown change event handler, I call a method that takes the response from the DirectionsService() call and grabs the distance field text from the “leg”.

 function showDistance(directionResult) {  
   var myDistance = directionResult.routes[0].legs[0].distance;  
   var myDistanceText = myDistance.text;  
   document.getElementById('outputDiv').innerHTML = myDistanceText;  
 }  

It's fairly straightforward. If your trip were going to have multiple legs then you would need to loop through the legs[] array and grab each distance field and add them up. In that case or in the case that you need to get a distance or distances for reasons other than just printing it out, I would separate the getting of the distance from the showing of the distance.

You can steal all the code here on GitHub. This app has opened the scope creep floodgates. If I add to it, I may update this post if something worth sharing comes out of it.

Thursday, July 17, 2014

Extending the Number object in JavaScript & the int type in C#

We will add a method to the Number prototype property in JavaScript. In C#, we will code the equivalent functionality with an extension method on int. Yep, we're going native! I'm hoping this will help somebody trying to move from C# to JavaScript or vice versa.

The JavaScript code can be found on GitHub here. The C# code can be found on GitHub here. You can fork the projects or just copy the code you need. Everything you need to run and test the code are in the projects. There is a QUnit page for the JavaScript project and a Unit Testing project for the C# project.

Let's start with JavaScript. All you need to do is add a method to the Number prototype property. I'm wanting to check if the Number is divisible by the dividend argument's value. I add isDivisibleBy to the prototype property and set it to an anonymous function with a dividend parameter. The function returns a Boolean:

 Number.prototype.isDivisibleBy = function(dividend){  
   return this % dividend == 0;  
 }  

You use it like so:

 var i = 6;  
 if (i.isDivisibleBy(3)) {  
       //it is and so do stuff  
 }  

There's a little bit more to do in C# but not much. We will add an extension method for int. Here, the first parameter is the type preceded by this and in our case it is our denominator. We also add our dividend parameter.

 public static bool IsDivisibleBy(this int denominator, int dividend)  
 {  
    return denominator % dividend == 0;  
 }  

To use it, it is EXACTLY the same syntax as JavaScript. The only difference is the method naming style. The method name starts with lowercase in JavaScript and starts with uppercase in C#. You could also use int instead of var in C#. But, it's all the same in the end.

 var i = 6;  
 if (i.IsDivisibleBy(3))  
 {  
     //it is so do stuff  
 }  

Tuesday, July 15, 2014

KnockoutJS Mapping to PHP & MySQL


A little while back I wrote a post called ‘Hello LAMP with Codio’. I wanted to leverage that example and create one that also uses KnockoutJS and the ko.mapping plugin.

So, I added a few files to the project on Codio. First, I added the Knockout script and the mapping plugin mentioned above. I also created knockout.php and ShowMsgs.html. You can view and run them from the Codio project.

The important part of knockout.php is fetching an object instead of an array and then echoing JSON back to the requesting ajax call that will be shown below.

image

If you actually browse to knockout.php, you will see the JSON:

image

The piece you’re probably searching for: In ShowMsgs.html, I code my viewModel (which I actually leave to ko.mapping), my template and the jQuery.


image

Please note that you’re going to need that jQuery reference as well. I used their CDN but you can reference it any way you wish. Also, in production, you don’t want to use the Debug version of any script but we are just creating a demo that we want to step through here.

Here’s what we get when we browse to ShowMsgs.html

image

Please see the original post “Hello LAMP with Codio” to see how the MySQL data was setup along with how to set up a Codio project in general.

Thursday, July 10, 2014

Pretty beautiful optimized JavaScript


I obviously try to use best practices to make my code as optimized and nicely formatted as possible. But, I use two tools pretty consistently during and after writing a script.

The first thing I do is run it through Google’s Closure Compiler. I use the “SIMPLE_OPTIMIZATIONS” compilation level.

Next, I paste the output from Closure Compiler in to jsbeautifier. They have some great options. I wont get in to how I like my braces. Those conversations can get ugly. :-)

You might ask why I don’t just use the “pretty_print” formatting with Closure Compiler. Well, I like the options with jsbeautifier. It may also just be habit.

I do drop by JSLint on occasion. It is good to get all the feedback I can on my JavaScript code.

There are a zillion IDE, online and local tools to help you optimize, minimize and pretty up your code. I find that these tools are more about learning how to write better JavaScript than any significant performance boost. That is, if you’re starting out with halfway decent code.

Let me know your process. Hopefully it includes peer and up code reviews!

Saturday, June 28, 2014

Hello LAMP with Codio


Codio has just announced that their web-based IDE is out of beta. They claimed that I could have a full LAMP stack set up in seconds. Zend made similar claims about their PHPCloud (which is now killed off by Zend) and while I did get it working and am a fan, it took some head scratching before I got it going. So, I set out to to get a “Hello LAMP” application working in Codio. It turned out to be fairly straightforward.

Here is what I did along with a link to the public project. You can check out all the Codio features and project settings etc. on the Codio site.
  1. Sign up for a free Codio account
  2. Click Create Project from the Dashboard, enter a project name and choose the PHP Project template. I kept this one Public. (Public means anybody can view it but they can’t edit it. Read more about that on their website). Click Create Project:

    image
  3. A project will almost instantly be created for you. Click on index.php in the Filetree and you will see that they have a “Hello PHP” already there for you. Right-click on index.php and select “Set as project index”. If you try to run this, you will be out of luck because you still need the A in LAMP. On the top menu bar click Tools –> Terminal and plug this in:

    2014-06-28_16-07-40
  4. You still wont be able to play your app because Apache isn’t running. This is spelled out to you in the terminal after the parts are installed. Do what it says AND switch your run option to “Box URL” AND… you still won’t be able to play your app!:

    image
  5. Don’t despair, there’s one more part to install ‘php5-apache2’ and then restart Apache:

    image
  6. Run the app via Box URL and VIOLA!

    image

  7. The name of this blog post is “Hello LAMP” so let’s start the M here:

    image

    image
  8. Create a database and then create your table and put at least a row in it:

    image
  9. Add your PHP code to index.php for reading and echoing your text from the database table:

    image

  10. Run your code and…

    image

The public project is out on Codio and you can check it out here: https://codio.com/joeldpalmer/PHP-Test
I’m pretty impressed with Codio as of now. If they add an integrated PHP debugger, that will make it a complete PHP IDE.


Bye PHP Cloud. I had high hopes. :-(

Friday, June 13, 2014

Sorting Grid Columns in LightSwitch apps Hosted on SharePoint 2013

Get grids to load pre-sorted and still allow users to re-sort via the column headers:
  1. Remove any sorts from the Query Designers but leave any desired filters:

    LS QueriesQueryDesigner
  2. For each Query, click the ‘Write Code’ drop down and find the PreprocessQuery method and it will add the declaration to the C# SPPurchaseReqDataService class
  3. Set the query value with LINQ:
     partial void QueryNewPR_PreprocessQuery(ref IQueryable<PurchaseRequisition> query)  
         {  
           query = query.OrderByDescending(p => p.Modified);  
         }  
     partial void QuerySubmittedPR_PreprocessQuery(ref IQueryable<PurchaseRequisition> query)  
         {  
           query = query.OrderByDescending(p => p.Modified);  
         }  

That's it. It's pretty straightforward once you do it but LightSwitch can be a bit confusing, at least for me. In theory, this code is supposed to do exactly what the Query Designer does. But, doing it in code (on the server-side) allows the users to re-sort whereas the designer lets the user believe they can re-sort but the grid is just reloaded with the original sort. I am able to repro this 100% of the time. I’m guessing that I am not the only one. If this is a known bug and/or if it is/gets fixed, please let me know. In any case, I hope this is still useful information on sorting in LightSwitch.

Wednesday, June 4, 2014

Display SharePoint App Web List Data in an App Part on the Host Web

At the time of this writing, I've seen a handful of posts that come close to what I needed but weren't quite there.

I needed to put an App Part on the Host that reads App Web list data, displays it in the App Part and contains links back to the App Web. This post from Corey Roth got me most of the way there. Thanks Corey!

To make sure you know exactly what I did, you should know that the fields, content types, list template and list instance are all part of the SharePoint-Hosted App project.

The code grabs the host and app web Urls and then loads up SP.js from the host. It queries the list and sticks the latest item's title in to a Marquee. This title is linked back to its associated display form on the app web list. I highly doubt you will come across these exact requirements but the plumbing should help.

Here is the full JavaScript source:

 var clientContext;  
 var siteCollection;  
 var collListItem;  
 var oList;  
 var appWebUrl;  
 $(document).ready(  
   function () {  
     var spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));  
     appWebUrl = decodeURIComponent(getQueryStringParameter('SPAppWebUrl'));  
     var layoutsRoot = spHostUrl + '/_layouts/15/';  
     $.getScript(layoutsRoot + "SP.Runtime.js", function () {  
       $.getScript(layoutsRoot + "SP.js", sharePointReady);  
     }  
     );  
     function sharePointReady() {  
       clientContext = SP.ClientContext.get_current();  
       oList = clientContext.get_web().get_lists().getByTitle('Notifications');  
       getList();  
     }  
   }  
 );  
 function getQueryStringParameter(urlParameterKey) {  
   var params = document.URL.split('?')[1].split('&');  
   var strParams = '';  
   for (var i = 0; i < params.length; i = i + 1) {  
     var singleParam = params[i].split('=');  
     if (singleParam[0] == urlParameterKey)  
       return decodeURIComponent(singleParam[1]);  
   }  
 }  
 function getList() {  
   var camlQuery = new SP.CamlQuery();  
   camlQuery.set_viewXml("<View><RowLimit>1</RowLimit><Query><OrderBy><FieldRef Name='Created' Ascending='False' /></OrderBy></Query></View>");  
   this.collListItem = oList.getItems(camlQuery);  
   clientContext.load(collListItem);  
   clientContext.executeQueryAsync(onRequestSucceeded, onRequestFailed);  
 }  
 function onRequestSucceeded() {  
   var lineBreak = document.createElement('br');  
   var listItemInfo = '';  
   var listItemEnumerator = collListItem.getEnumerator();  
   while (listItemEnumerator.moveNext()) {  
     var oListItem = listItemEnumerator.get_current();  
     var rightNow = new Date();  
     var expireDate = new Date(oListItem.get_item('NotificationExpiration'));  
     if (rightNow < expireDate) {  
       listItemInfo += "<marquee scrollamount=4>";  
       listItemInfo += '<a target=_blank href=' + appWebUrl + '/Lists/Notifications/DispForm.aspx?ID=' + oListItem.get_id() + '>' + oListItem.get_item('Title') + '</a>';  
       listItemInfo += "</<marquee>";  
       listItemInfo += "<br>";  
     }  
   }  
   $('#Notifications').html(listItemInfo);  
 }  
 function onRequestFailed(sender, args) {  
   alert('Error: ' + args.get_message());  
 }  
Helpful Resource: How to: Retrieve List Items Using JavaScript

On a side note, my Office 365 Developer Site is worth every penny. I used it to test and debug this code and it worked wonderfully.

JavaScript Scope: Function Evaluation


Function declarations are evaluated first and moved to the top of the scope during parsing. So, you can declare them anywhere in the body of the script and call them before the declaration:


Function expressions are not evaluated until assignment:


Like other variables, it is a good idea to define them at the top of the scope. But, with function expressions you must make the assignment before you make a call:


To sum it all up, take a look at the Locals window when execution starts:


The declared functions are evaluated and ready for calls as soon as script execution starts.