.. _tinyows_openlayershowtotransactional:

*****************************************************************************
Sample: WFS-T with TinyOWS and OpenLayers 
*****************************************************************************




0) Install PostGIS and TinyOWS (:ref:`tinyows_serverinstallation`)


1) Within PostGIS, create a spatial database called 'tinyows'

.. code-block:: bash

 createdb -U postgres tinyows
 psql -U postgres -d tinyows < `pg_config --sharedir`/contrib/postgis-2.0/postgis.sql
 psql -U postgres -d tinyows < `pg_config --sharedir`/contrib/postgis-2.0/spatial_ref_sys.sql



2) Import Frida data (we will use the parks layer) into your PostGIS database

.. code-block:: bash

 wget ftp://ftp.intevation.de/freegis/frida/frida-1.0.1-shp.tar.gz
 tar xvzf frida-1.0.1-shp.tar.gz
 cd frida-1.0.1-shp
 shp2pgsql -g geom -s 31467 -W LATIN1 -I gruenflaechen.shp frida | psql -U postgres -d tinyows



3) Configure TinyOWS by editing /usr/local/tinyows/config.xml

.. code-block:: xml

  <tinyows online_resource="http://127.0.0.1/cgi-bin/tinyows"
           schema_dir="/usr/local/share/tinyows/schema/">

  <pg host="127.0.0.1" user="postgres" password="postgres" dbname="tinyows" port="5432"/>

  <metadata name="TinyOWS Server"
            title="TinyOWS Server - WFS-T Frida Service" />

  <contact name="TinyOWS Server"
           site="http://www.mapserver.org/tinyows/"
           email="tinyows-users@lists.maptools.org" />

  <layer retrievable="1"
         writable="1"
         ns_prefix="tows"
         ns_uri="http://www.mapserver.org/tinyows/"
         name="frida"
         title="Frida Parks" />

  </tinyows>



4) Test your installations of TinyOWS and PostGIS

.. code-block:: bash

  ./YOUR_CGI-BIN_PATH/tinyows --check
  TinyOWS version:   1.1.0
  FCGI support:      Yes
  Config File Path:  /etc/tinyows.xml (TinyOWS XML)
  PostGIS Version:   2.0.1
  PostGIS dsn:       host=127.0.0.1 user=postgres password=postgres dbname=tinyows port=5432 
  Output Encoding:   UTF-8
  Database Encoding: UTF8
  Schema dir:        /usr/local/share/tinyows/schema/
  Display bbox:      Yes
  Estimated extent:  No
  Check schema:      Yes
  Check valid geoms: Yes
  Available layers:
   - public.frida (31467) -> tows:frida [RW]


5) Install OpenLayers 

.. code-block:: bash

  wget http://openlayers.org/download/OpenLayers-2.12.tar.gz
  tar xvzf OpenLayers-2.12.tar.gz
  sudo mv OpenLayers-2.12  /YOUR/SERVER/HTDOCS/


6) Install the OpenLayers proxy (you need the Python interpreter to make it work)

.. code-block:: bash

  sudo cp OpenLayers-2.12/examples/proxy.cgi  /YOUR/SERVER/CGI-BIN/

7) Add your server IP to proxy allowedHosts in (/YOUR/SERVER/CGI-BIN/proxy.cgi)
 
.. code-block:: bash

  allowedHosts = ['127.0.0.1', 'www.openlayers.org', 'openlayers.org', ... ]
 


8) Create a new file at OpenLayers-2.12/examples/tinyows.html 


.. code-block:: html

  <html>
  <head>
    <link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
    <link rel="stylesheet" href="style.css" type="text/css" />
    <script src="../lib/OpenLayers.js"></script>
    <style>
	#map {
    	    width: 800px;
   	    height: 500px;
    	    float: left;
    	    border: 1px solid #ccc;
	}
        #message {
	    position: relative;
            left: 5px;
	}
        #docs {
    	    float: left;
	}
        .customEditingToolbar {
            float: right;
            right: 0px;
            height: 30px; 
            width: 200px;
        }
        .customEditingToolbar div {
            float: right;
            margin: 5px;
            width: 24px;
            height: 24px;
        }
        .olControlNavigationItemActive { 
            background-image: url("../theme/default/img/editing_tool_bar.png");
            background-repeat: no-repeat;
            background-position: -103px -23px; 
        }
        .olControlNavigationItemInactive { 
            background-image: url("../theme/default/img/editing_tool_bar.png");
            background-repeat: no-repeat;
            background-position: -103px -0px; 
        }
        .olControlDrawFeaturePolygonItemInactive { 
            background-image: url("../theme/default/img/editing_tool_bar.png");
            background-repeat: no-repeat;
            background-position: -26px 0px; 
        }
        .olControlDrawFeaturePolygonItemActive { 
            background-image: url("../theme/default/img/editing_tool_bar.png");
            background-repeat: no-repeat;
            background-position: -26px -23px ;                                                                   
        }
        .olControlModifyFeatureItemActive { 
            background-image: url(../theme/default/img/move_feature_on.png);
            background-repeat: no-repeat;
            background-position: 0px 1px;
        }
        .olControlModifyFeatureItemInactive { 
            background-image: url(../theme/default/img/move_feature_off.png);
            background-repeat: no-repeat;
            background-position: 0px 1px;
        }
        .olControlDeleteFeatureItemActive { 
            background-image: url(../theme/default/img/remove_point_on.png);
            background-repeat: no-repeat;
            background-position: 0px 1px;
        }
        .olControlDeleteFeatureItemInactive { 
            background-image: url(../theme/default/img/remove_point_off.png);
            background-repeat: no-repeat;
            background-position: 0px 1px;
        }
    </style>
    <script src="tinyows.js"></script>
    </head>
    <body onload="init()">
        <h1 id="title">WFS Transaction Example, (TinyOWS ans OpenLayers)</h1>
        <div id="tags"></div>
        <p id="shortdesc">
            Shows the use of the WFS Transactions (WFS-T).
	    Parks of Osnabruck (Frida).
	<br />
	    Base layers is OpenStreetMap from Omniscale WMS Server.
        </p>
        <div id="map"></div>

	<div id="message"></div>
        <div id="docs">
            <p>
                The WFS protocol allows for creation of new features and
                reading, updating, or deleting of existing features.
            </p>
            <p>
                Use the tools to create, modify, and delete (in order from left
                to right) features. Use the save tool (picture of a disk) to
                save your changes. Use the navigation tool (hand) to stop
                editing and use the mouse for map navigation.
            </p>
            <p>
                See the <a href="tinyows.js" target="_blank">
                wfs-protocol-transactions.js source</a> to see how this is done.
            </p>        
        </div>
    </body>
  </html>


9) Create a new file at OpenLayers-2.12/examples/tinyows.js (and replace all 127.0.0.1 addresses by your IP server if necessary)


.. code-block:: javascript

  var map, wfs;
  OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
  var DeleteFeature = OpenLayers.Class(OpenLayers.Control, {
    initialize: function(layer, options) {
        OpenLayers.Control.prototype.initialize.apply(this, [options]);
        this.layer = layer;
        this.handler = new OpenLayers.Handler.Feature(
            this, layer, {click: this.clickFeature}
        );
    },
    clickFeature: function(feature) {
        // if feature doesn't have a fid, destroy it
        if(feature.fid == undefined) {
            this.layer.destroyFeatures([feature]);
        } else {
            feature.state = OpenLayers.State.DELETE;
            this.layer.events.triggerEvent("afterfeaturemodified", 
                                           {feature: feature});
            feature.renderIntent = "select";
            this.layer.drawFeature(feature);
        }
    },
    setMap: function(map) {
        this.handler.setMap(map);
        OpenLayers.Control.prototype.setMap.apply(this, arguments);
    },
    CLASS_NAME: "OpenLayers.Control.DeleteFeature"
  });
  function showMsg(szMessage) {
    document.getElementById("message").innerHTML = szMessage;
    setTimeout(
        "document.getElementById('message').innerHTML = ''",2000);
  }
  function showSuccessMsg(){
    showMsg("Transaction successfully completed");
  };
  function showFailureMsg(){
    showMsg("An error occurred while operating the transaction");
  };
  function init() {
    map = new OpenLayers.Map('map', {
        projection: new OpenLayers.Projection("EPSG:31467"),
        units: "m",
        maxResolution: "auto",
        maxExtent: new OpenLayers.Bounds(3427000,5788000,3444000,5800000),
        controls: [
            new OpenLayers.Control.PanZoom()
        ]
    });
    var osm = new OpenLayers.Layer.WMS(
        "OSM by Omniscale WMS",
	"http://osm.omniscale.net/proxy/service",
        {layers: 'osm', format: 'image/jpeg'},
	{projection:"EPSG:31467",  units: "m", maxResolution: "auto", maxExtent: new OpenLayers.Bounds(3427000,5788000,3444000,5800000)}
    );
    var saveStrategy = new OpenLayers.Strategy.Save();
    saveStrategy.events.register("success", '', showSuccessMsg);
    saveStrategy.events.register("fail", '', showFailureMsg);
    wfs = new OpenLayers.Layer.Vector("Editable Features", {
        strategies: [new OpenLayers.Strategy.BBOX(), saveStrategy],
        projection: new OpenLayers.Projection("EPSG:31467"),
        protocol: new OpenLayers.Protocol.WFS({
            version: "1.1.0",
            srsName: "EPSG:31467",
            url: "http://127.0.0.1/cgi-bin/tinyows",
            featureNS :  "http://www.mapserver.org/tinyows/",
            featureType: "frida",
            geometryName: "geom",
            schema: "http://127.0.0.1/cgi-bin/tinyows?service=wfs&request=DescribeFeatureType&version=1.1.0&typename=tows:frida"
        })
    }); 
    map.addLayers([osm, wfs]);
    var panel = new OpenLayers.Control.Panel(
        {'displayClass': 'customEditingToolbar'}
    );
    var navigate = new OpenLayers.Control.Navigation({
        title: "Pan Map"
    });
    var draw = new OpenLayers.Control.DrawFeature(
        wfs, OpenLayers.Handler.Polygon,
        {
            title: "Draw Feature",
            displayClass: "olControlDrawFeaturePolygon",
            multi: true
        }
    );
    var edit = new OpenLayers.Control.ModifyFeature(wfs, {
        title: "Modify Feature",
        displayClass: "olControlModifyFeature"
    });
    var del = new DeleteFeature(wfs, {title: "Delete Feature"});
    var save = new OpenLayers.Control.Button({
        title: "Save Changes",
        trigger: function() {
            if(edit.feature) {
                edit.selectControl.unselectAll();
            }
            saveStrategy.save();
        },
        displayClass: "olControlSaveFeatures"
    });
    panel.addControls([navigate, save, del, edit, draw]);
    panel.defaultControl = navigate;
    map.addControl(panel);
    map.zoomToMaxExtent();
  }
