1
votes

I am trying to take a string which has shape option information and create the shape on my Google Map application.

The string is made by splitting an array that was built from a local text document.

The string appears as: Circle{center: new google.maps.LatLng(38.041872419557094, -87.6046371459961),radius:5197.017394363823,fillColor: '#000000',strokeWeight: 1,strokeColor: '#000000',map:map};

The function I have to take such string and make the shape appears as:

function loadDrawings(evt)
{
    var f = evt.target.files[0];

    if (!f) 
    {
        alert("Failed to load file");
    } 
    else if (!f.type.match('text.*')) 
    {
        alert(f.name + " is not a valid text file.");
    } 
    else 
    {
        var r = new FileReader();
        r.onload = function (e) 
        {
            var contents = e.target.result;
            var drawings = [];
            var drawing;
            var drawingType;
            var shape;
            var shapeOptions;

            drawings = contents.split(";");
            for (i = 0; i < drawings.length - 1; i++) {
                drawing = drawings[i].toString();
                drawingType = drawing.substr(0, drawing.indexOf('{'));
                if (drawingType == "Circle")
                {
                    shapeOptions = drawing.substr(6);                //UNIQUE TO CIRCLE
                    shape = new google.maps.Circle(shapeOptions);
                    shape.setMap(map);
                }                    
            };
        }
        r.readAsText(f);
    } 
}

My issue is shapeOptions as a string does not work in the above syntax for creating the Circle. However, if I take the contents of the string, which is:

{center: new google.maps.LatLng(38.041872419557094, -87.6046371459961),radius:5197.017394363823,fillColor: '#000000',strokeWeight: 1,strokeColor: '#000000',map:map}

And directly enter it, the shape appears.

Do I need a certain variable type for my shapeOptions for this to work? I know that the new google.maps. requires (), but I have had no luck creating a variable from my string. Am I missing something here?

Much appreciation for any help!

1

1 Answers

0
votes

Your shapeOptions string is a JavaScript object literal, so you can eval() it to get the object:

shapeOptions = eval( '(' + drawing.substr(6) + ')' );

Since it has map:map in it, you don't need the subsequent setMap() call.

Also, you're missing a var for the i variable. I don't really recommend the coding style where all the var statements go at the top of a function. I find it error-prone; it's too easy to omit a var without noticing it. (I know some famous JavaScript experts insist that var at the top is the only way to do it, but they fail to see the tradeoffs involved.)

You don't need the .toString() on drawings[i]. It's already a string.

You have two different brace styles. Best to pick one and stick with it. For JavaScript, putting the { on a line by itself is not recommended, because this code will not do what you expect:

return  // hoping to return an object literal - but it doesn't!
{
    a: 'b',
    c: 'd'
}

Whereas this code does work correctly:

return {
    a: 'b',
    c: 'd'
}

Since you are using FileReader, I think it's safe to assume you also have .forEach() available.

You can replace the code that uses .indexOf() and the hard coded length with a regular expression.

Putting all that together, you might end up with code like this:

var r = new FileReader();
r.onload = function( e ) {
    e.target.result.split(";").forEach( function( drawing ) {
        var match = drawing.match( /^(\w+)({.*})$/ );
        if( ! match ) return;  // unrecognized
        var type = match[0], options = eval( match[1] );
        switch( type ) {
            case "Circle":
                new google.maps.Circle( options );
                break;
        }
    });
}
r.readAsText( f );

But you may be able to take it a step further. So far we're looking at a Circle (line breaks added for readability):

Circle{
    center: new google.maps.LatLng(
        38.041872419557094,
        -87.6046371459961
    ),
    radius:5197.017394363823,
    fillColor: '#000000',
    strokeWeight: 1,
    strokeColor: '#000000',
    map:map
}

With only a simple change, that could be executed as JavaScript directly. You just need the 'new google.maps.' at the beginning and () around the object literal:

new google.maps.Circle({
    center: new google.maps.LatLng(
        38.041872419557094,
        -87.6046371459961
    ),
    radius:5197.017394363823,
    fillColor: '#000000',
    strokeWeight: 1,
    strokeColor: '#000000',
    map:map
})

I assume you will have other drawing types as well? Will they all map directly to google.maps.* objects like Circle does? If so, you could simply do:

var r = new FileReader();
r.onload = function( e ) {
    e.target.result.split(";").forEach( function( drawing ) {
        eval( drawing.replace(
            /^(\w+)({.*})$/,
            'new google.maps.$1(\$2)'
        ) );
    });
}
r.readAsText( f );