/* GoogleMaps Plugin for FCKeditor Dialog plugin to handle insertion and modification of Google Maps in FCKeditor File Author: Alfonso Martinez de Lizarrondo amla70 at gmail dot com version 1.98 See readme.html */ // Check that the Google key is defined if ( typeof( FCKConfig.GoogleMaps_Key ) != 'string') { alert( 'Error.\r\nThe configuration doesn\'t contain the Google Maps key.\r\n' + 'Please read the Configuration section.') ; window.open(FCKPlugins.Items['googlemaps'].Path + 'docs/' + FCKLang.GMapsHelpFile + '#configure'); } // If it's empty automatically remove the button from any toolbar. if ( !FCKConfig.GoogleMaps_Key || FCKConfig.GoogleMaps_Key.length === 0) { for( var name in FCKConfig.ToolbarSets ) RemoveButtonFromToolbarSet( FCKConfig.ToolbarSets[name], 'googlemaps' ) ; } /** Helper function It does remove a button from an toolbarset. It's better than leaving it disabled as it will avoid questions about why some button is always disabled. */ function RemoveButtonFromToolbarSet(ToolbarSet, CommandName) { if (!ToolbarSet) return; for ( var x = 0 ; x < ToolbarSet.length ; x++ ) { var oToolbarItems = ToolbarSet[x] ; // If the configuration for the toolbar is missing some element or has any extra comma // this item won't be valid, so skip it and keep on processing. if ( !oToolbarItems ) continue ; if ( typeof( oToolbarItems ) == 'object' ) { for ( var j = 0 ; j < oToolbarItems.length ; j++ ) { if ( oToolbarItems[j] == CommandName) { oToolbarItems.splice(j, 1); ToolbarSet[x] = oToolbarItems ; return; } } } } } // Toolbar button // Register the related command. FCKCommands.RegisterCommand( 'googlemaps', new FCKDialogCommand( 'googlemaps', FCKLang.DlgGMapsTitle, FCKPlugins.Items['googlemaps'].Path + 'dialog/googleMaps.html', 450, 428 ) ) ; // Create the "googlemaps" toolbar button. var oGoogleMapsButton = new FCKToolbarButton( 'googlemaps', FCKLang.GMapsBtn, FCKLang.GMapsBtnTooltip) ; oGoogleMapsButton.IconPath = FCKPlugins.Items['googlemaps'].Path + 'images/mapIcon.gif' ; FCKToolbarItems.RegisterItem( 'googlemaps', oGoogleMapsButton ) ; // Detection of existing maps /** FCKCommentsProcessor --------------------------- It's run after a document has been loaded, it detects all the protected source elements In order to use it, you add your comment parser with FCKCommentsProcessor.AddParser( function ) */ if (typeof FCKCommentsProcessor === 'undefined') { var FCKCommentsProcessor = FCKDocumentProcessor.AppendNew() ; FCKCommentsProcessor.ProcessDocument = function( oDoc ) { if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG ) return ; if ( !oDoc ) return ; //Find all the comments: //try to choose the best approach according to the browser: if ( oDoc.evaluate ) this.findCommentsXPath( oDoc ); else { if (oDoc.all) this.findCommentsIE( oDoc.body ) ; else this.findComments( oDoc.body ) ; } } FCKCommentsProcessor.findCommentsXPath = function(oDoc) { var nodesSnapshot = oDoc.evaluate('//body//comment()', oDoc.body, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ); for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ ) { this.parseComment( nodesSnapshot.snapshotItem(i) ) ; } } FCKCommentsProcessor.findCommentsIE = function(oNode) { var aComments = oNode.getElementsByTagName( '!' ); for(var i=aComments.length-1; i >=0 ; i--) { var comment = aComments[i] ; if (comment.nodeType == 8 ) // oNode.COMMENT_NODE) this.parseComment( comment ) ; } } // Fallback function, iterate all the nodes and its children searching for comments. FCKCommentsProcessor.findComments = function( oNode ) { if (oNode.nodeType == 8 ) // oNode.COMMENT_NODE) { this.parseComment( oNode ) ; } else { if (oNode.hasChildNodes()) { var children = oNode.childNodes ; for (var i = children.length-1; i >=0 ; i--) this.findComments( children[ i ] ); } } } // We get a comment node // Check that it's one that we are interested on: FCKCommentsProcessor.parseComment = function( oNode ) { var value = oNode.nodeValue ; // Difference between 2.4.3 and 2.5 var prefix = ( FCKConfig.ProtectedSource._CodeTag || 'PS\\.\\.' ) ; var regex = new RegExp( "\\{" + prefix + "(\\d+)\\}", "g" ) ; if ( regex.test( value ) ) { var index = RegExp.$1 ; var content = FCKTempBin.Elements[ index ] ; // Now call the registered parser handlers. var oCalls = this.ParserHandlers ; if ( oCalls ) { for ( var i = 0 ; i < oCalls.length ; i++ ) oCalls[ i ]( oNode, content, index ) ; } } } /** The users of the object will add a parser here, the callback function gets two parameters: oNode: it's the node in the editorDocument that holds the position of our content oContent: it's the node (removed from the document) that holds the original contents index: the reference in the FCKTempBin of our content */ FCKCommentsProcessor.AddParser = function( handlerFunction ) { if ( !this.ParserHandlers ) this.ParserHandlers = [ handlerFunction ] ; else { // Check that the event handler isn't already registered with the same listener // It doesn't detect function pointers belonging to an object (at least in Gecko) if ( this.ParserHandlers.IndexOf( handlerFunction ) == -1 ) this.ParserHandlers.push( handlerFunction ) ; } } } /** END of FCKCommentsProcessor --------------------------- */ // Check if the comment it's one of our scripts: var GoogleMaps_CommentsProcessorParser = function( oNode, oContent, index) { if ( FCK.GoogleMapsHandler.detectMapScript( oContent ) ) { var oMap = FCK.GoogleMapsHandler.createNew() ; oMap.parse( oContent ) ; oMap.createHtmlElement( oNode, index ) ; } else { if ( FCK.GoogleMapsHandler.detectGoogleScript( oContent ) ) oNode.parentNode.removeChild( oNode ); } } FCKCommentsProcessor.AddParser( GoogleMaps_CommentsProcessorParser ); // Context menu FCK.ContextMenu.RegisterListener( { AddItems : function( menu, tag, tagName ) { // under what circumstances do we display this option if ( tagName == 'IMG' && tag.getAttribute( 'MapNumber' ) ) { // No other options: menu.RemoveAllItems() ; // the command needs the registered command name, the title for the context menu, and the icon path menu.AddItem( 'googlemaps', FCKLang.DlgGMapsTitle, oGoogleMapsButton.IconPath ) ; } }} ); // Double click FCK.RegisterDoubleClickHandler( editMap, 'IMG' ) ; function editMap( oNode ) { if ( !oNode.getAttribute( 'MapNumber' )) return ; FCK.Commands.GetCommand( 'googlemaps' ).Execute() ; } // Object that handles the common functions about all the maps FCK.GoogleMapsHandler = { // Object to store a reference to each map maps: {}, getMap: function(id){ return this.maps[id]; }, // Verify that the node is a script generated by this plugin. detectMapScript: function( script ) { // We only know about version 1: if ( !(/FCK googlemaps v1\.(\d+)/.test(script)) ) return false; return true }, // Self-executed function, we want to run it once at initialization only. // Public key that will be used for the generated maps, // while we are editing we will use only FCKConfig.GoogleMaps_Key publicKey : function() { // if FCKConfig.GoogleMaps_PublicKey is set to something, then use it if ( FCKConfig.GoogleMaps_PublicKey ) return FCKConfig.GoogleMaps_PublicKey ; // else we will use GoogleMaps_Key for both the public and private side. return FCKConfig.GoogleMaps_Key ; }(), // Detects both the google script as well as our ending block // both must be removed and then added later only if neccesary detectGoogleScript: function( script ) { // Our final script if (/FCK googlemapsEnd v1\./.test(script) ) return true ; // If it is the Google Maps script, get the public key from here: if ( !/^' ; }, // This can be called from the dialog createNew: function() { var map = new FCKGoogleMap() ; this.maps[ map.number ] = map; return map; }, BuildEndingScript: function() { var versionMarker = '// FCK googlemapsEnd v1.97'; var aScript = [] ; aScript.push('\r\n'); return aScript.join('\r\n'); }, // 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 CreatedMapsNames : [], // Function that will be injected into the normal core GetXHTMLAfter: function( node, includeNode, format, Result ) { if (FCK.GoogleMapsHandler.CreatedMapsNames.length > 0) { Result += FCK.GoogleMapsHandler.BuildEndingScript() ; } // Reset the counter each time the GetXHTML function is called FCK.GoogleMapsHandler.CreatedMapsNames = []; return Result ; }, // Store any previous processor so nothing breaks previousProcessor: FCKXHtml.TagProcessors[ 'img' ] } // Our object that will handle parsing of the script and creating the new one. var FCKGoogleMap = function() { var now = new Date() ; this.number = '' + now.getFullYear() + now.getMonth() + now.getDate() + now.getHours() + now.getMinutes() + now.getSeconds() ; this.width = FCKConfig.GoogleMaps_Width || 400 ; this.height = FCKConfig.GoogleMaps_Height || 240 ; this.centerLat = FCKConfig.GoogleMaps_CenterLat || 37.4419 ; this.centerLon = FCKConfig.GoogleMaps_CenterLon || -122.1419 ; this.zoom = FCKConfig.GoogleMaps_Zoom || 11 ; this.markerPoints = [] ; this.LinePoints = '' ; this.LineLevels = '' ; this.mapType = 0 ; this.WrapperClass = FCKConfig.GoogleMaps_WrapperClass || '' ; } FCKGoogleMap.prototype.createHtmlElement = function( oReplacedNode, index) { var oFakeNode = FCK.EditorDocument.createElement( 'IMG' ) ; // Are we creating a new map? if ( !oReplacedNode ) { index = FCKTempBin.AddElement( this.BuildScript() ) ; var prefix = ( FCKConfig.ProtectedSource._CodeTag || 'PS..' ) ; oReplacedNode = FCK.EditorDocument.createComment( '{' + prefix + index + '}' ) ; FCK.InsertElement(oReplacedNode); } oFakeNode.contentEditable = false ; // oFakeNode.setAttribute( '_fckfakelement', 'true', 0 ) ; oFakeNode.setAttribute( '_fckrealelement', FCKTempBin.AddElement( oReplacedNode ), 0 ) ; oFakeNode.setAttribute( '_fckBinNode', index, 0 ) ; oFakeNode.src = FCKConfig.FullBasePath + 'images/spacer.gif' ; oFakeNode.style.display = 'block' ; oFakeNode.style.border = '1px solid black' ; oFakeNode.style.background = 'white center center url("' + FCKPlugins.Items['googlemaps'].Path + 'images/maps_res_logo.png' + '") no-repeat' ; oFakeNode.setAttribute("MapNumber", this.number, 0) ; oReplacedNode.parentNode.insertBefore( oFakeNode, oReplacedNode ) ; oReplacedNode.parentNode.removeChild( oReplacedNode ) ; // dimensions this.updateHTMLElement( oFakeNode ); return oFakeNode ; } FCKGoogleMap.prototype.updateScript = function( oFakeNode ) { this.updateDimensions( oFakeNode ) ; var index = oFakeNode.getAttribute( '_fckBinNode' ); FCKTempBin.Elements[ index ] = this.BuildScript() ; } FCKGoogleMap.prototype.updateHTMLElement = function( oFakeNode ) { oFakeNode.width = this.width ; oFakeNode.height = this.height ; // Static maps preview :-) oFakeNode.src = this.generateStaticMap() ; oFakeNode.style.border = 0 ; // The wrapper class is applied to the IMG not to a wrapping DIV !!! if ( this.WrapperClass !== '') oFakeNode.className = this.WrapperClass ; } FCKGoogleMap.prototype.generateStaticMap = function() { var w = Math.min(this.width, 640); var h = Math.min(this.height, 640); var staticMapTypes = ['roadmap', 'satellite', 'hybrid', 'terrain'] ; return 'http://maps.google.com/staticmap?center=' + this.centerLat + ',' + this.centerLon + '&zoom=' + this.zoom + '&size=' + w + 'x' + h + '&maptype=' + staticMapTypes[ this.mapType ] + this.generateStaticMarkers() + '&key=' + FCKConfig.GoogleMaps_Key } FCKGoogleMap.prototype.generateStaticMarkers = function() { if (this.markerPoints.length==0) return ''; var aPoints = []; for (var i=0; i.'); var regexpDimensions = /
/ ; if (regexpDimensions.test( script ) ) { delete FCK.GoogleMapsHandler.maps[this.number] ; this.number = RegExp.$1 ; FCK.GoogleMapsHandler.maps[this.number] = this ; this.width = RegExp.$2 ; this.height = RegExp.$3 ; } // map.setCenter(new GLatLng(42.4298,-8.07756), 8); var 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 ( version<=5 ) { // var text = 'En O Carballino ha estado la d\'elegacion diplomatica japonesa'; var markerText, markerLat=0, markerLon=0; var regexpText = /var text\s*=\s*("|')(.*)\1;\s*\n/ ; if (regexpText.test( script ) ) { markerText = RegExp.$2 ; } // var point = new GLatLng(42.4298,-8.07756); var regexpMarker = /var point\s*=\s*new GLatLng\((-?\d{1,3}\.\d{1,6}),(-?\d{1,3}\.\d{1,6})\)/ ; 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)} ) ; } else { // v > 1.5. multiple points. // AddMarkers( [{lat:37.45088, lon:-122.21123, text:'Write your text'}] ) ; var regexpMarkers = /\{lat\:(-?\d{1,3}\.\d{1,6}),\s*lon\:(-?\d{1,3}\.\d{1,6}),\s*text\:("|')(.*)\3}(?:,|])/ ; var point; var sampleText = script ; var startIndex = 0; var totalLength = sampleText.length; var result, pos; while (startIndex != totalLength) { result = regexpMarkers.exec(sampleText); if (result && result.length > 0) { pos = sampleText.indexOf(result[0]); startIndex += pos; this.markerPoints.push( {lat:result[1], lon:result[2], text:this.decodeText(result[4])} ) ; sampleText = sampleText.substr(pos + result[0].length); startIndex += result[0].length; } else { break; } } /* while (result = regexpMarkers.exec( script ) ) { this.markerPoints.push( {lat:result[1], lon:result[2], text:result[4]} ) ; } */ } // var encodedPoints = "iuowFf{kbMzH}N`IbJb@zBpYzO{dAvfF{LwDyN`_@`NzKqB|Ec@|L}BKmBbCoPjrBeEdy@uJ`Mn@zoAer@bjA~Xz{JczBa]pIps@de@tW}rCdxSwhPl`XgikCl{soA{dLdAaaF~cCyxCk_Aao@jp@kEvnCgoJ`]y[pVguKhCkUflAwrEzKk@yzCv^k@?mI"; var regexpLinePoints = /var encodedPoints\s*=\s*("|')(.*)\1;\s*\n/ ; if (regexpLinePoints.test( script ) ) { this.LinePoints = RegExp.$2 ; } // var encodedLevels = "B????????????????????????????????????B"; var regexpLineLevels = /var encodedLevels\s*=\s*("|')(.*)\1;\s*\n/ ; if (regexpLineLevels.test( script ) ) { this.LineLevels = RegExp.$2 ; } // 1.8 mapType // map.setMapType( allMapTypes[ 1 ] ); var regexpMapType = /setMapType\([^\[]*\[\s*(\d+)\s*\]\s*\)/ ; if (regexpMapType.test( script ) ) { this.mapType = RegExp.$1 ; } // 1.9 wrapper div with custom class if ( version >= 9 ) { var regexpWrapper = /
') ; aScript.push( versionMarker ) ; if ( this.WrapperClass !== '') aScript.push('document.write(\'
\'); //wrapper'); aScript.push('document.write(\'
.<\\\/div>\');'); if ( this.WrapperClass !== '') aScript.push('document.write(\'<\\\/div>\'); '); aScript.push('function CreateGMap' + this.number + '() {'); aScript.push(' if(!GBrowserIsCompatible()) return;'); aScript.push(' var allMapTypes = [G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP, G_PHYSICAL_MAP] ;'); aScript.push(' var map = new GMap2(document.getElementById("gmap' + this.number + '"), {mapTypes:allMapTypes});'); aScript.push(' map.setCenter(new GLatLng(' + this.centerLat + ',' + this.centerLon + '), ' + this.zoom + ');'); aScript.push(' map.setMapType( allMapTypes[ ' + this.mapType + ' ] );'); aScript.push(' map.addControl(new GSmallMapControl());'); aScript.push(' map.addControl(new GMapTypeControl());'); var aPoints = []; for (var i=0; i'); return aScript.join('\r\n'); } // Modifications of the core routines of FCKeditor: FCKXHtml.GetXHTML = Inject(FCKXHtml.GetXHTML, null, FCK.GoogleMapsHandler.GetXHTMLAfter ) ; FCKXHtml.TagProcessors.img = function( node, htmlNode, xmlNode ) { if ( htmlNode.getAttribute( 'MapNumber' ) ) { var oMap = FCK.GoogleMapsHandler.getMap( htmlNode.getAttribute( 'MapNumber' ) ) ; FCK.GoogleMapsHandler.CreatedMapsNames.push( oMap.number ) ; oMap.updateScript( htmlNode ); node = FCK.GetRealElement( htmlNode ) ; if ( FCK.GoogleMapsHandler.CreatedMapsNames.length == 1 ) { // If it is the first map, insert the google maps script var index = FCKTempBin.AddElement( FCK.GoogleMapsHandler.GenerateGoogleScript() ) ; var prefix = ( FCKConfig.ProtectedSource._CodeTag || 'PS..' ) ; oScriptCommentNode = xmlNode.ownerDocument.createComment( '{' + prefix + index + '}' ) ; xmlNode.appendChild( oScriptCommentNode ) ; } return xmlNode.ownerDocument.createComment( node.nodeValue ) ; } if (typeof FCK.GoogleMapsHandler.previousProcessor == 'function') node = FCK.GoogleMapsHandler.previousProcessor( node, htmlNode, xmlNode ) ; else node = FCKXHtml._AppendChildNodes( node, htmlNode, false ) ; return node ; }; /** @desc inject the function @author Aimingoo&Riceball */ function Inject( aOrgFunc, aBeforeExec, aAtferExec ) { return function() { if (typeof(aBeforeExec) == 'function') arguments = aBeforeExec.apply(this, arguments) || arguments; //convert arguments object to array var Result, args = [].slice.call(arguments); args.push(aOrgFunc.apply(this, args)); if (typeof(aAtferExec) == 'function') Result = aAtferExec.apply(this, args); return (typeof(Result) != 'undefined')?Result:args.pop(); } ; }