| Current File : /home/jvzmxxx/wiki1/extensions/Kartographer/modules/ve-maps/ve.ce.MWMapsNode.js |
/*!
* VisualEditor ContentEditable MWMapsNode class.
*
* @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org
*/
/**
* ContentEditable paragraph node.
*
* @class
* @extends ve.ce.MWBlockExtensionNode
* @mixins ve.ce.ResizableNode
*
* @constructor
* @param {ve.dm.MWMapsNode} model Model to observe
* @param {Object} [config] Configuration options
*/
ve.ce.MWMapsNode = function VeCeMWMaps( model, config ) {
config = config || {};
// Parent constructor
ve.ce.MWMapsNode.super.apply( this, arguments );
// Mixin constructors
ve.ce.ResizableNode.call( this, this.$element, config );
this.$imageLoader = null;
this.geoJson = null;
this.updateGeoJson = $.debounce( 300, $.proxy( this.updateGeoJson, this ) );
// Events
this.model.connect( this, { attributeChange: 'onAttributeChange' } );
this.connect( this, { focus: 'onMapFocus' } );
// Ensure we have the styles to render the map node
mw.loader.using( 'ext.kartographer' );
// DOM changes
this.$element
.empty()
.addClass( 've-ce-mwMapsNode' )
.css( this.model.getCurrentDimensions() );
};
/* Inheritance */
OO.inheritClass( ve.ce.MWMapsNode, ve.ce.MWBlockExtensionNode );
OO.mixinClass( ve.ce.MWMapsNode, ve.ce.ResizableNode );
/* Static Properties */
ve.ce.MWMapsNode.static.name = 'mwMaps';
ve.ce.MWMapsNode.static.tagName = 'div';
ve.ce.MWMapsNode.static.primaryCommandName = 'mwMaps';
/* Methods */
/**
* A map requires interactive rendering
*
* Maps without GeoJSON can be rendered as static
*
* @return {boolean} Maps requires interactive rendering
*/
ve.ce.MWMapsNode.prototype.requiresInteractive = function () {
var mwData = this.model.getAttribute( 'mw' );
return mwData.body.extsrc;
};
/**
* Update the rendering of the 'align', src', 'width' and 'height' attributes
* when they change in the model.
*
* @method
* @param {string} key Attribute key
* @param {string} from Old value
* @param {string} to New value
*/
ve.ce.MWMapsNode.prototype.onAttributeChange = function () {
this.update();
};
/**
* @inheritdoc
*/
ve.ce.MWMapsNode.prototype.onSetup = function () {
ve.ce.MWMapsNode.super.prototype.onSetup.call( this );
this.update();
};
/**
* Update the map rendering
*/
ve.ce.MWMapsNode.prototype.update = function () {
var requiresInteractive = this.requiresInteractive(),
align = ve.getProp( this.model.getAttribute( 'mw' ), 'attrs', 'align' ) ||
( this.model.doc.getDir() === 'ltr' ? 'right' : 'left' ),
alignClasses = {
left: 'floatleft',
center: 'center',
right: 'floatright'
};
if ( requiresInteractive ) {
if ( !this.map && this.getRoot() ) {
mw.loader.using( 'ext.kartographer.live' ).then( this.setupMap.bind( this ) );
} else if ( this.map ) {
this.map.invalidateSize();
this.updateGeoJson();
}
} else {
if ( this.map ) {
// Node was previously interactive
this.map.remove();
this.map = null;
}
this.updateStatic();
$( '<img>' ).attr( 'src', this.model.getUrl( 1000, 1000 ) );
}
this.$element
.removeClass( 'floatleft center floatright' )
.addClass( alignClasses[ align ] );
};
/**
* Setup an interactive map
*/
ve.ce.MWMapsNode.prototype.setupMap = function () {
var mwData = this.model.getAttribute( 'mw' ),
mwAttrs = mwData && mwData.attrs,
latitude = +mwAttrs.latitude,
longitude = +mwAttrs.longitude,
zoom = +mwAttrs.zoom;
this.map = mw.kartographer.createMap( this.$element[ 0 ], {
latitude: latitude,
longitude: longitude,
zoom: zoom
// TODO: Support style editing
} );
this.updateGeoJson();
// Disable interaction
this.map.dragging.disable();
this.map.touchZoom.disable();
this.map.doubleClickZoom.disable();
this.map.scrollWheelZoom.disable();
this.map.keyboard.disable();
};
/**
* Update the GeoJSON layer from the current model state
*/
ve.ce.MWMapsNode.prototype.updateGeoJson = function () {
var mwData = this.model.getAttribute( 'mw' ),
geoJson = mwData && mwData.body.extsrc;
if ( geoJson !== this.geoJson ) {
mw.kartographer.updateKartographerLayer( this.map, mwData && mwData.body.extsrc );
this.geoJson = geoJson;
}
};
/**
* Update the static rendering
*/
ve.ce.MWMapsNode.prototype.updateStatic = function ( width, height ) {
var url, node = this;
if ( !this.model.getCurrentDimensions().width ) {
return;
}
if ( this.$imageLoader ) {
this.$imageLoader.off();
this.$imageLoader = null;
}
url = this.model.getUrl( width, height );
this.$imageLoader = this.$( '<img>' ).on( 'load', function () {
node.$element.css( 'backgroundImage', 'url(' + url + ')' );
} ).attr( 'src', url );
};
/**
* @inheritdoc ve.ce.ResizableNode
*/
ve.ce.MWMapsNode.prototype.onResizableResizing = function () {
// Mixin method
ve.ce.ResizableNode.prototype.onResizableResizing.apply( this, arguments );
if ( !this.requiresInteractive() ) {
this.updateStatic( 1000, 1000 );
} else if ( this.map ) {
this.map.invalidateSize();
}
};
/**
* @inheritdoc ve.ce.ResizableNode
*/
ve.ce.MWMapsNode.prototype.getAttributeChanges = function ( width, height ) {
var mwData = ve.copy( this.model.getAttribute( 'mw' ) );
mwData.attrs.width = width.toString();
mwData.attrs.height = height.toString();
return { mw: mwData };
};
/**
* Handle focus events
*/
ve.ce.MWMapsNode.prototype.onMapFocus = function () {
$( '<img>' ).attr( 'src', this.model.getUrl( 1000, 1000 ) );
};
/* Registration */
ve.ce.nodeFactory.register( ve.ce.MWMapsNode );