Category Archives: JavaScript
Functional Programming and Promises
Callbacks are imperative, promises are functional: Node’s biggest missed opportunity
A nice post about functional programming and promises. Promises are interesting concept, and it would be a powerful tool to assist the concurrent programming.
However, I still feel the Node’s callback-based model is a reasonable approach to lower the thresholds of event-based concurrent programming. Having the compact first-class functions, the most of the expressions are concise, compared with heavy-weight languages like Java.
I’m now learning the Futures and Promises on Scala, but I’m having difficulties on grasping its programming style. It requires abstracted ways of thinking, and I’m struggling. Need more study.
Testing Strategies for Angular JS – Protractor @ YouTube
http://www.youtube.com/watch?v=UYVcY9EJcRs
This screencast explains some tools for AngularJS testing. Already popular Testem and Jasmine are well covered in other screencasts, but Protractor example was interesting.
Protractor is built on top of WebDriverJs, but also it provides angular-aware features like “By.binding” or “By.repeater” selectors as in the examples.
- https://github.com/davemo/lineman-angular-template/blob/master/spec-e2e/login_spec.js
- https://github.com/juliemr/protractor/blob/master/example/onJasmineNodeSpec.js
The document is limited, but it seems the basic interface is the same as WebDriverJs, and the protractor.js source-code can be used to identify the additional definitions in “ProtractorBy.prototype” parts.
Nice.
Notes
- Default testing file defined in “myConf.js” is “spec/testAppSpec.js”, which needs to be created for your tests.
- “Appendix A: Setting up a standalone selenium server” in the github page covers the webdriver setup, and then running “node_modules/.bin/protractor myConf.js” works.
It’s pretty much basic one, but the following is what I tried for testAppSpec.js.
var protractor = require('../node_modules/protractor/lib/protractor.js'); require('../node_modules/protractor/jasminewd'); describe('login', function() { var ptor = protractor.getInstance(); it('should remain in the sign-in page if the password is invalid', function() { ptor.get('http://localhost:3000'); ptor.findElement(protractor.By.id("user_email")).sendKeys("xxx@yyy.com") ptor.findElement(protractor.By.id("user_password")).sendKeys("XXX") ptor.findElement(protractor.By.tagName("button")).click(); ptor.findElement(protractor.By.tagName('h3')).getText().then(function(text) { expect(text).toEqual('Sign in'); }); ptor.findElement(protractor.By.id("user_email")).getText().then(function(text) { expect(text).toEqual(''); }); ptor.findElement(protractor.By.id("user_password")).getText().then(function(text) { expect(text).toEqual(''); }); }, 10000); });
AngularJS and Firebase @ YouTube
Realtime Web Apps with AngularJS and Firebase
It’s amazing. As indicated, AngularJS’s 2-way binding is extended into multi-clients by just adding a hook for Firebase. The Firebase nicely handles both persistence and notification with a simple interface. There’re some applauses in the demonstration (around 10:00-11:00), and I would make a similar response.
Links
- https://www.firebase.com/blog/2013-03-29-firebase-bindings-for-angular.html
- A blogpost about firebase binding fro angularJS.
- https://github.com/firebase/angularFire
- Github repo.
Code
Just made some modification to the previous server/client communication code, and it just worked as advertised.
<html ng-app="app"> <head> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script> <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script> <script src="https://cdn.firebase.com/v0/firebase.js"></script> <script src="angularFire.js"></script> <style> body { margin-top: 10px; } input.message { height: 30px; } </style> <script> var app = angular.module('app', ['firebase']); function AppCtrl($scope, angularFire) { var url = 'https://<my-firebase>.firebaseio.com/items' $scope.items = angularFire(url, $scope, 'items'); $scope.send = function() { $scope.items.push($scope.text); } $scope.clear = function() { $scope.items.length = 0; } } </script> </head> <body ng-controller="AppCtrl"> <form class="form-inline"> <input type="text" ng-model="text" placeholder="input message to send" class="message"></input> <button ng-click="send()" class="btn">send</button> <button ng-click="clear()" class="btn">clear</button> </form> <table class="table table-striped"> <tr ng-repeat="item in items"> <td>{{item}}</td> </tr </table> </body> </html>
EventMachine – WebSocket + AngularJS
One more EventMachine. Just tried to write a simple chat server using “em-websocket” gem (WebSocket server written over EventMachine). Client part is a simple HTML with AngularJS. It’s just wrapped around the native WebSocket object (couldn’t provide strong interaction with AngularJS).
Screenshot
Code
The following is the result of my trial.
Server (server.rb)
require 'em-websocket' index = 1 connections = {} def login_names(connections) connections.map {|ws, name| name}.join(", ") end EM.run do EM::WebSocket.run(:host => "0.0.0.0", :port => 8000) do |ws| ws.onopen do |handshake| name = "Guest#{index}" connections[ws] = name index += 1 ws.send "[Server] Hello #{name}" ws.send "[Server] Members are: #{login_names(connections)}" end ws.onclose do connections.delete(ws) end ws.onmessage do |msg| sender = connections[ws] connections.each do |cws, name| cws.send "[#{sender}] #{msg}" end end end end
Client (client.js)
var app = angular.module('app', []); app.factory('ChatService', function() { var service = {}; service.connect = function() { if(service.ws) { return; } var ws = new WebSocket("ws://localhost:8000/socket/"); ws.onopen = function() { service.callback("Succeeded to open a connection"); }; ws.onerror = function() { service.callback("Failed to open a connection"); } ws.onmessage = function(message) { service.callback(message.data); }; service.ws = ws; } service.send = function(message) { service.ws.send(message); } service.subscribe = function(callback) { service.callback = callback; } return service; }); function AppCtrl($scope, ChatService) { $scope.messages = []; ChatService.subscribe(function(message) { $scope.messages.push(message); $scope.$apply(); }); $scope.connect = function() { ChatService.connect(); } $scope.send = function() { ChatService.send($scope.text); $scope.text = ""; } }
Client (client.html)
<html ng-app="app"> <head> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script> <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script> <script src="client.js"></script> <style> body { margin-top: 10px; } input.message { height: 30px; } </style> </head> <body ng-controller="AppCtrl"> <form class="form-inline"> <button ng-click="connect()" class="btn">Connect</button> <input type="text" ng-model="text" placeholder="input message to send" class="message"></input> <button ng-click="send()" class="btn">send</button> </form> <table class="table table-striped"> <tr ng-repeat="message in messages"> <td>{{message}}</td> </tr </table> </body> </html>
Referenced Documents
- Writing an AngularJS App with Socket.IO
- It describes the integration with angularJS and Socket.IO. Also, the angular-socket-io-im referenced in the document just works nicely with node.js server.
- The above example doesn’t use this library, as I couldn’t make it work (at around loading related libraries). The Socket.IO examples are almost always being used with Node.js, and I didn’t have enough knowledge on that part.
- ANGULARJS WEBSOCKET SERVICE EXAMPLE
- it shows an example to use WebSocket and AngularJS. It’s a little complex to understand maybe due to it’s mixed with CallbackID and Customer model.
- How to keep track of users (connections) in a WebSocket Chat application
- An example of chat server using “em-websocket”.
Structuring AngularJS Code
As my AngularJS trial application is getting larger, code structure is getting messy. Then, I just bestirred myself to do some research on how to structure the AngularJS code well. This framework surely has an ability to structure the code well, but I feel it’s a little too powerful and difficult to control them. Some opinionated frameworks like “Ruby on Rails” have very solid structure and relatively easier to make the code fit into the system. I need more practice and learning for JavaScript world.
Note
File Structure
It seems that one way is to separate out directory/files for each type of angularJS modules(controllers, directives, services and filters). The “angular-seed” project provides concise template for the project structure. They’re defined as sub-modules (e.g. “myApp.controllers” or “myApp.services”), and they’re referenced in the “angular.module” statement for being used.
angular.module(‘myApp’, [‘myApp.filters’, ‘myApp.services’, ‘myApp.directives’, ‘myApp.controllers’]).
- GitHub – angular/angular-seed
- It’s a simple template for AngularJS project with test runners.
- Building Huuuuuge Apps with AngularJS
- It shows some examples to seperating out files into categories.
- AngularJS Best Practices: I’ve Been Doing It Wrong! Part 1 of 3
- It shows example structure along with some related technologies like Grunt and Karma.
Model Definitions
The basic models in AngularJS are the variables defined in $scope. Just keep adding data in the $scope can become very flat and messy. Then, Angular’s services (or factory) can be used as model class that contains data and behaviors. If the model value is assigned to the $scope variable, changing the data in the service (arrays and lists contained in the service) are reflected back to the $scope through data-binding. Then, the corresponding views are updated (though replacing the array/list itself needs to be separately handled).
- Modeling Data and State in Your AngularJS Application
- Showing an example to define the model as Angular’s service.
- AngularJS: Where to put model data and behaviour?
- Another example to define it as Angular’s service (ListService) and related discussion.
- http://jsfiddle.net/carpasse/mcVfK/3/
- An example that uses Angular’s factory. It’s a little difficult to identify which one to use.
AngularJS vs Ember
http://eviltrout.com/2013/06/15/ember-vs-angular.html
It’s a nice post talking about the difference between AngularJS and EmberJS. Though each point would get counter-arguments from experienced AngularJS programmers, this post makes good points.
What I am trying to establish is the framework does not encourage these practices. It is left up to the developer to build their application in the correct way, and the “correct” way seems to be up for discussion. Many of the things people tell me about how to properly structure an Angular application are not to be found anywhere on the official Angular docs. I believe they are better classified as “community conventions” for building good apps.
AngularJS has nice and simple concepts, but also it’s very flexible. Everything starts from very catchy double-binding input-text and concise todo-list implementation. But, it’s a little difficult to go further with controllers, directives and services for structuring code well.
I love the concept of AngularJS, but I’m struggling with my messy code when I try to use it. Pretty much I’m looking for good practices and idioms. AngularJS feels like being structured on hacker-minded way, and it’s a little difficult to control well for me.
AngularJS is relatively new framework yet. As it become more mature, more good practices and libraries would become available (I’m hoping so).
AngularJS 1.2 and Beyond
http://www.youtube.com/watch?v=W13qDdJDHp8
Just watched the above one. AngularJS 1.2 has not been released yet, but it’s nice to know the coming features in a consolidated form.
ng-animation (around 5:00)
The following site has a nice example, and it seems like using the ng-animate and TweenMax library (the sliding animation on click item seems handled in appFocus directive in app.js, but couldn’t understand the behavior enough).
Angular-Resource and Promise (around 10:00)
Angular resource now supports promise (like Project.query().$promise), for easily handling the transition more seemless. It allows waiting for the resources to be loaded. Previously, there’re some complex treatments were required.
Some related topics are in the following stackoverflow articles.
- Delaying AngularJS route change until model loaded to prevent flicker
- Angular RouteProvider – resolve not passing object to controller
ng-swipe (around 30:00)
Swiping support with “ng-swipe-left” and “ng-swipe-right”. Getting more built-in features for standard actions, nice.
An example is,
End-to-End Testing with Protractor (around 50:00)
New framework for testing. As I previously failed to write Angular Scenario Runner with Karma (with unknown reason). I’ll be trying with this one lator.
AngularJS Testing
Testing Directive
http://www.youtube.com/watch?v=rB5b67Cg6bc
After watching several videos from Mr. Miško Hevery, I’m getting to understand more on the testability consideration in AngularJS. Along with the modular design of framework itself, it has nice helper methods for testing which allows to easily test directives which involves HTML (DOM) interaction. Also, as described in the above tutorial, Karma (Testacular) provides very nice way to run test codes.
The followings are some notes when I configured the environment.
References
-
The official github site, which provides some instructions to install. After the installation, just adding location of files in the configuration file (“karma.conf.js”) is enough. Then “karma start” command automatically picks up related files in real time.
-
Some AngularJS testing samples. It’s good to refer working examples, as it’s a little to tricky to load or inject dependencies for AngularJS related modules.
Notes
- I’m now using Rails backend for angular-resource with ‘angularjs-rails’ gem file. As gem file doesn’t provide libraries in each project folder, I’ve separately downloaded and stored in the testing folder (not sure if there’s any good way to refer gem file content location).
- “angular-mocks.js” is required to use “inject” and “module” testing helper functions. Otherwise, it throws “not defined” errors.
- In karma.conf.js, list files in libraries -> sources -> tests order. Otherwise, it can show “not defined” errors.
excerpt – karma.conf.js
// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
// libraries
'test/javascripts/lib/angular.js',
'test/javascripts/lib/angular-resource.js',
'test/javascripts/lib/angular-sanitize.js',
'test/javascripts/lib/angular-mocks.js',
'test/javascripts/lib/jquery.js',
// sources
'app/assets/javascripts/word.js',
'app/assets/javascripts/date_helper.js',
// tests
'test/javascripts/src/*.js',
];
GoogleTechTalks – The Clean Code Talks
The Clean Code Talks — Inheritance, Polymorphism, & Testing
http://www.youtube.com/watch?v=4F72VULWFvc
A little old one, but it’s a nice coding-technique presentation from the father of AngularJS. It talks about using polymorphism instead of “if statements” for writing codes which are easier to read/test/maintain.
The philosophy behind the presentation seems like the origin of the AngularJS concepts. The modularity and declarative definition of behaviors, and also dependency injection for separating out business logics and object factories. Nice.
Notes
The good candidates for applying polymorphism instead of “if statements” are the followings.
- an object behaves differently based on its state.
- you have to check the same conditions in multiple places.
The example used here is modeling “1 + 2 * 3” calculation tree structure (figure in 7:52). The simple design is to create a “Node” class which contains “operators” and “values” along with the child left/right nodes (figure in 10:10), but it results in redundant representation, since the “operators” and “values” only requires some of them (figure in 11:10). Therefore, not required fields need to be nullified or filled with an invalid value like -1.
In such situation, applying polymorphism (figure in 14:26) helps simplifying the code. Separating out “ValueNode” and “OpNode” from “Node”, then creating “AdditionNode” and “MultiplicationNode” from the “OpNode” removes the redundancy of fields.
As a result, each class have a specific role, and it doesn’t require “if” branching. Also, new behavior can be added without modifying the original code (ex. adding operator). Each behavior is separated and easy to understand and easy to test.
AngularJS – ngAnimate
Just playing around ng-animate directive, which is newly introduced in v1.1.4. The following is a working example, as a result of my trial.
ngAnimate can be used along with ngRepeat or ngShow/ngHide directives which adds/deletes items in the screen. Simple animation just works with several CSS definitions, without requiring additional JavaScript code. It’s interesting. The power of declarative programming is getting stronger as more directives are being introduced. View logics are getting more simple.
The following are the sites which I have referred to , and they have examples and tutorials.
- http://code.angularjs.org/1.1.5/docs/api/ng.directive:ngAnimate
- http://www.nganimate.org/
- http://www.yearofmoo.com/2013/04/animation-in-angularjs.html
- http://yearofmoo-articles.github.io/angularjs-animation-article/app/#/ng-repeat
html
<div ng-app="app" ng-controller='AnimateCtrl'> <div class="page-header"> <h3>Animate</h3> </div> <div> Filter (Default Directive) : <input type="text" ng-model="search" autofocus> </div> <div class="box" ng-repeat="item in items | filter:search" ng-animate="'animate'"> {{item}} </div> <br><br> <div> Filter (Custom Directive) : <input type="text" ng-model="search2"> </div> <div class="box" ng-repeat="item2 in items2 | filter:search2" ng-animate="'animate2'"> {{item2}} </div> </div>
javascript
var app = angular.module('app', []); function AnimateCtrl($scope) { $scope.items = ["test1", "aaa", "bbb", "abc", "bcd"]; $scope.items2 = ["test1", "aaa", "bbb", "abc", "bcd"]; } var animationFunction = function(startCSS, endCSS) { return function() { return { setup : function(element) { element.css(startCSS); }, start : function(element, done) { element.animate(endCSS, function() { done(); }); } } } }; app.animation('animate2-enter', animationFunction({'opacity': 0}, {'opacity' : 1})); app.animation('animate2-leave', animationFunction({'opacity': 1}, {'opacity' : 0}));
css
body, div { font-family: 'Donegal One', serif; } .box { border: 2px solid; width: 200px; height: 50px; padding: 10px; margin: 10px; display: inline-block; border-radius: 10px; } .animate-enter, .animate-leave, .animate-move { -webkit-transition: 0.5s linear all; -moz-transition: 0.5s linear all; -ms-transition: 0.5s linear all; transition: 0.5s linear all; -webkit-transform: rotateX(90deg); -moz-transform: rotateX(90deg); -ms-transform: rotateX(90deg); transform: rotateX(90deg); opacity: 0; } .animate-enter.animate-enter-active { -webkit-transform: rotateX(0deg); -moz-transform: rotateX(0deg); -ms-transform: rotateX(0deg); transform: rotateX(0deg); opacity: 1; } .animate-enter-setup { } .animate-leave-setup { }