From 506e74eef412ef31859830186a22149dd0c40784 Mon Sep 17 00:00:00 2001 From: brianjjones Date: Thu, 3 Apr 2014 16:42:29 -0700 Subject: [PATCH 1/1] Initial checkin of the Modello Navigation app Change-Id: Ic442a4be25f042f322bf0c6ac211e3940b0ec33b Signed-off-by: brianjjones --- Makefile | 18 + config.xml | 19 + css/style.css | 134 +++++++ icon.png | Bin 0 -> 2447 bytes images/icon_arrow_left.png | Bin 0 -> 1387 bytes images/icon_arrow_right.png | Bin 0 -> 1385 bytes images/icon_arrow_straight.png | Bin 0 -> 1363 bytes index.html | 110 ++++++ js/main.js | 778 ++++++++++++++++++++++++++++++++++++++ js/v3_epoly.js | 107 ++++++ packaging/html5-ui-nav.changes | 3 + packaging/html5-ui-nav.spec | 39 ++ templates/placesListDelegate.html | 5 + 13 files changed, 1213 insertions(+) create mode 100644 Makefile create mode 100644 config.xml create mode 100644 css/style.css create mode 100644 icon.png create mode 100644 images/icon_arrow_left.png create mode 100644 images/icon_arrow_right.png create mode 100644 images/icon_arrow_straight.png create mode 100644 index.html create mode 100644 js/main.js create mode 100644 js/v3_epoly.js create mode 100644 packaging/html5-ui-nav.changes create mode 100644 packaging/html5-ui-nav.spec create mode 100644 templates/placesListDelegate.html diff --git a/Makefile b/Makefile new file mode 100644 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 index 0000000..d1563d2 --- /dev/null +++ b/config.xml @@ -0,0 +1,19 @@ + + + + + + + Navigation + + + + + + + + + + diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..aac127d --- /dev/null +++ b/css/style.css @@ -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 index 0000000000000000000000000000000000000000..fda31dc1a18e3b4bbf6ef0ecd1d0d371a2811451 GIT binary patch literal 2447 zcmbVOeK?bQAHRnZMJgrgFcXRFjj`<+8r#ad!$OG7b}x&)oNd}B)l^4LT_ul~>LJfV zoI0g+P!hGCQxUz0I`pDi8cRw$C}hoZuhMz0>*+dwJok0o_wW1t{l1^?`}cR-tjCy5qtBvPgb1juYb3J4G4F*kuxAd@Zs zp$#MffH8+lkCViOg%Vi;9+GL0LCSbS2n_%vf0>ZUN&_YE6mS!l?~8cbq(s2EY+pny zE({$e3oP@PbY?i6m6^sOuo3=#aFUD&Dd2$;CS1l#=ZlFlU&JT9M2I$QqY&^< zB9b&;#Am1C!Xn{;0uczuA<-Tzv^NIs?S;g6p$T4u)o?5tgGOPnD723U22I5I5YZU; zmj?k^6R|nOC<^V1Er|0)q)H@0A_^syN|91eq(HO@g&`0KC^Qy@#d<&z9%4CP!jyUN z#ZEICD4>`n;tC~P0UvJA$V?GrNPH2Hr=LUM3B$s^D&~v7BnnCyO2!nTFi13t$1}wB zNm?w40{?X5o6=&sTnM6~K(Qc0#DeO>rOuOz#bEF>0+!%~Ctw0Fo_K;MdPc{$uozD&!7IQUhb0FD zU@%lH0Zqda0?0nz1R9MRNFmQ)gZN?zlg|QY>~bNy5EkQ!!_fW`OAHi&Oo>257YNd4 zIv_GtAQ6aD1wwdWG!BV@$8z~>fmCcL&*x|74b!05D4#L?P2?gSYKMB zG;y5Rl|3D#d_8~Xn9*YT(v+7UcA+M*xhW5ddG(yebFLvJs0ZzqkCC1)2)7or96hpy zGc4!axzsT}H@W!X6U~vS-i}`J+s1Lfj$3Zl=9YV7c_)m39AK#tV~)b{Gw}`9JfhCS zx2yHZXp zYa24zd^+BBdvH=-0jdDSJtqX---{pFB5LTG9LWEtjX2FONN=ntsc}~ORQ9{rF5XgL z+P25J&{(*rKDxJho{BpXJo5dB90(5|ZF?IG`Xq>N)D*<#D_2Ay=65fizx#dt9R4re z>j(qJXZiXMFnNCdh$Kk91URc)a$`+v{J!V8wWsbB&QrLLZEc#@P*|lNCyu{A2NSX~ z!`wP+WuaOlpr_`YT4Q9}ntnW{d7&b$$4PB(bKrvIvlTbq0Es1Ac4GrP7UXFg0PU^5 zM%8U(D6cAp)EZx2eVffIwmQA4EaM{0zNC0y^`ZQW#rUGF#aS@LskMu4XD>#LAB877 zYfe@&Pqm>g_VxXk=N6D3?;3 zb$+i_PQR2N;D;RJx+|KjY3(bE+C{yd^agj!M-{N;vL#w1W2j z#;(4hpDeYcju&f-ZoX&&&l@Wox)VEIv=-hhn8nyQ8IFxhXj=scCtV+`eUy-y6*?V%O5BHk+j0WBJbV%P?)gMi+_3hV`HngEwT;e^OOngJ*#2% zk$BTRuf{k2F?=;%%zBC#bDR9G>chnE3snzW;?e$5WS0G*hUcU}zc77O@S`qA=Chll1y?F=Ve?|0jh{Xr(}wXd~=Q`S)t0?PuTM9Ofk6kWG`2SM#Wj>Y5jk={+PWS7+U}8_-wZ#f3`!xw1xAIxr5oN9_K_&{Ft6(Hu`-k zAu}~1OEWgOZr{_XwAj+SLZGyI!lmwQiLUHfW8cX_W7WXRgK0YNPFh#_qU`SIvx-Is z{cp}n-*@4zgOTZqqv{sZMI`?~U#noEwG(5BV019zW$&hqCdpk3u8zBGb1$byH}4;p znPe=Qr7|FEmG|!sotkEH9Ea7R9*pi^i1#W&E8kgp zs5*%sqRY&dnX0ss^DTZ;q1Q63aH?`U+Wpv+H(T!k4}QPfz(FYWFJYrUk8NGA_wGaJ zg2(G&1G@8%q^_mnRgnqiXMR-%ZyxgmS{;+z%k+m`w(GPjfYxK#wn@f9m0fA^l%b z4#0tg1^~|oVR(L6rG>USpj-v7|MOBb+>W#Vmn}alNmjssDdzIF=D6@d!!J@0HJoxL HfU)yGbf5dP literal 0 HcmV?d00001 diff --git a/images/icon_arrow_left.png b/images/icon_arrow_left.png new file mode 100644 index 0000000000000000000000000000000000000000..6b2776a74a176ef84436339fa6d38ffc170fe2db GIT binary patch literal 1387 zcmbVMdraJP94`}a!kEJ+j3HeIjAh*QanBZRvs`=Q?z|g2Sh#64E7t-Qt}VT?J0Ofb zm;;S_`IwI_C_>0$fEYv_sAMq1%r<9;EMyu7Vl)IIi%ZBhAJ_v9{e$ceoAlS;IlsAol?hSh4w0iVyO~jWDX!%v4jKdex{7` za12{h^);6Z01uS%MP9}0dWP_cek~KmXhVJ}OakO?4@r!#f>Xc}u8bEf&}{zz1oEr} zDmJ(fmt^J2`TSa$E39=F`D!bCI16px2IhtcmB7y_3>flP3IQTyffjfPbspY^A#eer zR9K)zr@XEL&??FtXwV`WA7Vs7qh5>Z5nPXFgBXG$Fp9y5NrNJU!9*Y^xb#4(n#`6G z9?G_)rLHVcxuQq}3aU4c47{fFwLKCPF6egq*0-GWX6c_Nxyrl4= z0EQWv60usbK&q#UA^0ViYnfOGEG0@!8609H7}X-M-ye=^0Uc00+`n$Dhz=ChNF40p z0%Eo7Q|nQ>DPpYV?*2kypy~~=Q|8s8FqM?(tM+q(Vy7&SdZJ}{meAQylBQ@%O`VR$ zP}FS0F41WAQ4s^>q6AtC4O$c|<^@&^2Eyf8jF#eLejmr$ zWYG^U&WzFFxbv(!jK)kx(u5ieByNS4Y}x;lGgx&74mZbtnkBNO zc3^nA-1_Qb`SNgrdShhuY9!-BEdUU8#!it%p&K)AkyP}qq~QU+C)-I;N0nzCPRH|( zj;yl|rKxM`iRQl3?)I+cti;s0k@tOdQ{T4hJDR*iXRGt_3!ltSK4;6!>AC&O)jw?8 z_s@Mi`B(kTy4iQDwtbn>b~5U-_~J`Q>iU-6=(LISj04BOnow*v^JE59c5(jrpws(a zW3%U^CL~&$_H7-Bzc#UE4>k7km7%il^BNyIb$G|E*tru&qWR8ME%`$%>V74@D)lLe zKIA#tHL;<)A!h2O4(T8}ey{hs{$@gb`s&%zYq!oQn>CHWo)4MXxMQys6wzdZc35*q_aR; z+Thw(A0O-9a>@9E_-XI{+pC7hKYBf}eU$2t`gQN<_`Tn&zS#KV;KsiVWac-=AKu+{ zC9~M^b58$htNB7*zOwGCM>ibYJaRbeMJYi$2w$DP{PvoWwu=vvdnR=~_UK)o5A8nJ zN%LbfRfRj9CvG&**&nn{*QfK}S+JzGn1<*iU|_A=G=E3;Sor^Er`=Rn-rht10Pwr( AzyJUM literal 0 HcmV?d00001 diff --git a/images/icon_arrow_right.png b/images/icon_arrow_right.png new file mode 100644 index 0000000000000000000000000000000000000000..6fbf3febdac6d269d9e2c1177f31f1d25464bdad GIT binary patch literal 1385 zcmeAS@N?&q;$mQ6;Pv!y2?EkaK&;Ba1|%8Y?3x55B}-f*N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFsEgPM3hAM`dB6B=jtVb)aX^@7Jv+4u(7WwNKDR7Em25H zP0!4;ReHaBzmh^`img((sjq==fpcm`rbks#YH*cbNODznvSo^ry`6$hg%!|%+|-gp zg^Jvqyke^gTP3i$RzNmLSYJs2tfVB{Rte&$2;Tq&=lr5n1yel(-DCqZLj^MvJwp=% zOA|{S1tSAP1ARjyeFJk{Ljx;Qb1MTw1t?Gg+E$d3W) zw8T~k=u(ImatnNY;RfdwLjwvJWcn3}1^R}12Ku?VAb){X7ncO3BAkI$b#X{#L8^XG zYH@yPQ8F+-(v)GEfnkT=B9KC$Ypnc>GJ%njnB$V4T$-DjSK{ens|1wMOUX>JGIld` zbaioc0S2A1tC69hg`1_3rHO^5p_8Gpg{83p%nWRLf#L3GXzAi?Evi`X6feU>g?hO)9aa6T#}fVoC>oy6KF3~uM=LqR?bDKi6!|(A^G_^uoMuGkzbNu zoRMFk;2dnKXQ&XKnU|7ZUJQyJh;Lm|i!#enQ{0O3a}~hhYn6$`ep6Rd7gIBHR|}x) zLH>4hHZXT|b#gOtH8HhtHZW0w>P;ah%=Ced(FY|Cq{IRf0;WI^6Q1;e9C+qQ%>(9` zB4E~dr4rlCz`!`m)5S5Q;?|oP=iOZbCEDKq5isNt{L6SzX{(Ol+9;JpX0BZwE+U;} zxx!1$bQk$f4BI->^;W6|ujbpf8KEv+9?nbd^}pY;Vut12%X^>8?zOpddhTPJ;{BiR z7Uw^D_|&#TadiTJ%nm67$s?1+3b@2>xT=&Uu*x*6r3p@sE8zWg(^aKcf&H4J?dFb? zIu_SWU38T)nWrbridDJr=@tw7g2u=rDFM=s{!6)qD-=#Kz3!`MI;)Uf_*XiD&AaN) zVh_EX*WCu`2_jQ&c)iZvwdG11&_Kxz{AFKegdIuoxn07(yCYMoa>EHdB~Q-GBF>j_ z$_ozExR*KZ_Bg@$ShkWa_*dIcNwbMf(=KgiPr6k!A=h1a*2UO$n{~T-Pw?I-QZY(U zELweglJK*;?-euFsyy86A?eek_#xyhe~y>7=)@ya^aCWG$Dd{?lvL2t@o`B z82jq18~BxseijzUr%gyX!(GMqrFCjY@RAkTiHEN?m@S=Js$um0*Zh^O-vzTLUXK#g u{NG)n7W667WuHmd@1H>~a2?`)wTccmp1x>6Y-Q@QqD=n1_mcLyzq z5oGF2mTe3|;%C?}GGnGDcGGB#&JbaKM6%3}7)=~8ekW7W1&uo21B(7Z_J^0;d++lqfuv)QaIYqu$C4^A=+gA)`^QC6s7)rMqU$XR8rx`4m|EvZTw zT~cJ!Kok(tm%TB z1O>km^t)kezp5=8P=TN;YFttJ3LOwlDY~MilnfeZqirO*Pm)C?s~P24&z1wKGzi3? zs-)31epzV?|1?i?be)rT1t_19w=Y0AeY`*D;2pFpKsc}sTk-#JhQnZRqdET5ECmtl zKx4bv`tYzhJV1sMqr%a!dl&ygkfH-&&KJ*pmiY6^l?D^}MJc@G5x$>by)f< z<_=H1Q#D~)Uh%$fp0DwaOtx1EiJ4tp=4Bpz1tGUjeGt6;z0`LTW$2m4v7E^T&;j_M>O-K?hCC_Xl=MW7Orc+NZs(@_4-zF(r8SFXz4P2VT1Gmdb;(2czGV z%uD0+kNTLiHO=GvxQPDUyPqlF^?X^y<2R!v zgWDdezvHg6CmVwv>idbkM-B~(7piBgcKo(zi2NV@T}mR3#mk37r{_*eq<6Fk`Qfp6 T6trJl`_YB@7VZUq*Mt86WF^ed literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..0cb1f19 --- /dev/null +++ b/index.html @@ -0,0 +1,110 @@ + + + + + +Navigation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
PLACES
+ +
+
+ + + +
+ +
+ +
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +
+
+ + + \ No newline at end of file diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..4e22ae3 --- /dev/null +++ b/js/main.js @@ -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. + * + * + * + * Top bar icons + * Bottom panel + * Places library + * Navigation panel + * Animate along waypoints + * Switch map mode + * + * @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 + "KM"; + } else { + return Math.round(meters) + "m"; + } +} + +/** + * 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 + "MI"; + } else { + return Math.round(feets) + "ft"; + } +} + +/** + * 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 + "s"; + } + 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) + " km/h" + ")"; + } else { + averageSpeedText = Math.round(averageSpeed * 2.2369362920544) + " MPH" + ")"; + } + + $("#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 index 0000000..ca72e3b --- /dev/null +++ b/js/v3_epoly.js @@ -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 index 0000000..f4282bf --- /dev/null +++ b/packaging/html5-ui-nav.changes @@ -0,0 +1,3 @@ +* Thu Apr 03 2014 brianjjones 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 index 0000000..9d9589c --- /dev/null +++ b/packaging/html5-ui-nav.spec @@ -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 index 0000000..b0adc03 --- /dev/null +++ b/templates/placesListDelegate.html @@ -0,0 +1,5 @@ +
+
+
{{:destinationAddress}}
+
+
\ No newline at end of file -- 2.7.4