PicNet Custom Software Development

.Net and Javascript Development

A faster, better sql server and sql azure log appender for log4net

Posted on clock May 11, 2011 01:44 by author guido

After much effort, trying to get the default DatabaseAppender working in log4net I decided to write my own, so with the help of one of my alpha geeks (Tnx Chinsu) we created this awesome (its awesome because it uses batch inserts and actually works on Azure) database appender for Log4Net.

https://gist.github.com/965366

Use at your own risk, I did have to modify the code slightly to remove an internal dependency and I did not test this in prod after the modification.  However the modification was very minor and should not cause any issues.

Also remember to schedule a service that deletes your old log files.

Guido Tapia


Understanding Nancy - Sinatra for .Net

Posted on clock March 22, 2011 08:39 by author guido

For a project we are currently working on here at PicNet we decided to forgo the bloat of ASP.Net and Mvc and go for a super light weight web platform. We tried Kayak but this was a little too 'bare' so we then shifted our attention to Nancy which is a Sinatra clone (well, "inspired" project) in .Net.

We've now been working with Nancy for a few weeks and have thoroughly enjoyed the experience. One of the tougher parts of getting started with Nancy is the lack of documentation and tutorials, so I thought I would put what I've learned over the last week or so down on paper in the hopes that others may benefit.

This post is an introduction to the internal components of Nancy and how the nuts and bolts work (from a high level). In upcoming posts I hope to delve deeper into some of these areas and do a tutorial to bring all this into context.

Host
Capturing http requests and sending responses back to the client are left to the 'Host'. The host is really a web server and Nancy comes pre-bundled with a couple of options. You can use IIS, WCF and finally Nancy comes with its own "Self" implementation of the low level http hosting functionality. Both WCF and Self hosts can be used in windows services and in command line apps.

The host is also responsible for initialising and delegating request processing to the NancyEngine. Internally (and hence not really important uless developing Nancy) the host usually uses a NancyBootstrapper to initialise the engine. The bootstrapper is responsible for initializing all modules of the system, we will iterate through most of those models in this document.

Example: Setting up a WCF host with http and windows authentication binging:

WebHttpBinding whb = 
  new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
whb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

var host = new WebServiceHost(new NancyWcfGenericService(), new Uri(serverUrl));
host.AddServiceEndpoint(typeof (NancyWcfGenericService), whb, "");      
ServiceMetadataBehavior smb = new ServiceMetadataBehavior {
  HttpGetEnabled = true
};
host.Description.Behaviors.Add(smb);
host.Open();



Bootstrapper
Internally, Nancy uses the bootstrapper to initialise all required modules and the DI container that will be used by other core modules. The default Nancy project comes with its own IoC implementation but if you are a fan of other IoC containers then Nancy comes pre-bundled with support for Ninject, StructureMap, Unity and Windsor.

NancyEngine
The NancyEngine is the brains that the Host delegates requests to. The engine manages the request lifecycle. When the Engine receives a request from the Host, the engine:

  • Creates the request context
  • Invokes the pre-request hook (if specified). If the pre-request hook returns a Response then then no Routing is used as Nancy assumes the Request has been processed.
  • If the pre-request hook does not return a Response then Nancy looks for a valid Route to handle this Request. Routes are managed by Modules. (Note: Modules also have pre/post request hooks described below).
  • The post-request hook is then called with the current context.

If you are not writing your own bootstrapper I would leave the pre/post hooks alone and use the NancyModule’s Before/After pipeline support.

NancyContext
The NancyContext has a reference to the Request, Response (once it has been resolved) and the Request or context Items. The context Items is just an in-memory dictionary ideal for storing Request wide data.

Request
The Request is a pretty standard http request having a Body, Cookies, Session, Files, Form, Headers, the Method (get/post/etc), Protocol, Query and Uri details.

NancyModule
The module(s) register the routes handled by the system. Each module can have a root path (module path) meaning that it is only responsible for that path branch.

Modules can also define pre request hooks by adding items to the Before member. post-request hooks are added using the After member. The rules for pre/post hooks are the same as for the NancyEngine hooks. Basically if a pre-request hook returns a response then processing of that Request ends and the Response is passed to the post-request hook.

The module also has access to the current context.

Example: Setting up simple routes in a custom NancyModule

public class MyModule : NancyModule
{
  public IEModule() {            
      Get["/"] = x => GetMainWindow();
      Get["/resources/{name}"] = x =>Response.AsFile(x.name);
      Get["/dl/{filePath}"] = x => 
        GetDownloadResponse(Response.AsImage(filePath), filePath); 
      Post["/open/{filePath}"] = x => 
        GetDownloadResponse(Response.AsImage(filePath), filePath);
      Post["/ul/{dirid}/{fileName}"] = x => UploadFile(x.dirid, x.fileName);
    }
  }
  private Response GetDownloadResponse(Response r, string fileName) {
    r.Headers.Add("Expires", 
      DateTime.Now.AddSeconds(1).ToUniversalTime().ToString());      
    r.Headers.Add("content-disposition",
      "attachment;filename=" + new FileInfo(filePath).Name);
    return r;
  }
...

Response
Each request has to return a Response to the client. There are currently implicit casts in-place that allow you to return objects of the following types:

All of the non Response types are simply wrapped in a Response. The Response has the StatusCode, Headers, Cookies, ContentType and the Contents (as a stream).

The module also has access to helper methods that you can use to create Reponses. These are:

  • Reponse.AsFile
  • Reponse.AsCss
  • Reponse.AsImage
  • Reponse.AsJs
  • Reponse.AsJson
  • Reponse.AsRedirect
  • Reponse.AsXml

Views / ViewEngines
Nancy comes pre-packed with support for NDjango, Razor and Spark. Of course you could also just server html.

Example: Delegating rendering of model data to the current View engine:

Get["/"] = x =>
{
  IEnumerable model = 
    DB.BeerEvents.FindAllByEventDate(DateTime.Now.to(DateTime.Now.AddYears(1)));
  model = model.OrderBy(e=>e.EventDate).Take(10);
  // Current view engine will render this model
  return View["views/index",model.ToArray()]; 
};

Conclusion
That is pretty much every important module in Nancy. Who would have thought that a fully functional web framework was conceptually so simple. Next bat time we will go through a step by step tutorial in getting started with Nancy.

Thanks

Guido Tapia

Software Development Manager

PicNet Pty Ltd


PicNet's Closure Library Controls Now Public!!!

Posted on clock January 11, 2011 03:53 by author guido

It gives me great pleasure to anounce that PicNet's closure control library is now public.  We have started with only 2 of our controls but over the next few weeks we will port all of our control code to this project.

For a demo just visit http://picnet.github.com/picnet_closure_repo/demos/.

The google closure library is a project that I think is greatly under represented and I hope that this on going contribution does something to fix that.

Currently the library includes a Date Range Picker and a 'off the page' slide in and out panel.  See the demo for the full details.  

This demo will also be updated every time a new Control/Component is added.

Thanks

Guido Tapia


Google Closure Template Project - Getting Started Quickly with Google Closure Tools

Posted on clock October 15, 2010 02:44 by author guido

One of the hardest things about getting started properly with Google Closure Tools is that it has a huge amount of framework boilerplate that needs to be organised in order to write your first line of code. I have found that the effort is definately worthwhile but the process can definatelly be simplified.  These views are shared by many in the community and projects like plovr from Michael Bolin (author of the most awesome Closure: The Definitive Guide) offer alternatives to get started in a more efficient and intuitive way.

I created this sample project to get you going on your own closure project very quickly.  I did not use plovr as I'm not a fan of the additional server (hence additional deployment step, hence one more thing that can go wrong) design.

To get started with this sample project you need to do the following:

  1. Download this zip and extract somewhere on your dev box <installdir>.
  2. Download (if required) python 2.6 or 2.7.  Note: do not download 3+ as the calcdeps.py script does not work in 3 without modifications.
  3. SVN Checkout 'http://closure-library.googlecode.com/svn/trunk' to <installdir>\lib\closure-library (which is currently empty).  You may want to set up externals if you are using svn in your project.  Once this step is completed you should have the following directory tree in your project <installdir>.
    • <installdir>\src\...
    • <installdir>\lib\soy\...
    • <installdir>\lib\closure-library\
    • <installdir>\lib\closure-library\closure\...
    • <installdir>\lib\closure-library\third_party\...
  4. Edit <installdir>\build.bat, ensure python install path is correct
  5. Run <installdir>\build.bat
  6. If everything above worked and both <installdir>\index.html and <installdir>\index.compiled.html show the following text:

    Sum

    Expected Value: 15

    Actual Value: 15

 

Thats it, you have a running closure project, you can now use goog.require / goog.provide in your own source and have the above scripts manage all your dependencies.  You can also use soy templates without any additional work.  

 

Now just look around the code and familiarise yourself with the structure of the code.  I'll go through the main items here:

 

build.bat: The build file.  I used a windows batch file as using Ant is too java specific, using NAnt or MSBuild is too .Net specific.  Apologies to non win people but changing this to any other build tool should be very easy.

externs.js: If your source requires access to external APIs then they need to be defined in this file.  See here for documentation on extern files (http://code.google.com/closure/compiler/docs/api-tutorial3.html)  

index.html: A development html file.  This is used in development mode to debug your application.

index.compiled.html: Production html file.  This file includes the compiled javascript and soy files

requirements.js: This file defines the entry point into the application.  This is required as the closure compiler and calcdeps.py do not accept html files as valid input files.

deps.js: This file is created during the build process and its role is to define the dependencies of the application.  This dependency tree is used in development mode (index.html) to load all the neccessary js files.

lib\: Contains the compiler, the closure library, soy library files, etc

lib\closure-library\: An svn extern link to http://closure-library.googlecode.com/svn/trunk (You need to set this up yourself as its 20+ MB)

src\: Your source code.  It is recommended you use a Java like namespace directory structure.  Eg.  Class picnet.ui.tools.Grid should live in src\picnet\ui\tools\Grid.js file.  Note: google use lowercase file names (i.e. grid.js) but this makes little sense to me so I choose to spit in the face of conventions.

 

Thanks All

 

Guido Tapia


IndexedDB Google Closure extern file

Posted on clock August 29, 2010 04:03 by author guido

I've been doing some work with IndexedDB (on Mouse Eye Tracking) recently and created a closure extern file (download) to help with the process.

 

Hope this helps someone :)

 

Please let me know if someone would like me to create an open source project somewhere to continue improving this.

 

Note: The specs and FF implementation appear to be changing very quickly so this is just a guide as I'm sure it will be out of date soon.

 

Please assume MIT license.

 

Thanks

 

Guido Tapia


Annotated, Google Closure Javascript Compiler - Visual Studio Snippets

Posted on clock June 3, 2010 09:12 by author guido

I have spoken in the past about my great respect for the closure project.  This project brings some semblance of order to the chaotic and dangerous world of large application javascript development.  However it also has some problems, the biggest of this being the fact that it is very verbose.  This small set of Visual Studio 2010 snippets aims to aliviate that issue when developing in VS2010.  I have been using a similar set of these snippets in production for many months (in the Mouse Eye Tracking service) and whilst not being industrial strength they are ready for you to get some efficiencies from.

Why Visual Studio?

At PicNet most of our server side code is .Net so when developing html and javascript we also use Visual Studio (saves opening up a new IDE).  However the snippet template language is just XML so if you are interested in doing an XSLT into another language please get in contact with me and we can bring that into the project also.

How to install

 

  • Download the vsi file
  • Run (double click - will be recognized by Visual Studio) and install
  • Ready to use (by typing the shortcut name followed by TAB)

 

Note: The VSI file is just a zip file with the extension renamed so if you are worried about running strange files just rename to .zip and import the snippets manually into the IDE.

Current Snippets

ShortcutContentDeclarations
jsclass
/**
 * @fileoverview $classcomments$
 *
 */
goog.provide('$namespace$.$classname$');
goog.require('$require$');
/**
 * @constructor
 * @param {string} $param1$ A sample parameter.
 */
$namespace$.$classname$ = function($param1$) {
	$contents$
};
  • classcomments: Comments describing this class
  • namespace: The name of this class' namespace
  • classname: The name of this class
  • require: Classes to import
  • param1: The name of the first constructor parameter.
  • contents: The contents of the class.
jsconst
/**
 * @const
 * @type {$typename$}
 */
$namespace$.$constname$ = $constvalue$;
  • typename: The type of this constant.
  • namespace: The namespace that this constant resides in.
  • constname: The name of this constant.
  • constvalue: The value of this constant.
jsconstructor
/**
 * @constructor
 * @param {string} $param1$ A sample parameter.
 */
$namespace$.$classname$ = function($param1$) {
	$contents$
};
  • namespace: The name of this class' namespace
  • classname: The name of this class
  • param1: The name of the first constructor parameter.
  • contents: The contents of the class.
jsenum
/**
 * $enumcomments$
 * @enum {string}
 */
$namespace$.$enumname$ = {
  ON: 'on',
  OFF: 'off'
};
  • enumcomments: Comments describing this enumeration
  • namespace: The name of this class' namespace
  • enumname: The name of this enumeration
jsextends
* @extends {$namespace$.$inherits$}
  • namespace: The name of this class' namespace
  • inherits: The name of the inherited class
jsimpclass
/**
 * @fileoverview $classcomments$
 *
 */
goog.provide('$namespace$.$classname$');
goog.require('$require$');
/**
 * @constructor
 * @implements {$namespace$.$implements$}
 * @param {string} $param1$ A sample parameter.
 */
$namespace$.$classname$ = function($param1$) {
	$contents$
};
  • classcomments: Comments describing this class
  • namespace: The name of this class' namespace
  • classname: The name of this class
  • implements: The name of the implemented interface
  • require: Classes to import
  • param1: The name of the first constructor parameter.
  • contents: The contents of the class.
jsimplements
* @implements {$namespace$.$implements$}
  • namespace: The name of this class' namespace
  • implements: The name of the implemented interface
jsinherits
goog.inherits($namespace$.$classname$, $namespace$.$inherits$);
  • namespace: The name of this class' namespace
  • classname: The name of this class
  • inherits: The name of the inherited class
jsinterface
/**
 * @fileoverview $interfacecomments$
 *
 */
goog.provide('$namespace$.$interfacename$');
goog.require('$require$');
/**
 * @interface
 */
$namespace$.$interfacename$ = function() {};
$namespace$.$interfacename$.prototype.$methodname$ = function() {};
  • interfacecomments:
  • namespace: The name of this interface's namespace
  • interfacename: The name of this interface
  • require: Classes to import
  • methodname: A method definition in this interface.
jsparam
/**
 * @param {string} $param1$ A sample parameter.
 */
  • param1: The name of this parameter.
jsparaminline
* @param {string|number=} $param1$ A sample parameter.
  • param1: The name of this parameter.
jsprivate
		/**     
		 * @type {$typename$}
     * @private
     */
    this.$attrname$ = $declaration$;
  • typename: The name of this attribute's type
  • attrname: The name of this attribute
  • declaration: The initial declaration of this attribute
jsprivateinline
* @private
 
jsprivatevar
		/**
		 * @type {$typename$}
     * @private
     */
    var $attrname$ = $declaration$;
  • typename: The name of this attribute's type
  • attrname: The name of this attribute
  • declaration: The initial declaration of this attribute
jsprotected
		/**     
		 * @type {$typename$}
     * @protected
     */
    this.$attrname$ = $declaration$;
  • typename: The name of this attribute's type
  • attrname: The name of this attribute
  • declaration: The initial declaration of this attribute
jsprotectedinline
* @protected
 
jsprotomem
		/**
 * @param {*=} $param1$
 */
$namespace$.$classname$.prototype.$methodname$ = function($param1$) {				
		return this.member * args;
};
  • namespace: The name of this class' namespace
  • classname: The name of this class
  • methodname: The name of this method
  • param1: The name of the sameple parameter
jsprovide
goog.provide('$namespace$.$classname$');
  • namespace: The name of this class' namespace
  • classname: The name of this class
jsrequire
goog.require('$namespace$.$require$');
  • namespace: The name of this class' namespace
  • require: Classes to import
jsreturn
* @return {string}
 
jssubclass
/**
 * @fileoverview $classcomments$
 *
 */
goog.provide('$namespace$.$classname$');
goog.require('$require$');
/**
 * @constructor
 * @extends {$namespace$.$inherits$}
 * @param {string} $param1$ A sample parameter.
 */
$namespace$.$classname$ = function($param1$) {
	$contents$
};
goog.inherits($namespace$.$classname$, $namespace$.$inherits$);
  • classcomments: Comments describing this class
  • namespace: The name of this class' namespace
  • classname: The name of this class
  • inherits: The name of the inherited class
  • require: Classes to import
  • param1: The name of the first constructor parameter.
  • contents: The contents of the class.
jstypedef
/** @typedef {$type$} */
$namespace$.$typedefname$;
  • namespace: The name of this class' namespace
  • type: The composite type of this definition
  • typedefname: The name of this typedef

License

MIT

Development

If you are interested in helping mantain the source code, let me know and we'll organise something.  

Mantaining the code is very straight forward simply:

 

  • Download the latest source.
  • Open the solution in visual studio
  • Edit the snippets in the \snippets directory
  • F5 to build a new VSI file and the supporting documentation
  • Install the VSI as described above to test your changes

 

 

Guido Tapia

Software Development Manager

PicNet Pty Ltd


Split Testing (A/B Testing) in ASP.Net Mvc

Posted on clock May 11, 2010 10:21 by author guido

Working on our website heat maps product, Mouse Eye Tracking, has allowed us to really get into some of the more lean and super agile approaches to developing software.  Something that we have loved doing recently is Split Testing (or A/B Testing). Its really amazing how much time you can save when using techniques like this.

Basically for our heat map product we try every deployment out before investing huge amount of time into it.  For example.  We wanted to see if the features video could be made more prominent.  So what we did is created a page for this approach, published it and compared results.  We realised that this in fact was a waste of time and left the page exactly as it was.

There are plenty of products out there that allow you to do AB testing but most of those are CMSs which is useless when your site is in a server side language so what we use is a custom ASP.Net Mvc solution that works a real treat.  It's this solution that I hope to describe in this post.

SplitABController

The brains of the whole operation is a new controller (descendant of System.Web.Mvc.Controller) that allows you to provide multiple views for each ViewResult.  This is kind of hard to explain so why not just show some code:

 

    using System;

    using System.Web;

    using System.Web.Mvc;

 

    public abstract class SplitABController : Controller

    {

        private static readonly Results results = new Results();

        private const string B_TEST_SUFFIX = "_B";

        private const string SPLIT_TEST_VIEW_COOKIE_NAME = "SPLIT_TEST_VIEW_COOKIE";

        private static ViewFilesCache cache;

 

        public static Results GetSplitTestResults() { return results; }

 

        protected over ride void OnActionExecuting(ActionExecutingContext filterContext)

        {

            AddSplitTestResultsToResultsMap(filterContext);

            base.OnActionExecuting(filterContext);

        }

 

        private void AddSplitTestResultsToResultsMap(ActionExecutingContext filterContext)

        {

// If last request was not for a split test view then just return

            if (Request.Cookies[SPLIT_TEST_VIEW_COOKIE_NAME] == null) return;

 

// Add this controller/action to the results of the split test

            ResultRow rr = ResultRow.FromString(Request.Cookies[SPLIT_TEST_VIEW_COOKIE_NAME].Value);

            results.RemoveOneFromResults(rr);

            rr.ToControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;

            rr.ToAction = filterContext.ActionDescriptor.ActionName;

            results.AddOneToResults(rr);                        

        }                

 

/// <summary>

/// If the view has a _B counterpart then we mark this action as a 'Split Test' we

/// then record the results of this split view in the next request (OnActionExecuting).

/// 

/// This method also determines if we should supply the A or B view depending on the

/// 'ShouldRequestUseBView' algorithm.

/// </summary>

        protected override ViewResult View(string viewName, string masterName, object model)

        {            

            if (String.IsNullOrEmpty(viewName)) { viewName = (string) RouteData.Values["action"]; }

            bool isSplitTestingView = IsSplitTestingView(masterName, viewName);            

// If this view does not have a _B counterpart then we mark this request as non split test (by

// removing the 'SPLIT_TEST_VIEW_COOKIE_NAME' cookie) and just send control to base.View

            if (!isSplitTestingView)

            {

                Response.Cookies.Remove(SPLIT_TEST_VIEW_COOKIE_NAME);

                return base.View(viewName, masterName, model);

            }               

// Wether to use the A or B view depending on the 'ShouldRequestUseBView' algorithm

            bool useb = ShouldRequestUseBView();

// Lets create a results row and store it in the cookie (SPLIT_TEST_VIEW_COOKIE_NAME). This will let the 

// next request (OnActionExecuting) know that we just hit a split test view.

            ResultRow rr = new ResultRow {FromController = this, FromAction = viewName, UsedBView = useb};

            Response.Cookies.Add(new HttpCookie(SPLIT_TEST_VIEW_COOKIE_NAME, rr.ToString()));

            results.AddOneToResults(rr);            

 

// Display the appropriate view (A or B)

            return useb 

                ? base.View(viewName + B_TEST_SUFFIX, masterName, model)

                : base.View(viewName, masterName, model);            

        }        

 

/// <summary>

/// Returns wether the specified view has a _B counterpart. 

/// </summary>

        private bool IsSplitTestingView(string masterName, string viewName)

        {

            if (cache == null) { lock (GetType()) { if (cache == null) { cache = new ViewFilesCache(B_TEST_SUFFIX); } } }           

            return cache.HasSplitTestingAlternative(this, masterName, viewName);            

        }

 

/// <summary>

/// If odd IP then use 'B' view.  This will give a ~50% A / B split.

/// </summary>

        private bool ShouldRequestUseBView()

        {            

            return Int32.Parse(Request.UserHostAddress.Substring(Request.UserHostAddress.LastIndexOf('.') + 1)) % 2 == 1;

        }

    }

 

Description

So what is this code doing, basically it checks if a view has a '_B' counterpart, i.e.: If there is an Index.spark and an Index_B.spark.  If the view does have a _B counterpart then we mark the request as a split test and on the next request we save the results of that test.

To use this code simply extend this controller rather than the standard System.Web.Mvc.Controller.

Download

I have created a very simple test project (which uses Spark View Engine) that you can download here.  

Once you get the project set up simply navigation to Home.mvc/Index (which has a '_B' view also) and you can click around there for a while.  You can then navigation to Home.mvc/SplitTestResults to see a sample of how the results are stored.

Disclosure

This code was ripped quite aggressively from a much more comprehensive library and is intended only to illustrate the technique described here.  I highly suggest you do not use the code in production until you are happy with its stability.

Potential

I have been using this technique now for 2 months and have found it a fantastic way to measure true user acceptance of new features.  I also know that there is no other open source solution for asp.net mvc that allows you to do split testing efficiently so if you would like to work with me on getting this code production ready as an open source project let me know and I'll be more than happy to spend a bit more time making this code a bit more robust and creating a project for it,

Thanks

Guido Tapia

Software Development Manager

PicNet Pty Ltd


Visitor Heat Maps in WordPress - New Plugin

Posted on clock May 4, 2010 08:13 by author guido

Hi All,

I'm pleased to announce that we have just released a new WordPress plugin that will allow you to effortlessly add the PicNet Mouse Eye Tracking service to your WordPress website / blog. Now you can see exactly what your visitors are doing on your web site and not need to change a single html file.

For full details on what Mouse Eye Tracking can do for your web site see the home page.

Download the plugin.

Screenshots

Heat Map

Heat Maps

Page Navigation

Page Navigation

Thanks

Guido Tapia

Software Development Manager

PicNet Pty Ltd


Lean css in javascript

Posted on clock April 19, 2010 08:00 by author guido

This weekend I was looking at the lesscss.org project and found it very interesting.  There is also a .net implementation.  The basic features of these projects is to make css less verbose, they do this by offering features like mixins, variables and nested rules.  Now all of this is very straight forward lexical analysis to produce raw css so I thought to myself why does this need a server side component, what if I want to have a pure html site.  I don't want php, ruby, .net, etc just to compile some css.  I also don't want an additional deployment process to compile my css.  So... Why not javascript.

I thought there must be some limitations but a very quick test shows that it is entirely possible.  So here we go:

We want to prevent the bowser from doing 2 requests to css so change all your:


<link rel='stylesheet' href='style.css'/>

With:


<link rel='lss' href='style.css'/> <!-- I have called it lss for less but it can be anything -->

This will prevent the borwser from requesting this file, which is good as we will be manually requesting them. So now lets add a script file to load and parse our lss files:


<script src="jsless.js" type="text/javascript"></script> 

Content of jsless.js (Note I'm using jQuery)

 

$('link').each(function() {

  var lss = $(this);

  var lssurl = lss.attr('href');

  // Should we make this block?  Probably, but lets leave for now

  $.ajax({url: lssurl, dataType:"text", success: function(css) { getcsscallback(lss, css); }});

});

 

function getcsscallback(lss, cssText) { 

  var vars = getVariables(cssText); 

  for (var i in vars) {

  i = trim(i);

  var val = trim(vars[i]); 

  cssText = cssText.replace(/@[A-z^:]+:.*/g, ''); // remove var line

  cssText = cssText.replace(new RegExp(i,  'g'), val); // replace replace variables

  }

  cssText = '<style>' + cssText + '</style>'; // TODO: Add media, etc, etc from the attributes of lss into this tag

  $('head').append(cssText);

}

 

function getVariables(cssText) {

  return getMatches(/(@[A-z^:]+):([^;]+);/g, cssText);

}

/// Following code is just supporting regex and string manipulation code

function getMatches(regex, text) { 

  var matches = {};

  var match = null;

  while (match = regex.exec(text)) {  

  matches[match[1]] = match[2]; 

  }

  return matches;

}

 

function trim(str, chars) {

  return ltrim(rtrim(str, chars), chars);

}

 

function ltrim(str, chars) {

  chars = chars || "\\s";

  return str.replace(new RegExp("^[" + chars + "]+", "g"), "");

}

 

function rtrim(str, chars) {

  chars = chars || "\\s";

  return str.replace(new RegExp("[" + chars + "]+$", "g"), "");

}

 

Thats it, I have a test project set up that you can use to see this in action.  You can also just click here to see the html.  The css (lss) used is here and the js is here.

 

I personally think this project has some potential so if you are interested in working with me just email me and we can set up an OS project and start from there.

 

Note, I have tested the above in chrome, firefox and IE8 and it appears to work.

 

Anyways hopefully this inspires someone to do this properly.

 

Thanks

Guido Tapia

Software Development Manager

PicNet Pty Ltd


Javascript Tips, Tricks and Hacks

Posted on clock April 14, 2010 06:08 by author guido

JavaScript is by far the most expressive language I use today, that expresiveness is a result of the amount of flexibility that the language gives the developer.  This is also the same reason why it is so hard to develop in JS, however I will not be focusing on that here.  This article is solely about the art of JS development.  I will be following this article up with a series of usefull patterns in javascript and usefull utility classes, but for now lets focus on the sugar.

Note: This article is extremely subjective so if any of the following views offend please accept this as my sincerest of apologies.

Variables

Sometimes the way you do things has no impact on the results but it just 'feels' (or 'smells' if you want to Fowler it up) better.  One very clear example is variable declaration.  Example;

var i;

var x = 10;

var y =100;

var product = x*y;

I prefer this:

var i,

     x = 10, 

     y = 100.

     product = x*y;

Why? Don't know, I just do.

Also, you must always remember that assignment always returns the value of the assignment so why not do something like:

var product;

callFunction(product = x * y);

return product;

When doing multy variable assignment (separated by ,) then the last assignment is returned.  This is rarely usefull so no sugar there.

 

Conditions

Become familiar with falsy expressions.  Use them in your conditions.

So instead of:

if (typeof console !== 'undefined' && typeof console.trace !== 'undefined') console.trace(); 

Why not?

if (typeof console !== 'undefined'  && console.trace) console.trace(); 

Also, lazy conditions (or null-coalescing) are also cool.  Example:

x = x || getDefaultValueOfX(); // Basically only call getDefaultValueOfX if x does not have a value.  Synonimouse with ?? operator in C#

 

Loops

Iteration are a very personal thing some prefer to go backwards some forwards.  Some declare their 'i' before their 'for' some think this is very silly indeed.  This is how I loop.

for (var i = 0, e; e = array[i]; ++i) { ... }

Nice...  Oops, better mention a caveat here.  The termination expression here is e = array[i] which means that if the array contains: 0, '', null, undefined, false then the iteration will finnish prematurely.

But this syntax can also be used for lots of nice expressive statements like:

for (var i = 0, e, j = array.length - 1; e = array[i]; ++i; --j) { ... } 

How About:

for (var e; entries.length && (e = entries.shift());) { ... } // Awesome I hear you say?

etc, etc

 

Arrays

Arrays in javascript are very interesting, they are like an object with growths.  Some of those growths are very usefull but the fact that its still an object is pretty awesome also. So:

var x = [1, 2, 3 , 4];

x.max = function() {

 var m = Number.MIN_VALUE; 

 for (var i = 0, v; v = this[i]; ++i) { if (v > m) { m = v; } }

 return m;

}

How about (Continued from above):

x.length = 100;  // This actually increased the size of the array to 100 and filled in gaps with undefined

x.length = 2;  // This will shorten the array and 'delete' all enties above the specified index.

Something that needs to be mentioned here is the awesomeness of delete.  This marks a memory space for garbage collection so its a great way to ensure that something is infact 'deleted'.

Also, I highly suggest getting to know splice.  He can be a good friend.

 

Augmentation

The previous example (array x.max) is actually a form of augmentation but this concept can be taken even further and one of the pretties uses of this is a Crockfordian parasitic inheritance.  Let's have a look:

function Animal() {

 this.tallk = function() { return "Oink! Oink!"; }

}

 

function Dog() { // Dog will extend Animal parasitically (does that word exist?)

 var d = new Animal();

 d.talk = function() { return "Woooof, Grrrrrrrrrrr!"; }

 d.playDead = function() { return '.............'; }

}

alert(new Dog().talk());

There we go, we just implemented inheritance without ugly .prototype (s) and other nasties. 

 

Closures

If you ever have a chat to a Ruby developer they will probably bore you half to death with their preaching about the beaty of a closure, anyways JS has closures also, but javascript is a more practical language so we don't don't preach we just do.

Have you ever done this:

somearray.sort(function(a, b) { return a - b; });

We'll Array.sort takes in a cloure.  So closure is basically just a function that can be passed around and reused.  This is actually an amazingly powerful feature and can open a lot of doors when designing complex systems.  However, care must be taken when using closures, the context and hence the memory used up by the context of a function remains in memory as long as the closure is alive.  This is a common casue of JS memory leaks.

 

Hashtables (Dictionaries)

Objects are dictionaries.  This is actually a very usefull data structure so don't ignore it.

var dict = {};

dict['property1'] = prop1;

dict['property2'] = prop2;

dict['sub'] = function() { return this.propert1 + this.property2; };

 

Namespaces

Namespaces are usefull, they allow you to nicely modularise your code and prevent your code from clasing with other's code.  Namespacing in javascript is very easy.  I suggest the following approach:

// Create the namespace (using the uril finction below)

namespace('au.com.picnet.scripts');

 

// Add a class to the namespace

au.com.picnet.scripts.TestClass = function() {

 this.test = function() { alert('test'); }

};

 

// Instantiate the class and call test()

new au.com.picnet.scripts.TestClass().test();

 

// A safe namespace generator, can be called many times 

// with the same ns fragmens without fear of loosing objects.

function namespace(ns) {

 ns = ns.split('.');

 var current = window;

 for (var i = 0, n; n = ns[i]; ++i) {

 if (!current[n]) current[n] = {};

 current = current[n];

 }

}

 

Function Scope

The previous example of namespaces shows function scoping in action.  Function scope simply means that a function only has access its own members and its parent memebers (if it is nested).  So a parent funciton does not have access the the members of the nested function unless they are public.  This is actually a complex toic that I may explore further in its own article but for the time being I recommend reading this.

 

This!!

The this keyword is also a tricky beast especially when it can be manipulated with Function.apply and Function.call.  But generally this points to the current function (not the current function literal) or else the global scope.  Again too complex for this article but read this.

Note I generally try not to rely on 'this' very much.  If I need to access 'this' in future I generally create a temp variable that I can use:

var instance = this

This variable is created at a point I know that 'this' points to the right object and then don't worry about the technicalities.

 

Static Classes (Singleton, Utility Classes)

Object literals actually make great singletons.  Let see an example:

namespace('au.com.picnet.scripts');

au.com.picnet.scripts.Utilities = {

 add: function(x, y) { return x + y; },

 subtract: function(x, y) { return x - y; }

};

alert('add: ' + au.com.picnet.scripts.Utilities.add(1, 2) + ' subtrace: ' + au.com.picnet.scripts.Utilities.subtract(1, 2));

 

RegExp

The RegExp is an awesomly powefull object, it can make a 100 line parsing function vanish in a puff of elegance.  Howewer!!!!!  If you are anything like me, you need to use RegExps roughly 2-3 times a year.  The other times you just copy a previous use of the same regexp.  So when that time of year comes around you ask yoursel: How the hell do I do named groups again?

Well I have found that the best way to work with RegExs is to ignore them until needed.  When you do need a regex simply give yourself a 5 minute refresher here and make sure you test your regex thrououghly in places like here.  

I personally recommend not wasting too long getting good at RegExps as they are so rarely needed.  I have actually been good at RegExps several times but that all goes away... I have now accepted it.

 

Misc

- Always use '===' instead of '==' .

- Functions have a length attribute.  This is the length of expected parameters.

- Functions have an argumens array with all the arguments passed to the function, regardless of function signature.

 

Restraining the Beast

Javascript does give the developer too much rope, this is nice when trying to flex your creative powers but can become overpowering when working on large systems.  There are a number of tools which now allow you to try to tame this beast.  And at the top of the list is GWT (And other such projects).  However this is an extreme solution to this problem I personally like Javascript and don't really want to stop using it unless there are clear advantages on a project.  So some of the tools I use and look interesting are:

- Google's Closure Compiler : Adds some type safety to your beast (with annotations)

- FireBug : Don't leave home without it

- DOM / Ajax Helper Libs (jQuery, dojo, prototype, closure libs, etc): A must for cross browser development (I personally use jQuery as it seems to have won the popularity contest and regardless what the 'hardcore' tell you, this is actually very important)

 

The next generation of JS IDEs are also very exiting, leading this list are:

- WebStorm

- Visual Studio 2010

 

So Notepad++'s domination of the js development world may be comming to an end soon.  Ahhh I actually have dreams of accurate type inferrence in real time for a JS IDE.

 

Thanks

Guido Tapia

Software Development Manager

PicNet Pty Ltd