How Many Developers Does It Take to Screw In a Lightbulb? Leveraging the Internet of Things!

December 15, 2015 Leave a comment

The Internet of Things (IoT) refers to the increasing number of devices that are now connected to the Internet and can be programmed remotely (typically from your smartphone).  Everything from from Oral-B toothbrushes to Samsung Washer-Dryers, Nest Thermostats, and Philips Light Bulbs are now connected and have their own programming interfaces. Additional products are coming online that enable you to control virtually any electronic device remotely.

This technology revolution opens the door for software developers to produce some truly innovative and immersive experiences. Easy to use API’s and libraries now exist, such as Cylon.js and the forthcoming “Thunder” IoT platform from Salesforce.com that make it quite simple to control devices in the physical world from the virtual one. Of course, all of this power also opens up a myriad of security concerns as well. While I certainly don’t want my blender getting hacked into and ruining my margarita,  I have a dream where I can install NEST thermostats in my sales team’s houses and turn up the heat (literally) when automatic reporting from Salesforce.com indicates that they’re not making their quotas. Because that’s how I roll.

Enlightening yourself about IoT with Philips Hue Lights

For our first IoT trick, we’re going to use several well-proven technologies to produce a simple app to control a Philips Hue lightbulb. I’ve been using Hue bulbs for a couple of years now and they’re fantastic. They use light-emitting diodes to produce energy-efficient light across the RGB palette. Each bulb contains a wi-fi radio that connects to a bridge.

2015-12-13_09-31-21

Philips Hue Starter Kit with Bridge and 3 Connected Bulbs


The Bridge has its own REST API that enables you to easily get a list of the bulbs that have been named/registered as well as send commands to set the color and brightness of each bulb.

Tools of the Trade

We used the following tools to produce our first IoT app. As a bonus, all of the aforementioned products are free and open-source. They also all use JavaScript as their programming language.

  • Node.JS application server
    Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
  • Cylon.JS API for Controlling Devices
    Cylon.js is a JavaScript framework for robotics, physical computing, and the Internet of Things. It makes it incredibly easy to command robots and devices.
  • Sencha Ext JS (GPL License) for producing the front-end GUI.
    The most comprehensive JavaScript framework for building feature-rich cross-platform web applications targeting desktop, tablets, and smartphones. Ext JS leverages HTML5 features on modern browsers while maintaining compatibility and functionality for legacy browsers.

Using Node.JS and Cylon.JS – By your Command!

I’ve used Node.JS for a number of projects now and have always been impressed by its simple installation, fast performance, and ease-of-use. In particular, the Express framework for Node makes it ridiculously simple to produce a quick and dirty RESTful api like the one that we produced for this app.

Cylon.JS is an awesome API for connecting to more than 40 different hardware platforms — including Philips Hue bulbs and bridges.

iot2.png

Cylon.JS Supported Devices

To create our Node.JS project, we simply created a new folder (/IoT1/) on our filesystem, opened a command prompt, and issued the following statements which installs the Express framework for Node.JS, creates an express project, installs the Cylon API, and adds-in the cylon-hue library:

npm install express --save
express
npm install cylon --save
npm install cylon-hue --save

Next, we implemented a new route, named hue, by inserting code on lines 10 and 28 of the /IoT1/app.js file as illustrated by the following snippet. In effect, this programs our Node server to respond to HTTP requests to a url of http://serverip/hue


var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');
var hue = require('./routes/hue');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);
app.use('/hue', hue);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
     message: err.message,
     error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
  message: err.message,
  error: {}
 });
});

module.exports = app;

The Cylon.js library uses a high-level object named “Cylon” to control supported devices. A Cylon object has three major properties:

  • connections – Defines how to connect to devices and pass credentials
  • devices – Defines the types of devices that you want to control and their corresponding device drivers
  • work – a function that is automatically invoked after the device connection and authentication has occurred

Each device type has a series of methods that are enumerated in the Cylon.js documentation. Our application makes the following calls:

  • bridge.getFullState() – returns all information about the system including lights and color themes
  • bulb.toggle() – toggles the on/off state of the bulb
  • bulb.rgb() – Sets the color of the bulb as a red,green,blue 3-tuple
  • bulb.turnOn() – Turns the bulb on.
  • bulb.turnOff() – Turns the bulb off

Uisng this information, we created a node.js file named /IoT1/routes/hue.js to handle http GET/POST/PUT requests. In this particular case, we somewhat arbitrarily decided the following:

  • GET requests should return information about connected Hue bulbs from the Hue Bridge
  • PUT requests should turn on/off a selected bulb and change the bulb color to Fig Leaf’s green brand color
  • POST requests should activate the “Red Alert” mode, causing the light to blink like in Star Trek because, well… of course!
var express = require('express');
var router = express.Router();
var Cylon = require('cylon');

// see notes about host + username in the blog article
var host = '10.0.1.71';
var username = '215c4296227a3247159acafa1258e75b';

var redAlert = null; // red alert interval timer

/*
poll the bridge and return info about the lights
*/
router.get('/', function(req, res, next) {

 Cylon.robot({
  connections: {
  hue: {
   adaptor: 'hue',
   host: host,
   username: username
  }
 },

 devices: {
   bridge: {
    driver: 'hue-bridge'
   }
 },

 work: function(my) {
  
  my.bridge.getFullState(function(err, config) {
 
    if (err) {
     var result = {
      success: false,
      error: err
     }
    } else {
     var lights = [];
     for (var i in config.lights) {
       lights.push({
        'id': i,
        'state': config.lights[i].state.on,
        'reachable': config.lights[i].state.reachable,
        'name': config.lights[i].name
       });
     }
     var result = {
      success: true,
      lights: lights,
      config: config.config
     }
    }
    res.writeHead(200, {
     "Content-Type": "application/json"
    });
    res.write(JSON.stringify(result));
    res.end();
   });
  }
 }).start();

});

/*
* toggle bulb on/off
*/
router.put('/', function(req, res) {

var lightId = req.body.id;
var turnOn = (req.body.turnOn == 'true');

Cylon.robot({
 connections: {
  hue: {
   adaptor: 'hue',
   host: host,
   username: username
  }
 },

 devices: {
  bulb: {
  driver: 'hue-light',
  lightId: lightId
 }
},

 work: function(my) {
   if (turnOn) {
    my.bulb.turnOn();
    my.bulb.rgb(0, 102, 51); // fig leaf green
   } else {
    if (global.redAlert) {
     clearInterval(global.redAlert);
     global.redAlert = null;
    }
    my.bulb.turnOff();
   }

   var result = {
    success: true
   };
   res.writeHead(200, {
     "Content-Type": "application/json"
   });
   res.write(JSON.stringify(result));
   res.end();
   }
  }).start();
});

/*
* "Red Alert" mode - red blinking light
*/

router.post('/', function(req, res) {
  
  var lightId = req.body.id;
  var turnOn = (req.body.turnOn == 'true');

  Cylon.robot({
   connections: {
    hue: {
     adaptor: 'hue',
     host: host,
     username: username
    }
   },

   devices: {
    bulb: {
     driver: 'hue-light',
     lightId: lightId
    }
   },

   work: function(my) {
    
    if (!global.redAlert) {
      my.bulb.turnOn();
      my.bulb.rgb(255, 0, 0);
      global.redAlert = every((0.8).second(), function() {
       my.bulb.toggle();
      });
    }

    var result = { success: true };

    res.writeHead(200, {
      "Content-Type" : "application/json"
    });
    res.write(JSON.stringify(result));
    res.end();
   }
  }).start();
});

module.exports = router;

Building out the Web Client with Sencha Ext JS

On the client-side, we used Ext JS to produce a simple GUI illustrated in the figure below. Left-clicking on the bulb toggles its on/off state. Right-clicking on the bulb puts it into “Red Alert” mode.

Bulb Off Ext JS Bulb Activation UI

The View, which outputs the image of the bulb and the combo box light selector is fairly straightforward:


Ext.define('MyApp.view.Lightbulb', {
    extend: 'Ext.window.Window',
    alias: 'widget.Lightbulb',

    requires: [
        'MyApp.view.LightbulbViewModel',
        'MyApp.view.LightbulbViewController',
        'Ext.Img',
        'Ext.form.field.ComboBox'
    ],

    controller: 'lightbulb',
    viewModel: {
        type: 'lightbulb'
    },
    constrain: true,
    height: 358,
    width: 425,
    bodyPadding: 10,
    title: 'Fig Leaf Software IoT Demo 1',

    layout: {
        type: 'vbox',
        align: 'center',
        pack: 'center'
    },
    items: [
        {
            xtype: 'image',
            reference: 'lightbulbImg',
            disabled: true,
            height: 256,
            width: 256,
            bind: {
                src: '{lightbulbUrl}'
            }
        },
        {
            xtype: 'combobox',
            reference: 'lightscombo',
            width: 200,
            fieldLabel: '',
            displayField: 'name',
            forceSelection: true,
            valueField: 'id',
            bind: {
                store: '{Lights}'
            },
            listeners: {
                change: 'onComboboxChange'
            }
        }
    ],
    listeners: {
        afterrender: 'onWindowAfterRender'
    }

});

Ext JS 5 supports the concept of viewmodels that link data structures to a view. Our viewmodel, as illustrated by the following code snippet, defines lightStatus and lightId properties that indicate the on/off state and the id of the lamp that’s being controlled, respectively.

There’s also a data store (array of records) that makes a GET request to our /hue webservice in Node.JS in order to pull the relevant information about connected bulbs. The bulb listing is bound to the combo box in the view.

The lightbulbUrl formula is used in conjunction with data binding in the view to swap-in the appropriate image on mouseclick.


Ext.define('MyApp.view.LightbulbViewModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.lightbulb',

    requires: [
        'Ext.data.Store',
        'Ext.data.proxy.Ajax',
        'Ext.data.reader.Json',
        'Ext.util.Sorter',
        'Ext.util.Filter',
        'Ext.app.bind.Formula'
    ],

    data: {
        lightStatus: false,
        lightId: 0
    },

    stores: {
        Lights: {
            autoLoad: false,
            model: 'MyApp.model.Light',
            proxy: {
                type: 'ajax',
                url: '/hue',
                reader: {
                    type: 'json',
                    rootProperty: 'lights'
                }
            },
            sorters: {
                property: 'name'
            },
            filters: {
                property: 'reachable',
                value: true
            }
        }
    },
    formulas: {
        lightbulbUrl: function(get) {
            if (get('lightStatus')) {
                return 'resources/images/lightbulb_on.png';
            } else {
                return 'resources/images/lightbulb.png';
            }
        }
    }

});

The Ext JS ViewController handles all the events thrown from the view, performing the following functions:

  • On lightbulb click, invoke our Node.JS service, calling its PUT method
  • On lightbulb right-click, invoke our Node.JS service, calling its POST method
  • On combo box selection, set the appropriate values in the viewmodel and display the appropriate bulb image
  • On startup, attach the left-click and right-click event handlers

Ext.define('MyApp.view.LightbulbViewController', {
    extend: 'Ext.app.ViewController',
    alias: 'controller.lightbulb',

    onLightbulbClick: function() {
                var vm = this.getViewModel();
                var lightId = vm.get('lightId');
                if (lightId == 0) {
                    Ext.Msg.alert("Error","You must select a bulb");
                    return;
                }
                var status = vm.get('lightStatus');
                vm.set('lightStatus',!status );
                this.lookupReference('lightscombo').getSelection().set('state', !status );

                Ext.Ajax.request({
                    url: '/hue',
                    method: 'PUT',
                    params: {
                        id: vm.get('lightId'),
                        turnOn: !status
                    },
                    success:function(response) {
                        console.log(response);
                    }
                });
    },

    onLightbulbContextMenuClick: function(e) {
        e.preventDefault();
        var vm = this.getViewModel();
        var lightId = vm.get('lightId');

        if (lightId == 0) {
            Ext.Msg.alert("Error","You must select a bulb");
            return;
        }
        vm.set('lightStatus',true);
        Ext.Ajax.request({
            url: '/hue',
            method: 'POST',
            params: {
                id: vm.get('lightId')
            },
            success:function(response) {
                console.log(response);
            }
        });

    },

    onComboboxChange: function(field, newValue, oldValue, eOpts) {
        var vm = this.getViewModel();
        var selection = field.getSelection();
        vm.set('lightId',selection.get('id'));
        vm.set('lightStatus', selection.get('state'));

    },

    onWindowAfterRender: function(component, eOpts) {
        var l = this.lookupReference('lightbulbImg');
        l.getEl().on('click', this.onLightbulbClick, this);
        l.getEl().on('contextmenu', this.onLightbulbContextMenuClick, this);
    }

});

Where do we go from here?

For my next trick, I’m going to move some bulbs down the basement and put my node.js script on a timer so that they all go into “red alert” mode precisely at 8:30 pm. If that doesn’t get my two boys upstairs for bedtime then nothing will.

You can download the complete sourcecode from github by clicking here.

Check out our Node.JS training, Sencha Ext JS training,  and consulting services!

I hope that you found this article to be illuminating. Have a great holiday, everyone!

New Books from Fig Leaf Software

September 9, 2015 Leave a comment

Fast Track to ColdFusion 10/11 provides experienced web developers with the knowledge and hands-on practice they need to start building and maintaining dynamic and interactive Web applications using the ColdFusion application server. With over 25 hands-on exercises, this coursebook covers everything that you need to know in order to start building secure, scalable, dynamic, data-driven web sites as well as implement REST APIs to support mobile apps.
~300 pages
http://www.amazon.com/Fast-Track-ColdFusion-10-11/dp/1515067777

Fast Track to Sass and Compass
Whether you’re developing a static site, a dynamic site with a CMS (Drupal), or building an advanced web-based application with a Javascript framework (jQuery, jQuery Mobile, Sencha Ext JS, Sencha Touch, Angular, React.JS), you’ll find that Sass and Compass are indispensable tools for taming and optimizing your CSS. You’ll learn Sass and Compass by refactoring a very long and difficult to maintain single CSS file into a set of smaller, easier to manipulate .scss (Sassy CSS) files for optimal maintainability. You’ll also improve download and rendering times by producing minified production builds, base-64 encoding your images, and automatically merge multiple images into sprites.
http://www.amazon.com/Fast-Track-Compass-Steven-Drucker/dp/1515228770
~100 pages

Sencha Ext JS 5 Bootcamp in a Book teaches you everything that you need to know in order to build a cross-browser, x-device compatible, next-generation web application using nothing but Javascript and good intentions. This book contains over 60 hands-on exercises that cover nearly every aspect of developing enterprise-grade web apps using Sencha’s Ext JS 5 javascript framework.
~600 pages

http://www.amazon.com/Sencha-Ext-JS-Bootcamp-Book/dp/1511659580

More books coming soon!

Categories: Uncategorized

Buy our new book – Sencha Ext JS 5 Bootcamp in a Book!

May 22, 2015 9 comments

Sencha Ext JS 5 Bootcamp in a Book teaches you everything that you need to know in order to build a cross-browser, x-device compatible, next-generation web application using nothing but Javascript and good intentions. This book contains over 60 hands-on exercises that cover nearly every aspect of developing enterprise-grade web apps using Sencha’s Ext JS 5 javascript framework.

This book contains over 60 hands-on exercises that cover nearly every aspect of developing enterprise-grade web apps using Sencha’s Ext JS 5 javascript framework. Course files are downloadable from Github and Sencha Fiddle.

Table of Contents:

  1. Introducing the Course
  2. Introducing Ext JS 5
    • Implementing the 3-tier architecture
    • Reviewing features and capabilities
    • Reviewing the Ext JS examples
    • Introducing MVC and MVVM
    • Introducing the Class System
    • Generating App Scaffolding with Sencha Cmd
    • Using the API Docs
    • Debugging and troubleshooting your app
    • Getting Help from the Sencha Network
  3. Defining Views
    • Deep-Diving into the Class System
    • Working with DOM Elements vs. Ext Components
    • Using the Component Hierarchy
    • Instantiating a Viewport
    • Using the Border Layout
    • Defining Panels
    • Defining Toolbars, Buttons, and Menus
    • Handling User Events with ViewControllers
    • Working with Tab Panels
    • Supporting the “back” button with Routes
    • Working with Windows
    • Implementing a Dashboard
  4. Reading Complex Data from an App Server
    • Understanding AJAX and REST
    • Implementing View Models and Data Binding
    • Implementing Roles-Based Security
    • Defining a Data Model
    • Defining a Proxy
    • Reading Multiple Records into a Data Store
    • Using Chained Stores
  5. Visualizing Tabular Data in Grids
    • Defining a Grid
    • Using Grid Widgets
    • Implementing Data Pagination
    • Defining Grouped Grids
    • Enhancing Grouped Grids
    • Editing Data in Grids
  6. Generating Markup from Data
    • Working with XTemplates
    • Looping Through Data
    • Implementing Conditional Processing
    • Executing Inline JavaScript
    • Binding Custom JavaScript Methods to XTemplates
    • Performing Basic Calculations in an XTemplate
    • Binding a Template to a Component
    • Using the DataView
  7. Visualizing Hierarchical Data in Trees
    • Introducing the TreeStore
    • Understanding the NodeInterface Class
    • Implementing a Tree Panel
    • Implementing a Tree Grid
    • Working with Heterogeneous Node Types
    • Using Trees as an Input Mechanism
  8. Visualizing Data in Charts
    • Instantiating a Chart
    • Configuring Chart Axes
    • Configuring Chart Labels
    • Configuring Chart Legends
    • Using Chart Interactions
    • Working with Bar Charts
    • Working with Line Charts
    • Working with Gauges
  9. Maintaining State
    • Configuring the State Provider
    • Saving the State of Components
    • Adding State Management to Non-Stateful Components
  10. Creating Data Entry Forms
    • Creating Data Entry Forms
    • Defining a Form
    • Configuring Form Fields
    • Using the Combo Box Field
    • Sizing Fields with the Anchor Layout
    • Sizing Fields with the Form Layout
    • Assigning Default Configuration Values
    • Grouping Fields
    • Validating Input Data
    • Formatting the Data Validation Error Messages
    • Submitting Data to the Server for Processing
    • Binding Grids to Forms
  11. Theming your App
  12. Going into Production
    • Documenting your App with JSDuck
    • Unit Testing with Jasmine and Siesta
    • Generating Testing and Production Builds
  13. Appendix A: Configuring your Development Environment
  14. Appendix B: Congressional Earmarks Lab
  15. Appendix C: Proposal Manager Lab

Buy it today from Amazon.com at:
http://www.amazon.com/Sencha-Ext-JS-Bootcamp-Book/dp/1511659580/ref=sr_1_6?ie=UTF8&qid=1432283001&sr=8-6&keywords=sencha+ext+js

Categories: Uncategorized

Sencha Ext JS 5: Supporting Different Themes for Different Devices

March 31, 2015 Leave a comment

Sencha Ext JS 5 is the first version of the Ext framework to fully support iOS tablets.

Perhaps the most important task  that you’ll need to do in order add tablet support to your application is to automatically switch between desktop and touch-based themes (CSS files), depending on the type of device being used.

This tutorial demonstrates how to add this capability to your application.

Step 1: Create the App

  1. Open a command prompt to your Ext JS 5 folder
  2. Run the following command:
    sencha generate app TestApp ../TestApp

Step 2: Define the Themes

  1. In your command prompt, change directories to the TestApp folder.
  2. Enter the following commands:
    1. sencha generate theme TestApp-Desktop
    2. sencha generate theme TestApp-Tablet
  3. Using your editor, open /TestApp/packages/TestApp-Desktop/package.json
  4. Modify the “extend” property to extend ext-theme-neptune.
  5. Save the file.
  6. Using your editor, open /TestApp/packages/TestApp-Tablet/package.json
  7. Change the “extend” property from ext-theme-classic to ext-theme-neptune-touch.

Step 3: Modify your App.json file to support multiple platform builds

  1. Using your editor, open /TestApp/app.json
  2. Add a “builds” property as illustrated here:
    "builds": {
        "testAppDesktop": {
            "theme": "TestApp-Desktop"
        },
        "testAppTouch": {
            "theme": "TestApp-Tablet"
        }
    }

Step 4: Modify your output definition to create multiple application manifests

Replace the output config property in your app.json with the following:

"output": {
    "base": "${workspace.build.dir}/${build.environment}/${app.name}/${build.id}",
    "page": "./index.html",
    "manifest": "../${build.id}.json",
    "deltas": {
        "enable": false
    },
    "cache": {
        "enable": false
    }
}

Step 5: Refresh your App

Return to your command prompt and type the following:
sencha app refresh

This will generate two manifest files: testAppDesktop.json and testAppTouch.json

Step 6: Replace the CSS config in the App.json

Replace the css configuration property in your App.json with the following:

"css": [{
    "path": "${build.out.css.dir}/TestApp-all.css",
    "bootstrap": true
 }]

Step 7: Replace the bootstrap property to load the appropriate manifest file

"bootstrap": {
   "manifest": "${build.id}.json"
}

Step 8: Add the following code into a script tag in your index.html file, just above the microloader, to load the appropriate manifest:

var Ext = Ext || {};
Ext.beforeLoad = function(tags){	
    var theme = location.href.match(/theme=([\w-]+)/);
 	theme  = (theme && theme[1]) || (tags.desktop ? 'testAppDesktop' : 'testAppTouch');
   
    Ext.manifest = theme;
    tags.test = /testMode=true/.test(location.search);
    Ext.microloaderTags = tags;
};

Step 9: Build the Application

Return to your command prompt and type the following:

sencha app build development

Step 10: Test the Application in a Desktop and Mobile Browser

Categories: Ext JS 5 Tags:

Sample Node.JS REST API Implementation with MySQL

March 10, 2015 1 comment

Here’s a simple example of a RESTful API implementation that I cobbled together for one of the students in our Node.JS Fundamentals course. It’s illustrates how to use the Express framework, along with a mysql datasource to implement create/read/update/destroy functionality on records.

Enjoy!

var express = require('express');
var router = express.Router();

var mysql = require('mysql');
var pool = mysql.createPool({
	host: 'localhost',
	user: 'root',
	password: '',
	database: 'NodeJSExamples'
});

/* GET users listing. */
router.get('/', function(req, res) {

	console.log(req);

	pool.getConnection(function(err, connection) {

		if (err) {
			console.error("An error occurred: " + err);
		}

		connection.query('select * from Person', function(err, rows) {
			if (err) {
				throw err;
			} else {
				res.writeHead(200, {
					"Content-Type": "application/json"
				});
				var result = {
					success: true,
					rows: rows.length,

				}
				res.write(JSON.stringify(rows));
				res.end();
			}

			connection.release();
		});

	});

});


router.delete('/:id', function(req, res) {

	console.log(req);

	pool.getConnection(function(err, connection) {

		if (err) {
			console.error("An error occurred: " + err);
		}

		connection.query('delete from Person where id=?', [req.params.id], function(err, rows) {

			if (err) {
				throw err;
			} else {

				res.writeHead(200, {
					"Content-Type": "application/json"
				});
				var result = {
					success: true,
					rows: rows.length,
					detail: rows

				}
				res.write(JSON.stringify(result));
				res.end();

			}

			connection.release();
		});

	});

});

router.put('/:id', function(req, res) {

	console.log(req.body);

	req.assert('lastName', 'Last Name is required').notEmpty();
	var errors = req.validationErrors();

	pool.getConnection(function(err, connection) {

		if (err) {
			console.error("An error occurred: " + err);
		}

		connection.query('update Person set ? where id = ?', [req.body, req.params.id],
			function(err, rows) {
				if (err) {
					throw err;
				} else {
					res.writeHead(200, {
						"Content-Type": "application/json"
					});
					var result = {
						success: true,
						detail: rows

					}
					res.write(JSON.stringify(result));
					res.end();
				}

				connection.release();
			});

	});

});


router.post('/', function(req, res) {

	console.log(req.body);

	// req.assert('lastName', 'Last Name is required').notEmpty();
	// var errors = req.validationErrors();

	pool.getConnection(function(err, connection) {

		if (err) {
			console.error("An error occurred: " + err);
		}

		connection.query('insert into Person set ?', req.body,
			function(err, rows) {
				if (err) {
					throw err;
				} else {
					res.writeHead(200, {
						"Content-Type": "application/json"
					});
					var result = {
						success: true,
						detail: rows,
						id: rows.insertId

					}
					res.write(JSON.stringify(result));
					res.end();
				}

				connection.release();
			});

	});

});

module.exports = router;
Categories: JavaScript

Ext JS: Generating a Checkbox Group from a Store

February 12, 2015 Leave a comment

Ext JS checkbox groups enable you to group checkboxes into a single logical field. Since these checkboxes are often times dynamically generated from a store, I thought that it might make sense to extend the class with some store binding. Here’s my first, lightly tested attempt:

 Ext.define('Ext.ux.CheckboxStoreGroup', {
    extend: 'Ext.form.CheckboxGroup',
    alias: 'widget.checkboxstoregroup',
    config: {
        store: null,
        labelField: 'label',
        valueField: 'id',
        checkedField: 'checked',
        columns: 3,
        boxFieldName: 'mycheckbox'
    },
    applyStore: function(store) {
        if (Ext.isString(store)) {
            return Ext.getStore(store);
        } else {
            return store;
        }
    },
    updateStore: function(newStore, oldStore) {
        if (oldStore) {
            store.removeEventListener('datachanged', this.onStoreChange, this)
        }
        newStore.on('datachanged', this.onStoreChange, this);
    },
    onStoreChange: function(s) {
        
        Ext.suspendLayouts();
        this.removeAll();
        
        var vField = this.getValueField();
        var lField = this.getLabelField();
        var cField = this.getCheckedField();
        var fName = this.getBoxFieldName();
        var rec = null;
        
        for (var i=0; i<s.getCount(); i++) {
            rec = s.getAt(i);
           
            this.add({
                xtype: 'checkbox',
                inputValue: rec.get(vField),
                boxLabel: rec.get(lField),
                checked: rec.get(cField),
                name: fName
            });
        }
        
        Ext.resumeLayouts(true);
        
    }, 
    initComponent: function() {
        this.callParent(arguments);
        this.on('afterrender', this.onAfterRender);
    },
    onAfterRender: function() {   
        if (this.getStore().totalCount) {
            this.onStoreChange(this.getStore);
        }
    }
});

You can test and play around with the code here:
https://fiddle.sencha.com/#fiddle/i51

Categories: Ext JS 4, Ext JS 5

Using Brackets for Ext JS Development

February 12, 2015 3 comments

Recently I evaluated using Brackets, a free, open-source, multiplatform-editor as a potential replacement for Sublime Text in our Javascript training courses.
brackets1
Brackets has a lot going for it:

  • It’s free
  • Installation is simple
  • It’s open source
  • Projects are directory-based, just like Sublime
  • It has a js linter built in
  • It has some intellisense
  • It does *not* auto-complete array and object syntax (brackets and curly braces)
  • It supports scss (Sassy CSS)
  • Performance doesn’t completely suck
  • It’s supports 3rd Party Plugins
  • It’s available for multiple OS.

And while it doesn’t fully support Sencha’s massive Ext JS library, it should help students quickly identify syntax problems with their json configs. I was able to configure Bracket’s built-in JS Linter to ignore nearly all of its “false-positive” errors and warnings.

The trick is to modify Bracket’s preferences file (Debug > Open Preferences File) as follows:

{
    "linting.collapsed": false,
    "themes.theme": "light-theme",
    "jslint.options": {
        "plusplus": true,
        "devel": true,
        "predef": [
            "Ext"
        ],
        "sloppy": true,
        "browser": true,
        "white": true
    },
    "useTabChar": false
}

You’ll need to restart Brackets for these changes to take effect.

So if you’re looking for a change of pace from using Sublime, or money is tight and you can’t afford JetBrains WebStorm or Sencha Architect, it’s worth giving Brackets a try.

Download Brackets at http://brackets.io/

Happy coding!

Categories: Ext JS 5, JavaScript
Follow

Get every new post delivered to your Inbox.

Join 658 other followers