跳转到内容

XRX/地图导航

来自维基教科书,开放的书籍,为一个开放的世界
< XRX

您希望在您的 XRX 应用程序中添加地图导航功能。

虽然地图控件没有在原始 XForms 规范中定义,但可以通过使用一些 JavaScript 来添加它们。

我们将使用三个框架。

  1. XSLTForms - 用于启用模型、控件和绑定
  2. JQuery - JQuery UI,JQuery 布局 - 用于用户界面。这包括控件来进行北、南、东、西方向的平移
  3. OpenLayers - 用于地图导航、平移和缩放功能

XForms 模型将包含以下内容

  1. 一个包含搜索查询的默认实例,其中包含最小和最大经度和纬度(默认值)。
  2. 一个用于存储查询响应的位置(响应)。
  3. 一个定位实例(定位)
  4. 一些绑定语句
  5. 一个提交,用于从 openmap 数据库获取新的地图数据

示例用户界面

[编辑 | 编辑源代码]

此示例具有一个简单的地图用户界面控件,允许向北/南/东/西平移以及缩放和缩小。

此用户界面使用一个与 XForms 输入用户界面控件关联的 JQuery 对象。

示例模型源代码

[编辑 | 编辑源代码]

以下内容存储在 XForms 模型中

请注意,以下命名空间在此示例中使用

xmlns:geo="http://schematronic.ru/geo"
xmlns:param="http://schematronic.ru/param"
xmlns:ev="http://www.w3.org/2001/xml-events"
<xf:model>
   <!-- this holds the parameters for the outbound search query. -->
   <xf:instance id="default" xmlns="http://schematronic.ru/geo">
       <geo:search>
           <param:query/>
           <!-- variables for the min and max longitude and latitude -->
           <param:min-lon/>
           <param:min-lat/>
           <param:max-lon/>
           <param:max-lat/>
        </geo:search>
    </xf:instance>

    <!-- this holds the search results -->
    <xf:instance xmlns="" id="response">
       <response/>
    </xf:instance>

    <xf:instance id="locate">
       <eval>
           javascript:g.locate(<lon></lon>, <lat></lat>, "<icon></icon>")
       </eval>
    </xf:instance>

    <!-- These binds associate an id with a variable in the search form and a calculation -->
    <xf:bind id="query" nodeset="instance('default')/param:query"/>
    <xf:bind id="min-lon" nodeset="instance('default')/param:min-lon" calculate="min-lon()"/>
    <xf:bind id="min-lat" nodeset="instance('default')/param:min-lat" calculate="min-lat()"/>
    <xf:bind id="max-lon" nodeset="instance('default')/param:max-lon" calculate="max-lon()"/>
    <xf:bind id="max-lat" nodeset="instance('default')/param:max-lat" calculate="max-lat()"/>
    <!-- These binds associate an ID with 
    <xf:bind id="lon" nodeset="instance('locate')/lon"/>
    <xf:bind id="lat" nodeset="instance('locate')/lat"/>
    <xf:bind id="icon" nodeset="instance('locate')/icon"/>

    <!-- When the user selects any of the navigation controls, the following does a POST to the server. -->
    <!-- Note that the response to the search is places in the "response instance -->
     <xf:submission id="do-search" method="post" ref="instance('default')" replace="instance" instance="response" resource="/gate">
         <xf:load 
            ev:event="xforms-submit-done" 
            resource="javascript:showResult()"/>
     </xf:submission>
</xf:model>

JavaScript 导入

[编辑 | 编辑源代码]

Javascript 库将来自 openstreemap.org 网站。我们还将使用一些 JQuery 用户界面控件。

以下是您需要添加的静态 JavaScript 文件。

导入静态 JavaScript 库

[编辑 | 编辑源代码]
   <script type="text/javascript" src="http://openlayers.org/api/OpenLayers.js"></script>
   <script type="text/javascript" src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
   <script type="text/javascript" src="/share/geo.js"></script>
   <script type="text/javascript" src="/share/jquery.js"></script>
   <script type="text/javascript" src="/share/jquery-ui.js"></script>
   <script type="text/javascript" src="/share/jquery-layout.js"></script>

内联 JavaScript 数据

[编辑 | 编辑源代码]

除了以上内容外,还必须使用以下 JavaScript 数据。

<script type="text/javascript">
    var g;
    function map(){
       var lat  = 51.30505;
       var lon  = 37.85331;
       var zoom = 12;
       g = geo("map", lon, lat, zoom);            
    }
    var isDebug = false;                   
    var layout;
  
    function showResult (){
                    layout.open("west");
    }      
    jQuery(function (){      
        jQuery("#search input").addClass("ui-state-default ui-corner-left");
        jQuery("#search button").addClass("ui-button ui-state-default ui-corner-right");
        layout = jQuery("body").layout({
              north : {
                            resizable          : false,
                            slidable           : false,
                            closable           : false,
                            spacing_open       : 0,
                            spacing_closed     : 0,
                            size               : 40
                        },
              south : {
                            size               : 100,
                            resizable          : true,
                            slidable           : true,
                            closable           : true,
                            initHidden         : !isDebug
                        },
              west : {
                            size               : 300,
                            minSize            : 200,
                            maxSize            : 400,
                            resizable          : true,
                            slidable           : true,
                            closable           : true,
                            initHidden         : true
                        }
                        
                    }); 
             map();             
     if (isDebug) jQuery("#console").show();    
})

</script>

表单主体

[编辑 | 编辑源代码]
<body>
   <div id="header" class="ui-layout-north ui-widget-header">
      <span id="logo">
         <a href="/">
            <img src="/site/stkurier/images/logo/logo.png" alt="logo" />
         </a>
      </span>
      <span id="search">
          <xf:input xmlns:xf="http://www.w3.org/2002/xforms" bind="query">
               <xf:send submission="do-search" ev:event="xforms-value-changed"/>
          </xf:input>
          <xf:submit submission="do-search">
              <xf:label>
                  <img alt="search" src="/share/icons/fugue-icons/icons/magnifier-medium-left.png" />
               </xf:label>
           </xf:submit>
            </span>
        </div>
        <div class="ui-layout-west">
            <div id="result">
                <ol>
                    <xf:repeat xmlns:xf="http://www.w3.org/2002/xforms" id="place_list" nodeset="instance('response')//*:place">
                        <li>
                            <xf:trigger appearance="minimal">
                                <xf:action xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="DOMActivate">
                                    <xf:setvalue bind="lon" value="instance('response')//*:place[index('place_list')]/@lon"></xf:setvalue>
                                    <xf:setvalue bind="lat" value="instance('response')//*:place[index('place_list')]/@lat"></xf:setvalue>
                                    <xf:setvalue bind="icon" value="instance('response')//*:place[index('place_list')]/@icon"></xf:setvalue>
                                    <xf:load>
                                        <xf:resource value="instance('locate')"></xf:resource>
                                    </xf:load>

                                </xf:action>
                                <xf:label>
                                    <xf:output ref="@icon" mediatype="image/*" if="@icon"></xf:output>
                                    <xf:output ref="@display_name"></xf:output>
                                </xf:label>
                            </xf:trigger>
                        </li>
                    </xf:repeat>
                </ol>
            </div>
        </div>
        <div class="ui-layout-center">
            <div id="map"></div>
        </div>
        <div div="#debug" class="ui-layout-south">
            <div id="console"></div>
        </div>
    </body>

以下是服务器端 XQuery 代码的示例。

   geo:search($query, $min-lon, $min-lat, $max-lon, $max-lat)

将在服务器端针对实例进行评估

<geo:search>
     <param:query/>
     <param:min-lon/>
     <param:min-lat/>
     <param:max-lon/>
     <param:max-lat/>
</geo:search>

Geo XQuery 模块

[编辑 | 编辑源代码]
module namespace geo = "http://schematronic.ru/geo";

import module namespace http    = "http://exist-db.org/xquery/httpclient";
import module namespace request = "http://exist-db.org/xquery/request";

declare variable $geo:search-service-uri := "http://nominatim.openstreetmap.org/search";

declare function geo:search($query  as xs:string,
                           $min-lon as xs:float, $min-lat as xs:float,
                           $max-lon as xs:float, $max-lat as xs:float) {

   let $view-box := string-join(($min-lon, $min-lat, $max-lon, $max-lat), ",")
   let $lon      := ($min-lon + $max-lon) div 2
   let $lat      := ($min-lat + $max-lat) div 2
   let $uri      := escape-uri(xs:anyURI(concat(
                       $geo:search-service-uri,
                       "?format=xml",
                       "&amp;viewbox=", $view-box,
                       "&amp;addressdetails=1&amp;limit=100",
                       "&amp;polygon=0",
                       "&amp;q=", $query
                    )), false())
   let $response := http:get($uri, false(), ())

   let $results  := $response//searchresults

   return
       element {name($results)} {
           $response/@*,
           for $i in $results/place
           order by ($lon - $i/@lon) * ($lon - $i/@lon) + ($lat - $i/@lat) * ($lat - $i/@lat)
           return $i
       }

};

declare function geo:search($query as xs:string, $view-box as xs:float*) {
   geo:search($query, $view-box[1], $view-box[2], $view-box[3], $view-box[4])
};

declare function geo:search($query as xs:string) {
   geo:search($query, -180, -90, 180, 90)
};

所有工作均由 Evgeny Gazdovsky 完成。文稿由 Dan McCreary 完成。

华夏公益教科书