Increase your software development productivity 100x

Get more work done, for less effort!

The above might sound like an exaggeration. However, it is not! Simply because in Phosphorus Five, you can reuse almost everything you do. In the video below, I am demonstrating reducing my projects from 388 LOC (Lines Of Code) to 1 LOC, by creating a reusable extension widget, from an existing web app page.

Basically, what this implies, is that you can reuse almost everything you do in one project, to the next. This suggests that if you’re creating more than one project, then every time you start out a new project, you’re almost done with it, before you even start!

You can find the code for this below the video. For the record, I had to slightly modify the code below, to avoid angle brackets, etc, since my blog can’t handle angle brackets in code segments, even if I HTML encode them manually … (Darn it WordPress!!)

Now before you check out the code, realise that we started out with a “page”. Then we turned that page into a reusable extension widget, in roughly 5 seconds. The end result, being a reusable component, we can reuse in other projects, or in other pages in the same solution. Please watch the video for an explanation of how we did this.

Features of our GitHub project browser

The video also demonstrates some other pretty nifty features. For instance, we are able to traverse any project from GitHub, without using any of the GitHub APIs. The way this works, is that we are able to treat HTML semantically, and extract parts of the HTML returned by GitHub, by transforming it into a lambda object, to retrieve its actual “data”. Basically, we’re “scraping” GitHub, and semantically extracting parts of their HTML, to semantically “understand” the structure of the project we’re browsing.

This allows us to treat HTML semantically, as “data”, and create an Ajax TreeView, which you can see either in the video above, or the screenshot below. The Ajax TreeView in our little “app”, is basically created by semantically “scrape” the GitHub project website, retrieving the data for the links to download its folders, and its files, allowing us to recursively traverse any GitHub project, by treating their HTML semantically.

In addition, we will automatically parse any Markdown files, and show them in HTML view, and show any code segments in a “syntax highlighter widget”. To do this, we first use the HTTP REST capabilities of P5, which allows us to download files, using any of the HTTP verbs, such as GET, POST, PUT, etc. Notice, this is done on the server. Then we inject the code into a “pre” HTML widget (code files), which is later highlighted using the highlight.js JavaScript library. The Markdown files, are first converted into markdown using the [markdown2html] Active Event from Phosphorus Five, for then to be injected as the content into a “div” widget.

To understand how we do this, take a look at the code at the bottom of this blog.

Our little code snippet, also shows how you can use the System42’s Ajax TreeView, in addition to creating a “datagrid” manually, by creating a table element, wrapping your “grid”. Below is a screenshot of our little app.

Below is the code we ended up with, after having created our extension widget. Evaluate the following code in your System42/Executor.

/*
 * Creates a GitHub folder browser, that will allow the user 
 * to browse and read all files within each folder of a project.
 * Will create one Ajax TreeView mirroring the folder structure of the project, 
 * semantically parsed from the HTML of the project's landing page, in addition
 * to a "datagrid" allowing the user to see all files within currently selected folder,
 * and view its content.
 */
create-event:sys42.samples.git-hub.file-browser
  return
    container
      oninit
        p5.web.include-css-file:"https://highlightjs.org/static/demo/styles/rainbow.css"
        p5.web.include-javascript-file:"https://highlightjs.org/static/highlight.site.pack.js"
      events

        /*
         * Downloads GitHub index page, and returns the URLs for both 
         * the child folders, and the Markdown files.
         * Expects [_arg] being URL of GitHub HTML page to download, and semantically parse.
         * Returns [.files] and [.folders] being collection of source files, 
         * and folders recursively inwards.
         */
        sys42.samples.git-hub._get-files-folders

          /*
           * Checking cache to see if requested folder has already been traversed, 
           * and exists in cache.
           */
          p5.web.cache.get:sys42.samples.git-hub.{0}
            :x:/../*/_arg?value
          if:x:/@p5.web.cache.get/*/*
            return:x:/@p5.web.cache.get/*/*/*

          /*
           * Buffers.
           */
          .folders-tmp
          .files-tmp
          .folders
          .files

          /*
           * Retrieving all "xxx.md" types of files, in addition to all folders.
           */
          p5.http.get:x:/../*/_arg?value
          p5.html.html2lambda:x:/-/**/content?value
          add:x:/@.files-tmp
            src:x:@"/@p5.html.html2lambda/**/svg/*/\@class/=octicon octicon-file-text/././+/**/a/*/\@href"
          add:x:/@.folders-tmp
            src:x:@"/@p5.html.html2lambda/**/svg/*/\@class/=octicon octicon-file-directory/././+/**/a/*/\@href"

          /*
           * Massaging results from above.
           */
          for-each:x:/@.folders-tmp/*
            split:x:/@_dp/#?value
              =:/
            add:x:/@.folders
              src:@"{0}:""{1}{2}"""
                :x:/@split/0/-?name
                :"https://github.com"
                :x:/@_dp/#?value
          for-each:x:/@.files-tmp/*
            split:x:/@_dp/#?value
              =:/
            add:x:/@.files
              src:@"{0}:""{1}{2}"""
                :x:/@split/0/-?name
                :"https://github.com"
                :x:/@_dp/#?value

          /*
           * Returning folders and files to caller, making sure we cache results first.
           */
          add:x:/../*/p5.web.cache.set/*/*/items
            src:x:/@.files|/@.folders
          p5.web.cache.set:sys42.samples.git-hub.{0}
            :x:/../*/_arg?value
            src
              items
          return:x:/@.files|/@.folders

        /*
         * Creates our TreeView bugger.
         * Expects [.folders] being initially treeview root items to create.
         * Will also create the default "files datagrid" after TreeView has been created.
         * Hence, also expects [.files], which it will pass into creation of "files datagrid".
         */
        sys42.samples.git-hub._create-tree-view

          /*
           * Deleting any previously created datagrids, if existing.
           */
          if
            fetch:x:/0/0?value
              widget-exists:git-hub-treeview
            delete-widget:git-hub-treeview

          /*
           * Adding our treeview items.
           */
          split:x:/../*/_arg?value
            =:int:8
          add:x:/../*/create-widget/*/*/*/items/*/*/items
            src:x:/../*/.folders/*
          set:x:/../*/create-widget/**/root?name
            src:x:/@split/1?name

          /*
           * Creating our actual treeview.
           */
          create-widget:git-hub-treeview
            parent:results-wrapper
            class:col-xs-12 col-md-6 prepend-top git-hub-tree
            widgets
              sys42.widgets.tree

                /*
                 * Lambda callback for when an item is selected.
                 * We just simply retrieves files and folders, and create our 
                 * Markdown "files datagrid" here.
                 */
                .on-select
                  sys42.samples.git-hub._get-files-folders:x:/../*/items/*?name
                  add:x:/../*/sys42.samples.git-hub._create-files-grid
                    src:x:/../*/sys42.samples.git-hub._get-files-folders/*/.files
                  sys42.samples.git-hub._create-files-grid:x:/../*/items/*?name

                /*
                 * Lambda callback for retrieving child items.
                 * We retrieve the files and folders, and returns items to caller (TreeView).
                 */
                .on-get-items
                  sys42.samples.git-hub._get-files-folders:x:/../*/_item-id?value
                  add:x:/../*/return/*/items
                    src:x:/@sys42.samples.git-hub._get-files-folders/*/.folders/*
                  return
                    items
                items
                  root:x:/../*/_arg?value
                    items

          /*
           * Making sure we initially select the root tree item, and populate our
           * datagrid with the root Markdown files.
           */
          add:x:/../*/sys42.widgets.tree.select-items/*
            src:@"""{0}"""
              :x:/../*/_arg?value
          sys42.widgets.tree.select-items:git-hub-treeview
            items
          add:x:/../*/sys42.samples.git-hub._create-files-grid
            src:x:/../*/.files
          sys42.samples.git-hub._create-files-grid

        /*
         * Creates the "datagrid" that shows our files.
         * Expects [.files] being collection of files to create our "datagrid" around.
         */
        sys42.samples.git-hub._create-files-grid

          /*
           * Deleting any previously created datagrids, if existing.
           */
          if
            fetch:x:/0/0?value
              widget-exists:git-hub-datagrid
            delete-widget:git-hub-datagrid

          /*
           * "Databinding" our datagrid.
           */
          apply:x:/../*/create-widget/*/*/*/*/tbody/*/widgets
            src:x:/../*/.files/*
            template
              tr
                onclick

                  // Databound above.
                  {_url}:x:?value
                  sys42.samples.git-hub._create-file-view-widget:x:/@_url?value
                  set-widget-property:x:/../*/_event?value
                    class:active
                  p5.web.viewstate.get:sys42.samples.git-hub.active-row
                  if:x:/@p5.web.viewstate.get/*?value
                    and
                      fetch:x:/0/0?value
                        widget-exists:x:/@p5.web.viewstate.get/*?value
                    delete-widget-property:x:/@p5.web.viewstate.get/*?value
                      class
                  p5.web.viewstate.set:sys42.samples.git-hub.active-row
                    src:x:/../*/_event?value
                widgets
                  td
                    {innerValue}:x:?name

          /*
           * Creating our actual datagrid.
           */
          create-widget:git-hub-datagrid
            after:git-hub-treeview
            class:col-xs-12 col-md-6 prepend-top git-hub-grid
            widgets
              table
                class:table table-hover
                role:button
                widgets
                  thead
                    widgets
                      tr
                        widgets
                          td
                            innerValue:"Files"
                  tbody
                    widgets

        /*
         * Creates the "file-view" widget that shows the content of our files.
         * Expects URL to file to display as [_arg].
         */
        sys42.samples.git-hub._create-file-view-widget

          /*
           * Deleting any previously created markdown widgets, if existing.
           */
          if
            fetch:x:/0/0?value
              widget-exists:git-hub-markdown
            delete-widget:git-hub-markdown

          /*
           * Massaging URL.
           */
          replace:x:/../*/_arg?value
            src:"https://github.com"
            dest:"https://raw.githubusercontent.com"
          replace:x:/@replace?value
            src:"/blob/master/"
            dest:"/master/"

          /*
           * Retrieving Markdown file, creating HTML out of it, 
           * and creating our result widget showing file.
           */
          p5.http.get:x:/@replace?value
          if:x:/@p5.http.get/*/result/*/Content-Type?value
            !~:text/plain

            // We only handle text types of files.
            sys42.windows.info-tip:File is not a text file.
            return

          // Checking type of file.
          if:x:/@replace?value
            ~:.md

            // Markdown file.
            index-of:x:/@replace?value
              src:/
            split:x:/@replace?value
              =:x:/@index-of/0/-?value
            markdown2html:x:/@p5.http.get/**/content?value
              root-url:{0}/
                :x:/@split/0?name
            create-widget:git-hub-markdown
              parent:results-wrapper
              class:col-xs-12 prepend-top git-hub-markdown
              element:div
              innerValue:x:/@markdown2html?value

          else

            // Source code file.
            p5.html.html-encode:x:/@p5.http.get/**/content?value
            create-widget:git-hub-markdown
              parent:results-wrapper
              class:col-xs-12 prepend-top git-hub-markdown
              element:pre
              oninit
                p5.web.send-javascript:@"hljs.highlightBlock(p5.$('{0}').el);"
                  :x:/../*/_event?value
              innerValue:x:/@p5.html.html-encode?value

      widgets

        /*
         * This is our input for having user supply the URL to some GitHub project website.
         */
        container
          class:input-group
          widgets
            span
              class:input-group-addon
              innerValue:URL
            void:url
              placeholder:GitHub project's URL ...
              class:form-control
              accesskey:U
              value:"https://github.com/"
            container
              class:input-group-btn
              widgets

                /*
                 * Button will download main GitHub project's landing page, 
                 * and semantically parse the HTML for any sub-folders and all of its source files.
                 * Will use this result for creating a "folder Ajax TreeView" to allow you to browse
                 * the project structure, in addition to a "files datagrid" allowing you 
                 * to view the content of each file.
                 */
                button
                  class:btn btn-primary
                  innerValue:Fetch
                  onclick

                    /*
                     * Clearing out any previous results.
                     */
                    clear-widget:results-wrapper

                    /*
                     * Retrieving root URL for project, and fiding all "xxx.md" types of files, 
                     * in addition to all folders.
                     */
                    get-widget-property:url
                      value
                    sys42.samples.git-hub._get-files-folders:x:/@get-widget-property/*/*?value

                    /*
                     * Verifying that we actually found something worth looking at.
                     */
                    if:x:/@sys42.samples.git-hub._get-files-folders/*/*
                      not
                      sys42.windows.info-tip:No folders or files found at specified URL
                        class:info-window info-window-error
                      return

                    /*
                     * Creates our Ajax TreeView for navigating folders.
                     */
                    add:x:/../*/sys42.samples.git-hub._create-tree-view
                      src:x:/@sys42.samples.git-hub._get-files-folders/*(/.folders|/.files)
                    sys42.samples.git-hub._create-tree-view:x:/@get-widget-property/*/*?value

        /*
         * Used to hold our results widgets.
         * Both the TreeView, DataGrid and markdown/code widgets are appended as children into this bugger.
         */
        container:results-wrapper

Then create a “lambda” page in the CMS of System42, with the following code in it, to consume the widget we created above.

/*
 * This will create a page, consuming our newly created 
 * extension widget.
 */
create-widget
  parent:content
  class:col-xs-12
  widgets
    sys42.samples.git-hub.file-browser

Notice, this code example, like most other examples here on my blog, requires both Phosphorus Five, in addition to System42.

PS!
If you want to use the above as a “persisted extension widget”, you’ll need to stuff it in a Hyperlambda file, and make sure your file is evaluated as the server is started.

PPS!
This code is dependent upon the very latest release of both Phosphorus Five and System42 to function, version “Zen 2.1” that is.

KUDOS

KUDOS to highlight.js; I want to give som KUDOS to the guy who created highlight.js, which is a great JavaScript library, allowing anyone to easily show code as syntax highlighted in their web projects. Thank you Ivan Dementev for Open Source licensing your great library. Great work dude! 🙂

In addition, I want to give KUDOS to the Knagis for sharing his brilliant CommonMark.NET library with the world! Great work! For the record, I have a feature request for you, which is to have the option of having a separate URL resolver for images and hyperlinks. Pliiis …? 🙂

Advertisements

What does the speed of your Ajax web app really mean?

I have created several blogs lately where I have measured the performance differences between Phosphorus Five and all sorts of alternative Ajax libraries, such as jQuery, Infragistics, ExtJS, etc. The numbers are in the range of 50-200 times less bandwidth usage. However, what does this actually mean for you as a web developer? Well, let me use my own home as a use-case …

I am on a 50Mb connection where I live. However, my upload speed is only 5Mb. That translates into being able to upload 0.625 MB per second.

Below I have a screenshot of Sephia Five. The important parts are the parts encircled with red. The total initial download is 59.5KB of data. Notice, my cache is turned off though, as you can clearly see. If my client had cached the static resources, the total initial page load would have been 8.6KB to load my inbox.

Assuming 98% of the HTTP requests to my site has cached all the static resources, this would imply the average page load being around 9KB in total. Since my internet connection at home as a total theoretical limit of 0.625MB per second, this means that if I setup a web server at home, and paid $3 for a fixed IP address – I could theoretically serve roughly 73 clean page loads per second. Multiply that by the numbers of seconds per minute, and the number of minutes per hour, and the number of hours per day – Means I could serve 6307200 page loads per day!

If we assume that I have a shit load of users in my “GMail competition company”, and each user loads his inbox on average 10 times each day. This means I could create a GMail clone, all other factors set aside, and have 630720 users being my customers, on an average home internet ADSL connection, with really shitty bandwidth. Google is using hundreds of thousands of servers to deliver their product, and they’re pulling their own cables across the Atlantic ocean, in combination with Facebook to be able to deliver their services fast enough.

I live in Cyprus, which has about 800000 people. Assuming 170000 of these are too young to read emails, this means that in theory, I have enough bandwidth in my home, to setup every single citizen of Cyprus with an internet webmail service, using my home ADSL connection as the foundation.

Of course, when creating a service for hundreds of thousands of monthly users, there are a lot of other factors that comes into play. The above numbers also assume that the page load is perfectly evenly distributed across all the 24 hours of a day. But in theory, over a “shitty home internet connection”, I could serve 6.3 million page loads every single day, over an internet connection, that costs me $30 per month! If I had a handful of 5-10 year old PCs, with very large hard discs, I could serve the entire island of Cyprus, with a PGP encrypted email service, with an initial cost of 5 10 year old PCs, and a fixed monthly cost of $33.

To startup a webmail company in Cyprus, serving the entire population of Cyprus with encrypted emails, would cost me (in theory) no more than $5000 in initial costs, and $33 per month for an ADSL connection.

If I charged my users $1 per month for my service, I would earn 669997 dollars per month!

For the record, the above is an extreme use-case, and wouldn’t be practically likely to pull off, since first of all the bandwidth consumption would spike in working hours, 8-4, and be close to nothing during the night, etc. In addition, it would require huge amounts of storage, which would cost much more than $5000. But it illustrates the importance of having a *tiny Ajax library*!

Below is a screenshot of GMail’s bandwidth usage for loading the same inbox. Notice GMail uses 3.9MB, which is 67 times as much bandwidth as Sephia Five! This means I would need 67 times as much network to host GMail, as I would need to host Sephia Five!

That is disruptive technology!

The incredible scientific facts about Phosphorus Five

If I told you I could make you 13 times as productive, and that you’d achieve 220 times better results – Would you believe me? How about if I showed you the scientific data behind my statements, and how my numbers was reproducible, and easily verified. Would you take the time to test my claims?

The reason why I am asking, is because the above numbers are in fact the numbers behind the Ajax library of Phosphorus Five. I realise you probably don’t believe me, so I have therefor made it possible for you to verify my numbers for yourselves, in less than 5 minutes. That way you have the opportunity to prove me wrong, and show the world that I am a fruitcake if you wish.

Notice, the data is built upon some of the existing best practices tools within our industry; jQuery and Infragistics. If you go to StackOverflow.com and search for jQuery, you will find that it returns 851376 results (20th of June 2017)

If you visit the Infragistics website, you will find that their tools are used by some of the largest companies in the world, such as Dell and MacDonalds.

Would you want to create 220 times better web apps than MacDonalds and Dell, for a 13th of the cost? What do you think that would do for you and your business?

Become 100 times more productive, and create 100 times better quality, for 1/20th of the price

The above claim might sound like a fairytale, and as if somebody overdosed on their “marketing mumbo jumbo gibberish medicine”. However, I can prove these claims. I have in fact already done so, by profiling Phosphorus Five towards some of the most popular alternatives out there – And the numbers seems to often be at least 100x on most of the parameters. Sometimes less, sometimes more. But in general, 100x seems to be the average.

To put this into perspective, let’s create an analogy.

Imagine a car doing a 100 miles per hour and 30 miles per gallon, costing you $100.000, requiring service once every year. Then imagine a car doing 10000 miles per hour, driving 3000 miles per gallon, costing you $5.000, never crashes, and not requiring service before you’re 278 years old. Which car would you choose?

Literally, the above analogy is the difference. Don’t believe me, check out the data for yourselves.

It really doesn’t matter who you compare P5 towards. If you feel that your favourite framework is missing in the above comparison, or that I have done something wrong when doing these comparisons. Then please feel free to provide a comment, and give me feedback.

Most other Ajax vendors are ~20 times as expensive as Phosphorus Five

Would you buy this thing if I told you it was less expensive than a Volkswagen?

I license for Phosphorus Five will cost you exactly €57. In comparison, most other commercial Ajax library vendors, will charge you somewhere between $1000 and $2000 for arguably the same set of tools.

This means that you will save ~95% on average, if you choose Phosphorus Five instead of literally “anything else out there”. Below I have created a price list of all the different Ajax library vendors, and what they will charge you for their toolbox.

  • Infragistics for ASP.NET 2016 Vol. 2 w/priority support $1399
  • Telerik’s UI for ASP.NET AJAX $999
  • ComponentOne Ultimate developer license $1995

Some would argue that it’s like comparing apples and tomatoes, since some of the above toolkit vendors will throw in stuff such as iOS and Silverlight controls. However, it goes both ways, since Phosphorus Five for instance includes the ability to send PGP encrypted emails, in addition to tons of other goodies.

I want to emphasise that the entirety in the GaiaSoul suite will cost you €57, at which point you have a single developer license, legally allowing you to do whatever you wish with. This license even includes the ability to fork my GMail clone, improve it, close source your results, and sell licenses out of it if you wish.

This means, that all other things set aside, such as the fact that you will be 13 times as productive, and create up to 220 times more responsive apps, etc – You even pay on average less than 1/20th of the price for a commercial developer license, as you will be paying if you purchase one of the competitors’ products.

If you could buy a new Ferrari for €57, or an old Volkswagen for $1000 – Which would you choose …?

Create 156 times faster apps with P5 than with ExtJS

When it comes to Ajax, size is everything. The less bandwidth your apps consume, the more responsive they will be. In the video below, I am demonstrating in a reproducible environment, how creating a simple Ajax TreeView in ExtJS consumes 156 times the amount of bandwidth as creating the same in Phosphorus Five.

This translates into that if you’re on a really shitty internet connection, where it requires 1 second to download the P5 Ajax TreeView – It would require 2.5 minutes to download the ExtJS equivalent.

The reasons for this, is because of a concept in P5 I often refer to as “Managed Ajax”, which allows you to build almost any Ajax control you wish, and rarely if ever exceed ~5KB of JavaScript. So while you’d have to download several megabytes of JavaScript to build a simple Ajax Tree control in ExtJS, you can get away with ~5 kilobytes doing the same with P5.

If you wish to reproduce my performance test, you can find the Hyperlambda necessary to do that below the video.

Create a new “lambda” page in the System42 CMS, paste in the following code, and make sure you set its “template” settings to “empty”.

create-widget
  parent:content
  widgets
    sys42.widgets.tree
      crawl:true
      items
        root:/
      .on-get-items
        list-folders:x:/../*/_item-id?value
        for-each:x:/@list-folders/*?name
          list-folders:x:/@_dp?value
          split:x:/@_dp?value
            =:/
          add:x:/../*/return/*
            src:@"{0}:{1}"
              :x:/@split/0/-?name
              :x:/@_dp?value
          if:x:/@list-folders/*
            not
            add:x:/../*/return/*/items/0/-
              src
                class:tree-leaf
        return
          items

Changing from jQuery to P5 saves you 92% of your costs when developing software

Who do you think was the most lucky here? Small or big …?

According to many scientific studies about software productivity, the cost of developing software is directly proportional to the number of lines of code in your software projects. In addition, the less lines of code you have, the fewer bugs you will have. Both of these statements have been proven many times, in several scientific studies about this subject.

This means that if you could somehow create your software projects, with less code – You would not only save money initially, but also have fewer bugs when maintaining your software.

In the video below, I am demonstrating an example of how you could reduce the lines of code from 39 LOC in jQuery to 3 LOC in Phosphorus Five. This translates into saving 92% of your initial development costs, in addition to also 92% of your maintenance costs, due to reducing the number of bugs in your software.

“Many studies do show a rough correlation between LOC and the overall cost and length of development, and between LOC and number of defects.”

Source; wiki.c2.com

Below I walk you through the numbers and science behind this, proving how you’d spend 13 times as much resources using jQuery, as you’d need if you were using Phosphorus Five.

Creating an Ajax TreeView control without JavaScript making you 300 times more productive

In my previous blog, it might sound like as if I am lying through my teeth. However, once you realise how it’s done, there’s actually no magic to it. In p5.ajax, there is one JavaScript file. This is a general purpose JavaScript file, which takes care of serialising the form, updating attributes on DOM elements, and dynamically injecting new HTML snippets from JSON returned from the server.

These above traits though, just so happens to allow me to treat Ajax widgets, in an entirely new way. For instance, the animation you see in the video on my previous blog when I expand the tree nodes, is actually just a CSS animation. The toggling of nodes, occurs exclusively on the server. This allows me to have an entirely new way of dealing with the problem of Ajax, which is simply superior in regards to staying close to the “philosophy of the web”, and semantically much more true to the original design decisions of HTML.

For instance, one thing I didn’t even touch upon in the previous blog, was how the P5 Ajax TreeView can be crawled by search engine spiders, since the spider only see plain old pure hyperlinks – While a client with JavaScript enabled sees DOM events, raising Ajax requests. Semantically, these two different ways of seeing the DOM, ends up with the exact same results. So there’s no “cloaking” occurring. And it 100% perfectly degrades into plain Hyperlinks, if the client has turned off JavaScript for some reasons.

The above combined with the ability to incrementally create my markup and DOM, by composing widgets together, into rich hierarchies from the server – Just so happens to allow me to get away, with creating a fully fledged Ajax TreeView control, without ever having to expand upon my original JavaScript, beyond the 4.8KB that p5.ajax contains at its core.

The results hence becomes that of ending up with an Ajax TreeView, far superior to most other Ajax TreeView in the world, regardless of which parameter you measure it by – WITHOUT as much as a single line of JavaScript! This widget is also entirely created in Hyperlambda, and doesn’t even contain as much as a single line of C# code.

If you’re interested in seeing its code, you can check it out here, here, here, here, here and here. Basically 6 files of Hyperlambda, which are in total 717 lines of code (most of it comments) – Resulting in a reusable general purpose Ajax TreeView control, which are several orders of magnitudes better performance wise, than anything else out there – At least as far as I have seen.

It doesn’t matter who’s Ajax Tree you compare it against either, it’s basically a slaughter, regardless of which Ajax component vendor’s Tree you do the comparison towards; ExtJS/Sencha, Telerik, jQuery, Infragistics, ComponentOne, etc, etc, etc – Basically several orders of magnitude in difference! To give you an idea why, realise that jQuery in its zipped and minified version is at least 25KB. p5.core’s JavaScript is less than 5KB!

And to consume it, is as simple as the following example shows. Realise this is 25 lines of code for the record.

create-widget
  parent:content
  widgets
    sys42.widgets.tree
      crawl:true
      items
        root:/
      .on-get-items
        list-folders:x:/../*/_item-id?value
        for-each:x:/@list-folders/*?name
          list-folders:x:/@_dp?value
          split:x:/@_dp?value
            =:/
          add:x:/../*/return/*
            src:@"{0}:{1}"
              :x:/@split/0/-?name
              :x:/@_dp?value
          if:x:/@list-folders/*
            not
            add:x:/../*/return/*/items/0/-
              src
                class:tree-leaf
        return
          items

To illustrated these reusability features of p5.ajax, lets imagine we wanted to create another Ajax TreeView, a specialised version this time, out of the above code. This specialised version would allow us to inject a “folder browsing Ajax TreeView” into any page we wanted to in our system. Well, that’s as easy as creating an Active Event with the following code.

create-event:my-company.my-folder-tree-view
  return
    sys42.widgets.tree
      crawl:true
      items
        root:/
      .on-get-items
        list-folders:x:/../*/_item-id?value
        for-each:x:/@list-folders/*?name
          list-folders:x:/@_dp?value
          split:x:/@_dp?value
            =:/
          add:x:/../*/return/*
            src:@"{0}:{1}"
              :x:/@split/0/-?name
              :x:/@_dp?value
          if:x:/@list-folders/*
            not
            add:x:/../*/return/*/items/0/-
              src
                class:tree-leaf
        return
          items

After you’ve evaluated the above code in e.g. your Executor, you can create a CMS “lambda” page resembling the following.

create-widget
  parent:content
  class:col-xs-12
  widgets
    my-company.my-folder-tree-view

Notice BTW, that I changed less than 5 lines of code, and was able to create a control out of my existing code. At this point, we can include any “folder browsing Ajax TreeView” we wish, into any page we wish, with a single line of Hyperlambda! Most other Ajax vendors would require you to write hundreds of lines of code, often in 2-3 different programming languages to do the same. So let’s make a qualified guess and say roughly 300 lines of code, reduced to 1 line of code!

According to scientific studies on coding and productivity, which shows that your productivity is proportional to the number of lines you code and have to maintain – You are hence 300 times as productive with Phosphorus Five!

Not too bad for 0KB of JavaScript if you ask me … 😉

Infragistics Ignite UI Ajax Tree control performance versus P5

In the video below, I am measuring the performance of the Infragistics Ignite UI Ajax Tree control, and comparing it towards the Ajax TreeView from System42 and Phosphorus Five. Spoiler alert; Infragistics TreeView is 220 times the size on bandwidth consumption compared to P5’s Ajax TreeView.

The above difference in performance, translates into that if you’re on a very slow internet connection, where downloading P5’s Ajax TreeView would take you 1 second – It would take 3 minutes and 40 seconds to download the JavaScript for the Infragistics TreeView. That is almost like the difference between a Redwood tree and a Bonsai tree for the record! When it comes to Ajax, size is everything! And the smaller size, the more happy your customers are.

My results are easily reproduced, for anyone who wants to check out the facts for themselves. I know these kind of numbers sounds to incredible to be true, but sometimes the truth actually is just that! But instead of me trying to convince you, simply watch the video for yourselves, and check out my claims with your own eyes if you like to.

For the record, the numbers are similar, regardless of which Ajax TreeView you compare the P5 Ajax TreeView towards. I will come back with performance comparison with other frameworks out there, such as Sencha, Telerik, jQuery, etc. But for now, just watch the video above, and enjoy.