├── img ├── Gmail.png ├── Icon.psd ├── photo.ico ├── photo.jpg ├── plug-on.png ├── twitter.png ├── Icon-car.png ├── Icon-plane.png ├── facebook.png ├── plug-off.png ├── car-27-24-0.png ├── car-27-24-1.png ├── Icon-enterprise.png ├── photo_Gkf_icon.ico └── photo_ZDA_icon.ico ├── 404.html ├── README.md ├── ESP_GPS └── ESP_GPS.ino ├── js ├── bootstrap.min.js └── jquery-1.12.0.min.js └── index.html /img/Gmail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/Gmail.png -------------------------------------------------------------------------------- /img/Icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/Icon.psd -------------------------------------------------------------------------------- /img/photo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/photo.ico -------------------------------------------------------------------------------- /img/photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/photo.jpg -------------------------------------------------------------------------------- /img/plug-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/plug-on.png -------------------------------------------------------------------------------- /img/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/twitter.png -------------------------------------------------------------------------------- /img/Icon-car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/Icon-car.png -------------------------------------------------------------------------------- /img/Icon-plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/Icon-plane.png -------------------------------------------------------------------------------- /img/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/facebook.png -------------------------------------------------------------------------------- /img/plug-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/plug-off.png -------------------------------------------------------------------------------- /img/car-27-24-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/car-27-24-0.png -------------------------------------------------------------------------------- /img/car-27-24-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/car-27-24-1.png -------------------------------------------------------------------------------- /img/Icon-enterprise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/Icon-enterprise.png -------------------------------------------------------------------------------- /img/photo_Gkf_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/photo_Gkf_icon.ico -------------------------------------------------------------------------------- /img/photo_ZDA_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ExploreLab/IoT-GPS-Tracker/HEAD/img/photo_ZDA_icon.ico -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page Not Found 7 | 8 | 23 | 24 | 25 |
26 |

404

27 |

Page Not Found

28 |

The specified file was not found on this website. Please check the URL for mistakes and try again.

29 |

Why am I seeing this?

30 |

This page was generated by the Firebase Command-Line Interface. To modify it, edit the 404.html file in your project's configured public directory.

31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IoT-GPS-Tracker 2 | This is article is GPS Tracker module using GY-NEO6MV2 NEO-6M GPS Module to scan Location and then nodeMCU will send data to Firebase for the map using Google MAP API and shown in the Web application. 3 | 4 | Full Tutorial: https://myelectronicslab.com/gps-tracker/ 5 | 6 | Result: https://iot-gps-tracker.firebaseapp.com/ 7 | 8 | Dev: Jukrapun Chitpong 9 | 10 | ![Alt Text](https://firebasestorage.googleapis.com/v0/b/iot-gps-tracker.appspot.com/o/IoT_GPS_Diagram.jpg?alt=media&token=227d625b-37ca-451a-a0d0-7c0e63c43bd7) 11 | 12 | ![Alt Text](https://firebasestorage.googleapis.com/v0/b/iot-gps-tracker.appspot.com/o/IoT_GPS_055.jpg?alt=media&token=d6ce1c8a-df89-4ae8-b90d-178e5ff7fca9) 13 | 14 | ## Hardware Needed 15 | 16 | 17 | NodeMCU or ESP8166-12E 18 | 19 | GPS Module 20 | 21 | USB Data Cable 22 | 23 | ## Software Needed 24 | 25 | 26 | Web browser (Google Chrome) 27 | 28 | Sublime 29 | 30 | Arduino IDE (We using Arduino IDE version 1.8.3) 31 | 32 | ### Hardware Section. 33 | NodeMCU >> GPS Module 34 | 35 | GPIO12 (D6) >> Tx PIN 36 | 37 | GPIO13 (D7) >> Rx PIN 38 | 39 | ### Software Section. 40 | 41 | #### 1. Firebase 42 | 43 | 1.1 Sign in to Firebase 44 | 45 | 1.2 Create Project 46 | 47 | #### 2. Arduino 48 | 49 | 2.1 Open file "ESP_GPS.ino" and then Change YOUR SSID and PASS. 50 | 51 | 2.2 Change 52 | - FirebaseIO [Database ] 53 | - Database Secrets [Project Settings > SERVICE ACCOUNTS > Database Secrets] 54 | 55 | #### 3. Google MAP & FIREBASE 56 | 3.1 Google Maps APIs 57 | - Create KEY Google Maps APIs 58 | - Open files "index.html" (We using Sublime Text) 59 | - Copy KEY and Paste instead of "YOUR_API_KEY " into your application HTML. 60 | ##### ref. https://developers.google.com/maps/documentation/javascript/signedin 61 | 62 | 3.2 Add Firebase to your JavaScript Project 63 | - Create a Firebase project in the Firebase. 64 | - Click Add Firebase to your web app. 65 | - Copy script and Paste instead of initialize Firebase script into your application HTML. 66 | Click Copy, then paste the code snippet into your application HTML. 67 | 68 | 3.3 Deploy Your Site. 69 | 70 | Install the Firebase CLI 71 | - install Firebase command line tools using npm (Node.js) 72 | ##### npm install -g firebase-tools 73 | Initializing your site 74 | Open a terminal window and navigate to or create a directory for your site 75 | - Sign in to Google and Initiate your project 76 | ##### firebase login 77 | ##### firebase init 78 | 79 | Deploying your site 80 | Add your static files to your deploy directory (the default is public) 81 | - Deploy your website 82 | ##### firebase deploy 83 | #### ref. https://firebase.google.com/docs/hosting/deploying 84 | 85 | ### Finally 86 | ##### https://iot-gps-tracker.firebaseapp.com 87 | ##### Log in by USER 88 | ##### User: user@eeeg.com 89 | ##### Password: P@ssw0rd 90 | 91 | [![](http://img.youtube.com/vi/54FfeH21ptk/0.jpg)](http://www.youtube.com/watch?v=54FfeH21ptk "IoT-GPS-Tracker") 92 | 93 | -------------------------------------------------------------------------------- /ESP_GPS/ESP_GPS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Electrical Engineering Enterprise Group. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | ESP_GPS tracking using Firebase is a sample that demo of the GPS Tracker module 17 | using GY-NEO6MV2 NEO-6M GPS Module to scan Location and then nodeMCU will send data 18 | to Firebase for map using Google MAP Api and shown on Web application. 19 | 20 | Dev.Jukrapun Chitpong 21 | facebook.com/eeeg.ch 22 | date Jan29, 2017 23 | Uo to date - Dec25, 2017 24 | Uo to date - Jan2, 2018 25 | 26 | */ 27 | 28 | #include // Tiny GPS Plus Library 29 | #include // Software Serial Library so we can use other Pins for communication with the GPS module 30 | #include 31 | #include 32 | #include 33 | #include 34 | ESP8266WiFiMulti wifiMulti; 35 | #include 36 | 37 | #define YOUR_SSID "YOUR_SSID" 38 | #define YOUR_PASS "YOUR_PASS" 39 | #define FIREBASE_io "example.firebaseio.com" // Select > Database 40 | #define FIREBASE_dataSecret "Database_Secrets" // Project Overview > Project Settings > SERVICE ACCOUNTS > Database Secrets 41 | 42 | const double Office_LAT = 13.9017211; // Your Home Latitude 43 | const double Office_LNG = 100.5327769; // Your Home Longitude 44 | 45 | unsigned int localPort = 2390; 46 | static const int RXPin = 12, TXPin = 13; // Ublox 6m GPS module to pins 12 and 13 47 | static const uint32_t GPSBaud = 9600; 48 | TinyGPSPlus gps; // Create an Instance of the TinyGPS++ object called gps 49 | SoftwareSerial ss(RXPin, TXPin); // The serial connection to the GPS device 50 | 51 | boolean connectioWasAlive = true; 52 | 53 | int Sat = 0; 54 | int Minute = 0; 55 | int Minuted = 0; 56 | int Hour = 0; 57 | int Day = 0; 58 | int DayS = 0; 59 | int A = 1; 60 | int B = 0; 61 | double LAT = 13.85905; 62 | double LNG = 100.52071; 63 | 64 | // Config time 65 | int timezone = 7; // Zone +7 for Thailand 66 | char ntp_server1[20] = "time.navy.mi.th"; 67 | char ntp_server2[20] = "time.nist.gov"; 68 | char ntp_server3[20] = "time.uni.net.th"; 69 | int dst = 0; 70 | String d, m, y, h, t; 71 | 72 | unsigned long previousMillis = 0; 73 | const long interval = 1000; 74 | 75 | void setup() { 76 | 77 | // Serial.end(); 78 | // Serial.begin(115200); 79 | delay(1); 80 | 81 | ss.begin(GPSBaud); // Set Software Serial Comm Speed to 9600 82 | 83 | wifiMulti.addAP("i-Juk", "P@ssw0rd"); 84 | wifiMulti.addAP("EEEG.CH", "UFI-IoT-2017"); 85 | wifiMulti.addAP(YOUR_SSID, YOUR_PASS); 86 | 87 | while (wifiMulti.run() != WL_CONNECTED) { 88 | // Serial.println("WiFi not connected!"); 89 | delay(1000); 90 | } 91 | // Serial.println("WiFi connected!"); 92 | delay(500); 93 | 94 | /*---- Config Firebase ----*/ 95 | // Firebase.begin("example.firebaseio.com", "token_or_secret"); 96 | Firebase.begin(FIREBASE_io, FIREBASE_dataSecret); 97 | 98 | StaticJsonBuffer<200> jsonBuffer; 99 | JsonObject& root = jsonBuffer.createObject(); 100 | root["OfficeLAT"] = LocLat1(); 101 | root["OfficeLNG"] = LocLng1(); 102 | 103 | Firebase.set("GPS", root); 104 | 105 | /*---- Config Time ----*/ 106 | configTime(timezone * 3600, dst, ntp_server1, ntp_server2, ntp_server3); 107 | // Serial.println("Waiting for time"); 108 | 109 | } 110 | 111 | void loop() { 112 | if (wifiMulti.run() != WL_CONNECTED) { 113 | // Serial.println("WiFi not connected!"); 114 | delay(1000); 115 | } else {} 116 | 117 | unsigned long currentMillis = millis(); 118 | if (currentMillis - previousMillis >= interval) { 119 | previousMillis = currentMillis; 120 | LAT = gps.location.lat(); 121 | LNG = gps.location.lng(); 122 | 123 | StaticJsonBuffer<200> jsonBuffer; 124 | JsonObject& root = jsonBuffer.createObject(); 125 | root["TrackLAT"] = LocLat11(); 126 | root["TrackLNG"] = LocLng11(); 127 | root["OfficeLAT"] = LocLat1(); 128 | root["OfficeLNG"] = LocLng1(); 129 | 130 | // A = (float)Firebase.get("Amount/A"); 131 | if (A > 0) { 132 | A++; 133 | B = !B; 134 | 135 | StaticJsonBuffer<200> jsonBuffer; 136 | JsonObject& rootC = jsonBuffer.createObject(); 137 | rootC["A"] = A; 138 | rootC["B"] = B; 139 | Firebase.set("Amount", rootC); 140 | } else {} 141 | delay(100); 142 | 143 | /*------------------- Local_Time.SET to Firebase -------------------*/ 144 | NowString(); 145 | 146 | if (Minuted < Minute) { 147 | Firebase.set("TinyGPSPlusTIME/hour", Hour); 148 | Firebase.set("TinyGPSPlusTIME/minute", Minute); 149 | Firebase.set("TinyGPSPlusDAY/year", y.toInt()); 150 | Firebase.set("TinyGPSPlusDAY/month", m.toInt()); 151 | Firebase.set("TinyGPSPlusDAY/day", d.toInt()); 152 | 153 | Firebase.set("GPS", root); 154 | 155 | } else {} 156 | yield(); 157 | 158 | /*------------------- Serial ------------------- 159 | Serial.print("Latitude : "); 160 | Serial.print(LAT, 6); 161 | Serial.print(" Longitude : "); 162 | Serial.print(LNG, 6); 163 | Serial.print(" Time NTP : ");*/ 164 | delay(10); 165 | 166 | smartDelay(500); // Run Procedure smartDelay 167 | 168 | Minuted = Minute; 169 | DayS = Day; 170 | } 171 | } 172 | 173 | String LocLat11() { 174 | String LocLat11 = ""; 175 | LocLat11 += String(LAT, 6); 176 | 177 | return LocLat11; 178 | } 179 | 180 | String LocLng11() { 181 | String LocLng11 = ""; 182 | LocLng11 += String(LNG, 6); 183 | 184 | return LocLng11; 185 | } 186 | 187 | String LocLat1() { 188 | String LocLat1 = ""; 189 | LocLat1 += String(Office_LAT, 6); 190 | 191 | return LocLat1; 192 | } 193 | 194 | String LocLng1() { 195 | String LocLng1 = ""; 196 | LocLng1 += String(Office_LNG, 6); 197 | 198 | return LocLng1; 199 | } 200 | 201 | String NowString() { 202 | time_t now = time(nullptr); 203 | struct tm* newtime = localtime(&now); 204 | 205 | String tmpNow = ""; 206 | tmpNow += String(newtime->tm_year + 1900); 207 | tmpNow += "-"; 208 | tmpNow += String(newtime->tm_mon + 1); 209 | tmpNow += "-"; 210 | tmpNow += String(newtime->tm_mday); 211 | tmpNow += " "; 212 | tmpNow += String(newtime->tm_hour); 213 | tmpNow += ":"; 214 | tmpNow += String(newtime->tm_min); 215 | tmpNow += ":"; 216 | tmpNow += String(newtime->tm_sec); 217 | 218 | y = String(newtime->tm_year + 1900); 219 | // Serial.print(y); 220 | m = String(newtime->tm_mon + 1); 221 | // Serial.print(m); 222 | d = String(newtime->tm_mday); 223 | // Serial.print(d); 224 | Hour = String(newtime->tm_hour).toInt(); 225 | // Serial.print(Hour); 226 | Minute = String(newtime->tm_min).toInt(); 227 | // Serial.println(Minute); 228 | 229 | // Serial.println(tmpNow); 230 | return tmpNow; 231 | 232 | } 233 | 234 | static void smartDelay(unsigned long ms) { // This custom version of delay() ensures that the gps object is being "fed". 235 | unsigned long start = millis(); 236 | do { 237 | while (ss.available()) 238 | gps.encode(ss.read()); 239 | } while (millis() - start < ms); 240 | } 241 | 242 | /*Credit 243 | http://www.instructables.com/id/ESP8266-12e-With-GPS-OLED-Display/?ALLSTEPS 244 | https://github.com/mkconer/ESP8266_GPS 245 | http://arduiniana.org/libraries/tinygpsplus/ 246 | 247 | */ 248 | 249 | /*Ref.TinyPlus++ 250 | Serial.println(gps.location.lat(), 6); // Latitude in degrees (double) 251 | Serial.println(gps.location.lng(), 6); // Longitude in degrees (double) 252 | Serial.print(gps.location.rawLat().negative ? "-" : "+"); 253 | Serial.println(gps.location.rawLat().deg); // Raw latitude in whole degrees 254 | Serial.println(gps.location.rawLat().billionths);// ... and billionths (u16/u32) 255 | Serial.print(gps.location.rawLng().negative ? "-" : "+"); 256 | Serial.println(gps.location.rawLng().deg); // Raw longitude in whole degrees 257 | Serial.println(gps.location.rawLng().billionths);// ... and billionths (u16/u32) 258 | Serial.println(gps.date.value()); // Raw date in DDMMYY format (u32) 259 | Serial.println(gps.date.year()); // Year (2000+) (u16) 260 | Serial.println(gps.date.month()); // Month (1-12) (u8) 261 | Serial.println(gps.date.day()); // Day (1-31) (u8) 262 | Serial.println(gps.time.value()); // Raw time in HHMMSSCC format (u32) 263 | Serial.println(gps.time.hour()); // Hour (0-23) (u8) 264 | Serial.println(gps.time.minute()); // Minute (0-59) (u8) 265 | Serial.println(gps.time.second()); // Second (0-59) (u8) 266 | Serial.println(gps.time.centisecond()); // 100ths of a second (0-99) (u8) 267 | Serial.println(gps.speed.value()); // Raw speed in 100ths of a knot (i32) 268 | Serial.println(gps.speed.knots()); // Speed in knots (double) 269 | Serial.println(gps.speed.mph()); // Speed in miles per hour (double) 270 | Serial.println(gps.speed.mps()); // Speed in meters per second (double) 271 | Serial.println(gps.speed.kmph()); // Speed in kilometers per hour (double) 272 | Serial.println(gps.course.value()); // Raw course in 100ths of a degree (i32) 273 | Serial.println(gps.course.deg()); // Course in degrees (double) 274 | Serial.println(gps.altitude.value()); // Raw altitude in centimeters (i32) 275 | Serial.println(gps.altitude.meters()); // Altitude in meters (double) 276 | Serial.println(gps.altitude.miles()); // Altitude in miles (double) 277 | Serial.println(gps.altitude.kilometers()); // Altitude in kilometers (double) 278 | Serial.println(gps.altitude.feet()); // Altitude in feet (double) 279 | Serial.println(gps.satellites.value()); // Number of satellites in use (u32) 280 | Serial.println(gps.hdop.value()); // Horizontal Dim. of Precision (100ths-i32) 281 | 282 | */ 283 | 284 | 285 | -------------------------------------------------------------------------------- /js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap.js by @fat & @mdo 3 | * Copyright 2013 Twitter, Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0.txt 5 | */ 6 | !function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(".dropdown-backdrop").remove(),e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||("ontouchstart"in document.documentElement&&e('