cartodb-4.42/lib/assets/javascripts/cartodb/table/export_image_view.js

435 lines
12 KiB
JavaScript
Raw Normal View History

2024-04-06 13:25:13 +08:00
/**
* Generate export image view
*
*/
cdb.admin.ExportImageView = cdb.core.View.extend({
className: 'ExportImageView',
events: {
'click .js-ok': '_ok',
'click .js-format': '_openFormatDropdow',
'dblclick .js-format': 'killEvent',
'click .js-advanced': '_openAdvancedExport',
'click .js-close': '_close',
'dblclick input': 'killEvent',
'click input': 'killEvent',
'keyup input': '_onKeyUp'
},
_MIN_WIDTH: 520,
_DEFAULT_MARGIN: 45,
_DEFAULT_MIN_WIDTH: 480,
defaults: {
clean_on_hide: true,
top: 60,
left: 60,
horizontalMargin: 90,
verticalMargin: 130,
title: "",
description: "",
show_title: false,
show_description: false,
template_name: 'table/views/export_image_view',
modal_class: 'static_image_dialog'
},
initialize: function() {
_.bindAll(this, "_onResizeWindow", "_onChangeDimensions", "_onImageCallback", "_onAdvancedImageCallback", "_keydown", "_onDrag", "_onResize", "_updateHelpers");
$(document).bind('keydown', this._keydown);
$(window).on('resize', this._onResizeWindow);
this.bind("clean", this._reClean);
this.map = this.options.map;
this.vis = this.options.vis;
this.mapOverlays = this.options.overlays;
this.header = this.mapOverlays.getHeaderOverlay();
this.auhtTokens = this.options.authTokens;
this.vis.bind("change:name", this._onChangeVisName, this);
this.vis.bind("change:description", this._onChangeVisDescription, this);
_.extend(this.options, this.defaults, {
attribution: this.vis.map.get("attribution"),
legend: $('.cartodb-map .cartodb-legend-stack').html()
});
if (this.header) {
_.extend(this.options, this.header.attributes);
}
this.width = this.options.width - this.options.horizontalMargin;
this.height = this.options.height - this.options.verticalMargin;
this.model = new cdb.core.Model({
format: 'png',
x: this.options.left,
y: this.options.top,
width: this.width,
height: this.height
});
this.model.bind("change:format", this._onChangeFormat, this);
this.model.bind("change:x change:y change:width change:height", this._onChangeDimensions, this);
this.constructor.__super__.initialize.apply(this);
},
render: function() {
this.template_base = cdb.templates.getTemplate(this.options.template_name);
this.$el.append(this.template_base(_.extend({}, this.options, { width: this.width, height: this.height })));
this._setupCanvas();
this._hideOverlays();
this._updateHelpers(this.options.left, this.options.top, this.width, this.height);
return this;
},
_getMarkdown: function(content) {
content = cdb.Utils.stripHTML(content);
content = markdown.toHTML(content);
content = cdb.Utils.stripHTML(content, '<a><i><em><strong><b><u><s>');
content = content.replace(/&#39;/g, "'"); // replaces single quote
return cdb.core.sanitize.html(content);
},
_onResizeWindow: function(e) {
if (e.target === window) {
this._onChangeDimensions();
}
},
_onChangeVisName: function() {
this.$(".js-title").text(this.vis.get("name"));
},
_onChangeVisDescription: function() {
this.$(".js-description").html(this._getMarkdown(this.vis.get("description")));
},
_setupCanvas: function() {
this.$(".CanvasExport").resizable({
resize: this._onResize,
containment: this.options.mapView.$el,
handles: "n, e, s, w, ne, se, sw, nw"
});
this.$(".CanvasExport").draggableOverlay({
drag: this._onDrag,
container: this.options.mapView.$el
});
this.$(".CanvasExport").css({
top: this.options.top,
left: this.options.left,
width: this.width,
height: this.height
});
},
_showOverlays: function() {
$(".map-options").show();
$(".leaflet-control-attribution").show();
$(".cartodb-map .cartodb-legend-stack").show();
if (this._legendsHidden) {
this.options.vis.map.set("legends", true);
this._legendsHidden = false;
}
this.mapOverlays.overlays.each(function(overlay) {
var type = overlay.get("type");
if (type !== "zoom" && type !== "loader" && type !== "annotation" && type !== "text" && type !== "image") {
overlay.set("display", true);
}
}, this);
},
_hideOverlays: function() {
$(".map-options").hide();
$(".leaflet-control-attribution").hide();
$(".cartodb-map .cartodb-legend-stack").hide();
if (this.options.vis.map.get("legends")) {
this.options.vis.map.set("legends", false);
this._legendsHidden = true;
}
this.mapOverlays.overlays.each(function(overlay) {
var type = overlay.get("type");
if (type !== "zoom" && type !== "loader" && type !== "annotation" && type !== "text" && type !== "image") {
overlay.set("display", false);
}
}, this);
},
_updateHelpers: function(x, y, width, height) {
var canvasWidth = this.options.mapView.$el.width();
var canvasHeight = this.options.mapView.$el.height();
this.$(".CanvasExport").css({ height: height, width: width });
this.$el.toggleClass("is-small", width <= this._MIN_WIDTH);
if (x >= 0 && y >= 0) {
this.$(".js-helper-north").css({ top: 0, width: x + width + 1, height: y + 1});
this.$(".js-helper-west").css({ left: 0, top: y + 1, width: x + 1, height: height});
this.$(".js-helper-south").css({ top: y + height + 1, left: 0, width: canvasWidth, height: canvasHeight - height + y });
this.$(".js-helper-east").css({ left: x + width + 1, top: 0, width: canvasWidth - width, height: y + height + 1});
}
var isTop = y < this._DEFAULT_MARGIN;
var isBottom = y + height + this._DEFAULT_MARGIN > canvasHeight;
this.$(".CanvasExport").toggleClass('is-small', isTop && width < this._DEFAULT_MIN_WIDTH);
this.$(".CanvasExport").toggleClass('is-top', isTop);
this.$(".CanvasExport").toggleClass('is-bottom', isBottom);
},
_onChangeFormat: function() {
this.$(".js-formatName").text('.' + this.model.get("format"));
},
_onChangeDimensions: function() {
var width = this.model.get("width");
var height = this.model.get("height");
var x = this.model.get("x");
var y = this.model.get("y");
if (this.dropdown) {
this.dropdown.hide();
}
this._updateHelpers(x, y, width, height);
this.$(".js-width").val(width);
this.$(".js-height").val(height);
},
_onDrag: function() {
var width = this.$(".CanvasExport").width();
var height = this.$(".CanvasExport").height();
var x = this.$(".CanvasExport").position().left;
var y = this.$(".CanvasExport").position().top;
this.model.set({ x: x, y: y, width: width, height: height });
},
_onResize: function(e, ui) {
var width = ui.helper.width();
var height = ui.helper.height();
var x = ui.helper.position().left;
var y = ui.helper.position().top;
this.model.set({ x: x, y: y, width: width, height: height });
},
_keydown: function(e) {
if (e.keyCode === 27) this._cancel();
},
_calcCenter: function() {
var x = this.model.get("x") + this.model.get("width") / 2;
var y = this.model.get("y") + this.model.get("height") / 2;
return this.options.mapView.pixelToLatLon([x, y]);
},
_isHTTPS: function() {
return location.protocol.indexOf("https") === 0;
},
_onImageCallback: function(error, url) {
if (error && error.errors) {
cdb.editor.ViewFactory.createDialogByTemplate('common/templates/fail', { msg: error.errors })
.render().appendToBody();
return;
}
var view = new cdb.editor.ExportImageResultView({
vis: this.vis,
clean_on_hide: true,
enter_to_confirm: false,
user: this.options.user,
format: this.model.get('format'),
x: this.model.get('x'),
y: this.model.get('y'),
width: this.model.get('width'),
height: this.model.get('height')
});
view.bind("finish", this._cancel, this);
view.appendToBody();
view.generateImage(url);
},
_close: function(e) {
this.killEvent(e);
this._cancel();
},
_openFormatDropdow: function(e) {
this.killEvent(e);
this.dropdown = new cdb.admin.ExportImageFormatsDropdown({
target: this.$(".js-format"),
model: this.model,
speedIn: 150,
speedOut: 150,
vertical_position: 'up',
horizontal_offset: 3,
tick: 'center'
});
this.addView(this.dropdown);
this.dropdown.render();
this.dropdown.open(e);
},
_openAdvancedExport: function(e) {
var width = this.model.get("width");
var height = this.model.get("height");
var view = new cdb.editor.AdvancedExportView({
mapView: this.options.mapView,
clean_on_hide: true,
enter_to_confirm: false,
user: this.options.user,
format: this.model.get('format'),
x: this.$(".CanvasExport").position().left,
y: this.$(".CanvasExport").position().top,
width: width,
height: height
});
view.appendToBody();
view.bind("generate_image", this._onAdvancedImageGeneration, this);
this._close();
},
_onAdvancedImageGeneration: function(options) {
this.url = this.options.vizjson;
var width = options.width;
var height = options.height;
var format = options.format;
var authTokens = this.options.authTokens;
var bounds = [];
bounds.push([options.bounds[0][1], options.bounds[0][0]]);
bounds.push([options.bounds[1][1], options.bounds[1][0]]);
cdb.Image(this.url, { https: this._isHTTPS(), auth_tokens: authTokens })
.size(width, height)
.bbox(bounds)
.format(format)
.getUrl(this._onAdvancedImageCallback);
},
_onAdvancedImageCallback: function(error, url) {
if (error && error.errors) {
cdb.editor.ViewFactory.createDialogByTemplate('common/templates/fail', { msg: error.errors })
.render().appendToBody();
return;
}
var view = new cdb.editor.ExportImageResultView({
vis: this.vis,
clean_on_hide: true,
enter_to_confirm: false
});
view.bind("finish", this._cancel, this);
view.appendToBody();
view.loadURL(url);
},
_ok: function(e) {
this.killEvent(e);
this.url = this.options.vizjson;
var center = this._calcCenter();
var width = this.model.get("width");
var height = this.model.get("height");
var authTokens = this.options.authTokens;
cdb.Image(this.url, { https: this._isHTTPS(), auth_tokens: authTokens })
.format(this.model.get('format'))
.size(width, height)
.center([center.lat, center.lng])
.zoom(this.map.get('zoom'))
.getUrl(this._onImageCallback);
},
_onKeyUp: function(e) {
this.killEvent(e);
var property = "width";
var value = +$(e.target).val();
if ($(e.target).hasClass("js-height")) {
property = "height";
}
if (e.keyCode === $.ui.keyCode.UP) {
value++;
} else if (e.keyCode === $.ui.keyCode.DOWN) {
value--;
}
if (property === 'height') {
var top = this.$(".CanvasExport").position().top;
var canvasHeight = this.options.mapView.$el.height();
if (top + value > canvasHeight) {
value = canvasHeight - top;
this.$(".js-height").val(value);
}
} else {
var left = this.$(".CanvasExport").position().left;
var canvasWidth = this.options.mapView.$el.width();
if (left + value > canvasWidth) {
value = canvasWidth - left;
this.$(".js-width").val(value);
}
}
if (_.isNumber(value)) {
this.model.set(property, value);
}
},
_cancel: function(e) {
this.killEvent(e);
this._showOverlays();
this.hide();
},
hide: function() {
this.trigger("was_removed", this);
this.$el.hide();
this.clean();
},
clean: function() {
$(document).unbind('keydown', this._keydown);
$(window).off("resize", this._onResizeWindow);
this.elder('clean');
},
open: function() {
this.$el.show();
}
});