SnackJS: A Tiny-But-Tasty JavaScript Framework

By  on  
Snack JS

moo4q creator Ryan Florence and I generally agree on most JavaScript-related topics, one of which is that most JavaScript frameworks, jQuery, MooTools, and Dojo included, are much more feature-rich (and thus larger) than most websites need.  You wouldn't build a corporate or enterprise-level website without an expansive JavaScript framework, but many smaller scale websites simply don't need the heft.  Enter Florence's new JavaScript framework, SnackJS -- a JavaScript framework that provides only the functionality that most smaller websites need -- and in only 3KB! (minified and gzipped)

What does "only the functionality that most smaller websites need" mean?  By that I mean the ability to:

  • more easily work with arrays
  • efficiently retrieve and modify element CSS classes and attributes, etc.
  • easily add, remove, and fire event handlers
  • execute and handle the result of basic AJAX / JSON / JSONP request

SnackJS provides all of the above, with a few extras:

  • a small pub/sub system for easier app communication
  • an extend method for shallow merging of object properties
  • everyone's favorite: a "ready" event
  • a selector engine wrapper for easy implementation of any selector engine (Slick, Sizzle, etc.)
  • a punch method which acts very much like dojo.connect, in that a function can be assigned to execute any time another function is executed
  • an element store solution

Let's take a look SnackJS code snippets so you can get a feel for it usage!

snack.extend

This method simply merges properties from any number of objects into the first argument:

// Mix objects
var endObject = {
	color: "red"
};
snack.extend(
	endObject, // The starting object
	{ color: "green", text: "Name" }, // A second object
	{ color: "blue" } // And another
);

// endObject becomes: { color: "blue", "text: "Name" }

snack.punch

The ability to "connect" to functions is extremely useful within the Dojo Toolkit, so I couldn't have been more happy to see this in SnackJS:

// Create an object with a function
var myObjectWithFns = {
	color: "red",
	onColorChange: function(color) {
		// Reset the color
		this.color = color;
	}
};

// Punch time:  whenever myObjectWithFns is called, call another function which simple logs the value
var reactor = function(color) {
	console.log("The color was just changed to: ",color);
};
snack.punch(myObjectWithFns,"onColorChange",reactor,true);
myObjectWithFns.onColorChange("red");

Whenever the myObjectWithFn.onColorChange is executed, the reactor function immediately runs.

snack.wrap

snack.wrap acts very similar to the dojo.query method or jQuery("selector") usage in that it wraps nodes so extra functionality can be added to them. Nodes themselves are not modified as they are within MooTools.

// Get all DIV elements.
var divs = snack.wrap("div");
// Add a CSS class to the divs
divs.addClass("found");
// Add a click event that...
divs.attach("click",function() {
	// Removes the class we added
	snack.wrap(this).removeClass("found");
});

snack.listener

The snack.listener method is your standard cross-browser node event syntax.

// Add an event listener to a given node
var listener = snack.listener({
	node: document.getElementById("content"),
	event: "click"
},function() {
	console.warn("You clicked on the node!");
});

// Detach the listener at any time
listener.detach();

// ...and add it back again
listener.attach();

Especially nice are the detach and attach methods, allowing you to effectively disable and enable event listeners.

snack.request

Runs a standard AJAX request with the standard options:

// Create an AJAX request
var req = snack.request({
	url: "get-user-bio.php",
	data: {
		userId: 1234
	},
	method: "get",
	now: false // Don't send immediately
},function(error,response){ // The success event
	// If it was successful...
	if(!error) {
		document.getElementById("content").innerHTML = response;
	}
});

// Now send it!
req.send();

snack.publisher: PubSub Implementation

SnackJS implements the ever-useful pub/sub system by creating a publisher, and then publishing and subscribing to it:

// Set up a pub/sub event
var pubsub = snack.publisher();

// Create a subscription to an event
pubsub.subscribe("inputchange",function(val) {
	console.warn("The value was changed to: ",val);
});

// Attach an onKeyUp event to the input node
// When keyup'd, the node's value has changed, and we should notify all subscribers
snack.wrap("#email").attach("keyup",function() {
	pubsub.publish("inputchange",[this.value]);
});

The power of pub/sub is that you don't need references to events or anything else -- you simply need the name of the wire. Whenever a message is published to that wire, you'll know about it!

These are just a few of the functionalities available within SnackJS.  There are many more methods available, so I encourage you to check out the SnackJS documentation. I'll bet that SnackJS has all the functionality you need for most websites!

Moving Forward

Snack JS was just recently released so there aren't many custom modules/plugins available.  There are a few items I'd like added to see added to SnackJS:

  • style setter and getter -- I know that the style property of nodes is where you set individual styles, but opacity takes more work since it's not standard, and an object-to-styles setter would be awesome
  • deferreds -- They're a godsend within Dojo, and could prove to be with SnackJS as well

The SnackJS repository lives at GitHub and the documentation and demos can be found at snackjs.com.  Congratulations to Ryan Florence for this awesome micro framework!  I look forward to contributing in the future!

In the coming days, I'll be showing you how you can create your own SnackJS plugin for creating nodes, placing them within the page, and getting and setting their attributes! Stay tuned!

Recent Features

Incredible Demos

  • By
    Scrolling “Agree to Terms” Component with MooTools ScrollSpy

    Remember the good old days of Windows applications forcing you to scroll down to the bottom of the "terms and conditions" pane, theoretically in an effort ensure that you actually read them? You're saying "No David, don't do it." Too late -- I've done...

  • By
    FileReader API

    As broadband speed continues to get faster, the web continues to be more media-centric.  Sometimes that can be good (Netflix, other streaming services), sometimes that can be bad (wanting to read a news article but it has an accompanying useless video with it).  And every social service does...

Discussion

  1. This will be super handy. There are a lot of sites I modify that just use those core functions and 3kb is a ton smaller than jQuery or MooTools.

    Thanks for the share!

  2. Wow, that little framework looks handy. I’m content with learning MooTools because I like it and it’s capability of handling anything, but if I need something really small or just want to learn something knew, I’ll look into this.

  3. Talk about good timing. I am working on a site that only requires a twitter feed through a json request! this is perfect for the job!

    • If all you are doing is a single ajax request, you should probably just use pure javascript. There is no need for a framework if you only are running a few lines.

      Here is a link if you are interested.
      http://www.w3schools.com/ajax/default.asp

    • alpha123

      You might want to check out http://w3fools.com/

    • He’ll probably need at least an event handler as well to trigger the request. Also, it’s not an AJAX request, since you can’t do cross-domain xhr, it’s JSONP.

      All that said, I whole heartedly encourage people to check out snack’s source and pull out only the tiny pieces they need, it’s also delete key friendly :)

  4. What’s the difference between Snack and a more stripped down JavaScript framework like DOM Assistant? (and DOM Assistant works with the ultra-useful Selectivizr)

  5. alpha123

    Interestingly enough, I just finished something like this, called Shrike (GitHub). It’s about 5.5KB gzipped though, so Snack is lighter. Shrike’s documentation is still missing, and the event system is definitely less cool than Snack’s, but it’s pretty neat if you need a lightweight JavaScript framework.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!