2

In our mobile application, we'd like to use the map offline.

Actually, we don't care about tiles, but we want the user to be able to see some Vector layers. Here is a piece of code:

            layer = new OpenLayers.Layer.Vector("Block", {
                strategies: [new OpenLayers.Strategy.BBOX()],
                filter: VMMS.GIS.GetBlockFilter(i),
                protocol: new OpenLayers.Protocol.WFS({
                    url: self.urlProxyGeoserver,
                    version: "1.1.0",
                    featureType: "block",
                    featureNS: self.urlGeoserver + self.dataStore,
                    featurePrefix: self.dataStore,
                    srsName: "EPSG:900913",
                    geometryName: "block_geom",
                    schema: self.urlGeoserver + "wfs/DescribeFeatureType?version=1.1.0&typename=" + self.dataStore + ":block"

                }),
                projection: "EPSG:900913",
                styleMap : self.StyleBlockWithOpacity
            });

I would like to be able to load this layer before to be offline, then use it. I tried to do it, and cache it with localstorage (HTML5), but some problems occurs because of javascript cyclic object.

I could make the request (with url parameter) with my own API, and then cache the response. But I have the feeling that we have to use OpenLayers API.

Otherwise, do you have any idea?

On google, I have only seen solution to cache tiles, but not about my problem. I'm kind of newbie to Openlayers, so I might have miss something. In that case, I would be happy to know what :)

Thanks

Edit: By the way, I tried the recommandation there: WFS Caching / Back button But it's not working (or doesn't match with my needs for some)

1 Answer 1

2

One option is to store the features in the mobile local storage like a sqlite database, you can even store it in a html5 web sql database. When it's offline you can create the layer from stored feature.

Edit:

Following is the code to save the features (in geojson format) to local storage

var features = ...; // This is the features you will store in local storage

var geojsonParser = new OpenLayers.Format.GeoJSON();

var feature_geojson_list = [];
for (var i=0; i<features.length; i++) {
    var feature_geojson = geojsonParser.write(features[i]);
    feature_geojson_list.push(feature_geojson);
}

//save feature_geojson_list to local storage
...

Following is how you create feature from the geojson objects (when it's offline):

var feature_geojson_list = ... // read feature geojson list from local storage

var geojsonParser = new OpenLayers.Fomrat.GeoJSON();

var features = [];

for (var i=0; i<feature_geojson_list.length; i++) {
    var feature = geojsonParser.read(feature_geojson_list[i], "Feature");
    features.push(feature);
}

// now add features to your layer
...

More edits: So in your map page, there will be some kind of connection check, and you get the features from different sources depend on whether it's online or offline.


if (**api_meothod_return_mobile_is_online**) {
    // when it's on line you get the layer from server
    var layer = new OpenLayers.Layer.Vector("Block", {
                strategies: [new OpenLayers.Strategy.BBOX()],
                filter: VMMS.GIS.GetBlockFilter(i),
                protocol: new OpenLayers.Protocol.WFS({
                    url: self.urlProxyGeoserver,
                    version: "1.1.0",
                    featureType: "block",
                    featureNS: self.urlGeoserver + self.dataStore,
                    featurePrefix: self.dataStore,
                    srsName: "EPSG:900913",
                    geometryName: "block_geom",
                    schema: self.urlGeoserver + "wfs/DescribeFeatureType?version=1.1.0&typename=" + self.dataStore + ":block"

                }),
                projection: "EPSG:900913",
                styleMap : self.StyleBlockWithOpacity
            });

     // some other code 
     map.addLayer(layer);
     ... 

     //after you get the features from server, you need to store them to local storage. 
     //But make sure all features get loaded before storing the features, 
     //so you probably need to listen on layer's 'loadend' event.

     //**Additional comments from new comments: if you only cache the data by
     //clicking some button, this is not the right code. Make it listen on
     //the button clicking event. But also make sure all the wfs features get loaded
     //before you clicking the button.
     layer.events.on('loadend', layer, function(event) {
         //here cache all layer features to local storage
         var features = layer.features;
         var geojsonParser = new OpenLayers.Format.GeoJSON();
         ... // the same code above.
     }); 
}
else {
    // when it's offline, you get the layer from local storage
    // note you just need to create a normal empty vector layer, but with same projection and stylemap
    var layer = new OpenLayers.Layer.Vector("Block", {
         projection: "EPSG:900913",
         styleMap: self.StyleBlockWithOpacity
    });

    //some other code
    map.addLayer(layer);
    ...

    // read features from local storage
    var feature_geojson_list = ... // if you don't find any feature in local storage, that means the app never get online, process the application properly in such case.
    var geojsonParser = new OpenLayers.Fomrat.GeoJSON();

    ... // the same code above

    // after get the features, add it to the layer
    layer.addFeatures(features);
}

The above code is quite primitive, you need to modify it according to your own application.

11
  • I can not use a sql database for that. But I tried to store it in the mobile local storage. There were some difficulties with JSON.stringify and cyclic objects. Have you already succeed in that task? Thanks
    – nicolasca
    Aug 30, 2013 at 14:30
  • No, I have not developed a mobile application. But are you trying to save the OpenLayers.Vector.Feature objects?
    – mfdev
    Aug 30, 2013 at 14:35
  • Well, maybe you can tell what is the best :). From the piece of code in my question, I would like to be able to cache data that would let me creating the OpenLayers.Layer.Vector once offline. As I find the documentation of OpenLayers very light, I don't really know how to manage that.
    – nicolasca
    Aug 30, 2013 at 14:39
  • What I would like to suggest is to store the features in a standard format, like geojson. But I will update my answer and put some codes there.
    – mfdev
    Aug 30, 2013 at 14:40
  • Yes that's a great explanation. I have still a (very) newbie question. You wrote 'var features = ...; // This is the features you will store in local storage". But I cannot find how to create these features. I mean, from my code I do it using Protocol.WFS, and that populates the features of my Vector.Layer. But if I want to get directly these features, can I? Thanks for the help.
    – nicolasca
    Aug 30, 2013 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.