Mobile App (PhoneGap) Code

This is a web app based on PhoneGap framework. PhoneGap allows you to create mobile apps using standardized web APIs. Code was primarily developed and tested for Android, but I think you can build it for all other platforms with no major problems.
Because is created using web technologies HTML, CSS, and JavaScript you can run the app on your mobile phone, tablet or simply on your local computer.
You can drive the car with tapping the buttons on the screen, rotating the phone with accelerometers or using computer keyboard arrows.

Here you can see how the app looks like.

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="format-detection" content="telephone=no" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
  7. <title>Car App</title>
  8. <link href="css/style.css" rel="stylesheet" />
  9. <script src="js/jquery-2.0.3.min.js"></script>
  10. <!--Reference the SignalR library. -->
  11. <script src="js/jquery.signalR-2.0.2.min.js"></script>
  12. <script src="js/connect.js"></script>
  13. <!--Reference the autogenerated SignalR hub script. -->
  14. <!--<script src="http://192.168.1.148/signalr/hubs"></script>-->
  15. <!--<script src="http://home.tvojnet.si/signalr/hubs"></script>-->
  16.     <!-- Cordova -->
  17. <script src="cordova.js"></script>
  18. <!-- Main -->
  19. <script src="js/main.js"></script>
  20. <!-- jQuery Mobile (Must Be after Main.js) -->
  21. <script src="js/jquery.mobile-1.4.3.min.js"></script>
  22. <!-- Start Native App -->
  23. <script src="js/startapp.js"></script>
  24. </head>
  25. <body>
  26. <div id="wrapper">
  27.     <!-- Home page -->
  28.         <div data-role="page" id="home">
  29.             <div data-role="header">
  30.              <header>
  31.                  <h1 class="home">Choose your way to drive</h1>
  32.                  <div id="connect"></div>
  33.              </header>
  34.          </div>
  35.          <div role="main" class="ui-content">
  36. <!-- Connect -->
  37. <form id="connectForm">
  38. <div class="connectOpt">
  39. <h1>Select the connection method</h1>
  40. <div id="serverIP" class="row">
  41. <p>Server IP</p>
  42. <input type="text" name="serverIP" value="192.168.1.4" data-role="none" />
  43. </div>
  44. <div id="serverDomain" class="row">
  45. <p>Domain</p>
  46. <div class="domain">http://home.tvojnet.si</div>
  47. </div>
  48. <input type="submit" value="Connect" data-role="none" />
  49. </div>
  50. </form>
  51. <!-- END -->
  52.              <div id="driveOpt">
  53.                  <div id="1" class="driveVer">
  54.                      <a href="#driveBut"><img src="img/driveButtons.png" alt="z gumbi" /></a>
  55.                      <p>With Buttons</p>
  56.                  </div>
  57.                  <div id="2" class="driveVer">
  58.                      <a href="#driveAcc"><img src="img/driveAccelerometers.png" alt="Z accelerometri" /></a>
  59.                      <p>With Accelerometers</p>
  60.                  </div>
  61.              </div>
  62.              <div id="options">
  63.                  <ul>
  64.                      <li id="calibrate">
  65.                          <div class="icon"></div>
  66.                          <h2>Calibrate Accelerometers</h2>
  67.                          <div class="onOffSwitch">
  68.                              <select name="calibrate" data-role="slider">
  69.                              <option value="off"></option>
  70.                              <option value="on"></option>
  71.                              </select>
  72.                          </div>
  73.                      </li>
  74.                      <li id="speed" class="subpage">
  75.                          <div class="icon"></div>
  76.                          <h2>Speed Settings</h2>
  77.                      </li>
  78.                      <li id="steerSensitivity" class="subpage">
  79.                          <div class="icon"></div>
  80.                          <h2>Steering Sensitivity</h2>
  81.                      </li>
  82.                      <li id="steerCalibrate" class="subpage">
  83.                          <div class="icon"></div>
  84.                          <h2>Centering Wheels</h2>
  85.                      </li>
  86.                      <li id="rangeSensors" class="subpage">
  87.                          <div class="icon"></div>
  88.                          <h2>Range sensors</h2>
  89.                          <div class="onOffSwitch">
  90.                              <select id="rs" name="rangeSensors" data-role="slider">
  91.                              <option value="off"></option>
  92.                              <option value="on"></option>
  93.                              </select>
  94.                          </div>
  95.                      </li>
  96.                      <li id="blinkers">
  97.                          <div class="icon"></div>
  98.                          <h2>Turn signals</h2>
  99.                          <div class="onOffSwitch">
  100.                              <select id="bl" name="blinkers" data-role="slider">
  101.                              <option value="off"></option>
  102.                              <option value="on"></option>
  103.                              </select>
  104.                          </div>    
  105.                      </li>
  106.                      <li id="vibrate">
  107.                          <div class="icon"></div>
  108.                          <h2>Vibrate</h2>
  109.                          <div class="onOffSwitch">
  110.                              <select name="vibrate" data-role="slider">
  111.                              <option value="off"></option>
  112.                              <option value="on"></option>
  113.                              </select>
  114.                          </div>
  115.                      </li>
  116.                      <li id="arduinoUno" class="subpage">
  117.                          <div class="icon"></div>
  118.                          <h2>Arduino Uno R3</h2>
  119.                      </li>
  120.                  </ul>
  121.              </div>
  122.          </div>
  123.     </div>
  124.     <!-- END -->
  125.     
  126.     <!-- Drive with buttons -->
  127.         <div data-role="page" id="driveBut">
  128.         <div data-role="header">
  129.              <header>
  130.              </header>
  131.          </div>
  132.          <div role="main" class="ui-content">
  133. <div class="fwBtns">
  134. <button id="forward" class="driveBtn" value="w"></button>
  135.                     <button id="backward" class="driveBtn" value="s"></button>
  136. </div>
  137. <div class="dashboard">
  138. <ul>
  139. <li id="rr" class="record"></li>
  140. <li id="oo" class="speedSet"></li>
  141. <li id="b4" class="blinkers4"></li>
  142. <li id="ll" class="longLights"></li>
  143. <li id="cl" class="lights"></li>
  144. </ul>
  145. </div>
  146. <div class="mainC">
  147. <div class="driveData">
  148. <div class="speed">
  149. <div class="max">MAX: <span>0</span> km/h</div>
  150. <div class="current"><div>0</div> <p>km/h</p></div>
  151. </div>
  152. <div class="adtData">
  153. <div class="mTemp"><span>0</span>°C</div>
  154. <div class="battLevel">
  155. <div class="bar"><span></span></div>
  156. <div class="perc">0</div>
  157. <p>% BATT</p>
  158. </div>
  159. </div>
  160. </div>
  161. <div class="steerC">
  162. <button id="left" class="driveBtn" value="a"></button>
  163.                         <button id="right" class="driveBtn" value="d"></button>
  164. </div>
  165. </div>
  166. <div class="overlay"><p>Obrni telefon v ležeč položaj</p></div>
  167.          </div>
  168.     </div>
  169.     <!-- END -->
  170.     
  171.     <!-- Drive with Accelerometers -->
  172.         <div data-role="page" id="driveAcc">
  173.         <div data-role="header">
  174.              <header>
  175.              </header>
  176.          </div>
  177.          <div role="main" class="ui-content">                
  178. <div class="overlay"><p>Obrni telefon v ležeč položaj</p></div>
  179.          </div>
  180.     </div>
  181.     <!-- END -->
  182.     
  183.     <!-- Hitrost -->
  184.         <div data-role="page" id="speed">
  185.         <div data-role="header">
  186.              <header>
  187.                  <h1>Set maximum speed</h1>
  188.              </header>
  189.          </div>
  190.          <div role="main" class="ui-content">
  191.              <div class="setSpeed">
  192.                  <div class="sliderRow">
  193.                      <input type="range" name="maxSpeed" value="120" min="95" max="165" step="1" data-highlight="true" />
  194.                  </div>
  195.              </div>
  196.          </div>
  197.      </div>
  198.      <!-- END -->
  199.     
  200.     <!-- Občutljivost volana -->
  201.     <div data-role="page" id="steerSensitivity">
  202.         <div data-role="header">
  203.              <header>
  204.                  <h1>Steering Sensitivity</h1>
  205.              </header>
  206.          </div>
  207.          <div role="main" class="ui-content">
  208. <div class="optoSteer">
  209.               <div class="sliderRowRS" data-role="rangeslider">
  210.                   <p>Forward (range in degrees °)</p>
  211. <!--<input type="range" name="speedForw" value="10" min="10" max="60" step="5" data-highlight="true" />-->
  212. <input name="speedNeutralMax" min="0" max="60" step="5" value="5" type="range">
  213. <input name="speedFactor" min="0" max="60" step="5" value="25" type="range">
  214.                  </div>
  215. <div class="sliderRowRS" data-role="rangeslider">
  216.                   <p>Backward (range in degrees °)</p>
  217. <!--<input name="speedFactorBack" min="335" max="359" step="5" value="335" type="range">
  218. <input name="speedNeutralMin" min="335" max="359" step="5" value="355" type="range">-->
  219. <input name="speedNeutralMin" min="0" max="60" step="5" value="5" type="range">
  220. <input name="speedFactorBack" min="0" max="60" step="5" value="25" type="range">
  221.                  </div>
  222. <div class="sliderRow">
  223.                   <p>Forward/Backward (change every n°)</p>
  224.                      <input type="range" name="driveTol" value="3" min="1" max="5" step="1" data-highlight="true" />
  225.                  </div>
  226. <div class="line"></div>
  227.               <div class="sliderRow">
  228.                   <p>Left/Right</p>
  229.                      <input type="range" name="steerFactor" value="25" min="25" max="80" step="5" data-highlight="true" />
  230.                  </div>
  231. <div class="sliderRow">
  232.                   <p>Left/Right (neutral range "straight")</p>
  233.                      <input type="range" name="steerZone" value="5" min="0" max="15" step="1" data-highlight="true" />
  234.                  </div>
  235. <div class="sliderRow">
  236.                   <p>Left/Right (change every n°)</p>
  237.                      <input type="range" name="steerTol" value="3" min="1" max="5" step="1" data-highlight="true" />
  238.                  </div>
  239. </div>
  240.          </div>
  241.      </div>
  242.     <!-- END -->
  243.     
  244.     <!-- Centriranje koles -->
  245.         <div data-role="page" id="steerCalibrate">
  246.         <div data-role="header">
  247.              <header>
  248.                  <h1>Centering Wheels</h1>
  249.              </header>
  250.          </div>
  251.          <div role="main" class="ui-content">
  252.              <div class="steerCalib">
  253.                  <button class="arrBut left"></button>
  254.                  <div class="tire">
  255.                      <img class="steerTire" src="img/tire.png" />
  256.                  </div>
  257.                  <button class="arrBut right"></button>
  258.              </div>
  259.              <div class="steerAng">0</div>
  260.          </div>
  261.      </div>
  262.      <!-- END -->
  263. <!-- Senzorji razdalje -->
  264.         <div data-role="page" id="rangeSensors">
  265.         <div data-role="header">
  266.              <header>
  267.                  <h1>Range Sensors</h1>
  268.              </header>
  269.          </div>
  270.          <div role="main" class="ui-content">
  271.              <div class="rangeSett">
  272.                  <div class="wrapImg">
  273.                      <img src="img/car-sensors.png" />
  274.                  </div>
  275. <div class="calBox">
  276. <button class="arrBut left"></button>
  277. <div class="servoAng">0</div>
  278. <button class="arrBut right"></button>
  279. </div>
  280. </div>
  281.          </div>
  282.      </div>
  283.      <!-- END -->
  284.     
  285.      <!-- Arduino Shema -->
  286.         <div data-role="page" id="arduinoUno">
  287.         <div data-role="header">
  288.              <header>
  289.                  <h1>Arduino Uno R3 - Scheme</h1>
  290.              </header>
  291.          </div>
  292.          <div role="main" class="ui-content">
  293.              <div class="arduino" id="arduinoImg">
  294.                  <img src="img/arduinoUno.png" usemap="#arClear" />
  295. <map name="arClear">
  296. <area shape="rect" coords="242,53,275,87" id="clearLS" />
  297. </map>
  298.              </div>
  299.              <div class="arduinoPins">
  300.                  <h3>Analog pins</h3>
  301.                  <ul>
  302.                      <li><span>0</span> - Motor temperature <i>(INPUT "LM35")</i></li>
  303.                      <li><span>1</span> - Battery voltage <i>(INPUT)</i></li>
  304.                      <li><span>2</span> - Range Sensor front "Echo" <i>(INPUT) grey</i></li>
  305.                      <li><span>3</span> - Range Sensor front "Trig" <i>(OUTPUT) purple</i></li>
  306.                      <li><span>4</span> - Range Sensor back "Echo" <i>(INPUT)</i></li>
  307.                      <li><span>5</span> - Range Sensor back "Trig" <i>(OUTPUT)</i></li>
  308.                  </ul>
  309.                  <h3>Digital pins</h3>
  310.                  <ul>
  311.                      <li><span>0</span> - XBee communication <i>RX</i></li>
  312.                      <li><span>1</span> - XBee communication <i>TX</i></li>
  313.                      <li><span>2</span> - Speed <i>(INPUT) vijolična</i></li>
  314.                      <li><span>3</span> - Motor Rotation Direction <i>(INPUT) blue</i></li>
  315.                      <li><span>4</span> - Long lights <i>(OUTPUT) orange</i></li>
  316.                      <li><span>5</span> - Underbody Lighting RED <i>(OUTPUT) green</i></li>
  317.                      <li><span>6</span> - Underbody Lighting BLUE <i>(OUTPUT) yellow</i></li>
  318.                      <li><span>7</span> - Turn signals "left" <i>(OUTPUT) yellow</i></li>
  319.                      <li><span>8</span> - Turn signals "right" <i>(OUTPUT) blue</i></li>
  320.                      <li><span>9</span> - Left/Right <i>(OUTPUT) blue</i></li>
  321.                      <li><span>10</span> - Servo for Front Range Sensor <i>(OUTPUT) yellow</i></li>
  322.                      <li><span>11</span>    - Forward/Backward <i>(OUTPUT) white</i></li>
  323.                      <li><span>12</span> - Lights <i>(OUTPUT) green</i></li>
  324.                      <li><span>13</span> - Braking lights <i>(OUTPUT) purple</i></li>
  325.                  </ul>
  326.              </div>
  327.          </div>
  328.      </div>
  329.      <!-- END -->
  330. <!-- Critical Temperature -->
  331. <div id="criticalTemp"></div>
  332. <!-- END -->
  333.     </div>
  334. </body>
  335. </html>
  1. body
  2. {
  3. font-family:"trebuchet ms",serif;
  4. font-size:100%;
  5. line-height:110%;
  6. margin:0;
  7. padding:0;
  8. width:100%;
  9. height:100%;
  10.     background-color:#f0f2f5;
  11. }
  12. html
  13. {
  14. margin:0;
  15. padding:0;
  16. height:100%;
  17. }
  18. a
  19. {
  20. text-decoration:none;
  21. }
  22. a img
  23. {
  24. border:none;
  25. }
  26. .clr
  27. {
  28. clear:both;
  29. padding:0;
  30. margin:0;
  31. }
  32. * {
  33. -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  34. }
  35. :focus {
  36.     outline: 0;
  37.     border:none;
  38.     color: rgba(0, 0, 0, 0);
  39. }
  40. h1 {
  41.     margin:0;
  42.     font-size:20px;
  43.     font-weight:normal;
  44.     color:#333;
  45.     text-align:center;
  46.     text-transform:uppercase;
  47.     text-shadow:0 2px #fff;
  48. }
  49. #wrapper {
  50.     width:100%;
  51.     margin:0 auto;
  52. }
  53. /* Header */
  54. header {
  55.     float:left;
  56.     width:100%;
  57.     border-top:5px solid #FD5B00;
  58.     padding-top:20px;
  59.     margin-bottom:10px;
  60.     
  61.     h1.home {
  62.         float:left;
  63.         margin:0 0 0 15px;
  64.         text-align:left;
  65.     }
  66.     
  67.     /* Connect Icon */
  68.     #connect {
  69.         float:right;
  70.         margin:-5px 15px 0 0;
  71.         width:35px;
  72.         height:28px;
  73.         background:url(../img/notConnected.png) no-repeat;
  74.     }
  75.     #connect.active {
  76.         background-image:url(../img/connected.png);
  77.     }
  78. }
  79. /* Connect Options */
  80. .connectOpt {
  81. position:absolute;
  82. top:0;
  83. width:0;
  84. width:100%;
  85. height:100%;
  86. background:#F0F2F5;
  87. z-index:9;
  88. margin:5px 0 0 0;
  89. text-align:center;
  90. h1 {
  91. margin:20px 0 40px 0;
  92. }
  93. .row {
  94. /*margin-bottom:15px;*/
  95. padding:15px 0;
  96. p {
  97. margin:0 0 7px 0;
  98. font-size:12px;
  99. text-shadow:1px 1px #fff;
  100. }
  101. div {
  102. font-size:14px;
  103. font-weight:bold;
  104. }
  105. input[type=text] {
  106. padding:10px 12px;
  107. border:1px solid #ccc;
  108. border-radius:3px;
  109. font-size:14px;
  110. font-weight:bold;
  111. color:#000;
  112. }
  113. }
  114. .row:nth-of-type(1) {
  115. border-bottom:1px dashed #CCCCCC;
  116. }
  117. .row.active {
  118. background:rgba(0, 0, 0, 0.07);
  119. }
  120. .error {
  121. font-size:12px;
  122. font-weight:bold;
  123. color:#FD5B00;
  124. text-shadow:1px 1px #fff;
  125. }
  126. input[type=submit] {
  127. margin-top:30px;
  128. padding:10px 40px;
  129. border:none;
  130. border-bottom:1px solid #db3900;
  131. background-color:#FD5B00;
  132. font-size:14px;
  133. font-weight:bold;
  134. color:#fff;
  135. border-radius:6px;
  136. }
  137. }
  138. /* Drive Options */
  139. #driveOpt {
  140.     clear:both;
  141.     float:left;
  142.     width:100%;
  143.     margin-bottom:30px;
  144.     padding:15px 0;
  145.     background-color:rgba(0, 0, 0, 0.03);
  146.     
  147.     .driveVer {
  148.         float:left;
  149.         width:50%;
  150.         
  151.         a {
  152.             display:block;
  153.             text-align:center;
  154.             
  155.             img {
  156.                 width:100%;
  157.                 margin:0 auto;
  158.                 min-width:120px;
  159.                 max-width:150px;
  160.                 border:5px solid #fff;
  161.                 border-radius:120px;
  162.                 box-shadow:2px 2px 7px rgba(0,0,0,.1);
  163.                 transition-duration:.3s;
  164.             }
  165.             img:active, img:hover {
  166.                 box-shadow:0 0 25px rgba(0,0,0,0.25);
  167.             }
  168.         }
  169.         p {
  170.             margin:5px 0 0 0;
  171.             font-size:11px;
  172.             line-height:11px;
  173.             color:#333;
  174.             text-align:center;
  175.             text-transform:uppercase;
  176.             text-shadow:1px 1px #fff;
  177.         }
  178.     }
  179.     .driveVer:nth-of-type(2) {
  180.         float:right;
  181.     }
  182. }
  183. /* Options */
  184. #options {
  185.     clear:both;
  186.     float:left;
  187.     width:100%;
  188.     
  189.     ul {
  190.         margin:0;
  191.         padding:0;
  192.         list-style:none;
  193.     
  194.         li {
  195.             float:left;
  196.             width:100%;
  197.             height:46px;
  198.             line-height:46px;
  199.             border-bottom:1px solid #e2e2e2;
  200.             box-shadow:0 1px #fff;
  201.             color:#666;
  202.             
  203.             .icon {
  204.                 float:left;
  205.                 margin:0 auto 0 15px;
  206.                 width:45px;
  207.                 height:46px;
  208.                 background-position:center center;
  209.                 background-repeat:no-repeat;
  210.             }
  211.             h2 {
  212.                 float:left;
  213.                 margin:0;
  214.                 margin-left:15px;
  215.                 font-size:12px;
  216.                 font-weight:normal;
  217.                 color:#666;
  218.                 text-shadow:1px 1px #fff;
  219.             }
  220.             .onOffSwitch {
  221.                 float:right;
  222.                 height:46px;
  223.             }
  224.         }
  225.         #calibrate .icon {
  226.             background-image:url(../img/calibrate.png);
  227.         }
  228.         #speed .icon {
  229.             background-image:url(../img/speed.png);
  230.         }
  231.         #steerSensitivity .icon {
  232.             background-image:url(../img/steerSensitivity.png);
  233.         }
  234.         #steerCalibrate .icon {
  235.             background-image:url(../img/rim.png);
  236.         }
  237.         #motorTemp .icon {
  238.             background-image:url(../img/motorTemp.png);
  239.         }
  240.         #rangeSensors .icon {
  241.             background-image:url(../img/rangeSensors.png);
  242.         }
  243.         #battery .icon {
  244.             background-image:url(../img/battery.png);
  245.         }
  246.         #kers .icon {
  247.             background-image:url(../img/kers.png);
  248.         }
  249.         #lights .icon {
  250.             background-image:url(../img/lights.png);
  251.         }
  252.         #blinkers .icon {
  253.             background-image:url(../img/blinkers.png);
  254.         }
  255.         #blinkers4 .icon {
  256.             background-image:url(../img/blinkers4.png);
  257.         }
  258.         #lightSens .icon {
  259.             background-image:url(../img/lightSens.png);
  260.         }
  261.         #camera .icon {
  262.             background-image:url(../img/camera.png);
  263.         }
  264.         #gps .icon {
  265.             background-image:url(../img/gps.png);
  266.         }
  267.         #vibrate .icon {
  268.             background-image:url(../img/vibrate2.png);
  269.         }
  270.         #arduinoUno .icon {
  271.             background-image:url(../img/arduino.png);
  272.         }
  273.     }
  274. }
  275. /**** Drive with Buttons ****/
  276. #driveBut {
  277. button.driveBtn {
  278. position:relative;
  279. width:100px;
  280. height:100px;
  281. margin:0;
  282. border:1px solid #d79241;
  283. border-radius:8px;
  284. box-shadow:0 4px 3px -2px rgba(0, 0, 0, 0.15), 0 1px #fff inset;
  285. cursor:pointer;
  286. outline: 0;
  287. background-color:#fdb855;
  288. /*background: -moz-linear-gradient(top, #f6f2ef 0%, #eae7e4 100%);
  289. background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f2ef), color-stop(100%,#eae7e4));
  290. background: -webkit-linear-gradient(top, #f6f2ef 0%,#eae7e4 100%);
  291. background: -o-linear-gradient(top, #f6f2ef 0%,#eae7e4 100%);
  292. background: -ms-linear-gradient(top, #f6f2ef 0%,#eae7e4 100%);
  293. background: linear-gradient(to bottom, #f6f2ef 0%,#eae7e4 100%);*/
  294. }
  295. button.driveBtn:focus, button.driveBtn:active {
  296. box-shadow:0 -1px #FFFFFF inset, 0 3px 2px rgba(0, 0, 0, 0.15) inset;
  297. outline: 0;
  298. /*background: -moz-linear-gradient(top, #eae7e4 0%, #f6f2ef 100%);
  299. background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#eae7e4), color-stop(100%,#f6f2ef));
  300. background: -webkit-linear-gradient(top, #eae7e4 0%,#f6f2ef 100%);
  301. background: -o-linear-gradient(top, #eae7e4 0%,#f6f2ef 100%);
  302. background: -ms-linear-gradient(top, #eae7e4 0%,#f6f2ef 100%);
  303. background: linear-gradient(to bottom, #eae7e4 0%,#f6f2ef 100%);*/
  304. }
  305. button.driveBtn:before {
  306. position:absolute;
  307. top:43px;
  308. left:39px;
  309. width:20px;
  310. height:12px;
  311. content:"";
  312. }
  313. /* Forward, Backward, KERS buttons */
  314. .fwBtns {
  315. position:absolute;
  316. bottom:15px;
  317.      left:15px;
  318. button {
  319. display: block;
  320.             margin-bottom:15px;
  321.         }
  322. button:last-child {
  323. margin-bottom:0;
  324. }
  325. #kersBtn {
  326. background:#D42627;
  327. }
  328. #kersBtn:before {
  329. top:33px;
  330. width:12px;
  331. height:24px;
  332. background:url(../img/kers-small-2.png) no-repeat center center;
  333. }
  334. #forward:before {
  335. background:url(../img/up-arrow-white.png) no-repeat center center;
  336. }
  337. #backward:before {
  338. background:url(../img/down-arrow-white.png) no-repeat center center;
  339. }
  340. }
  341. /* Car Dashboard */
  342. .dashboard {
  343. position:absolute;
  344.      top:20px;
  345.      right:0;
  346. z-index:2;
  347. ul {
  348. float:right;
  349. margin:0 15px;
  350. padding:0;
  351. list-style:none;
  352. li {
  353. float:left;
  354. width:50px;
  355. height:50px;
  356. margin-left:10px;
  357. background-color:#fff;
  358. border:1px solid #e2e2e2;
  359. background-position:center center;
  360. background-repeat:no-repeat;
  361. border-radius:3px;
  362. box-shadow:0 0 5px rgba(0,0,0,0.15) inset;
  363. }
  364. /* Lights */
  365. .lights {
  366. background-image:url(../img/lights-small.png);
  367. }
  368. .lights.on {
  369. /*background-image:url(../img/lights-small-on.png);*/
  370. background-color:#cfff7f;
  371. border-color:#fff;
  372. }
  373. /* Long Lights */
  374. .longLights {
  375. background-image:url(../img/long-lights.png);
  376. }
  377. .longLights.on {
  378. /*background-image:url(../img/long-lights-on.png);*/
  379. background-color:#4fedfa;
  380. border-color:#fff;
  381. }
  382. /* Blinkers 4 */
  383. .blinkers4 {
  384. background-image:url(../img/blinkers4-small.png);
  385. }
  386. .blinkers4.on {
  387. /*background-image:url(../img/blinkers4-small-on.png);*/
  388. background-color:#f6854b;
  389. border-color:#fff;
  390. animation: blinker 1s linear infinite;
  391. -moz-animation: blinker 1s linear infinite;
  392. -webkit-animation: blinker 1s linear infinite;
  393. }
  394. @keyframes blinker {
  395. 0% { background-color:#fff; }
  396. 50% { background-color:#f9b87e; }
  397. 100% { background-color:#f6854b; }
  398. }
  399. @-moz-keyframes blinker {
  400. 0% { background-color:#fff; }
  401. 50% { background-color:#f9b87e; }
  402. 100% { background-color:#f6854b; }
  403. }
  404. @-webkit-keyframes blinker {
  405. 0% { background-color:#fff; }
  406. 50% { background-color:#f9b87e; }
  407. 100% { background-color:#f6854b; }
  408. }
  409. /* Speed */
  410. .speedSet {
  411. background-image:url(../img/steerSensitivity.png);
  412. }
  413. /* Video Recording */
  414. .record {
  415. background-image:url(../img/camera2.png);
  416. }
  417. .record.on {
  418. background-color:tomato;
  419. border-color:#fff;
  420. }
  421. }
  422. }
  423. /* Main Car Data */
  424. .mainC {
  425. position:absolute;
  426.      right:15px;
  427.      bottom:15px;
  428. width:75%;
  429. /* Drive Data */
  430. .driveData {
  431. position:absolute;
  432. left:0;
  433. bottom:0;
  434. width:100%;
  435. max-width:250px;
  436. /* Speed */
  437. .speed {
  438. position:relative;
  439. /* Average */
  440. .avg {
  441. position:absolute;
  442. left:0;
  443. bottom:44px;
  444. font-size:13px;
  445. color:#333;
  446. span {
  447. font-weight:bold;
  448. }
  449. }
  450. /* Max */
  451. .max {
  452. position:absolute;
  453. left:0;
  454. bottom:23px;
  455. font-size:13px;
  456. color:#333;
  457. span {
  458. font-weight:bold;
  459. }
  460. }
  461. /* Current */
  462. .current {
  463. div {
  464. font-size:160px;
  465. color:#333;
  466. text-align:right;
  467. text-shadow:1px 2px #fff;
  468. }
  469. p {
  470. margin:60px 24px 0 0;
  471. font-size:16px;
  472. text-align:right;
  473. text-shadow:0 1px #fff;
  474. }
  475. }
  476. }
  477. /* Additional Data */
  478. .adtData {
  479. clear:both;
  480. float:left;
  481. width:100%;
  482. margin-top:35px;
  483. text-shadow:0 1px #fff;
  484. /* Temperature */
  485. .mTemp {
  486. float:left;
  487. height:24px;
  488. line-height:24px;
  489. margin-top:9px;
  490. background:url(../img/motorTemp.png) no-repeat left center;
  491. padding-left:35px;
  492. font-size:16px;
  493. color:#333;
  494. span {
  495. font-weight:bold;
  496. }
  497. }
  498. /* Battery Level */
  499. .battLevel {
  500. float:right;
  501. margin-right:5px;
  502. text-align:center;
  503. .bar {
  504. width:100px;
  505. height:5px;
  506. border:1px solid #356a08;
  507. border-radius:5px;
  508. box-shadow:0 0 2px rgba(0,0,0,0.15) inset;
  509. span {
  510. display:block;
  511. height:5px;
  512. background-color:#689D1B;
  513. border-radius:5px;
  514. }
  515. }
  516. .perc {
  517. margin-top:3px;
  518. font-size:18px;
  519. font-weight:bold;
  520. color:#666;
  521. }
  522. p {
  523. margin:0;
  524. font-size:12px;
  525. color:#999;
  526. }
  527. }
  528. }
  529. }
  530. /* Steer Controls */
  531. .steerC {
  532. float:right;
  533. width:100%;
  534. max-width:220px;
  535. margin-bottom:115px;
  536. button.driveBtn {
  537.              display:inline-block;
  538.          }
  539. button.driveBtn:before {
  540. top:39px;
  541. left:43px;
  542. width:12px;
  543. height:20px;
  544. }
  545. #left:before {
  546. background:url(../img/left-arrow-white-steer.png) no-repeat center center;
  547. }
  548. #right {
  549. margin-left:15px;
  550. }
  551. #right:before {
  552. background:url(../img/right-arrow-white-steer.png) no-repeat center center;
  553. }
  554. /* Drive Time */
  555. .driveTime {
  556. clear:both;
  557. float:left;
  558. width:100%;
  559. margin-top:20px;
  560. text-shadow:0 1px #fff;
  561. p {
  562. margin:0;
  563. font-size:14px;
  564. color:#666;
  565. }
  566. button {
  567. display:inline-block;
  568. border:1px solid #bbb;
  569. margin:0;
  570. padding:0;
  571. width:30px;
  572. height:30px;
  573. line-height:30px;
  574. background-color:#fff;
  575. border-radius:120px;
  576. background-position:center center;
  577. background-repeat:no-repeat;
  578. }
  579. button#startStop {
  580. background-image:url(../img/timer-start.png);
  581. }
  582. button#startStop.stop {
  583. background-image:url(../img/timer-stop.png);
  584. }
  585. button#timerReset {
  586. margin-left:5px;
  587. background-image:url(../img/timer-restart.png);
  588. }
  589. .time {
  590. /*margin-bottom:10px;*/
  591. text-align:right;
  592. span {
  593. float:left;
  594. margin-top:6px;
  595. }
  596. }
  597. .distance {
  598. text-align:right;
  599. .distM {
  600. float:left;
  601. margin-top:6px;
  602. }
  603. }
  604. }
  605. }
  606. }
  607. }
  608. /**** Steer Calibrate ****/
  609. button.arrBut {
  610.     position:relative;
  611.     width:50px;
  612.     height:50px;
  613.     padding:0;
  614.     border:none;
  615.     background-color:#FD5B00;
  616.     border-radius:120px;
  617.     box-shadow:0 0 10px #fff;
  618.     transition-duration:.3s;
  619. }
  620. button.arrBut:before {
  621.     position:absolute;
  622. top:17px;
  623. left:20px;
  624. width:10px;
  625. height:16px;
  626. content:"";
  627. }
  628. button.arrBut:focus {
  629. box-shadow:0 0 15px rgba(0,0,0,.3);
  630. }
  631. button.left:before {
  632. left:19px;
  633. background:url(../img/left-arrow-white.png) no-repeat;
  634. }
  635. button.right:before {
  636. left:21px;
  637. background:url(../img/right-arrow-white.png) no-repeat;
  638. }
  639. .steerCalib {
  640.     width:100%;
  641.     max-width:600px;
  642.     margin:20px auto 0 auto;
  643.     text-align:center;
  644.     
  645.     .tire {
  646.         display:inline-block;
  647.     
  648.         img {
  649.             width:100%;
  650.             min-width:165px;
  651.             display:block;
  652.             margin:0 auto;
  653.         }
  654.     }
  655. button.arrBut {
  656. margin:82px 0 0 0;
  657. }
  658.     button.left {
  659.         float:left;
  660.         margin-left:15px;
  661.     }
  662.     button.right {
  663.         float:right;
  664.         margin-right:15px;
  665.     }
  666. }
  667. /* Range Sensors */
  668. .rangeSett {
  669. width:100%;
  670.     margin:20px auto 0 auto;
  671.     text-align:center;
  672.     
  673.     .wrapImg {
  674.         display:inline-block;
  675.     
  676.         img {
  677.             width:100%;
  678.             min-width:165px;
  679.             display:block;
  680.             margin:0 auto;
  681.         }
  682.     }
  683. .calBox {
  684. position:relative;
  685. clear:both;
  686. float:left;
  687. width:100%;
  688. height:50px;
  689. margin-top:30px;
  690. .servoAng {
  691. display:inline-block;
  692. line-height:50px;
  693. padding:0 20px;
  694. font-size:22px;
  695. font-weight:bold;
  696. background-color:rgba(0,0,0,.05);
  697. box-shadow:0 0 8px rgba(0, 0, 0, 0.07) inset;
  698. border-radius:120px;
  699. }
  700. button.left {
  701.          float:left;
  702.          margin-left:15px;
  703.      }
  704.      button.right {
  705.          float:right;
  706.          margin-right:15px;
  707.      }
  708. .ui-btn {
  709. margin:0;
  710. }
  711. }
  712. .rangeSS {
  713. clear:both;
  714. float:left;
  715. width:100%;
  716. margin:50px 15px 0 15px;
  717. input {
  718. float:left;
  719. height:32px;
  720. line-height:32px;
  721. padding:0 10px;
  722. width:50px;
  723. border:1px solid #ccc;
  724. border-radius:5px;
  725. color:#000;
  726. }
  727. }
  728. }
  729. /* Steer Sensitivity */
  730. .optoSteer, .setSpeed {
  731. margin:0 15px 0 15px;
  732. .sliderRow, .sliderRowRS {
  733. float:left;
  734. width:100%;
  735. margin-bottom:40px;
  736. p {
  737. margin:0 0 7px 0;
  738. font-size:14px;
  739. text-shadow:1px 1px #FFFFFF;
  740. }
  741. input {
  742. float:left;
  743. height:32px;
  744. line-height:32px;
  745. padding:0 10px;
  746. width:40px;
  747. border:1px solid #ccc;
  748. border-radius:5px;
  749. }
  750. .ui-slider-track {
  751. top:9px;
  752. left:5px;
  753. margin-right:20px;
  754. border-radius:8px;
  755. .ui-btn {
  756. top:-8px;
  757. }
  758. .ui-btn-active {
  759. height:15px;
  760. background-color:#9CBA3F;
  761. }
  762. }
  763. }
  764. .sliderRowRS:last-child {
  765. margin-bottom:0;
  766. }
  767. .sliderRow:last-child {
  768. margin-bottom:20px;
  769. }
  770. .line {
  771. float:left;
  772. width:100%;
  773. margin:0 0 30px 0;
  774. border:1px dashed #666;
  775. }
  776. }
  777. /* Speed */
  778. .setSpeed {
  779.     .sliderRow {
  780.         margin-top:30px;
  781.         
  782.         input {
  783.             width:40px;
  784.         }
  785.     }
  786. }
  787. /* Angle */
  788. .steerAng {
  789.     clear:both;
  790.     float:left;
  791.     width:100%;
  792.     margin-top:-30px;
  793.     padding:15px 0;
  794.     background-color:rgba(0,0,0,.05);
  795.     font-size:22px;
  796.     font-weight:bold;
  797.     text-align:center;
  798.     box-shadow:0 0 8px rgba(0,0,0,0.07) inset;
  799.     /*color:#FD5B00;*/
  800. }
  801. /* Battery Type */
  802. .batteryType {
  803.     margin-top:20px;
  804.     
  805.     div {
  806.         padding:15px 0;
  807.         text-align:center;
  808.         
  809.         h3 {
  810.             margin:0 0 20px 0;
  811.             font-size:16px;
  812.         }
  813.     }
  814.     div:first-child {
  815.         margin-bottom:30px;
  816.     }
  817.     .active {
  818.         background-color:rgba(0,0,0,.1);
  819.     }
  820. }
  821. /* Arduino Uno - Shema */
  822. .arduino {
  823.     clear:both;
  824.     float:left;
  825.     width:100%;
  826.     margin:20px auto 30px auto;
  827.     
  828.     img {
  829.         width:100%;
  830.         max-width:278px;
  831.         display:block;
  832.         margin:0 auto;
  833.     }
  834.     
  835. }
  836. .arduinoPins {
  837.     margin:0 auto;
  838.     width:100%;
  839.     max-width:278px;
  840.     
  841.     h3 {
  842.         margin:25px 0 10px 0;
  843.         font-size:16px;
  844.         color:#666;
  845.         text-shadow:1px 1px #fff;
  846.     }
  847.     ul {
  848.         margin:0 0 20px 0;
  849.         padding:0 0 0 10px;
  850.         list-style:none;
  851.         
  852.         li {
  853.             padding:3px 0;
  854.             font-size:0.75em;
  855.             text-shadow:0 1px #fff;
  856.             
  857.             
  858.             span {
  859.                 display:inline-block;
  860.                 width:15px;
  861.                 color:#FD5B00;
  862.                 font-weight:bold;
  863.             }
  864.         }
  865.     }
  866. }
  867. /* Overlay */
  868. .overlay {
  869. display:none;
  870. position:absolute;
  871. top:0;
  872. left:0;
  873. width:100%;
  874. height:100%;
  875. background-color:rgba(0,0,0,.8);
  876. z-index:9;
  877. p {
  878. position:absolute;
  879. top:45%;
  880. width:100%;
  881. height:100%;
  882. margin:0;
  883. font-size:18px;
  884. color:#fff;
  885. text-align:center;
  886. text-transform:uppercase;
  887. line-height:100%;
  888. vertical-align:middle;
  889. }
  890. }
  891. /* Critical Temperature */
  892. #criticalTemp {
  893. display:none;
  894. position:absolute;
  895. top:0;
  896. left:0;
  897. width:100%;
  898. height:100%;
  899. background-color:#f00;
  900. z-index:9;
  901. }
  902. /* Landscape */
  903. @media screen and (orientation:landscape) {
  904.     #driveOpt {
  905.         padding:10px 0;
  906.         .driveVer {
  907.             
  908.             a {
  909.                 
  910.                 img {
  911.                     width:100%;
  912.                     max-width:80px;
  913.                 }
  914.             }
  915.         }
  916.     }
  917.     /* Battery Type */
  918.     .batteryType {
  919.         
  920.         div {
  921.             float:left;
  922.             width:50%;
  923.             height:235px;
  924.             
  925.             a {
  926.                 display:table-cell;
  927.                 vertical-align:middle;
  928.                 width:50%;
  929.                 height:193px;
  930.                 
  931.                 img {
  932.                     display:block;
  933.                     margin:0 auto;
  934.                 }
  935.             }
  936.         }
  937.         div:first-child {
  938.             margin-bottom:0;
  939.         }
  940.     }
  941.     
  942.     
  943.     /* Arduino Uno - Shema */
  944.     .arduino {
  945.         width:50%;
  946.     }
  947.     .arduinoPins {
  948.         float:left;
  949.         width:48%;
  950.         margin-left:2%;
  951.         
  952.         h3:first-child {
  953.             margin-top:20px;
  954.         }
  955.     }
  956.     
  957. }
  958. /* Small devices (tablets, 768px and up) */
  959. @media (min-width: 768px) {
  960. }
  961. /* Medium devices (desktops, 992px and up) */
  962. @media (min-width: 992px) {
  963. }
  964. /* Large devices (large desktops, 1200px and up) */
  965. @media (min-width: 1200px) {
  966. }
  967. /**** jQUERY MOBILE ****/
  968. /* On/Off Switch */
  969. select.ui-slider-switch {
  970.     position: absolute !important;
  971.     height: 1px;
  972.     width: 1px;
  973.     overflow: hidden;
  974.     clip: rect(1px,1px,1px,1px);
  975. }
  976. div.ui-slider-switch {
  977.     display: inline-block;
  978.     height: 32px;
  979.     width:80px;
  980.     top: 7px;
  981.     border-radius:30px;
  982. }
  983. .ui-slider-switch .ui-slider-label {
  984.     position: absolute;
  985.     text-align: center;
  986.     width: 100%;
  987.     overflow: hidden;
  988.     font-size: 14px;
  989.     top: 0;
  990.     line-height: 32px;
  991.     min-height: 100%;
  992.     white-space: nowrap;
  993. }
  994. .ui-slider-switch .ui-slider-label-a {
  995.     z-index: 1;
  996.     left: 0;
  997.     text-indent:-25px;
  998. }
  999. .ui-slider-switch .ui-slider-label-b {
  1000.     z-index: 0;
  1001.     right: 0;
  1002.     text-indent:25px;
  1003. }
  1004. .ui-slider-track {
  1005.     position: relative;
  1006.     overflow: visible;
  1007.     height: 15px;
  1008.     margin: 0 15px 0 68px;
  1009.     top: 6px;
  1010. }
  1011. .ui-slider-inneroffset {
  1012.     margin: 0 16px;
  1013.     position: relative;
  1014.     z-index: 1;
  1015. }
  1016. .ui-slider-track .ui-btn.ui-slider-handle {
  1017.     position: absolute;
  1018.     z-index: 1;
  1019.     top: 50%;
  1020.     width: 32px;
  1021.     height: 32px;
  1022.     margin: 0 0 0 -15px;
  1023.     outline: 0;
  1024.     padding: 0;
  1025.     border-radius:50px;
  1026.     box-shadow:0 0 3px rgba(0, 0, 0, 0.45), 0 3px 1px rgba(0, 0, 0, 0.10);
  1027. }
  1028. .ui-slider-handle-snapping {
  1029.     -webkit-transition: left 70ms linear;
  1030.     -moz-transition: left 70ms linear;
  1031.     transition: left 70ms linear;
  1032. }
  1033. .ui-btn {
  1034.     font-size: 16px;
  1035.     margin: .5em 0;
  1036.     padding: .7em 1em;
  1037.     display: block;
  1038.     position: relative;
  1039.     text-align: center;
  1040.     text-overflow: ellipsis;
  1041.     overflow: hidden;
  1042.     white-space: nowrap;
  1043.     cursor: pointer;
  1044.     -webkit-user-select: none;
  1045.     -moz-user-select: none;
  1046.     -ms-user-select: none;
  1047.     user-select: none;
  1048.     
  1049.     background:#f6f6f6;
  1050.     color:#333;
  1051.     text-shadow: 0 1px 0 #f3f3f3;
  1052. }
  1053. /* Range Slider */
  1054. .ui-rangeslider .ui-slider-input.ui-rangeslider-last {
  1055.     float: right;
  1056. }
  1057. .ui-rangeslider .ui-rangeslider-sliders {
  1058.     position: relative;
  1059.     overflow: visible;
  1060.     margin: 0 86px 0 73px;
  1061. }
  1062. .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {
  1063.     position: absolute;
  1064.     right: 0;
  1065.     left: 0;
  1066.     margin: 0;
  1067. }
  1068. /* Active */
  1069. .ui-slider-track .ui-btn-active {
  1070.     background-color:#9cba3f;
  1071.     color:#fff;
  1072.     text-shadow: 0 1px 0 #6c7e2e;
  1073.     border-radius:30px;
  1074.     box-shadow:0 0 3px rgba(0, 0, 0, 0.25) inset;
  1075. }
  1076. /* Inactive */
  1077. .ui-bar-inherit {
  1078.     background:#e5e7ea;
  1079.     color:#666;
  1080.     text-shadow: 0 1px 0 #fff;
  1081.     font-weight: bold;
  1082. }
  1083. .ui-shadow-inset {
  1084.     box-shadow: inset 0 0 4px rgba(0,0,0,.2);
  1085. }
  1086. /* Loading screen */
  1087. .ui-loading .ui-loader {
  1088.     display: block;
  1089. }
  1090. .ui-loader {
  1091.     display: none;
  1092.     z-index: 9999999;
  1093.     position: fixed;
  1094.     top: 50%;
  1095.     left: 50%;
  1096.     border:0;
  1097. }
  1098. /* Page */
  1099. /* Viewport */
  1100. .ui-mobile-viewport {
  1101.     margin: 0;
  1102.     overflow-x: visible;
  1103.     -webkit-text-size-adjust: 100%;
  1104.     -ms-text-size-adjust:none;
  1105.     -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  1106. }
  1107. /* Issue #2066 */
  1108. body.ui-mobile-viewport,
  1109. div.ui-mobile-viewport {
  1110.     overflow-x: hidden;
  1111. }
  1112. /* Page and overlay */
  1113. .ui-overlay-a,
  1114. .ui-page-theme-a,
  1115. .ui-page-theme-a .ui-panel-wrapper {
  1116.     background:             #f0f2f5;
  1117.     color:                     #333;
  1118. }
  1119. /* Bar: Toolbars, dividers, slider track */
  1120. .ui-bar-a,
  1121. .ui-page-theme-a .ui-bar-inherit,
  1122. html .ui-bar-a .ui-bar-inherit,
  1123. html .ui-body-a .ui-bar-inherit,
  1124. html body .ui-group-theme-a .ui-bar-inherit {
  1125.     background:             #f0f2f5;
  1126.     color:                     #333;
  1127. }
  1128. /* Body: Read-only lists, text inputs, collapsible content */
  1129. .ui-body-a,
  1130. .ui-page-theme-a .ui-body-inherit,
  1131. html .ui-bar-a .ui-body-inherit,
  1132. html .ui-body-a .ui-body-inherit,
  1133. html body .ui-group-theme-a .ui-body-inherit,
  1134. html .ui-panel-page-container-a {
  1135.     background:             #fff;
  1136.     color:                     #333;
  1137. }
  1138. .ui-mobile fieldset,
  1139. .ui-page {
  1140.     padding: 0;
  1141.     margin: 0;
  1142. }
  1143. /* "page" containers - full-screen views, one should always be in view post-pageload */
  1144. .ui-mobile [data-role=page],
  1145. .ui-mobile [data-role=dialog],
  1146. .ui-page {
  1147.     top: 0;
  1148.     left: 0;
  1149.     width: 100%;
  1150.     min-height: 100%;
  1151.     position: absolute;
  1152.     display: none;
  1153.     border: 0;
  1154. }
  1155. .ui-mobile .ui-page-active {
  1156.     display: block;
  1157.     overflow: visible;
  1158.     overflow-x: hidden;
  1159. }
  1160. .ui-content {
  1161.     clear:both;
  1162.     float:left;
  1163.     width:100%;
  1164.     border-width: 0;
  1165.     overflow: visible;
  1166.     overflow-x: hidden;
  1167.     padding:5px 0;
  1168. }
  1169. /* Transitions originally inspired by those from jQtouch, nice work, folks */
  1170. .ui-mobile-viewport-transitioning,
  1171. .ui-mobile-viewport-transitioning .ui-page {
  1172.     width: 100%;
  1173.     height: 100%;
  1174.     overflow: hidden;
  1175.     -webkit-box-sizing: border-box;
  1176.     -moz-box-sizing: border-box;
  1177.     box-sizing: border-box;
  1178. }
  1179. .ui-page-pre-in {
  1180.     opacity: 0;
  1181. }
  1182. .in {
  1183.     -webkit-animation-timing-function: ease-out;
  1184.     -webkit-animation-duration: 350ms;
  1185.     -moz-animation-timing-function: ease-out;
  1186.     -moz-animation-duration: 350ms;
  1187.     animation-timing-function: ease-out;
  1188.     animation-duration: 350ms;
  1189. }
  1190. .out {
  1191.     -webkit-animation-timing-function: ease-in;
  1192.     -webkit-animation-duration: 225ms;
  1193.     -moz-animation-timing-function: ease-in;
  1194.     -moz-animation-duration: 225ms;
  1195.     animation-timing-function: ease-in;
  1196.     animation-duration: 225ms;
  1197. }
  1198. @-webkit-keyframes fadein {
  1199. from { opacity: 0; }
  1200. to { opacity: 1; }
  1201. }
  1202. @-moz-keyframes fadein {
  1203. from { opacity: 0; }
  1204. to { opacity: 1; }
  1205. }
  1206. @keyframes fadein {
  1207. from { opacity: 0; }
  1208. to { opacity: 1; }
  1209. }
  1210. @-webkit-keyframes fadeout {
  1211. from { opacity: 1; }
  1212. to { opacity: 0; }
  1213. }
  1214. @-moz-keyframes fadeout {
  1215. from { opacity: 1; }
  1216. to { opacity: 0; }
  1217. }
  1218. @keyframes fadeout {
  1219. from { opacity: 1; }
  1220. to { opacity: 0; }
  1221. }
  1222. .fade.out {
  1223.     opacity: 0;
  1224.     -webkit-animation-duration: 125ms;
  1225.     -webkit-animation-name: fadeout;
  1226.     -moz-animation-duration: 125ms;
  1227.     -moz-animation-name: fadeout;
  1228.     animation-duration: 125ms;
  1229.     animation-name: fadeout;
  1230. }
  1231. .fade.in {
  1232.     opacity: 1;
  1233.     -webkit-animation-duration: 225ms;
  1234.     -webkit-animation-name: fadein;
  1235.     -moz-animation-duration: 225ms;
  1236.     -moz-animation-name: fadein;
  1237.     animation-duration: 225ms;
  1238.     animation-name: fadein;
  1239. }
  1240. /* keyframes for slidein from sides */
  1241. @-webkit-keyframes slideinfromright {
  1242. from { -webkit-transform: translate3d(100%,0,0); }
  1243. to { -webkit-transform: translate3d(0,0,0); }
  1244. }
  1245. @-moz-keyframes slideinfromright {
  1246. from { -moz-transform: translateX(100%); }
  1247. to { -moz-transform: translateX(0); }
  1248. }
  1249. @keyframes slideinfromright {
  1250. from { transform: translateX(100%); }
  1251. to { transform: translateX(0); }
  1252. }
  1253. @-webkit-keyframes slideinfromleft {
  1254. from { -webkit-transform: translate3d(-100%,0,0); }
  1255. to { -webkit-transform: translate3d(0,0,0); }
  1256. }
  1257. @-moz-keyframes slideinfromleft {
  1258. from { -moz-transform: translateX(-100%); }
  1259. to { -moz-transform: translateX(0); }
  1260. }
  1261. @keyframes slideinfromleft {
  1262. from { transform: translateX(-100%); }
  1263. to { transform: translateX(0); }
  1264. }
  1265. /* keyframes for slideout to sides */
  1266. @-webkit-keyframes slideouttoleft {
  1267. from { -webkit-transform: translate3d(0,0,0); }
  1268. to { -webkit-transform: translate3d(-100%,0,0); }
  1269. }
  1270. @-moz-keyframes slideouttoleft {
  1271. from { -moz-transform: translateX(0); }
  1272. to { -moz-transform: translateX(-100%); }
  1273. }
  1274. @keyframes slideouttoleft {
  1275. from { transform: translateX(0); }
  1276. to { transform: translateX(-100%); }
  1277. }
  1278. @-webkit-keyframes slideouttoright {
  1279. from { -webkit-transform: translate3d(0,0,0); }
  1280. to { -webkit-transform: translate3d(100%,0,0); }
  1281. }
  1282. @-moz-keyframes slideouttoright {
  1283. from { -moz-transform: translateX(0); }
  1284. to { -moz-transform: translateX(100%); }
  1285. }
  1286. @keyframes slideouttoright {
  1287. from { transform: translateX(0); }
  1288. to { transform: translateX(100%); }
  1289. }
  1290. .slide.out, .slide.in {
  1291.     -webkit-animation-timing-function: ease-out;
  1292.     -webkit-animation-duration: 350ms;
  1293.     -moz-animation-timing-function: ease-out;
  1294.     -moz-animation-duration: 350ms;
  1295.     animation-timing-function: ease-out;
  1296.     animation-duration: 350ms;
  1297. }
  1298. .slide.out {
  1299.     -webkit-transform: translate3d(-100%,0,0);
  1300.     -webkit-animation-name: slideouttoleft;
  1301.     -moz-transform: translateX(-100%);
  1302.     -moz-animation-name: slideouttoleft;
  1303.     transform: translateX(-100%);
  1304.     animation-name: slideouttoleft;
  1305. }
  1306. .slide.in {
  1307.     -webkit-transform: translate3d(0,0,0);
  1308.     -webkit-animation-name: slideinfromright;
  1309.     -moz-transform: translateX(0);
  1310.     -moz-animation-name: slideinfromright;
  1311.     transform: translateX(0);
  1312.     animation-name: slideinfromright;
  1313. }
  1314. .slide.out.reverse {
  1315.     -webkit-transform: translate3d(100%,0,0);
  1316.     -webkit-animation-name: slideouttoright;
  1317.     -moz-transform: translateX(100%);
  1318.     -moz-animation-name: slideouttoright;
  1319.     transform: translateX(100%);
  1320.     animation-name: slideouttoright;
  1321. }
  1322. .slide.in.reverse {
  1323.     -webkit-transform: translate3d(0,0,0);
  1324.     -webkit-animation-name: slideinfromleft;
  1325.     -moz-transform: translateX(0);
  1326.     -moz-animation-name: slideinfromleft;
  1327.     transform: translateX(0);
  1328.     animation-name: slideinfromleft;
  1329. }
  1330. .slidefade.out {
  1331.     -webkit-transform: translateX(-100%);
  1332.     -webkit-animation-name: slideouttoleft;
  1333.     -webkit-animation-duration: 225ms;
  1334.     -moz-transform: translateX(-100%);
  1335.     -moz-animation-name: slideouttoleft;
  1336.     -moz-animation-duration: 225ms;
  1337.     transform: translateX(-100%);
  1338.     animation-name: slideouttoleft;
  1339.     animation-duration: 225ms;
  1340. }
  1341. .slidefade.in {
  1342.     -webkit-transform: translateX(0);
  1343.     -webkit-animation-name: fadein;
  1344.     -webkit-animation-duration: 200ms;
  1345.     -moz-transform: translateX(0);
  1346.     -moz-animation-name: fadein;
  1347.     -moz-animation-duration: 200ms;
  1348.     transform: translateX(0);
  1349.     animation-name: fadein;
  1350.     animation-duration: 200ms;
  1351. }
  1352. .slidefade.out.reverse {
  1353.     -webkit-transform: translateX(100%);
  1354.     -webkit-animation-name: slideouttoright;
  1355.     -webkit-animation-duration: 200ms;
  1356.     -moz-transform: translateX(100%);
  1357.     -moz-animation-name: slideouttoright;
  1358.     -moz-animation-duration: 200ms;
  1359.     transform: translateX(100%);
  1360.     animation-name: slideouttoright;
  1361.     animation-duration: 200ms;
  1362. }
  1363. .slidefade.in.reverse {
  1364.     -webkit-transform: translateX(0);
  1365.     -webkit-animation-name: fadein;
  1366.     -webkit-animation-duration: 200ms;
  1367.     -moz-transform: translateX(0);
  1368.     -moz-animation-name: fadein;
  1369.     -moz-animation-duration: 200ms;
  1370.     transform: translateX(0);
  1371.     animation-name: fadein;
  1372.     animation-duration: 200ms;
  1373. }
  1374. /* slide down */
  1375. .slidedown.out {
  1376.     -webkit-animation-name: fadeout;
  1377.     -webkit-animation-duration: 100ms;
  1378.     -moz-animation-name: fadeout;
  1379.     -moz-animation-duration: 100ms;
  1380.     animation-name: fadeout;
  1381.     animation-duration: 100ms;
  1382. }
  1383. .slidedown.in {
  1384.     -webkit-transform: translateY(0);
  1385.     -webkit-animation-name: slideinfromtop;
  1386.     -webkit-animation-duration: 250ms;
  1387.     -moz-transform: translateY(0);
  1388.     -moz-animation-name: slideinfromtop;
  1389.     -moz-animation-duration: 250ms;
  1390.     transform: translateY(0);
  1391.     animation-name: slideinfromtop;
  1392.     animation-duration: 250ms;
  1393. }
  1394. .slidedown.in.reverse {
  1395.     -webkit-animation-name: fadein;
  1396.     -webkit-animation-duration: 150ms;
  1397.     -moz-animation-name: fadein;
  1398.     -moz-animation-duration: 150ms;
  1399.     animation-name: fadein;
  1400.     animation-duration: 150ms;
  1401. }
  1402. .slidedown.out.reverse {
  1403.     -webkit-transform: translateY(-100%);
  1404.     -webkit-animation-name: slideouttotop;
  1405.     -webkit-animation-duration: 200ms;
  1406.     -moz-transform: translateY(-100%);
  1407.     -moz-animation-name: slideouttotop;
  1408.     -moz-animation-duration: 200ms;
  1409.     transform: translateY(-100%);
  1410.     animation-name: slideouttotop;
  1411.     animation-duration: 200ms;
  1412. }
  1413. @-webkit-keyframes slideinfromtop {
  1414. from { -webkit-transform: translateY(-100%); }
  1415. to { -webkit-transform: translateY(0); }
  1416. }
  1417. @-moz-keyframes slideinfromtop {
  1418. from { -moz-transform: translateY(-100%); }
  1419. to { -moz-transform: translateY(0); }
  1420. }
  1421. @keyframes slideinfromtop {
  1422. from { transform: translateY(-100%); }
  1423. to { transform: translateY(0); }
  1424. }
  1425. @-webkit-keyframes slideouttotop {
  1426. from { -webkit-transform: translateY(0); }
  1427. to { -webkit-transform: translateY(-100%); }
  1428. }
  1429. @-moz-keyframes slideouttotop {
  1430. from { -moz-transform: translateY(0); }
  1431. to { -moz-transform: translateY(-100%); }
  1432. }
  1433. @keyframes slideouttotop {
  1434. from { transform: translateY(0); }
  1435. to { transform: translateY(-100%); }
  1436. }
  1437. /* slide up */
  1438. .slideup.out {
  1439.     -webkit-animation-name: fadeout;
  1440.     -webkit-animation-duration: 100ms;
  1441.     -moz-animation-name: fadeout;
  1442.     -moz-animation-duration: 100ms;
  1443.     animation-name: fadeout;
  1444.     animation-duration: 100ms;
  1445. }
  1446. .slideup.in {
  1447.     -webkit-transform: translateY(0);
  1448.     -webkit-animation-name: slideinfrombottom;
  1449.     -webkit-animation-duration: 250ms;
  1450.     -moz-transform: translateY(0);
  1451.     -moz-animation-name: slideinfrombottom;
  1452.     -moz-animation-duration: 250ms;
  1453.     transform: translateY(0);
  1454.     animation-name: slideinfrombottom;
  1455.     animation-duration: 250ms;
  1456. }
  1457. .slideup.in.reverse {
  1458.     -webkit-animation-name: fadein;
  1459.     -webkit-animation-duration: 150ms;
  1460.     -moz-animation-name: fadein;
  1461.     -moz-animation-duration: 150ms;
  1462.     animation-name: fadein;
  1463.     animation-duration: 150ms;
  1464. }
  1465. .slideup.out.reverse {
  1466.     -webkit-transform: translateY(100%);
  1467.     -webkit-animation-name: slideouttobottom;
  1468.     -webkit-animation-duration: 200ms;
  1469.     -moz-transform: translateY(100%);
  1470.     -moz-animation-name: slideouttobottom;
  1471.     -moz-animation-duration: 200ms;
  1472.     transform: translateY(100%);
  1473.     animation-name: slideouttobottom;
  1474.     animation-duration: 200ms;
  1475. }
  1476. @-webkit-keyframes slideinfrombottom {
  1477. from { -webkit-transform: translateY(100%); }
  1478. to { -webkit-transform: translateY(0); }
  1479. }
  1480. @-moz-keyframes slideinfrombottom {
  1481. from { -moz-transform: translateY(100%); }
  1482. to { -moz-transform: translateY(0); }
  1483. }
  1484. @keyframes slideinfrombottom {
  1485. from { transform: translateY(100%); }
  1486. to { transform: translateY(0); }
  1487. }
  1488. @-webkit-keyframes slideouttobottom {
  1489. from { -webkit-transform: translateY(0); }
  1490. to { -webkit-transform: translateY(100%); }
  1491. }
  1492. @-moz-keyframes slideouttobottom {
  1493. from { -moz-transform: translateY(0); }
  1494. to { -moz-transform: translateY(100%); }
  1495. }
  1496. @keyframes slideouttobottom {
  1497. from { transform: translateY(0); }
  1498. to { transform: translateY(100%); }
  1499. }
  1. var chatHub;
  2. var mobile;
  3. // Touch - Click events
  4. var TCstart;
  5. var TCstop;
  6. $(document).ready(function () {
  7. var selectedCon;
  8. var domainURL = "home.tvojnet.si";
  9. // Mobile - Desktop (Touch - Click) events
  10. mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
  11. TCstart = mobile ? "touchstart" : "mousedown";
  12. TCstop = mobile ? "touchend" : "mouseup";
  13. $('.connectOpt .row').on('touchstart mousedown', function () {
  14. $('.connectOpt .error').hide();
  15. $('.connectOpt .row').each(function () {
  16. $(this).removeClass("active");
  17. });
  18. var selected = $(this);
  19. selected.addClass("active");
  20. selectedCon = selected.attr("id");
  21. });
  22. $('#connectForm').submit(function (event) {
  23. vibrate();
  24. // IP
  25. if (selectedCon == "serverIP") {
  26. var serverIP = $('.connectOpt .row').find('input').val();
  27. $.getScript("http://" + serverIP + "/signalr/hubs");
  28. setTimeout(function () {
  29. $.connection.hub.url = 'http://' + serverIP + '/signalr';
  30. startSignalR();
  31. }, 1000);
  32. $('#connectForm').remove();
  33. }
  34. // Domain
  35. else if (selectedCon == "serverDomain") {
  36. $.getScript("http://" + domainURL + "/signalr/hubs");
  37. setTimeout(function () {
  38. $.connection.hub.url = 'http://' + domainURL + '/signalr';
  39. startSignalR();
  40. }, 8000);
  41. $('#connectForm').remove();
  42. }
  43. else {
  44. $('#noConnection').after("<div class='error'>You must select a connection method</div>");
  45. }
  46. event.preventDefault();
  47. });
  48. });
  49. function startSignalR() {
  50. chatHub = $.connection.chatHub;
  51. // Register client Methods to be called by server
  52. chatHub.client.arread = function (data) {
  53. arduinoData(data);
  54. }
  55. $.connection.hub.start().done(function () {
  56. keepAlive();
  57. connectionActive();
  58. sendOptions();
  59. }).fail(function (msg) {
  60. alert("Failed to connect " + msg);
  61. connectionDisc();
  62. });
  63. }
  1. // Name Commands
  2. // dm -> drive mode
  3. // ad -> accelerometers drive
  4. // ab -> accelerometers backward (drive)
  5. // as -> accelerometers steer
  6. // db -> drive buttons
  7. // kp -> keep alive (connection)
  8. // sc -> steer calibrate
  9. // st -> stop the car on exit driveMode 2 (Accelerometers)
  10. // sf -> speed factor
  11. // ARDUINO OPTIONS
  12. // rs -> range sensors
  13. // rc -> range sensor servo angle
  14. // cl -> car lights
  15. // bl -> blinkers
  16. // b4 -> all 4 blinkers
  17. // cm -> camera
  18. // ll -> long lights
  19. // INCOMING DATA (ARDUINO DATA)
  20. // mt -> motor temperature
  21. // sp -> car speed
  22. // bv -> battery voltage
  23. // rs -> range sensor problem
  24. // Global variables
  25. var calibrated;
  26. if(localStorage.getItem("option-calibrate") == "on") {
  27.     calibrated = true;
  28. }
  29. // Range Sensors
  30. if (localStorage.getItem("arOpt-rs") == null) {
  31. localStorage.setItem("arOpt-rs", "on");
  32. }
  33. // Accelerometers & Device Orientation
  34. var accY;
  35. var orienG;
  36. // Drive/Steer Tolerance
  37. var tempDrive = 0;
  38. var tempSteer = 0;
  39. var driveTol = 3;
  40. var steerTol = 3;
  41. // Speed Angle
  42. var speedAngle = 25;
  43. var speedFactor = 25;
  44. var speedAngleBack = 25;
  45. var speedFactorBack = 25;
  46. var speedNeutralMax = 5;
  47. var speedNeutralMin = 5;
  48. // Steer Angle
  49. var steerAngle = 25;
  50. var steerFactor = 25;
  51. var steerZone = 5;
  52. // End Character
  53. var endChar = "\n";
  54. // Drive Mode
  55. var driveMode = 0;
  56. // Touch - Click events
  57. //var TCstart;
  58. //var TCstop;
  59. // Steer Calibrated Max Angle
  60. var steerMaxAng = 15;
  61. var carMaxSpeed = 0;
  62. var speedAccF = 1;
  63. // Default (speed Factor)
  64. var maxSpeed = 1;
  65. $(document).ready(function() {
  66. // Clear All Local Storage
  67. $('#arduinoImg #clearLS').on('click', function () {
  68. localStorage.clear();
  69. alert("Local Storage Cleared");
  70. });
  71.     // Connect Serial
  72.     $('#connect').on(TCstart, function () {
  73.         chatHub.server.connectserial().done(function () {
  74.             connectionActive();
  75.             sendOptions();
  76.         }).fail(function(msg) {
  77.             alert("Failed to connect " + msg);
  78.             connectionDisc();
  79.         });
  80.         vibrate();
  81.     });
  82.     // jQuery Mobile
  83.     //$.mobile.defaultPageTransition = "slidefade";
  84.     // Drive Mode
  85.     $('#driveOpt .driveVer').on(TCstart, function() {
  86.         driveMode = $(this).attr("id");
  87.         chatHub.server.arduino("dm" + driveMode + endChar);
  88.         vibrate();
  89.      // Change to Portrait Orientation Notification
  90.         if (window.orientation == 0 || window.orientation == 180) {
  91.          $($(this).find('a').attr("href") + ' .overlay').show();
  92.         }
  93.     });
  94.     
  95. // HTML5 DeviceOrientation event
  96.     // Forward/Backward
  97.     window.addEventListener('deviceorientation', function(event) {
  98.         // Drive Mode
  99.         if(driveMode == 2) {
  100.             orienG = event.gamma;
  101.          // Calibrated
  102.      if(calibrated == true) {
  103.          var drive = parseInt((event.gamma - parseFloat(localStorage.getItem("orientationG"))) + 90);
  104.          var origAng = drive;
  105.                 
  106. // Forward
  107.          if((drive < 90) && (drive >= tempDrive + driveTol || drive <= tempDrive - driveTol)) {
  108.              var angFact = speedAngle / speedFactor;
  109.              drive = parseInt(drive * angFact);
  110.              var neuFact = speedNeutralMax * angFact;
  111.                     var speedFact = speedFactor / (speedFactor - speedNeutralMax);
  112.                     var speed = parseInt((drive - neuFact) * speedFact);
  113.          
  114.           driveCar(speed, origAng, drive);
  115.                     tempDrive = drive;
  116.          }
  117.          // Backward
  118.          else if ((drive > 270) && (drive >= tempDrive + driveTol || drive <= tempDrive - driveTol)) {
  119.           var angFact = speedAngleBack / speedFactorBack;
  120.           drive = parseInt(((drive - 360) * angFact) * -1);
  121.           var neuFact = speedNeutralMin * angFact;
  122.           var speedFact = speedFactorBack / (speedFactorBack - speedNeutralMin);
  123.           var speedB = parseInt((drive - neuFact) * speedFact);
  124.          
  125.           driveCar(drive, origAng, speedB);
  126.                     tempDrive = drive;
  127.          }
  128.      } // NOT Calibrated
  129.      else {
  130.          var drive = parseInt(event.gamma + 90);
  131.          var origAng = drive;
  132.      // Forward
  133.          if((drive < 90) && (drive >= tempDrive + driveTol || drive <= tempDrive - driveTol)) {
  134.              var angFact = speedAngle / speedFactor;
  135.              drive = parseInt(drive * angFact);
  136.              var neuFact = speedNeutralMax * angFact;
  137.                     var speedFact = speedFactor / (speedFactor - speedNeutralMax);
  138.                     var speed = parseInt((drive - neuFact) * speedFact);
  139.          
  140.           driveCar(speed, origAng, drive);
  141.                     tempDrive = drive;
  142.          }
  143.          // Backward
  144.          else if ((drive > 270) && (drive >= tempDrive + driveTol || drive <= tempDrive - driveTol)) {
  145.           var angFact = speedAngleBack / speedFactorBack;
  146.           drive = parseInt(((drive - 360) * angFact) * -1);
  147.           var neuFact = speedNeutralMin * angFact;
  148.           var speedFact = speedFactorBack / (speedFactorBack - speedNeutralMin);
  149.           var speedB = parseInt((drive - neuFact) * speedFact);
  150.          
  151.           driveCar(drive, origAng, speedB);
  152.                     tempDrive = drive;
  153.          }
  154.      }
  155. }
  156.     }, false);
  157.     
  158.     // PHONEGAP
  159.     // The watch id references the current `watchAcceleration`
  160. var watchID = null;
  161. // Wait for device API libraries to load
  162. document.addEventListener("deviceready", onDeviceReady, false);
  163. // device APIs are available
  164. function onDeviceReady() {
  165. startWatch();
  166. }
  167. // Start watching the acceleration
  168. function startWatch() {
  169. // Update acceleration every milisec
  170. var options = { frequency: 20 };
  171.      watchID = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
  172. }
  173. // onSuccess: Get a snapshot of the current acceleration
  174. // Left/Right
  175. function onSuccess(acceleration) {
  176.     // Drive Mode
  177.     if(driveMode == 2) {     
  178.      accY = acceleration.y;
  179.     
  180.      // Calibrated
  181.      if(calibrated == true) {
  182.          var steer = (Math.round((acceleration.y - parseFloat(localStorage.getItem("calibrationY"))) * 10) / 10) * 10;
  183.          // Steer Sensitivity
  184.          steer = parseInt(steer * (steerAngle / steerFactor));
  185.          if(steer >= tempSteer + steerTol || steer <= tempSteer - steerTol) {
  186.              steerCar(steer);
  187.              tempSteer = steer;
  188.          }
  189.      } // NOT Calibrated
  190.      else {
  191.          var steer = (Math.round(acceleration.y * 10) / 10) * 10;
  192.      // Steer Sensitivity
  193.          steer = parseInt(steer * (steerAngle / steerFactor));
  194.          if(steer >= tempSteer + steerTol || steer <= tempSteer - steerTol) {
  195.              steerCar(steer);
  196.              tempSteer = steer;
  197.          }
  198.      }
  199. }
  200. }
  201. // onError: Failed to get the acceleration
  202. function onError() {
  203. alert('Failed to get the acceleration!');
  204. }
  205. // Stop watching the acceleration
  206. /*function stopWatch() {
  207. if (watchID) {
  208. navigator.accelerometer.clearWatch(watchID);
  209. watchID = null;
  210. }
  211. }*/
  212. // HTML5 Local Storage
  213. $('select[name="rangeSensors"], select[name="blinkers"]').on('change', function (event, ui) {
  214. var selectedID = $(this).attr("id");
  215. // For On/Off Switch
  216. localStorage.setItem("arOpt-" + selectedID, $(this).val());
  217. if (localStorage.getItem("arOpt-" + selectedID) == "on") {
  218. chatHub.server.arduino(selectedID + 1 + endChar);
  219. } else {
  220. chatHub.server.arduino(selectedID + 0 + endChar);
  221. }
  222.     });
  223.     
  224.     // If Calibrate Change
  225.     $('select[name="calibrate"]').on('change', function(event, ui) {
  226.         localStorage.setItem("option-calibrate", $(this).val());
  227.         
  228.         if(localStorage.getItem("option-calibrate") == "on") {
  229.             calibrate();
  230.         } else {
  231.             calibrated = false;
  232.         }
  233.     });
  234.             
  235. // Vibrate
  236.     $('select[name="vibrate"]').on('change', function(event, ui) {
  237.      localStorage.setItem("option-" + $(this).closest('li').attr("id"), $(this).val());
  238. });
  239.     
  240.     // SubPages
  241.     $('#options .subpage').on('click', function (event, ui) {
  242.         var selected = $(this).attr("id");
  243.         $(":mobile-pagecontainer").pagecontainer('change', "#" + selected);
  244.     });
  245.     $('.dashboard li.speedSet').on(TCstart, function () {
  246.      $(":mobile-pagecontainer").pagecontainer('change', "#speed");
  247.     });
  248.     
  249.     // Set Default States (Switch On/Off, Sliders) from HTML5 Local Storage -> On page load
  250.     for(i=0; i < localStorage.length; i++) {
  251.      var optName = localStorage.key(i);
  252.      if ((optName.substr(0, 7) == "option-" || optName.substr(0, 6) == "arOpt-") && localStorage.getItem(optName) == "on") {
  253.      $('select[name="' + optName.substr(7) + '"] option[value="on"], select[id="' + optName.substr(6) + '"] option[value="on"]').attr("selected", "selected");
  254.         }
  255.      // Steer Sensitivity Set Saved Local Storage Settings
  256.         else if (optName.substr(0, 10) == "sliderSet-") {
  257.          var varName = optName.substr(10);
  258.          // Set Varibles
  259.          //console.log(varName + "=>" + parseInt(localStorage.getItem(optName)));
  260.          window[varName] = parseInt(localStorage.getItem(optName));
  261. // Set Slider Values
  262.          $('input[name="' + varName + '"]').attr("value", localStorage.getItem(optName));
  263.         }
  264.     }
  265. ////////////////////////////////
  266.     // DRIVE WITH ACCELEROMETERS //
  267. ///////////////////////////////
  268.     accSpeedF();
  269. // Forward/Backward drive
  270.     function driveCar(speed, origAng, speedB) {        
  271.      // Neutral Zone
  272.      if (origAng <= speedNeutralMax || origAng >= (360 - speedNeutralMin)) {
  273.      chatHub.server.arduino("ad90" + endChar);
  274.      }
  275.      // Forward
  276.      else if (origAng > speedNeutralMax && speed <= speedAngle && origAng < 90) {
  277.      chatHub.server.arduino("ad" + parseInt(90 + (speed * speedAccF)) + endChar);
  278.      }
  279.         // Backward
  280.      else if (origAng < (360 - speedNeutralMin) && origAng > 270 && speedB <= speedAngleBack) {
  281.      chatHub.server.arduino("ad" + parseInt(90 - (speedB * 3)) + endChar);
  282.         }
  283.         // MAX Acceleration
  284.         else if(speed > speedAngle && origAng < 90) {
  285.          chatHub.server.arduino("ad" + parseInt(maxSpeed) + endChar);
  286.         }
  287.         // MAX Back Acceleration
  288.         else if (speedB > speedAngleBack && origAng > 270) {
  289.          chatHub.server.arduino("ad15" + endChar);
  290.         }
  291.         // STOP
  292.         else {
  293.             chatHub.server.arduino("ad90" + endChar);
  294.         }
  295.     }
  296.     
  297.     // Left/Right steer
  298.     function steerCar(leftright) {
  299.     
  300.         //$('#testB span, #testC span').empty();
  301.         
  302.         if(leftright >= -steerAngle && leftright <= steerAngle) {
  303.          if (leftright >= -steerZone && leftright <= steerZone) {
  304.          chatHub.server.arduino("as0" + endChar);
  305.          //$('#testA span').html("000");
  306.          } else {
  307.          chatHub.server.arduino("as" + leftright + endChar);
  308.          //$('#testA span').html(leftright);
  309.          }
  310.         }
  311.         // Max left
  312.         else if(leftright < -steerAngle) {
  313.             chatHub.server.arduino("as-" + steerAngle + endChar);
  314.             
  315.             //$('#testB span').html("-25");
  316.         }
  317.         // Max Right
  318.         else if(leftright > steerAngle) {
  319.             chatHub.server.arduino("as" + steerAngle + endChar);
  320.             
  321.             //$('#testC span').html("+25");
  322.         }
  323.     }
  324.     
  325.     
  326.     /////////////////////////
  327.     // DRIVE WITH BUTTONS //
  328.     ////////////////////////
  329.     // Forward/Backward
  330. $('button#forward, button#backward').on(TCstart, function (event) {
  331. var command = $(this).val();
  332. chatHub.server.arduino("db" + command + endChar);
  333. // Vibrate
  334. if(localStorage.getItem("option-vibrate") == "on") {
  335.     vibrate();
  336. }
  337. event.preventDefault(); // Android 4.4 Touch Events
  338. })
  339. .on(TCstop, function () {
  340. chatHub.server.arduino("dbx" + endChar);
  341.     });
  342.     
  343.     // Left/Right
  344. $('button#left, button#right').on(TCstart, function (event) {
  345. var command = $(this).val();
  346. chatHub.server.arduino("db" + command + endChar);
  347. // Vibrate
  348. if(localStorage.getItem("option-vibrate") == "on") {
  349.     vibrate();
  350. }
  351. event.preventDefault(); // Android 4.4 Touch Events
  352. })
  353. .on(TCstop, function () {
  354. chatHub.server.arduino("dbg" + endChar);
  355. });
  356. /////////////////////////
  357. // DRIVE WITH KEYBOARD //
  358. ////////////////////////
  359. var allowedFB = false;
  360. var allowedLR = false;
  361. $(document).on('keydown', function (event) {
  362. if (event.keyCode == 38 || event.keyCode == 40) {
  363. if (!allowedFB) {
  364. allowedFB = true;
  365. switch (event.keyCode) {
  366. // Forward
  367. case 38: chatHub.server.arduino("dbw" + endChar);
  368. break;
  369. // Backward
  370. case 40: chatHub.server.arduino("dbs" + endChar);
  371. break;
  372. }
  373. }
  374. } else if (event.keyCode == 37 || event.keyCode == 39) {
  375. if (!allowedLR) {
  376. allowedLR = true;
  377. switch (event.keyCode) {
  378. // Left
  379. case 37: chatHub.server.arduino("dba" + endChar);
  380. break;
  381. // Right
  382. case 39: chatHub.server.arduino("dbd" + endChar);
  383. break;
  384. }
  385. }
  386. }
  387. });
  388. $(document).on('keyup', function (event) {
  389. if (event.keyCode == 38 || event.keyCode == 40) {
  390. allowedFB = false;
  391. }
  392. else if (event.keyCode == 37 || event.keyCode == 39) {
  393. allowedLR = false;
  394. }
  395. switch (event.keyCode) {
  396. // Forward
  397. case 38: chatHub.server.arduino("dbx" + endChar);
  398. break;
  399. // Backward
  400. case 40: chatHub.server.arduino("dbx" + endChar);
  401. break;
  402. // Left
  403. case 37: chatHub.server.arduino("dbg" + endChar);
  404. break;
  405. // Right
  406. case 39: chatHub.server.arduino("dbg" + endChar);
  407. break;
  408. }
  409. });
  410.     
  411. // Steer Calibrated Angle
  412. stCalibAngle();
  413.     $('.steerCalib .left').on(TCstart, function() {
  414.         var currAng = parseInt(localStorage.getItem("option-stCalibAngle"));
  415.         // Max Angle -15
  416.         if(currAng > -steerMaxAng && currAng <= steerMaxAng) {
  417.             currAng -= 1;
  418.             $('#steerCalibrate .steerAng').html(currAng);
  419.             localStorage.setItem("option-stCalibAngle", currAng);
  420.             chatHub.server.arduino("sc" + localStorage.getItem("option-stCalibAngle") + endChar);
  421.             vibrate();
  422.         }
  423.     });
  424.     $('.steerCalib .right').on(TCstart, function() {
  425.         var currAng = parseInt(localStorage.getItem("option-stCalibAngle"));
  426.         // Max Angle 15
  427.         if(currAng >= -steerMaxAng && currAng < steerMaxAng) {
  428.             currAng += 1;
  429.             $('#steerCalibrate .steerAng').html(currAng);
  430.             localStorage.setItem("option-stCalibAngle", currAng);
  431.             chatHub.server.arduino("sc" + localStorage.getItem("option-stCalibAngle") + endChar);
  432.             vibrate();
  433.         }
  434.     });
  435. // Range Sensors Servo Angle
  436.     rcCalibAngle();
  437.     $('.rangeSett .left').on(TCstart, function () {
  438.      var currAng = parseInt(localStorage.getItem("option-rcCalibAngle"));
  439.      // Max Angle -30
  440.      if (currAng > -30 && currAng <= 30) {
  441.      currAng -= 1;
  442.      $('.rangeSett .servoAng').html(currAng);
  443.      localStorage.setItem("option-rcCalibAngle", currAng);
  444.      chatHub.server.arduino("rc" + localStorage.getItem("option-rcCalibAngle") + endChar);
  445.      vibrate();
  446.      }
  447.     });
  448.     $('.rangeSett .right').on(TCstart, function () {
  449.      var currAng = parseInt(localStorage.getItem("option-rcCalibAngle"));
  450.      // Max Angle 30
  451.      if (currAng >= -30 && currAng < 30) {
  452.      currAng += 1;
  453.      $('.rangeSett .servoAng').html(currAng);
  454.      localStorage.setItem("option-rcCalibAngle", currAng);
  455.      chatHub.server.arduino("rc" + localStorage.getItem("option-rcCalibAngle") + endChar);
  456.      vibrate();
  457.      }
  458.     });
  459.     
  460.     // Page Container Show
  461.     $(document).on('pagecontainershow', function( event, ui ) {
  462.         // Stop Sending Accelerometers Data
  463.         if(ui.prevPage.attr("id") == "driveAcc") {
  464.             driveMode = 0;
  465.             // Stop the Car On Exit DriveMode 2 (Accelerometers)
  466.             chatHub.server.arduino("st" + endChar);
  467.         }
  468.     });
  469.     
  470. // Car Dashboard Controls
  471.     $('.dashboard li').on(TCstart, function () {
  472.      var selected = $(this);
  473.      if (selected.hasClass("on")) {
  474.      selected.removeClass("on");
  475.      chatHub.server.arduino(selected.attr("id") + 0 + endChar);
  476.      } else {
  477.      selected.addClass("on");
  478.      chatHub.server.arduino(selected.attr("id") + 1 + endChar);
  479.      }
  480.      vibrate();
  481.     });
  482.     
  483.     // Device Orientation Change
  484.     window.addEventListener("orientationchange", function () {
  485.      $('#driveBut .overlay, #driveAcc .overlay').hide();
  486.     });
  487.         
  488. // Drive/Steer Sensitivity Sliders
  489.     $(".sliderRow").on('change', function () {
  490.      var selected = $(this).find('input');
  491.      var sliderName = selected.attr("name");
  492.      var sliderVal = selected.val();
  493.      window[sliderName] = parseInt(sliderVal);
  494.      localStorage.setItem("sliderSet-" + sliderName, sliderVal);
  495.     
  496.      // Speed Slider
  497.      if(sliderName == "maxSpeed") {
  498.      chatHub.server.arduino("sf" + sliderVal + endChar);
  499.      }
  500.      accSpeedF();
  501.     });
  502. // Drive/Steer Sensitivity Range Sliders
  503.     $(".sliderRowRS").on('change', function () {
  504.      $(this).find('input').each(function () {
  505.      var selected = $(this);
  506.      var sliderName = selected.attr("name");
  507.      var sliderVal = selected.val();
  508.      window[sliderName] = parseInt(sliderVal);
  509.      localStorage.setItem("sliderSet-" + sliderName, sliderVal);
  510.      });
  511.     });
  512. // Video Recording (You Need to Have Installed -> Secret Video Recorder APP)
  513.     $('#driveBut .dashboard .record').on(TCstart, function () {
  514.      window.startapp.start(
  515. { android: 'com.zeronoiseapps.secretvideorecorder' },
  516. successCallback, failureCallback
  517. );
  518.     });
  519. // Stop
  520.     $('#driveBut .dashboard .record.on').on(TCstart, function () {
  521.      window.startapp.stop(
  522. { android: 'com.zeronoiseapps.secretvideorecorder' },
  523. successCallback, failureCallback
  524. );
  525.     });
  526.     function successCallback() {
  527.     }
  528.     function failureCallback(data) {
  529.     }
  530. });
  531. // Arduino Data
  532. function arduinoData(data) {
  533. var stopChar = /[^X]*/.exec(data)[0];
  534. var option = stopChar.substring(0, 2);
  535. var value = stopChar.substring(2);
  536. switch (option) {
  537. // Motor Temp
  538. case "mt": motorTemp(value);
  539. break;
  540. // Car Speed
  541. case "sp": carSpeed(value);
  542. break;
  543. // Battery Voltage
  544. case "bv": batVolt(value);
  545. break;
  546. // Range Senso Problem
  547. case "rs": rangeSens(value);
  548. break;
  549. }
  550. }
  551. // Keep Alive Connection
  552. function keepAlive() {
  553. setInterval(function () {
  554. chatHub.server.arduino("kp" + endChar);
  555. }, 100);
  556. }
  557. // Send Options to Arduino on App Start
  558. function sendOptions() {
  559. // Steer Calibrated Angle
  560. if (!localStorage.getItem("option-stCalibAngle") == 0) {
  561. chatHub.server.arduino("sc" + localStorage.getItem("option-stCalibAngle") + endChar);
  562. }
  563. // Steer Calibrated Angle
  564. if (!localStorage.getItem("option-rcCalibAngle") == 0) {
  565. chatHub.server.arduino("rc" + localStorage.getItem("option-rcCalibAngle") + endChar);
  566. }
  567. // Speed Factor
  568. if (!localStorage.getItem("sliderSet-maxSpeed") == 0) {
  569. chatHub.server.arduino("sf" + localStorage.getItem("sliderSet-maxSpeed") + endChar);
  570. }
  571. // Enabled Functions
  572. for (i = 0; i < localStorage.length; i++) {
  573. var optName = localStorage.key(i);
  574. if (localStorage.key(i).substr(0, 6) == "arOpt-" && localStorage.getItem(optName) == "on") {
  575. chatHub.server.arduino(optName.substr(6) + 1 + endChar);
  576. }
  577. }
  578. }
  579. // Calibrate Accelerometers & Device Orientation
  580. function calibrate() {
  581.     // Accelerometers & Device Orientation
  582.     localStorage.setItem("calibrationY", accY);
  583.     localStorage.setItem("orientationG", orienG);
  584.     calibrated = true;
  585. }
  586. // Vibrate (ms)
  587. function vibrate() {
  588. if(mobile) {
  589. navigator.notification.vibrate(50);
  590. }
  591. }
  592. // Connection Disconnected
  593. function connectionDisc() {
  594.     $('#connect').removeClass("active");
  595. }
  596. // Connection Active
  597. function connectionActive() {
  598.     $('#connect').addClass("active");
  599. }
  600. // Steer Calibrated Angle
  601. function stCalibAngle() {
  602. if (localStorage.getItem("option-stCalibAngle") == null) {
  603. localStorage.setItem("option-stCalibAngle", 0);
  604. }
  605.     $('#steerCalibrate .steerAng').html(localStorage.getItem("option-stCalibAngle"));
  606. }
  607. // Range Sensors Servo Motor
  608. function rcCalibAngle() {
  609. if (localStorage.getItem("option-rcCalibAngle") == null) {
  610. localStorage.setItem("option-rcCalibAngle", 0);
  611. }
  612. $('#rangeSensors .servoAng').html(localStorage.getItem("option-rcCalibAngle"));
  613. }
  614. // Car Speed
  615. function carSpeed(speed) {
  616. $('#driveBut .driveData .speed .current div').html(parseInt(speed));
  617. // MAX Speed
  618. if (parseInt(speed) > carMaxSpeed) {
  619. carMaxSpeed = parseInt(speed);
  620. $('#driveBut .driveData .speed .max span').html(parseInt(carMaxSpeed));
  621. }
  622. }
  623. // Battery Voltage
  624. function batVolt(volt) {
  625. // MAX (16,8V) => 675 => 3,3V
  626. // MIN (12,8V) => 435 => 2,13V
  627. // (15,8V) => 614 => 3V
  628. // 1V => 60 enot
  629. // 16mV => 1 enota
  630. var battPercentage = 100 * (parseInt(volt) - 435) / (597 - 435);
  631. $('#driveBut .driveData .adtData .battLevel .bar span').css("width", parseInt(battPercentage));
  632. $('#driveBut .driveData .adtData .battLevel .perc').html(parseInt(battPercentage));
  633. }
  634. // Motor Temperature
  635. var critical;
  636. function motorTemp(temp) {
  637. $('#driveAcc .ui-content #motorTemp span, #driveBut .driveData .adtData .mTemp span').html(temp);
  638. // Critical Temperature (70°)
  639. if (parseInt(temp) >= 50) {
  640. navigator.notification.vibrate(5000);
  641. critical = setInterval(criticalTemp, 50);
  642. } else {
  643. clearInterval(critical);
  644. $('#criticalTemp').hide();
  645. }
  646. }
  647. function criticalTemp() {
  648. $('#criticalTemp').toggle();
  649. }
  650. // Range Sensor Problem
  651. function rangeSens(value) {
  652. }
  653. // Accelerometers Speed Factor
  654. function accSpeedF() {
  655. speedAccF = (maxSpeed - 90) / 25;
  656. }
.