802 lines
19 KiB
JavaScript
802 lines
19 KiB
JavaScript
var _ = require('underscore');
|
|
var $ = require('jquery');
|
|
var Ps = require('perfect-scrollbar');
|
|
require('clip-path-polygon');
|
|
var sanitize = require('../../core/sanitize');
|
|
var Template = require('../../core/template');
|
|
var View = require('../../core/view');
|
|
var util = require('../../core/util');
|
|
|
|
var ESC_KEY = 27;
|
|
|
|
/**
|
|
* Usage:
|
|
* var infowindow = new Infowindow({
|
|
* model: infowindowModel,
|
|
* mapView: mapView
|
|
* });
|
|
*
|
|
* // Show the infowindow:
|
|
* infowindow.showInfowindow();
|
|
*/
|
|
|
|
var Infowindow = View.extend({
|
|
options: {
|
|
imageTransitionSpeed: 300,
|
|
hookMargin: 24,
|
|
hookHeight: 16
|
|
},
|
|
|
|
className: 'CDB-infowindow-wrapper',
|
|
|
|
events: {
|
|
// Close bindings
|
|
'click .js-close': '_closeInfowindow',
|
|
// some migrations doesn't have js-close class
|
|
'click .close': '_closeInfowindow',
|
|
'touchstart .js-close': '_closeInfowindow',
|
|
'MSPointerDown .js-close': '_closeInfowindow',
|
|
// Rest infowindow bindings
|
|
'dragstart': '_stopPropagation',
|
|
'mousedown': '_stopPropagation',
|
|
'pointerdown': '_stopPropagation',
|
|
'touchstart': '_stopPropagation',
|
|
'MSPointerDown': '_stopPropagation',
|
|
'dblclick': '_stopPropagation',
|
|
'DOMMouseScroll': 'killEvent',
|
|
'MozMousePixelScroll': 'killEvent',
|
|
'mousewheel': 'killEvent',
|
|
'dbclick': '_stopPropagation',
|
|
'click': '_stopPropagation'
|
|
},
|
|
|
|
initialize: function () {
|
|
this.mapView = this.options.mapView;
|
|
|
|
this._compileTemplate();
|
|
this._initBinds();
|
|
|
|
// Hide the element
|
|
this.$el.hide();
|
|
},
|
|
|
|
/**
|
|
* Render infowindow content
|
|
*/
|
|
render: function () {
|
|
this.clearSubViews();
|
|
this.$el.empty();
|
|
|
|
if (this.template) {
|
|
// Clone fields and template name
|
|
var fields = _.map(this.model.attributes.content.fields, function (field) {
|
|
return _.clone(field);
|
|
});
|
|
|
|
var data = this.model.get('content') ? this.model.get('content').data : {};
|
|
|
|
// Sanitized fields
|
|
fields = _.map(fields, this._sanitizeField, this);
|
|
|
|
// Join plan fields values with content to work with
|
|
// custom infowindows and CartoDB infowindows.
|
|
var values = {};
|
|
|
|
_.each(fields, function (pair) {
|
|
values[pair.name] = pair.value;
|
|
});
|
|
|
|
var obj = _.extend({
|
|
content: {
|
|
fields: fields,
|
|
data: data
|
|
}
|
|
}, values);
|
|
|
|
this.$el.html(
|
|
// sanitize.html(this.template(obj), this.model.get('sanitizeTemplate'))
|
|
sanitize.html(this.template(obj), false)
|
|
);
|
|
|
|
// Set width and max-height from the model only
|
|
// If there is no width set, we don't force our infowindow
|
|
if (this.model.get('width')) {
|
|
this.$('.js-infowindow').css('width', this.model.get('width') + 'px');
|
|
}
|
|
|
|
if (this.model.get('height')) {
|
|
this.$('.js-infowindow').css('height', this.model.get('height') + 'px');
|
|
}
|
|
if (this.model.get('maxHeight')) {
|
|
this._getContent().css('max-height', this.model.get('maxHeight') + 'px');
|
|
}
|
|
|
|
if (this._containsCover()) {
|
|
this._loadCover();
|
|
}
|
|
|
|
if (this._containsVideo()) {
|
|
this._loadVideo();
|
|
}
|
|
|
|
if (this._containsH5url()) {
|
|
this._loadH5url();
|
|
}
|
|
|
|
this._setupClasses();
|
|
this._renderScroll();
|
|
this._renderShadows();
|
|
this._bindScroll();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
// video add
|
|
_containsH5url: function () {
|
|
return !!this.$('.js-infowindow').attr('data-h5url');
|
|
},
|
|
|
|
_loadH5url: function () {
|
|
var url = this._getCoverURL();
|
|
|
|
var $urlsrc = this.$('#mainContent');
|
|
$urlsrc.attr('src', url);
|
|
|
|
},
|
|
|
|
_containsVideo: function () {
|
|
return !!this.$('.js-infowindow').attr('data-video');
|
|
},
|
|
|
|
_loadVideo: function () {
|
|
//this._renderCoverLoader();
|
|
//this._startCoverLoader();
|
|
|
|
var url = this._getCoverURL();
|
|
var $urlsrc = this.$('#target');
|
|
$urlsrc.attr('src', url);
|
|
|
|
/*
|
|
if (this._isLoadingFields()) {
|
|
return;
|
|
}
|
|
|
|
if (!this._isValidVideoURL(url)) {
|
|
this._stopCoverLoader();
|
|
this._showInfowindowVideoError();
|
|
return;
|
|
}
|
|
|
|
if (this._containsTemplateCover()) {
|
|
this._loadCoverFromTemplate(url);
|
|
} else {
|
|
this._loadVideoFromUrl(url);
|
|
}
|
|
*/
|
|
var $urlsrc = this.$('#target');
|
|
$urlsrc.attr('src', url);
|
|
|
|
},
|
|
|
|
_isValidVideoURL: function (url) {
|
|
if (url) {
|
|
var urlPattern = /^(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-|]*[\w@?^=%&\/~+#-])?$/;
|
|
return String(url).match(urlPattern) !== null;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
_showInfowindowVideoError: function () {
|
|
this.$('.js-infowindow').addClass('is-fail');
|
|
this.$('.js-cover').append('<p class="CDB-infowindow-fail">无效的视频网址</p>');
|
|
},
|
|
|
|
_loadVideoFromUrl: function (url) {
|
|
var $urlsrc = this.$('#target');
|
|
|
|
//this._startCoverLoader();
|
|
|
|
$urlsrc.attr('src', url);
|
|
|
|
player = videojs('hls-video');
|
|
|
|
},
|
|
|
|
_onLoadVideoError: function () {
|
|
this._stopCoverLoader();
|
|
this._showInfowindowVideoError();
|
|
},
|
|
|
|
_onLoadVideoSuccess: function () {
|
|
|
|
this._stopCoverLoader();
|
|
|
|
return;
|
|
|
|
/*
|
|
var $cover = this.$('.js-cover');
|
|
var $img = this.$('.CDB-infowindow-media-item');
|
|
var url = $img.attr('src');
|
|
var numFields = this.model.get('content').fields.length;
|
|
|
|
var imageDimensions = { width: $img.width(), height: $img.height() };
|
|
var coverDimensions = { width: $cover.width(), height: $cover.height() };
|
|
|
|
var styles = this._calcImageStyle(imageDimensions, coverDimensions);
|
|
|
|
$img.css(styles);
|
|
|
|
$cover.css({ height: imageDimensions.height - this.options.hookHeight });
|
|
|
|
this._stopCoverLoader();
|
|
|
|
$img.fadeIn(150);
|
|
|
|
if (numFields < 3 && imageDimensions.height >= this.$el.height()) {
|
|
this._loadImageHook(imageDimensions, coverDimensions, url);
|
|
}
|
|
*/
|
|
},
|
|
|
|
// end video
|
|
|
|
_initBinds: function () {
|
|
_.bindAll(this, '_onKeyUp', '_onLoadImageSuccess', '_onLoadImageError', '_onLoadVideoSuccess', '_onLoadVideoError');
|
|
|
|
this.listenTo(this.model, 'change:content change:alternative_names change:width change:maxHeight', this.render, this);
|
|
this.listenTo(this.model, 'change:latlng', this._updateAndAdjustPan, this);
|
|
this.listenTo(this.model, 'change:visibility', this.toggle, this);
|
|
this.listenTo(this.model, 'change:template change:sanitizeTemplate', this._compileTemplate, this);
|
|
|
|
this.listenTo(this.mapView.map, 'change', this._updatePosition, this);
|
|
|
|
this.listenTo(this.mapView, 'zoomstart', function () {
|
|
this.hide(true);
|
|
});
|
|
|
|
this.listenTo(this.mapView, 'zoomend', function () {
|
|
this.show();
|
|
});
|
|
},
|
|
|
|
// migration issue: some infowindows doesn't have this selector
|
|
_getContent: function () {
|
|
var $el = this.$('.js-content');
|
|
if ($el.length === 0) {
|
|
$el = this.$('.cartodb-popup-content');
|
|
}
|
|
|
|
return $el;
|
|
},
|
|
|
|
_onKeyUp: function (event) {
|
|
if (event && event.keyCode === ESC_KEY) {
|
|
this._closeInfowindow();
|
|
}
|
|
},
|
|
|
|
_setupClasses: function () {
|
|
var $infowindow = this.$('.js-infowindow');
|
|
var hasHeader = this.$('.js-header').length;
|
|
var hasCover = this.$('.js-cover').length;
|
|
var hasContent = this._getContent().length;
|
|
var hasTitle = this.$('.CDB-infowindow-title').length;
|
|
var numberOfFields = this.model.get('content') && this.model.get('content').fields.length;
|
|
|
|
if (hasCover) {
|
|
$infowindow
|
|
.addClass('has-header-image')
|
|
.toggleClass('no-content', numberOfFields < 3);
|
|
}
|
|
|
|
if (hasHeader) {
|
|
$infowindow.addClass('has-header');
|
|
}
|
|
|
|
if (hasContent) {
|
|
$infowindow.addClass('has-fields');
|
|
}
|
|
|
|
if (hasTitle) {
|
|
$infowindow.addClass('has-title');
|
|
}
|
|
},
|
|
|
|
_renderScroll: function () {
|
|
if (this._getContent().length === 0) {
|
|
return;
|
|
}
|
|
|
|
this._content = this._getContent().get(0);
|
|
this.$('.js-infowindow').addClass('has-scroll');
|
|
|
|
Ps.initialize(this._content, {
|
|
wheelSpeed: 1,
|
|
wheelPropagation: true,
|
|
minScrollbarLength: 20
|
|
});
|
|
},
|
|
|
|
_renderShadows: function () {
|
|
this.$shadowTop = $('<div>').addClass('CDB-infowindow-canvasShadow CDB-infowindow-canvasShadow--top');
|
|
this.$shadowBottom = $('<div>').addClass('CDB-infowindow-canvasShadow CDB-infowindow-canvasShadow--bottom');
|
|
var $inner = this.$('.js-inner');
|
|
$inner.append(this.$shadowTop);
|
|
$inner.append(this.$shadowBottom);
|
|
_.defer(function () {
|
|
this._showOrHideShadows();
|
|
}.bind(this));
|
|
},
|
|
|
|
_bindScroll: function () {
|
|
this.$(this._content)
|
|
.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));
|
|
},
|
|
|
|
_onScrollTop: function () {
|
|
this.$shadowTop.removeClass('is-visible');
|
|
},
|
|
|
|
_onScroll: function () {
|
|
this._showOrHideShadows();
|
|
},
|
|
|
|
_showOrHideShadows: function () {
|
|
var $el = $(this._content);
|
|
if ($el.length) {
|
|
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);
|
|
}
|
|
},
|
|
|
|
_onScrollBottom: function () {
|
|
this.$shadowBottom.removeClass('is-visible');
|
|
},
|
|
|
|
_container: function () {
|
|
return this.el.querySelector('.js-container');
|
|
},
|
|
|
|
/**
|
|
* Compile template of the infowindow
|
|
*/
|
|
_compileTemplate: function () {
|
|
var template = this.model.get('template');
|
|
|
|
if (typeof (template) !== 'function') {
|
|
this.template = new Template({
|
|
template: template,
|
|
type: this.model.get('template_type') || 'mustache'
|
|
}).asFunction();
|
|
} else {
|
|
this.template = template;
|
|
}
|
|
|
|
this.render();
|
|
},
|
|
|
|
_sanitizeValue: function (key, val) {
|
|
if (_.isObject(val)) {
|
|
return val;
|
|
}
|
|
|
|
return String(val);
|
|
},
|
|
|
|
_sanitizeField: function (attr) {
|
|
// Check null or undefined :| and set both to empty == ''
|
|
if (attr.value === null || attr.value === undefined) {
|
|
attr.value = '';
|
|
}
|
|
|
|
// Get the alternative name
|
|
var alternativeName = this.model.getAlternativeName(attr.name);
|
|
attr.title = (attr.title && alternativeName) ? alternativeName : attr.title;
|
|
|
|
// Save new sanitized value
|
|
attr.value = JSON.parse(JSON.stringify(attr.value), this._sanitizeValue);
|
|
|
|
return attr;
|
|
},
|
|
|
|
/**
|
|
* Does header contain cover?
|
|
*/
|
|
_containsCover: function () {
|
|
return !!this.$('.js-infowindow').attr('data-cover');
|
|
},
|
|
|
|
_containsTemplateCover: function () {
|
|
return this.$('.js-cover img').length > 0;
|
|
},
|
|
|
|
_getCoverURL: function () {
|
|
var content = this.model.get('content');
|
|
var imageSRC = this.$('.js-cover img').attr('src');
|
|
|
|
if (imageSRC) {
|
|
return imageSRC;
|
|
}
|
|
|
|
if (content && content.fields && content.fields.length > 0) {
|
|
return (content.fields[0].value || '').toString();
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
_imageOnHookNotSupported: function () {
|
|
var noCssClipPath = util.ie || util.browser.ie || util.browser.edge;
|
|
return noCssClipPath;
|
|
},
|
|
|
|
_loadImageHook: function (imageDimensions, coverDimensions, url) {
|
|
var $hook = this.$('.CDB-hook');
|
|
if (!$hook) {
|
|
return;
|
|
}
|
|
|
|
if (this._imageOnHookNotSupported()) {
|
|
$hook.hide();
|
|
return;
|
|
}
|
|
|
|
var $hookImage = $('<img />')
|
|
.addClass('CDB-hookImage js-hookImage')
|
|
.attr('src', url);
|
|
|
|
$hook.append($hookImage);
|
|
|
|
$hookImage.css({
|
|
marginTop: -(imageDimensions.height - this.options.hookHeight),
|
|
width: coverDimensions.width,
|
|
display: 'none'
|
|
});
|
|
|
|
$hookImage.load(
|
|
function () {
|
|
$hook.parent().addClass('has-image');
|
|
$hookImage.clipPath(this._getHookPoints(imageDimensions.height - this.options.hookHeight));
|
|
$hookImage.show();
|
|
}.bind(this)
|
|
);
|
|
},
|
|
|
|
_getHookPoints: function (imageHeight) {
|
|
return [
|
|
[24, imageHeight],
|
|
[24, imageHeight + 16],
|
|
[48, imageHeight],
|
|
[24, imageHeight]
|
|
];
|
|
},
|
|
|
|
_loadCoverFromTemplate: function (url) {
|
|
this.$('.js-cover img').remove();
|
|
this._loadCoverFromUrl(url);
|
|
},
|
|
|
|
_loadCoverFromUrl: function (url) {
|
|
var $cover = this.$('.js-cover');
|
|
|
|
this._startCoverLoader();
|
|
|
|
var $img = $("<img class='CDB-infowindow-media-item' />");
|
|
$cover.append($img);
|
|
|
|
$img
|
|
.load(this._onLoadImageSuccess)
|
|
.error(this._onLoadImageError)
|
|
.attr('src', url);
|
|
},
|
|
|
|
_onLoadImageError: function () {
|
|
this._stopCoverLoader();
|
|
this._showInfowindowImageError();
|
|
},
|
|
|
|
_onLoadImageSuccess: function () {
|
|
var $cover = this.$('.js-cover');
|
|
var $img = this.$('.CDB-infowindow-media-item');
|
|
var url = $img.attr('src');
|
|
var numFields = this.model.get('content').fields.length;
|
|
|
|
var imageDimensions = { width: $img.width(), height: $img.height() };
|
|
var coverDimensions = { width: $cover.width(), height: $cover.height() };
|
|
|
|
var styles = this._calcImageStyle(imageDimensions, coverDimensions);
|
|
|
|
$img.css(styles);
|
|
|
|
$cover.css({ height: imageDimensions.height - this.options.hookHeight });
|
|
|
|
this._stopCoverLoader();
|
|
|
|
$img.fadeIn(150);
|
|
|
|
if (numFields < 3 && imageDimensions.height >= this.$el.height()) {
|
|
this._loadImageHook(imageDimensions, coverDimensions, url);
|
|
}
|
|
},
|
|
|
|
_calcImageStyle: function (imageDimensions, coverDimensions) {
|
|
var styles = {};
|
|
|
|
var imageRatio = imageDimensions.height / imageDimensions.width;
|
|
var coverRatio = coverDimensions.height / coverDimensions.width;
|
|
|
|
if (imageDimensions.width > coverDimensions.width && imageDimensions.height > coverDimensions.height) {
|
|
if (imageRatio < coverRatio) {
|
|
styles = { height: coverDimensions.height };
|
|
}
|
|
} else {
|
|
styles = { width: imageDimensions.width };
|
|
}
|
|
|
|
return styles;
|
|
},
|
|
|
|
_loadCover: function () {
|
|
this._renderCoverLoader();
|
|
this._startCoverLoader();
|
|
|
|
var url = this._getCoverURL();
|
|
|
|
if (this._isLoadingFields()) {
|
|
return;
|
|
}
|
|
|
|
if (!this._isValidURL(url)) {
|
|
this._stopCoverLoader();
|
|
this._showInfowindowImageError();
|
|
return;
|
|
}
|
|
|
|
if (this._containsTemplateCover()) {
|
|
this._loadCoverFromTemplate(url);
|
|
} else {
|
|
this._loadCoverFromUrl(url);
|
|
}
|
|
},
|
|
|
|
_isLoadingFields: function () {
|
|
var content = this.model.get('content');
|
|
return !content || (content.fields.length === 1 && content.fields[0].type === 'loading');
|
|
},
|
|
|
|
_renderCoverLoader: function () {
|
|
var $loader = $('<div>').addClass('CDB-Loader js-loader');
|
|
|
|
if (this.$('.js-cover').length > 0) {
|
|
this.$('.js-cover').append($loader);
|
|
}
|
|
},
|
|
|
|
_startCoverLoader: function () {
|
|
this.$('.js-infowindow').addClass('is-loading');
|
|
this.$('.js-loader').addClass('is-visible');
|
|
},
|
|
|
|
_clearInfowindowImageError: function () {
|
|
this.$('.js-infowindow').removeClass('is-fail');
|
|
},
|
|
|
|
_showInfowindowImageError: function () {
|
|
this.$('.js-infowindow').addClass('is-fail');
|
|
this.$('.js-cover').append('<p class="CDB-infowindow-fail">Non-valid picture URL</p>');
|
|
},
|
|
|
|
_stopCoverLoader: function () {
|
|
this.$('.js-infowindow').removeClass('is-loading');
|
|
this.$('.js-loader').removeClass('is-visible');
|
|
},
|
|
|
|
/**
|
|
* Return true if the provided URL is valid
|
|
*/
|
|
_isValidURL: function (url) {
|
|
if (url) {
|
|
var urlPattern = /^(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-|]*[\w@?^=%&\/~+#-])?$/;
|
|
return String(url).match(urlPattern) !== null;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Toggle infowindow visibility
|
|
*/
|
|
toggle: function () {
|
|
if (this.model.get('visibility')) {
|
|
this.show(true);
|
|
} else {
|
|
this.hide();
|
|
}
|
|
},
|
|
|
|
_stopPropagation: function (ev) {
|
|
ev.stopPropagation();
|
|
},
|
|
|
|
/**
|
|
* Close infowindow
|
|
*/
|
|
_closeInfowindow: function (ev) {
|
|
if (ev) {
|
|
ev.preventDefault();
|
|
ev.stopImmediatePropagation();
|
|
}
|
|
if (this.model.get('visibility')) {
|
|
this.model.set('visibility', false);
|
|
}
|
|
|
|
alert("videojs 暂停" );
|
|
},
|
|
|
|
/**
|
|
* Show infowindow (update, pan, etc)
|
|
*/
|
|
show: function (adjustPan) {
|
|
$(document)
|
|
.off('keyup', this._onKeyUp)
|
|
.on('keyup', this._onKeyUp);
|
|
|
|
if (this.model.get('visibility')) {
|
|
this.$el.css({ left: -5000 });
|
|
this._update(adjustPan);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get infowindow visibility
|
|
*/
|
|
isHidden: function () {
|
|
return !this.model.get('visibility');
|
|
},
|
|
|
|
/**
|
|
* Set infowindow to hidden
|
|
*/
|
|
hide: function (force) {
|
|
$(document).off('keyup', this._onKeyUp);
|
|
if (force || !this.model.get('visibility')) this._animateOut();
|
|
|
|
},
|
|
|
|
_updateAndAdjustPan: function () {
|
|
this._update(true);
|
|
},
|
|
|
|
/**
|
|
* Update infowindow
|
|
*/
|
|
_update: function (adjustPan) {
|
|
if (!this.isHidden()) {
|
|
var delay = 0;
|
|
|
|
if (adjustPan) {
|
|
delay = this.adjustPan();
|
|
}
|
|
|
|
this._updatePosition();
|
|
this._animateIn(delay);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Animate infowindow to show up
|
|
*/
|
|
_animateIn: function (delay) {
|
|
if (!util.ie || (util.browser.ie && util.browser.ie.version > 8)) {
|
|
this.$el.css({
|
|
'marginBottom': '-10px',
|
|
'display': 'block',
|
|
'visibility': 'visible',
|
|
opacity: 0
|
|
});
|
|
|
|
this.$el
|
|
.delay(delay)
|
|
.animate({
|
|
opacity: 1,
|
|
marginBottom: 0
|
|
}, 300);
|
|
} else {
|
|
this.$el.show();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Animate infowindow to disappear
|
|
*/
|
|
_animateOut: function () {
|
|
if (!util.ie || (util.browser.ie && util.browser.ie.version > 8)) {
|
|
var self = this;
|
|
this.$el.animate({
|
|
marginBottom: '-10px',
|
|
opacity: '0',
|
|
display: 'block'
|
|
}, 180, function () {
|
|
self.$el.css({visibility: 'hidden'});
|
|
});
|
|
} else {
|
|
this.$el.hide();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adjust pan to show correctly the infowindow
|
|
*/
|
|
// TODO: This can be private
|
|
adjustPan: function () {
|
|
var offset = this.model.get('offset');
|
|
|
|
if (!this.model.get('autoPan') || this.isHidden()) { return; }
|
|
|
|
var containerHeight = this.$el.outerHeight(true) + 15; // Adding some more space
|
|
var containerWidth = this.$el.width();
|
|
var pos = this.mapView.latLngToContainerPoint(this.model.get('latlng'));
|
|
var adjustOffset = {x: 0, y: 0};
|
|
var size = this.mapView.getSize();
|
|
var waitCallback = 0;
|
|
|
|
if (pos.x - offset[0] < 0) {
|
|
adjustOffset.x = pos.x - offset[0] - 10;
|
|
}
|
|
|
|
if (pos.x - offset[0] + containerWidth > size.x) {
|
|
adjustOffset.x = pos.x + containerWidth - size.x - offset[0] + 10;
|
|
}
|
|
|
|
if (pos.y - containerHeight < 0) {
|
|
adjustOffset.y = pos.y - containerHeight - 10;
|
|
}
|
|
|
|
if (pos.y - containerHeight > size.y) {
|
|
adjustOffset.y = pos.y + containerHeight - size.y;
|
|
}
|
|
|
|
if (adjustOffset.x || adjustOffset.y) {
|
|
this.mapView.panBy(adjustOffset);
|
|
waitCallback = 300;
|
|
}
|
|
|
|
return waitCallback;
|
|
},
|
|
|
|
/**
|
|
* Update the position (private)
|
|
*/
|
|
_updatePosition: function () {
|
|
if (this.isHidden()) {
|
|
return;
|
|
}
|
|
|
|
var offset = this.model.get('offset');
|
|
var pos = this.mapView.latLngToContainerPoint(this.model.get('latlng'));
|
|
var left = pos.x - offset[0];
|
|
var size = this.mapView.getSize();
|
|
var bottom = -1 * (pos.y - offset[1] - size.y);
|
|
|
|
this.$el.css({ bottom: bottom, left: left });
|
|
},
|
|
|
|
/**
|
|
* Set visibility infowindow
|
|
*/
|
|
showInfowindow: function () {
|
|
this.model.set('visibility', true);
|
|
}
|
|
});
|
|
|
|
module.exports = Infowindow;
|