Initial commit
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
var $ = require('jquery');
|
||||
var DropdownBaseView = require('./dropdown-base-view');
|
||||
|
||||
module.exports = DropdownBaseView.extend({
|
||||
|
||||
show: function () {
|
||||
var dfd = $.Deferred();
|
||||
var self = this;
|
||||
// sometimes this dialog is child of a node that is removed
|
||||
// for that reason we link again DOM events just in case
|
||||
this.delegateEvents();
|
||||
this.$el
|
||||
.css({
|
||||
marginTop: self.options.verticalPosition === 'down' ? '-10px' : '10px',
|
||||
opacity: 0,
|
||||
display: 'block'
|
||||
})
|
||||
.animate({
|
||||
margin: '0',
|
||||
opacity: 1
|
||||
}, {
|
||||
'duration': this.options.speedIn,
|
||||
'complete': function () {
|
||||
dfd.resolve();
|
||||
}
|
||||
});
|
||||
this.trigger('onDropdownShown', this.el);
|
||||
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
/**
|
||||
* open the dialog at x, y
|
||||
*/
|
||||
openAt: function (x, y) {
|
||||
var dfd = $.Deferred();
|
||||
|
||||
this.$el.css({
|
||||
top: y,
|
||||
left: x,
|
||||
width: this.options.width
|
||||
})
|
||||
.addClass(
|
||||
(this.options.verticalPosition === 'up' ? 'vertical_top' : 'vertical_bottom') + ' ' +
|
||||
(this.options.horizontalPosition === 'right' ? 'horizontal_right' : 'horizontal_left') + ' ' +
|
||||
// Add tick class
|
||||
'tick_' + this.options.tick
|
||||
);
|
||||
|
||||
this.modelView.set({open: true});
|
||||
|
||||
// Show
|
||||
$.when(this.show()).done(function () {
|
||||
dfd.resolve();
|
||||
});
|
||||
// xabel: I've add the deferred to make it easily testable
|
||||
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
hide: function (done) {
|
||||
// don't attempt to hide the dropdown if it's already hidden
|
||||
if (!this.isOpen) { done && done(); return; }
|
||||
|
||||
var self = this;
|
||||
|
||||
this.$el.animate({
|
||||
marginTop: self.options.verticalPosition === 'down' ? '10px' : '-10px',
|
||||
opacity: 0
|
||||
}, this.options.speedOut, function () {
|
||||
// Remove selected class
|
||||
$(self.options.target).removeClass('selected');
|
||||
|
||||
// And hide it
|
||||
self.$el.hide();
|
||||
done && done();
|
||||
|
||||
self.trigger('onDropdownHidden', self.el);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,136 @@
|
||||
var $ = require('jquery');
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
|
||||
var DEFAULTS = {
|
||||
width: 160,
|
||||
speedIn: 150,
|
||||
speedOut: 300,
|
||||
verticalPosition: 'down',
|
||||
horizontalPosition: 'right',
|
||||
tick: 'right',
|
||||
verticalOffset: 0,
|
||||
horizontalOffset: 0
|
||||
};
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
className: 'dropdown',
|
||||
|
||||
initialize: function (options) {
|
||||
_.bindAll(this, 'open', 'hide', '_handleClick', '_keydown', '_onDocumentClick');
|
||||
|
||||
this.options = {};
|
||||
// Extend options
|
||||
_.defaults(this.options, options, DEFAULTS);
|
||||
|
||||
if (options.template) {
|
||||
this.template = options.template;
|
||||
}
|
||||
|
||||
// Bind to target
|
||||
$(options.target).on('click', this._handleClick);
|
||||
$(document).on('keydown', this._keydown);
|
||||
$(document).on('click', this._onDocumentClick);
|
||||
|
||||
this.modelView = new Backbone.Model({
|
||||
open: false
|
||||
});
|
||||
|
||||
this.modelView.on('change:open', function (model, isOpen) {
|
||||
isOpen ? this.hide() : this.open();
|
||||
}, this);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
// Render
|
||||
var $el = this.$el;
|
||||
$el
|
||||
.html(this.template && this.template(this.options))
|
||||
.css({
|
||||
width: this.options.width
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
_handleClick: function (event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
var isOpen = this.modelView.get('open');
|
||||
this.modelView.set('open', !isOpen);
|
||||
},
|
||||
|
||||
_onDocumentClick: function (e) {
|
||||
var $el = $(e.target);
|
||||
var $target = $(this.options.target);
|
||||
var isTarget = $el.get(0) === $target.get(0);
|
||||
if (!isTarget && $el.closest('.Dropdown').length === 0) {
|
||||
this.modelView.set({open: false}, {silent: true});
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_keydown: function (event) {
|
||||
if (event.keyCode === 27) {
|
||||
this.modelView.set('open', false);
|
||||
}
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.$el.hide();
|
||||
},
|
||||
|
||||
show: function () {
|
||||
this.$el.css({
|
||||
display: 'block',
|
||||
opacity: 1
|
||||
});
|
||||
},
|
||||
|
||||
open: function (event, target) {
|
||||
// Target
|
||||
var $target = target && $(target) || this.options.target;
|
||||
this.options.target = $target;
|
||||
|
||||
// Positionate
|
||||
var targetPos = $target[this.options.position || 'offset']();
|
||||
var targetWidth = $target.outerWidth();
|
||||
var targetHeight = $target.outerHeight();
|
||||
var elementWidth = this.$el.outerWidth();
|
||||
var elementHeight = this.$el.outerHeight();
|
||||
var verticalPosition = this.options.verticalPosition;
|
||||
var verticalOffset = this.options.verticalOffset;
|
||||
var horizontalPosition = this.options.horizontalPosition;
|
||||
var horizontalOffset = this.options.horizontalOffset;
|
||||
|
||||
this.$el.css({
|
||||
top: targetPos.top + parseInt((verticalPosition === 'up') ? (-elementHeight - 10 - verticalOffset) : (targetHeight + 10 - verticalOffset)),
|
||||
left: targetPos.left + parseInt((horizontalPosition === 'left') ? (horizontalOffset - 15) : (targetWidth - elementWidth + 15 - horizontalOffset))
|
||||
})
|
||||
.addClass(
|
||||
// Add vertical and horizontal position class
|
||||
(verticalPosition === 'up' ? 'vertical_top' : 'vertical_bottom') +
|
||||
' ' +
|
||||
(horizontalPosition === 'right' ? 'horizontal_right' : 'horizontal_left') +
|
||||
' ' +
|
||||
// Add tick class
|
||||
'tick_' + this.options.tick
|
||||
);
|
||||
|
||||
this.show();
|
||||
},
|
||||
|
||||
isOpen: function () {
|
||||
return this.modelView.get('open');
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
const target = $(this.options.target);
|
||||
this.options.target && target.off('click', this._handleClick);
|
||||
$(document).off('keydown', this._keydown);
|
||||
$(document).off('click', this._onDocumentClick);
|
||||
CoreView.prototype.clean.apply(this);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user