• April 15th, 2010

    Modulr: script concatination via CommonJS

    Modulr is a script concatenation tool I’ve been playing with which pre-processes client-side scripts into a single script suitable for deployment. This accomplishes two valuable goals:

    • lets you break your scripts out into discreet chunks for functionality
    • improves performance by minimizing the number of HTTP requests

    Example, assuming this hypothetical directory structure:

    - canvas
    --- tools.js
    - color.js
    - lang
    --- enumerable.js
    - main.js
    

    The content of main.js:

    // Declare your dependencies and assign them to variables.
    var color = require('color');
    var ctools = require('canvas/tools');
    var enumerable = require('lang/enumerable');
    
    // Use your imported scripts!
    var rgb = color.hex2rgb("#C00");
    var myCanvas = ctools.attach("some-canvas-id");
    
    enumerable.each(["stuff", "things", "other"], function(item, i) {
      // ...
    });
    

    As you can see, at the top of the file you simply require the scripts you’d like to use before using them. That’s it, done! Modulr takes care of fetching them and writing them into the file.

    Modulr avoids global-scope pollution

    Note that each require invocation assigns the result to a variable. The scripts which get concatenated via require are trapped within a closure, ensuring that your scripts do not pollute the global scope.

    Modulr makes your code more portable

    Another great thing about Modulr is that if follows the CommonJS API, allowing you to declare your script dependencies in plain old JavaScript. No config files or embedded tokens, just JavaScript. This has the added benefit of making your scripts more portable — as long as your environment supports the CommonJS API (node, narwhal, etc) your scripts will know how to resolve their dependencies.

    Creating a CommonJS compatible module

    In order for a script to work with the CommonJS API it must assign public properties to the exports object.

    The content of color.js illustrates this:

    
    // Define your functionality:
    function hex2rgb(hex) {
      /* ... */
    }
    
    function rgb2hex(rgb) {
      /* ... */
    }
    
    // Attach your API to the exports object:
    exports.hex2rgb = hex2rgb;
    exports.rgb2hex = rgb2hex;
    

    A working example

    To get in and get your hands dirty, check out my working example up on Github. It’s very tiny, and attempts to get the core ideas through as simply as possible.

    http://github.com/dandean/modulr-demo

    Suggestions and corrections are always welcome.

    Posted in Code/Projects, JavaScript, Ruby | 2 Comments »

  • Installing Node.js on a Dreamhost Shared Server

    April 9th, 2010

    First, get the latest Node.js source onto your server. I keep my git downloads at ~/downloads/git.

    If it doesn’t already exist, create your download directories and cd into it:

      $ mkdir ~/downloads/git
      $ cd ~/downloads/git
    

    Then, pull down the latest Node.js source code from GitHub:

      $ git clone git://github.com/ry/node.git
    

    Since we’re on a Dreamhost shared server, we have to specify a personal directory for the node binaries to install to. This is because Dreamhost won’t allow us (for good reason) to install whatever we want into location which is shared by every other user on your server.

    So, lets create our OWN /usr/local/bin directory:

      $ mkdir ~/usr/local/bin
    

    Now that we’ve got that, let’s get into the node Git repo and configure node to use our new custom bin directory:

      $ ./configure --prefix=~/usr/local
    

    If everything went well, make should handle the rest!

      $ make
      > ... a whole bunch of compilation output ...
      $ make install
      > ... more output ...
      > Done!
    

    Now, you need to do one more thing to make node visible to your own scripts: add the new node binaries to your PATH! To do this you need to add the following line to two files in your home directory: .bashrc and .bash_profile.

      export PATH=$PATH:/home/[YOUR USER NAME]/usr/local/bin
    

    You’re almost done! Just save both of those files, close your connection, reconnect, and check if you can run node! You should get something like this:

      $ node --version
      > v0.1.33-221-gff56d63
    

    Hot shit! Now go build some killer Node.js apps!

    Posted in Code/Projects, JavaScript | 7 Comments »

  • JavaScript Naming Conventions For People With Beards

    March 9th, 2010

    When developing in a team environment, coming to an agreed-upon set of naming conventions is incredibly important. The speed at which we as developers can come to comprehend the thought-processes and intentions of our peers greatly depends on our ability to look straight to their intentions, rather than having to first read the code line by line, mentally translating it into our own dialect, before truly understanding.

    In short, Aaron Cruz, here is a quick summary of the naming conventions which I adhere to:

    var MyClass = Class.create({
      initialize: function(arg1, arg2) {
        this.publicProperty = "'Public' property";
        this._privateProperty = "'Private' property";
        var localVariable = null;
      },
    
      publicMethod: function() {
        return "'Public' method";
      },
    
      isBooleanMethod: function() {
        return true;
      },
    
      _privateMethod: function() {
        return "'Private' method";
      },
    
      __eventHandlerMethodClick: function(e) {
        return "Click-event handler method";
      }
    });
    
    MyClass.classProperty = "Class-level property";
    
    MyClass.classMethod = function() {
      return "Class-level method";
    };
    
    MyClass.MY_CLASS_CONSTANT = "CONSTANT's should never change";
    
    MyClass.ClassEnumOrSubType = {
      value0: 0,
      value1: 1,
      value2: 2,
      value3: 4,
      value4: 8
    };
    

    While the above example uses the Prototype class structure, none of the principles themselves are Prototype-specific.

    Posted in Code/Projects, JavaScript | 3 Comments »

  • My Very Own GIT Manual

    August 11th, 2009

    GIT confuses the hell out of me. I’m used to Subversion and Vault, and the translation isn’t always clear. Thankfully, there’s GitHub which makes it super easy to jump into using GIT.

    Unfortunately I constantly forget how to do simple tasks, not to speak of complex ones. This post is going to serve as my very own GIT manual so I can make these translations easily and not have to remember the intricacies.

    Updating your local repositories with remote changes: git pull

    To get the latest changes from your remote repository merged into your local master, run git pull. This is pretty much the same as running git fetch then git merge origin/master. Think of this as the GIT version of svn:update or Vault’s “Get Latest”.

    git pull
    

    Pushing local changes to your remote repository

    git add 'your file name'  #do this for each file or folder with changes
    git commit -a -m 'Your commit message'
    git push origin master
    

    Rejected!

    If a push to your remote repository gets rejected, it’s probably because remote files have been changed since you last used git pull. Run git pull then git push origin/master again. With any luck you should be in business.

    Push master to origin/master

    git push origin master
    > To git@github.com:<username>/<reponame>.git
    >  ! [rejected]        master -> master (non-fast forward)
    > error: failed to push some refs to 'git@github.com:<username>/<reponame>.git'
    

    Damn! Shit’s broke! Pull again then re-try your push!

    git pull
    > Merge made by recursive.
    
    git push origin master
    > Counting objects: 10, done.
    > Compressing objects: 100% (5/5), done.
    > Writing objects: 100% (6/6), 814 bytes, done.
    > Total 6 (delta 1), reused 0 (delta 0)
    > To git@github.com:<username>/<reponame>.git
    >    65a1527..79239e9  master -> master
    

    It worked!

    Updating your fork of another user’s repository

    get fetch origin
    git fetch upstream
    git merge upstream/master
    git push origin master
    

    There’s probably an easier way to do that, but I haven’t figured out as of this writing.

    Counting the number of commits (and commiters)

    git shortlog -s -n
    

    This just gives you a nice clean list. The best I can figure out is to clean it up with some regex and count it.

    • Replace all letters and spaces with nothing: [a-z ]+
    • Replace new lines with commas
    • Wrap the result in array delimiting square brackets
    • Count it up with JavaScript
    var commits = [744,536,68รถ,39,17...1,1,1,1,1,1,1,1,1,1,1];
    var count = 0;
    
    commits.forEach(function(x) {
      count += x;
    });
    console.log(count);
    

    If somebody has a better way, please tell me — this approach is overly complicated.

    Posted in Code/Projects, git | 2 Comments »

  • Hatin’ on textContent and innerText

    June 1st, 2009

    It’s surprisingly annoying to get just the text content of an html element in a cross-browser friendly way. I wrote Element#getTextContent() to take care of this simple operation for me.

    The Prototype Version:

    Element.addMethods({
      /**
       *  Element#getTextContent(@element) -> String
       *  Cross-browser means of getting Element#textContent or Element#innerText
       **/
      getTextContent: function(element) {
        if (!Object.isUndefined(element.textContent)) {
          return element.textContent;
        }
        return element.innerText;
      }
    });
    

    The Procedural Version

    /**
     * Gets the text content of the specified element.
     * @param element {HTMLElement} The html element
     * @return {String} The string content of the specified element.
     */
    function getTextContent(element) {
      if (typeof element.textContent != "undefined") {
        return element.textContent;
      }
      return element.innerText;
    }
    

    Posted in Code/Projects, JavaScript | 8 Comments »

Next Page »

Un-Dumbify