diff --git a/.gitignore b/.gitignore index 25ab2bc..ffcb269 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,4 @@ *.swp *.pyc -*.log -js/mobile.js -js/init_plot.js -css/mobile.css -cache.manifest -tiles/ +node_modules/ +js/*.js diff --git a/.htaccess b/.htaccess deleted file mode 100644 index 6fcc26d..0000000 --- a/.htaccess +++ /dev/null @@ -1,11 +0,0 @@ - - SetOutputFilter DEFLATE - - -AddType text/cache-manifest .manifest -AddType text/cache-manifest .appcache - -AddType application/x-font-woff .woff -AddType application/x-font-ttf .ttf -AddType application/vnd.ms-fontobject .eot -AddType image/svg+xml .svg diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 0fdfd9a..0000000 --- a/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2012-2016 Rossen Georgiev - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 8da1f65..0000000 --- a/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# Habhub tracker - -![mobile tracker screenshot](resources/mobiletracker-screencap.png "mobile tracker screenshot") - -A webapp for tracking high altitude balloons. Works an desktop and mobile devices. -The habhub tracker is a continuation of [spacenear.us/tracker](http://spacenear.us/tracker). - -Checkout the [Live version](http://habhub.org/mt/) - -## Features - -* HAB tracking with [Habitat](http://habitat.habhub.org/) ([@github/ukhas/habitat](https://github.com/ukhas/habitat)) -* Telemetry graph for each balloon -* Chase Car functionality -* Near realtime weather overlays -* [Daylight cycle overlay](https://github.com/rossengeorgiev/nite-overlay), for long flights -* Available to embed on any website -* Map tracker with Google Maps API 3 -* Run the app natively on `iOS` or with Chrome's 'add to screen' on `Android` - -### Geo position - -Available only on mobile devices. - -The app will ask for permission to use your location. -This is required for some of the features. It is **important** to note that -your location will not be made available or send to anyone. Unless, you enable - the `chase car mode`, which will periodically upload it to habitat. _The app -will always start with `chase car mode` disabled._ - -### Offline storage - -The app will ask to use offline storage. You will need to accept, in order to -use the offline capabilities. The app will cache all files making it available -even when there is no network coverage. Latest position data will also be stored -and used when you start up with no network. When you get back online, the app -will fetch the latest position data. - -## Browser requirements - -Any modern browser should be able to run the app. Including the latest version of IE. -This is also true for mobile, some build-in browsers may not work. - -## Contribute - -Don't hesitate to report any issues, or suggest improvements. Just visit the [issues page](https://github.com/rossengeorgiev/habitat-mobile-tracker/issues). -Pull requests are welcome. - - -## Installation - -Requirements: __Java__ and (Linux or Cygwin environment) - - $ git clone git://github.com/rossengeorgiev/habitat-mobile-tracker.git - $ ./build.sh - -For __applicationCache__ to work your server needs to send the correct MIME type. -`.htaccess` for Apache is included. Consult it if you are using different server software. - -## Original design - -Author: Daniel Saul [@danielsaul](https://github.com/danielsaul) - -[See concept for phone portrait mode](https://github.com/rossengeorgiev/habitat-mobile-tracker/blob/master/resources/concept-app-portrait.png) -[See concept for tablets](https://github.com/rossengeorgiev/habitat-mobile-tracker/blob/master/resources/concept-app-tablet.png) - - - diff --git a/build.sh b/build.sh deleted file mode 100755 index 778275b..0000000 --- a/build.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# compile stylesheet -echo -n "Compiling CSS... " -cd css -rm -f mobile.css -cat base.css skeleton.css layout.css habitat-font.css main.css > mobile.tmp -java -jar "../tools/yuicompressor-2.4.8.jar" --type=css mobile.tmp > mobile.css -rm -f mobile.tmp -cd .. -echo "Done!" - -#compile javascript -echo -n "Compiling JavaScript... " -cd js -rm -f mobile.js init_plot.js -# precompiled libs -cat jquery* >> mobile.js - -VERSION="`git rev-parse --short HEAD`" - -# compile the rest -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge gmaps_extentions.js >> mobile.js -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge iscroll.js >> mobile.js -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge chasecar.lib.js | sed "s/{VER}/$VERSION/" >> mobile.js -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge nite-overlay.js >> mobile.js -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge tracker.js >> mobile.js -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge app.js >> mobile.js - -#compile plot lib and config -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge _jquery.flot.js >> init_plot.js -java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge plot_config.js >> init_plot.js - -cd .. -echo "Done!" -echo -n "Generate cache.manifest..." - - -sed "s/^\(# version\) .*$/\1 $VERSION `date +%s`/" cache.manifest-dev > cache.manifest - -echo "Done!" - -echo "Build version: $VERSION" diff --git a/cache.manifest-dev b/cache.manifest-dev deleted file mode 100644 index 701d56c..0000000 --- a/cache.manifest-dev +++ /dev/null @@ -1,75 +0,0 @@ -CACHE MANIFEST -# version {VERSION} - -# gogole maps files -http://maps.google.com/maps/api/js?v=3.22&sensor=false&libraries=map,common,controls,util,marker,onion,kml,ga,infowindow,stats,poly,overlay,weather,weather_impl,geometry&language=en_us&key=AIzaSyCOqkcNey4CCyG4X0X5qxHAhCgD8g5DwXg -http://fonts.googleapis.com/css?family=Roboto:300,400,500,700 -http://maps.gstatic.com/mapfiles/undo_poly.png -http://maps.gstatic.com/mapfiles/mv/imgs8.png -http://maps.gstatic.com/mapfiles/transparent.png -http://maps.gstatic.com/mapfiles/api-3/images/mapcnt3.png -http://maps.gstatic.com/mapfiles/api-3/images/google_white2_hdpi.png -http://maps.gstatic.com/mapfiles/api-3/images/google_white2.png -http://maps.gstatic.com/mapfiles/openhand_8_8.cur - -# app files -img/closedhand.cur -img/openhand.cur -img/logo.png -img/blank.png -img/marker-you.png -img/apple-touch-icon.png -img/markers/hab_nyan.gif -img/markers/nyan.gif -img/markers/antenna-green.png -img/markers/balloon-red.png -img/markers/balloon-blue.png -img/markers/balloon-green.png -img/markers/balloon-purple.png -img/markers/balloon-cyan.png -img/markers/balloon-orange.png -img/markers/balloon-yellow.png -img/markers/balloon-rpi.png -img/markers/car-blue.png -img/markers/car-green.png -img/markers/car-red.png -img/markers/car-yellow.png -img/markers/parachute-blue.png -img/markers/parachute-green.png -img/markers/parachute-red.png -img/markers/parachute-yellow.png -img/markers/parachute-cyan.png -img/markers/parachute-orange.png -img/markers/parachute-purple.png -img/markers/parachute-rpi.png -img/markers/payload-blue.png -img/markers/payload-cyan.png -img/markers/payload-green.png -img/markers/payload-orange.png -img/markers/payload-purple.png -img/markers/payload-red.png -img/markers/payload-yellow.png -img/markers/payload-rpi.png -img/markers/shadow.png -img/markers/target-blue.png -img/markers/target-cyan.png -img/markers/target-green.png -img/markers/target-orange.png -img/markers/target-purple.png -img/markers/target-red.png -img/markers/target-yellow.png -img/hab-spinner.gif -css/mobile.css -js/mobile.js -js/init_plot.js -font/HabitatFont.eot -font/HabitatFont.svg -font/HabitatFont.ttf -font/HabitatFont.woff -font/Roboto-regular.woff - -NETWORK: -* - -FALLBACK: -/ index.html diff --git a/coffee/habitat.coffee b/coffee/habitat.coffee new file mode 100644 index 0000000..1b30f36 --- /dev/null +++ b/coffee/habitat.coffee @@ -0,0 +1,6 @@ +$ = $ || {} + +habitat = + db: if $.couch then $.couch.db "habitat" else {} + +habitat.db.uri = "http://habitat.habhub.org/habitat/" diff --git a/coffee/habitat.tracker.Vehicle.coffee b/coffee/habitat.tracker.Vehicle.coffee new file mode 100644 index 0000000..41c133f --- /dev/null +++ b/coffee/habitat.tracker.Vehicle.coffee @@ -0,0 +1,161 @@ +# order of map elements +Z_RANGE = 1 +Z_STATION = 2 +Z_PATH = 10 +Z_CAR = 11 +Z_SHADOW = 12 +Z_PAYLOAD = 13 + +# ballons modes +MODE_BALLOON = 1 +MODE_CHUTE = 2 +MODE_LANDED = 3 + +class habitat.tracker.Vehicle +# default options + marker: null + markers_root: "img/markers/" + map: null + name: "undefined" + type: "car" + color: "blue" + position: null + altitude: 0 + + constructor: (opts) -> + if opts? + if opts.position? then @position = opts.position + if opts.altitude? then @altitude = opts.altitude + if opts.map? then @map = opts.map + + if opts.color? then @color = opts.color + if opts.type? then @type = opts.type + if opts.name? then @name = opts.name + + @init() + + + @init: -> + @marker = new google.maps.Marker + map: @map + optimized: false + zIndex: Z_PAYLOAD + icon: + url: "#{@markers_root}#{@type}-#{@color}.png" + size: new google.maps.Size(55,25), + scaledSize: new google.maps.Size(55,25) + title: @name + null + + setPosition: (lat,lng) -> + @position = new google.maps.LatLng latlng[0], latlng[1] + @marker.setPosition @position + + setAltitude: (alt) -> + @altitude = alt + +class habitat.tracker.Balloon extends habitat.tracker.Vehicle + marker_shadow: null + type: "balloon" + mode: -1 + path: null + polyline: null + timestamp: 0 + + init: -> + @path = [] + # init markers, we need two + @marker = new google.maps.Marker + map: @map + optimized: false + zIndex: Z_PAYLOAD + title: @name + @marker_shadow = new google.maps.Marker + map: @map + icon: + url: "#{@markers_root}shadow.png" + size: new google.maps.Size 24,16 + scaledSize: new google.maps.Size 24,16 + anchor: new google.maps.Point 12,8 + optimized: false + zIndex: Z_SHADOW + + @setMode MODE_BALLOON + + # draws the path + @polyline = new google.maps.Polyline + map: @map + zIndex: Z_PATH, + strokeColor: @color + strokeOpacity: 0.8, + strokeWeight: 3, + clickable: false, + draggable: false, + + # update altitude offset, when map zoom is changed + this_ref = this + google.maps.event.addListener @map,'idle', -> + this_ref.update_position() + + setTelemetry: (tele) -> + @telemetry = tele + null + + setPosition: (lat,lng) -> + @position = new google.maps.LatLng lat,lng + + addPosition: (lat,lng) -> + @setPosition lat,lng + @path.push @position + null + + setAltitude: (alt) -> + @altitude = alt + + # change marker icon to balloon, parachute or just payload + setMode: (mode) -> + if @mode is mode then return + @mode = mode + + switch mode + when MODE_BALLOON, MODE_CHUTE + @marker_shadow.setVisible true + icon = + url: "#{@markers_root}#{if MODE_BALLOON then 'balloon' else 'parachute'}-#{@color}.png" + size: new google.maps.Size(46,84), + scaledSize: new google.maps.Size(46,84) + when MODE_LANDED + @marker_shadow.setVisible false + icon = + url: "#{@markers_root}payload-#{@color}.png" + size: new google.maps.Size(17,18), + scaledSize: new google.maps.Size(17,18) + + @marker.setIcon icon + null + + # emulate altitude on the map by move the marker slighly north + altitude_offset: -> + if not @map or not @position or @mode is "landed" then return + + pixel_altitude = 0 + zoom = @map.getZoom() + zoom = if zoom > 18 then 18 else zoom + + if 0 < @altitude < 55000 + pixel_altitude = -Math.round @altitude/(1000/3)*(zoom/18.0) + habitat.tracker.map_pixel_offset @position, [0, pixel_altitude] + else + @position + + update_position: -> + @marker.setPosition @altitude_offset() + @marker_shadow.setPosition @position + + # call this to push the latest changes to the map + redraw: -> + # redraw markers + @update_position() + + # redraw path + @polyline.setPath @path diff --git a/coffee/habitat.tracker.coffee b/coffee/habitat.tracker.coffee new file mode 100644 index 0000000..8d381c7 --- /dev/null +++ b/coffee/habitat.tracker.coffee @@ -0,0 +1,187 @@ +habitat.tracker = +# configs + color_names: ["red", "blue", "green", "yellow", "purple", "orange", "cyan"] + colors: ["#f00", "blue", "green", "#ff0", "#c700e6", "#ff8a0f", "#0fffca"] + +# reserved + db: null + Vehicle: null + Balloon: null + +# properties + color_idx: 0 + flights: + active: [] + upcoming: [] + options: {} + vehicles: {} + map: null + +# methods + init: (opts) -> + if @map then return + + if opts? + @options = opts + + @map = new google.maps.Map document.getElementById('map'), + zoom: 5 + center: new google.maps.LatLng 53.467511,-2.2338940 + mapTypeId: google.maps.MapTypeId.ROADMAP + keyboardShortcuts: false + streetViewControl: false + rotateControl: false + panControl: false + scaleControl: false + zoomContro: true + zoomControlOptions: + style: google.maps.ZoomControlStyle.LARGE + scrollwheel: true + + @map._overlay = new google.maps.OverlayView() + @map._overlay.draw = -> + @map._overlay.setMap @map + + # pull flight list + @update_flight_list() + + # wait for the map to load + google.maps.event.addListenerOnce @map,'tilesloaded', -> + habitat.tracker.mapLoaded() + null + + mapLoaded: -> + tmp = window.location.search.split('=') + if tmp[0] is "?ids" + list = tmp[1].split(',') + + for id in list + @db.get_telemetry_by_id(@consumer, id) + else + @fetch_test() + + null + + # reset tracker state to pre-init state + reset: -> + delete @flights + delete @options + delete @vehicles + + @flights = + active: [] + upcoming: [] + @options = {} + @vehicles = [] + + # gets the latest flight from habitat + update_flight_list: -> + @db.get_flights (data) -> + current_ts = habitat.util.timestamp_now() + + for flight in data + flight_ts = habitat.util.rfc3339_to_timestamp flight.start + + if flight_ts < current_ts + habitat.tracker.flights.active.push flight + else + habitat.tracker.flights.upcoming.push flight + + null + + fetch_latest_telemetry: -> + for flight in @flights.active + for payload in flight.payloads + @db.get_telemetry_by_id @consumer payload._id + null + + # chews through any data from habitat + consumer: (habitat_result) -> + if habitat_result.length == 0 then return + + for row in habitat_result + switch row.doc.type + when "payload_telemetry" then habitat.tracker.process_telemetry row + when "listener_telemetry" then habitat.tracker.process_listener row + else continue + + habitat.tracker.refresh() + null + + refresh: -> + for key of @vehicles + @vehicles[key].redraw() + null + + process_telemetry: (row) -> + doc = row['doc'] + key = row['key'] + ts = key[-1..][0] + + if not @vehicles[doc.data._parsed.payload_configuration]? + @vehicles[doc.data._parsed.payload_configuration] = new habitat.tracker.Balloon + map: @map + name: doc.data.payload + color: @color_names[@color_idx++ % @color_names.length] + + veh = @vehicles[doc.data._parsed.payload_configuration] + + # if initial packet has 0,0 lat/long, drop it + if veh.path.length is 0 and doc.data.latitude is 0 and doc.data.longitude is 0 then return + + # if packet is out of order, drop it + if ts <= veh.timestamp then return + veh.timestamp = ts + + veh.setAltitude doc.data.altitude + veh.addPosition doc.data.latitude, doc.data.longitude + + telemetry = {} + + for key,val of doc.data + if key[0] is '_' then continue + + switch key + when "altitude","payload","latitude","longitude","time" + continue + else + telemetry[key] = val + + veh.setTelemetry telemetry + null + + process_listener: (row) -> + null + +# tempolary methods + fetch_test: -> + @db.get_telemetry_by_id(@consumer, "b177187f988c44cce53eca6106381564") + + clear: -> + $('body').html '' + + list: -> + out = $('body') + @clear + + out.append("Upcoming flights

") + @append(@flights.upcoming) + out.append("
Active flights

") + @append(@flights.active) + + append: (list) -> + out = $('body') + + for flight in list + out.append "#{flight.start} #{flight.name} [#{flight._id}]
" + for payload, k in flight.payloads + out.append if k == _len1-1 then "\\- " else "|-" + out.append "#{payload.name} [#{payload._id}]
" + + null + + map_pixel_offset: (pos, offset) -> + new_pos = @map._overlay.getProjection().fromLatLngToDivPixel pos + new_pos.x += offset[0] + new_pos.y += offset[1] + @map._overlay.getProjection().fromDivPixelToLatLng new_pos diff --git a/coffee/habitat.tracker.db.coffee b/coffee/habitat.tracker.db.coffee new file mode 100644 index 0000000..baf3c77 --- /dev/null +++ b/coffee/habitat.tracker.db.coffee @@ -0,0 +1,43 @@ +habitat.tracker.db = + + # pulls latest flights from habitat + get_flights: (callback, time) -> + ts = if time? then time else Math.floor (new Date()).getTime() / 1000 + + habitat.db.view "flight/end_start_including_payloads", + startkey: [ts] + include_docs: true + success: (data) -> + last = null + list = [] + payloads + + # merge payload_configs into flight docs + for row in data.rows + doc = row.doc + + if doc.type is "flight" and doc.approved is true + last = doc + payloads = doc.payloads + doc.payloads = [] + list.push doc + else if payloads.indexOf doc._id is not -1 + last.payloads.push doc + + # return results + callback list + null + + get_telemetry_by_flight_id: (callback, id) -> + habitat.db.view "payload_telemetry/flight_payload_time", + startkey: [id] + endkey: [id,{}] + include_docs: true + success: (data) -> callback data.rows + + get_telemetry_by_id: (callback, id, time = 0) -> + habitat.db.view "payload_telemetry/payload_time", + startkey: [id,time] + endkey: [id,{}] + include_docs: true + success: (data) -> callback data.rows diff --git a/coffee/habitat.util.coffee b/coffee/habitat.util.coffee new file mode 100644 index 0000000..0dd95dc --- /dev/null +++ b/coffee/habitat.util.coffee @@ -0,0 +1,12 @@ + +habitat.util = + timestamp_now: -> + Math.floor (new Date()).getTime() / 1000 + + rfc3339_to_timestamp: (str) -> + Math.floor (new Date str).getTime() / 1000 + + timestamp_to_rfc3339: (ts) -> + date = new Date() + date.setTime ts * 1000 + date.toISOString() diff --git a/css/layout.css b/css/layout.css index 2c811f3..bff1ee1 100644 --- a/css/layout.css +++ b/css/layout.css @@ -42,6 +42,10 @@ header h1{ float: left; } +header span#app_name { + float: right; +} + /* Grey Area */ #grey-section{ width: 100%; diff --git a/css/main.css b/css/main.css index c9df9e4..b05704d 100644 --- a/css/main.css +++ b/css/main.css @@ -2,12 +2,6 @@ * Main style sheet * */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto Regular'), local('Roboto-Regular'), url(../font/Roboto-regular.woff) format('woff'); -} html, body { margin: 0; @@ -15,34 +9,10 @@ html, body { width: 100%; height: 100%; overflow: hidden; - -webkit-touch-action: none; - -khtml-touch-action: none; - -moz-touch-action: none; - -ms-touch-action: none; - touch-action: none; -} -body { - font-family: "Roboto", Ariel, sans-serif; -} - -.noselect { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.rfloat { - float: right; -} -.lfloat { - float: left; } -.iScrollVerticalScrollbar { - z-index: 49; +.scrollStyleV { + z-index: 100; width: 5px; bottom: 6px; top: 6px; @@ -50,92 +20,14 @@ body { position: absolute; } -.iScrollVerticalScrollbar > div { +.scrollStyleV > div { position: absolute; background: none repeat scroll 0 0 padding-box rgba(0, 0, 0, 0.5); border: 1px solid rgba(255, 255, 255, 0.9); border-radius: 3px 3px 3px 3px; position: absolute; width: 100%; - z-index: 49; -} - -.slickbox { - z-index: 49; - background-color: #fff; - position: absolute; - height: 28px; - width: 195px; - border-radius: 20px; - box-shadow: 0 0 5px #888; - font-size: 11px; -} - -.slickbox svg { - width: 28px; - height: 28px; -} - -.slickbox span { - line-height: 14px; -} - -.slickbox div { - font-size: 14px; - margin-top: 3px; - width: 150px; - text-align: center; -} - -.slickbox svg path { - -webkit-transition: all 0.4s ease-in-out; - -moz-transition: all 0.4s ease-in-out; - -ms-transition: all 0.4s ease-in-out; - -o-transition: all 0.4s ease-in-out; - transition: all 0.4s ease-in-out; - fill: #00a3d3; -} - -#timebox { - top: 7px; - right: 5px; -} - -#lookanglesbox { - top: 40px; - right: 5px; -} - -#timebox.past svg path { - fill: #c00; -} -#timebox .current { - margin-left: 11px; -} -#timebox .local { - margin-left: 5px; -} - -.slickbox .azimuth { - margin-left: 9px; - width: 91px; -} -.slickbox .bearing { - margin-right: 5px; - width: 60px; -} -.slickbox .elevation { - margin-left: 5px; - width: 95px; -} -.slickbox .range { - margin-right: 5px; - width: 60px; -} - -#mapscreen { - float: right; - position: relative; + z-index: 100; } #map img { @@ -177,9 +69,6 @@ body { } header { - position: fixed; - top: 0; - left; 0; padding: 0; margin: 0; height: 50px; @@ -189,25 +78,18 @@ header { border-bottom: 5px solid #33b5e5; box-shadow: 0px 1px 3px #555; z-index: 5; + position: relative; } #app_name { line-height: normal; - margin-top: 6px; - position: absolute; - left: 225px; + margin-top: 10px; + position: relative; height: 40px; - text-align: left; - cursor: pointer; } header > div { position: relative; height: 50px; } - -#mapscreen { - margin-top: 55px; -} - #map, #main { position: relative; @@ -219,39 +101,6 @@ header > div { height: 100%; width: 100%; } -#main { - float: left; - overflow: hidden; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -header .search { - float: left; - width: 190px; - margin-top: 10px; -} - -header .search form { - position: relative; -} -header .search form input { - position: absolute; - border-radius: 100px; -} -header .search form input[type='text'] { - left: 0; - padding-left: 10px; - padding-right: 35px; - width: 143px; -} -header .search form input[type='submit'] { - right: 0; -} .nav { list-style: none outside none; @@ -261,18 +110,17 @@ header .search form input[type='submit'] { display: block; min-width: 40px; width: auto; - float: right; + float: left; margin: 5px 0px; } #locate-me { - position: absolute; - left: 195px; - top: 12px; + float: right; font-size: 25px; - height: 25px; - width: 25px; - line-height: 25px; + height: 45px; + line-height: 50px; + margin-top: 5px; + margin-left: 5px; cursor: pointer; } @@ -281,7 +129,6 @@ header .search form input[type='submit'] { padding: 0 5px;; float: left; height: 40px; - width: 35px; border-right: 1px solid #33b5e5; cursor: pointer; color: #fff; @@ -292,40 +139,21 @@ header .search form input[type='submit'] { .nav > li:active { background-color: #33b5e5; } .nav > li:hover { border-bottom: 5px solid #fff; } - -#main .data { - cursor: url('../img/openhand.cur'), row-resize; -} - -#main.drag, -#main.drag .data, -#main.drag .header { - cursor: url('../img/closedhand.cur'), row-resize; -} - +.header .arrow { + font-weight: normal; + float: right; + color: #aaa; + } #main .header { height: 20px; padding: 10px; padding-right: 3px; - padding-left: 5px; border-bottom: 1px solid #33b5e5; position: relative; - z-index: 51; + z-index: 4; cursor: pointer; background-color: #fff; - border-left: 5px solid #fff; -} -#main .row.selected { - border-left: 5px solid #00A3D3; -} -#main .row:hover .header { - border-left: 5px solid #00A3D3; -} - -#main .row:hover .data { - border-left: 5px solid #ccc; } - #main .vehicle0 .header { border-top: 1px solid #33b5e5; } @@ -336,58 +164,14 @@ header .search form input[type='submit'] { line-height: 100px; border: 0; } -#main .header.empty:hover { - border:0; -} #main .header span { overflow: hidden; display: block; width: 90%; float: left; - white-space: nowrap; -} - -.header .arrow { - font-weight: normal; - float: right; - color: #aaa; - display: block; - height: 14px; - width: 16px; - line-height: 11px; - font-size: 16px; - margin-top: 4px; - -webkit-transition: 0.2s linear; - -moz-transition: 0.2s linear; - -ms-transition: 0.2s linear; - -o-transition: 0.2s linear; - transition: 0.2s linear; - -webkit-transform-origin: center; - -moz-transform-origin: center; - -ms-transform-origin: center; - -o-transform-origin: center; - transform-origin: center; -} - - -.row .header .arrow:after { - content: "▲"; -} -.row:hover .arrow { - -webkit-transform: rotate(-90deg); - -moz-transform: rotate(-90deg); - -ms-transform: rotate(-90deg); - -o-transform: rotate(-90deg); - transform: rotate(-90deg); - color: #00a3d3; -} -.row.active .header .arrow { - -webkit-transform: rotate(-180deg); - -moz-transform: rotate(-180deg); - -ms-transform: rotate(-180deg); - -o-transform: rotate(-180deg); - transform: rotate(-180deg); } +.row .header .arrow:after { content: "▲"; } +.row.active .header .arrow:after { content: "▼"; } #main .row { background-color: #f4f4f4; @@ -397,83 +181,33 @@ header .search form input[type='submit'] { } #main .row .header { } -#main .row .data { - display: none; - width: 100%; - border-left: 5px solid #F4F4F4; -} - -#main .row .icon-target:before { - display: none; -} -#main .row.follow .icon-target:before { - display: inline-block; -} +#main .row:hover .header { color: #33b5e5; font-weight: bold; } +#main .row .data { display: none; width: 100%; } #main .row.active .data { display: inline-block; } #main .row .data .left, #main .row .data .right { position: relative; z-index: 4; } -#main .row .data .vbutton { - position: absolute; - background-color: #fff; - right: 5px; - top: 150px; - padding-left: 3px; - padding-right: 3px; - font-size: 10px; - border-radius: 5px; - border: 1px solid #ccc; - cursor: pointer; - z-index: 5; -} - -#main .row .data .vbutton.active { - background-color: #33b5e5; - border: 1px solid #33b5e5; - color: #fff; -} - -#main .row .data .vbutton:hover { - border: 1px solid #5E5E5E; -} - -#main .portrait .row .data .vbutton { - display: none; -} - #main .row .data img { position: absolute; z-index: 2; bottom: 40%; - right: 30%; + right: 25%; opacity: 0.6; width: 46px; height: 84px; - -webkit-transition: 0.2s ease; - -moz-transition: 0.2s ease; - -ms-transition: 0.2s ease; - -o-transition: 0.2s ease; - transition: 0.2s ease; } #main .row .data img.car { width: 55px; height: 25px; } -#main .row:hover .data img { - opacity: 0.8; -} -#main .row.follow .data img { - opacity: 1.0; -} #main .row .header .graph { position: absolute; bottom: -1px; - right: 22px; + right: 18px; width: 60px; height: 40px; - z-index: 1; } #main .row .data dt > i { font-size: 12px; @@ -482,33 +216,15 @@ header .search form input[type='submit'] { text-decoration: none; color: #00A3D3; } -#main .data dl > dt.receivers { - font-size: 12px; - font-weight: normal; -} -.flatpage { - margin-top: 55px; - overflow: auto; +#chasecarbox, +#aboutbox { position: absolute; width: 100%; - z-index: 100; + z-index: 4; background: #fff; } - -.topanel { - float: right; - position: relative; - width: auto; - padding: 0; - padding-left: 10px; - padding-right: 20px; - box-shadow: 2px 0px 8px 0px #555; - overflow-x: hidden; - z-index: 3; -} - -.flatpage p { +#aboutbox span { display: block; text-align: justify; margin-bottom: 15px; @@ -519,19 +235,18 @@ header .search form input[type='submit'] { margin: 0; } .slimContainer { - position: relative; margin: 20px auto; - width: 290px; + width: 300px; + height: 100%; } .slimContainer hr { margin-bottom: 10px; } .slimContainer .row { - width: 280px; + width: 100%; display: block; margin: 5px; vertical-align: middle; - position: relative; } .slimContainer .row.info { margin-top: 10px; @@ -539,9 +254,6 @@ header .search form input[type='submit'] { .slimContainer .row > span { float: left; } -.slimContainer .row.option > span { - width: 200px; -} .slimContainer .row.option > span { line-height: 30px; } @@ -552,8 +264,7 @@ header .search form input[type='submit'] { /* iOS styled switch buttons */ .switch { - position: absolute; - right: 0px; + float: right; height: 28px; width: 77px; border: 1px solid #979797; @@ -585,7 +296,7 @@ header .search form input[type='submit'] { height: 26px; position: relative; top: 0; - z-index: 51; + z-index: 3; border: solid 1px #919191; border-radius: 28px; box-shadow: inset 0 2px 1px white, inset 0 -2px 1px white; @@ -593,23 +304,17 @@ header .search form input[type='submit'] { background-image: -webkit-linear-gradient(#CECECE, #FBFBFB); background-image: -moz-linear-gradient(#CECECE, #FBFBFB); background-image: -o-linear-gradient(#CECECE, #FBFBFB); + -o-transition: all 0.125s ease-in-out; -webkit-transition: all 0.125s ease-in-out; -moz-transition: all 0.125s ease-in-out; - -ms-transition: all 0.125s ease-in-out; - -o-transition: all 0.125s ease-in-out; - transition: all 0.125s ease-in-out; + -o-transform: translateX(0px); -webkit-transform: translate3d(0,0,0); -moz-transform: translateX(0px); - -ms-transform: translateX(0px); - -o-transform: translateX(0px); - transform: translateX(0px); } .switch.on > .thumb { -webkit-transform: translate3d(49px,0,0); - -moz-transform: translateX(49px); - -ms-transform: translateX(49px); -o-transform: translateX(49px); - transform: translateX(49px); + -moz-transform: translateX(49px); } .switch:hover > .thumb { box-shadow: inset 0 2px 1px #fff, inset 0 -2px 1px #fff; @@ -644,41 +349,7 @@ header .search form input[type='submit'] { display: none; } -.nav .home { - display: none; -} - -@media only screen and (min-width: 900px) { -} - -@media only screen and (max-width: 600px) { - #app_name { - left: 150px; - } - #locate-me { - left: 120px; - } - header .search { - width: 110px; - } - header .search form input[type='text'] { - width: 63px; - } -} - -@media only screen and (max-width: 500px) { - #app_name { - left: 30px; - } - #locate-me { - left: 0px; - } - header .search { - display: none; - } -} - -@media only screen and (min-width: 481px) { +@media only screen and (min-width: 361px) { .portrait { display: none; } .landscape { display: block; } #telemetry_graph { @@ -688,10 +359,6 @@ header .search form input[type='submit'] { width: 280px; background: #fff; position: relative; - z-index: 2; - } - #telemetry_graph .holder { - border-left: 1px solid #ddd; } #telemetry_graph .graph_label { position: absolute; @@ -709,6 +376,7 @@ header .search form input[type='submit'] { cursor: pointer; } #map { + float: right; height: 245px; width: 280px; } @@ -716,8 +384,8 @@ header .search form input[type='submit'] { float: left; height: 245px; width: 199px; - margin-top: 55px; - box-shadow: -2px 0px 6px 0px #555; + border-right: 1px solid #ddd; + overflow: hidden; } #main .data { height: 100%; @@ -726,7 +394,7 @@ header .search form input[type='submit'] { #main .data .left { float: left; width: 160px; - padding-left: 5px; + padding-left: 10px; } #main .data dl > dt { color: #000; @@ -742,37 +410,45 @@ header .search form input[type='submit'] { line-height: 11px; font-size: 11px; } + #main .data dl > dt.receivers { + font-size: 10px; + font-weight: normal; + } + #main .data dl > dd.receivers { + font-size: 10px; + } #main .row .data img { right: 5%; top: 50px; } } -@media only screen and (max-width: 480px) { +@media only screen and (max-width: 360px) { .portrait { display: block; } .landscape { display: none; } #map{ height: 225px; } #main { - height: 150px; + height: 180px; } #main .data { - min-height: 108px; + height: 140px; } #main .data .left { float: left; width: 65%; - padding-left: 5px; + padding-left: 10px; + padding-right: 20px; } #main .data .right { float: right; padding-right: 10px; - width: 25%; + width: 20%; } #main .data dl > dt { color: #000; line-height: 11px; - margin-top: 7px; + margin-top: 15px; font-weight: bold; font-size: 14px; } @@ -783,15 +459,16 @@ header .search form input[type='submit'] { line-height: 11px; font-size: 11px; } - #main .row .header .graph { - width: 180px; - height: 40px; + #main .data dl > dt.receivers { + font-size: 10px; + font-weight: normal; } - #locate-me { - display: none; + #main .data dl > dd.receivers { + font-size: 10px; } - #app_name { - left: 0px; + #main .row .header .graph { + width: 150px; + height: 40px; } } diff --git a/embed-preview.html b/embed-preview.html deleted file mode 100644 index ed7a94e..0000000 --- a/embed-preview.html +++ /dev/null @@ -1,263 +0,0 @@ - - - Preview of embedded habhub tracker - - - - - - - -
-

Embed habhub tracker on your page

-

1. Options

-
- - -
- - -
- - -
- - -
-

2. Style

-
- - - - -
- - - - -
-

3. HTML code

- - -

4. Live preview

-
- -
-
- - - diff --git a/fabfile.py b/fabfile.py new file mode 100644 index 0000000..54a2c89 --- /dev/null +++ b/fabfile.py @@ -0,0 +1,16 @@ +from fabric.api import * + +def dothis(cmd): + if len(env.hosts) == 0: + local(cmd) + else: + run(cmd) + +def compile_coffee(): + dothis("/usr/local/lib/node_modules/coffee-script/bin/coffee -b -c -o js/ coffee/*.coffee") + +def build(): + compile_coffee() + +def clean(): + dothis("rm -f js/*js") diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index e5199b1..0000000 Binary files a/favicon.ico and /dev/null differ diff --git a/font/Roboto-regular.woff b/font/Roboto-regular.woff deleted file mode 100644 index ebea051..0000000 Binary files a/font/Roboto-regular.woff and /dev/null differ diff --git a/glyphs/icon-clock.svg b/glyphs/icon-clock.svg deleted file mode 100644 index a6d8537..0000000 --- a/glyphs/icon-clock.svg +++ /dev/null @@ -1,144 +0,0 @@ - - - - - Clock Icon - - - - - - image/svg+xml - - Clock Icon - - 2014-06-11 - - - Rossen Georgiev - - - - - Rossen Georgiev - - - - - - - - - - - - - - - - - - - diff --git a/glyphs/icon-clock_simple.svg b/glyphs/icon-clock_simple.svg deleted file mode 100644 index 3631242..0000000 --- a/glyphs/icon-clock_simple.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - Clock Icon - - - - - - - - image/svg+xml - - - - Clock Icon - - - - 2014-06-11 - - - - - - Rossen Georgiev - - - - - - - - - - Rossen Georgiev - - - - - - - - - - - - - - - - - - - - - diff --git a/glyphs/icon-code.svg b/glyphs/icon-code.svg deleted file mode 100644 index bf2bec3..0000000 --- a/glyphs/icon-code.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Code Icon - - - - - - image/svg+xml - - Code Icon - - 2014-06-06 - - - Rossen Georgiev - - - - - Rossen Georgiev - - - - - - - diff --git a/glyphs/icon-compass.svg b/glyphs/icon-compass.svg deleted file mode 100644 index 30c2129..0000000 --- a/glyphs/icon-compass.svg +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Clock Compass - - - - - - - - - - - - image/svg+xml - - Clock Compass - - 2014-07-09 - - - Rossen Georgiev - - - - - Rossen Georgiev - - - - - - - - - - - - - N - W - E - S - - - diff --git a/glyphs/icon-compass_simple.svg b/glyphs/icon-compass_simple.svg deleted file mode 100644 index 69ef31a..0000000 --- a/glyphs/icon-compass_simple.svg +++ /dev/null @@ -1,29 +0,0 @@ - - -Clock Compass - - - -image/svg+xml - -Clock Compass - -2014-07-09 - - -Rossen Georgiev - - - - -Rossen Georgiev - - - - - - - - - - diff --git a/glyphs/icon-weather.svg b/glyphs/icon-weather.svg deleted file mode 100644 index 7ea62c8..0000000 --- a/glyphs/icon-weather.svg +++ /dev/null @@ -1,74 +0,0 @@ - - - - - Weather Icon - - - - - - image/svg+xml - - Weather Icon - - 2013 - - - KickstandApps (kickstandapps.com). - - - - - KickstandApps (kickstandapps.com). - - - https://github.com/kickstandapps/WeatherIcons - - - - - diff --git a/img/closedhand.cur b/img/closedhand.cur deleted file mode 100644 index ef36639..0000000 Binary files a/img/closedhand.cur and /dev/null differ diff --git a/img/fluidicon.png b/img/fluidicon.png deleted file mode 100755 index 9345aed..0000000 Binary files a/img/fluidicon.png and /dev/null differ diff --git a/img/hab-spinner.gif b/img/hab-spinner.gif deleted file mode 100755 index 48eac54..0000000 Binary files a/img/hab-spinner.gif and /dev/null differ diff --git a/img/markers/antenna-green.png b/img/markers/antenna-green.png index 37ffbd2..62e267b 100644 Binary files a/img/markers/antenna-green.png and b/img/markers/antenna-green.png differ diff --git a/img/markers/balloon-xmark.png b/img/markers/balloon-xmark.png deleted file mode 100644 index 6e8c201..0000000 Binary files a/img/markers/balloon-xmark.png and /dev/null differ diff --git a/img/markers/car-blue.png b/img/markers/car-blue.png index 09192f0..d9a0e68 100644 Binary files a/img/markers/car-blue.png and b/img/markers/car-blue.png differ diff --git a/img/markers/car-green.png b/img/markers/car-green.png index c42da50..974dd77 100644 Binary files a/img/markers/car-green.png and b/img/markers/car-green.png differ diff --git a/img/markers/car-red.png b/img/markers/car-red.png index ce44c92..5a4dc85 100644 Binary files a/img/markers/car-red.png and b/img/markers/car-red.png differ diff --git a/img/markers/car-yellow.png b/img/markers/car-yellow.png index 5c35476..79f5cdc 100644 Binary files a/img/markers/car-yellow.png and b/img/markers/car-yellow.png differ diff --git a/img/markers/nyan-afro.gif b/img/markers/nyan-afro.gif deleted file mode 100644 index 62cf2d7..0000000 Binary files a/img/markers/nyan-afro.gif and /dev/null differ diff --git a/img/markers/nyan-coin.gif b/img/markers/nyan-coin.gif deleted file mode 100644 index 7bde0a2..0000000 Binary files a/img/markers/nyan-coin.gif and /dev/null differ diff --git a/img/markers/nyan-cool.gif b/img/markers/nyan-cool.gif deleted file mode 100644 index 82260e2..0000000 Binary files a/img/markers/nyan-cool.gif and /dev/null differ diff --git a/img/markers/nyan-gameboy.gif b/img/markers/nyan-gameboy.gif deleted file mode 100644 index a3389e6..0000000 Binary files a/img/markers/nyan-gameboy.gif and /dev/null differ diff --git a/img/markers/nyan-mon.gif b/img/markers/nyan-mon.gif deleted file mode 100644 index afb9806..0000000 Binary files a/img/markers/nyan-mon.gif and /dev/null differ diff --git a/img/markers/nyan-mummy.gif b/img/markers/nyan-mummy.gif deleted file mode 100644 index 6221b5f..0000000 Binary files a/img/markers/nyan-mummy.gif and /dev/null differ diff --git a/img/markers/nyan-pirate.gif b/img/markers/nyan-pirate.gif deleted file mode 100644 index 7e47916..0000000 Binary files a/img/markers/nyan-pirate.gif and /dev/null differ diff --git a/img/markers/nyan-pumpkin.gif b/img/markers/nyan-pumpkin.gif deleted file mode 100644 index 8952601..0000000 Binary files a/img/markers/nyan-pumpkin.gif and /dev/null differ diff --git a/img/markers/nyan-tothemax.gif b/img/markers/nyan-tothemax.gif deleted file mode 100644 index e978749..0000000 Binary files a/img/markers/nyan-tothemax.gif and /dev/null differ diff --git a/img/openhand.cur b/img/openhand.cur deleted file mode 100644 index cb444f9..0000000 Binary files a/img/openhand.cur and /dev/null differ diff --git a/index.html b/index.html index ef149c0..ecd0837 100644 --- a/index.html +++ b/index.html @@ -1,161 +1,68 @@ - + - habhub tracker (high altitude balloons) - + habitat mobile tracker v2.0 + - - - + + - - - - - - + + -
+ -
+
- -
-