cartodb/lib/assets/javascripts/deep-insights/dashboard-sidebar-view.js
2020-06-15 10:58:47 +08:00

197 lines
5.5 KiB
JavaScript

var _ = require('underscore');
var $ = require('jquery');
var Ps = require('perfect-scrollbar');
var CoreView = require('backbone/core-view');
var CategoryContentView = require('./widgets/category/content-view');
var FormulaContentView = require('./widgets/formula/content-view');
var HistogramContentView = require('./widgets/histogram/content-view');
var WidgetViewFactory = require('./widgets/widget-view-factory');
var template = require('./dashboard-sidebar.tpl');
var matchMedia = window.matchMedia;
module.exports = CoreView.extend({
className: 'CDB-Widget-canvas',
initialize: function (options) {
this._widgetViewFactory = new WidgetViewFactory([
{
type: 'formula',
createContentView: function (widgetModel) {
return new FormulaContentView({
model: widgetModel
});
}
}, {
type: 'histogram',
createContentView: function (widgetModel) {
return new HistogramContentView({
model: widgetModel
});
}
}, {
type: 'category',
createContentView: function (widgetModel) {
return new CategoryContentView({
model: widgetModel
});
}
}
]);
this._widgets = options.widgets;
this._widgets.bind('add', this._maybeRenderWidgetView, this);
this._widgets.bind('reset', this.render, this);
this._widgets.bind('orderChanged', this.render, this);
this._widgets.bind('change:collapsed', this._onWidgetUpdate, this);
this._widgets.bind('add remove reset', this._onWidgetsChange, this);
this.add_related_model(this._widgets);
this._resizeHandler = this._onResize.bind(this);
},
render: function () {
this._cleanScroll();
this._observer && this._observer.disconnect();
this.clearSubViews();
this.$el.html(template());
this.$el.toggleClass('CDB-Widget-canvas--withMenu', this.model.get('renderMenu'));
this._widgets.each(this._maybeRenderWidgetView, this);
this._toggleVisiblity();
this._renderScroll();
this._renderShadows();
this._bindScroll();
this._initResize();
return this;
},
_initResize: function () {
var breakpoints = ['(max-width: 1600px)', '(max-width: 1280px)', '(max-width: 759px)'];
breakpoints.forEach(function (breakpoint) {
var mq = matchMedia(breakpoint);
mq.addListener(this._resizeHandler);
}, this);
},
_updateScrollCss: function () {
this._onWidgetUpdate();
var element = this._container();
if (!element) return;
var containerWidth = element.clientWidth;
var containerHeight = element.clientHeight;
var contentWidth = element.scrollWidth;
var contentHeight = element.scrollHeight;
var xScroll = containerWidth < contentWidth;
var yScroll = containerHeight < contentHeight;
this._$container().toggleClass('hasXScroll', xScroll);
this._$container().toggleClass('hasYScroll', yScroll);
},
_$container: function () {
return $(this._container());
},
_container: function () {
return this.el.querySelector('.js-container');
},
_maybeRenderWidgetView: function (widgetModel) {
var view = this._widgetViewFactory.createWidgetView(widgetModel);
if (view) {
this.addView(view);
this._$container().append(view.render().el);
}
},
_bindScroll: function () {
this._$container()
.on('ps-y-reach-start', _.bind(this._onScrollTop, this))
.on('ps-y-reach-end', _.bind(this._onScrollBottom, this))
.on('ps-scroll-y', _.bind(this._onScroll, this));
},
_renderScroll: function () {
Ps.initialize(this._container(), {
wheelSpeed: 1,
wheelPropagation: false,
swipePropagation: true,
stopPropagationOnClick: false,
minScrollbarLength: 20,
useBothWheelAxes: true
});
},
_onWidgetUpdate: function () {
Ps.update(this._container());
},
_renderShadows: function () {
this.$shadowTop = $('<div>').addClass('CDB-Widget-canvasShadow CDB-Widget-canvasShadow--top');
this.$shadowBottom = $('<div>').addClass('CDB-Widget-canvasShadow CDB-Widget-canvasShadow--bottom');
this.$el.append(this.$shadowTop);
this.$el.append(this.$shadowBottom);
},
_onScrollTop: function () {
this.$shadowTop.removeClass('is-visible');
},
_onScroll: function () {
var $el = this._$container();
var currentPos = $el.scrollTop();
var max = $el.get(0).scrollHeight;
var height = $el.outerHeight();
var maxPos = max - height;
this.$shadowTop.toggleClass('is-visible', currentPos > 0);
this.$shadowBottom.toggleClass('is-visible', currentPos < maxPos);
},
_updateScroll: function () {
this._$container().scrollLeft = 0;
this._$container().scrollTop = 0;
},
_onResize: function (mediaQuery) {
// we don't use mediaQuery.matches
// trigger actions always if breakpoints changes
this._updateScroll();
this._onScroll();
},
_onScrollBottom: function () {
this.$shadowBottom.removeClass('is-visible');
},
_cleanScroll: function () {
$(window).off('resize', this._resizeHandler);
if (this._container()) {
this._$container().off('ps-scroll-y');
Ps.destroy(this._container());
}
},
_toggleVisiblity: function () {
this.$el.toggle(!_.isEmpty(this._subviews));
},
_onWidgetsChange: function () {
this._toggleVisiblity();
this.render();
},
clean: function () {
this._cleanScroll();
this._observer && this._observer.disconnect();
CoreView.prototype.clean.call(this);
}
});