Webgrep and monthly update

28 August 2014 |

So I haven’t been able to work on a solid blog post on any specific technology. I’d like my articles to be a lot like the articles you see on nettuts or sitepoint, just haven’t found tech I’m super passionate about like that this month.

Webgrep screenshot

The other day I was doing market research and was searching for affiliate marketing programs in different industries. After opening a bunch of website tabs and ctrl-F-ing on every page for ‘affiilate’ I look at rick and ask him, “why isn’t there a chrome extension or something that’ll do this for me?”. I whipped up wordgrep.org the next day. Some friendly people on ##javascript (freenode irc channel) told me about Yahoo query language which acts as a free proxy for us. Next things I’d like to add are

  • ability to point the tool at a url
  • ability to drop in a word/excel doc
  • infer if the found word is inside a link and return that instead
  • filter by result found/not found/yql error
  • provide counter and spinner so user knows if the program is still executing

If I see there is demand for this tool I’d be willing to offer a pro version where you get access to a proxy I make and crawls sites Yahoo wont. If you have any other feature requests lmk.

Teaching at Hacker Coding Academy

14 July 2014 |

This post is secretly only for testing embedding jsfiddles in a webpage. But I might as well give the blog an update. I’m currently teaching part-time at Hacker Coding Academy a 12 week full stack Javascript Vocational school. I’m very excited to work on my communication skills and really learn what I know by passing it on.

Below is an assignment I’m playing around with. Would it be cool to design your own business card with html/css? Could be fun. <iframe width="100%" height="300" src="http://jsfiddle.net/morenoh149/42HgD/embedded/#Result" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

Adding unix aliases to OSX

10 June 2014 |

A part of mastering the commandline is extending it with your own custom commands. On any nix environment you should have access to config files, e.g., ~/.bashrc or ~/.profile. I add my aliases to my ~/.zshrc file. ZSH is pretty dope btw, definitely check it out.

Heres and excerpt of my .zshrc.

alias mkblog="jekyll build; jekyll serve -w"
alias gph="git push heroku master"
alias rr="rake routes"
alias corrun="cordova build android; cordova run android; adb logcat | grep CONSOLE"
function pyserver() {
  python -m SimpleHTTPServer "${1:-8765}";
}
alias tunnel="ssh harry@< took out my ip :p > -D 8080"

Vim-like mission control shortcut

08 May 2014 |

So I use iterm2 on my mac. And there’s a shortcut option-spacebar which switches back and forth between a desktop and iterm2 in fullscreen. I do most of my work that way, switching between a browser and code. Recently however I’ve been following some screencasts on youtube which required me to switch between broswer, fullscreen iterm2 and fullscreen youtube player. This was the perfect time to change the mission control shortcut on my mac.

As you can see I mapped moving one screen left or right to ⌥h and ⌥l so I can switch using vim-like keys.

AngularJS - UI-Router, Params and Ionic

14 April 2014 |

I’ve been learning ui-router and I’d like to share some things I’ve learned that took me a while to get. With bits of Ionic Framework.

Let’s say you have an abstract state with a child and another state and you want to trigger a transition from the controller to the other state. The following is a concrete example. I was building an ionic app that would grab a photo from the phones photolibrary and transition to another view, passing the fetched uri to the new view.

app.js

'use strict';

var app = angular.module('Txtbinge', ['ionic', 'firebase']);

app.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  .state('app', {
    url: '/app',
    abstract: true,
    controller: 'AppController',
    templateUrl: 'templates/applayout.html'
  })

  .state('app.home', {
    url: '/home',
    views: {
      'centerContent' :{
        templateUrl: 'templates/home.html'
      }
    }
  })

  .state('crop-image', {
    url: '/crop-image/:imageURI',
    templateUrl: 'templates/crop-image.html',
    controller: 'CropController'
  });

  $urlRouterProvider.otherwise('/app/home');
});

Here we set up all the states in our app. Note that the ‘crop-image’ state is going to require an ‘:imageURI’ param in it’s url.

'use strict';

app.controller('AppController', function($scope, $state, Camera) {

  $scope.newPost = function() {
    if( navigator.camera ) {
      Camera.getPicture().then(function(imageURI) {
        $scope.imagesrc = encodeURIComponent(imageURI);
        $state.go('crop-image', {imageURI:$scope.imagesrc});
      }, function(err) {
        console.log('error inside getPicture(): ' + err);
      });
    } else {
      console.log('no camera');
      var str = encodeURIComponent('app/images/ionic.png');
      console.log('encoded uri is: ' + str);
      $state.go('crop-image', {imageURI:str});
    }
  };
});

app.controller('CropController', function($scope, $stateParams) {
  $scope.imageURI = $stateParams.imageURI;
  console.log('inside cropcontroller ' + $scope.imageURI);
});

The AppController is the main controller for this app. Accessible from any state inheriting from the app abstract state declared in app.js. Notice how we are fetching a uri from the photolibrary and passing it as a parameter for the CropController. We must first call encodeURIComponent() on this uri to pass the value around. Otherwise ui-router get’s confused - loading CropController but failing to change the url or load the template.

camera-service.js

'use strict';

app.factory('Camera', ['$q', function($q) {
  function cameraSuccess(imageURI, q) {
    // hack until cordova 3.5.0 is released
    if (imageURI.substring(0,21) === 'content://com.android') {
      var photoSplit=imageURI.split('%3A');
      imageURI='content://media/external/images/media/'+photoSplit[1];
    }
    q.resolve(imageURI);
  }
  return {
    getPicture: function() {
      var q = $q.defer();
      navigator.camera.getPicture(function(imageURI) { cameraSuccess(imageURI, q); },
                                  function(msg) {
                                    q.reject(msg);
                                  }, {
        sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY
      });
      return q.promise;
    }
  };
}]);

In camera-service.js we’ve wrapped all calls to the cordova-plugin-camera in an agularjs service. This is a good solution until the Ionic Framework provides guidance on interfacing with cordova plugins. See How to use Cordova plugins ….

tbc

When brew punks out

26 March 2014 |

Today I was trying to upgrade all my brew kegs with brew upgrade. But it trips up on libiconv. You might try like I did and call brew with sudo but you get this message

Error: Cowardly refusing to `sudo brew upgrade`
You can use brew with sudo, but only if the brew executable is owned by root.
However, this is both not recommended and completely unsupported so do so at
your own risk.

Interesting, so now what? We could login as root but that might complicate things. What I did was give myself (a non-root user) access to the file. Like so

sudo su
<password>
chown <username> /usr/local/Cellar/libiconv/
exit

Now that directory belongs to the current user and brew has no issues modifying that directory!

http://stackoverflow.com/questions/14527521/brew-doctor-says-warning-usr-local-include-isnt-writable sudo chown -R $USER /usr/local/include

Using github pages environment variables

05 March 2014 |

This method is now outdated. Github Pages now exposes the site.github namespace

I use jekyll with github pages to build this blog. I also use disqus for comments. You just have to add a code snippet into the page. Problem is when developing with jekyll I usually like to test how things look locally and then push the site to github pages. Which means whenever I look at a blog post I haven’t pushed, Disqus will create a thread like localhost:4000/something.html in addition to the intended one morenoh149.github.io/something.html. I asked around and found a jekyll plugin for environment variables. But github pages disables plugins. So I dug through the site variable on both production and github pages and found github pages sets GH_ENV which I haven’t seen documented anywhere. Now I simply do

{% if site.GH_ENV == 'gh_pages' %}
  < disqus snippet >
{% endif %}

to get the disqus thread generated only if the post is being viewed on github pages.

Changing the owner of a heroku app with S3 assets

24 February 2014 |

I recently had to migrate a Heroku app that was under my personal accounts, Heroku and s3, to another user. But this app also had assets under Amazon Web Services Simple Storage Service which made the process more complicated. You can use something like bucket explorer to manage S3 with a gui. I’ll show you how to do it with aws-cli. I’m assuming you installed it and you’re familiar with the commandline in general.

Since we are using more than one aws account we should use a config file to store both sets of credentials. See AWS configuring environment. Place your personal credentials under default and make another set for the recipient.

#~/.aws/config
  [default]
  aws_access_key_id=blah
  aws_secret_access_key=blah
  region=blah

  [profile client001]
  aws_access_key_id=new-blah
  aws_secret_access_key=new-blah
  region=new-blah

Remember to clear your env variables if you were using them before. aws-cli defaults to using the env variables if present, even if you pass the --profile argument.

Now you should be able to do aws s3 ls and get your file listing. And aws s3 ls --profile client001 and get the client’s files. If you are dealing with a small amount of data < 1TB we can simply copy the files to our local machine and then copy them back to the new bucket. For larger amounts I have no clue :(

aws s3 cp s3://mybucket/ . --recursive

Note aws-cli cp command doesn’t support matching by * so you have to use the --recursive flag. You can test what will happen if you run the command, with the --dryrun flag.

You can copy the files to the new bucket like so.

aws s3 cp . s3://new-bucket --profile client001 --recursive

Note you may have to specifiy --region some-region for some reason specifying the region in my config file didn’t work.

You have to set the heroku env variables to the new aws credentials using the heroku toolbelt

heroku config:set AWS_ACCESS_KEY_ID=new_blah
heroku config:set AWS_SECRET_ACCESS_KEY=new_blah
heroku config:set AWS_S3_BUCKET=new_blah

and just transfer it using heroku’s system.

Bash script for creating a bootable usb stick on OS X

26 January 2014 |

Many times you have to create a bootable usb stick on a mac. I always follow the instructions at How to create a bootable USB stick on OS X. I created a quick bash script that makes this process faster

 1 #!/bin/bash
 2 HELP_STR="please provide location of .iso"
 3 if [ "$#" -lt 1 ]; then
 4   echo $HELP_STR
 5 else
 6   echo "`diskutil list`"
 7   echo "==============="
 8   echo "enter disk to eject"
 9   echo -e ">> \c"
10   read word
11   echo "ejecting: $word"
12   echo "`diskutil unmountDisk $word`"
13   echo "copying $1 to $word note this may take a while and there won't be a progress bar"
14   echo "`sudo dd if=$1 of=$word bs=1m`"
15 fi

Gist on Github

Getting started with emberjs and phonegap (work in progress)

30 December 2013 |

Source code for this project can be found here.

The ember app kit is currently the defacto starting point for any ember project.

You’re going to have to learn a little grunt and bower. The getting started tutorial on the ember site is a good starting point. To add bootstrap, moment.js and showdown.js add them to the end of the dependencies section. Note, bower in the ember-app-kit installs to the vendor/ directory as opposed to the bower_components which is usually the default.

 1 {
 2   "name": "ember-app-kit",
 3   "dependencies": {
 4     "handlebars": "~1.1.2",
 5     "jquery": "~1.9.1",
 6     "qunit": "~1.12.0",
 7     "ember": "~1.3.0-beta.4",
 8     "ember-data": "~1.0.0-beta.4",
 9     "ember-resolver": "git://github.com/stefanpenner/ember-jj-abrams-resolver.git#master",
10     "ic-ajax": "~0.2",
11     "ember-testing-httpRespond": "~0.1.1",
12     "bootstrap": "~3",
13     "momentjs": "",
14     "showdown": ""
15   },
16   "resolutions": {
17     "ember": "~1.3.0-beta.4"
18   }
19 }

putting an “” empty string seems to work fine. Then reference these assets from index.html as normal.

The next deviation deals with how handlebars is setup. In the tutorial you see dale declaring <script type="text/x-handlebars"> and writing his handlebars stuff right there. With EAK the templating is put into the templates/ directory. With application.hbs wrapping the other templates.

app/templates/application.hbs

 1 <div class="navbar navbar-default" role="navigation">
 2   <div class="navbar-header">
 3     <a class="navbar-brand" href="#">Bloggr</a>
 4   </div>
 5   <div class="collapse navbar-collapse">
 6     <ul class="nav navbar-nav">
 7       <li><a href="#">Posts</a></li>
 8       <li><a>About</a></li>
 9     </ul>
10   </div>
11 </div>
12 
13 {{outlet}}

We then add the about resource to router.js

In the tutorial tom simply adds a posts var for our sample data fixture. In EAK there’s a api-stub mechanism. Let’s use that instead.

You’ll need to read (and probably re-read) Using Modules & the Resolver

How to disable subtitles in VLC by default

18 September 2013 |

VLC is my media player of choice. One of my only complaints is that it loads subtitles by default. It’d be really nice if you could have them off by default, with the option of loading them if you need them.

This is how you do that. Go to Preferences > Show All (in the lower left corner) > Video > Subtitles/OCD Here you’ll see some checkboxes. Uncheck Autodetect subtitle file.

And that’s that. You can still load subtitles manually by going to Video > subtitles track > Open file… Navigate to your subtitles file and it’ll be loaded.