Category Archives: Uncategorized

Console Log Output – Substitution and CSS in Chrome

Debugging should be more colorful.

Console.log in Chrome accepts a number of parameters including css.

Output can be stylized by using %c prior to the stylized text.

Example:

console.log("I'm%c Colorful.", "color: blue; font-size:14px");

A simple utility wrapper I use to stylize console.log output.

var styled = (function () {

var fontStyle = 'font-family: Helvetica,Arial,sans-serif; font-size: 13px;', boxStyle = ' line-height: 25px; padding: 5px 5px; border-radius: 4px;', styles = { msg : ' color: #eee; background: #222; ' + fontStyle + boxStyle, err : ' color: #0F0; background: #222; ' + fontStyle + boxStyle }, log = function (msg, styleStr) { if (styleStr) { console.log('%c' + msg, styles[styleStr]); } else { console.log('%c' + msg, styles.msg); } } return log; }());

styled('New Log Style. '); 
styled('New Error Style. ', 'err');

Additional Console substitutions.

As String:

console.log('%s', 'String'); // String

As Integer:

console.log('%d', 5.3); // 5
console.log('%i', 5.3); // 5

As Float:

console.log('%f', 5.3); // 5.3

Displaying expandable Objects / Arrays (note: css cannot style this output).

console.log('Expandable object or array %O', {type:'color', color:'blue'}); // Expandable object or array Object

Random Example:

console.log("I'm%c - %c%s%c.", "color: black; font-size:19px", "color: blue; font-size:14px", "Colorful", "color: black; font-size:19px");

Javascript – Observer Pattern Implementation

While working on a project that needs to notify when updates are made, I started playing with the Observer Pattern in Javascript. Changes made to the Observed Object trigger a console.log when updates are made. The actual implementation is using SocketIO to notify users of updates concurrent with updates to the persistence layer.

Note: The code is still in development and needs additional refactoring.

(function () {

  'use strict';
  /*global console */

  function Observable() {

  // Observable class
    var _observingArray = [];
    
    return {

      action: function (action, func) {
        console.log(action, func);
      },

      addWatcher: function (obj) {
        var funcName = arguments[0].name;
        if (!_observingArray[funcName]) {
          this.action('New Watcher:', funcName);
          _observingArray.push(obj);
        }
      },
      
      removeWatcher: function(obj) {
        var i = 0,
          len = _observingArray.length;
        for (i; i < len; i++ ) {
          if (_observingArray[i] === obj ) {
            _observingArray.splice(i, 1);
            var funcName = arguments[0].name;
            this.action('Removing Watcher:', funcName);
            return true;
          }
        }
        return false;
      },
      
      notify: function () {
        // arguments is an array like object / converted to array here
        var args = Array.prototype.slice.call( arguments, 0 );
        var i = 0,
          len = _observingArray.length;
        for (i; i < len; i++) {
          _observingArray[i].update.apply( null, args );
        }
      }

    };
  }

  // basic example of observer object with 
  function MakeObservableObject() {

    // very basic object comparator
    function updateObject(obj, updates) {
        var updated = false;

        Object.keys(updates).forEach(function(k) {
          // if property values are different update
          if (obj.contents[k] !== updates[k]) {
            if (updates[k] > 0 || updates[k].length > 0) {
              // if property has a value - update
              obj.contents[k] = updates[k];
            } else {
              // if property has no value - delete the property
              delete obj[k];
            }
            updated = true;
          }
        });
        if (updated) {
          return obj;
        }
        return false;
    }

    var items = {}; 

    var observer = MakeObserver(this);

    // notifies watchers
    this.getItems = function getItems() {
      observer.notify(items);
    };

    // initial configuration of object properties
    // does not notify watchers
    this.setItems = function setItems(obj) {
      items = obj;
    };

    // updates object properties
    // notifies watchers of new object contents
    this.update = function updateItems(updates) {
      if (updates) {
        var updated = updateObject(items, updates);
        if (updated) {
          items = updated;
          observer.notify(items);
        }
      }    
    };
  }
  

  function MakeObserver(obj) {
      
      // obj passed in is extended with Observable methods and returned
      var observable = Observable();

      // obj passed in is added as an observer
      obj.addObserver = function addObserver(observer) {
        observable.addWatcher(observer);
      };

      // obj passed in is removed from observable as an observer
      obj.removeObserver = function removeObserver(observer) {
        observable.removeWatcher(observer);
      };

      return observable;
  }

  // ============================
  // ========= Examples =========
  // ============================

  // CUSTOM OBSERVER Methods
  var ItemUpdater = {
    name: 'ItemUpdater',
    update : function() {
      var item = arguments[0];
      console.log( 'Update ItemUpdater:', item.name, ' = ', JSON.stringify(item.contents));
    }
  };

  var ItemCharts = {
    name: 'ItemCharts',
    update : function() {
      var item = arguments[0];
      console.log( 'Update ItemCharts:', item.name, ' = ', JSON.stringify(item.contents));
    }
  };

  // OBSERVABLE OBJECT
  var app = new MakeObservableObject();

  // OBSERVABLE OBJECT CONTENTS
  var items = {
    name: 'clothes', 
    'contents': {socks : 7, pants : 3, shirts : 4}
    }; 

  // SET OBSERVABLE OBJECTS - PUBLIC CONTENTS 
  app.setItems.call(app, items);

  // ADD OBSERVER
  app.addObserver(ItemUpdater);

  // ADD OBSERVER
  app.addObserver(ItemCharts);

  // CHECK CURRENT CONTENTS / TRIGGER NOTIFICATION
  app.getItems();

  // REMOVE OBSERVER
  app.removeObserver(ItemUpdater);

  // REMOVE OBSERVER
  app.removeObserver(ItemCharts);

  // ADD OBSERVER
  app.addObserver(ItemCharts);
  app.update({'ties':26.00});
  app.getItems();

  // OBSERVABLE OBJECT
  var music = new MakeObservableObject();
  // OBSERVABLE CONTENTS
  var albums = {
    name: 'music', 
    'contents': {blues : 1, jazz : 3, punk : 2}
    }; 
  music.setItems(albums);
  music.addObserver(ItemCharts);
  music.addObserver(ItemUpdater);

}());

Apple Remote Desktop Client – Status Offline

Apple Remote Desktop Client has been displaying “Current Status = Offline” for machines without cause. When a mac is “Offline”, ARD, AFP, SMB, and SSH are stop working. However, the
mac can still be pinged and its web server is still accessible.

Apple Remote Desktop Client is crashing and causing the issues. I don’t understand why SSH and SMB stop working when this happens, any comments would be appreciated.

I’m posting the AppleScript that I wrote to resolve the issue. A restart is not required, but resolved network issues outside of ARD for me. Please comment if this works, doesn’t work or needs to be updated in any way.


on doShellScript(cmd, pswd)
    if (length of pswd > 0) then
        display dialog pswd
        do shell script cmd password pswd with administrator privileges
    else
        display dialog "This process requires an admin password."
        requestInput()
    end if
end doShellScript

on restartNow()
    tell application "Finder"
        restart
    end tell
end restartNow

on requestInput()
    set admin_password to display dialog ¬
        "Please enter your password:" with title ¬
        "Password" with icon caution ¬
        default answer ¬
        "" buttons {"Cancel", "OK"} default button 2 ¬
        giving up after 295 ¬
        with hidden answer
    set pswd to text of text returned of admin_password
    
    set cmds to {¬
        "ls", ¬
        "sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -agent -stop", ¬
        "sudo rm -R /Library/Application\\ Support/Apple/Remote\\ Desktop/Client", ¬
        "sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -agent -restart"}
    
    doShellScript(item 1 of cmds, pswd)
    doShellScript(item 2 of cmds, pswd)
    doShellScript(item 3 of cmds, pswd)
    requestRestart()
end requestInput

on requestRestart()
    set restartAnswer to display dialog ¬
        "Would you like to restart now?" with title ¬
        "Restart" with icon caution ¬
        buttons {"Cancel", "OK"} default button 2 ¬
        giving up after 295
    
    set answer to text of button returned of restartAnswer
    
    if (answer is equal to "OK") then
        restartNow()
    end if
end requestRestart

requestInput()

Set up Mongodb as a daemon / service on a Mac –

Launch MongoDB on Startup or User Login

A quick post on setting up Mongodb to start automatically on a Mac so I can do my other work. To start, I found a link to Apple’s info about Mac daemons and services.

About Daemons and Services

Which lead me to the section that specifically talks about Launching Custom Daemons Using launchd.

Launching Custom Daemons Using launchd

Which talks about system daemons.

It uses the plist files in the following folders /System/Library/LaunchDaemons/ and /Library/LaunchDaemons/ to register daemons. It attempts to launch the daemons in a somewhat random order, if a daemon has a dependency, its launch is deferred momentarily while other daemons are launched.

MONGODB as a daemon / service for mac

Create a link to the MONGODB plist file

(s = symbolic, f = replace existing, n = link is seen as a normal file)

To start using the current users LaunchAgents

ln -sfv /usr/local/opt/mongodb/*.plist ~/Library/LaunchAgents

use launchctl to direct launchd to load mongodb .

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist

To start as a system wide daemon use the following

ln -sfv /usr/local/opt/mongodb/*.plist /Library/LaunchDaemons/

use launchctl to direct launchd to load mongodb .

launchctl load /Library/LaunchDaemons/homebrew.mxcl.mongodb.plist

homebrew.mxcl.mongodb.plist

This file tells launchd how to launch the application, where the config files and log files should be and should look something like this.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>homebrew.mxcl.mongodb</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/opt/mongodb/bin/mongod</string>
<string>--config</string>
<string>/usr/local/etc/mongod.conf</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
<key>WorkingDirectory</key>
<string>/usr/local</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/mongodb/output.log</string>
<key>StandardOutPath</key>
<string>/usr/local/var/log/mongodb/output.log</string>
<key>HardResourceLimits</key>
<dict>
<key>NumberOfFiles</key>
<integer>1024</integer>
</dict>
<key>SoftResourceLimits</key>
<dict>
<key>NumberOfFiles</key>
<integer>1024</integer>
</dict>
</dict>
</plist>

The config location is referenced in above plist file (--config). Currently, the default points to /usr/local/etc/mongod.conf. Set the dbPath to the path to the db for your implementation.

mongod.conf
systemLog:
destination: filexvc
path: /usr/local/var/log/mongodb/mongo.log
logAppend: true
storage:
dbPath: /dbData/db
net:
bindIp: 127.0.0.1

AngularJS – UI Bootstrap DatePicker

The AngularUI team made a collection of nice Bootstrap components.

Unfortunately, the DatePicker appears to have a conflict with other scope variables.

The recommended javascript to open the DatePicker is shown below.

$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};

This code will work once and only one.

If the DatePicker is closed, it cannot be re-opened.

The problem is caused by a generically named scope property.

Changing three things will fix the issue.

Change the javascript to the following.
$scope.openDatepicker = function($event) {
$event.preventDefault();
$event.stopPropagation();
if (typeof($scope.datepicker) === 'undefined'){
$scope.datepicker = {};
}
$scope.datepicker.opened = true;
};

Change the inputs is-open attribute as shown below.
is-open="datepicker.opened"

Change the buttons ng-click attribute as shown below.

ng-click="openDatepicker($event)"

Angular UI Bootstrap

Angularjs – ngTagsInput v2.2.0 – “Duplicates in a repeater are not allowed.”

ngTagsInput is a great tags input directive for Angularjs. It auto suggests tags from an external source and populates them into an input for form submission. While using it, I discovered that having multiple instances on a form caused an angularjs error.

Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: tag in tagList.items track by track(tag), Duplicate key

If you experience this error, search and find the following.

tag in tagList.items track by track(tag)
item in suggestionList.items track by track(item)
Replace it with the code below.

tag in tagList.items track by $index

This allows Angular to keep track of the items in the repeat.

item in suggestionList.items track by $index

ngTagsInput

ngRepeat

csmsc – Create SailsJS Model and Controller w Node Command Line

Published a node command module to automate the creation of Models and Controllers for a SailsJS api.

csmsc

This is a node.js command line utility that creates SailsJS base Models and Controllers for API use.

Installation

This utility is available on npm. Globally install it by using the -g flag:

bash
npm install -g csmsc

Usage

To use it, cd into a project directory, and run csmsc with -n and -f args to represent model name and properties respectively.

Examples

Make a model and controller for ‘modelName’ with properties ‘primaryproperty’, ‘anotherproperty’ and ‘aThirdproperty’:

bash
csmsc -n ModelName -f firstprop,secondprop,thirdprop

bash
csmsc -n ModelName -f title,url,subtitle,text,author -c tags -m company

Notes

SailsJS expects controllers and models to be created using Pascal Case please appropriately name Models with the first character uppercase to ensure compatibility.

csmsc will write the model into the api/models/ folder. csmsc will write the controller into the api/controllers/ folder.

Existing files will be over written.

Model properties are string by default, modify as needed.

MongoDb will add the following

_id as a unique identifier.
createdAt date created.
updatedAt date last updated.

csmsc will add the following

createdBy user that created the record.
updatedBy user that last updated the record.

createdBy and updatedBy values must be passed to the api or will default to ‘admin’

Additional Notes

GENERATE model and Sails controller for SailsJS api

-n is the name of the model and controller.
-f is a list of comma separated fields
-c is a list of comma separated collections (one to many)
-m is a list of comma separated models (one to one)

the first field in the field list is considered the primary field.

CREATE Sails model and Sails controller EXAMPLE FROM COMMAND LINE

csmsc -n NewModel -f one,two,three 

MODEL – Returns model definition for frontend Validation Error Checking

http://localhost:1337/newmodel/model/

DISPLAYORDER – Returns list of fields for ordered Dynamic view presentation

http://localhost:1337/newmodel/displayOrder/

GET – Returns ID AND PRIMARY fields for dropdowns / suggestive lists

http://localhost:1337/newmodel/get/

mongodb’s auto generated id will be used as the key primaryFild will be the value for that key

SEARCH – Returns results after searching primary or specified field for string

http://localhost:1337/newmodel/search/la?field=ObjectName

Search string follows the slash

Field string is optional and follows ?field=

Using a search string without a field name will search the primary field / node of the object.

Using a search string with a field name specified will search the specified field / node for the string provided.

LIMIT, SKIP

Limit

    &limit=

Skip

    &skip= 

SORT

Implementation is not complete, this is a placeholder.

https://www.npmjs.com/package/csmsc

Publishing a Node Module

I created and published a command line tool to generate my Models and Controllers for a SailsJS API.

The process is the same as writing anything for node but requires the following at the top of the main script.

#!/usr/bin/env node

And the following addition in the package.json file.

"preferGlobal": true,
"bin": {
"commandlineCommand": "./bin/mainScript.js"
}

Commit the project to github or another repository and publish to npmjs.org using the following commands.

npm set init.author.name "Your Name"
npm set init.author.email "email@email.com"
npm set init.author.url "http://www.projectWebsite.com/"
npm adduser

npm publish ./

Finished.