CarlosSimoes / geoxml3

Automatically exported from code.google.com/p/geoxml3
0 stars 0 forks source link

docs array, first element gets clobbered on each parse. Does not save one doc per Array element #100

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
First of all, great library, many thanks for creating this!

This issue I'm reporting has caused a LOT of frustration and seems like a very 
glaring bug.

First, here's the seemingly correct way to use the parser. Of course, it 
doesn’t work:

// Public class variable
this.kmlParser = new geoXML3.parser( options );

// Each time you need to load KML:
this.kmlParser.parse( data );

// When done parsing, you now have the result saved into:
this.kmlParser.docs

// Which is an array, supposedly (according to your own docs) having a new 
element for each parsed KML. But it doesn’t work. The array never grows in 
size. Instead, all new elements from each newly parsed KML file are merged 
together into the ONE doc (docs[0]). Like it’s auto-combining all KML data 
into one KML document. Feature + Bug simultaneously??

Supposed Solution... doesn't work either:

afterParse = function( docs ) {
    // This is a callback function called when done parsing
    // docs[0] is the parsed KML object / doc

    this.someOtherArrayCopy.push( docs[0] );

    // Done. Now you have another array of the KML docs, correctly saved with one doc per Array element.
    // But it fails. For some reason Array element [0] keeps getting over-written by the latest parsed doc. Elements 2 … n have no problems. But the first keeps getting clobbered. Even though you copied docs[0] into this.someOtherArrayCopy, both references get clobbered.
}

Method two. The real solution.

Do not save an instance of geoXML3 for more than one use!

Instead of a class variable, inside any function do this:

var p = new geoXML3.parser( options );
p.parse( data );

afterParse = function( docs ) {
    this.someOtherArrayCopy.push( docs[0] );
    // DONE. What should've been a 10 minute job took 2+ hours.
}

So basically it seems like geoXML3 is broken. It can’t save its own array of 
parsed docs. It merges all docs into one doc. If you try to copy parsed KML 
results into your own array, the first one always gets clobbered. It does not 
behave as described in the extremely minimal documentation, here:

https://code.google.com/p/geoxml3/wiki/JsonObjects

"doc
The root object; one is created for each KML document processed."

Nope!

But destroying the geoXML3 instance every time solves the problem.

Luckily every parsed KML doc retains a reference to its parser inside of it!

So to call show / hideDocument even with no reference to the parser, you can 
say:

var KMLDoc = this.someOtherArrayCopy[0];
KMLDoc.internals.parser.hideDocument( KMLDoc );

But that really doesn't seem like it should be the way. Seems like a hacky 
workaround that luckily is working.

Also this entire issue seems to happen only with parseKmlString(), not parse() 
... but not 100% sure.

Thanks so much!

Original issue reported on code.google.com by car...@bumpnetworks.com on 5 Oct 2014 at 12:28

GoogleCodeExporter commented 9 years ago
Please 
1. provide code to reproduce the issue
2. indicate which version of the code you are using, the polys branch or the 
kmz branch

Original comment by geocodezip on 5 Oct 2014 at 5:31

GoogleCodeExporter commented 9 years ago

Original comment by geocodezip on 5 Oct 2014 at 9:40

GoogleCodeExporter commented 9 years ago
I'm using the kmz branch, with ProjectedOverlay.js and ZipFile.complete.js both 
in the project as well.

Downloaded the code from here:
https://code.google.com/p/geoxml3/source/browse/#svn%2Fbranches%2Fkmz

Actual source code in use:

// This code is inside a "class" (function), and the following methods show the 
behavior described:

                  this.uploadKMLFile = function() {

                        // A file uploader class we made
                        // It uses FileReader.readAsBinaryString() to pull in the text content of a file.
                        this.fileUploader.startUpload();

                        // Callback when fileUploader has a file loaded
                        function onFileReady( result, file ) {

                            this.fileUploader.clearOutFiles();

                            this.lastFileName = file.name;

                            // This is the form of using geoXML3 that works. By instantiating it into a new var,
                            // It does not clobber the doc saved to docs[0]
                            var p = new geoXML3.parser({
                                map: this.map,
                                afterParse: this.afterKMLParsed
                            });

                            p.parseKmlString( result );

                            // The way that FAILED was:
                            this.kmlParser = new geoXML3.parser({ map: self.map, afterParse: self.afterKMLParsed });

                            // ... And referencing the same this.kmlParser instance repeatedly, hoping its this.kmlParser.docs array would be increasing in size each time, but it doesn't.
                            // It just keeps appending placemarks, etc. into docs[0]. And also causes the problems described below...
                        }
                    };

                    this.afterKMLParsed = function( docs ) {

                        // Inject the properties we need into the parsed doc object
                        docs[0].fileName = this.lastFileName;
                        docs[0].visible = true;

                        // For some reason, geoXML3 is not making a new doc (object) for each parse in the docs array.
                        // It's combining ALL DOCS into the same doc!! This is not the behavior as described in their, ... ahem... docs.
                        // So just using this function to make each run of the parser separate up the docs, as it should

                        this.kmlLayers.push( docs[0] );

                        // If we had used this.kmlParser = new geoXML3.parser(...) as described above, not only would docs[0] be clobbered, but the reference to it in this.kmlLayers[0] would be clobbered too!
                        // But since we used var p = new geoXML3.parser(...) above, the instance is destroyed after function runs, and everything works fine.
                    };

Thanks so much!
Carlos

Original comment by car...@bumpnetworks.com on 6 Oct 2014 at 4:36

GoogleCodeExporter commented 9 years ago
Please provide a complete minimal example that exhibits the problem.
(see http://sscce.org/ or http://stackoverflow.com/help/mcve)

Original comment by geocodezip on 7 Oct 2014 at 5:40

GoogleCodeExporter commented 9 years ago
Ok, here is a complete working example:

http://jsbin.com/pesiz/1/edit?html,js,console,output

In order to see the problem, just click the "Choose File" input button on the 
top left of the map. (Thick red border.)

Choose a KML file from your hard drive. The KML files I'm using are just plain 
text files ending in ".kml"

The map should re-center to show the KML data. The parsing was successful.

Now, in the JSBin console (3rd panel), type in TEST.geo.kmlLayers and hit 
enter. Ignore the output in JSBin. Just open the real web inspector console 
(cmd+opt+I on Chrome) and view the console tab. You should see an Array with 
one element, the first doc parsed. If you open it up, you'll see fileName = 
"(your file name)" and visible = true. (The two properties I injected into the 
object.)

Now do it again. Click the file upload button. Choose a second KML file. (It 
has to be a different file.) The file is parsed, shown on the map. Success! 
However....  Now type in TEST.geo.kmlLayers into the console again, and you'll 
see the problem.

You'll see two objects, and they're both the same!! Array element 0 (zero) is 
the same as 1! And in [0], the filename and visible properties are undefined.

If you continue parsing new KML files in the same way, you'll see that array 
elements [1] - [...n] work fine. Just [0] continually gets clobbered.

Also, you'll probably notice the docs array (inside geoXML3.parser.docs) never 
grows in size. It just keeps appending the features of each new doc to the 
first doc in docs[0]

Now here is the slightly modified code that works:
http://jsbin.com/fageje/1/edit?html,js,console,output

You can do all the same steps over again and when you write TEST.geo.kmlLayers 
in the console, you'll see that array element [0] never gets clobbered.

This is because I'm starting with a brand new geoXML3 instance every time and 
it never gets a chance to store more than one doc in its memory / scope.

I hope this is clear.

Thanks!
Carlos

Original comment by car...@bumpnetworks.com on 8 Oct 2014 at 1:34