Sammy
Documentation
API
- Handlebars.SafeString
- Sammy
- Sammy.Application
- Sammy.Cache
- Sammy.DataLocationProxy
- Sammy.EventContext
- Sammy.Form
- Sammy.FormBuilder
- Sammy.GoogleAnalytics
- Sammy.Haml
- Sammy.Handlebars
- Sammy.HashLocationProxy
- Sammy.JSON
- Sammy.Meld
- Sammy.Mustache
- Sammy.NestedParams
- Sammy.Object
- Sammy.PathLocationProxy
- Sammy.Pure
- Sammy.RenderContext
- Sammy.Session
- Sammy.Storage
- Sammy.Store
- Sammy.Store.Cookie
- Sammy.Store.Data
- Sammy.Store.LocalStorage
- Sammy.Store.Memory
- Sammy.Store.SessionStorage
- Sammy.Store.isAvailable
- Sammy.Template
- Sammy.Title
- Sammy.addLogger
- Sammy.log
Handlebars.SafeString ( string )
Build out our basic SafeString type
Sammy ( )
Sammy
(also aliased as $.sammy) is not only the namespace for a
number of prototypes, its also a top level method that allows for easy
creation/management of Sammy.Application
instances. There are a
number of different forms for Sammy()
but each returns an instance
of Sammy.Application
. When a new instance is created using
Sammy
it is added to an Object called Sammy.apps
. This
provides for an easy way to get at existing Sammy applications. Only one
instance is allowed per element_selector
so when calling
Sammy('selector')
multiple times, the first time will create
the application and the following times will extend the application
already added to that selector.
Example
// returns the app at #main or a new app
Sammy('#main')
// equivilent to "new Sammy.Application", except appends to apps
Sammy();
Sammy(function() { ... });
// extends the app at '#main' with function.
Sammy('#main', function() { ... });
Sammy.Application ( app_function )
Sammy.Application is the Base prototype for defining 'applications'.
An 'application' is a collection of 'routes' and bound events that is
attached to an element when run()
is called.
The only argument an 'app_function' is evaluated within the context of the application.
Attributes
- APP_EVENTS
- ROUTE_VERBS
- any
- debug
- del
- element_selector
- get
- post
- put
- raise_errors
- run_interval_every
- template_engine
APP_EVENTS = ['run'
An array of the default events triggered by the application during its lifecycle
ROUTE_VERBS = ['get','post','put','delete']
the four route verbs
any = _routeWrapper('any')
Alias for route('any', ...)
debug = false
When set to true, logs all of the default events using log()
del = _routeWrapper('delete')
Alias for route('delete', ...)
element_selector = 'body'
Defines what element the application is bound to. Provide a selector
(parseable by jQuery()
) and this will be used by $element()
get = _routeWrapper('get')
Alias for route('get', ...)
post = _routeWrapper('post')
Alias for route('post', ...)
put = _routeWrapper('put')
Alias for route('put', ...)
raise_errors = false
When set to true, and the error() handler is not overriden, will actually raise JS errors in routes (500) and when routes can't be found (404)
run_interval_every = 50
The time in milliseconds that the URL is queried for changes
template_engine = null
The default template engine to use when using partial()
in an
EventContext
. template_engine
can either be a string that
corresponds to the name of a method/helper on EventContext or it can be a function
that takes two arguments, the content of the unrendered partial and an optional
JS object that contains interpolation data. Template engine is only called/refered
to if the extension of the partial is null or unknown. See partial()
for more information
Methods
- $element
- after
- around
- before
- bind
- bindToAllEvents
- clearTemplateCache
- contextMatchesOptions
- error
- eventNamespace
- getLocation
- helper
- helpers
- isRunning
- lookupRoute
- mapRoutes
- notFound
- refresh
- routablePath
- route
- run
- runRoute
- setLocation
- setLocationProxy
- swap
- templateCache
- toString
- trigger
- unload
- use
$element ( )
returns a jQuery object of the Applications bound element.
after ( callback )
A shortcut for binding a callback to be run after a route is executed. After callbacks have no guarunteed order.
around ( callback )
Adds an around filter to the application. around filters are functions
that take a single argument callback
which is the entire route
execution path wrapped up in a closure. This means you can decide whether
or not to proceed with execution by not invoking callback
or,
more usefuly wrapping callback inside the result of an asynchronous execution.
Example
The most common use case for around() is calling a possibly async function and executing the route within the functions callback:
var app = $.sammy(function() {
var current_user = false;
function checkLoggedIn(callback) {
// /session returns a JSON representation of the logged in user
// or an empty object
if (!current_user) {
$.getJSON('/session', function(json) {
if (json.login) {
// show the user as logged in
current_user = json;
// execute the route path
callback();
} else {
// show the user as not logged in
current_user = false;
// the context of aroundFilters is an EventContext
this.redirect('#/login');
}
});
} else {
// execute the route path
callback();
}
};
this.around(checkLoggedIn);
});
before ( options, callback )
Takes a single callback that is pushed on to a stack.
Before any route is run, the callbacks are evaluated in order within
the current Sammy.EventContext
If any of the callbacks explicitly return false, execution of any further callbacks and the route itself is halted.
You can also provide a set of options that will define when to run this before based on the route it proceeds.
Example
var app = $.sammy(function() {
// will run at #/route but not at #/
this.before('#/route', function() {
//...
});
// will run at #/ but not at #/route
this.before({except: {path: '#/route'}}, function() {
this.log('not before #/route');
});
this.get('#/', function() {});
this.get('#/route', function() {});
});
See contextMatchesOptions()
for a full list of supported options
bind ( name, data, callback )
Works just like jQuery.fn.bind()
with a couple noteable differences.
- It binds all events to the application element
- All events are bound within the
eventNamespace()
- Events are not actually bound until the application is started with
run()
- callbacks are evaluated within the context of a Sammy.EventContext
See http://code.quirkey.com/sammy/docs/events.html for more info.
bindToAllEvents ( callback )
Will bind a single callback function to every event that is already
being listened to in the app. This includes all the APP_EVENTS
as well as any custom events defined with bind()
.
Used internally for debug logging.
clearTemplateCache ( )
clear the templateCache
contextMatchesOptions ( context, match_options, positive )
Matches an object of options against an EventContext
like object that
contains path
and verb
attributes. Internally Sammy uses this
for matching before()
filters against specific options. You can set the
object to only match certain paths or verbs, or match all paths or verbs except
those that match the options.
Example
var app = $.sammy(),
context = {verb: 'get', path: '#/mypath'};
// match against a path string
app.contextMatchesOptions(context, '#/mypath'); //=> true
app.contextMatchesOptions(context, '#/otherpath'); //=> false
// equivilent to
app.contextMatchesOptions(context, {only: {path:'#/mypath'}}); //=> true
app.contextMatchesOptions(context, {only: {path:'#/otherpath'}}); //=> false
// match against a path regexp
app.contextMatchesOptions(context, /path/); //=> true
app.contextMatchesOptions(context, /^path/); //=> false
// match only a verb
app.contextMatchesOptions(context, {only: {verb:'get'}}); //=> true
app.contextMatchesOptions(context, {only: {verb:'post'}}); //=> false
// match all except a verb
app.contextMatchesOptions(context, {except: {verb:'post'}}); //=> true
app.contextMatchesOptions(context, {except: {verb:'get'}}); //=> false
// match all except a path
app.contextMatchesOptions(context, {except: {path:'#/otherpath'}}); //=> true
app.contextMatchesOptions(context, {except: {path:'#/mypath'}}); //=> false
error ( message, original_error )
The base error handler takes a string message
and an Error
object. If raise_errors
is set to true
on the app level,
this will re-throw the error to the browser. Otherwise it will send the error
to log()
. Override this method to provide custom error handling
e.g logging to a server side component or displaying some feedback to the
user.
eventNamespace ( )
A unique event namespace defined per application.
All events bound with bind()
are automatically bound within this space.
getLocation ( )
Delegates to the location_proxy
to get the current location.
See Sammy.HashLocationProxy
for more info on location proxies.
helper ( name, method )
Helper extends the event context just like helpers()
but does it
a single method at a time. This is especially useful for dynamically named
helpers
Example
// Trivial example that adds 3 helper methods to the context dynamically
var app = $.sammy(function(app) {
$.each([1,2,3], function(i, num) {
app.helper('helper' + num, function() {
this.log("I'm helper number " + num);
});
});
this.get('#/', function() {
this.helper2(); //=> I'm helper number 2
});
});
Arguments
name
The name of the methodmethod
The function to be added to the prototype atname
helpers ( extensions )
Helpers extends the EventContext prototype specific to this app. This allows you to define app specific helper functions that can be used whenever you're inside of an event context (templates, routes, bind).
Example
var app = $.sammy(function() {
helpers({
upcase: function(text) {
return text.toString().toUpperCase();
}
});
get('#/', function() { with(this) {
// inside of this context I can use the helpers
$('#main').html(upcase($('#main').text());
}});
});
Arguments
extensions
An object collection of functions to extend the context.
isRunning ( )
Returns true
if the current application is running.
lookupRoute ( verb, path )
Given a verb and a String path, will return either a route object or false if a matching route can be found within the current defined set.
mapRoutes ( route_array )
mapRoutes
takes an array of arrays, each array being passed to route()
as arguments, this allows for mass definition of routes. Another benefit is
this makes it possible/easier to load routes via remote JSON.
Example
var app = $.sammy(function() {
this.mapRoutes([
['get', '#/', function() { this.log('index'); }],
// strings in callbacks are looked up as methods on the app
['post', '#/create', 'addUser'],
// No verb assumes 'any' as the verb
[/dowhatever/, function() { this.log(this.verb, this.path)}];
]);
})
notFound ( verb, path )
This thows a '404 Not Found' error by invoking error()
.
Override this method or error()
to provide custom
404 behavior (i.e redirecting to / or showing a warning)
refresh ( )
Reruns the current route
routablePath ( path )
Returns a copy of the given path with any query string after the hash removed.
route ( verb, path, callback )
route()
is the main method for defining routes within an application.
For great detail on routes, check out: http://code.quirkey.com/sammy/doc/routes.html
This method also has aliases for each of the different verbs (eg. get()
, post()
, etc.)
Arguments
verb
A String in the set of ROUTE_VERBS or 'any'. 'any' will add routes for each of the ROUTE_VERBS. If only two arguments are passed, the first argument is the path, the second is the callback and the verb is assumed to be 'any'.path
A Regexp or a String representing the path to match to invoke this verb.callback
A Function that is called/evaluated whent the route is run see:runRoute()
. It is also possible to pass a string as the callback, which is looked up as the name of a method on the application.
run ( start_url )
Actually starts the application's lifecycle. run()
should be invoked
within a document.ready block to ensure the DOM exists before binding events, etc.
Example
var app = $.sammy(function() { ... }); // your application
$(function() { // document.ready
app.run();
});
Arguments
start_url
Optionally, a String can be passed which the App will redirect to after the events/routes have been bound.
runRoute ( verb, path, params, target )
First, invokes lookupRoute()
and if a route is found, parses the
possible URL params and then invokes the route's callback within a new
Sammy.EventContext
. If the route can not be found, it calls
notFound()
. If raise_errors
is set to true
and
the error()
has not been overriden, it will throw an actual JS
error.
You probably will never have to call this directly.
Arguments
verb
A String for the verb.path
A String path to lookup.params
An Object of Params pulled from the URI or passed directly.
Returns
Either returns the value returned by the route callback or raises a 404 Not Found error.
setLocation ( new_location )
Delegates to the location_proxy
to set the current location.
See Sammy.HashLocationProxy
for more info on location proxies.
Arguments
new_location
A new location string (e.g. '#/')
setLocationProxy ( new_proxy )
Sets the location proxy for the current app. By default this is set to
a new Sammy.HashLocationProxy
on initialization. However, you can set
the location_proxy inside you're app function to give your app a custom
location mechanism. See Sammy.HashLocationProxy
and Sammy.DataLocationProxy
for examples.
setLocationProxy()
takes an initialized location proxy.
Example
// to bind to data instead of the default hash;
var app = $.sammy(function() {
this.setLocationProxy(new Sammy.DataLocationProxy(this));
});
swap ( content )
Swaps the content of $element()
with content
You can override this method to provide an alternate swap behavior
for EventContext.partial()
.
Example
var app = $.sammy(function() {
// implements a 'fade out'/'fade in'
this.swap = function(content) {
this.$element().hide('slow').html(content).show('slow');
}
get('#/', function() {
this.partial('index.html.erb') // will fade out and in
});
});
templateCache ( key, value )
a simple global cache for templates. Uses the same semantics as
Sammy.Cache
and Sammy.Storage
so can easily be replaced with
a persistant storage that lasts beyond the current request.
toString ( )
//=> Sammy.Application: body
trigger ( name, data )
Triggers custom events defined with bind()
Arguments
name
The name of the event. Automatically prefixed with theeventNamespace()
data
An optional Object that can be passed to the bound callback.context
An optional context/Object in which to execute the bound callback. If no context is supplied a the context is a newSammy.EventContext
unload ( )
The opposite of run()
, un-binds all event listeners and intervals
run()
Automaticaly binds a onunload
event to run this when
the document is closed.
use ( )
use()
is the entry point for including Sammy plugins.
The first argument to use should be a function() that is evaluated
in the context of the current application, just like the app_function
argument to the Sammy.Application
constructor.
Any additional arguments are passed to the app function sequentially.
For much more detail about plugins, check out: http://code.quirkey.com/sammy/doc/plugins.html
Example
var MyPlugin = function(app, prepend) {
this.helpers({
myhelper: function(text) {
alert(prepend + " " + text);
}
});
};
var app = $.sammy(function() {
this.use(MyPlugin, 'This is my plugin');
this.get('#/', function() {
this.myhelper('and dont you forget it!');
//=> Alerts: This is my plugin and dont you forget it!
});
});
If plugin is passed as a string it assumes your are trying to load Sammy."Plugin". This is the prefered way of loading core Sammy plugins as it allows for better error-messaging.
Example
$.sammy(function() {
this.use('Mustache'); //=> Sammy.Mustache
this.use('Storage'); //=> Sammy.Storage
});
Sammy.Cache ( app, options )
Sammy.Cache provides helpers for caching data within the lifecycle of a
Sammy app. The plugin provides two main methods on Sammy.Application
,
cache
and clearCache
. Each app has its own cache store so that
you dont have to worry about collisions. As of 0.5 the original Sammy.Cache module
has been deprecated in favor of this one based on Sammy.Storage. The exposed
API is almost identical, but Sammy.Storage provides additional backends including
HTML5 Storage. Sammy.Cache
will try to use these backends when available
(in this order) LocalStorage
, SessionStorage
, and Memory
Sammy.DataLocationProxy ( app, data_name, href_attribute )
The DataLocationProxy is an optional location proxy prototype. As opposed to
the HashLocationProxy
it gets its location from a jQuery.data attribute
tied to the application's element. You can set the name of the attribute by
passing a string as the second argument to the constructor. The default attribute
name is 'sammy-location'. To read more about location proxies, check out the
documentation for Sammy.HashLocationProxy
An optional href_attribute
can be passed, which specifies a DOM element
attribute that holds "links" to different locations in the app. When the
proxy is bound, clicks to element that have this attribute activate a
setLocation()
using the contents of the href_attribute
.
Example
var app = $.sammy(function() {
// set up the location proxy
this.setLocationProxy(new Sammy.DataLocationProxy(this, 'location', 'rel'));
this.get('about', function() {
this.partial('about.html');
});
});
In this scenario, if an element existed within the template:
<a href="/about" rel="about">About Us</a>
Clicking on that link would not go to /about, but would set the apps location to 'about' and trigger the route.
Sammy.EventContext ( app, verb, path, params, target )
Sammy.EventContext
objects are created every time a route is run or a
bound event is triggered. The callbacks for these events are evaluated within a Sammy.EventContext
This within these callbacks the special methods of EventContext
are available.
Example
$.sammy(function() {
// The context here is this Sammy.Application
this.get('#/:name', function() {
// The context here is a new Sammy.EventContext
if (this.params['name'] == 'sammy') {
this.partial('name.html.erb', {name: 'Sammy'});
} else {
this.redirect('#/somewhere-else')
}
});
});
Initialize a new EventContext
Arguments
app
TheSammy.Application
this event is called within.verb
The verb invoked to run this context/route.path
The string path invoked to run this context/route.params
An Object of optional params to pass to the context. Is converted to aSammy.Object
.target
a DOM element that the event that holds this context originates from. For post, put and del routes, this is the form element that triggered the route.
Methods
- $element
- engineFor
- eventNamespace
- interpolate
- json
- load
- notFound
- partial
- redirect
- render
- renderEach
- send
- swap
- toString
- trigger
$element ( )
A shortcut to the app's $element()
engineFor ( engine )
Look up a templating engine within the current app and context.
engine
can be one of the following:
- a function: should conform to
function(content, data) { return interploated; }
- a template path: 'template.ejs', looks up the extension to match to
the
ejs()
helper - a string referering to the helper: "mustache" =>
mustache()
If no engine is found, use the app's default template_engine
eventNamespace ( )
A shortcut to app's eventNamespace()
interpolate ( content, data, engine )
using the template engine
found with engineFor()
, interpolate the
data
into content
json ( string )
Default JSON parsing uses jQuery's parseJSON()
. Include Sammy.JSON
plugin for the more conformant "crockford special".
load ( location, options, callback )
create a new Sammy.RenderContext
calling load()
with location
and
options
. Called without interpolation or placement, this allows for
preloading/caching the templates.
notFound ( )
Raises a possible notFound()
error for the current path.
partial ( location, data )
render()
the the location
with data
and then swap()
the
app's $element
with the rendered content.
redirect ( )
Changes the location of the current window. If to
begins with
'#' it only changes the document's hash. If passed more than 1 argument
redirect will join them together with forward slashes.
Example
redirect('#/other/route');
// equivilent to
redirect('#', 'other', 'route');
render ( location, data, callback )
Create and return a Sammy.RenderContext
calling render()
on it.
Loads the template and interpolate the data, however does not actual
place it in the DOM.
Example
// mytemplate.mustache <div class="name"></div>
render('mytemplate.mustache', {name: 'quirkey'});
// sets the `content` to <div class="name">quirkey</div>
render('mytemplate.mustache', {name: 'quirkey'})
.appendTo('ul');
// appends the rendered content to $('ul')
renderEach ( location, name, data, callback )
Create and return a Sammy.RenderContext
calling renderEach()
on it.
Loads the template and interpolates the data for each item,
however does not actual place it in the DOM.
Example
// mytemplate.mustache <div class="name"></div>
renderEach('mytemplate.mustache', [{name: 'quirkey'}, {name: 'endor'}])
// sets the `content` to <div class="name">quirkey</div><div class="name">endor</div>
renderEach('mytemplate.mustache', [{name: 'quirkey'}, {name: 'endor'}]).appendTo('ul');
// appends the rendered content to $('ul')
send ( )
create a new Sammy.RenderContext
calling send()
with an arbitrary
function
swap ( contents )
A shortcut to app's swap()
toString ( )
//=> Sammy.EventContext: get #/ {}
trigger ( name, data )
Triggers events on app
within the current context.
Sammy.Form ( app )
Sammy.Form is a Sammy plugin that adds form building helpers to a Sammy.Application
Attributes
simple_element = simple_element
simple_element is a simple helper for creating HTML tags.
Arguments
tag
the HTML tag to generate e.g. input, p, etc/attributes
an object representing the attributes of the element as key value pairs. e.g. {class: 'element-class'}content
an optional string representing the content for the the element. If ommited, the element becomes self closing
Methods
formFor ( name, object, content_callback )
formFor creates a Sammy.Form builder object with the passed name
and object
and passes it as an argument to the content_callback
.
This is a shortcut for creating FormBuilder objects for use within
templates.
Example
// in item_form.template
<% formFor('item', item, function(f) { %>
<%= f.open({action: '#/items'}) %>
<p>
<%= f.label('name') %>
<%= f.text('name') %>
</p>
<p>
<%= f.submit() %>
</p>
<%= f.close() %>
<% }); %>
Sammy.FormBuilder ( name, object )
Sammy.FormBuilder is based very closely on the Rails FormBuilder classes. Its goal is to make it easy to create HTML forms for creating and editing JavaScript objects. It eases the process by auto-populating existing values into form inputs and creating input names suitable for parsing by Sammy.NestedParams and other backend frameworks.
You initialize a Sammy.FormBuilder by passing the 'name' of the object and the object itself. Once initialized you create form elements with the object's prototype methods. Each of these methods returns a string of HTML suitable for appending through a template or directly with jQuery.
Example
var item = {
name: 'My Item',
price: '$25.50',
meta: {
id: '123'
}
};
var form = new Sammy.FormBuilder('item', item);
form.text('name');
//=> <input type='text' name='item[form]' value='My Item' />
Nested attributes can be accessed/referred to by a 'keypath' which is basically a string representation of the dot notation.
form.hidden('meta.id');
//=> <input type='hidden' name='item[meta][id]' value='123' />
Methods
checkbox ( keypath, value, attributes )
creates a checkbox input for keypath with the value value
. Multiple
checkboxes can be created with different value, if value
equals the
current value of the key of the form builder's object the attribute
checked='checked' will be added.
By default checkbox()
also generates a hidden element whose value is
the inverse of the value given. This is known hack to get around a common
gotcha where browsers and jQuery itself does not include 'unchecked'
elements in the list of submittable inputs. This ensures that a value
should always be passed to Sammy and hence the server. You can disable
the creation of the hidden element by setting the hidden_element
attribute
to false
close ( )
closes the form
label ( keypath, content, attributes )
creates a label for keypath
with the text content
with an optional
attributes` object
open ( attributes )
creates the open form tag with the object attributes
password ( keypath, attributes )
creates a password input for keypath
with an optional attributes
object
radio ( keypath, value, attributes )
creates a radio input for keypath with the value value
. Multiple
radios can be created with different value, if value
equals the
current value of the key of the form builder's object the attribute
checked='checked' will be added.
select ( keypath, options, attributes )
creates a select element for keypath
with the option elements
specified by an array in options
. If options
is an array of arrays,
the first element in each subarray becomes the text of the option and the
second becomes the value.
Example
var options = [
['Small', 's'],
['Medium', 'm'],
['Large', 'l']
];
form.select('size', options);
//=> <select name='item[size]'><option value='s'>Small</option> ...
submit ( attributes )
creates a submit input for keypath
with an optional attributes
object
text ( keypath, attributes )
creates a text input for keypath
with an optional attributes
object
textarea ( keypath, attributes )
creates a textarea for keypath
with an optional attributes
object
Sammy.GoogleAnalytics ( app, tracker )
A simple plugin that pings Google Analytics tracker every time a route is triggered. Originally by Brit Gardner (britg), with updates from Aaron Quint (quirkey).
=== Arguments
+tracker+:: the Google Analytics pageTracker object. Defaults to the default object defined by the GA snippet, or pass your own if you have a custom install
=== Example
Install Google Analytics to your site as you normally would. Be sure that the 'pageTracker' global variable exists.
Then, simply add the plugin to your Sammy App and it will automatically track all of your routes in Google Analytics. They will appear as page views to the route's path.
$.sammy(function() {
this.use('GoogleAnalytics');
...
});
If you have routes that you do not want to track, simply call noTrack
within the route.
$.sammy(function() {
this.use('GoogleAnalytics')
get('#/dont/track/me', function() {
this.noTrack(); // This route will not be tracked
});
});
Methods
noTrack ( )
Disable tracking for the current route. Put at the begining of the route's callback
track ( path )
send a page view to the tracker with path
Sammy.Haml ( app, method_alias )
Sammy.Haml provides a quick way of using haml style templates in your app. The plugin itself includes the haml-js library created by Tim Caswell at at http://github.com/creationix/haml-js
Haml is an alternative HTML syntax that is really great for describing the structure of HTML documents.
By default using Sammy.Haml in your app adds the haml() method to the EventContext prototype. However, just like Sammy.Template you can change the default name of the method by passing a second argument (e.g. you could use the hml() as the method alias so that all the template files could be in the form file.hml instead of file.haml)
Example
The template (mytemplate.haml):
%h1&= title
Hey, #{name}! Welcome to Haml!
The app:
var $.app = $.sammy(function() {
// include the plugin
this.use(Sammy.Haml);
this.get('#/hello/:name', function() {
// set local vars
this.title = 'Hello!'
this.name = this.params.name;
// render the template and pass it through haml
this.partial('mytemplate.haml');
});
});
If I go to #/hello/AQ in the browser, Sammy will render this to the body:
<h1>Hello!</h1>
Hey, AQ! Welcome to HAML!
Note: You dont have to include the haml.js file on top of the plugin as the plugin includes the full source.
Attributes
pathPatterns = {}
spot to memoize paths to speed up loops and subsequent parses
Methods
filterOutput ( value, escape )
Escapes output and converts empty values to empty strings
parsePath ( path )
returns a two element array containing the numbers of contexts to back up the stack and the properties to dig into on the current context
for example, if the path is "../../alan/name", the result will be [2, ["alan", "name"]].
Sammy.Handlebars ( app, method_alias )
Sammy.Handlebars provides a quick way of using Handlebars templates in your app. The plugin itself includes the handlebars.js library created by Yehuda Katz at at http://github.com/wycats/handlebars.js
Handlebars.js is an extension to the Mustache templating language created by Chris Wanstrath. Handlebars.js and Mustache are both logicless templating languages that keep the view and the code separated like we all know they should be.
By default using Sammy.Handlbars in your app adds the handlebars() method to the EventContext prototype. However, just like Sammy.Template you can change the default name of the method by passing a second argument (e.g. you could use the hbr() as the method alias so that all the template files could be in the form file.hbr instead of file.handlebars)
Example #1
The template (mytemplate.hb):
<h1>\{\{title\}\}<h1>
Hey, ! Welcome to Handlebars!
The app:
var $.app = $.sammy(function() {
// include the plugin and alias handlebars() to hb()
this.use(Sammy.Handlebars, 'hb');
this.get('#/hello/:name', function() {
// set local vars
this.title = 'Hello!'
this.name = this.params.name;
// render the template and pass it through handlebars
this.partial('mytemplate.hb');
});
});
If I go to #/hello/AQ in the browser, Sammy will render this to the body:
<h1>Hello!</h1>
Hey, AQ! Welcome to Handlebars!
Example #2 - Handlebars partials
The template (mytemplate.hb)
Hey, !
The partial (mypartial.hb)
Say hello to your friend !
The app:
var $.app = $.sammy(function() {
// include the plugin and alias handlebars() to hb()
this.use(Sammy.Handlebars, 'hb');
this.get('#/hello/:name/to/:friend', function() {
var context = this;
// fetch handlebars-partial first
$.get('mypartial.hb', function(response){
context.partials = response;
// set local vars
context.name = this.params.name;
context.hello_friend = {name: this.params.friend};
// render the template and pass it through handlebars
context.partial('mytemplate.hb');
});
});
});
If I go to #/hello/AQ/to/dP in the browser, Sammy will render this to the body:
Hey, AQ! Say hello to your friend dP!
Note: You dont have to include the handlebars.js file on top of the plugin as the plugin includes the full source.
Sammy.HashLocationProxy ( app, run_interval_every )
The HashLocationProxy is the default location proxy for all Sammy applications. A location proxy is a prototype that conforms to a simple interface. The purpose of a location proxy is to notify the Sammy.Application its bound to when the location or 'external state' changes. The HashLocationProxy considers the state to be changed when the 'hash' (window.location.hash / '#') changes. It does this in two different ways depending on what browser you are using. The newest browsers (IE, Safari > 4, FF >= 3.6) support a 'onhashchange' DOM event, thats fired whenever the location.hash changes. In this situation the HashLocationProxy just binds to this event and delegates it to the application. In the case of older browsers a poller is set up to track changes to the hash. Unlike Sammy 0.3 or earlier, the HashLocationProxy allows the poller to be a global object, eliminating the need for multiple pollers even when thier are multiple apps on the page.
Methods
bind ( )
bind the proxy events to the current app.
getLocation ( )
get the current location from the hash.
setLocation ( new_location )
set the current location to new_location
unbind ( )
unbind the proxy events from the current app
Sammy.JSON ( app )
Sammy.JSON is a simple wrapper around Douglas Crockford's ever-useful json2.js (http://www.json.org/js.html]) Sammy.JSON includes the top level JSON object if it doesn't already exist (a.k.a. does not override the native implementation that some browsers include). It also adds a json() helper to a Sammy app when included.
Methods
json ( object )
json is a polymorphic function that translates objects aback and forth from JSON to JS. If given a string, it will parse into JS, if given a JS object it will stringify into JSON.
Example
var app = $.sammy(function() {
this.use(Sammy.JSON);
this.get('#/', function() {
this.json({user_id: 123}); //=> "{\"user_id\":\"123\"}"
this.json("{\"user_id\":\"123\"}"); //=> [object Object]
this.json("{\"user_id\":\"123\"}").user_id; //=> "123"
});
})
Sammy.Meld ( app, method_alias )
Sammy.Meld
is a simple templating engine that uses the power of jQuery's
DOM manipulation to easily meld JSON data and HTML templates very quickly.
The template can either be a string (i.e. loaded from a remote template) or a DOM Element/jQuery object. This allows you to have templates be DOM elements as the initial document load.
Example
The simplest case is a nested <div>
whose class name is tied to a
property of a JS object.
Template:
<div class="post">
<div class="title"></div>
<div class="entry"></div>
<div class="author">
<span class="name"></span>
</div>
</div>
Data:
{
"post": {
"title": "My Post",
"entry": "My Entry",
"author": {
"name": "@aq"
}
}
}
Result:
<div class="post">
<div class="title">My Post</div>
<div class="entry">My Entry</div>
<div class="author">
<span class="name">@aq</span>
</div>
</div>
Templates can be much more complex, and more deeply nested.
More examples can be found in test/fixtures/meld/
If you don't think the lookup by classes is semantic for you, you can easily switch the method of lookup by defining a selector function in the options
For example:
meld($('.post'), post_data, {
selector: function(k) {
return '[data-key=' + k + ']';
}
});
Would look for template nodes like <div data-key='entry'>
Methods
create_context ( _context )
by @langalex, support for arrays of strings
Sammy.Mustache ( app, method_alias )
Sammy.Mustache provides a quick way of using mustache style templates in your app. The plugin itself includes the awesome mustache.js lib created and maintained by Jan Lehnardt at http://github.com/janl/mustache.js
Mustache is a clever templating system that relys on double brackets for interpolation. For full details on syntax check out the original Ruby implementation created by Chris Wanstrath at http://github.com/defunkt/mustache
By default using Sammy.Mustache in your app adds the mustache() method to the EventContext prototype. However, just like Sammy.Template you can change the default name of the method by passing a second argument (e.g. you could use the ms() as the method alias so that all the template files could be in the form file.ms instead of file.mustache)
Example #1
The template (mytemplate.ms):
<h1>\{\{title\}\}<h1>
Hey, ! Welcome to Mustache!
The app:
var $.app = $.sammy(function() {
// include the plugin and alias mustache() to ms()
this.use(Sammy.Mustache, 'ms');
this.get('#/hello/:name', function() {
// set local vars
this.title = 'Hello!'
this.name = this.params.name;
// render the template and pass it through mustache
this.partial('mytemplate.ms');
});
});
If I go to #/hello/AQ in the browser, Sammy will render this to the body:
<h1>Hello!</h1>
Hey, AQ! Welcome to Mustache!
Example #2 - Mustache partials
The template (mytemplate.ms)
Hey, !
The partial (mypartial.ms)
Say hello to your friend !
The app:
var $.app = $.sammy(function() {
// include the plugin and alias mustache() to ms()
this.use(Sammy.Mustache, 'ms');
this.get('#/hello/:name/to/:friend', function() {
var context = this;
// fetch mustache-partial first
$.get('mypartial.ms', function(response){
context.partials = response;
// set local vars
context.name = this.params.name;
context.hello_friend = {name: this.params.friend};
// render the template and pass it through mustache
context.partial('mytemplate.ms');
});
});
});
If I go to #/hello/AQ/to/dP in the browser, Sammy will render this to the body:
Hey, AQ! Say hello to your friend dP!
Note: You dont have to include the mustache.js file on top of the plugin as the plugin includes the full source.
Sammy.NestedParams ( app )
Sammy.NestedParams overrides the default form parsing behavior to provide extended functionality for parsing Rack/Rails style form name/value pairs into JS Objects. In fact it passes the same suite of tests as Rack's nested query parsing. The code and tests were ported to JavaScript/Sammy by http://github.com/endor
This allows you to translate a form with properly named inputs into a JSON object.
Example
Given an HTML form like so:
<form action="#/parse_me" method="post">
<input type="text" name="obj[first]" />
<input type="text" name="obj[second]" />
<input type="text" name="obj[hash][first]" />
<input type="text" name="obj[hash][second]" />
</form>
And a Sammy app like:
var app = $.sammy(function(app) {
this.use(Sammy.NestedParams);
this.post('#/parse_me', function(context) {
$.log(this.params);
});
});
If you filled out the form with some values and submitted it, you would see something like this in your log:
{
'obj': {
'first': 'value',
'second': 'value',
'hash': {
'first': 'value',
'second': 'value'
}
}
}
It supports creating arrays with [] and other niceities. Check out the tests for full specs.
Sammy.Object ( obj )
Sammy.Object is the base for all other Sammy classes. It provides some useful functionality, including cloning, iterating, etc.
Attributes
escapeHTML = _escapeHTML
Escape HTML in string, use in templates to prevent script injection.
Also aliased as h()
Methods
has ( key )
Checks if the object has a value at key
and that the value is not empty
join ( )
convenience method to join as many arguments as you want by the first argument - useful for making paths
keys ( attributes_only )
Returns an array of keys for this object. If attributes_only
is true will not return keys that map to a function()
log ( )
Shortcut to Sammy.log
toHTML ( )
Renders a simple HTML version of this Objects attributes. Does not render functions. For example. Given this Sammy.Object:
var s = new Sammy.Object({first_name: 'Sammy', last_name: 'Davis Jr.'});
s.toHTML() //=> '<strong>first_name</strong> Sammy<br /><strong>last_name</strong> Davis Jr.<br />'
toHash ( )
Returns a copy of the object with Functions removed.
toString ( include_functions )
Returns a string representation of this object.
if include_functions
is true, it will also toString() the
methods of this object. By default only prints the attributes.
Sammy.PathLocationProxy ( app )
Sammy.PathLocationProxy
is a simple Location Proxy that just
gets and sets window.location. This allows you to use
Sammy to route on the full URL path instead of just the hash. It
will take a full refresh to get the app to change state.
To read more about location proxies, check out the
documentation for Sammy.HashLocationProxy
Sammy.Pure ( app, method_alias )
Sammy.Pure
is a simple wrapper around the pure.js templating engine for
use in Sammy apps.
See http://beebole.com/pure/ for detailed documentation.
Sammy.RenderContext ( event_context )
Sammy.RenderContext
is an object that makes sequential template loading,
rendering and interpolation seamless even when dealing with asyncronous
operations.
RenderContext
objects are not usually created directly, rather they are
instatiated from an Sammy.EventContext
by using render()
, load()
or
partial()
which all return RenderContext
objects.
RenderContext
methods always returns a modified RenderContext
for chaining (like jQuery itself).
The core magic is in the then()
method which puts the callback passed as
an argument into a queue to be executed once the previous callback is complete.
All the methods of RenderContext
are wrapped in then()
which allows you
to queue up methods by chaining, but maintaing a guarunteed execution order
even with remote calls to fetch templates.
Methods
- appendTo
- collect
- interpolate
- load
- next
- partial
- prependTo
- render
- renderEach
- replace
- send
- swap
- then
- trigger
- wait
appendTo ( selector )
Same usage as jQuery.fn.appendTo()
but uses then()
to ensure order
collect ( array, callback, now )
itterates over an array, applying the callback for each item item. the
callback takes the same style of arguments as jQuery.each()
(index, item).
The return value of each callback is collected as a single string and stored
as content
to be used in the next iteration of the RenderContext
.
interpolate ( data, engine, retain )
uses the previous loaded content
and the data
object to interpolate
a template. engine
defines the templating/interpolation method/engine
that should be used. If engine
is not passed, the next_engine
is
used. If retain
is true
, the final interpolated data is appended to
the previous_content
instead of just replacing it.
load ( location, options, callback )
Load a template into the context.
The location
can either be a string specifiying the remote path to the
file, a jQuery object, or a DOM element.
No interpolation happens by default, the content is stored in
content
.
In the case of a path, unless the option {cache: false}
is passed the
data is stored in the app's templateCache()
.
If a jQuery or DOM object is passed the innerHTML
of the node is pulled in.
This is useful for nesting templates as part of the initial page load wrapped
in invisible elements or <script>
tags. With template paths, the template
engine is looked up by the extension. For DOM/jQuery embedded templates,
this isnt possible, so there are a couple of options:
- pass an
{engine:}
option. - define the engine in the
data-engine
attribute of the passed node. - just store the raw template data and use
interpolate()
manually
If a callback
is passed it is executed after the template load.
next ( content )
Resume the queue, setting content
to be used in the next operation.
See wait()
for an example.
partial ( location, data )
render()
the the location
with data
and then swap()
the
app's $element
with the rendered content.
prependTo ( selector )
Same usage as jQuery.fn.prependTo()
but uses then()
to ensure order
render ( location, data, callback )
load()
a template and then interpolate()
it with data.
Example
this.get('#/', function() {
this.render('mytemplate.template', {name: 'test'});
});
renderEach ( location, name, data, callback )
loads a template, and then interpolates it for each item in the data
array. If a callback is passed, it will call the callback with each
item in the array after interpolation
replace ( selector )
Replaces the $(selector)
using html()
with the previously loaded
content
send ( )
defers the call of function to occur in order of the render queue.
The function can accept any number of arguments as long as the last
argument is a callback function. This is useful for putting arbitrary
asynchronous functions into the queue. The content passed to the
callback is passed as content
to the next item in the queue.
=== Example
this.send($.getJSON, '/app.json')
.then(function(json) {
$('#message).text(json['message']);
});
swap ( )
executes EventContext#swap()
with the content
then ( callback )
The "core" of the RenderContext
object, adds the callback
to the
queue. If the context is waiting
(meaning an async operation is happening)
then the callback will be executed in order, once the other operations are
complete. If there is no currently executing operation, the callback
is executed immediately.
The value returned from the callback is stored in content
for the
subsiquent operation. If you return false
, the queue will pause, and
the next callback in the queue will not be executed until next()
is
called. This allows for the guarunteed order of execution while working
with async operations.
If then() is passed a string instead of a function, the string is looked up as a helper method on the event context.
Example
this.get('#/', function() {
// initialize the RenderContext
// Even though `load()` executes async, the next `then()`
// wont execute until the load finishes
this.load('myfile.txt')
.then(function(content) {
// the first argument to then is the content of the
// prev operation
$('#main').html(content);
});
});
trigger ( name, data )
trigger the event in the order of the event context. Same semantics
as Sammy.EventContext#trigger()
. If data is ommitted, content
is sent as {content: content}
wait ( )
Pause the RenderContext
queue. Combined with next()
allows for async
operations.
Example
this.get('#/', function() {
this.load('mytext.json')
.then(function(content) {
var context = this,
data = JSON.parse(content);
// pause execution
context.wait();
// post to a url
$.post(data.url, {}, function(response) {
context.next(JSON.parse(response));
});
})
.then(function(data) {
// data is json from the previous post
$('#message').text(data.status);
});
});
Sammy.Session ( app, options )
Sammy.Session is an additional plugin for creating a common 'session' store
for the given app. It is a very simple wrapper around Sammy.Storage
that provides a simple fallback mechanism for trying to provide the best
possible storage type for the session. This means, LocalStorage
if available, otherwise Cookie
, otherwise Memory
.
It provides the session()
helper through Sammy.Storage#store()
.
See the Sammy.Storage
plugin for full documentation.
Sammy.Storage ( app )
Sammy.Storage is a plugin that provides shortcuts for creating and using
Sammy.Store objects. Once included it provides the store()
app level
and helper methods. Depends on Sammy.JSON (or json2.js).
Sammy.Store ( options )
Sammy.Store is an abstract adapter class that wraps the multitude of in browser data storage into a single common set of methods for storing and retreiving data. The JSON library is used (through the inclusion of the Sammy.JSON) plugin, to automatically convert objects back and forth from stored strings.
Sammy.Store can be used directly, but within a Sammy.Application it is much
easier to use the Sammy.Storage
plugin and its helper methods.
Sammy.Store also supports the KVO pattern, by firing DOM/jQuery Events when a key is set.
Example
// create a new store named 'mystore', tied to the #main element, using HTML5 localStorage
// Note: localStorage only works on browsers that support it
var store = new Sammy.Store({name: 'mystore', element: '#element', type: 'local'});
store.set('foo', 'bar');
store.get('foo'); //=> 'bar'
store.set('json', {obj: 'this is an obj'});
store.get('json'); //=> {obj: 'this is an obj'}
store.keys(); //=> ['foo','json']
store.clear('foo');
store.keys(); //=> ['json']
store.clearAll();
store.keys(); //=> []
Arguments
The constructor takes a single argument which is a Object containing these possible options.
name
The name/namespace of this store. Stores are unique by name/type. (default 'store')element
A selector for the element that the store is bound to. (default 'body')type
The type of storage/proxy to use (default 'memory')
Extra options are passed to the storage constructor. Sammy.Store supports the following methods of storage:
memory
Basic object storagedata
jQuery.data DOM Storagecookie
Access to document.cookie. Limited to 2Klocal
HTML5 DOM localStorage, browswer support is currently limited.session
HTML5 DOM sessionStorage, browswer support is currently limited.
Methods
clear ( key )
Removes the value at key
from the current store
clearAll ( )
Clears all the values for the current store.
each ( callback )
Iterates over each key value pair passing them to the callback
function
Example
store.each(function(key, value) {
Sammy.log('key', key, 'value', value);
});
exists ( key )
Checks for the existance of key
in the current store. Returns a boolean.
fetch ( key, callback )
Returns the value at key
if set, otherwise, runs the callback
and sets the value to the value returned in the callback.
Example
var store = new Sammy.Store;
store.exists('foo'); //=> false
store.fetch('foo', function() {
return 'bar!';
}); //=> 'bar!'
store.get('foo') //=> 'bar!'
store.fetch('foo', function() {
return 'baz!';
}); //=> 'bar!
filter ( callback )
Filters the store by a filter function that takes a key value. Returns an array of arrays where the first element of each array is the key and the second is the value of that key.
Example
var store = new Sammy.Store;
store.set('one', 'two');
store.set('two', 'three');
store.set('1', 'two');
var returned = store.filter(function(key, value) {
// only return
return value === 'two';
});
// returned => [['one', 'two'], ['1', 'two']];
first ( callback )
Works exactly like filter except only returns the first matching key value pair instead of all of them
get ( key )
Returns the set value at key
, parsing with JSON.parse
and
turning into an object if possible
isAvailable ( )
Checks for the availability of the current storage type in the current browser/config.
keys ( )
Returns the all the keys set for the current store as an array. Internally Sammy.Store keeps this array in a 'meta_key' for easy access.
load ( key, path, callback )
loads the response of a request to path
into key
.
Example
In /mytemplate.tpl:
My Template
In app.js:
var store = new Sammy.Store;
store.load('mytemplate', '/mytemplate.tpl', function() {
s.get('mytemplate') //=> My Template
});
set ( key, value )
Sets the value of key
with value
. If value
is an
object, it is turned to and stored as a string with JSON.stringify
.
It also tries to conform to the KVO pattern triggering jQuery events on the
element that the store is bound to.
Example
var store = new Sammy.Store({name: 'kvo'});
$('body').bind('set-kvo-foo', function(e, data) {
Sammy.log(data.key + ' changed to ' + data.value);
});
store.set('foo', 'bar'); // logged: foo changed to bar
Sammy.Store.Cookie ( name, element, options )
.Cookie ('cookie') storage uses browser cookies to store data. JavaScript has access to a single document.cookie variable, which is limited to 2Kb in size. Cookies are also considered 'unsecure' as the data can be read easily by other sites/JS. Cookies do have the advantage, though, of being widely supported and persistent through refresh and close/open. Where available, HTML5 DOM Storage like LocalStorage and SessionStorage should be used.
.Cookie can also take additional options:
expires_in
Number of seconds to keep the cookie alive (default 2 weeks).path
The path to activate the current cookie for (default '/').
For more information about document.cookie, check out the pre-eminint article by ppk: [http://www.quirksmode.org/js/cookies.html]
Sammy.Store.Data ( name, element )
Data ('data') stores objects using the jQuery.data() methods. This has the advantadge of scoping the data to the specific element. Like the 'memory' store its data will only last for the length of the current request (data is lost on refresh/etc).
Sammy.Store.LocalStorage ( name, element )
LocalStorage ('local') makes use of HTML5 DOM Storage, and the window.localStorage object. The great advantage of this method is that data will persist beyond the current request. It can be considered a pretty awesome replacement for cookies accessed via JS. The great disadvantage, though, is its only available on the latest and greatest browsers.
For more info on DOM Storage: [https://developer.mozilla.org/en/DOM/Storage] [http://www.w3.org/TR/2009/WD-webstorage-20091222/]
Sammy.Store.Memory ( name, element )
Memory ('memory') is the basic/default store. It stores data in a global JS object. Data is lost on refresh.
Sammy.Store.SessionStorage ( name, element )
.SessionStorage ('session') is similar to LocalStorage (part of the same API)
and shares similar browser support/availability. The difference is that
SessionStorage is only persistant through the current 'session' which is defined
as the length that the current window is open. This means that data will survive
refreshes but not close/open or multiple windows/tabs. For more info, check out
the LocalStorage
documentation and links.
Sammy.Store.isAvailable ( type )
Tests if the type of storage is available/works in the current browser/config. Especially useful for testing the availability of the awesome, but not widely supported HTML5 DOM storage
Sammy.Template ( app, method_alias )
Sammy.Template is a simple plugin that provides a way to create and render client side templates. The rendering code is based on John Resig's quick templates and Greg Borenstien's srender plugin. This is also a great template/boilerplate for Sammy plugins.
Templates use <% %> tags to denote embedded javascript.
Examples
Here is an example template (user.template):
<div class="user">
<div class="user-name"><%= user.name %></div>
<% if (user.photo_url) { %>
<div class="photo"><img src="<%= user.photo_url %>" /></div>
<% } %>
</div>
Given that is a publicly accesible file, you would render it like:
$.sammy(function() {
// include the plugin
this.use(Sammy.Template);
this.get('#/', function() {
// the template is rendered in the current context.
this.user = {name: 'Aaron Quint'};
// partial calls template() because of the file extension
this.partial('user.template');
})
});
You can also pass a second argument to use() that will alias the template method and therefore allow you to use a different extension for template files in partial()
// alias to 'tpl'
this.use(Sammy.Template, 'tpl');
// now .tpl files will be run through srender
this.get('#/', function() {
this.partial('myfile.tpl');
});
Sammy.Title ( )
Sammy.Title is a very simple plugin to easily set the document's title.
It supplies a helper for setting the title (title()
) within routes,
and an app level method for setting the global title (setTitle()
)
Attributes
_default = { $1: "$data" }
Encoded expression evaluation. Abbreviated form is ${}.
Methods
complete ( items )
This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
template ( name, tmpl )
Get: Use $.template( name ) to access a cached template. Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) will return the compiled template, without adding a name reference. If templateString includes at least one HTML tag, $.template( templateString ) is equivalent to $.template( null, templateString )
template ( name )
Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
tmpl ( tmpl, data, options, parentItem )
Return wrapped set of template items, obtained by rendering template against data.
tmpl ( data, options, parentItem )
Use first wrapped element as template markup. Return wrapped set of template items, obtained by rendering template against data.
tmplItem ( )
Find which rendered template item the first wrapped DOM element belongs to
tmplItem ( elem )
Return rendered template item for an element.
Sammy.addLogger ( logger )
Add to the global logger pool. Takes a function that accepts an unknown number of arguments and should print them or send them somewhere The first argument is always a timestamp.
Sammy.log ( )
Sends a log message to each logger listed in the global loggers pool. Can take any number of arguments. Also prefixes the arguments with a timestamp.