Tuesday, December 31, 2013

Awestruck by 2013 Tech!

Google Glass came to us in 2013, and while I'm not overly impressed with Google Glass, I am impressed with Google in general, so let Google Glass be a symbol of the greater Google future! Google seems to be the most impressive tech company of the year behind us. Microsoft seems to be struggling (while still ruling the roost) and I didn't see anything I cared about coming out of the modern day Apple that lingers without Steve Jobs, yet it's Google that impresses. I started really using Google Chrome all the time in lieu of having Internet Explorer as my default this year. The Google Chrome Developer Tools now mean there is no longer a reason to use Firefox and Firebug whatsoever. AngularJS seems the most impressive of the emerging JavaScript frameworks. I suppose a lot of this may be of 2012 or 2011 and not 2013, but it is catching up to me, average Joe, this year. It is sad there is no more Feedburner, but I suppose Google must pick its battles. That scene in the "The Internship" where interns are taking tech support calls of how to use gmail seemed comedic as it was so "disingenuous." Is there really any way to get someone from Google on the phone? I hate how opaque Google is, but if Google wasn't opaque I suppose we'd all know how to game their search engine. We had all of our Google history stolen by Uncle Sam via the Muscular project this year too. It has been a much more interesting year for Google than it has for Microsoft and Apple and that is both something new and something that will likely continue. I wonder if the next CEO of Microsoft will just drop Bing and just admit that Google has won in the search engine space. More of 2013 Tech:

  • In the social media space, I fell in love with Vine. I never tried Snapchat, but I did note that the word "selfie" is making the English dictionaries as of this year!
  • For the most part I find Marissa Mayer and Yahoo just as overhyped as, say, Danica Patrick and Go Daddy. It seems like a pretty face garners disproportionate attention, but one thing nice I will say about Marissa is that I am impressed that she not only ended working from home at Yahoo, but somewhat made herself the face of that issue nationally thus stirring up a debate. She made the right decision and I'm grateful that we got to talk about it.
  • I didn't know who Aaron Swartz was until he took his own life this year, but now that I know, I again want to mention his tragic passing. It is sad. He invented RSS.
  • The big news in 2012 America was about our presidential election and the big news in 2014 will likely be, I'm guessing, about a pullout from Afghanistan and our experimentations with legalizing marijuana, but the news in 2013 was actually about tech itself. Edward Snowden and healthcare.gov were the big stories. In Britain they've pushed through a law that goes into effect in the New Year which forces all ISPs to block naughty content unless mature parties explicitly opt-in for it. New Zealand meanwhile has done away with honoring software patents.
  • Finally, just yesterday, I learned from Scott Hanselman's online video tutorials for Visual Studio 2013 that there is finally a way to rotate text in HTML via modern CSS tricks. It seems so simple, and yet it has taken us so long to get here. This is really big to me. I'm serious.

In Windows 8 one may drag a not maximized window against the right or left edge of the screen to maximize it to just half of the screen.

This easily allows you to run two apps side by side in two halves of the screen. This is another something I learned from Scott Hanselman's videos on what is new in Visual Studio 2013.

Monday, December 30, 2013

After nineteen years of the World Wide Web, we may now rotate text in HTML.

I just watched the 2nd in a series of Scott-Hanselman-made video clips mentioned here and find myself blown away by the modern CSS tricks to rotate text! If you slap the following in a class...

.hyena {
   width: 200px;
   height: 200px;
   color: #00FF00;
   -moz-transform: rotate(45deg);
   -ms-transform: rotate(45deg);
   -o-transform: rotate(45deg);
   -webkit-transform: rotate(45deg);
   transform: rotate(45deg);
}

 
 

...and then decorate a div tag with it like so:

<div class="hyena">Never laugh at a hyena!</div>

 
 

The result is:

Never laugh at a hyena!

Beginning to watch Scott Hanselman's what's-new-in-VS-2013 videos...

I think this is how I'll try to wake up in the mornings. I watched the first clip today at http://www.hanselman.com/blog/SCREENCASTSWhatsNewInVisualStudio2013LearnOverLunch.aspx and am most impressed so far by:

  1. built-in Intellisense for Angular
  2. you may drag a video flie such as an .mp4 tag from the Solution Explorer into a .cshtml view and an HTML tag for the video will automatically be generated
    <video controls="controls">
       <source src="http://localhost:55655/ASP_NET_1920.mp4" type="video/mp4">
    </video>

Saturday, December 28, 2013

Does Entity Framework no longer suck?

A goal of mine for the year ahead is to learn AngularJS, but it's probably also time to find an excuse for an Entity Framework 5 project. I'll need the skill. I see more and more Twitter traffic from NHibernate escapees embracing EF5. If I throw together a dummy project I'll do it the code first way as suggested here and not the old school way suggested here and here. My old framesdirect.com cellmate Jagruthi Mamidi (below at right) and her husband had a housewarming party today and when I compared notes with her regarding her immediate circumstance, well, sure enough, her workplace has shifted away from LINQ to SQL to EF! There is likely much to learn regarding IQueryable pitfalls and how to use IQueryable without opening the door to an anti-pattern.

 
 

Addendum 3/21/2018: Jagruthi Reddy is another name for Jagruthi Mamidi.

Friday, December 27, 2013

It looks like Angular HAS to run at a web server.

If you just try to double-click the index.html in the seed project and "run" it in Windowsland from a browser you see something like:

XMLHttpRequest cannot load file:///C:/whatever/partials/partial1.html. Cross origin requests are only supported for HTTP.

...in the console, but not so if you bring the site up in IIS.

Thursday, December 26, 2013

HP Data Protector

...is software for automating backups per this.

MSSQL Server recovery models

This mentions there are three kinds of recovery models:

  1. Simple
  2. Full
  3. Bulk logged

 
 

This mentions how to change the setting. Something taken verbatim from there is:

  1. After connecting to the appropriate instance of the SQL Server Database Engine, in Object Explorer, click the server name to expand the server tree.
  2. Expand Databases, and, depending on the database, either select a user database or expand System Databases and select a system database.
  3. Right-click the database, and then click Properties, which opens the Database Properties dialog box.
  4. In the Select a page pane, click Options.
  5. The current recovery model is displayed in the Recovery model list box.
  6. Optionally, to change the recovery model select a different model list. The choices are Full, Bulk-logged, or Simple.
  7. Click OK.

beforeActivate versus afterActivate in dojox views

OK, a beforeActivate method is run before the DOM is drawn and may be used to prep stuff to be drawn within the DOM. This is NOT the thing to use if you need to create something, for example a pie chart, reactively based upon the height of a div it is to sit within which may fluctuate with browser size, especially so if you are driving the height and width of the pie chart from JavaScript in lieu of CSS like this:

pieChart.surface.rawNode.setAttribute('width', domStyle.get(this.chartWrapper, "width"));
pieChart.surface.rawNode.setAttribute('height', domStyle.get(this.chartWrapper, "height"));

 
 

Instead, make use of the afterActivate method, which will allow you to blot on new stuff right after the rest of the DOM has appeared! Yay!

more regarding: getting rid of script tags in AngularJS

Following upon this, I have failed to get the suggested approach to cleaning up a script tags-based AngularJS implementation to one that uses AMD modules working. I am still struggling with it. I am attempting to now instead use a comparable implemenation that a coworker has used in another project. The other implemenation gets me farther, yet I still hit a brick wall (so far). The HTML bootstrapping everything in a one page application starts out like so:

<!DOCTYPE html>
<html lang="en" ng-app="assetDashboardApp">

 
 

...and has this farther downstream:

<script src="js/lib/common/require.js" data-main="js/main.js"></script>

 
 

...begging the question: What is in main.js?

(function() {
   "use strict";
   
   require.config({
      baseUrl: "js",
      
      paths: {
         "underscore": "lib/common/underscore",
         "moment": "lib/common/moment",
         "angular": "lib/angular/angular",
         "jquery": "lib/jquery/jquery-1.10.2",
         "ngBootstrap": "js/lib/common/bootstrap",
         "jquery.bootstrap-growl": "lib/jquery/jquery.bootstrap-growl",
         "angular-resource": "lib/angular/angular-resource",
         "ui.router": "lib/angular/angular-ui-router",
         "http-auth-interceptor": "lib/http-auth-interceptor",
         "LocalStorageModule": "lib/angular/angular-local-storage",
         "ui.bootstrap": "lib/ui-bootstrap-tpls-0.7.0",
         "services": "services",
         "util": "util",
         "assetLogTypeFilter": "filters/assetLogTypeFilter",
         "dictionaryLookUpFilter": "filters/dictionaryLookUpFilter",
         "controllers": "controllers",
         "login-auth": "directives/login-auth",
         "daterangepicker": "lib/daterangepicker",
         "ng-bs-daterangepicker": "lib/ng-bs-daterangepicker"
      },
      
      shim:   {
         "angular":   { deps: ['jquery'], exports: 'angular' },
         "underscore": { exports: '_' }
      }
   });
   
   function tryHoldReady() {
      if (!tryHoldReady.executed && window.jQuery) {
         window.jQuery.holdReady(true);
         tryHoldReady.executed = true;
      }
   }
   
   tryHoldReady();
   require.onResourceLoad = tryHoldReady;
   
   require([
      "jquery", "angular", "app"
   ], function($) {
      $.holdReady(false);
   });
})();

 
 

So far, I have gotten out of main.js only to find errors in app.js. I got past the first hurdle by wrapping the contents of app.js inside an AMD module signature which pulled in both require and Angular. I then fall down here:

angular.module('LocalStorageModule').value('prefix', 'assetDashboard');

 
 

A look at the code inside angular-local-storage.js makes it obvious that there is an expectation for an object called "angular" to already exist. The immediate challenge is that need to shim this AMD-unfriendly thing as an AMD module... perhaps by using the shimming section in main.js above? I don't know yet. I'm still experimenting. It is worth nothing above that there are some hijinks going on in main.js to make jQuery play nicely with Angular. Guy in grey sweater wisely suggests after all: "if you don't load jQuery via AMD then modules that need it are going to fail."

Tuesday, December 24, 2013

Disable cache (while DevTools is open)

...when checked in Google Chrome Developer Tools seems more astute at making sure JavaScript refreshes upon a refresh than .html files. I had to do a hard refresh a moment ago to refresh an .htm file. (Ctrl-F5 or Ctrl-Click on the refresh button)

Monday, December 23, 2013

React to window.onresize within a dojo widget!

Following on the heels of what I offer here, I have visited this and found that the suggested way of using window.onresize (by way of AMD modules wrapping the functionality) worked best, used in a dojo widget, when set at the postCreate method like so:

postCreate: function() {
   on(win.global, 'resize', function() {
      console.log('whatever');
   });
},

 
 

You may leave the view and return, and the act of dragging around the window will still put "whatever" to the console. For all this to work on needs to correspond to dojo/on at the AMD signature "up top" while win needs to correspond to dojo/_base/window additionally.

JavaScript has an event which is triggered when you resize a browser window.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>Whatever</title>
      </style>
   </head>
   <body>
      <div id="whatever"></div>
      <script type="text/javascript">
         window.onresize = function(event) {
            var winWidth = document.all ? document.body.clientWidth : window.innerWidth;
            var winHeight = document.all ? document.body.clientHeight : window.innerHeight;
            document.getElementById('whatever').innerHTML = winWidth + "x" + winHeight;
         }
      </script>
   </body>
</html>

Saturday, December 21, 2013

a dojo mixin

...is sort of an extension to a dojo widget. A common mixin for a list widget is an addon for searching the list.

To get rid of endless Facebook invites to play "Candy Crush Saga" just unfriend the person who started the invite.

If you friend them anew, you will be on the other side of the problem. Your friend does not realize they are spamming you.

Addendum 12/26/2013: I have spoken too soon. I had a window of quiet and then now, today, I've gotten a new request. Boo. I may need to REALLY unfriend Nichole FOREVER.

Friday, December 20, 2013

things I learned in a JavaScript training yesterday

  1. === which is the strictly equals operator evaluates BOTH value and type!
  2. I am making closures too complicated here. A closure is just a circumstance wherein a variable declaration is followed by a function and the function makes use of the variable that was defined outside of its scope by way of the the variable living upstream from the function within the same blob of code (another function perhaps) that holds the function. Yes, you may do this without a scope problem and it is called a closure.
  3. bind is the plain Jane JavaScript way to do what you'd do with lang.hitch in Dojo, namely pass the scope of "this" as is into another setting where it would otherwise be different.
  4. strict mode is going to be cross with you if you declare a variable without using the var keyword. You may technically do this in JavaScript and a variable will end up in global scope. Strict mode will block this bad practice.
  5. The distinction between callback and promises is that promises are a better way to do callbacks. Instead of handing in a function as an object/variable to an asynchronous thing to fire off when the asynchronous item finishes its chore, one may use .when() implementations and moreover chain .when() implementations.

Thursday, December 19, 2013

disabling a form field in AngularJS implementations

An Angular Scope variable like so:

$scope.disabledFlag = true;

 
 

...could be used to drive a disabled state like so:

<input class="form-control" type="text" ng-model="name" required
   ng-disabled="{{disabledFlag}}" />

 
 

In my scenario I have one template driving the CRUD screens for both editing and creating, but I don't want every field to be editable when editing.

ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js

...is where to get AngularJS.

Wednesday, December 18, 2013

Ant stands for Another Neat Tool!

seriously

getting rid of script tags in AngularJS

About seven and a half minutes into this movie comes the suggestion that this:

<html lang="en" ng-app="myHelloWorldApplication">

 
 

...needs to be swapped out (downstream of a require.js script tag) with something like so:

$script([
   'lib/angular/angular.js',
   'js/app.js',
   'js/services.js',
   'js/controllers.js',
   'js/filters.js',
   'js/directives.js'
], function() {
   angular.bootstrap(document, ['myHelloWorldApplication']);
});

 
 

...in the name of cleaning up an AngularJS implementation which uses script tags to one that has an AMD pattern. This reiterates what is given here as well: "Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfil their goals" ...I need to actually attempt the script-tag-to-AMD migration. Let's see how it goes.

gotta love the Select Lambda

var myList = new List<int>();
foreach (KeyValuePair<int, int> x in existingAssets)
{
   myList.Add(x.Key);
}
var myArray = myList.ToArray();

 
 

What is above may merely become...

var myArray = existingAssets.Select(x => x.Key).ToArray();

Tuesday, December 17, 2013

Imperative versus Declarative

Again, in keeping with this declarative means concise while imperative in contrast is more verbose but also more readable. This shows algorithmic approaches in which one loops through an array to progressively build a result in an imperative means and just processes the whole of the array at once with a function in a declarative undertaking.

page loading tricks

  1. Put script tags at the end of an HTML page if possible (just before </body> to allow the HTML content to load. Putting a script tag in the <head> tag in an old school way requires the .js script referenced to load completely before any HTML may be shown in the browser.
  2. Try not to have one <div> tag wrapping all page contents. If you do this, the whole of the contents have to load at once. Try to have a series of tags inside the <body> tag instead of falling immediately into a second God wrapper.

JQM is jQuery Mobile

That's what it stands for.

naming convention bridge between routes and services in ServiceStack

Building on this blog posting on ServiceStack, it would seem that the attributes magic allows a route class like so...

[Route("/widgets", "POST")]
[Authenticate]
public class WidgetCreate : Widget
{
   public string Foo { get; set; }
   public int Bar { get; set; }
   public DateTime Baz { get; set; }
   public bool Qux { get; set; }
}

 
 

...to find a dance partner such as this:

public class WidgetCreateService
{
   public MyDataTransferObjectToHandBackAsJson Post(Widget widget)
   {
      
whatever...

 
 

The name of the service class is the name of its route with "Service" appended to its end.

Monday, December 16, 2013

Batarang Dependencies Subtab

The "Dependencies" subtab within the AngularJS tab which AngularJS Batarang gives us in Google Chrome Developer Tools is pretty interesting. It seems to give us a map of all dependencies for an AngularJS project:

 
 

Click on any one item to see afferent and efferent couplings. Above, $window has been clicked and a green line out to $position shows $window afferently coupled to $position as $position depends on at least $window. Clicking on $position, as seen below, we learn that it also depends on $document! Red lines out to $document and $window show us what $position is efferently coupled to.

If you right-click on a "Live Tile" in Windows 8, an option for "Turn Live Tile Off" should appear at the the bottom of the screen.

Use this toggle to show a generic Windows 8 icon in lieu of the imagry if desired!

One of your disks needs to be checked for consistency.

Of this error:

Checking file system on C:
The type of the file system is NTFS.
Volume label is OS.
One of your disks needs to be checked for consistency. You may cancel the disk check, but it is strongly recommended that you continue. To skip disk checking, press any key within 10 seconds(s).

 
 

...which appears as you start up a laptop, this suggests:

  • It means what it says.
  • You have corrupt files or bad sectors.
  • This will come up periodically.

 
 

...which says to me: "Don't worry too much about it." Naive?

how to make a $resource service in AngularJS

angular.module('widgetsServices', ['ngResource'])
   .factory('Widgets', function($resource, $http) {
      var resource = $resource('./widgets/:id', {id: "@id"},
      {
         update: {method:'PUT'}
      });
      return resource;
   });

 
 

With that under our belt, note that this...

Widgets.save(order, function(data) {
   var orderId = data.pKey;
   $state.transitionTo("viewWidget", {id: orderId});
}, widgetControllers.reportServiceError);

 
 

...and this...

Widgets.update(order, function(data) {
   var orderId = data.pKey;
   $state.transitionTo("viewWidget", {id: orderId});
}, widgetControllers.reportServiceError);

 
 

...are examples of how to, from a controller, hit the widgetsServices defined at the top of this blog posting. The services then use RESTful routing to hit a backend such as that suggested here. Notice that we have to explictly define the "update" but not the "save" at the top of this blog posting. That is because the save is a given per this which suggests the following will always be available:

  1. get
  2. save
  3. query
  4. remove
  5. delete

 
 

$stateParams.id is another fascinating bit of AngularJS magic that I do not yet understand. It gave me the id of the current object (Widget) which I needed at a CRUD screen for editing a Widget (so that I might update the appropriate record at the database). Clearly, "$stateParams" and "Widgets" need to be in a controllers signature for this magic (above) to work.

The Network tab in Google Chrome Developer Tools...

...is vaguely Fiddleresque! It looks great for troubleshooting an API. It will show you a history of GET, POST, PUT, and DELETE calls and the status codes for each.

In ServiceStack routing, be wary of using too much inheritance in the name of the DRY principal.

The following is bad as any attempt to reach the PUT implementation will just go to the POST implementation. This is one of the pain points of inheriting everything from a class that also designates a route while only differentiating the route by way of a verb and not a signature too. It is a quirk of ServiceStack it seems. The GET route may still be reached, perhaps because the shape of the JSON that is handed to it differs from that of PUT and POST implementations. I don't really know. I’ve not really used ServiceStack before today. It does seem that the abstraction here in the name of the DRY (don't repeat yourself) principle won't fly.

[Route("/widgets", "POST")]
[Authenticate]
public class WidgetCreate : WidgetUpdate
{
}
 
[Route("/widgets/{id}", "PUT")]
[Authenticate]
public class WidgetUpdate : Widget
{
   public string Foo { get; set; }
   public int Bar { get; set; }
   public DateTime Baz { get; set; }
   public bool Qux { get; set; }
}
 
[Route("/widgets/{id}", "GET")]
[Authenticate]
public class Widget
{
   public int? Id { get; set; }
}

 
 

If the POST class inherits from the PUT class, the PUT class is walled off from accessibility in circumstances where there is not enough differentiation! It is best to repeat yourself like so:

[Route("/widgets", "POST")]
[Authenticate]
public class WidgetCreate : Widget
{
   public string Foo { get; set; }
   public int Bar { get; set; }
   public DateTime Baz { get; set; }
   public bool Qux { get; set; }
}
 
[Route("/widgets/{id}", "PUT")]
[Authenticate]
public class WidgetUpdate : Widget
{
   public string Foo { get; set; }
   public int Bar { get; set; }
   public DateTime Baz { get; set; }
   public bool Qux { get; set; }
}
 
[Route("/widgets/{id}", "GET")]
[Authenticate]
public class Widget
{
   public int? Id { get; set; }
}

an example of using the double curly brackets markup syntax in an AngularJS template

<table>
   <thead>
      <tr>
         <th>
            Mouse
         </th>
         <th>
            Vocals
         </th>
      </tr>
   </thead>
   <tbody>
      <tr ng-repeat="mouse in mice">
         <td>
            {{mouse.name}}
         </td>
         <td>
            {{mouse.squeak}}
         </td>
      </tr>
   </tbody>
</table>

Drop rows out of a HTML table in AngularJS with an update to a scope variable!

I'm making things too hard here. If you are using AngularJS, you may just drop a row in a table by dropping a record from the array that feeds the table if that array is in a $scope variable! Angular is taking some getting used to. :P

$scope.removeAsset = function(asset) {
   var counter = 0;
   angular.forEach($scope.assets, function(scopeasset) {
      if (scopeasset.pKey == asset.pKey) {
         $scope.assets.splice(counter, 1);
      }
      counter++;
   });
}

 
 

The rows must repeat in the table based upon a binding to the $scope variable like so:

<tr ng-repeat="asset in assets">

Sunday, December 15, 2013

I saw The Bad Rackets play at White Swan as yesterday bled into today at midnight.

My boss, Tim Trentham, played drums.

 
 

He is the drummer for a band called The Bad Rackets.

 
 

It was punk music.

 
 

They rocked.

Saturday, December 14, 2013

synchronous Node file mechanics

fs.readdir, fs.readFile, and fs.writeFile as detailed here all have synchronous counterparts! They are fs.readdirSync, fs.readFileSync, and fs.writeFileSync respectively. The fs stuff is Node's "File System" stuff.

Drop rows out of a HTML table in JavaScript with deleteRow!

$scope.removeAsset = function(asset) {
   var assettable = document.getElementById('assettable');
   var rows = assettable.getElementsByTagName('tr');
   for(i=0; i < rows.length; i++) {
      var cells = rows[i].getElementsByTagName('td');
      if (cells[0]) {
         var link = cells[0].innerHTML;
         if(cells[0]) {
            if(cells[0].innerHTML) {
               if (cells[0].innerHTML.indexOf("/" + asset.pKey + "/") > -1) {
                  assettable.deleteRow(i);
               }
            }
         }
      }
   }
}

To turn back off the Google voice search feature in Google Chrome...

...you must uninstall and reinstall Chrome. At this thread there is a lot of gripes about how there in an opt in for the voice search and not an opt out. I found a way out. :P To opt in to begin with you must pull up Google in Google Chrome (it only works in the Chrome Browser) and then click on the microphone icon which will appear at the very right of the search box (only in Chrome).

Friday, December 13, 2013

If you drag and drop a file into a folder in Windowsland it will not inherit the permissions of the folder as it would if you copied and pasted it there.

In this manner you may add a file to an IIS web site that users will be unable to see! Be wary of this.

Drop something out of an array in JavaScript.

$scope.deleteAsset = function(asset) {
   console.log($scope.order.assets);
   $scope.order.assets.forEach(function(key) {
      if (key == asset.pKey) {
         $scope.order.assets.splice($scope.order.assets.indexOf(key), 1);
      }
   });
   console.log($scope.order.assets);
   $scope.save();
}

It turns out you may slap :hover on anything and not just an a tag.

.danger-stop-alert a:hover ...is an example of how I am used to using hover, but if you press the :hover up against something else it will work too. I'm just now realizing this. :P The following makes a hover effect for the text inside a div without the need for a link. In fact, a link should sabotage the effect. I'll drive what happens upon a click from AngularJS's ng-click.

.danger-stop-alert {
   color: #c0392b !important;
}
.danger-stop-alert:hover {
   color: #000000 !important;
   cursor: pointer;
}

Thursday, December 12, 2013

ng-dblclick is like ng-click in AngularJS, save that it is for double clicking.

Duh.

Put a method in an AngularJS controller!

I am jamming a method into the controller I made here:

assetControllers.controller('fooCtrl', ['$scope', '$state', '$stateParams', '$modal',
   function fooCtrl($scope, $state, $stateParams, $modal) {
      var myid = $stateParams.id;
      $scope.things = [];
      $scope.things.push({asgiven: myid, asaddedtoself: myid + myid});
      
      $scope.whatever = function() {
         alert('whatever');
      }
}]);

 
 

I may call it from the click of a button if the button (in the appropriate template) looks like so:

<button class="btn btn-default" ng-click="whatever()">Cancel</button>

AngularJS controllers and templates

Something I threw together today was the ability to hit this route:

http://localhost/whatever/index.htm#/foo/13

 
 

...and get the following back in an AngularJS application:

13
1313

 
 

It comes up in a web page. The piece of HTML is in a template. The templates are summoned into a div which is a piece of a greater .html page which holds the navigation for the application. Think master pages in ASP.NET. Anyways, the most important bit of our master page is:

<div id="page-wrapper" ui-view></div>

 
 

We use the following controller. The .js file containing the controller gets referenced in the "master page" so that the controller may be found.

assetControllers.controller('fooCtrl', ['$scope', '$state', '$stateParams', '$modal',
   function fooCtrl($scope, $state, $stateParams, $modal) {
      var myid = $stateParams.id;
      $scope.things = [];
      $scope.things.push({asgiven: myid, asaddedtoself: myid + myid});
}]);

 
 

The template:

<h1 class="page-header">Foo!</h1>
<div ng-repeat="thing in things">
   {{thing.asgiven}}
   <br />
   {{thing.asaddedtoself}}
</div>

 
 

I was at first surprised that 13 + 13 equaled 1313 instead of 26, but I suppose I should not be. Everything that comes over the URL line is going to be a string. If I needed 13 to be an integer, I would have had to do some casting in my controller. How do the template and the controller get found to begin with? Well, there has to be a list of routes in app.js. It will look like so:

adminApp.config(function($stateProvider, $urlRouterProvider) {
   $urlRouterProvider.otherwise("/bar");
   $stateProvider
      .state('foo', {
         url: "/foo/:id",
         templateUrl: "templates/foo.html",
         controller: 'fooCtrl'
      })
      .state('bar', {
         url: "/bar",
         templateUrl: "templates/bar.html",
         controller: 'barCtrl'
      })
      .state('baz', {
         url: "/baz",
         templateUrl: "templates/baz.html",
         controller: 'bazCtrl'
      })
      .state('qux', {
         url: "/qux",
         templateUrl: "templates/qux.html",
         controller: 'quxCtrl'
      });
});

 
 

Yay!

Wednesday, December 11, 2013

Pie is yummy.

While I am thinking about it I wanted to show off the code I wrote for the dojo piecharting widget I allude to here and here. It follows. A coworker sent out the link here earlier suggesting that pie charts are in fact a really stupid way to try to communicate data. After reading the article I am sold on its logic. It seems like the legend for a pie chart is the real chart and the colorful circle is just some gravy for it if you think about it. Sigh. That said I was in a car crash this evening and some pie sure does sound tasty right now.

define([
   "dojo/_base/lang",
   "ah/mdo",
   "ah/Util",
   "dojo/_base/declare",
   "dojo/_base/lang",
   "dojo/dom",
   "dojo/on",
   "dijit/_WidgetBase",
   "dijit/_TemplatedMixin",
   "dojo/text!ah/widgets/PieChart.html",
   "lib/underscore",
   "dojo/dom-style",
   "dojo/dom-class",
   "dojo/dom-construct",
   "dojox/charting/Chart",
   "dojox/charting/themes/Distinctive",
   "dojox/charting/plot2d/Pie",
   "dojox/charting/DataChart",
   "dojox/charting/widget/Legend"
], function(lang, mdo, Util, declare, lang, dom, on, _WidgetBase, _TemplatedMixin,
      template, _, domStyle, domClass, domConstruct, Chart, defaultTheme,
      Pie, DataChart, Legend){
   
   var app;
   var legend;
   var pieChart;
   var pieChartData;
   var legendData;
   var error;
   
   return declare("ah.widgets.PieChart", [_WidgetBase, _TemplatedMixin], {
      templateString: template,
      
      init: function() {
         app = this.app;
      },
      
      postCreate: function() {
      },
      
      setData: function(data) {
         pieChartData = data;
         legendData = new Array();
         var totalRecords = 0;
         for (i = 0; i < data.length; i++) {
            totalRecords = totalRecords + data[i].y;
         }
         for (i = 0; i < data.length; i++) {
            var number = data[i].y;
            var description = data[i].text;
            var percentage = "-";
            if (totalRecords > 0) {
               var piece = (number/totalRecords)*100;
               if (piece >= 10) {
                  percentage = piece.toPrecision(3) + "%";
               } else {
                  percentage = piece.toPrecision(2) + "%";
               }
            }
            legendData.push({ number: number, percentage: percentage, description:
                  description })
         }
      },
      
      prepChart: function(theme) {
         if(pieChartData) {
            if(pieChart) {
               pieChart.removeSeries("series");
            } else {
               pieChart = new Chart(this.chartNode);
            }
            if (theme) {
               pieChart.setTheme(theme);
            } else {
               pieChart.setTheme(defaultTheme);
            }
            pieChart.addPlot("default", { type: Pie });
            pieChart.addSeries("series",pieChartData);
            pieChart.surface.rawNode.setAttribute('width', domStyle.get(this.chartWrapper,
                  "width"));
            pieChart.surface.rawNode.setAttribute('height', domStyle.get(this.chartWrapper,
                  "height"));
            pieChart.render();
            pieChart.surface.rawNode.childNodes[1].setAttribute('stroke-opacity','0');
            pieChart.surface.rawNode.childNodes[1].setAttribute('fill-opacity','0');
            pieChart.surface.rawNode.childNodes[2].setAttribute('stroke-opacity','0');
            pieChart.surface.rawNode.childNodes[2].setAttribute('fill-opacity','0');
            pieChart.surface.rawNode.childNodes[3].setAttribute('stroke-opacity','0');
            pieChart.surface.rawNode.childNodes[3].setAttribute('fill-opacity','0');
            Legend({chart:pieChart}, this.legend);
            legend = dom.byId("dojox_charting_widget_Legend_0");
            if (legend) {
               domClass.add(legend, "display-none");
            }
         } else {
            error = "The call to prepChart does not have a preceding call to setData and thus
                  is moot.";
            console.log(error);
         }
      },
      
      prepLegend: function(table) {
         if (pieChartData) {
         while (table.hasChildNodes()) {
            table.removeChild(table.lastChild);
         }
         var header = domConstruct.create("tr", {}, table)
         domConstruct.create("td", { innerHTML: "quantity & percentage", colspan: 4, class:
               "right-padding" }, header);
         
         if (legend) {
            var tableRows = legend.childNodes[0].childNodes[0].childNodes;
         }
         
         for (i = 0; i < legendData.length; i++) {
            var row = domConstruct.create("tr", {}, table);
            var legendKey = "";
            if (legend) {
               legendKey =
                     legend.childNodes[0].childNodes[0].childNodes[i].childNodes[0].innerHTML;
               }
               domConstruct.create("td", { innerHTML: legendData[i].number, class:
                     "data-column" }, row);
               domConstruct.create("td", { innerHTML: legendData[i].percentage, class:
                     "data-column" }, row);
               domConstruct.create("td", { innerHTML: legendData[i].description, class:
                     "description-column" }, row);
               domConstruct.create("td", { innerHTML: legendKey }, row);
            }
         } else {
            error = "The call to prepLegend does not have a preceding call to setData and
                  thus is moot.";
            console.log(error);
         }
      },
      
      getLegendData: function() {
         return legendData;
      },
      
      getError: function() {
         pieChartData = null;
         return error;
      },
      
      getSvg: function() {
         return pieChart.surface.rawNode;
      }
   });
});

Use before/after/content in CSS to wrap blockquote copy in quotes.

I steal what follows from here:

blockquote:before, blockquote:after {
   content: '"';
}

ui-sref in Angular convention

This more or less creates an href tag which takes one to the noodle.salad controller while passing 42 as the id:

<a ui-sref="noodle.salad({id: 42})">

 
 

This suggests a "state transition" will be triggered as part of the process when one clicks the link that gets made.

Tuesday, December 10, 2013

trying to learn AngularJS

Today I saw this error:

You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

 
 

This suggested that it came from screwing up an assignment like this:

var assetControllers = angular.module('assetControllers', ['serverServices', 'services',
      'filters']);

 
 

The problem befell me when I broke one Angular module which looked (let's pretend) like so:

angular.module('filters', [])
   .filter('foo', function() {
      return function(input) {
         return input * 2;
      }
   }).filter('bar', function() {
      return function(input) {
         return input * 3;
      }
   });

 
 

...up into to separate files like so:

  1. angular.module('foo', [])
       .filter('foo', function() {
          return function(input) {
             return input * 2;
          }
       });
       

  2. angular.module('bar', [])
       .filter('bar', function() {
          return function(input) {
             return input * 3;
          }
       });

In the HTML file bootstrapping the Angular stuff, I was smart enough to change the script tag I had for the consolidated file into two separate script tags for what became two separate files. (It seems one has to bootstrap modules with script tags as there is not an AMD paradigm.) However, the error I saw came because I had not yet changed the line of code at the very top of this blog posting to:

var assetControllers = angular.module('assetControllers', ['serverServices', 'services', 'foo',
      'bar']);

 
 

I suppose I have a lot to learn. I asked a coworker how he learned AngularJS and he responded that he worked on a project with others in which they pulled the code for what he called the seed project and hammered on it until it became something else they needed. Scott Bellware is tweeting of Angular, at least as of today, and links to tutorials he has offered include:

Ctrl-Shift-F in Sublime

...gives you a power akin to that of Agent Ransack. You may pick a folder and grep against it, searching every file in the folder for a particular string. w00t

Monday, December 9, 2013

.whenAll is an emerging concept in JavaScript for acting when all of the promises in an array of promises have resolved.

This is something you will have to roll yourself. For example this suggests you may do so in jQuery by aggregating instances of .when like so:

(function($) {
   $.whenAll = function() {
      return $.when.apply($, arguments);
   };
})(jQuery);

 
 

This touches on .when in jQuery in turn. At my place of work, we use a common library for interacting with Web SQL databases and it supports .whenAll as seen here:

populatePieChart: function(workOrders) {
   var pieChart = this.pieChart;
   var domNodeForLegend = dom.byId("table");
   var promises = workOrders.map(function(workOrder) {
      return workOrder.mdoElt.fetchWorkStatus().then(function(workStatus) {
         return workStatus;
      });
   });
   app.mdo.MDO.whenAll(promises).then(function(workStatuses) {
      var data = [];
      workStatuses.forEach(function(workStatus) {
         var isMatch = false;
         data.forEach(function(datum) {
            if (datum.text == workStatus) {
               datum.y = datum.y + 1;
               isMatch = true;
            }
         });
         if (!isMatch) {
            data.push({y: 1, text: workStatus});
         }
      });
      pieChart.setData(data);
      pieChart.prepChart();
      pieChart.prepLegend(domNodeForLegend);
   });
}

 
 

If I wanted to do the same thing without .whenAll there is a dirtier way to do it like so:

populatePieChart: function(workOrders) {
   var pieChart = this.pieChart;
   var domNodeForLegend = dom.byId("table");
   var data = [];
   var counter = 0;
   workOrders.forEach(function(workOrder) {
      workOrder.mdoElt.fetchWorkStatus().then(function(workStatus) {
         var isMatch = false;
         data.forEach(function(datum) {
            if (datum.text == workStatus) {
               datum.y = datum.y + 1;
               isMatch = true;
            }
         });
         if (!isMatch) {
            data.push({y: 1, text: workStatus});
         }
         counter++;
         if (counter == workOrders.length) {
            pieChart.setData(data);
            pieChart.prepChart();
            pieChart.prepLegend(domNodeForLegend);
         }
      });
   });
}

 
 

In both cases, I am attempting to aggregate data for the pie chart I made and I need to get a data point off of each workOrder in workOrders which is returned by way of a promise (we must go on a fishing excursion in the database) coming back from .fetchWorkStatus() thus creating the challenge for .whenAll to solve.

Associate a check in with a different case in FogBugz Kiln.

A check in with a comment such as:

Case 123: removing all the time wasting loops I originally added in the name of a performance gain

 
 

...will associate the check in with case 123. If this is a mistake and you wanted to associate the check in with case 124, you may do so by:

  1. going into the repository in Kiln
  2. clicking on the "History" tab
  3. finding the check in and clicking upon it to enter its details
  4. clicking the "Cases" subtab
  5. using "Add a case" to add a case number
  6. deleting the prior case number

flatuicolors.com

flatuicolors.com has... you guessed it... flat UI colors! Click on any swatch to copy the hexadecimal value to your clipboard! They seem to be:

Turquoise #1abc9c
Emerald #2ecc71
Peter River #3498db
Amethyst #9b59b6
Wet Asphalt #34495e
Green Sea #16a085
Nephritis #27ae60
Belize Hole #2980b9
Wisteria #8e44ad
Midnight Blue #2c3e50
Sun Flower #f1c40f
Carrot #e67e22
Alizarin #e74c3c
Clouds #ecf0f1
Concrete #95a5a6
Orange #f39c12
Pumpkin #d35400
Pomegranate #c0392b
Silver #bdc3c7
Asbestos #7f8c8d

Saturday, December 7, 2013

WADL versus WSDL

stackoverflow asserts that WSDLs (Web Services Description Language) are of SOAP (XML) while WADLs (Web Application Description Language) are of REST (JSON). A WADL in and of itself seems to have a XML shape where it is speced. See: this

how to name mocha tests

I made a pie chart dojo/dojox widget at work this week. Upon making a first pass at testing and then braving a review, a coworker suggested that the names of my tests could be better. We ended up changing up what I had to:

  • Pie Chart Widget
    • setData method
      • when y/text data is supplied
        • should have legend data with percentages
    • prepLegend method
      • when is called following data being set
        • should be no error
      • when is called without data being set
        • should yield appropriate error
    • prepChart method
      • when is called without data being set
        • should yield appropriate error
      • when is called following data being set
        • when no theme is specified
          • should have the Distinctive theme
        • when a theme is specified
          • should use theme

 
 

I feel what is above mostly speaks on its lone in terms of what is good form. One thing I will add is that I was under the misimpression for a while that the describes in a mocha test should strictly be three tiers deep which is not so. Just use as many tiers as makes sense. Here are the actual tests themselves:

define([
   "dojoTest/fixtures/TestImage",
   "dojoSrc/Util",
   "dojoSrc/widgets/PieChart",
   "dojo/Deferred",
   "dojox/charting/themes/Adobebricks",
   "dojox/charting/themes/Distinctive",
   "dojo/dom-construct"
], function(TestImage, Util, PieChart, Deferred, adobebricks, distinctive, domConstruct) {
   describe("Pie Chart Widget", function() {
      describe("setData method", function() {
         describe("when y/text data is supplied", function() {
            var legendData;
            
            before(function() {
               var data = [];
               data.push({y: 15, text: "Buchanan"});
               data.push({y: 30, text: "Coolidge"});
               data.push({y: 13, text: "Fillmore"});
               data.push({y: 20, text: "Garfield"});
               data.push({y: 37, text: "Nixon"});
               data.push({y: 11, text: "Polk"});
               data.push({y: 27, text: "Taft"});
               var widget = new PieChart();
               widget.setData(data);
               legendData = widget.getLegendData();
            });
            
            it("should have legend data with percentages", function() {
               assert.isTrue(legendData[0].number == 15);
               assert.isTrue(legendData[0].percentage == "9.8%");
               assert.isTrue(legendData[0].description == "Buchanan");
               
               assert.isTrue(legendData[1].number == 30);
               assert.isTrue(legendData[1].percentage == "19.6%");
               assert.isTrue(legendData[1].description == "Coolidge");
               
               assert.isTrue(legendData[2].number == 13);
               assert.isTrue(legendData[2].percentage == "8.5%");
               assert.isTrue(legendData[2].description == "Fillmore");
               
               assert.isTrue(legendData[3].number == 20);
               assert.isTrue(legendData[3].percentage == "13.1%");
               assert.isTrue(legendData[3].description == "Garfield");
               
               assert.isTrue(legendData[4].number == 37);
               assert.isTrue(legendData[4].percentage == "24.2%");
               assert.isTrue(legendData[4].description == "Nixon");
               
               assert.isTrue(legendData[5].number == 11);
               assert.isTrue(legendData[5].percentage == "7.2%");
               assert.isTrue(legendData[5].description == "Polk");
               
               assert.isTrue(legendData[6].number == 27);
               assert.isTrue(legendData[6].percentage == "17.6%");
               assert.isTrue(legendData[6].description == "Taft");
            });
         });
      });
      
      describe("prepLegend method", function() {
         describe("when is called following data being set", function() {
            var error
            
            before(function() {
               var data = [];
               var widget = new PieChart();
               widget.setData(data);
               widget.prepChart();
               var table = domConstruct.create("table");
               widget.prepLegend(table);
               error = widget.getError();
            });
               
            it("should be no error", function() {
               assert.isTrue(error == null);
            });
         });
         
         describe("when is called without data being set", function() {
            var error
            
            before(function() {
               var widget = new PieChart();
               widget.prepChart();
               var table = domConstruct.create("table");
               widget.prepLegend(table);
               error = widget.getError();
            });
            
            it("should yield appropriate error", function() {
               assert.isTrue(error == "The call to prepLegend does not have a preceding call
                     to setData and thus is moot.");
            });
         });
      });
      
      describe("prepChart method", function() {
         describe("when is called without data being set", function() {
            var error;
            
            before(function() {
               var widget = new PieChart();
               widget.prepChart();
               error = widget.getError();
            });
            
            it("should yield appropriate error", function() {
               assert.isTrue(error == "The call to prepChart does not have a preceding call to
                     setData and thus is moot.");
            });
         });
         
         describe("when is called following data being set", function() {
            describe("when no theme is specified", function() {
               var firstPieSliceColor;
               var distinctiveComparison;
               
               before(function() {
                  var data = [];
                  data.push({y: 15, text: "Buchanan"});
                  data.push({y: 30, text: "Coolidge"});
                  data.push({y: 13, text: "Fillmore"});
                  data.push({y: 20, text: "Garfield"});
                  data.push({y: 37, text: "Nixon"});
                  data.push({y: 11, text: "Polk"});
                  data.push({y: 27, text: "Taft"});
                  var widget = new PieChart();
                  widget.setData(data);
                  widget.prepChart();
                  var svg = widget.getSvg();
                  firstPieSliceColor = svg.childNodes[3].childNodes[0].getAttribute("fill");
               });
               
               it("should have the Distinctive theme", function() {
                  assert.isTrue(firstPieSliceColor == "rgb(73, 124, 145)");
               });
            });
            
            describe("when a theme is specified", function() {
               var firstPieSliceColor;
               var distinctiveComparison;
               
               before(function() {
                  var data = [];
                  data.push({y: 15, text: "Buchanan"});
                  data.push({y: 30, text: "Coolidge"});
                  data.push({y: 13, text: "Fillmore"});
                  data.push({y: 20, text: "Garfield"});
                  data.push({y: 37, text: "Nixon"});
                  data.push({y: 11, text: "Polk"});
                  data.push({y: 27, text: "Taft"});
                  var widget = new PieChart();
                  widget.setData(data);
                  widget.prepChart(adobebricks);
                  var svg = widget.getSvg();
                  firstPieSliceColor = svg.childNodes[3].childNodes[0].getAttribute("fill");
               });
               
               it("should use theme", function() {
                  assert.isTrue(firstPieSliceColor == "rgb(127, 37, 24)");
               });
            });
         });
      });
   });
});

Node-Webkit ...and some CSS!

I saw Richard Anaya of Evernote speak on Node-Webkit at JavaScript Austin on Thursday night. Node-Webkit is a project based upon Chromium (the open source web browser project which powers the Google Chrome browser) and runs a browser at the desktop while using Node as a backend server-side technology. When you pull down the source code you will end up with an .exe file which when run will display a "Hello World" app. A browser will spin up at your desktop pointing to an .html file kept in the stuff you downloaded. The art of using Node-Webkit is one in which one refactors the dummy app into something meaningful, bringing in more HTML and JavaScript. Mr. Anaya asserted that, every app has a manifest which specifies a name for the project and a starting point. The GitHub site for Node-Webkit seems to suggest that this is a package.json file shaped like so:

{
   "name": "nw-demo",
   "main": "index.html"
}

 
 

Here, index.html is one's starting point and it could be changed out with another file if so desired. HTML and JavaScript may be referenced locally by way of file path or remotely by way of URL. You choose. This talk came with plenty of CSS that is new to this space such as:

-webkit-app-region: drag;

 
 

...which will make an element a place you may click and then drag to drag the whole of the application about the desktop. You may hide all title bars and borders in a Node-Webkit desktop app (again with interesting desktop-flavored CSS) and just use your own handles in this manner for this functionality. On a tangent, this talk also showed off plenty everyday CSS and some of it was new to me. For example:

.whatever: nth-child(3n-7)
{
   background-size: cover;
   height: calc(20% + 100px);
}

 
 

window.close() is a JavaScript example of how you might close one of the apps. Using Node one may write to flat files locally and do file IO stuff. That is where the Node end of things comes in. The example that was on exposition really used Node sparingly in this manner when it had to but otherwise showed off how easy it was to use the frontend skills you already have (HTML/CSS/JavaScript) to make a desktop application. Flat files that got saved out just had JSON in them. One may zip up all of their HTML/CSS/JavaScript files and rename the .zip file to package.nw and set package.nw next to the .exe file to clean up the noise of lots of files surrounding the .exe. The .exe will "know" by convention to try to find and look into the package.nw. One may take things one step further by using a tool such as The Engima Protector to ball up the supporting files into the .exe itself so that the application may be handed to another with only a single file (the .exe) as a deliverable. Something else I had not seen before was a man with a bald spot split in half by a Mohawk, but I seem to have captured it in my photo.

Friday, December 6, 2013

ionic

...uses AngularJS in the mobile space. Get it here.

using calc in modern CSS

calc will calculate an offset from a percentage measurement in pixels.

.pie-chart-calc {
   height: calc(20% + 100px);
}

disk icon in Beyond Compare is all important

When using Beyond Compare to merge files as the "Tool Resolve" option for TortoiseHg Workbench (Mercurial), you will see four panes, three side by side up top showing version one (left), version two (right), and their synergy, and one below where one may click a disk icon to save off what has been hodgepodged together.

AngularJS Batarang

This gives you an "AngularJS" tab in Google Chrome Developer Tools for further Angular-specific debugging!

Matlab

This appears to be a hodgepodge of scripting language and charting tools.

Wednesday, December 4, 2013

using commas to consolidate CSS styles

This...

.displaynone {
   display: none;
}
.hideInnerDivs div {
   display: none;
}

 
 

...may be consolidated to...

.displaynone, .hideInnerDivs div {
   display: none;
}

 
 

...without issue! In both examples, displaynone hides the immediate thing it styles (and everything inside) while hideInnerDivs does not hide the immediate thing it styles, just the div tags nested within said DOM node. The second effect is a cascading effect. Rock!

the better way to array

A coworker suggested to me today that...

var data = [];

 
 

...is a better way to new up an array in JavaScript than...

var data = new Array();

 
 

...as the second approach might confuse an eighty-year-old who has only done C and C++ into believing that memory is being set aside on "the stack" (which doesn't exist in JavaScript wherein everything goes on "the heap" so to speak). The first way does seem like a better convention.

Type certmgr.msc at the start menu in Windows 7 to get the certmgr program.

It will list the signing certificates you have installed.

How to rotate a shape in PowerPoint (I had to Google it so I suppose it merits a blog posting.)

One: If you click on a shape or drag a box around it, you will see the typical selection box with nodes you may tug on to resize the shape.

 
 

Two: If you put the cursor over the green node that is sort of on a stick sprouting off of the rectangle, the cursor will turn into a rotation symbol. The green node is the key to everything. I would not have figured this out without Googling it.

 
 

Three: Drag and hold the mouse. You will get a preview of the rotation to be.

 
 

Four: Let go.