Skip to content

Instantly share code, notes, and snippets.

@danmillar
Created February 19, 2012 22:33
Show Gist options
  • Save danmillar/1866239 to your computer and use it in GitHub Desktop.
Save danmillar/1866239 to your computer and use it in GitHub Desktop.
Sammy Modals (Plugin)
/*
* Sammy Modals (plugin)
* Version 1.0
* https://gist.github.com/1866239
*
* Copyright (c) 2012 Dan Millar (@danmillar / decode.uk.com)
* Dual licensed under the MIT and GPL licenses.
*/
;(function($) {
Sammy = Sammy || {};
// <tt>Sammy.Modals</tt> provides a quick way of using Twitter Bootstrap Modals with mustache style templates in your app.
// The plugin is dependant upon the following:
// - Sammy.Mustache at https://github.com/quirkey/sammy/blob/master/lib/plugins/sammy.mustache.js
// - Twitter Bootstrap Modals at http://twitter.github.com/bootstrap/
//
// Note: As of Sammy 0.7 the Mustache lib is not included in the templates source. Please download
// mustache.js and include it before Sammy.Mustache.
//
// By default using Sammy.Modals in your app adds the <tt>modal()</tt> method to the EventContext prototype.
// The modal templates are wrapped in a div with the id of <tt>sammy-modal</tt>. You can change the id by passing
// a second argument through when including the plugin.
//
// A huge benefit of the plugin is how it handles switching templates within active modals. Additional hooks are also
// available via the 'switch' and 'switched' events which are added to the Modal.
//
// ### Example #1
//
// The template:
//
// <script id="welcome" type="text/mustache" data-engine="mustache">
// <h1>{{title}}</h1>
// <p>Welcome the the app, {{name}}.</p>
// <//script>
//
// The app:
//
// var $.app = $.sammy(function() {
// // include the plugin
// this.use('Modals');
//
// this.get('#/welcome/:name', function() {
// // render the template and pass it through mustache and display as modal
// this.modal('#welcome', {
// title: 'Hello!',
// name: this.params.name
// }, {
// keyboard: false
// });
// });
//
// });
//
// If I go to #/welcome/Dan in the browser, Sammy will display this <tt>modal</tt>:
//
// <h1>Hello!</h1>
//
// <p>Welcome the the app, Dan.</p>
//
Sammy.Modals = function(app, container_id) {
// This plugin is dependant upon the Mustache template for templating
this.use('Mustache');
// Set the default id of the modal container if not manually set
if (!container_id) { container_id = 'sammy-modal'; }
// The container template is based on Twitter Bootstrap Modal templates
var mTemplate = '<div id="{{container_id}}" class="modal {{options.transition}}"><div id="{{id}}"></div></div>',
mObject,
init_location = this.getLocation();
this.helpers({
// *Helper* Uses Mustache.js to parse a template and then display as a Twitter Bootstrap Modal
//
// ### Arguments
//
// * `selector` A selector for a Mustache template or A String template.
// {{}} Tags are evaluated and interpolated by Mustache.js
// * `data` An Object containing the replacement values for the template.
// data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
// * `partials` An Object containing one or more partials (String templates
// that are called from the main template).
// * `options` An Object containing one or more options to be set on the Modal (See Bootstrap documentation)
//
modal: function(selector, data, partials, options) {
var context = this,
id = selector.replace('#', ''),
container = mObject ? ('#'+container_id) : Mustache.render(mTemplate, {
container_id: container_id,
id: id,
options: options
}),
$container = $(container);
this.render($(selector), data)
.then(function(template) {
if(mObject) {
// Trigger 'switch' event (in line with Twitter modals 'show', 'shown', 'hide' and 'hidden' events)
$container.trigger('switch');
// Switch modal content
$container.children('div').attr('id', id)
.html(template);
// Update the Twitter Modal object options
mObject.options = $.extend({}, $.fn.modal.defaults, typeof options == 'object' && options);
// Ensure the Backdrop is click is attached
mObject.$backdrop.click(function() {
if(mObject.options.backdrop !== "static") {
mObject.hide();
}
});
// If not shown, show. (This should never happen. Belt & Braces)
if(!mObject.isShown) {
mObject.show();
}
// Trigger 'switched' event (in line with Twitter modals 'show', 'shown', 'hide' and 'hidden' events)
$container.trigger('switched');
} else {
// Append template to modal container
$container.find('div').append(template);
// init a new Modal and add on 'hidden' event
$container.modal(options).on('hidden', function(e) {
// Set location back to initial Uri
context.app.setLocation(init_location);
// Clear any fragments
window.location.hash = '';
// When a modal is hidden, remove it from the DOM (ensuring it transitions correctly next time)
$(this).remove();
mObject = null;
});
// Store the Twitter Modal object
mObject = $container.data('modal');
}
});
// Return the container so that event listeners can be attached
return $container;
},
// Checks if there is an active modal and closes it
closeModal: function() {
if(mObject) {
mObject.hide();
}
}
});
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment