How to set up Sortable in AngularJS – without jQuery!

The de-facto standard of sortable libraries is jQuery UI Sortable, but it’s a bit silly to use jQuery and jQuery UI when you’re already using AngularJS. Why should you have to include two other big asset files for one, small functionality?

Here’s an alternative solution using this sortable library instead.

First off, here’s the demo on Plunker.

There are detailed comments throughout the code, but here’s the basic gist of it:

<!-- html / view -->
<div ng-app="myApp">
<div ng-controller="SortController" class="container">
    <ul id="my-sort" class="sortable" ng-model="people">
        <!-- note the "track by" section. this is important so that it doesn't rebuild the list -->
        <li ng-repeat="person in people track by person.id" data-index="{{$index}}">
            {{person.id}} - {{person.name}}
        </li>
    </ul>
</div>
</div>
// controllers.js
var myApp = angular.module('myApp',[]);
myApp.controller('SortController', ['$scope', '$http', function($scope, $http) {
    
  // initialize data. you would normally use a $http.get() here
  $scope.newSortIndexes = [];   
  $scope.people = [
    { id: 3, name: 'john' },
    { id: 4, name: 'mary' },
    { id: 1, name: 'james' },
    { id: 2, name: 'nancy' }
  ];
  
  // add sortable to <ul>
  var mySort = document.getElementById("my-sort");
  new Sortable(mySort, {
    onUpdate: function (evt){
      // get new sort order based on indexes
      var newSortIndexes = [];
      var liElements = mySort.getElementsByTagName("li");
      for (var i=0; i<liElements.length; i++) {
        newSortIndexes.push(liElements[i].getAttribute('data-index'));
      }
      
      // process change. you would normally use a $http.post() here
      $scope.newSortIndexes = newSortIndexes;
      $scope.people = getSorted($scope.people, newSortIndexes);
      $scope.$apply();
    }
  });   
}]);

// sort by indexes
// http://stackoverflow.com/q/4046967/3261678
function getSorted(arr, sortArr) {
  var result = [];
  for(var i=0; i<arr.length; i++) {
    result[i] = arr[sortArr[i]];
  }
  return result;
}

Dailylist.me launched!

I’m pleased to announce the official launch of my daily gratitude website!

It’s a simple site for users to express their gratitude and share it with the world. So simple, in fact, that registration isn’t even needed – just go to the site and start writing your list!

Backstory:

I started writing my daily gratitude list back in 2011. Every day, I would spend a few minutes writing in the 5-subject notebook sitting next to bed. This was nice, but at some point I realized that I wouldn’t be able to continue this if I went on vacation. I didn’t want to lug around a huge notebook with me; I wanted to be light and portable. So I started using a gmail draft to keep track of my list.

However, I knew that this wouldn’t work in the long term. It took too much work to write things down: go to gmail.com, click on drafts, click on the the email, scroll to the bottom, and then finally, start writing. Nope, I wanted something faster. I wanted to be able to go to the website and then start writing right away.

I looked online, but couldn’t find any sites like this. I found sites explaining why you should write a list. And I found sites explaining how you should write a list. And of course, I found sites where you could read someone else’s list. But I couldn’t find a site where you actually write your own list.

So I built it: Dailylist.me. It’s simple, it’s fast, and it works.

As expected, it doesn’t offer many fancy features in its infancy. But if you have any ideas or feedback, please let me know!

Fun links:

The science of gratitude
How to write a gratitude list

Technologies used:

Ubuntu 13.04 VPS
Nginx / PHP-FPM
PHP via Yii 2 Framework
MySQL
jQuery
Bootstrap

Learning Node.js Part 2 – “module.exports” and “exports”

In my previous post, I explained the basics of loading files/modules in Node.js. In this post, I’ll explain how to work with the return data. Specifically, I will describe what you get when you call something like var math = require('./math').

First, let’s talk about how to return data in a module. There are two ways to do it:

1) exports = data (where data is what you want to return)
2) module.exports = data

What’s the difference? Nothing actually. In fact, the exports variable is simply a reference, or alias, to module.exports. This means that you could use either one, though you’ll typically see module.exports. As the documentation suggests:

As a guideline, if the relationship between exports and module.exports seems like magic to you, ignore exports and only use module.exports.

You’ll also want to notice that you set the data instead of returning it. If you’ve used PHP before, then you may be used to including files and returning the data at the end by calling return $data. In Node.js, however, you just set the variable module.exports = data and it will return it for you.

The cool thing about this syntax is that you can return the data in numerous ways.

For example, if you just need some variables/functions:

// File: math.js
module.exports.double = function(n) { return n*2; };
//-----------------------------------
// File: test.js
math = require('./math');
console.log(math.double(5));

Or if you need a a full class instance:

// File: math.js
var Math = function() {
  this.double = function(n) { return n*2; };
};
module.exports = new Math;
//-----------------------------------
// File: test.js
var apple = require('./apple');
console.log(math.double(5));

Or if you’re really cool and just want to export a function directly:

// File: double.js
module.exports = function(n) {
  return n*2;
};
//-----------------------------------
// File: test.js
var double = require('./double');
console.log(double(5));

// you could also use this shorthand notation for functions:
console.log(require('./double')(5));

Of course, you can always return basic elements as well: a string, number, array, json object, etc. It really depends on what you need, though typically you’ll find that modules are best for classes/class instances. Anything simpler probably doesn’t belong in a module.

So there you have it. You now understand how loading modules work, and you know how to process and return data in those modules. It’s such a simple concept, but it was a little difficult for me to comprehend when I jumped directly into the code via tutorials.

Hope this helps! As always, feel free to ask questions if you have any.

Learning Node.js Part 1 – require() and modules

When I first started learning Node.js, I did what everyone else does: I searched google for “nodejs tutorial”, picked one of the top choices, and followed along. While it was great, I eventually discovered that these tutorials skipped over a very important aspect of Node.js. Specifically, they never really go into how require() and modules work.

As a PHP developer, I understand how require() works very well, at least in PHP. You include a file, it runs through some code in the same scope, and then possibly return some data.

Naturally, I assumed that it would be the same in Node.js… Not quite! In Node.js, require() does in fact work very similar, but it has the whole idea of modules tied into it. That is, each and every file you have is actually a module. I know that doesn’t really say anything (i.e., what’s a module?), so let’s just get to the important stuff:

Directly from the Node.js documentation:

Node has a simple module loading system. In Node, files and modules are in one-to-one correspondence.

Modules are cached after the first time they are loaded. This means (among other things) that every call to require(‘foo’) will get exactly the same object returned, if it would resolve to the same file.

What does this mean? It means that when you call require() on a file, it will return an instance of the module. To be more precise, it will return the same instance every time.

Going back to the previous question, what is a module? Well, when you think about it with the info I just provided, you could say that a module is a global variable. Or, you could say that a module is global object (because everything in javascript is an object). Thus, the module could be a string, number, class, function, or anything else.

Let’s go through an example. Take these three files:

// File: test.js
var apple1 = require('./apple'); 
console.log('apple1 is ' + apple1.getColor()); // outputs red

apple1.setColor('green');
console.log('apple1 is ' + apple1.getColor()); // outputs green

var apple2 = require('./apple');
console.log('apple2 is ' + apple2.getColor()); // outputs green

var test2 = require('./test2');
console.log('test2 = apple3 is' + test2.getColor()); // outputs green
//-----------------------------------
// File: apple.js
function Apple (type) {
  this.color = "red";
  this.getColor = function() {
    return this.color;
  };
  this.setColor = function(newColor) {
    this.color = newColor;
  };
}

module.exports = new Apple;
//-----------------------------------
// File: test2.js
var apple3 = require('./apple');

module.exports = apple3;

//-----------------------------------

Whew! Okay, the code is simple but may be a little hard to follow. Let me explain by explaining the three files:

test.js – the main script file that you can via node test.js.
apple.js – the apple module which returns an object Apple.
test2.js – the test2 module which is a wrapper and also returns an Apple object.

Now, let’s break the code down in steps:

1) Loads apple module into var apple1 and immediately outputs color “red” (defined directly in apple.js)
2) Changes color via apple1.setColor('green'); and outputs color “green”
3) Loads apple module again, this time into var apple2, and outputs .. “green”! This is the important part right here, because the apple module is returning the old, cached instance and not creating a new one!
4) Loads test2 module, which in turn loads the apple module yet again – this time into var apple3 and returns it. Outputs color “green” yet again

As you can see, this is vastly different from PHP. In PHP, you would get a new instance every time and thus get “red”, “green”, and “red” again.

So that’s how require() modules work in Node.js If you have any questions, let me know in the comments below.

One last note: I didn’t mention it explicitly, but it was described in the code. The line module.exports = {{data}} is how you return data from a module. Without it, the script would just run through the code procedurally and not return anything at all. Note, however, that even though it wouldn’t return anything, it could still affect other modules!

More info on this in my next post, so stay tuned!

The math behind exercising – Time spent vs Time gained

I realize that this is not exactly scientific, but I thought it would be a fun exercise to do the math and see some numbers. From my past experience with the Insanity workout, each workout generally takes 1 to 1.5 hours depending on the exercise. For the purposes of this post, let’s try to be conservative and round that to 1 hour and 2 hours.

Now, if you don’t know anything about the Insanity workout, it’s a 2-month program with a very simple schedule. There are 9 weeks total, each week consisting of 6 exercise days and 1 rest day per week. However, let’s maintain the conservative aspect so that we can account for things like prep, travel, and rest.

So let’s get to the numbers:

Time 1 hr avg 2 hrs avg
1 day 1 hr 2 hrs
1 week 7 hrs 14 hrs
1 month ~28 hrs ~56 hrs
1 year 364 hrs 728 hrs
In days 15.2 days 30.3 days

So what does this all mean? It means that exercising takes up A LOT OF TIME. If you’re consistently working out, you’re spending around 15 to 30 entire days exercising per year, or 4.1% to 8.2%.

Mother of god

Ok then, the next question is: What does that mean in the long term? To answer that, let’s start figuring out what long term means. According to Wikipedia, the average life expectancy of the US is approximately 80 years.

With that in mind, here are the long-term numbers:

Time Starting age 1 hr avg 2 hrs avg
1 year 79 15.2 days (.04 yrs) 30.3 days (.08 yrs)
10 years 70 152 days (.42 yrs) 304 days (.83 yrs)
20 years 60 304 days (.83 yrs) 608 days (1.67 yrs)
30 years 50 456 days (1.25 yrs) 912 days (2.50 yrs)
40 years 40 608 days (1.67 yrs) 1216 days (3.33 yrs)
50 years 30 760 days (2.08 yrs) 1520 days (4.16 yrs)
60 years 20 912 days (2.50 yrs) 1824 days (5.00 yrs)

More big numbers! How did I even read this?

Well, in my particular case, I am nearly 30 years old. That means that I’m looking at the second-to-last row, which is where the Starting Age column is 30. From here, I see that I would spend about 2.08 to 4.16 years exercising over the next 50 years before hitting the age expectancy of 80.

That means that if I live 4.16 years more, then I’m coming out ahead. In other words, if I live more than 84.16 years, then I’m coming out ahead and the exercise was definitely worth it. Mathematically, at least, because time spent > time gained.

Unfortunately, there’s really no way to tell how long I would live (both with and without exercise). Thus one could argue that all this math is moot. Nevertheless, I found it interesting to do the math and see some concrete numbers; it gives me a different way of looking at the benefits of exercise.

So how about you? After looking at the numbers, did you change the way you think about exercise?

Disclaimer: This post is all about the math behind exercising. It does not describe any of the numerous benefits of exercising, which are of course very valuable and will dramatically increase quality of life.

Taking a rest day and reflecting on self

Yesterday was quite an interesting day. After working so hard for the past two months, I decided to take a rest day and not do any work whatsoever. None. Whatsoever.

Sadly, it didn’t really work (I ended up doing some programming anyway), but I did notice something important about myself.

Specifically, it was interesting to see how much I’ve changed over the past few months. Back when I quit my job on 2/15/2013 (yes, I remember the exact day), I remember spending entire days doing nothing but playing games and watching TV. I would play League of Legends on one screen while watching video game streams on another. It was … depressing. I was addicted, and I knew it. What’s worse is that I didn’t know how to stop doing it.

But now, it seems like I spend most of time programming and working on personal development. It’s kind of scary, actually, how different I am now. Just looking at the numbers alone, I went from doing 0 hours of productive work per day to 4+ hours per day. That’s quite a big difference isn’t it?

I know. You may be thinking to yourself, “Whoa, that was a huge jump. Why did you suddenly skip from being a total slacker to a what productive person?” Don’t worry, I know that I didn’t transition well between the two different states. I did that on purpose because the truth is that I have no idea how I did it. Seriously. I’ve been trying to reflect back and figure it out, but I honestly don’t know.

I guess the easy answer is that I instilled a new habit of working instead of playing around. But the question is, how? What happened exactly? I can’t say for certain, but the two things that come to mind are:

1) Office change. Instead of using my desktop upstairs in my room, I started using my laptop downstairs in the dining room. I assume the difference is that my laptop is clearly less powerful and cant play games as well, but that doesn’t really make much sense. I still play games a little bit, just a lot less. Hell, I can still play League of Legends that my laptop if I wanted. Then again, I did hit Diamond league back in Septemember, so maybe my motivation to play the game completely dropped when I hit my goal.

2) Pomodoro technique. I started trying this out a bit, initially doing 4 pomodoris (or intervals) per day. I know, 2 hours doesn’t really seem like much. But considering the fact that I was doing no work at all before that, I’d say going from 0 to 2 hours was huge for me. After all, improving yourself is all about the small steps!

(If you don’t know what the Pomodoro technique is, it’s basically 25 minutes of work followed by 5 minutes break. Do this 4 times and then take a longer 15 minute break.)

Nowadays, I spend 4+ hours working per day. However, I don’t use the Pomodoro technique anymore. This is because programming is all about getting into the zone and letting the code flow out. So when I take frequent breaks via Pomodoro, it really throws me off my game and drastically reduces my output. I guess I would need to figure out how to plan my intervals better if I want to continue using it.

Anyway, my goal is to get to 10 hours per day. This is because in the startup/entrepreneurial world, hard work is the defacto standard for being successful. It’s also more work than the typical 9-5 job, but you know what? I enjoy it.

So cheers to progress. It’s going to be a great year!

Goal updates 2014

God I hate writing blog posts. But I set a goal for myself to write one a week this year, so I’m going to stick with it. For this post, I’ll be improving my goals by trying to make them more specific and trackable.

Health

  • I want to become more fit – Follow a schedule. Tentative plan is alternate between insanity and bodyweight fitness every 2 weeks
  • I want to eat healthier – Stay under 50g carbs at least 3 days every week

Friends and family

  • I want to spend more time with my friends and family

Significant Other

  • Nope, I hate people too much – Keep on hating

Personal Growth and Learning

  • I want to maintain my happiness and positivity – Practice meditation 5 minutes a day
  • I want to read more books – Read 15 minutes a day

Fun Leisure and Recreation

  • I want to go out and do more things – Go out once per month

Physical Enviroment

  • I want to groom myself better – Get two pairs of shoes and a suit

Career

  • I want to release some web apps – dailylist.me by Jan 15
  • I want to co-found a startup – Attend NYC startup weekend Feb 21 and Disrupt hackathon (may?)
  • I want to post on blog at least once a week – Yup

Money

  • I want to make money – Make $100 a month

Happy New Years!

It’s that time again, a brand new year!

I can’t believe it. It seems just like yesterday when I started my journey, but it’s already been almost a year. Time flies so fast doesn’t it?

This year, I need some direction – I’m going to actually work on writing down my goals and track my journey. Obviously, I’m not doing very well so far. I said that I wanted to write at least one post a week … two weeks ago. Not to mention that it’s already Jan 4th and I’m still writing this New Years post.

Damn. But oh well, time to move on! I learned of a very interesting concept recently called NonZero Days. This concept is very simple: work on your goals every. single. day. No matter what, period. Even if it’s for a minute, it’s better than not doing it at all.

Using this post as a guide, here’s an initial draft of my high level goals:

Health

  • I want to become more fit
  • I want to eat healthier

Friends and family

  • I want to spend more time with my friends and family

Significant Other

  • Nope, I hate people too much

Personal Growth and Learning

  • I want to maintain my happiness and positivity
  • I want to read more books

Fun Leisure and Recreation

  • I want to go out and do more things

Physical Enviroment

  • I want to groom myself better

Career

  • I want to release some web apps
  • I want to co-found a startup
  • I want to post on blog at least once a week

Money

  • I want to make money (lol)

Because I’ve been postponing this for so long, I’m just going to leave it as is for now. I think it’s better than I release something early *ahem* and quickly rather than not at all. Over the next few days, I’ll be coming up and updating this list to make it more concrete.

How to display, sort, and filter related model data in GridView

I thought I’d share how to process related model data in GridView. Starting off, we actually have two cases to consider. Let’s use the following three tables to demonstrate:

tbl_user:    id, role_id, email, username, etc
tbl_role:    id, name
tbl_profile: id, user_id, full_name

From these three tables, you can see that the user belongs to a role and has a profile.

Depending on the belongs to/has relationship, we’ll have to do slightly different things. For this example, we’ll work on getting tbl_role.name and the tbl_profile.full_name into the grid.

Let’s start with the easy part.

1) Display the data in the view file

<?php echo \yii\grid\GridView::widget([               
    'dataProvider' => $dataProvider,
    'filterModel' => $searchModel,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],
        // other columns
        [
            'attribute' => 'full_name',
            'label' => 'Full Name',
            'value' => function($model, $index, $dataColumn) {
                return $model->profile->full_name;
            }
        ],
        [
            'attribute' => 'role_id',
            'label' => 'Role',
            'filter' => Role::dropdown(),
            'value' => function($model, $index, $dataColumn) {
                // more optimized than $model->role->name;
                $roleDropdown = Role::dropdown();
                return $roleDropdown[$model->role_id];
            },
        ],
        // other columns
        ['class' => 'yii\grid\ActionColumn'],
    ],
]); ?>
public static function dropdown() {
    $models = static::find()->all();
    foreach ($models as $model) {
        $dropdown[$model->id] = $model->name;
    }
    return $dropdown;
}

Awesome! Believe it or not, but that’s all we need for the role info. Done and done.

Next, let’s work on the profile info. We need to update the search model ($searchModel from above).

2) Add the attribute into the model

a) public $full_name;
b) public function rules() { // add a rule so that it can validate }
c) public function attributeLabels() { // add a label to it }

3) Modify the search query to handle the new attribute

public function search($params) {

    // add the inner join
    $query = User::find();
    $query->innerJoin("tbl_profile", "tbl_user.id=tbl_profile.user_id");
    $query->with("profile"); // eager load to reduce number of queries
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    // add extra sort attributes
    $addSortAttributes = ["full_name"];
    foreach ($addSortAttributes as $addSortAttribute) {
        $dataProvider->sort->attributes[$addSortAttribute] = [
            'asc' => [$addSortAttribute => SORT_ASC],
            'desc' => [$addSortAttribute => SORT_DESC],
            'label' => $this->getAttributeLabel($addSortAttribute),
        ];
    }

    if (!($this->load($params) && $this->validate())) {
        return $dataProvider;
    }

    // add the full_name condition at the end
    $this->addCondition($query, 'id');
    ...
    $this->addCondition($query, 'full_name', true);
}
protected function addCondition($query, $attribute, $partialMatch = false) {
    $value = $this->$attribute;
    if (trim($value) === '') {
        return;
    }

    // add table name to id to prevent ambiguous error with profile.id, 
    // i.e., "tbl_user.id"
    if ($attribute == "id") {
        $attribute = "tbl_user.id";
    }

    if ($partialMatch) {
        $query->andWhere(['like', $attribute, $value]);
    } else {
        $query->andWhere([$attribute => $value]);
    }
}

Boom! We now have a full grid with sorting and filtering on our related models.

But wait, what if we have lots of roles? What do we do if the dropdown list is too massive and we need to be able to search for the name?

Ok, then we’ll need to convert it to a text search. That means that we are no longer working with a role_id, but instead with role_name. So let’s go ahead and change all instances of it in our code.

4) Update the data in the view file

[
    'attribute' => 'role_name',
    'label' => 'Role',
    // remove dropdown filter so it reverts to text
    //'filter' => Role::dropdown(),
    'value' => function($model, $index, $dataColumn) {
        // more optimized than $model->role->name;
        $roleDropdown = Role::dropdown();
        return $roleDropdown[$model->role_id];
    },
],

Then we need to go back to the search model.

5) Update the attribute in the model

a) public $role_name; // $role_id to $role_name
b) public function rules() { // 'role_id' to 'role_name', int to string }
c) public function attributeLabels() { // 'role_id' to 'role_name' }

6) Modify the search query to handle the new attribute

public function search($params) {

    // add BOTH inner joins
    $query = User::find();
    $query->innerJoin("tbl_profile", "tbl_user.id=tbl_profile.user_id");
    $query->innerJoin("tbl_role", "tbl_user.role_id=tbl_role.id");
    $query->with("profile"); // eager load to reduce number of queries
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    // update sort for role_id -> role_name
    $dataProvider->sort->attributes["role_name"]["asc"] = ["tbl_role.name" => SORT_ASC];
    $dataProvider->sort->attributes["role_name"]["desc"] = ["tbl_role.name" => SORT_DESC];
    $dataProvider->sort->attributes["role_name"]["label"] = "Role";

    // add extra sort attributes
    $addSortAttributes = ["full_name"];
    foreach ($addSortAttributes as $addSortAttribute) {
        $dataProvider->sort->attributes[$addSortAttribute] = [
            'asc' => [$addSortAttribute => SORT_ASC],
            'desc' => [$addSortAttribute => SORT_DESC],
            'label' => $this->getAttributeLabel($addSortAttribute),
        ];
    }

    if (!($this->load($params) && $this->validate())) {
        return $dataProvider;
    }

    // modify the addCondition, role_id -> role_name with partial match
    $this->addCondition($query, 'id');
    ...
    //$this->addCondition($query, 'role_id'); // replace with "role_name"
    $this->addCondition($query, 'role_name', true);
    ...
}

7) Modify addCondition function to convert role_name into its proper sql

protected function addCondition($query, $attribute, $partialMatch = false) {
    $value = $this->$attribute;
    if (trim($value) === '') {
        return;
    }

    // add table name to id to prevent ambiguous error with profile.id,
    // i.e., "tbl_user.id"
    if ($attribute == "id") {
        $attribute = "tbl_user.id";
    }
    // convert "role_name" to "tbl_role.name"
    elseif ($attribute == "role_name") {
        $attribute = "tbl_role.name";
    }
    
    if ($partialMatch) {
        $query->andWhere(['like', $attribute, $value]);
    } else {
        $query->andWhere([$attribute => $value]);
    }
}

And there we go – we now have a searchable text box for roles.

edited 2014/1/2 – added syntax highlighting

Blog relaunched!

It’s go time. Time to put this site to use and hold myself accountable.

New theme, new content, new direction.. I’m aiming for one blog post a week.