JSass: A Sass Compiler Written In JavaScript

As part of a hackathon at Hack Reactor, I build my very own Sass compiler. For those of you unfamiliar with it, Sass is a CSS pre-processor and probably the best one out there. There's a lot of Sass compilers out there, but mine is the only one written purely in (and not ported to) JavaScript. Features Let's be honest here. This is not fully-fledged Sass compiler, but it has the basic features in Sass. Nesting Nesting is probably the most useful feature in Sass. It lets you organize your code and prevent writing to many classes. It also makes maintenance easier. .main { background: green; .side { background: blue; color: #777; } } Compiles to: .main { background: green; } .main .side { background: blue; color: #777; } Comments Sass allows inline comments. These are not included in your compiled CSS. // This is some comment on the .main class .main { display: none; } Compiles to: .main { display: none; } Variables Variables for your CSS. How could this not be useful? $color: purple; .main { background: $color; .side { background: red; color: $color; } } compiles to: .main { background: purple; } .main .side { background: red; color: purple; } Online Compiler As part of this project, I also made an online UI for the compiler with a couple of examples. Check It Out Testing Obviously, this comes with a testing suite. The testing suite tests the result of jSass against lib-sass, one of the most common Sass compilers out there. Some of the test are disabled, but that's because the output was off by a space or a new line and it wasn't worth it to invest too much time on making it pass.

NQueens Distributed Web Worker

I made an asynchronous N Queens solver with web workers. This particular implementation uses 4 web workers to distribute the work of getting a solution for n. To be honest, I became a little obsessed with turning my solution to N Queens (which wasn't really very challenging) and turning that into something that would work asynchronously. Even that wasn't really hard, but I got stuck at some point implementing a solution that was too complicated for my problem. I spent a lot of time trying to get my hear around how to separate the different parts in a way that would work asynchronously but was still simple to grasp and understand. Anyways, this was still one of my favorite sprints and on of my favorite projects so far.


A simple, intuitive blackjack client. You start with $1000 and increase and decrease your bet as you go. I spent a lot of time on the UI and I'm pretty happy with the way it looks. Most of the time was spent creating the logic for the Backbone.js models, views and collections.

Just Type: My First Node.js Experiement

Wanting to experiment with node.js, I made a simple pseudo-chat application.

Thanks For

"A community challenge to express thanks to someone else with a neon sticker." A nice little Django/Backbone.js site made for a friend. This project was a good opportunity to sharpen my Django skills and tackle Django deployment.  

Testing the Youtube API with OO Javascript

Yesterday, I wrote a simple script to test out the youtube player api. The demo is meant to test how responsive the API is with multiple videos playing the same time. Performance Performance is pretty good, but not perfect (playing about 11 videos). They take a bit to initiate and then subsequently play pretty well. Volume control is also very responsive. Currently, there is a hover binding that mutes all videos except the one being hovered and that works pretty well. Re-sizing videos also works pretty well. Videos are responsive an respond quickly. All that being said, seeking and skipping to other parts of the video is quite slow and not as responsive as everything else. I wasn't too surprised this would be the slowest part of the demo. The Code This particular demo, consists of three components: the video class, a video array that holds these objects, and some jQuery bindings to do stuff with the video. The video class is mainly an abstraction of the Youtube player with a couple of other things, but not really that interesting to look at. What is a bit more interesting is how Youtube handles player and videos, since these things are not necessarily one and the same. The loading of a video happens in the following order: 1. The player is initiated with SWF object Video.prototype.init = function(){ // The video to load. $("<div id='c" + this.id + "'></div>").appendTo("#container"); this.elementId = "video" + this.id; // Lets Flash from another domain call JavaScript var params = { allowScriptAccess: "always" }; // The element id of the Flash embed var atts = { id: this.elementId, class: "video" }; // All of the magic handled by SWFObject (http://code.google.com/p/swfobject/) swfobject.embedSWF("http://www.youtube.com/apiplayer?" + "version=3&enablejsapi=1&playerapiid=player" + this.index, "c" + this.id, this.w, this.h, "9", null, null, params, atts); } 2. The Api fires an event that the player is ready. function onYouTubePlayerReady(playerId) { var id = parseInt(playerId.replace("player","")) videos[id].createPlayer(); } 3.  A video is cued into the player by its Youtube id. Video.prototype.createPlayer = function(){ this.player = document.getElementById(this.elementId); this.player.cueVideoById(this.id); this.player.setVolume(); this.playing = false; }

Boredom - Interactive Experiments

A project originally created by Hong Zhang, this single page website attempts to incorporate users into the how the website is displayed and laid out. Users can move and resize any image on the page, and the page automatically and permanently saves those changes into the site... until another user comes along.

Spain's Economic Crisis: Visualization

These are some sketches I've been working on about Spain. I'm interested in Spain's recent economic crisis.

Watchout! A Game

A game called "Watchout." After completing the game, I played around with adding sounds with timbre.js and changing the way nodes behave through using D3's awesome force capabilities.

Presidential Dance Party

Created a 'dance party' in which I used prototypal inheritance and some GSAP magic to bring the presidents to life!

1 Dollar Payments

Simple, straightforward web app to send money to anyone with a bank account. The site uses the Stripe API to send money form one user with an email account to another. This little project was made in the 2014 RVA Hackathon. Built with Django and Stripe.

Three.Js Experiments

Recently, I've been experimenting with three.js. It's an amazing library and the fact that you can do all these amazing things in the browser is simply unbelievable. This set of experiments (5 for now) are meant to explore animation and movement of basic geometry in 3d space. I'm particularly interested in having many objects in a scene at the same time. As you can see from some of the examples, this is not trivial, since multiple nodes can bring down your FPS pretty easily.

Pugalicious - A Backbone App

As a way to teach myself Backbone.js, I made a Backbone app built on top of the Rotten Tomatoes API. Basically, you can search for movies instantly and read some basic info on each one. Initially, I thought I was going to make this post interesting. But it's late and I'm lazy, so I'm just going to copy paste some JS code in here. Setting up the App This was actually the most frustrating experience of the whole thing. I used require.js for this and had a touch time because I forgot to setup my dependencies correctly (More on that in a bit). How my setup looks: In the index.html, I have this: <script type="text/javascript" src="js/lib/require.js" data-main="js/app"></script> This tiny little line of code starts up my whole app. It includes require.js and then tells require js what .js file to look for in order to start the app. So in this case, my app will look for js/app.js for further instrucitons. In app.js we find this: // Configure loading modules from the lib directory, // except 'app' ones, requirejs.config({ "baseUrl": "js/lib", 'urlArgs': "bust=" + (new Date()).getTime(), "paths": { "app": "../app" }, shim: { "backbone": { //These script dependencies should be loaded before loading backbone.js deps: ['underscore', 'jquery'], //Once loaded, use the global 'Backbone' as the module value. exports: 'Backbone' }, "underscore": { exports: '_' }, } }); So, here we first include a 'baseUrl' which will contain all our libraries. In this case, that's 'js/lib/' which contains backbone.js, jquery.js, less.js (not used through require.js), require.js, and underscore.js. We tell requires.js to expire the application immediately for development purposes. Then specify our app directory js/app/. Finally (and this is where I got stuck for a bit), we establish dependencies and namespaces. Backbone requires jquery and underscore. Similarly, underscore requires jquery. So we tell require to load them accordingly. We also declare our namespaces ( Backbone for backbone and _ for underscore). // Load the main app module to start the app requirejs(["app/main"]); We're finished with this file. Require.js has loaded all our dependencies and has started to load our app. Where exactly is our app again? That would be in js/app/main.js! Let's take a look. Now, really this is where the magic happens and all we have to do in order to get started is this:   // Setup some requirements. Jquery and Underscore are requiremetns for backbone require([ 'jquery', 'underscore', 'backbone', ], function($, _, Backbone){ // Some Asome Javascript that will change the world }); Now we have all the components we need to start writing some functionality. In this case, we'll start at the end ouf our code with the router. The Router function($, _, Backbone){ // Some Asome Javascript that will change the world /* YOUR MODELS */ // ...200 lines of code laters /* YOUR VIEWS */ // ...300 lines of code later /* YOUR ROUTER */ var Router = Backbone.Router.extend({ routes : { "movies/:id": "getMovie", "search/:query": "search", "not-found": "notFound", // For when we can't find something '*path': 'defaultRoute', // Our last resort, go home }, defaultRoute : function() { }, notFound : function(){ }, search : function(this_query_term){ }, getMovie : function(id){ } } }); }); This is our router. It basically sniffs out our changes, matches different patterns for it, and redirects to a url accordingly. It's pretty cool. In this case, when we go to a home page, it will fire up 'defaultRoute', because there isn't anything in the url. If it find movies/23423 it will pass on that number to the getMovie function, in order for it to use it. Search The user first encounters the site through the search box. In Backbone this is described as follows: // A separate view for search SearchView = Backbone.View.extend({ // Tied to an element in the DOM el: '#search_container', // Tied to a template template: _.template($("#search_template").html()), initialize: function(){ // Render on init this.render(); }, render: function(){ // We don't pass any variables here this.$el.html(this.template()); return this; }, events : { // We bind certain events to a custom function, which looks for movies in the API "change" : "query_movies", 'click .submit' : "query_movies", }, query_movies : function(){ // Using jquery, find the query term var this_query_term = $(this.el).find('.search-box').val(); // Push the query term to the router router.navigate('search/' + encodeURIComponent(this_query_term) , true); }}); // Down Below, we initiate this view  // By default, we init our search and our router var serch_view = new SearchView(); var router = new Router(); // URLs don't work without this Backbone.history.start(); We have initiated this view on init, along with our router and our Backbone.history (which takes care of push states). This will render out our view and bind any changes in search to the router. The event would go something like this: 1. Page is loaded 2. Search view is loaded, html is added, and element is binded 3. A search is entered 4. The query_movies function (inside the search view) is triggered 5. the query_movies function calls the router 6. The router redirects the app to search funciton, feeding it the query variable 7. A query to the API is made and returned 8. A collection is made 9. That collection is rendered, appended to the html and binded On a later episode of this great blog, I will talk a bit more about collections, models and a bit more about views. In the mean time, you can checkout this app and checkout the repo on github.com.    

Me, Me, Me! - Interactive Experiment

Uses Processing.js. It's simple. It's interactive. It uses a simple Soft Float class, originally written by Andrés Colubri. This is really the highlight of this little script, since it's what powers the animations. While I've done some classes for animations, this once is much better than anything I've seen before! function SoftFloat(v) { this.value = v; this.ATTRACTION = 0.0001; this.DAMPING = 0.05; this.velocity = 0; this.acceleration = 0; this.enabled = true; this.targeting = false; this.source = 0; this.target = 0; this.enableAnimation = true; } SoftFloat.prototype.enable = function() { this.enabled = true; } SoftFloat.prototype.disable = function() { this.enabled = false; } SoftFloat.prototype.update = function() { if (!this.enabled) return false; if (this.targeting) { if(!this.enableAnimation){ this.value = this.target; this.targeting = false; } else { this.acceleration += (this.ATTRACTION * (this.target - this.value)); this.acceleration += (this.target - this.value); this.velocity = (this.velocity + this.acceleration) * this.DAMPING; this.value += this.velocity; //this.value += (this.target - this.value)/30; this.acceleration = 0; if (p5.abs(this.velocity) > 0.0001) { return true; } this.value = this.target; this.targeting = false; } } return false; } SoftFloat.prototype.setTarget = function(t) { this.targeting = true; this.target = t; this.source = this.value; } SoftFloat.prototype.getTarget = function() { return this.targeting ? this.target : this.value; }

Simple Google Maps API Example

This is a simple Google Maps API example I coded up in about an hour. Maybe someone else can use this at some point?
Do NOT follow this link or you will be banned from the site!