Files
2024-11-10 11:11:35 +01:00

1397 lines
47 KiB
JavaScript

/**
* @file GoogleMaps plugin for CKEditor
* Version 3.6.0
* Allows to insert and edit GoogleMaps inside CKEditor with markers, polygons,...
*
* Copyright (C) 2012-16 Alfonso Martínez de Lizarrondo
*
*/
/* global CKEDITOR */
(function() {
'use strict';
// Object that handles the common functions about all the maps
function GoogleMapsHandler(editor) {
this.editor = editor;
// Clean up
editor.on( 'destroy', function() { this.maps = {}; this.editor = null;});
// Object to store a reference to each map
this.maps = {};
// We will use this to track the number of maps that are generated
// This way we know if we must add the Google Script or not.
// We store their names so they are called properly from BuildEndingScript
this.CreatedMapsNames = [];
return this;
}
GoogleMapsHandler.prototype = {
majorVersion : 3,
minorVersion : 6,
isStaticImage: function( node ) {
return node.getAttribute( 'mapnumber' ) || (/^(https?\:)?\/\/maps\.google(apis)?\.com\/(maps\/api\/)?staticmap/).test( node.src );
},
getMap: function( id ) {
return this.maps[id];
},
// Verify that the node is a script generated by this plugin.
detectMapScript: function( script ) {
if ( !/CK googlemaps v(\d)\.(\d+)/.test(script) )
return false;
var version = parseInt(RegExp.$1, 10),
revision = parseInt(RegExp.$2, 10);
if ( version > this.majorVersion || (version == this.majorVersion && revision > this.minorVersion) )
return false;
return true;
},
// Detects both the google script as well as our ending block
// both must be removed and then added later only if necessary
detectGoogleScript: function( script ) {
// Our final script
if (/CK googlemapsEnd v(\d)\.(\d+)/.test(script) ) {
var version = parseInt(RegExp.$1, 10),
revision = parseInt(RegExp.$2, 10);
if ( version > this.majorVersion || (version == this.majorVersion && revision > this.minorVersion) )
return false;
if (version == 2) {
if ( !/script.src\s*=\s*"http:\/\/www\.google\.com\/.*key=(.*?)("|&)/.test(script) )
return false;
}
return true;
}
// Check if it is the Google Maps script (but we don't need the key)
if ( !(/^<script src="http:\/\/maps\.google\.com\/.*key=(.*?)("|&)/).test(script) )
return false;
return true;
},
// This can be called from the dialog
createNew: function() {
var map = new CKEGoogleMap( this.editor );
this.maps[ map.number ] = map;
return map;
},
BuildEndingScript: function() {
var aScript = [],
path = this.editor.config.googleMaps_endScriptPath;
// Empty string: don't insert it at all. It must be inserted in the page template
if (path === '')
return '';
// Not defined: use default path
if (typeof path == 'undefined')
path = this.editor.plugins.googlemaps.path + 'scripts/cke_gmaps_end.js';
aScript.push('\r\n<script type="text/javascript" src="' + path + '">');
aScript.push( '/* CK googlemapsEnd v' + this.majorVersion + '.' + this.minorVersion + ' */' );
aScript.push('</script>');
return aScript.join('');
},
// Function that will test if the divs and images are correctly wrapped
// returns true if it was OK, false if it has modified the DOM
validateDOM: function() {
// if no maps have been used, then exit
var tmpMap, aMaps = [], i, j, imgs, mapId, map, div, img, element,
modified = false,
maps = this.maps;
for (tmpMap in maps)
aMaps.push( tmpMap );
if (aMaps.length === 0)
return true;
var theDoc = this.editor.document.$;
// the user might have moved an img outside its container div.
for (i = 0; i < aMaps.length; i++) {
mapId = aMaps[i];
map = maps[mapId];
img = theDoc.getElementById( mapId );
if ( img ) {
if (img.parentNode.nodeName != 'DIV' || img.parentNode.id != 'd' + map.number) {
modified = true;
map.createDivs( img );
}
map.updateDimensions( img );
} else {
div = theDoc.getElementById( 'd' + mapId );
if (div) {
element = new CKEDITOR.dom.element( div );
element.remove( true );
modified = true;
}
delete maps[ mapId ];
}
}
// Try to check if the container divs have been duplicated (for example by drag&drop)
if ( document.querySelectorAll ) {
for (i = 0; i < aMaps.length; i++) {
mapId = aMaps[i];
var divs = theDoc.querySelectorAll('div#d' + mapId);
if (divs.length <= 1)
continue;
//Ups, there are two or more divs, only one must remain
for (j = divs.length - 1; j >= 0; j--) {
div = divs[j];
imgs = div.getElementsByTagName( 'IMG' );
if ( !imgs || !imgs[0] || imgs[0].id != mapId) {
// If it doesn't have an image inside, remove that div
// but leave whatever it's inside, just in case...
element = new CKEDITOR.dom.element( div );
element.remove( true );
modified = true;
}
}
}
}
return !modified;
}
};
// Our object that will handle parsing of the script and creating the new one.
function CKEGoogleMap( editor ) {
this.editor = editor;
var now = new Date();
this.number = 'gmap' + now.getFullYear() + now.getMonth() + now.getDate() + now.getHours() + now.getMinutes() + now.getSeconds();
this.width = editor.config.googleMaps_Width || 900;
this.height = editor.config.googleMaps_Height || 250;
this.responsive = true; //editor.config.googleMaps_Responsive;
this.centerLat = editor.config.googleMaps_CenterLat || 37.4419;
this.centerLon = editor.config.googleMaps_CenterLon || -122.1419;
this.zoom = editor.config.googleMaps_Zoom || 11;
this.tilt = 0;
this.heading = 0;
this.markerPoints = [];
this.textsData = [];
this.linesData = [];
this.areasData = [];
this.circlesData = [];
this.mapType = 0; // map, satellite, hybrid...
this.generatedType = 3; // 1: only static, 2: static + click to load, 3: load with page, 4: loaded on demand by call to initGmapsLoader
this.kmlOverlay = '';
this.zoomControl = 'Default';
this.mapTypeControl = 'Default';
this.scaleControl = false;
this.overviewMapControl = false;
this.overviewMapControlOpened = true;
this.googleBar = false;
this.weather = false;
this.weatherUsaUnits = editor.config.googleMaps_weatherUsaUnits || false;
this.pathType = 'Default';
this.WrapperClass = editor.config.googleMaps_WrapperClass || '';
this.key = editor.config.googleMaps_ApiKey || '';
}
CKEGoogleMap.prototype.createHtmlElement = function() {
// let's assure that the map exists in the list
this.editor.plugins.googleMapsHandler.maps[ this.number ] = this;
var oFakeNode = this.editor.document.createElement( 'IMG' );
oFakeNode.setAttribute( 'mapnumber', this.number );
oFakeNode.setAttribute( 'id', this.number );
var oDiv = this.editor.document.createElement( 'DIV' );
oDiv.setAttribute( 'id', 'd' + this.number);
if (this.WrapperClass !== '') {
var oWrapper = this.editor.document.createElement( 'DIV' );
oWrapper.setAttribute( 'class', this.WrapperClass );
this.editor.insertElement( oWrapper );
oWrapper.append( oDiv );
} else
this.editor.insertElement( oDiv );
oDiv.append( oFakeNode );
return oFakeNode.$;
};
CKEGoogleMap.prototype.createDivs = function( oFakeNode ) {
var oWrapper,
oDiv = this.editor.document.$.createElement( 'DIV' );
oDiv.setAttribute( 'id', 'd' + this.number);
oFakeNode.parentNode.insertBefore( oDiv, oFakeNode );
if (this.WrapperClass !== '') {
oWrapper = this.editor.document.$.createElement( 'DIV' );
oWrapper.className = this.WrapperClass;
oDiv.parentNode.insertBefore( oWrapper, oDiv );
oWrapper.appendChild( oDiv );
}
oDiv.appendChild( oFakeNode );
};
CKEGoogleMap.prototype.updateHTMLElement = function( oFakeNode ) {
// let's assure that the map exists in the list
this.editor.plugins.googleMapsHandler.maps[ this.number ] = this;
oFakeNode.setAttribute('width', this.width);
oFakeNode.setAttribute('height', this.height);
// Static maps preview :-)
var staticMap = this.generateStaticMap();
oFakeNode.setAttribute( 'src', staticMap);
oFakeNode.setAttribute( 'data-cke-saved-src', staticMap);
oFakeNode.setAttribute( 'alt', '');
if (this.responsive) {
oFakeNode.style.width = '100%';
oFakeNode.style.maxWidth = this.cssWidth();
oFakeNode.style.height = this.height; //'auto';
} else {
oFakeNode.style.width = '';
oFakeNode.style.height = '';
}
};
CKEGoogleMap.prototype.getMapTypeIndex = function( type ) {
return CKEDITOR.tools.indexOf([ 'roadmap', 'satellite', 'hybrid', 'terrain' ], type);
};
CKEGoogleMap.prototype.parseStaticMap = function( oImage ) {
var reStatic = /center=(-?\d+\.\d*),(-?\d+\.\d*)&zoom=(\d+)&size=(\d+)x(\d+)&maptype=(.*?)(?:&markers=(.*?))?(&path=(?:.*?))?/,
markers, paths, result,
reMarks = /(-?\d+\.\d*),(-?\d+\.\d*),(\w+)\|?/g,
reLines = /rgba:0x(\w{6})(\w\w),weight:(\d)(.*?)(&|$)/g;
if (reStatic.test( oImage.src ) ) {
this.generatedType = 1;
this.centerLat = RegExp.$1;
this.centerLon = RegExp.$2;
this.zoom = RegExp.$3;
this.width = oImage.width;
this.height = oImage.height; alert( this.height );
this.mapType = this.getMapTypeIndex(RegExp.$6);
// markers
markers = RegExp.$7;
// paths
paths = RegExp.$8;
while ( (result = reMarks.exec( markers )) ) {
this.markerPoints.push( { lat:result[1], lon:result[2], text:'', color:result[3], title:'', maxWidth:200 } );
}
while ( (result = reLines.exec( paths )) ) {
this.linesData.push( { color:'#' + result[1], opacity:parseInt(result[2], 16) / 255, weight:parseInt(result[3], 10), PointsData:result[4], points:null, text:'', maxWidth:200 } );
}
}
};
CKEGoogleMap.prototype.parseStaticMap2 = function( oImage ) {
var reStatic = /center=(-?\d+\.\d*),(-?\d+\.\d*)&zoom=(\d+)&size=(\d+)x(\d+)&maptype=(\w*?)(&markers=.*?)?(&path=.*?)?&?/,
markers, paths, result, line,
reMarks = /markers=color:(\w*)\|(-?\d+\.\d*),(-?\d+\.\d*)(&|$)/g,
reLines = /path=color:0x(\w{6})(\w\w)\|weight:(\d)\|(fillcolor:0x(\w{6})(\w\w)\|)?enc:(.*?)&pathData=zf:(\d*)\|nl:(\d*)\|lvl:(.*?)(&|$)/g;
if (reStatic.test( oImage.src ) ) {
this.generatedType = 1;
this.centerLat = RegExp.$1;
this.centerLon = RegExp.$2;
this.zoom = RegExp.$3;
this.width = oImage.width;
this.height = oImage.height;
this.mapType = this.getMapTypeIndex(RegExp.$6);
// markers
markers = RegExp.$7;
// paths
paths = RegExp.$8;
while ( (result = reMarks.exec( markers )) ) {
this.markerPoints.push( { lat:result[2], lon:result[3], text:'', color:result[1], title:'', maxWidth:200 } );
}
while ( (result = reLines.exec( paths )) ) {
line = { color:'#' + result[1], opacity:parseInt(result[2], 16) / 255, weight:parseInt(result[3], 10), points:unescape(result[7]) };
if (result[4]) {
//polygons
this.areasData.push( { polylines: [ line ], fill:line.color, color:'#' + result[5], opacity:parseInt(result[6], 16) / 255, text:'', maxWidth:200 } );
} else {
// lines
line.text = '';
line.maxWidth = 200;
this.linesData.push( line );
}
}
} else {
// Static Maps V1
this.parseStaticMap( oImage );
}
};
CKEGoogleMap.prototype.generateStaticMap = function() {
var w = Math.min(this.width, 640),
h = Math.min(this.height, 640),
staticMapTypes = [ 'roadmap', 'satellite', 'hybrid', 'terrain' ];
if (this.panorama) {
var fov = 180 / Math.pow(2, this.panorama.zoom);
return 'https://maps.googleapis.com/maps/api/streetview?location=' + this.panorama.lat + ',' + this.panorama.lng +
'&size=' + w + 'x' + h + '&heading=' + this.panorama.heading + '&pitch=' + this.panorama.pitch + '&fov=' + fov +
'&key=' + this.key;
}
var part1 = 'https://maps.googleapis.com/maps/api/staticmap?center=' + this.centerLat + ',' + this.centerLon +
'&zoom=' + this.zoom + '&size=' + w + 'x' + h +
'&maptype=' + staticMapTypes[ this.mapType ],
part2 = this.generateStaticMarkers(),
part3 = this.generateStaticPaths() +
'&key=' + this.key;
// If the URL is too large Google won't generate the image. Try to trim it using default icons
if ((part1 + part2 + part3).length >= 1950) {
part2 = this.generateStaticMarkers(true);
}
return part1 + part2 + part3;
};
CKEGoogleMap.prototype.generateStaticMarkers = function(shortened) {
if (this.markerPoints.length === 0)
return '';
var i = 0, point,
aPoints = [],
googleMaps_Icons = this.editor.config.googleMaps_Icons;
for (; i < this.markerPoints.length; i++) {
point = this.markerPoints[i];
aPoints.push('&markers=');
// Custom icons
if (!shortened) {
if ( googleMaps_Icons && googleMaps_Icons[ point.color ] ) {
var url = googleMaps_Icons[ point.color ].marker.image;
// avoid linking to localhost or the map generator will return an error
if (/:\/\/.*\..*\//.test( url ))
aPoints.push('icon:' + url);
else
aPoints.push('icon:' + point.color);
} else
aPoints.push('color:' + point.color);
}
aPoints.push('|' + point.lat + ',' + point.lon );
}
return aPoints.join('');
};
CKEGoogleMap.prototype.generateStaticPaths = function() {
function hex(n) {
var h = Math.round(255 * n).toString(16);
if (h.length == 1)
h = '0' + h;
return h;
}
var strings = '', i = 0, line, area;
for (; i < this.linesData.length; i++) {
// transform the color to rgba....
line = this.linesData[i];
strings += '&path=' + 'color:0x' + line.color.replace('#', '') + hex(line.opacity) + '|weight:' + line.weight + '|enc:' + line.points;
}
// Polygons
for (i = 0; i < this.areasData.length; i++) {
area = this.areasData[i];
line = area.polylines[0];
strings += '&path=' + 'color:0x' + line.color.replace('#', '') + hex(line.opacity) + '|weight:' + line.weight + '|fillcolor:0x' + area.color.replace('#', '') + hex(area.opacity) + '|enc:' + line.points;
}
return strings;
};
// Read the dimensions back from the fake node (the user might have manually resized it)
CKEGoogleMap.prototype.updateDimensions = function( oFakeNode ) {
var iWidth, iHeight,
regexSize = /^\s*(\d+)px\s*$/i,
aMatchW, aMatchH;
if ( oFakeNode.style.width ) {
aMatchW = oFakeNode.style.width.match( regexSize );
if ( aMatchW ) {
iWidth = aMatchW[1];
oFakeNode.style.width = '';
oFakeNode.width = iWidth;
}
}
if ( oFakeNode.style.height ) {
aMatchH = oFakeNode.style.height.match( regexSize );
if ( aMatchH ) {
iHeight = aMatchH[1];
oFakeNode.style.height = '';
oFakeNode.height = iHeight;
}
}
this.width = iWidth ? iWidth : oFakeNode.width;
this.height = iHeight ? iHeight : oFakeNode.height;
};
CKEGoogleMap.prototype.decodeText = function(string) {
return string.replace(/<\\\//g, '</').replace(/\\n/g, '').replace(/\\'/g, '\'').replace(/\\"/g, '\"').replace(/\\\\/g, '\\');
};
CKEGoogleMap.prototype.encodeText = function(string) {
return string.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/'/g, '\\\'').replace(/\n/g, '').replace(/<\//g, '<\\/');
};
CKEGoogleMap.prototype.parse = function( script ) {
// Get version info:
if ( !/CK googlemaps v(\d+)\.(\d+)/.test(script) )
return false;
var regexpKml = /google\.maps\.GeoXml\("([^"]*?)"\)/ ,
majorVersion = parseInt(RegExp.$1, 10) ,
minorVersion = parseInt(RegExp.$2, 10) ,
regexpId = /dMap\s=\sdocument\.getElementById\("(.*?)"\)/ ,
regexpWidth = /dMap\.style\.width\s=\s"(.*?)"/ ,
regexpHeight = /dMap\.style\.height\s=\s"(.*?)"/ ,
regexpType = /\/(?:\/|\*)generatedType = (\d)/ ,
maxWidth ,
regexpPosition = /map\.setCenter\(new google\.maps\.LatLng\((-?\d{1,3}\.\d{1,6}),(-?\d{1,3}\.\d{1,6})\), (\d{1,2})\);/ ,
markerText, markerLat = 0, markerLon = 0 ,
regexpText = /var text\s*=\s*("|')(.*)\1;\s*\n/ ,
regexpDimensions = /<div id="(.*)" style="width\:\s*(\d+)px; height\:\s*(\d+)px;/ ,
regexpMarker = /var point\s*=\s*new GLatLng\((-?\d{1,3}\.\d{1,6}),(-?\d{1,3}\.\d{1,6})\)/, // v< 1.5
regexpMarkers = /\{lat\:(-?\d{1,3}\.\d{1,6}),\s*lon\:(-?\d{1,3}\.\d{1,6}),\s*text\:("|')(.*?)\3(?:,\s*color:"(.*?)"(?:,\s*title:"(.*?)"(?:,\s*maxWidth:(\d+))?)?)?}(?:,|])/g ,
linePoints = '' ,
lineLevels = '' ,
regexpLinePoints = /var encodedPoints\s*=\s*("|')(.*)\1;\s*\n/ ,
regexpLineLevels = /var encodedLevels\s*=\s*("|')(.*)\1;\s*\n/ ,
color = 'red' ,
title = '' ,
regexpLines = /\{color\:'(.*)',\s*weight:(\d+),\s*opacity:(-?\d\.\d{1,2}),\s*points\:'(.*?)',\s*levels\:'(.*?)',\s*zoomFactor:(\d+),\s*numLevels:(\d+),\s*text\:'(.*?)'(?:,\s*maxWidth:(\d+))?}(?:,|])/g ,
regexpAreas = /\{polylines:\s*\[\{color\:'(.*)',\s*opacity:(-?\d\.\d{1,2}),\s*weight:(\d+),\s*points\:'(.*)',\s*levels\:'(.*)',\s*zoomFactor:(\d+),\s*numLevels:(\d+)\}\],\s*fill:(.*),\s*color:'(.*)',\s*opacity:(-?\d\.\d{1,2}),\s*outline:(.*?),\s*text\:'(.*?)'(?:,\s*maxWidth:(\d+))?\}(?:,|])/g ,
lines = [] ,
regexpTexts = /\{lat\:(-?\d{1,3}\.\d{1,6}),\s*lon\:(-?\d{1,3}\.\d{1,6}),\s*title\:"(.*?)",\s*className:"(.*?)"}(?:,|])/g,
result;
var handler = this.editor.plugins.googleMapsHandler;
if (majorVersion > 3)
return false;
if (majorVersion > 2)
regexpKml = /AddKml\("([^"]*)"\)/;
if (majorVersion >= 3 && minorVersion >= 3)
regexpMarkers = /\{lat\:(-?\d{1,3}\.\d{1,6}),\s*lon\:(-?\d{1,3}\.\d{1,6}),\s*text\:("|')(.*?)\3,\s*color:"(.*?)",\s*title:"(.*?)",\s*maxWidth:(\d+),\s*open:(\d)}(?:,|])/g ;
// dimensions:
// document.writeln('<div id="gmap1" style="width: 544px; height: 350px;">.</div>');
if (majorVersion < 2) {
if (regexpDimensions.test( script ) ) {
delete handler.maps[this.number];
this.number = RegExp.$1;
handler.maps[this.number] = this;
this.width = RegExp.$2;
this.height = RegExp.$3;
}
} else {
// var dMap = document.getElementById("gmap200893233020");
// dMap.style.width = "300px";
// dMap.style.height = "200px";
if (regexpId.test( script ) ) {
delete handler.maps[this.number];
this.number = RegExp.$1;
handler.maps[this.number] = this;
}
if (regexpWidth.test( script ) ) {
this.width = RegExp.$1.replace(/px$/, '');
//if (this.width == '100%')
this.responsive = true;
}
if (regexpHeight.test( script ) )
this.height = RegExp.$1.replace(/px$/, '');
if (regexpType.test( script ) )
this.generatedType = RegExp.$1;
}
// map.setCenter(new GLatLng(42.4298,-8.07756), 8);
if (majorVersion == 1)
regexpPosition = /map\.setCenter\(new GLatLng\((-?\d{1,3}\.\d{1,6}),(-?\d{1,3}\.\d{1,6})\), (\d{1,2})\);/;
if (regexpPosition.test( script ) ) {
this.centerLat = RegExp.$1;
this.centerLon = RegExp.$2;
this.zoom = RegExp.$3;
}
// v <= 1.5
if (majorVersion == 1 && minorVersion <= 5 ) {
// var text = 'En O Carballino ha estado la d\'elegacion diplomatica japonesa';
if (regexpText.test( script ) ) {
markerText = RegExp.$2;
}
// var point = new GLatLng(42.4298,-8.07756);
if (regexpMarker.test( script ) ) {
markerLat = RegExp.$1;
markerLon = RegExp.$2;
}
if (markerLat !== 0 && markerLon !== 0)
this.markerPoints.push( { lat:markerLat, lon:markerLon, text:this.decodeText(markerText), color:'red', title:'' } );
} else {
// v > 1.5. multiple points.
// AddMarkers( [{lat:37.45088, lon:-122.21123, text:'Write your text'}] );
while ( (result = regexpMarkers.exec(script)) ) {
maxWidth = 200;
var opened = false;
if (result[5])
color = result[5];
if (result[6])
title = result[6];
if (result[7])
maxWidth = result[7];
if (result[8])
opened = result[8] == '1';
this.markerPoints.push( { lat:result[1], lon:result[2], text:this.decodeText(result[4]), color:color, title:this.decodeText(title), maxWidth:maxWidth, open:opened } );
}
// Texts v>=2.1
while ( (result = regexpTexts.exec(script)) ) {
this.textsData.push( { lat:result[1], lon:result[2], title:this.decodeText(result[3]), className:this.decodeText(result[4]) } );
}
}
if (majorVersion == 1) {
// Notify back to parser that it must insert an img
this.requiresImage = true;
if (regexpLinePoints.test( script ) )
linePoints = RegExp.$2;
if (regexpLineLevels.test( script ) )
lineLevels = RegExp.$2;
if (linePoints !== '' && lineLevels !== '') {
this.linesData.push({ color:'#3333cc', weight:5, opacity:0.45, points:linePoints, text:'', maxWidth:200 });
}
} else {
// V2: multiple lines and areas.
// aLines.push('{color:\'' + line.color + '\', weight:' + line.weight + ', points:\'' + line.points + '\', levels:\'' + line.levels + '\'}');
// }
// aScript.push(' AddLines( map, [' + aLines.join(',\r\n') + '] );');
if (majorVersion < 3 || (majorVersion == 3 && minorVersion === 0)) {
while ( (result = regexpLines.exec(script)) ) {
maxWidth = 200;
if (result[9])
maxWidth = result[9];
this.linesData.push( { color:result[1], weight:result[2], opacity:result[3], points:this.decodeText(result[4]) } );
}
// only one line in each area
// we reverse the opacity and weight to be able to avoid parsing them as normal polylines
// AddAreas( map, [{polylines: [{color:'#008000', opacity:0.7, weight:2, points:'iatcFnzrhVpfA{nOtuExkJnd@ffOwbIecJ', levels:'BBBBB'}], fill: true, color:'#008000', opacity:0.2, outline:true}] );
while ( (result = regexpAreas.exec(script)) ) {
lines = [ { color:result[1], weight:parseInt(result[3],10), opacity:parseFloat(result[2]), points:this.decodeText(result[4]) } ];
maxWidth = 200;
if (result[13])
maxWidth = parseInt(result[13], 10);
this.areasData.push( { polylines: lines, fill:true, color:result[9], opacity:parseFloat(result[10]) } );
}
} else {
if (majorVersion == 3 && minorVersion < 6) {
// withouth levels, zoomfactor and numLevels params, but always with maxWidth
regexpLines = /\{color\:("|')(.*)\1,\s*weight:(\d+),\s*opacity:(-?\d\.\d{1,2}),\s*points\:("|')(.*?)\5,\s*text\:("|')(.*?)\7,\s*maxWidth:(\d+)}(?:,|])/g ;
regexpAreas = /\{polylines:\s*\[\{color\:("|')(.*)\1,\s*opacity:(-?\d\.\d{1,2}),\s*weight:(\d+),\s*points\:("|')(.*)\5}\],\s*fill:(.*),\s*color:("|')(.*)\8,\s*opacity:(-?\d\.\d{1,2}),\s*text\:("|')(.*?)\11,\s*maxWidth:(\d+)\}(?:,|])/g ;
while ( (result = regexpLines.exec(script)) ) {
this.linesData.push( { color:result[2], weight:parseInt(result[3],10), opacity:parseFloat(result[4]), points:this.decodeText(result[6]) } );
}
while ( (result = regexpAreas.exec(script)) ) {
lines = [ { color:result[2], opacity:parseFloat(result[3]), weight:parseInt(result[4],10), points:this.decodeText(result[6]) } ];
this.areasData.push( { polylines:lines, color:result[9], opacity:parseFloat(result[10]) } );
}
} else {
regexpLines = /\{color\:"(.*)",\s*weight:(\d+),\s*opacity:(-?\d\.\d{1,2}),\s*points\:"(.*?)"}(?:,|])/g ;
while ( (result = regexpLines.exec(script)) ) {
this.linesData.push( { color:result[1], weight:parseInt(result[2],10), opacity:parseFloat(result[3]), points:this.decodeText(result[4]) } );
}
regexpAreas = /\{polylines:\s*\[\{color\:"(.*)",\s*opacity:(-?\d\.\d{1,2}),\s*weight:(\d+),\s*points\:"(.*)"}\],\s*color:"(.*)",\s*opacity:(-?\d\.\d{1,2})\}(?:,|])/g ;
while ( (result = regexpAreas.exec(script)) ) {
lines = [ { color:result[1], opacity:parseFloat(result[2]), weight:parseInt(result[3],10), points:this.decodeText(result[4]) } ];
this.areasData.push( { polylines:lines, color:result[5], opacity:parseFloat(result[6]) } );
}
var regexpCircles = /\{lat\:(-?\d{1,3}\.\d{1,6}),\s*lon\:(-?\d{1,3}\.\d{1,6}),radius:(\d+),color\:"(.*)",\s*weight:(\d+),\s*opacity:(-?\d\.\d{1,2}),\s*fillColor:"(.*)",\s*fillOpacity:(-?\d\.\d{1,2})\}(?:,|])/g ;
while ( (result = regexpCircles.exec(script)) ) {
this.circlesData.push( { lat:result[1], lon:result[2], radius:parseInt(result[3], 10), color:result[4], weight:parseInt(result[5],10), opacity:parseFloat(result[6]), fillColor:result[7], fillOpacity:parseFloat(result[8]) } );
}
// panorama
var regexpPanorama = /panorama:\{lat:(-?\d{1,3}\.\d+),lng:(-?\d{1,3}\.\d+),pov1:(\d+\.?\d*),pov2:(\d+\.?\d*),pov3:(\d+\.?\d*)\}/;
if (regexpPanorama.test( script ) ) {
var panorama = {};
panorama.lat = parseFloat(RegExp.$1);
panorama.lng = parseFloat(RegExp.$2);
panorama.heading = parseFloat(RegExp.$3);
panorama.pitch = parseFloat(RegExp.$4);
panorama.zoom = parseFloat(RegExp.$5);
this.panorama = panorama;
}
}
}
}
// 1.8 mapType
// map.setMapType( allMapTypes[ 1 ] );
if (/setMapType\([^\[]*\[\s*(\d+)\s*\]\s*\)/.test( script ) ) {
this.mapType = RegExp.$1;
}
// 1.9 wrapper div with custom class
if ( majorVersion == 1 && minorVersion >= 9 ) {
if (/<div class=("|')(.*)\1.*\/\/wrapper/.test( script ) )
this.WrapperClass = RegExp.$2;
else
this.WrapperClass = '';
}
if (regexpKml.test( script ) ) {
this.kmlOverlay = RegExp.$1;
}
// controls:
if ( majorVersion == 2 ) {
if (/google\.maps\.(.*)\(\)\);\/\*zoom\*\//.test( script ) )
this.zoomControl = RegExp.$1;
else
this.zoomControl = '';
if (/google\.maps\.(.*)\(\)\);\/\*type\*\//.test( script ) )
this.mapTypeControl = RegExp.$1;
else
this.mapTypeControl = '';
this.overviewMapControl = script.indexOf('OverviewMapControl') >= 0;
this.scaleControl = script.indexOf('ScaleControl') >= 0;
this.googleBar = script.indexOf('enableGoogleBar') >= 0;
// Remap them to v3:
switch (this.zoomControl) {
case 'SmallZoomControl':
this.zoomControl = 'Small';
break;
case 'SmallMapControl':
this.zoomControl = 'Small';
break;
case 'LargeMapControl':
this.zoomControl = 'Full';
break;
default:
this.zoomControl = 'None';
break;
}
switch (this.mapTypeControl) {
case 'MapTypeControl':
this.mapTypeControl = 'Full';
break;
case 'HierarchicalMapTypeControl':
this.mapTypeControl = 'Menu';
break;
default:
this.mapTypeControl = 'None';
break;
}
}
// controls:
if ( majorVersion == 3 ) {
/*
var mapOptions = {
zoom: 7,
center: [42.7228,-1.72485],
mapType: 0,
zoomControl: 'Full',
mapsControl: 'Menu',
overviewMapControl: false,
scaleControl: false,
googleBar: false
};
*/
if (/center:\s*\[(-?\d{1,3}\.\d{1,6}),(-?\d{1,3}\.\d{1,6})\],/.test( script ) ) {
this.centerLat = RegExp.$1;
this.centerLon = RegExp.$2;
}
if (/zoom: (\d{1,2}),/.test( script ) )
this.zoom = parseInt(RegExp.$1, 10);
if (/mapType: (\d{1,2}),/.test( script ) )
this.mapType = parseInt(RegExp.$1, 10);
// old
if (/navigationControl: "(.*?)",/.test( script ) )
this.zoomControl = RegExp.$1;
if (/zoomControl: "(.*?)",/.test( script ) )
this.zoomControl = RegExp.$1;
if (/mapsControl: "(.*?)",/.test( script ) )
this.mapTypeControl = RegExp.$1;
if (/overviewMapControl: (.*?),/.test( script ) )
this.overviewMapControl = RegExp.$1 == 'true';
if (/overviewMapControlOptions: \{opened:(.*?)\},/.test( script ) )
this.overviewMapControlOpened = RegExp.$1 == 'true';
if (/scaleControl: (.*?),/.test( script ) )
this.scaleControl = RegExp.$1 == 'true';
if (/traffic: (.*?),/.test( script ) ) {
if (RegExp.$1 == 'true')
this.pathType = 'Traffic';
}
if (/transit: (.*?),/.test( script ) ) {
if (RegExp.$1 == 'true')
this.pathType = 'Transit';
}
if (/pathType: "(.*?)",/.test( script ) )
this.pathType = RegExp.$1;
if (/weather: (.*?),/.test( script ) )
this.weather = RegExp.$1 == 'true';
if (/weatherUsaUnits: (.*?),/.test( script ) )
this.weatherUsaUnits = RegExp.$1 == 'true';
// last one without trailing comma
if (/googleBar: (.*?)\n/.test( script ) )
this.googleBar = RegExp.$1 == 'true';
if (/heading: (\d{1,3}),/.test( script ) )
this.heading = parseInt(RegExp.$1, 10);
if (/tilt: (\d{1,2}),/.test( script ) )
this.tilt = parseInt(RegExp.$1, 10);
// extra icons
if ( minorVersion >= 3 ) {
if (!this.editor.config.googleMaps_Icons)
this.editor.config.googleMaps_Icons = {};
var reIcons = /googleMaps_Icons\["(.*?)"\] = ({.*?});/g;
while ( (result = reIcons.exec(script)) ) {
// Simulate that it was included in the config:
this.editor.config.googleMaps_Icons[ result[1] ] = JSON.parse( result[2] );
}
}
}
return true;
};
// fixme: allow %
CKEGoogleMap.prototype.cssWidth = function() {
if (/\d+\D+/.test(this.width))
return this.width;
return this.width + 'px';
};
CKEGoogleMap.prototype.cssHeight = function() {
if (/\d+\D+/.test(this.height))
return this.height;
return this.height + 'px';
};
CKEGoogleMap.prototype.BuildScript = function() {
var handler = this.editor.plugins.googleMapsHandler,
aScript = [], i,
aPoints = [], point,
aTexts = [],
aLines = [], line,
aAreas = [], area, areaLine,
aCircles = [], circle;
aScript.push('\r\n<script type="text/javascript">');
aScript.push('/*<![CDATA[*/');
aScript.push( '/* CK googlemaps v' + handler.majorVersion + '.' + handler.minorVersion + ' */' );
aScript.push('var imgMap = document.getElementById("' + this.number + '"),');
aScript.push(' dMap = document.createElement("div"),');
aScript.push(' canvas = document.createElement("canvas"),');
aScript.push(' dGMap = imgMap.parentNode;');
aScript.push('dMap.id="w' + this.number + '";');
aScript.push('dGMap.insertBefore( dMap, imgMap);');
aScript.push('dMap.appendChild(imgMap);');
aScript.push('if (dGMap.style.textAlign == "center") dGMap.style.margin="0 auto";');
if (this.responsive) {
aScript.push('dGMap.style.maxWidth = "' + this.cssWidth() + '";');
aScript.push('dGMap.insertBefore( canvas, dMap);');
aScript.push('canvas.style.width = "100%";');
aScript.push('canvas.style.height = "auto";');
aScript.push('canvas.width = "' + this.width + '";');
aScript.push('canvas.height = "' + this.height + '";');
aScript.push('dMap.style.width = "100%";');
aScript.push('dMap.style.height = "100%";');
aScript.push('dMap.style.left = 0;');
aScript.push('dMap.style.top = 0;');
aScript.push('dMap.style.position = "absolute";');
aScript.push('dGMap.style.position = "relative";');
} else {
aScript.push('dMap.style.width = "' + this.cssWidth() + '";');
aScript.push('dMap.style.height = "' + this.cssHeight() + '";');
}
aScript.push('var generatedType = ' + this.generatedType + ';');
aScript.push('if (generatedType==3 && navigator.userAgent.indexOf("Mobile")>0) generatedType=2;');
aScript.push('if (generatedType==2) {');
//aScript.push('dMap.style.position = "relative";');
aScript.push('dMap.style.cursor = "pointer";');
aScript.push('dMap.onclick = function(e) {initGmapsLoader(e||event)};');
aScript.push('var t = document.createTextNode("' + this.editor.lang.googlemaps.clickToLoad + '"),');
aScript.push(' d = document.createElement("div");');
aScript.push('d.appendChild(t);');
aScript.push('d.style.cssText="background-color:#e5e5e5; filter:alpha(opacity=80); opacity:0.8; padding:1em; font-weight:bold; text-align:center; position:absolute; left:0; box-sizing:border-box; width:100%; max-width:' + this.width + 'px; top:0";');
aScript.push('dMap.appendChild(d);');
aScript.push('}');
aScript.push('function CreateGMap' + this.number + '() {');
aScript.push(' var dMap = document.getElementById("' + this.number + '");');
aScript.push(' if (dMap) ');
aScript.push(' dMap = dMap.parentNode;');
aScript.push(' else ');
aScript.push(' dMap = document.getElementById("w' + this.number + '");');
aScript.push(' if (!dMap) return;');
aScript.push(' if (dMap.ckemap) {');
aScript.push(' var map = dMap.ckemap.map, center = map.getCenter();');
aScript.push(' google.maps.event.trigger(map, "resize");');
aScript.push(' map.setCenter(center);');
aScript.push(' return; ');
aScript.push(' } ');
aScript.push(' dMap.onclick = null;');
aScript.push(' var mapOptions = {');
aScript.push(' zoom: ' + this.zoom + ',');
aScript.push(' center: [' + this.centerLat + ',' + this.centerLon + '],');
aScript.push(' mapType: ' + this.mapType + ',' );
aScript.push(' zoomControl: "' + this.zoomControl + '",' );
aScript.push(' mapsControl: "' + this.mapTypeControl + '",' );
aScript.push(' heading: ' + this.heading + ',');
aScript.push(' tilt: ' + this.tilt + ',');
if (this.overviewMapControl) aScript.push(' overviewMapControl: ' + this.overviewMapControl + ',' );
if (this.overviewMapControlOpened) aScript.push(' overviewMapControlOptions: {opened:' + this.overviewMapControlOpened + '},' );
if (this.scaleControl) aScript.push(' scaleControl: ' + this.scaleControl + ',' );
if (this.weather) aScript.push(' weather: ' + this.weather + ',' );
if (this.weatherUsaUnits) aScript.push(' weatherUsaUnits: ' + this.weatherUsaUnits + ',' );
aScript.push(' pathType: "' + this.pathType + '",' );
aScript.push(' googleBar: ' + this.googleBar );
if (this.panorama) {
var pan = this.panorama;
aScript.push(', panorama:{' +
'lat:' + pan.lat + ',' +
'lng:' + pan.lng + ',' +
'pov1:' + pan.heading + ',' +
'pov2:' + pan.pitch + ',' +
'pov3:' + pan.zoom + '' +
'}');
}
aScript.push(' };');
aScript.push(' var myMap = new CKEMap(dMap, mapOptions);');
aScript.push(' dMap.ckemap=myMap;');
var googleMaps_Icons = this.editor.config.googleMaps_Icons,
usedIcons = {};
if (this.markerPoints.length) {
for (i = 0; i < this.markerPoints.length; i++) {
point = this.markerPoints[i];
aPoints.push('{lat:' + point.lat + ', lon:' + point.lon + ', text:\"' + this.encodeText(point.text) + '\",color:\"' + point.color +
'\", title:\"' + this.encodeText(point.title) + '\", maxWidth:' + point.maxWidth + ', open:' + (point.open ? 1 : 0) + '}');
if ( googleMaps_Icons && googleMaps_Icons[ point.color ] )
usedIcons[ point.color ] = googleMaps_Icons[ point.color ];
}
aScript.push(' myMap.AddMarkers( [' + aPoints.join(',\r\n') + '] );');
}
if (this.textsData.length) {
for (i = 0; i < this.textsData.length; i++) {
point = this.textsData[i];
aTexts.push('{lat:' + point.lat + ', lon:' + point.lon + ', title:\"' + this.encodeText(point.title) + '\", className:\"' + this.encodeText(point.className) + '\"}');
}
aScript.push(' myMap.AddTexts( [' + aTexts.join(',\r\n') + '] );');
}
if (this.linesData.length) {
for (i = 0; i < this.linesData.length; i++) {
line = this.linesData[i];
aLines.push('{color:\"' + line.color + '\", weight:' + line.weight + ', opacity:' + line.opacity + ', points:\"' + this.encodeText(line.points) + '\"}');
}
aScript.push(' myMap.AddLines( [' + aLines.join(',\r\n') + '] );');
}
if (this.areasData.length) {
for (i = 0; i < this.areasData.length; i++) {
area = this.areasData[i];
areaLine = area.polylines[0];
aAreas.push('{polylines: [{color:"' + areaLine.color + '", opacity:' + areaLine.opacity + ', weight:' + areaLine.weight + ', points:"' + this.encodeText(areaLine.points) + '"}], color:"' + area.color + '", opacity:' + area.opacity + '}');
}
aScript.push(' myMap.AddAreas( [' + aAreas.join(',\r\n') + '] );');
}
if (this.circlesData.length) {
for (i = 0; i < this.circlesData.length; i++) {
circle = this.circlesData[i];
aCircles.push('{lat:' + circle.lat + ',lon:' + circle.lon + ',radius:' + circle.radius + ',color:"' + circle.color + '",weight:' + circle.weight + ',opacity:' + circle.opacity + ',fillColor:"' + circle.fillColor + '",fillOpacity:' + circle.fillOpacity + '}');
}
aScript.push(' myMap.AddCircles( [' + aCircles.join(',\r\n') + '] );');
}
if (this.kmlOverlay)
aScript.push(' myMap.AddKml("' + this.kmlOverlay + '");');
aScript.push('}');
aScript.push('');
if ( !CKEDITOR.tools.isEmpty( usedIcons ) ) {
aScript.push('if (!window.googleMaps_Icons) window.googleMaps_Icons = {};');
for ( var iconName in usedIcons ) {
if ( usedIcons.hasOwnProperty( iconName ) ) {
aScript.push('window.googleMaps_Icons["' + iconName + '"] = ' + JSON.stringify( usedIcons[ iconName ] ) + ';');
}
}
}
aScript.push('if (!window.gmapsLoaders) window.gmapsLoaders = [];');
aScript.push('window.gmapsLoaders.push(CreateGMap' + this.number + ');');
aScript.push('if (generatedType==3)');
aScript.push(' window.gmapsAutoload=true;');
if (this.linesData.length || this.areasData.length)
aScript.push('window.gmapsGeometry=true;');
if (this.weather)
aScript.push('window.gmapsWeather=true;');
if (this.key)
aScript.push('window.gmapsKey="' + this.key + '";');
aScript.push('/*]]>*/');
aScript.push('</script>');
return aScript.join('\r\n');
};
CKEDITOR.plugins.add( 'googlemaps', {
requires : [ 'dialog' ],
// translations
lang : 'en,ar,cs,de,el,es,fi,fr,it,nl,pl,ru,sk,tr',
icons: 'googlemaps,gmapsinsertdirections', // %REMOVE_LINE_CORE%
init : function( editor ) {
editor.plugins.googleMapsHandler = new GoogleMapsHandler( editor );
// Add buttons.
var allowed = 'div[id];img[id,src,style];script';
if (editor.config.googleMaps_WrapperClass)
allowed += ';div(' + editor.config.googleMaps_WrapperClass + ')';
editor.addCommand( 'googlemaps', new CKEDITOR.dialogCommand( 'googlemaps', {
allowedContent: allowed,
requiredContent: 'script'
} ) );
editor.ui.addButton( 'GoogleMaps', {
label : editor.lang.googlemaps.toolbar,
command : 'googlemaps',
icon : this.path + 'icons/googlemaps.png', // %REMOVE_LINE_CORE%
toolbar : 'insert'
} );
CKEDITOR.dialog.add( 'googlemaps', this.path + 'dialogs/googlemaps.js' );
CKEDITOR.dialog.add( 'googlemapsMarker', this.path + 'dialogs/marker.js' );
CKEDITOR.dialog.add( 'googlemapsIcons', this.path + 'dialogs/icons.js' );
CKEDITOR.dialog.add( 'googlemapsText', this.path + 'dialogs/text.js' );
CKEDITOR.dialog.add( 'googlemapsLine', this.path + 'dialogs/line.js' );
CKEDITOR.dialog.add( 'googlemapsArea', this.path + 'dialogs/area.js' );
// If the "menu" plugin is loaded, register the menu items.
if ( editor.addMenuItems ) {
editor.addMenuItems(
{
googlemaps :
{
label : editor.lang.googlemaps.menu,
icon : this.path + 'icons/googlemaps.png', // %REMOVE_LINE_CORE%
command : 'googlemaps',
group : 'image',
order : 1
}
});
}
// If the "contextmenu" plugin is loaded, register the listeners.
if ( editor.contextMenu ) {
// check the image
// We put our listener as the first item
// The aim of this listener is to mark the images as "fake", but only while the context menu is displayed
editor.contextMenu._.listeners.unshift( function( element ) {
if ( !element || !element.is( 'img' ) || !editor.plugins.googleMapsHandler.isStaticImage( element.$ ) )
return null;
// Set here the trick
element.data( 'cke-realelement', '1' );
return null;
});
editor.contextMenu.addListener( function( element ) {
if ( !element || !element.is( 'img' ) || !editor.plugins.googleMapsHandler.isStaticImage( element.$ ) )
return null;
// Now we clear it
element.data( 'cke-realelement', false );
// And say that this context menu item must be shown
return { googlemaps : CKEDITOR.TRISTATE_ON };
});
}
// Open our dialog on double click
editor.on( 'doubleclick', function( evt ) {
var element = evt.data.element;
if ( element.is( 'img' ) && editor.plugins.googleMapsHandler.isStaticImage( element.$ ) ) {
evt.data.dialog = 'googlemaps';
// evt.stop();
}
}, null, null, 20); // after the default options
// patch for #13481
var initialZindex;
editor.on( 'beforeCommandExec', function( evt ) {
if (evt.data.name != 'maximize')
return;
if (!initialZindex)
initialZindex = editor.config.baseFloatZIndex;
// Only the first time to get the initial value
evt.removeListener();
} );
editor.on( 'afterCommandExec', function( evt ) {
if (evt.data.name != 'maximize')
return;
if (evt.data.command.state == CKEDITOR.TRISTATE_ON)
editor.config.baseFloatZIndex = initialZindex * 2;
else
editor.config.baseFloatZIndex = initialZindex;
} );
// end patch for #13481
},
afterInit : function(editor) {
// We need to control if the scripts must be added or removed
processScriptOutput(editor);
// Expand the editor to provide controlled dialogs.
editor.openNestedDialog = function( dialogName, callbackOpen, callbackOK ) {
var onOk = function() {
releaseHandlers( this );
if (callbackOK)
callbackOK( this );
};
var onCancel = function() {
releaseHandlers( this );
};
var releaseHandlers = function( dialog ) {
dialog.removeListener( 'ok', onOk );
dialog.removeListener( 'cancel', onCancel );
};
var bindToDialog = function( dialog ) {
dialog.on( 'ok', onOk );
dialog.on( 'cancel', onCancel );
if (callbackOpen)
callbackOpen( dialog );
};
if ( editor._.storedDialogs[ dialogName ])
bindToDialog( editor._.storedDialogs[ dialogName ] );
else {
CKEDITOR.on( 'dialogDefinition', function( e ) {
if ( e.data.name != dialogName )
return;
var definition = e.data.definition;
e.removeListener();
if (typeof definition.onLoad == 'function') {
definition.onLoad = CKEDITOR.tools.override( definition.onLoad, function( original ) {
return function() {
definition.onLoad = original;
if ( typeof original == 'function' )
original.call( this );
bindToDialog( this );
};
} );
} else {
definition.onLoad = function() {
bindToDialog( this );
};
}
});
}
editor.openDialog( dialogName );
};
// Workaround for #9060
if (CKEDITOR.env.ie) {
CKEDITOR.dialog.prototype.hide = CKEDITOR.tools.override( CKEDITOR.dialog.prototype.hide , function( originalFunction ) {
return function() {
var parent = this._.parentDialog;
originalFunction.call( this );
if (parent && this._.editor != parent._.editor) {
if ( this._.editor.mode == 'wysiwyg' ) {
var selection = this._.editor.getSelection();
if (selection)
selection.unlock( true );
}
}
};
});
}
}
});
// Adjust the output
function processScriptOutput( editor ) {
var dataProcessor = editor.dataProcessor,
htmlFilter = dataProcessor && dataProcessor.htmlFilter,
dataFilter = dataProcessor && dataProcessor.dataFilter,
handler = editor.plugins.googleMapsHandler;
// Avoid that our images are upcasted to widgets
editor.on( 'toHtml', function( evt ) {
evt.data.dataValue.forEach( function( element ) {
// find images and if they belong to us, set an attribute to avoid the conversion by image2
if (element.name == 'img') {
var id = element.attributes['id'];
if (id && (/^gmap\d+$/).test(id))
element.attributes['data-cke-realelement'] = 'googlemap';
else {
var parent = element.parent;
if (parent && parent.name == 'div') {
id = parent.attributes['id'];
if (id && (/^dgmap\d+$/).test(id)) {
element.attributes['data-cke-realelement'] = 'googlemap';
}
}
}
}
});
// lower priority than the widget system
}, null, null, 5);
// dataFilter : conversion from html input to internal data
dataFilter.addRules(
{
comment : function( contents ) {
// Check if they are part of our scripts. Parse them and remove from the content.
var protectedSourceMarker = '{cke_protected}';
if (contents.substr(0, protectedSourceMarker.length) == protectedSourceMarker) {
var data = contents.substr( protectedSourceMarker.length );
data = decodeURIComponent( data );
if ( handler.detectMapScript( data ) ) {
var oMap = handler.createNew();
if (oMap.parse( data ) ) {
if (oMap.requiresImage) {
// Insert an image with the map data
return new CKEDITOR.htmlParser.element( 'img',
{
id: oMap.number,
mapnumber: oMap.number,
src: oMap.generateStaticMap(),
width: oMap.width,
height: oMap.height
} );
}
return false;
}
} else {
if ( handler.detectGoogleScript( data ) )
return false;
}
}
return contents;
},
elements :
{
'img' : function(element) {
var id = element.attributes['id'];
if (id && (/^gmap\d+$/).test(id))
element.attributes['mapnumber'] = id;
else {
var parent = element.parent;
if (parent && parent.name == 'div') {
id = parent.attributes['id'];
if (id && (/^dgmap\d+$/).test(id)) {
element.attributes['id'] = element.attributes['mapnumber'] = id.substr(1);
}
}
}
if (element.attributes['data-cke-realelement'] && element.attributes['data-cke-realelement'] == 'googlemap') {
delete element.attributes['data-cke-realelement'];
}
},
'div' : function(element) {
// Readjust previous ids.
var id = element.attributes['id'];
if (id && (/^gmap\d+$/).test(id)) {
element.attributes[ 'id' ] = 'd' + id;
}
}
}
}
);
// htmlFilter : conversion from internal data to html output.
htmlFilter.addRules(
{
elements :
{
'img' : function( element ) {
var number = element.attributes.mapnumber;
if (number) {
var scriptNode,
handler = editor.plugins.googleMapsHandler,
oMap = handler.getMap( number );
if (oMap && oMap.generatedType > 1) {
handler.CreatedMapsNames.push( oMap.number );
// Inject the <script> for this map
scriptNode = new CKEDITOR.htmlParser.cdata( oMap.BuildScript() );
element.parent.children.push( scriptNode );
}
delete element.attributes.mapnumber;
}
return element;
}
}
}, { applyToAll: true } );
dataProcessor.toDataFormat = CKEDITOR.tools.override( dataProcessor.toDataFormat , function( originalFunction ) {
return function( html, fixForBody ) {
// Check if we need to include or not the global maps building script
var handler = editor.plugins.googleMapsHandler;
handler.CreatedMapsNames = [];
// Validate that everything is properly nested and there aren't left-over divs.
if (!handler.validateDOM()) {
var config = editor.config,
fullPage = config.fullPage,
doc = editor.document;
// Get the new HTML
html = fullPage ? doc.getDocumentElement().getOuterHtml() : doc.getBody().getHtml();
}
var Result = originalFunction.call(this, html, fixForBody);
if (handler.CreatedMapsNames.length > 0)
Result += handler.BuildEndingScript();
return Result;
};
});
}
/*
Compatibility between CKEditor 3 and 4
*/
if (CKEDITOR.skins) {
CKEDITOR.plugins.setLang = CKEDITOR.tools.override( CKEDITOR.plugins.setLang , function( originalFunction ) {
return function( plugin, lang, obj ) {
if (plugin != 'devtools' && typeof obj[plugin] != 'object') {
var newObj = {};
newObj[ plugin ] = obj;
obj = newObj;
}
originalFunction.call(this, plugin, lang, obj);
};
});
}
})();