You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by rg...@apache.org on 2010/02/09 22:42:54 UTC
svn commit: r908241 - in /incubator/wookie/trunk/tutorials: ./ geoLocation/
geoLocation/images/ geoLocation/images/map/ geoLocation/legal/
geoLocation/scripts/
Author: rgardler
Date: Tue Feb 9 21:42:53 2010
New Revision: 908241
URL: http://svn.apache.org/viewvc?rev=908241&view=rev
Log:
A simple tutorial taking the user through the steps required to build your first widget.
Added:
incubator/wookie/trunk/tutorials/
incubator/wookie/trunk/tutorials/firstWidget.odp (with props)
incubator/wookie/trunk/tutorials/geoLocation/
incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithSimulator.html
incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithoutFallback.html
incubator/wookie/trunk/tutorials/geoLocation/images/
incubator/wookie/trunk/tutorials/geoLocation/images/icon.png (with props)
incubator/wookie/trunk/tutorials/geoLocation/images/map/
incubator/wookie/trunk/tutorials/geoLocation/images/map/college.png (with props)
incubator/wookie/trunk/tutorials/geoLocation/images/map/library.png (with props)
incubator/wookie/trunk/tutorials/geoLocation/images/map/person.png (with props)
incubator/wookie/trunk/tutorials/geoLocation/images/map/readme.txt
incubator/wookie/trunk/tutorials/geoLocation/images/map/yellowPin.png (with props)
incubator/wookie/trunk/tutorials/geoLocation/legal/
incubator/wookie/trunk/tutorials/geoLocation/legal/geo_LICENSE.txt
incubator/wookie/trunk/tutorials/geoLocation/legal/geo_position_js_simulator_LICENSE.txt
incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulator.html
incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulatorAndSettings.html
incubator/wookie/trunk/tutorials/geoLocation/scripts/
incubator/wookie/trunk/tutorials/geoLocation/scripts/geo.js
incubator/wookie/trunk/tutorials/geoLocation/scripts/geo_position_js_simulator.js
incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndLayers.js
incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndSettings.js
Added: incubator/wookie/trunk/tutorials/firstWidget.odp
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/firstWidget.odp?rev=908241&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/tutorials/firstWidget.odp
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithSimulator.html
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithSimulator.html?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithSimulator.html (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithSimulator.html Tue Feb 9 21:42:53 2010
@@ -0,0 +1,79 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="pragma" content="no-cache" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>part1</title>
+<link rel="stylesheet" href="style/screen.css" type="text/css" />
+
+<script src="http://code.google.com/apis/gears/gears_init.js"
+ type="text/javascript"></script>
+<script src="scripts/geo.js" type="text/javascript"></script>
+<script src="scripts/geo_position_js_simulator.js" type="text/javascript" charset="utf-8"></script>
+</head>
+<body>
+ <h1>Javascript geo sample</h1>
+ <p><span id="message"></span></p>
+
+ <div id="locationData">
+ <p>Latitude: <span id="latitude">Unkown</span>, Longitude: <span id="longitude">Unknown</span></p>
+ </div>
+
+ <script>
+ var last_position = null;
+
+ if(geo_position_js.init()){
+ setInterval(retrieve,1000);
+ } else{
+ document.getElementById("message").innerHTML = "Geo-Location functionality not available";
+ }
+
+ function retrieve() {
+ document.getElementById('message').innerHTML="Receiving...";
+ geo_position_js.getCurrentPosition(success_callback,error_callback,{enableHighAccuracy:true});
+ }
+
+ function success_callback(p) {
+ if(last_position && last_position.coords.latitude==p.coords.latitude && last_position.coords.longitude==p.coords.longitude) {
+ document.getElementById('message').innerHTML="User has not moved, checking again in 1s";
+ return;
+ }
+
+ last_position = p;
+ document.getElementById('message').innerHTML="User has moved, checking again in 1s";
+
+ document.getElementById("latitude").innerHTML = p.coords.latitude.toFixed(4);
+ document.getElementById("longitude").innerHTML = p.coords.longitude.toFixed(4);
+ }
+
+ function error_callback(p) {
+ document.getElementById("message").innerHTML = p.message;
+ }
+
+ // Set the simulated locations
+ locations=new Array();
+ locations.push({ coords:{latitude:41.399856290690956,longitude:2.1961069107055664},duration:5000 });
+ locations.push({ coords:{latitude:41.400634242252046,longitude:2.1971797943115234},duration:5000 });
+ locations.push({ coords:{latitude:41.40124586762545,longitude:2.197995185852051},duration:5000 });
+ geo_position_js_simulator.init(locations);
+
+ </script>
+
+</body>
+</html>
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithoutFallback.html
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithoutFallback.html?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithoutFallback.html (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/basicGeoWithoutFallback.html Tue Feb 9 21:42:53 2010
@@ -0,0 +1,55 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="pragma" content="no-cache" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>part1</title>
+<link rel="stylesheet" href="style/screen.css" type="text/css" />
+
+<script src="http://code.google.com/apis/gears/gears_init.js"
+ type="text/javascript"></script>
+<script src="scripts/geo.js" type="text/javascript"></script>
+</head>
+<body>
+ <h1>Javascript geo sample</h1>
+ <p><span id="message"></span></p>
+
+ <div id="locationData">
+ <p>Latitude: <span id="latitude">Unkown</span>, Longitude: <span id="longitude">Unknown</span></p>
+ </div>
+
+ <script>
+ if(geo_position_js.init()){
+ geo_position_js.getCurrentPosition(success_callback,error_callback,{enableHighAccuracy:true});
+ } else{
+ document.getElementById("message").innerHTML = "Geo-Location functionality not available";
+ }
+
+ function success_callback(p) {
+ document.getElementById("latitude").innerHTML = p.coords.latitude.toFixed(2);
+ document.getElementById("longitude").innerHTML = p.coords.longitude.toFixed(2);
+ }
+
+ function error_callback(p) {
+ document.getElementById("message").innerHTML = p.message;
+ }
+ </script>
+
+</body>
+</html>
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/images/icon.png
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/images/icon.png?rev=908241&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/tutorials/geoLocation/images/icon.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/wookie/trunk/tutorials/geoLocation/images/map/college.png
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/images/map/college.png?rev=908241&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/tutorials/geoLocation/images/map/college.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/wookie/trunk/tutorials/geoLocation/images/map/library.png
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/images/map/library.png?rev=908241&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/tutorials/geoLocation/images/map/library.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/wookie/trunk/tutorials/geoLocation/images/map/person.png
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/images/map/person.png?rev=908241&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/tutorials/geoLocation/images/map/person.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/wookie/trunk/tutorials/geoLocation/images/map/readme.txt
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/images/map/readme.txt?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/images/map/readme.txt (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/images/map/readme.txt Tue Feb 9 21:42:53 2010
@@ -0,0 +1,20 @@
+The icon files in this folder are in the public domain and are sources from http://www.clker.com
+
+DISCLAIMER & NO WARRANTY
+
+BECAUSE CLKER.COM AND ITS CONTENTS ARE FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY,
+TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING,
+CLKER.COM AND ITS OWNERS PROVIDE THE CONTENT AND IMAGES 'AS IS' WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE CONTENT IS WITH YOU. SHOULD ANY PART OF CLKER.COM OR ITS CONTENT PROVE DEFECTIVE,
+OR NOT PUBLIC DOMAIN YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, CORRECTION AND OTHER
+COSTS THAT MIGHT HAPPEN TO YOU OR YOUR PRODUCT OR CLIENTS OR CUSTOMERS FROM USING CONTENT OR IMAGES
+FROM CLKER.COM OR ANY DERIVATIVES OF YOUR WORK THAT INCLUDED OR WAS DERIVED FROM OUR CONTENT.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL CLKER.COM, IT'S OWNERS, BE LIABLE TO YOU FOR
+DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
+DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
+PICTURES/IMAGES/SOFTWARE TO OPERATE WITH ANY PROGRAMS) THE SITE OR ITS CONTENTS, EVEN IF YOU HAVE
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/images/map/yellowPin.png
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/images/map/yellowPin.png?rev=908241&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/tutorials/geoLocation/images/map/yellowPin.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/wookie/trunk/tutorials/geoLocation/legal/geo_LICENSE.txt
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/legal/geo_LICENSE.txt?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/legal/geo_LICENSE.txt (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/legal/geo_LICENSE.txt Tue Feb 9 21:42:53 2010
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2009 Stan Wiechers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/legal/geo_position_js_simulator_LICENSE.txt
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/legal/geo_position_js_simulator_LICENSE.txt?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/legal/geo_position_js_simulator_LICENSE.txt (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/legal/geo_position_js_simulator_LICENSE.txt Tue Feb 9 21:42:53 2010
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2009 Stan Wiechers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulator.html
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulator.html?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulator.html (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulator.html Tue Feb 9 21:42:53 2010
@@ -0,0 +1,47 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+<meta http-equiv="pragma" content="no-cache" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>part1</title>
+<link rel="stylesheet" href="style/screen.css" type="text/css" />
+
+<script type="text/javascript"
+ src="/wookie/shared/js/jquery/jquery-1.3.2.min.js"></script>
+<script src="http://code.google.com/apis/gears/gears_init.js"
+ type="text/javascript"></script>
+<script src="scripts/geo.js" type="text/javascript"></script>
+<script src="scripts/geo_position_js_simulator.js" type="text/javascript" charset="utf-8"></script>
+
+ <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
+ <script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
+ <!-- This Google Maps API key is for localhost only -->
+ <script src='http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAnfs7bKE82qgb3Zc2YyS-oBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSySz_REpPq-4WZA27OwgbtyR3VcA
+'></script>
+
+ <script src="scripts/map.js" type="text/javascript"></script>
+</head>
+
+<body onLoad="initMapWidget();">
+ <div id="mapPage">
+ <div style="width: 100%; height: 80%;" id="map"></div>
+ <p><span id="message"></span></p>
+ </div>
+</body>
+
+</html>
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulatorAndSettings.html
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulatorAndSettings.html?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulatorAndSettings.html (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/osmWithSimulatorAndSettings.html Tue Feb 9 21:42:53 2010
@@ -0,0 +1,59 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html>
+<head>
+<meta http-equiv="pragma" content="no-cache" />
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>part1</title>
+<link rel="stylesheet" href="style/screen.css" type="text/css" />
+
+<script type="text/javascript"
+ src="/wookie/shared/js/jquery/jquery-1.3.2.min.js"></script>
+<script src="http://code.google.com/apis/gears/gears_init.js"
+ type="text/javascript"></script>
+<script src="scripts/geo.js" type="text/javascript"></script>
+<script src="scripts/geo_position_js_simulator.js" type="text/javascript" charset="utf-8"></script>
+
+ <script src="http://www.openlayers.org/api/OpenLayers.js"></script>
+ <script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
+ <!-- This Google Maps API key is for localhost only -->
+ <script src='http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAnfs7bKE82qgb3Zc2YyS-oBT2yXp_ZAY8_ufC3CFXhHIE1NvwkxSySz_REpPq-4WZA27OwgbtyR3VcA
+'></script>
+
+ <script src="scripts/map.js" type="text/javascript"></script>
+</head>
+
+<body onLoad="initMapWidget();">
+ <div id="mapPage">
+ <div style="width: 100%; height: 80%;" id="map"></div>
+ <p><span id="message"></span></p>
+ <div id="settings">
+ <input type="submit"
+ class="groovybutton"
+ id ="settings"
+ value="settings"
+ onclick="showSettingsPage()"/>
+ </div>
+ </div>
+
+ <div style="display: none" id="settingsPage">
+ <h2>Settings</h2>
+ <div id="controls"/>
+ </div>
+</body>
+
+</html>
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/scripts/geo.js
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/scripts/geo.js?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/scripts/geo.js (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/scripts/geo.js Tue Feb 9 21:42:53 2010
@@ -0,0 +1,294 @@
+/*!
+ * geo-location-javascript v0.4.1
+ * http://code.google.com/p/geo-location-javascript/
+ *
+ * Copyright (c) 2009 Stan Wiechers
+ * Licensed under the MIT licenses.
+ *
+ * Revision: $Rev: 66 $:
+ * Author: $Author: whoisstan $:
+ * Date: $Date: 2010-01-10 08:27:48 -0500 (Sun, 10 Jan 2010) $:
+ */
+var bb_successCallback;
+var bb_errorCallback;
+
+function handleBlackBerryLocation()
+{
+ if (bb_successCallback && bb_errorCallback)
+ {
+ if(blackberry.location.latitude==0 && blackberry.location.longitude==0)
+ {
+ //http://dev.w3.org/geo/api/spec-source.html#position_unavailable_error
+ //POSITION_UNAVAILABLE (numeric value 2)
+ bb_errorCallback({message:"Position unavailable", code:2});
+ }
+ else
+ {
+ var timestamp=null;
+ //only available with 4.6 and later
+ //http://na.blackberry.com/eng/deliverables/8861/blackberry_location_568404_11.jsp
+ if (blackberry.location.timestamp)
+ {
+ timestamp=new Date(blackberry.location.timestamp);
+ }
+ bb_successCallback({timestamp:timestamp, coords: {latitude:blackberry.location.latitude,longitude:blackberry.location.longitude}});
+ }
+ //If you have passed the method a function, you can cancel the callback using blackberry.location.removeLocationUpdate().
+ //If you have passed a string, the callback cannot be removed.
+ //http://docs.blackberry.com/en/developers/deliverables/11849/blackberry_location_onLocationUpdate_568407_11.jsp
+ if(parseFloat(navigator.appVersion)>=4.6)
+ {
+ blackberry.location.removeLocationUpdate();
+ }
+
+ bb_successCallback = null;
+ bb_errorCallback = null;
+ }
+
+}
+
+var geo_position_js=function()
+{
+
+ var pub = {};
+ var provider=null;
+
+ pub.getCurrentPosition = function(successCallback,errorCallback,options){
+
+ provider.getCurrentPosition(successCallback, errorCallback,options);
+ }
+
+
+
+ pub.init = function()
+ {
+ try
+ {
+ if (typeof(geo_position_js_simulator) != "undefined")
+ {
+ provider = geo_position_js_simulator;
+ }
+ else if (typeof(bondi) != "undefined" && typeof(bondi.geolocation) != "undefined") {
+ provider = bondi.geolocation;
+ }
+
+ else if (typeof(window.google) != "undefined" && typeof(window.google.gears) != "undefined")
+ {
+ provider = google.gears.factory.create('beta.geolocation');
+ pub.getCurrentPosition = function(successCallback, errorCallback, options){
+
+ try
+ {
+ function _successCallback(p){
+ if (typeof(p.latitude) != "undefined") {
+ successCallback({
+ timestamp: p.timestamp,
+ coords: {
+ latitude: p.latitude,
+ longitude: p.longitude
+ }
+ });
+ }
+ else
+ {
+ successCallback(p);
+ }
+ }
+ provider.getCurrentPosition(_successCallback, errorCallback, options);
+ }
+ catch(e)
+ {
+ //this is thrown when the request is denied
+ errorCallback({message:e,code:1});
+ }
+ }
+ }
+ else if (typeof(navigator.geolocation) != "undefined")
+ {
+ provider = navigator.geolocation;
+ pub.getCurrentPosition = function(successCallback, errorCallback, options)
+ {
+ function _successCallback(p){
+
+ //for mozilla geode,it returns the coordinates slightly differently
+ if (typeof(p.latitude) != "undefined") {
+ successCallback({
+ timestamp: p.timestamp,
+ coords: {
+ latitude: p.latitude,
+ longitude: p.longitude
+ }
+ });
+ }
+ else
+ {
+ successCallback(p);
+ }
+ }
+ provider.getCurrentPosition(_successCallback, errorCallback, options);
+ }
+ pub.watchPosition = function(successCallback,errorCallback,options){
+
+ try
+ {
+ provider.watchPosition(successCallback,errorCallback,options);
+
+ pub.clearWatch = function(watchId){
+ if(typeof(provider.clearWatch) != "undefined") // Should always be true, but just in case
+ provider.clearWatch(watchId);
+ }
+ }
+ catch(e)
+ {
+ //thrown when method not available
+ errorCallback({message:e,code:1});
+ }
+
+ }
+ }
+ else if (typeof(Mojo) != "undefined" && typeof(Mojo.Service) != "undefined" && typeof(Mojo.Service.Request) != "Mojo.Service.Request") {
+ provider = true;
+ pub.getCurrentPosition = function(successCallback, errorCallback, options){
+
+ parameters = {};
+ if (options) {
+ //http://developer.palm.com/index.php?option=com_content&view=article&id=1673#GPS-getCurrentPosition
+ if (options.enableHighAccuracy && options.enableHighAccuracy == true) {
+ parameters.accuracy = 1;
+ }
+ if (options.maximumAge) {
+ parameters.maximumAge = options.maximumAge;
+ }
+ if (options.responseTime) {
+ if (options.responseTime < 5) {
+ parameters.responseTime = 1;
+ }
+ else
+ if (options.responseTime < 20) {
+ parameters.responseTime = 2;
+ }
+ else {
+ parameters.timeout = 3;
+ }
+ }
+ }
+
+
+ r = new Mojo.Service.Request('palm://com.palm.location', {
+ method: "getCurrentPosition",
+ parameters: parameters,
+ onSuccess: function(p){
+ successCallback({
+ timestamp: p.timestamp,
+ coords: {
+ latitude: p.latitude,
+ longitude: p.longitude,
+ heading: p.heading
+ }
+ });
+ },
+ onFailure: function(e){
+ if (e.errorCode == 1) {
+ errorCallback({
+ code: 3,
+ message: "Timeout"
+ });
+ }
+ else
+ if (e.errorCode == 2) {
+ errorCallback({
+ code: 2,
+ message: "Position Unavailable"
+ });
+ }
+ else {
+ errorCallback({
+ code: 0,
+ message: "Unknown Error: webOS-code" + errorCode
+ });
+ }
+ }
+ });
+ }
+
+ }
+ else if (typeof(device) != "undefined" && typeof(device.getServiceObject) != "undefined") {
+ provider = device.getServiceObject("Service.Location", "ILocation");
+
+ //override default method implementation
+ pub.getCurrentPosition = function(successCallback, errorCallback, options){
+ function callback(transId, eventCode, result){
+ if (eventCode == 4) {
+ errorCallback({
+ message: "Position unavailable",
+ code: 2
+ });
+ }
+ else {
+ //no timestamp of location given?
+ successCallback({
+ timestamp: null,
+ coords: {
+ latitude: result.ReturnValue.Latitude,
+ longitude: result.ReturnValue.Longitude,
+ altitude: result.ReturnValue.Altitude,
+ heading: result.ReturnValue.Heading
+ }
+ });
+ }
+ }
+ //location criteria
+ var criteria = new Object();
+ criteria.LocationInformationClass = "BasicLocationInformation";
+ //make the call
+ provider.ILocation.GetLocation(criteria, callback);
+ }
+ }
+ else if (typeof(window.blackberry) != "undefined" && blackberry.location.GPSSupported) {
+
+ // set to autonomous mode
+ blackberry.location.setAidMode(2);
+
+ //override default method implementation
+ pub.getCurrentPosition = function(successCallback, errorCallback, options){
+
+ //passing over callbacks as parameter didn't work consistently
+ //in the onLocationUpdate method, thats why they have to be set
+ //outside
+ bb_successCallback = successCallback;
+ bb_errorCallback = errorCallback;
+
+ //http://docs.blackberry.com/en/developers/deliverables/11849/blackberry_location_onLocationUpdate_568407_11.jsp
+ //On BlackBerry devices running versions of BlackBerry® Device Software earlier than version 4.6,
+ //this method must be passed as a string that is evaluated each time the location is refreshed.
+ //On BlackBerry devices running BlackBerry Device Software version 4.6 or later, you can pass a string,
+ //or use the method to register a callback function.
+ if(parseFloat(navigator.appVersion)>=4.6)
+ {
+ blackberry.location.onLocationUpdate(handleBlackBerryLocation());
+ }
+ else
+ {
+ blackberry.location.onLocationUpdate("handleBlackBerryLocation()");
+ }
+ blackberry.location.refreshLocation();
+
+ }
+ provider = blackberry.location;
+
+ }
+ }
+ catch (e) {
+ if (typeof(console) != "undefined") {
+ console.log(e);
+ }
+ }
+
+
+
+ return provider!=null;
+ }
+
+
+ return pub;
+}();
Added: incubator/wookie/trunk/tutorials/geoLocation/scripts/geo_position_js_simulator.js
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/scripts/geo_position_js_simulator.js?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/scripts/geo_position_js_simulator.js (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/scripts/geo_position_js_simulator.js Tue Feb 9 21:42:53 2010
@@ -0,0 +1,42 @@
+/*!
+ * geo-location-javascript v0.4.1 Simulator
+ * http://code.google.com/p/geo-location-javascript/
+ *
+ * Copyright (c) 2009 Stan Wiechers
+ * Licensed under the MIT licenses.
+ *
+ * Revision: $Rev: 62 $:
+ * Author: $Author: whoisstan $:
+ * Date: $Date: 2009-12-17 15:46:49 -0500 (Thu, 17 Dec 2009) $:
+ */
+var geo_position_js_simulator=function(){
+
+ var pub = {};
+ var current_pos=null;
+ pub.init = function(array)
+ {
+ var next=0;
+ for (i in array)
+ {
+ if(i==0)
+ {
+ current_pos=array[i];
+ }
+ else
+ {
+ setTimeout((function(pos) {
+ return function() {
+ current_pos=pos;
+ }
+ })(array[i]),next);
+ }
+ next+=array[i].duration;
+ }
+ }
+
+ pub.getCurrentPosition = function(locationCallback,errorCallback)
+ {
+ locationCallback(current_pos);
+ }
+ return pub;
+}();
\ No newline at end of file
Added: incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndLayers.js
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndLayers.js?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndLayers.js (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndLayers.js Tue Feb 9 21:42:53 2010
@@ -0,0 +1,147 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+var last_position = null;
+
+var zoom = 17;
+
+var map;
+var epsg4326;
+var route;
+var routeMarkerIcon;
+var req;
+
+/**
+ * Initialise the widget. The map will be created an tracking will be started.
+ *
+ * @return
+ */
+function initMapWidget() {
+ var options = {
+ maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
+ units:'meters',
+ projection: "EPSG:900913",
+ displayProjection: new OpenLayers.Projection("EPSG:4326"),
+
+ };
+ map = new OpenLayers.Map('map', options);
+
+ var mapnik = new OpenLayers.Layer.OSM.Mapnik("OpenStreetMap", {sphericalMercator:true});
+ var gmap = new OpenLayers.Layer.Google("Google", {sphericalMercator:true, numZoomLevels: 20});
+ var gphy = new OpenLayers.Layer.Google(
+ "Google Physical",
+ {type: G_PHYSICAL_MAP, sphericalMercator:true, numZoomLevels: 20}
+ );
+ var ghyb = new OpenLayers.Layer.Google(
+ "Google Hybrid",
+ {type: G_HYBRID_MAP, numZoomLevels: 20, sphericalMercator:true, numZoomLevels: 20}
+ );
+ var gsat = new OpenLayers.Layer.Google(
+ "Google Satellite",
+ {type: G_SATELLITE_MAP, numZoomLevels: 20, sphericalMercator:true, numZoomLevels: 20}
+ );
+
+ map.addLayers([mapnik, gmap, gphy, ghyb, gsat]);
+
+ route = new OpenLayers.Layer.Markers( "Route" );
+ map.addLayer(route);
+ var size = new OpenLayers.Size(20,34);
+ var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
+ routeMarkerIcon = new OpenLayers.Icon('images/map/person.png', size, offset);
+
+ map.addControl( new OpenLayers.Control.LayerSwitcher() );
+
+ epsg4326 = new OpenLayers.Projection("EPSG:4326");
+
+ startTracking()
+}
+
+/**
+ * Start tracking the current location. If the device has a GPS or other
+ * location facility (such as Google Gears) the users location will be updated
+ * periodically. If no such device is present one can be simulated for development
+ * purposes by setting the "simulate" preference to true.
+ *
+ * If there is no geo-location facility and no simulation then an error will
+ * be displayed in the message panel.
+ */
+function startTracking() {
+ if(geo_position_js.init()){
+ // Set the simulated route
+ locations=new Array();
+ locations.push({ coords:{latitude:51.760768,longitude:-1.260123},duration:5000 });
+ locations.push({ coords:{latitude:51.758643,longitude:-1.259823},duration:5000 });
+ locations.push({ coords:{latitude:51.757872,longitude:-1.25978},duration:4000 });
+ locations.push({ coords:{latitude:51.757766,longitude:-1.260381},duration:6000 });
+ locations.push({ coords:{latitude:51.757421,longitude:-1.260166},duration:5000 });
+ locations.push({ coords:{latitude:51.756757,longitude:-1.259866},duration:5000 });
+ locations.push({ coords:{latitude:51.756491,longitude:-1.261368},duration:5000 });
+ locations.push({ coords:{latitude:51.756039,longitude:-1.261711},duration:5000 });
+ locations.push({ coords:{latitude:51.754871,longitude:-1.261325},duration:5000 });
+ geo_position_js_simulator.init(locations);
+
+ var lonLat = new OpenLayers.LonLat(locations[0].coords.longitude, locations[0].coords.latitude);
+ lonLat.transform( epsg4326, map.getProjectionObject());
+ map.setCenter(lonLat, zoom);
+ setPosition(locations[0]);
+ setInterval(retrieveCurrentLocation, 2000);
+ } else{
+ document.getElementById("message").innerHTML = "Geo-Location functionality not available";
+ }
+}
+
+/**
+ * Retrieve the current location and, if successful, set the current position on the map.
+ */
+function retrieveCurrentLocation() {
+ document.getElementById('message').innerHTML="Receiving...";
+ geo_position_js.getCurrentPosition(setPosition, locationErrorCallback, {enableHighAccuracy:true});
+}
+
+/**
+ * Set the position on the map. The map will be centred on this position.
+ *
+ * @param p - the position object, providing coords.longitde and coords.latitude fields
+ */
+function setPosition(p) {
+ if (p == null) {
+ document.getElementById("message").innerHTML = "Failed to locate you.";
+ return;
+ }
+
+ if(last_position && last_position.coords.latitude==p.coords.latitude && last_position.coords.longitude==p.coords.longitude) {
+ document.getElementById('message').innerHTML="User has not moved.";
+ return;
+ }
+
+ last_position = p;
+ document.getElementById('message').innerHTML="User has moved.";
+
+ var lonLat = new OpenLayers.LonLat(p.coords.longitude, p.coords.latitude);
+ lonLat.transform( epsg4326, map.getProjectionObject());
+
+ route.addMarker(new OpenLayers.Marker(lonLat, routeMarkerIcon.clone()));
+ map.panTo(lonLat);
+}
+
+/**
+ * Display an error message if there is a problem retrieving the current location.
+ * @param p
+ */
+function locationErrorCallback(p) {
+ document.getElementById("message").innerHTML = p.message;
+}
Added: incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndSettings.js
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndSettings.js?rev=908241&view=auto
==============================================================================
--- incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndSettings.js (added)
+++ incubator/wookie/trunk/tutorials/geoLocation/scripts/map_osmWithSimulatorAndSettings.js Tue Feb 9 21:42:53 2010
@@ -0,0 +1,186 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+var last_position = null;
+
+var zoom = 17;
+
+var map;
+var epsg4326;
+var route;
+var routeMarkerIcon;
+var req;
+
+/**
+ * Initialise the widget. The map will be created an tracking will be started.
+ *
+ * @return
+ */
+function initMapWidget() {
+ var options = {
+ maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
+ units:'meters',
+ projection: "EPSG:900913",
+ displayProjection: new OpenLayers.Projection("EPSG:4326"),
+
+ };
+ map = new OpenLayers.Map('map', options);
+
+ var mapnik = new OpenLayers.Layer.OSM.Mapnik("OpenStreetMap", {sphericalMercator:true});
+ var gmap = new OpenLayers.Layer.Google("Google", {sphericalMercator:true, numZoomLevels: 20});
+ var gphy = new OpenLayers.Layer.Google(
+ "Google Physical",
+ {type: G_PHYSICAL_MAP, sphericalMercator:true, numZoomLevels: 20}
+ );
+ var ghyb = new OpenLayers.Layer.Google(
+ "Google Hybrid",
+ {type: G_HYBRID_MAP, numZoomLevels: 20, sphericalMercator:true, numZoomLevels: 20}
+ );
+ var gsat = new OpenLayers.Layer.Google(
+ "Google Satellite",
+ {type: G_SATELLITE_MAP, numZoomLevels: 20, sphericalMercator:true, numZoomLevels: 20}
+ );
+
+ map.addLayers([mapnik, gmap, gphy, ghyb, gsat]);
+
+ route = new OpenLayers.Layer.Markers( "Route" );
+ map.addLayer(route);
+ var size = new OpenLayers.Size(20,34);
+ var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
+ routeMarkerIcon = new OpenLayers.Icon('images/map/person.png', size, offset);
+
+ map.addControl( new OpenLayers.Control.LayerSwitcher() );
+
+ epsg4326 = new OpenLayers.Projection("EPSG:4326");
+
+ startTracking();
+}
+
+/**
+ * Start tracking using a simulated GPS for development.
+ *
+ */
+function startTracking() {
+ if(geo_position_js.init()){
+ // Set the simulated route
+ locations=new Array();
+ locations.push({ coords:{latitude:51.760768,longitude:-1.260123},duration:5000 });
+ locations.push({ coords:{latitude:51.758643,longitude:-1.259823},duration:5000 });
+ locations.push({ coords:{latitude:51.757872,longitude:-1.25978},duration:4000 });
+ locations.push({ coords:{latitude:51.757766,longitude:-1.260381},duration:6000 });
+ locations.push({ coords:{latitude:51.757421,longitude:-1.260166},duration:5000 });
+ locations.push({ coords:{latitude:51.756757,longitude:-1.259866},duration:5000 });
+ locations.push({ coords:{latitude:51.756491,longitude:-1.261368},duration:5000 });
+ locations.push({ coords:{latitude:51.756039,longitude:-1.261711},duration:5000 });
+ locations.push({ coords:{latitude:51.754871,longitude:-1.261325},duration:5000 });
+ geo_position_js_simulator.init(locations);
+
+ var lonLat = new OpenLayers.LonLat(locations[0].coords.longitude, locations[0].coords.latitude);
+ lonLat.transform( epsg4326, map.getProjectionObject());
+ map.setCenter(lonLat, zoom);
+ setPosition(locations[0]);
+ setInterval(retrieveCurrentLocation, 2000);
+ } else{
+ document.getElementById("message").innerHTML = "Geo-Location functionality not available";
+ }
+}
+
+/**
+ * Retrieve the current location and, if successful, set the current position on
+ * the map.
+ */
+function retrieveCurrentLocation() {
+ document.getElementById('message').innerHTML="Receiving...";
+ geo_position_js.getCurrentPosition(setPosition, locationErrorCallback, {enableHighAccuracy:true});
+}
+
+/**
+ * Set the position on the map. The map will be centred on this position.
+ *
+ * @param p -
+ * the position object, providing coords.longitde and coords.latitude
+ * fields
+ */
+function setPosition(p) {
+ if (p == null) {
+ document.getElementById("message").innerHTML = "Failed to locate you.";
+ return;
+ }
+
+ if(last_position && last_position.coords.latitude==p.coords.latitude && last_position.coords.longitude==p.coords.longitude) {
+ document.getElementById('message').innerHTML="User has not moved.";
+ return;
+ }
+
+ last_position = p;
+ document.getElementById('message').innerHTML="User has moved.";
+
+ var lonLat = new OpenLayers.LonLat(p.coords.longitude, p.coords.latitude);
+ lonLat.transform( epsg4326, map.getProjectionObject());
+
+ route.addMarker(new OpenLayers.Marker(lonLat, routeMarkerIcon.clone()));
+ map.panTo(lonLat);
+}
+
+/**
+ * Display an error message if there is a problem retrieving the current
+ * location.
+ *
+ * @param p
+ */
+function locationErrorCallback(p) {
+ document.getElementById("message").innerHTML = p.message;
+}
+
+/**
+ * Display the settings page and hide the map page.
+ *
+ * @param event
+ * the event that triggered this change in the display
+ */
+function showSettingsPage(event) {
+ var mapPage = document.getElementById("mapPage");
+ var settingsPage = document.getElementById("settingsPage");
+ mapPage.style.display="none";
+
+ var htmlText = "<input type=\"checkbox\" id=\"displayStatus\" name=\"displayStatus\" onchange=\"Widget.preferences.setItem(\'displayStatus\', this.checked)\"";
+ if (Widget.preferences.getItem("displayStatus")) {
+ htmlText += " checked";
+ }
+ htmlText += "/>";
+ htmlText += "<label for=\"displayStatus\">Display status</p>";
+ htmlText += "<input type=\"submit\" class=\"groovybutton\" id =\"done\" value=\"Done\" onClick=\"showMapPage()\">";
+ WidgetUtil.setValue("controls", htmlText, { escapeHtml:false });
+ settingsPage.style.display="block";
+}
+
+/**
+ * Display the map page and hide the settings page.
+ *
+ */
+function showMapPage() {
+ var mapPage = document.getElementById("mapPage");
+ var settingsPage = document.getElementById("settingsPage");
+ mapPage.style.display="block";
+ settingsPage.style.display="none";
+
+ if (Widget.preferences.getItem("displayStatus")) {
+ document.getElementById("message").style.display="block";
+ } else {
+ document.getElementById("message").style.display="none";
+ }
+}
\ No newline at end of file