Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add width and classHeader properties #46

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ You can listen to the events triggered by the modal inside the Backbone.View
Set up the modal with the following options:

- {String|View} [options.content] Modal content. Default: none
- {String} [options.classHeader] Add class to modal header. Default none.
- {String} [options.width] Override bootstrap width.Default none.
- {String} [options.title] Title. Default: none
- {String} [options.okText] Text for the OK button. Default: 'OK'
- {Boolean} [options.focusOk] Wether the 'OK' button should have the focus or not. Default: true
Expand Down
94 changes: 23 additions & 71 deletions src/backbone.bootstrap-modal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Bootstrap Modal wrapper for use with Backbone.
*
*
* Takes care of instantiation, manages multiple modals,
* adds several options and removes the element from the DOM when closed
*
Expand All @@ -13,24 +13,22 @@
* ok: The user clicked OK
*/
(function($, _, Backbone) {

//Set custom template settings
var _interpolateBackup = _.templateSettings;
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g,
evaluate: /<%([\s\S]+?)%>/g
}

var template = _.template('\
<% if (title) { %>\
<div class="modal-header">\
<div class="modal-header <% if (classHeader) { %>{{ classHeader }}<% } %>">\
<% if (allowCancel) { %>\
<a class="close">&times;</a>\
<a class="close">×</a>\
<% } %>\
<h3>{{title}}</h3>\
</div>\
<% } %>\
<div class="modal-body">{{content}}</div>\
<div class="modal-body <% if (classHeader) { %>{{ classHeader }}<% } %>">{{content}}</div>\
<div class="modal-footer">\
<% if (allowCancel) { %>\
<% if (cancelText) { %>\
Expand All @@ -40,49 +38,36 @@
<a href="#" class="btn ok btn-primary">{{okText}}</a>\
</div>\
');

//Reset to users' template settings
_.templateSettings = _interpolateBackup;


var Modal = Backbone.View.extend({

className: 'modal',

events: {
'click .close': function(event) {
event.preventDefault();

this.trigger('cancel');

if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('cancel', this);
}
},
'click .cancel': function(event) {
event.preventDefault();

this.trigger('cancel');

if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('cancel', this);
}
},
'click .ok': function(event) {
event.preventDefault();

this.trigger('ok');

if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('ok', this);
}

if (this.options.okCloses) {
this.close();
}
}
},

/**
* Creates an instance of a Bootstrap Modal
*
Expand All @@ -106,143 +91,116 @@
okCloses: true,
cancelText: 'Cancel',
allowCancel: true,
classHeader: true,
width: true,
escape: true,
animate: false,
template: template
}, options);
},

/**
* Creates the DOM element
*
*
* @api private
*/
render: function() {
var $el = this.$el,
options = this.options,
content = options.content;

options = this.options,
content = options.content;
//Create the modal container
$el.html(options.template(options));

if (options.width) {
$el.css({
'width': options.width,
'margin-left': (options.width / 2) * -1
});
}
var $content = this.$content = $el.find('.modal-body')

//Insert the main content if it's a view
if (content.$el) {
content.render();
$el.find('.modal-body').html(content.$el);
}

if (options.animate) $el.addClass('fade');

this.isRendered = true;

return this;
},

/**
* Renders and shows the modal
*
* @param {Function} [cb] Optional callback that runs only when OK is pressed.
*/
open: function(cb) {
if (!this.isRendered) this.render();

var self = this,
$el = this.$el;

$el = this.$el;
//Create it
$el.modal(_.extend({
keyboard: this.options.allowCancel,
backdrop: this.options.allowCancel ? true : 'static'
}, this.options.modalOptions));

//Focus OK button
$el.one('shown', function() {
if (self.options.focusOk) {
$el.find('.btn.ok').focus();
}

if (self.options.content && self.options.content.trigger) {
self.options.content.trigger('shown', self);
}

self.trigger('shown');
});

//Adjust the modal and backdrop z-index; for dealing with multiple modals
var numModals = Modal.count,
$backdrop = $('.modal-backdrop:eq('+numModals+')'),
backdropIndex = parseInt($backdrop.css('z-index'),10),
elIndex = parseInt($backdrop.css('z-index'), 10);

$backdrop = $('.modal-backdrop:eq(' + numModals + ')'),
backdropIndex = parseInt($backdrop.css('z-index'), 10),
elIndex = parseInt($backdrop.css('z-index'), 10);
$backdrop.css('z-index', backdropIndex + numModals);
this.$el.css('z-index', elIndex + numModals);

if (this.options.allowCancel) {
$backdrop.one('click', function() {
if (self.options.content && self.options.content.trigger) {
self.options.content.trigger('cancel', self);
}

self.trigger('cancel');
});

$(document).one('keyup.dismiss.modal', function (e) {
$(document).one('keyup.dismiss.modal', function(e) {
e.which == 27 && self.trigger('cancel');

if (self.options.content && self.options.content.trigger) {
e.which == 27 && self.options.content.trigger('shown', self);
}
});
}

this.on('cancel', function() {
self.close();
});

Modal.count++;

//Run callback on OK if provided
if (cb) {
self.on('ok', cb);
}

return this;
},

/**
* Closes the modal
*/
close: function() {
var self = this,
$el = this.$el;

$el = this.$el;
//Check if the modal should stay open
if (this._preventClose) {
this._preventClose = false;
return;
}

$el.one('hidden', function onHidden(e) {
// Ignore events propagated from interior objects, like bootstrap tooltips
if(e.target !== e.currentTarget){
return $el.one('hidden', onHidden);
}
$el.one('hidden', function() {
self.remove();

if (self.options.content && self.options.content.trigger) {
self.options.content.trigger('hidden', self);
}

self.trigger('hidden');
});

$el.modal('hide');

Modal.count--;
},

/**
* Stop the modal from closing.
* Can be called from within a 'close' or 'ok' event listener.
Expand All @@ -252,28 +210,22 @@
}
}, {
//STATICS

//The number of modals on display
count: 0
});


//EXPORTS
//CommonJS
if (typeof require == 'function' && typeof module !== 'undefined' && exports) {
module.exports = Modal;
}

//AMD / RequireJS
if (typeof define === 'function' && define.amd) {
return define(function() {
Backbone.BootstrapModal = Modal;
})
}

//Regular; add to Backbone.Bootstrap.Modal
else {
Backbone.BootstrapModal = Modal;
}

})(jQuery, _, Backbone);
})(jQuery, _, Backbone);