cartodb/lib/assets/javascripts/dashboard/components/dropdown/dropdown-base-view.js
2020-06-15 10:58:47 +08:00

137 lines
3.6 KiB
JavaScript

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);
}
});