Initial checkin of the Modello Navigation app 89/18989/1
authorbrianjjones <brian.j.jones@intel.com>
Thu, 3 Apr 2014 23:42:29 +0000 (16:42 -0700)
committerbrianjjones <brian.j.jones@intel.com>
Thu, 3 Apr 2014 23:42:40 +0000 (16:42 -0700)
Change-Id: Ic442a4be25f042f322bf0c6ac211e3940b0ec33b
Signed-off-by: brianjjones <brian.j.jones@intel.com>
13 files changed:
Makefile [new file with mode: 0644]
config.xml [new file with mode: 0644]
css/style.css [new file with mode: 0644]
icon.png [new file with mode: 0644]
images/icon_arrow_left.png [new file with mode: 0644]
images/icon_arrow_right.png [new file with mode: 0644]
images/icon_arrow_straight.png [new file with mode: 0644]
index.html [new file with mode: 0644]
js/main.js [new file with mode: 0644]
js/v3_epoly.js [new file with mode: 0644]
packaging/html5-ui-nav.changes [new file with mode: 0644]
packaging/html5-ui-nav.spec [new file with mode: 0644]
templates/placesListDelegate.html [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..8889bd4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+PROJECT = html5UINav
+
+VERSION := 0.0.1
+PACKAGE = $(PROJECT)-$(VERSION)
+
+INSTALL_FILES = $(PROJECT).wgt
+INSTALL_DIR = ${DESTDIR}/opt/usr/apps/.preinstallWidgets
+
+wgtPkg:
+       zip -r $(PROJECT).wgt config.xml css icon.png images index.html js templates
+
+install:
+       @echo "Installing Navigation, stand by..."
+       mkdir -p $(INSTALL_DIR)/
+       cp $(PROJECT).wgt $(INSTALL_DIR)/
+
+dist:
+       tar czf ../$(PACKAGE).tar.bz2 .
diff --git a/config.xml b/config.xml
new file mode 100644 (file)
index 0000000..d1563d2
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://com.intel.tizen/navigationgoogle" version="1.0.0" viewmodes="fullscreen">
+    <access origin="*" subdomains="true"/>
+    <tizen:application id="html5POC08.Nav" package="html5POC08" required_version="2.1"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>Navigation</name>
+    <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
+       <tizen:privilege name="http://tizen.org/privilege/filesystem.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/content.read" />
+    <tizen:privilege name="http://tizen.org/privilege/speech" />
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.admin" />
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.spp" />
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.gap" />
+    <tizen:setting screen-orientation="portrait"
+               context-menu="enable" background-support="disable" encryption="disable"
+               install-location="auto" />
+</widget>
diff --git a/css/style.css b/css/style.css
new file mode 100644 (file)
index 0000000..aac127d
--- /dev/null
@@ -0,0 +1,134 @@
+.placesLibraryContentList .placesElement {
+       padding: 10px 0 10px 0;
+       height: 70px;
+       box-shadow: none;
+       border-bottom-style: solid;
+       border-bottom-width: 2px;
+       line-height: 0;
+       text-align: left;
+       cursor: pointer;
+}
+
+.placesLibraryContentList .placesBox {
+       display: inline-block;
+       vertical-align: top;
+       padding-top: 20px;
+       background-color: transparent !important;
+}
+
+#upNextRectangle {
+       position: absolute;
+       left: 35px;
+       top: 100px;
+}
+
+#turnArrow {
+       position: absolute;
+       top: 135px;
+       left: 45px;
+       width: 50px;
+       height: 37px;
+       background-repeat: no-repeat;
+       background-position: center center;
+}
+
+.navigationPanel {
+       position: absolute;
+       top: 128px;
+       left: 106px;
+       width: 470px;
+       text-transform: uppercase;
+}
+
+#distanceTo {
+       position: absolute;
+       top: 180px;
+       left: 35px;
+       width: 70px;
+       text-align: center;
+}
+
+#destinationProgress {
+       position: absolute;
+       left: 9px;
+       top: 189px;
+       width: 700px;
+       height: 62px;
+}
+
+#destinationItem {
+       position: absolute;
+       left: 35px;
+       top: 233px;
+       width: 410px;
+}
+
+#destinationAddress {
+       margin-top: 2px;
+}
+
+#destinationAddressTown {
+       margin-top: 2px;
+       display: none;
+}
+
+#stillToGoItem {
+       position: absolute;
+       left: 450px;
+       top: 232px;
+       max-width: 260px;
+}
+
+#stillToGoTimeAndDistance {
+       margin-top: 2px;
+}
+
+#arrivalText {
+       margin-top: 6px;
+}
+
+.mapPanel {
+       position: absolute;
+       top: 330px;
+       width: 720px;
+       height: 805px;
+}
+
+.iconBbox {
+       left: 590px;
+       top: 990px;
+       border-style: solid;
+       border-width: 2px;
+       position: absolute;
+       width: 110px;
+       height: 80px;
+}
+
+.iconBbox:active {
+       top: 991px;
+}
+
+.satelitteIcon {
+       width: 56px;
+       height: 54px;
+       position: absolute;
+       margin: auto;
+       top: 0;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       display: none;
+       background-repeat: no-repeat;
+}
+
+.mapIcon {
+       margin: auto;
+       position: absolute;
+       top: 0;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       width: 56px;
+       height: 40px;
+       background-repeat: no-repeat;
+}
\ No newline at end of file
diff --git a/icon.png b/icon.png
new file mode 100644 (file)
index 0000000..fda31dc
Binary files /dev/null and b/icon.png differ
diff --git a/images/icon_arrow_left.png b/images/icon_arrow_left.png
new file mode 100644 (file)
index 0000000..6b2776a
Binary files /dev/null and b/images/icon_arrow_left.png differ
diff --git a/images/icon_arrow_right.png b/images/icon_arrow_right.png
new file mode 100644 (file)
index 0000000..6fbf3fe
Binary files /dev/null and b/images/icon_arrow_right.png differ
diff --git a/images/icon_arrow_straight.png b/images/icon_arrow_straight.png
new file mode 100644 (file)
index 0000000..5069906
Binary files /dev/null and b/images/icon_arrow_straight.png differ
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..0cb1f19
--- /dev/null
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport"
+       content="width=720, height=1280, user-scalable = no">
+<meta http-equiv="cache-control" content="no-cache" />
+<title>Navigation</title>
+
+<!--  jquery and plugins  -->
+<script type="text/javascript"
+       src="./css/car/components/jQuery/jquery-1.8.2.js"></script>
+<script type="text/javascript"
+       src="./css/car/components/knockout/knockout.js"></script>
+
+<!-- user and car theme, theme engine  -->
+<link rel="stylesheet" href="./css/car/car.css" />
+<link rel="stylesheet"
+       href="./css/car/components/incomingCall/incomingCall.css" />
+<script type="text/javascript" src='./css/car/car.js'></script>
+<script type='text/javascript' src='./js/services/bootstrap.js'></script>
+
+<script type='text/javascript'
+       src='./css/car/components/boxCaption/boxCaption.js'></script>
+<link rel="stylesheet"
+       href="./css/car/components/boxCaption/boxCaption.css" />
+<script type='text/javascript'
+       src='./css/car/components/topBarIcons/topBarIcons.js'></script>
+<link rel="stylesheet"
+       href="./css/car/components/topBarIcons/topBarIcons.css" />
+<script type="text/javascript"
+       src="./css/car/components/bottomPanel/bottomPanel.js"></script>
+<script type="text/javascript"
+       src="./css/car/components/progressBar/progressBar.js"></script>
+<link rel="stylesheet"
+       href="./css/car/components/progressBar/progressBar.css" />
+<script type="text/javascript"
+       src="http://maps.google.com/maps/api/js?sensor=false&language=en"></script>
+
+<!-- jsRender Library Import -->
+<script type="text/javascript"
+       src="./css/car/components/jsViews/jsrender.js"></script>
+<script type="text/javascript"
+       src="./css/car/components/jsViews/template.js"></script>
+
+<script type="text/javascript"
+       src='./css/car/components/alphabetBookmark/alphabetBookmark.js'></script>
+<link rel="stylesheet"
+       href="./css/car/components/alphabetBookmark/alphabetBookmark.css" />
+<script type="text/javascript"
+       src="./css/car/components/library/library.js"></script>
+<link rel="stylesheet" href="./css/car/components/library/library.css" />
+
+<!-- Navigation -->
+<script type="text/javascript" src="./js/main.js"></script>
+<script type="text/javascript" src="./js/v3_epoly.js"></script>
+<link rel="stylesheet" type="text/css" href="./css/style.css" />
+
+</head>
+
+<body>
+       <div id="wrapper" class="wrapper">
+               <div id="topBarIcons"></div>
+
+               <div id="placesButton"
+                       class="libraryButton fontSizeSmaller fontWeightBold fontColorNormal">PLACES</div>
+
+               <div id="upNextRectangle"></div>
+               <div id="turnArrow"></div>
+
+               <div id="navigationPanel"
+                       class="navigationPanel fontSizeLarge fontWeightBold fontColorNormal threeLinesEllipsis"></div>
+
+               <div id="distanceTo" class=" fontSizeSmaller fontColorDimmedLight "></div>
+
+               <div id="destinationProgress"></div>
+
+               <div id="destinationItem">
+                       <div id="destinationRectangle"></div>
+                       <div id="destinationAddress"
+                               class="fontSizeSmall fontWeightBold fontColorNormal twoLinesEllipsis"></div>
+
+                       <div id="destinationAddressTown"
+                               class="fontSizeXXSmall fontColorDimmedLight"></div>
+               </div>
+
+               <div id="stillToGoItem">
+                       <div id="stillToGoRectangle"></div>
+                       <div id="stillToGoTimeAndDistance"
+                               class="fontSizeXLarge fontColorNormal oneLineEllipsis"></div>
+                       <div id="arrivalText"
+                               class="fontSizeSmaller fontWeightBold fontColorNormal"></div>
+               </div>
+
+               <div data-role="content">
+                       <div id="map_div" class="mapPanel"></div>
+               </div>
+
+               <div
+                       class="iconBbox button bgColorDark borderColorDark boxShadow4Active"
+                       onClick="switchMapSatelitteView()">
+                       <div id="satelliteButton" class="satelitteIcon"></div>
+                       <div id="mapButton" class="mapIcon"></div>
+               </div>
+       </div>
+
+       <div id="placesLibrary" class="library pageBgColorNormalTransparent"></div>
+       <div id="bottomPanel" class="bottomPanel bottomPanelImg"></div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/js/main.js b/js/main.js
new file mode 100644 (file)
index 0000000..4e22ae3
--- /dev/null
@@ -0,0 +1,778 @@
+/*jshint eqnull:true*/
+/*global google*/
+
+/**
+ * Navigation application allows user to use Google Maps to navigate around in predefined set of waypoints in Places library with Text-To-Speech feature
+ * (via {{#crossLink "Speech"}}{{/crossLink}} object). Nvigation doesn't use GPS but updates position of marker along the route in periodic intervals.
+ * Default navigation waypoints are defined by:
+ *
+ * * start point: {{#crossLink "NavigationGoogle/originAddress:property"}}{{/crossLink}} property
+ * * end point: {{#crossLink "NavigationGoogle/destinationAddress:property"}}{{/crossLink}} property
+ *
+ * To add additional places or update existing ones please change property {{#crossLink "NavigationGoogle/places:property"}}{{/crossLink}}.
+ *
+ * Hover and click on elements in images below to navigate to components of Navigation application.
+ *
+ * <img id="Image-Maps_1201312180420487" src="../assets/img/navigation.png" usemap="#Image-Maps_1201312180420487" border="0" width="650" height="1148" alt="" />
+ *   <map id="_Image-Maps_1201312180420487" name="Image-Maps_1201312180420487">
+ *     <area shape="rect" coords="0,0,573,78" href="../classes/topbaricons.html" alt="Top bar icons" title="Top bar icons" />
+ *     <area shape="rect" coords="0,994,644,1147" href="../classes/bottompanel.html" alt="Bottom panel" title="Bottom panel" />
+ *     <area shape="rect" coords="521,133,645,186" href="../classes/Library.html" alt="Places library" title="Places library"    />
+ *     <area shape="poly" coords="1,78,512,80,514,191,648,192,646,291,0,292," href="../classes/NavigationGoogle.html#method_updateNavigationPanel" alt="Navigation panel" title="Navigation panel"   />
+ *     <area shape="poly" coords="1,298,648,301,644,890,530,887,528,970,648,969,647,1022,3,1022," href="../classes/NavigationGoogle.html#method_animate" alt="Animate along waypoints" title="Animate along waypoints"   />
+ *     <area shape="rect" coords="530,888,631,965" href="../classes/NavigationGoogle.html#method_switchMapSatelitteView" alt="Switch map mode" title="Switch map mode"    />
+ *   </map>
+ * @module NavigationGoogleApplication
+ * @main NavigationGoogleApplication
+ * @class NavigationGoogle
+ */
+
+/**
+ * Reference to instance of class object this class is inherited from dataModel {@link CarIndicator}.
+ * @property carInd {Object}
+ */
+var carInd;
+
+/**
+ * Array of destination addresses used in places library list.
+ * @property places {Object[String]}
+ * @for NavigationGoogle
+ */
+var places = [
+              {destinationAddress: "Golden Gate Bridge, San Francisco, CA 94129, USA"},
+              {destinationAddress: "Coit Tower, San Francisco, CA 94133, USA"},
+              {destinationAddress: "The Exploratorium, Pier 15, San Francisco, CA 94111, USA"},
+              {destinationAddress: "Steinhart Aquarium, 55 Music Concourse Drive, San Francisco, CA 94122, USA"}
+             ];
+
+/**
+ * Holds origin address value.
+ * @for NavigationGoogle
+ * @property originAddress {String}
+ */
+var originAddress = "Fell Street, San Francisco, CA, United States";
+
+/**
+ * Holds destination address value.
+ * @for NavigationGoogle
+ * @property destinationAddress {String}
+ */
+var destinationAddress = "75 Hagiwara Tea Garden Dr San Francisco, CA 94118";
+
+/**
+ * Holds origin object value.
+ * @for NavigationGoogle
+ * @private
+ * @property origin {String}
+ */
+var origin = null;
+
+/**
+ * Holds destination object value.
+ * @for NavigationGoogle
+ * @private
+ * @property destination {String}
+ */
+var destination = null;
+
+/**
+ * Holds map object.
+ * @for NavigationGoogle
+ * @private
+ * @property map {Object}
+ */
+var map;
+
+/**
+ * Holds geocoder object.
+ * @for NavigationGoogle
+ * @private
+ * @property geocoder {Object}
+ */
+var geocoder = null;
+
+/**
+ * Holds direction service method.
+ * @for NavigationGoogle
+ * @private
+ * @property directionsService {Object}
+ */
+var directionsService = null;
+
+/**
+ * Holds direction renderer method.
+ * @for NavigationGoogle
+ * @private
+ * @property directionRenderer {Object}
+ */
+var directionRenderer = null;
+
+/**
+ * Holds polyline method.
+ * @for NavigationGoogle
+ * @private
+ * @property polyline {Object}
+ */
+var polyline = null;
+
+/**
+ * Holds route object method.
+ * @for NavigationGoogle
+ * @private
+ * @property route {Object}
+ */
+var route = null;
+
+/**
+ * Holds marker object.
+ * @for NavigationGoogle
+ * @private
+ * @property marker {Object}
+ */
+var marker = null;
+
+/**
+ * Holds direction instructions objects array.
+ * @for NavigationGoogle
+ * @private
+ * @property instructions {Object[]}
+ */
+var instructions = [];
+
+/**
+ * Holds status if metric system is used.
+ * @for NavigationGoogle
+ * @private
+ * @property useMetricSystem {Boolean}
+ */
+var useMetricSystem = false;
+
+/**
+ * Holds step value in meters.
+ * @for NavigationGoogle
+ * @private
+ * @property step {Integer}
+ */
+var step = 10; // metres
+
+/**
+ * Holds tick value in milliseconds.
+ * @for NavigationGoogle
+ * @private
+ * @property tick {Integer}
+ */
+var tick = 200; // milliseconds
+
+/**
+ * Holds distance value.
+ * @for NavigationGoogle
+ * @private
+ * @property distance {Integer}
+ */
+var polDistance = 0;
+
+/**
+ * Holds remaining distance value.
+ * @for NavigationGoogle
+ * @private
+ * @property remainingDistance {Integer}
+ */
+var remainingDistance = 0;
+
+/**
+ * Holds remaining step distance value.
+ * @for NavigationGoogle
+ * @private
+ * @property remainingStepDistance {Integer}
+ */
+var remainingStepDistance = 0;
+
+/**
+ * Holds remaining time value.
+ * @for NavigationGoogle
+ * @private
+ * @property remainingTime {Integer}
+ */
+var remainingTime = 0;
+
+/**
+ * Holds route duration value.
+ * @for NavigationGoogle
+ * @private
+ * @property routeDuration {Integer}
+ */
+var routeDuration = 0;
+
+/**
+ * Holds average speed value.
+ * @for NavigationGoogle
+ * @private
+ * @property averageSpeed {Integer}
+ */
+var averageSpeed = 0;
+
+/**
+ * Holds instruction index value.
+ * @for NavigationGoogle
+ * @private
+ * @property instructionIndex {Integer}
+ */
+var instructionIndex = 0;
+
+/**
+ * Holds status value if instruction changed.
+ * @for NavigationGoogle
+ * @private
+ * @property instructionChanged {Boolean}
+ */
+var instructionChanged = true;
+
+/**
+ * Holds animation timer object.
+ * @for NavigationGoogle
+ * @private
+ * @property timerHandle {Object}
+ */
+var timerHandle;
+
+/**
+ * Instance of class Bootstrap, this class provides unified way to boot up the HTML applications by loading shared components in proper order.
+ * * {{#crossLink "Bootstrap"}}{{/crossLink}}
+ *
+ * @property bootstrap {Object}
+ */
+var bootstrap;
+
+/**
+ * Strips the HTML code removing all the HTML marks from it.
+ * @method strip
+ * @for NavigationGoogle
+ * @private
+ * @param html {String} HTML code
+ */
+function strip(html) {
+       "use strict";
+    var tmp = document.createElement("DIV");
+    tmp.innerHTML = html;
+    return tmp.textContent || tmp.innerText;
+}
+/**
+ * Method switches between satellite or classic map view.
+ * @method switchMapSatelitteView
+ * @for NavigationGoogle
+ */
+function switchMapSatelitteView() {
+       "use strict";
+       /*global google */
+       if (map.getMapTypeId() === google.maps.MapTypeId.ROADMAP) {
+               map.setMapTypeId(google.maps.MapTypeId.SATELLITE);
+               $(".mapIcon").css('display', 'none');
+               $(".satelitteIcon").css('display', 'inherit');
+       } else if (map.getMapTypeId() === google.maps.MapTypeId.SATELLITE) {
+               map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
+               $(".satelitteIcon").css('display', 'none');
+               $(".mapIcon").css('display', 'inherit');
+       } else {
+               console.log("Othere map type is " + map.getMapTypeId());
+       }
+       console.log(map.getMapTypeId());
+}
+
+/**
+ * NMethod changes navigation arrow based on instruction text.
+ * @method changeNavigationArrow
+ * @for NavigationGoogle
+ * @param instructionText {String} Instruction text.
+ */
+function changeNavigationArrow(instructionText) {
+       "use strict";
+       var turnRight = instructionText.indexOf("right");
+       var turnLeft = instructionText.indexOf("left");
+
+       if (turnRight > 0 && turnRight < 10) {
+               //"left" or "right" is on the beginning of instruction step
+               $("#turnArrow").css("background-image", "url('images/icon_arrow_right.png')");
+       } else if (turnLeft > 0 && turnLeft < 10) {
+               //"left" or "right" is on the beginning of instruction step
+               $("#turnArrow").css("background-image", "url('images/icon_arrow_left.png')");
+       } else {
+               $("#turnArrow").css("background-image", "url('images/icon_arrow_straight.png')");
+       }
+}
+
+/**
+ * Method changes format of distance value text.
+ * @method formatMeters
+ * @for NavigationGoogle
+ * @param meters {Integer} Distance value in meters.
+ * @param fontSize {Integer} Font size.
+ * @return {String} Distance in meters width changed font format.
+ */
+function formatMeters(meters, fontSize) {
+       "use strict";
+       if (meters > 500) {
+               return (Math.round(meters / 100)) / 10 + "<span class=" + fontSize + ">KM</span>";
+       } else {
+               return Math.round(meters) + "<span class=" + fontSize + ">m</span>";
+       }
+}
+
+/**
+ * Method converts distance from meters to feets and changing formats of distance value text.
+ * @method convertMetersToFeetsMiles
+ * @for NavigationGoogle
+ * @param meters {Integer} Distance value in meters.
+ * @param fontSize {Integer} Font size.
+ * @return {String} Distance in feets width changed font format.
+ */
+function convertMetersToFeetsMiles(meters, fontSize) {
+       "use strict";
+       var feets = meters * 3.280839895;
+       if (feets > 528) {
+               return (Math.round(feets / 528)) / 10 + "<span class=" + fontSize + ">MI</span>";
+       } else {
+               return Math.round(feets) + "<span class=" + fontSize + ">ft</span>";
+       }
+}
+
+/**
+ * Method converts seconds to time.
+ * @method secondsToTime
+ * @for NavigationGoogle
+ * @param secs {Integer} Time value in seconds.
+ * @return {Object} Time in object with hours, minutes and second separated format.
+ */
+function secondsToTime(secs) {
+       "use strict";
+       var hours = Math.floor(secs / (60 * 60));
+
+       var divisorForMinutes = secs % (60 * 60);
+       var minutes = Math.floor(divisorForMinutes / 60);
+
+       var divisorForSeconds = divisorForMinutes % 60;
+       var seconds = Math.ceil(divisorForSeconds);
+
+       var obj = {
+                       "h" : hours,
+                       "m" : minutes,
+                       "s" : seconds
+               };
+       return obj;
+}
+
+/**
+ * Method provides leading 0 to time value.
+ * @method addLeading0ToTime
+ * @for NavigationGoogle
+ * @param time {Integer} Time value.
+ * @return time {String} Time with leading 0.
+ */
+function addLeading0ToTime(time) {
+       "use strict";
+       if (time < 10) {
+               return "0" + time;
+       } else {
+               return time;
+       }
+}
+
+/**
+ * Method formats time to HHMM format.
+ * @method formatTimeToHHMM
+ * @for NavigationGoogle
+ * @param seconds {Integer} Time value in seconds.
+ * @return formatedTime {String} Time in format HHMM.
+ */
+function formatTimeToHHMM(seconds) {
+       "use strict";
+       var hours = secondsToTime(seconds).h;
+       var minutes = secondsToTime(seconds).m;
+       var formatedTime;
+
+       if (hours > 0 || minutes > 0) {
+               formatedTime = addLeading0ToTime(hours) + ":" + addLeading0ToTime(minutes);
+       } else {
+               formatedTime = seconds + "<span class='fontSizeSmall'>s</span>";
+       }
+       return formatedTime;
+}
+
+/**
+ * Method adds seconds to current time.
+ * @method addSecondsToCurrentTime
+ * @for NavigationGoogle
+ * @param secs {Integer} Time value in seconds.
+ * @return result {String} Time in format HHMM.
+ */
+function addSecondsToCurrentTime(secs) {
+   "use strict";
+   var todayDate = new Date();
+   var hours = todayDate.getHours();
+   var minutes = todayDate.getMinutes();
+   var seconds = todayDate.getSeconds();
+   var newSec = parseInt(seconds, 10) + parseInt(secs, 10);
+   var newMin;
+   var mins;
+   var sec;
+   var min;
+   var newHrs;
+
+   if (newSec > 59) {
+      mins = parseInt(newSec / 60, 10);
+      sec = newSec - mins * 60;
+      newMin = parseInt(minutes, 10) + mins;
+
+      if (newMin > 59) {
+         var hrs = parseInt(newMin / 60, 10);
+         min = newMin - (hrs * 60);
+         newHrs = parseInt(hours, 10) + hrs;
+      } else {
+         newHrs = hours;
+         min = newMin;
+      }
+   } else {
+      newHrs = hours;
+      min = minutes;
+      sec = newSec;
+   }
+
+   var format = "AM";
+
+   if (newHrs > 11) {
+      format = "PM";
+   }
+   if (newHrs > 12) {
+      newHrs = newHrs - 12;
+   }
+   if (newHrs === 0) {
+      newHrs = 12;
+   }
+   if (min < 10) {
+      min = "0" + min;
+   }
+
+   return newHrs + ":" + min + format;
+}
+
+/**
+ * Method update the navigation panel.
+ * @method updateNavigationPanel
+ * @for NavigationGoogle
+ */
+function updateNavigationPanel() {
+       "use strict";
+       if (instructionChanged) {
+               var instruction = strip(instructions[instructionIndex].instruction);
+               console.log("Instruction changed to '" + instruction + "'.");
+               $("#navigationPanel").html(instruction);
+               /* global Speech*/
+               Speech.vocalizeString(instruction);
+               changeNavigationArrow(instruction);
+               instructionChanged = false;
+       }
+
+       if (useMetricSystem === true) {
+               remainingStepDistance = formatMeters(remainingStepDistance, 'fontSizeSmaller');
+       } else {
+               remainingStepDistance = convertMetersToFeetsMiles(remainingStepDistance, 'fontSizeSmaller');
+       }
+
+       $("#distanceTo").html(remainingStepDistance);
+       $("#destinationProgress").progressBarPlugin('setPosition', (remainingDistance / polDistance) * 100);
+
+       var remainingTime = Math.round(remainingDistance / averageSpeed); //time in seconds
+       remainingTime = formatTimeToHHMM(remainingTime);        //seconds to hh:mm
+
+       if (useMetricSystem === true) {
+               remainingDistance = formatMeters(remainingDistance, 'fontSizeSmall');
+       } else {
+               remainingDistance =  convertMetersToFeetsMiles(remainingDistance, 'fontSizeSmall');
+       }
+
+       $("#stillToGoTimeAndDistance").html(remainingTime + " / " + remainingDistance);
+}
+
+/**
+ * Method animates current position along the route.
+ * @method animate
+ * @for NavigationGoogle
+ * @param d {Integer}
+ */
+function animate(d) {
+       "use strict";
+       if (d + step > instructions[instructionIndex].distanceValue) {
+               if (instructionIndex < instructions.length - 1) {
+                       instructionChanged = true;
+                       instructionIndex++;
+               }
+       }
+
+       if (d > polDistance) {
+               instructionIndex = instructions.length - 1;
+               instructionChanged = false;
+
+               remainingDistance = 0;
+               remainingStepDistance = 0;
+               remainingTime = 0;
+
+               updateNavigationPanel();
+
+               map.panTo(polyline.getPath().getAt(polyline.getPath().length - 1));
+               marker.setPosition(polyline.getPath().getAt(polyline.getPath().length - 1));
+
+               var option = {draggable: true};
+               map.setOptions(option);
+               return;
+       }
+
+       remainingDistance = polDistance - d;
+       remainingStepDistance = instructions[instructionIndex].distanceValue - d;
+
+       updateNavigationPanel();
+
+       var p = polyline.GetPointAtDistance(d);
+       map.panTo(p);
+       marker.setPosition(p);
+       timerHandle = setTimeout("animate(" + (d + step) + ")", tick);
+}
+
+/**
+ * Method starts animation.
+ * @method startAnimation
+ * @for NavigationGoogle
+ * @constructor
+ */
+function startAnimation() {
+       "use strict";
+       var option = {
+                       draggable: false
+               };
+       map.setOptions(option);
+
+       marker = new google.maps.Marker();
+       marker.setMap(map);
+       marker.setPosition(polyline.getPath().getAt(0));
+       map.setCenter(polyline.getPath().getAt(0));
+       polDistance = polyline.Distance();
+
+       console.log(polyline.getPath());
+       console.log(polDistance);
+       console.log(instructions);
+
+       remainingDistance = polDistance;
+       remainingStepDistance = instructions[instructionIndex].distanceValue;
+       routeDuration = route.duration.value;
+       remainingTime = routeDuration;
+       averageSpeed = (route.distance.value / routeDuration);
+
+       /* jshint camelcase: false */
+       $("#destinationAddress").html(destination.formatted_address);
+       $("#destinationAddressTown").html(destination.address_components[2].short_name + ", " + destination.address_components[3].short_name);
+       /* jshint camelcase: true */
+
+       var averageSpeedText;
+
+       if (useMetricSystem === true) {
+               averageSpeedText = Math.round(averageSpeed * 3.6) + "<span class='fontSizeXXSmall'> km/h</span>" + ")";
+       } else {
+               averageSpeedText = Math.round(averageSpeed * 2.2369362920544) + "<span class='fontSizeXXSmall'> MPH</span>" + ")";
+       }
+
+       $("#arrivalText").html("ARRIVAL " + addSecondsToCurrentTime(routeDuration) + " (" + averageSpeedText);
+
+       updateNavigationPanel();
+       window.setTimeout(function(){
+               animate(0);
+               }, 2000); // Allow time for the initial map display
+}
+
+/**
+ * Method renders the route.
+ * @method renderRoute
+ * @for NavigationGoogle
+ * @param origin {Object} Origin position object.
+ * @param destination {Object} Destination position object.
+ */
+function renderRoute(origin, destination) {
+       "use strict";
+       if (directionsService === null) {
+               directionsService = new google.maps.DirectionsService();
+       }
+
+       if (directionRenderer === null) {
+               directionRenderer = new google.maps.DirectionsRenderer();
+       }
+
+       directionRenderer.setMap(map);
+
+       var request = {
+                       origin: origin,
+                       destination: destination,
+                       travelMode: google.maps.DirectionsTravelMode.DRIVING
+               };
+
+       directionsService.route(request, function (response, status) {
+               console.log(status);
+               console.log(response);
+               if (status === google.maps.DirectionsStatus.OK && response.routes.length) {
+                       if (response.routes && response.routes[0] && response.routes[0].legs && response.routes[0].legs[0]) {
+                               polyline = new google.maps.Polyline({
+                                       path : []
+                               });
+
+                               route = response.routes[0].legs[0];
+                               directionRenderer.setDirections(response);
+
+                               var steps = route.steps;
+                               var distanceStep = 0;
+                               var j;
+                               for (j = 0; j < steps.length; j++) {
+                                       var latLngs = steps[j].path;
+                                       distanceStep = distanceStep + (steps[j].distance.value || 0);
+
+                                       var instruction = {
+                                                       distance: (steps[j].distance || 0),
+                                                       distanceValue: distanceStep,
+                                                       instruction: (steps[j].instructions ? steps[j].instructions.trim() : "")
+                                               };
+
+                                       instructions.push(instruction);
+                                       var k;
+                                       for (k = 0; k < latLngs.length; k++) {
+                                               polyline.getPath().push(latLngs[k]);
+                                       }
+                               }
+                               startAnimation();
+                       }
+               } else {
+                       console.log('Route calculation failed: ' + status);
+               }
+       });
+}
+
+/**
+ * Starts the navigation.
+ * @method startNavigation
+ * @for NavigationGoogle
+ */
+function startNavigation(){
+       "use strict";
+       try {
+               if (geocoder == null) {
+                       geocoder = new google.maps.Geocoder();
+               }
+               geocoder.geocode({
+                       address: originAddress
+               }, function (results, status) {
+                       if (status === "OK" && results.length) {
+                               origin = results[0] || null;
+                               map.setCenter(origin.geometry.location);
+                               geocoder.geocode({
+                                       address: destinationAddress
+                               }, function (results, status) {
+                                       if (status === "OK" && results.length) {
+                                               destination = results[0] || null;
+
+                                               if (origin && destination) {
+                                                       renderRoute(origin.geometry.location, destination.geometry.location);
+                                               }
+                                       } else {
+                                               console.log("Destination not found. Unable to get the route.");
+                                       }
+                               });
+                       } else {
+                               console.log("Origin not found. Unable to get the route.");
+                       }
+               });
+       } catch (error) {
+               console.log(error.message);
+       }
+}
+var bootstrap;
+$(document).ready(function () {
+       "use strict";
+       /* global Bootstrap*/
+       bootstrap = new Bootstrap(function (status) {
+               $("#topBarIcons").topBarIconsPlugin('init', 'navigation');
+               $("#upNextRectangle").boxCaptionPlugin('init', 'up next');
+               $("#destinationProgress").progressBarPlugin('init', 'progressBar');
+               $("#destinationRectangle").boxCaptionPlugin('init', 'destination');
+               $("#stillToGoRectangle").boxCaptionPlugin('init', 'still to go');
+               $('#bottomPanel').bottomPanel('init');
+
+               var options = {
+                       backgroundColor: "transparent",
+                       mapTypeId: google.maps.MapTypeId.ROADMAP,
+                       mapTypeControl: false,
+                       streetViewControl: false,
+                       zoom: 18
+               };
+
+               map = new google.maps.Map(document.getElementById("map_div"), options);
+
+               startNavigation();
+
+               $("#placesLibrary").library("setSectionTitle", "PLACES LIBRARY");
+               $("#placesLibrary").library("init");
+               $("#placesLibrary").library("hideAlphabet");
+               $("#placesLibrary").library("setGridBtnDisabled", true);
+               $("#placesLibrary").library("setSearchBtnDisabled", true);
+
+               $("#placesButton").on("click", function() {
+                       $("#placesLibrary").library("showPage");
+               });
+
+               var tabMenuItems = [ {
+                       text : "DESTINATIONS",
+                       selected : true
+               } ];
+
+               var tabMenuModel = {
+                       Tabs : tabMenuItems
+               };
+
+               $("#placesLibrary").library("tabMenuTemplateCompile", tabMenuModel);
+               $("#placesLibrary").library("setContentDelegate", "templates/placesListDelegate.html");
+               $("#placesLibrary").library("contentTemplateCompile", places, "placesLibraryContentList");
+       });
+});
+
+/**
+ * Restarts the navigation with a new destination address taken into account.
+ * @method changeDestinationAddress
+ * @for NavigationGoogle
+ * @param newDestinationAddress {String} a new destination address
+ */
+function changeDestinationAddress(newDestinationAddress) {
+       "use strict";
+       $("#placesLibrary").library("hidePage");
+
+       destinationAddress = newDestinationAddress;
+
+       origin = null;
+       destination = null;
+       polyline = null;
+       route = null;
+
+       polDistance = 0;
+       remainingDistance = 0;
+       remainingStepDistance = 0;
+       remainingTime = 0;
+       routeDuration = 0;
+       averageSpeed = 0;
+
+       instructions = [];
+       instructionIndex = 0;
+       instructionChanged = true;
+
+       marker.setMap(null);
+       marker = null;
+
+       clearTimeout(timerHandle);
+    timerHandle = null;
+
+    directionRenderer.setMap(null);
+    directionRenderer = null;
+
+    startNavigation();
+}
diff --git a/js/v3_epoly.js b/js/v3_epoly.js
new file mode 100644 (file)
index 0000000..ca72e3b
--- /dev/null
@@ -0,0 +1,107 @@
+/*global google*/
+
+// The first support methods that don't (yet) exist in v3
+google.maps.LatLng.prototype.distanceFrom = function (newLatLng) {
+       "use strict";
+       var EarthRadiusMeters = 6378137.0; // meters
+       var lat1 = this.lat();
+       var lon1 = this.lng();
+       var lat2 = newLatLng.lat();
+       var lon2 = newLatLng.lng();
+       var dLat = (lat2 - lat1) * Math.PI / 180;
+       var dLon = (lon2 - lon1) * Math.PI / 180;
+       var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
+       var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+       var d = EarthRadiusMeters * c;
+       return d;
+};
+
+google.maps.LatLng.prototype.latRadians = function () {
+       "use strict";
+       return this.lat() * Math.PI / 180;
+};
+
+google.maps.LatLng.prototype.lngRadians = function () {
+       "use strict";
+       return this.lng() * Math.PI / 180;
+};
+
+/**
+ * Returns the length of a path in metres.
+ * @method Distance
+ */
+google.maps.Polygon.prototype.Distance = function () {
+       "use strict";
+       var dist = 0, i = 0;
+       for (i = 1; i < this.getPath().getLength(); i++) {
+               dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
+       }
+       return dist;
+};
+
+/**
+ * Returns GLatLng of the point at the given distance along the path. Returns null if the path is shorter than the specified distance.
+ * @method GetPointAtDistance
+ * @param metres {Integer} distance in metres
+ */
+google.maps.Polygon.prototype.GetPointAtDistance = function (metres) {
+       "use strict";
+       // some awkward special cases
+       if (metres === 0) {
+               return this.getPath().getAt(0);
+       }
+       if (metres < 0) {
+               return null;
+       }
+       if (this.getPath().getLength() < 2) {
+               return null;
+       }
+
+       var dist = 0, olddist = 0, i = 0;
+
+       for (i = 1; (i < this.getPath().getLength() && dist < metres); i++) {
+               olddist = dist;
+               dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
+       }
+       if (dist < metres) {
+               return null;
+       }
+       var p1 = this.getPath().getAt(i - 2);
+       var p2 = this.getPath().getAt(i - 1);
+       var m = (metres - olddist) / (dist - olddist);
+       return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
+};
+
+/**
+ * Returns the Vertex number at the given distance along the path. Returns null if the path is shorter than the specified distance.
+ * @method GetIndexAtDistance
+ * @param metres {Integer} distance in metres
+ */
+google.maps.Polygon.prototype.GetIndexAtDistance = function (metres) {
+       "use strict";
+       // some awkward special cases
+       if (metres === 0) {
+               return this.getPath().getAt(0);
+       }
+       if (metres < 0) {
+               return null;
+       }
+       var dist = 0, i = 0;
+       for (i = 1; (i < this.getPath().getLength() && dist < metres); i++) {
+               dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
+       }
+       if (dist < metres) {
+               return null;
+       }
+       return i;
+};
+
+// Copy all the above functions to GPolyline
+google.maps.Polyline.prototype.Distance             = google.maps.Polygon.prototype.Distance;
+google.maps.Polyline.prototype.GetPointAtDistance   = google.maps.Polygon.prototype.GetPointAtDistance;
+google.maps.Polyline.prototype.GetIndexAtDistance   = google.maps.Polygon.prototype.GetIndexAtDistance;
+
+
+
+
+
diff --git a/packaging/html5-ui-nav.changes b/packaging/html5-ui-nav.changes
new file mode 100644 (file)
index 0000000..f4282bf
--- /dev/null
@@ -0,0 +1,3 @@
+* Thu Apr 03 2014 brianjjones <brian.j.jones@intel.com> 9a96c32
+- Initial checkin of the Modello Navigation app
+
diff --git a/packaging/html5-ui-nav.spec b/packaging/html5-ui-nav.spec
new file mode 100644 (file)
index 0000000..9d9589c
--- /dev/null
@@ -0,0 +1,39 @@
+Name:       html5_UI_Nav
+Summary:    A proof of concept pure html5 UI
+Version:    0.0.1
+Release:    1
+Group:      Applications/System
+License:    Apache 2.0
+URL:        http://www.tizen.org
+Source0:    %{name}-%{version}.tar.bz2
+BuildRequires:  zip
+Requires:   html5_UI_Common
+Requires:   wrt-installer
+Requires:   wrt-plugins-ivi
+Requires:   wrt-plugins-tizen-bt
+
+%description
+A proof of concept pure html5 UI
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+
+make wgtPkg
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%post
+    wrt-installer -i /opt/usr/apps/.preinstallWidgets/html5UINav.wgt;
+    cp -r /opt/usr/apps/_common/js/services /opt/usr/apps/html5POC08/res/wgt/js/
+    cp -r /opt/usr/apps/_common/css/* /opt/usr/apps/html5POC08/res/wgt/css/
+
+%postun
+    wrt-installer -un html5POC08.Nav
+
+%files
+%defattr(-,root,root,-)
+/opt/usr/apps/.preinstallWidgets/html5UINav.wgt
diff --git a/templates/placesListDelegate.html b/templates/placesListDelegate.html
new file mode 100644 (file)
index 0000000..b0adc03
--- /dev/null
@@ -0,0 +1,5 @@
+<div class="placesElement borderColorTheme">
+       <div class="placesBox">
+               <div class="fontSizeLarge fontWeightBold fontColorNormal oneLineEllipsis" onClick="changeDestinationAddress('{{:destinationAddress}}');">{{:destinationAddress}}</div>
+       </div>
+</div>
\ No newline at end of file