js: angular touch delay/lag on mobile

I had built InviteAgain.com to seamlessly work on mobile devices. This was the first project in Angular where I wasn’t handling my own mouse/touch up and down, and I just planned to rely on ng-click, and default mouse/touch behaviors to handle the table scrolling.

I was getting what felt like bad lag when running the app on mobile. The connection to the database would load and refresh data immediately, but the user interaction, ie touch, was taking forever to respond. So after some head bashing, I managed to learn the hard way that the library angular-touch, made by angular, is pretty much a requirement for mobile if you are going to rely on ng-click, and not handle your own mouse up and down.

Angular-touch modifies the standard ng-click to remove a 300ms delay mobile browsers otherwise impose while waiting to see if the user is going to double tap. Problem solved!

js: parsing csv files in angular with papa parse

I’ve been trying to embrace/balance using more libraries and less native code. The CSV parsing I needed to do on InviteAgain.com was a great candidate. I found PapaParse. Perfect. Simple javascript class that can handle all use cases via a single settings object.

I setup an Angular directive and template that I can plug in anywhere to get a custom file input UI. That UI contains another directive linked to the file input event. On file input angular hands the csv off to the Papa object. I tell it the data has headers, to use web workers, and to run $apply() on the scope after it’s completed parsing the file. Papa hands me back a javascript object with all the csv’s key/value pairs. Done.

.directive('onReadFile', function ($parse) {
  return {
    restrict: 'A',
    scope: {conSec: '=', current: '='},
    link: function(scope, element, attrs) {
      element.on('change', function(onChangeEvent) {

      var file = (onChangeEvent.srcElement || onChangeEvent.target).files[0];

       Papa.parse(file, {
          header: true,
          worker: true,

          complete: function(results) {
            if(scope.conSec.name){
              scope.conSec.fileInput.err = results.err;
              scope.conSec.fileInput.data = results.data;
              scope.conSec.fileInput.meta = results.meta;
              // Need to force the update
              scope.$apply();
            }
          }
        });
      });
    }
  };
})

.directive('fileInput', function(){
  return {
    restrict: 'E',
    scope: {conSec: '=', current: '='},
    templateUrl: "../templates/fileInput.html"
  };
});

js: hhgholders.js, a 2d object oriented sprite based engine v0.5.1

hhgholders.com

This is a 2d object oriented engine, written in javascript. It only uses the DOM for rendering, while extrapolating everything else into a standard sprite system, akin to Cocos2d or Apple’s SpriteKit, based on sprites and actions.

The standard usage is to simply use the HHgHolder class and then allow the engine to handle the rest. You get to completely ignore HTML and CSS. But all elements remain as standard DIVs behind the scenes, so any modifications can be made to HTML/CSS/Javascript that would be made to a standard web page.

The engine functions entirely independantly of the DOM, except for HHgScene.js which updates all the dirty visible elements per frame. HHgScene could be modified to “translate” the engine’s data into any one of a number of visual forms/renderers. The rest of engine is agnostic.

The engine is most notably missing a physics system, but in general is not really designed to be a thousands of things bouncing and updating engine. Though one could easily be added and then use updates on HHgHolders.


Usage Doc v0.1.5
(This is much more easily read on github, or in the local repo)
//=============================================================
Preface: for the most part, you should not need to modify many engine files
          except for:
          HHgConfig.js (top level and settings)
          HHgGame.js (the entry point for custom code)
          HHgTests.js (test and debug settings)

1. The scene will automatically scale visually to the width of the screen.
  a. But all measurements are done on a point system of 1920/1080.
    aa. so even if you are on a tiny phone, or in a small browser window, you would still commonly use 1920 as screen width (if set to landscape).
  b. All of these settings can be changed in HHgConfig.js

2. HHgLoadingScreen.js is loaded before any engine processing takes place.
  a. This is the only other file you would need to modify.

3. HHgGame.doStart() is called by the scene once setup is finished.
  a. Modifying HHgTestsOverride in HHgTests.js will use the doStart() in HHgTests.js as a starting point.
  a. Otherwise the engine will run the default demo doStart() located in HHgGame.js.

4. HHgActionManager runs a requestAnimationFrame loop which has 3 steps per frame:
  a. calculate outcomes of all HHgActions.
  b. calculate final results of these on all HHgHolders.
  c. tell scene to update all visual elements.
  d. NOTE: it also calls HHgGame.doLoop once per frame, but making use of it is not required

5. HHgHolder is the only visual element in the engine.
  a. It holds images/sprites, color, text/paragraph text, or other HHgHolders:
    var someHolder = new HHgHolder({w: 100, h: 100});
    aa. but unless you specifally choose not to use it, you should use the ObjectPool to get holders:
      var someHolder = var HHgGetHolder({w: 100, h: 100});
      aaa. and then return the holder to the pool when no longer needed:
        HHgReleaseHolder(someHoldervar);
    ab. a holder needs to be added to a parent holder, HHgGameHolder is created by default, in order to be visible, and then needs a sprite/image, color, or text.
      someHolder.doMoveToNewParent({parent: someOtherHolder, position: new HHgVector2(-200,-200), isScreenPos: true});
      someHolder.doAddSprite("testSprite");
      someHolder.doAddParagraphText({text: "my text", color: {H: 255, S: .5, L: .5, A: 1}, shadow: {color: "black", x: 4, y: 4, blur: 4}});
      someHolder.setMouseable(true);
      someHolder.setIsDraggable(true);
  b. Please note that many of the properties (most) require the use of getters/setters
    ba. This is to allow for specific calculations and scene updates when values are changed.
      var someNumber = someHolder.getWidth();
      someHolder.setPositionInScreenTo(29,45);
      someHolder.setPositionInParentTo(new HHgVector2(200,200));
  c. HHgHolders are automatically updated when their parent holders are updated by Position/Rotation/Scale.
  d. holders can be positioned in a parent, or in screen. and each one updates the other.
    da. So if you call someHolder.setPositionInScreenTo(0,0), its position in parent will change.
      daa. var newVector = someHolder.getPositionInParent();
  e. HHgHolders depth is based on their zIndex property. Changing the zIndex of a parent will adjust all children

6. HHgGameHolder is the top level Holder in the hierarchy.
  a. any HHgHolders you wish to add to the game and not be parented to another Holder should be parented to this:
    someHolder.doMoveToNewParent({parent: HHgGameHolder, position: {x: 200, y: 200} });
    aa. providing no parent argument will default to adding to HHgGameHolder.
  b. HHgScene is technically an HHgHolder, but scale and position will be incorrect for children.

7. Properties Object - most classes and high level functions expect a javascript {} to be passed as arguments.
  a. The HHgHelper object then runs one function per expected argument to process and filter the input
    aa. This means that argument passing tends to be flexible, so for size you could pass in:
      aaa. {size: 100} or {w: 100, h: 100} or {size:{w: 100, h: 100}} etc.
  b. But for complex classes like creating an action, you'll pass in a single object with multiple key value pairs.
  c. Almost all values are optional, and will be filled in with a sensible value if omitted, like 0,0 for position.

8. HHgAction is what holders use to animate or change or set timers.
  a. You do not need to create HHgActions directly, you can use helper functions of .doAction("Move") or:
  aa. helper functions on HHgHolder
    someHolder.doActionRotateBy({rotation: HHg.returnRandomInt(120,720), time: HHg.returnRandomInt(5,35)});
    someHolder.doActionFollowQuad({cx: 0, cy: 540, x: 960, y: -540, time: 10, easeIn: 25, easeOut: 25 });
  b. The holder and the actionManager will handle the rest.
  c. You can pass a 'name' key/value into the above functions to uniquely name an action on an object.
    ca. This then allows you to call doRemoveActionByName(name);
  d. passing a key for 'onComplete: someFunction' to the function will cause the passed function to be executed on completion.
  e. HHgHolder has actions for:
    doActionRotateBy(any amount from negative to positive, time);
    doActionRotateLeftTo(any degree from 0 - 360, time); doActionRotateRightTo(); doActionRotateForever(+/- rotation per second);
    doActionMoveInScreenTo(x,y, time); doActionMoveInScreenBy(); doActionMoveForever(vector per second);
    doActionScaleTo(positive value, positive value, time); doActionScaleBy(positive value, positive value); doActionScaleForever(scale per second);
    doActionFollowQuad(vector control, vector destination, time); //creates a quadratic path using the current xy, a control xy, and final xy
   f. //TODO make this more complete: but there are also Sequences and Clusters of actions, and helper functions to create and save actions, which can then be added to sequence, or run forever, etc.

9. Timers - do not use setTimeOut or setInterval anywhere, as this will cause things to fall out of sync
  9a. Instead call a timer action on an HHgHolder
    someHolder.doActionTimer({time: 10, onComplete: someFunc});

10. Values
  a. the xy grid for positioning on the screen, and in Holders is 0,0 centric with Y-up x,y coordinates (default point dimension is 1920/1080)
  b. time is always in seconds
  c. colors are always eventually in an HHgColorRGBA object, but most classes and functions will take HSL, RGB, or Hex values
    ca. this just means that passing in arguments other than a color object will result in a conversion step.
  d. all position/rotation/scale values are in points, so 1 or 1.5 or .044567. no strings, no trailing "px", etc.
    da. the engine will handle all of the conversions in the HHgScene.js file.

11. Mouse and Touch
  a. there are built in mouse and touch and drag handlers on HHgMouse.js, the engine will use the correct ones based on device type.
  b. you should not need to modify HHgMouse.js, instead, override the existing HHgHolder methods:
    doMouseDown(); doMouseUp(); doStartMouseMove(); doMouseMove(); doEndMouseMove();
  c. the engine calculates a holder as 'touched' based on z-index and sprite pixel alpha;
    -note: if a holder is set to mouseable, but has no sprite, then the holder width and height will be used.
    ca. but a Holder must have mouseable set to true, which is set to false by default.
      someHolder.setMouseable(true) to receive any mouse or touch interactions.
  d. for a holder to recieve the move events, it must be set to draggable.
    da. someHolder.setIsDraggable(true);
  e. HHgMouse recieves an array of all qualifying Holders for mouse/touch, it only uses the highest element in the array.
    ea. if you need to access a "stack of holders" for something like dragging a stack, then you'll need to modify HHgMouse.js.

12. HHgColor
  a. all color in the engine eventually comes down to R: 1-255 G: 1-255 B: 1-255 A: 0-1
    aa. and creating a new color object:
      var someColor = new HHgColorRGBA(255,255,255,1);
    ab. there is also an HSL color object: H: 0-360, S: 0-100, L: 0-100, A: 0-1
      var someColor = new HHgColorHSLA(360,100,100,1);
    ac. HHgColorHelper has methods to convert to and from RGB, HSL and Hex
      aca. many functions and classes will do this conversion automatically if you pass in anything other than RGBA
  b. HHgColor objects also have methods like .lighten(color, percent).
  c. HHgColorHelper has methods like .blendRGBA(color1, color2, percent).

13. HHgVector2 //TODO update vector names and functions
  a. HHgVector2 is the basis for passing grid coordinates, vectors, and scales.
    var someVector = new HHgVector2(50.5,323.7);
  b. HHgVector2's contain all functions for vector math: add, subtract, divide, etc.
    ba. these are also all versioned with aliased and verbose names:
    bb. they also return a new vector, and do not modify the existing vector
      var someVector = vector1.returnVectorPlusVector(vector2);
      var someVector = vector1.returnAdd(vector2);
      var someVector = vector1.returnVectorScaledBy(vector2);
      var someVector = vector1.returnMultiply(vector2);
  c. to immediately modify existing vectors, use the 'plusEquals'/etc functions.
    someVector.plusEquals(someOtherVector); someVector.addEquals(someOtherVector);
    someVector.divideEquals(someOtherVector);
  d. Other useful functions:
    someVector.returnDistanceToVector(someOtherVector);
    someVector.returnVectorRotatedAroundVectorAtAngle(someOtherVector, angle); //this will all be handled for you in actions and they rarely ever need to used directly
    someVector.returnVectorAtDistanceToVector(someOtherVector);
  e. to save memory allocation you can use someVector.setXY(x,y) to change the values of a vector.
    ea. but be very careful using this, as vectors tend to get passed around, and these are objects passed by reference:
      eaa. unlike in many languages where a vector would be a struct passed by value.

14. HHgText
  a. all text is displayed in engine by adding it to HHgHolders.
    aa. this text is one of 2 types:
      aaa. someHolder.doAddParagraphText({text: "my text", color: {H: 255, S: .5, L: .5, A: 1}, shadow: {color: "black", x: 4, y: 4, blur: 4}});
      aab. someHolder.doAddCanvasText({text: "my text", color: {H: 255, S: .5, L: .5, A: 1}, shadow: {color: "black", x: 4, y: 4, blur: 4}});
    ab. paragraph text creates a 'pre' (preformatted text) element inside of the div.
      aba. this text is then modified via standard CSS.
      abb. when the div is scaled, the scene recalculates the font size to adjust for the div scale.
      abc. this text is not part of the canvas, and is therefore not subject to mouse/touch tests.
    ac. canvas text is created by formatting a 2d context and then painting the text directly onto the div's canvas
      aca. there are different pros and cons for rendered/rasterized text. Canvas text will also be part of the alpha pixel test for mouse interactions.

15. Adding and Modifying
  a. the engine is designed to have anything and everything modded, but I recommend not changing anything on HHgHolder or HHgScene:
    aa. unless you understand exactly what it's doing.
  b. tack any properties onto holders that make sense to you, and create any custom controllers to handle game logic.
  c. HHgActionManager runs a set of functions every frame that receive the delta time since the last frame:
    ca. actions already handle all of their updates via this delta
    cb. but you can also make use of HHgGame.doLoop() which is called each frame if you were going to add somthing like a physics system, etc.
  d. you can also use the doAddCSSClass() and doRemoveCSSClass() to use custom CSS class functionality in holders.
    da. but I don't really recommend it, as things like actions and canvases won't always play nice with them. But they can be handy if you are using the engine for making more static things, or just for pure styling.
  e. the engine uses the file HHgMain.css as it's only css file.
    ea. this file resets browser behavior, adds clearfix, and sets up some basic table functionality for text in divs
    eb. you are welcome to add, but be careful of modifying any of the existing css elements, as alot depends on them.

15. Usage and Quirks
  a. you'll notice that pretty much any function that you are supposed to interact with starts with "do" to do something or "return" to calculate and return something
  b. or "get" and "set" for property access. the engine does a lot of secondary computation after properties are set.
    ba. so this requires the use of functions instead of standard .access
  c. most functions require property objects to be passed as arguments {R: 255, G: 255, B: 255};
    ca. but if a function just takes 1 concept, then it usally can be short-handed for faster typing:
      funcTakesColor(255,255,255); or funcTakesColor(new HHgColorRGBA({R:255, G:255, B:255, A:1}));

node: mysql column name collisions on select, join

I’ve been playing around with the MySQL Node module. I came to a place where the async javascript callback result for selects on multi-table joins started having key name collisions.

In comes nestTables:true. Wrapping the select query in an object with the nestTables property set to true will cause the result object to use nested objects for each table.

//Return Obj has name collisions
  db.query('SELECT parents.name,\
                   jobs.type, \
                   locations.name \       
            FROM parents JOIN jobs \
              ON jobs.id=parents.jobId \
                         JOIN locations \
              ON locations.id=parents.locationId',
            function(err, result){
              console.log("LOG:",result);
              //LOG: [{type:'Teacher',
              //       name:'Home'}]
          });
//Return Obj is now broken out by table with sub properties
  db.query({sql: \
           'SELECT parents.name,\
                   jobs.type,\
                   locations.name\
            FROM parents JOIN jobs \
              ON jobs.id=parents.jobId \
                         JOIN locations \
              ON locations.id=parents.locationId',
            nestTables:true},
            function(err, result){
              console.log("LOG:",result);
              //LOG: [{parents:{name: "Joe"},
              //       jobs: {type:'Teacher'},
              //       locations:{name:'Home'}}]
          });

Note: you can also use nestedTable: "_" to force the result to use TableName_ColumnName as the object keys.

meteor.js: easier default account system files

The account backend in meteor is pretty decent, and is wired up to all the basics, but manipulating the front end is an exercise in frustration, and wiring up the additional features is a headache. The CSS is all wrapped up in compiled files and LASS. So you install one of the packages that removes the styling, but even that makes it a huge pain to change or manipulate the UI. And even then, that UI is tied to some of the basic vanilla behavior and leaves out a lot of the smart and complex features that are available and sometimes necessary.

So instead of making a package that would just be difficult to customize to my needs on projects going forward, I baked all features of the Meteor account system down into 3 files:

customAccounts.html
customAccounts.css
customAccounts.js

By default, all the features are in place, and the UI is styled to match meteor’s home page. As well as being broken into easy to understand templates for all states and use cases…using actual buttons instead of a weird hybrid of hyperlinks and buttons. Every account related feature and function is either wired up in the javascript file, or if it’s a less common feature, then stubbed in with example uses.

Just drop ’em into your project folder, no package installation required.
https://github.com/CHBDev/Complete-Meteor-Account-Pipeline

js: the requestAnimationFrame() game loop

Historically, web/js based apps had to basically set their own “loop” using setInterval or setTimeout. There’s actually not a huge downside to using those, except when framerate becomes an issue. So now we can use requestAnimationFrame(). It has a number of uses, but the simplest is just to have it handle the entire game loop.

Essentially RAF calls a callback function every time the interpreter can come up for air. This combined with tracking the delta in time between frames can allow you to handle changes in framerate more smoothly.

In the implementation below calling myGame.actionLoop() calls recurse(), which then has requestAnimationFrame call the recurse loop repeatedly. I’ve broken the specific game logic out into the function var doThisEveryFrame just to clearly illustrate the effect.

myGame.actionLoop = function() {
    var lastFrameTime;
    var deltaT;
    var lowEnd = 1;
    var highEnd = 160;

    var doThisEveryFrame = function(timeDiff){
      myGame.updatePhysics(timeDiff);
      myGame.updateLogic(timeDiff);
      myGame.renderChangesToScreen();
    };

    function recurse( thisFrameTime ) {
        window.requestAnimationFrame(recurse);
        thisFrameTime = thisFrameTime && thisFrameTime > 5000 ? thisFrameTime : window.performance.now();
        lastFrameTime = lastFrameTime || thisFrameTime;
        deltaT = thisFrameTime - lastFrameTime;

        if (deltaT >  highEnd){
          deltaT = highEnd;
        }
        if(deltaT > lowEnd){
          doThisEveryFrame(deltaT);
          lastFrameTime = thisFrameTime;
        }
    }
  recurse();
};

js: window.performance on mobile

I’d been playing around with some graphically intensive tests in javascript and openGL, but when I went to test them on various mobile devices, huge aspects of them were failing. After a few minutes I realized that window.performance.now was missing. Here’s a shim I found that does the trick.

(function(){
  if ("performance" in window == false) {
      window.performance = {};
  }
  Date.now = (Date.now || function () {
    return new Date().getTime();
  });
  if ("now" in window.performance == false){
    var nowOffset = Date.now();
    if (performance.timing && performance.timing.navigationStart){
      nowOffset = performance.timing.navigationStart
    }
    window.performance.now = function now(){
      return Date.now() - nowOffset;
    }
  }
})();

the above polyfill is // copyright Paul Irish 2015

js: div actions

divAction.js

I made a simple demo framework for animating divs using composite actions for position, scale, and rotation. I was tired of manipulating css for demoing things. I just wanted to instantiate a class, and then call methods on it to animate, much like you would in cocos2d or SpriteKit.

It’s actually a pretty performant little streamlined package. It updates all actions per frame using requestAnimationFrame. It was meant for demoing and presentations, but it could do more.

demo.js contains the examples for how to:

–instance a Thing, which is just a class wrapped around a div.
–add actions to a Thing to move it, rotate it and scale it.
–the top portion has demo flags to force fixed intervals, and lower performance, all just for the purpose of discussion.
–Note: actions are composite, which means if you add 2 movement actions to a Thing, then the thing will be updating each frame based on both actions.

Since everything is just a div, you could add CSS classes and files, use standard button and click and link commands, etc.

For demo purposes the code in the Thing/actions is not very dry, if you were going to really use this to do anything, you’d want to make an action class and create instances of Actions and add them to Things. That way you could also easily pause or remove an individual action ahead of schedule.

Oh, and obviously all the objects have just simple names stored in global, so please wrap them up in something first.

https://github.com/CHBDev/divActions