From 7f2ae39f8818aafb51c80d913bbe8bab4480bb87 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Wed, 1 Jul 2015 17:59:31 -0500 Subject: [PATCH] Weather demo --- ionic/components/app/test/weather/flickr.js | 35 +++ ionic/components/app/test/weather/geo.js | 56 +++++ ionic/components/app/test/weather/index.js | 123 ++++++++++ ionic/components/app/test/weather/main.html | 18 ++ ionic/components/app/test/weather/style.css | 240 +++++++++++++++++++ ionic/components/app/test/weather/weather.js | 12 + 6 files changed, 484 insertions(+) create mode 100644 ionic/components/app/test/weather/flickr.js create mode 100644 ionic/components/app/test/weather/geo.js create mode 100644 ionic/components/app/test/weather/index.js create mode 100644 ionic/components/app/test/weather/main.html create mode 100644 ionic/components/app/test/weather/style.css create mode 100644 ionic/components/app/test/weather/weather.js diff --git a/ionic/components/app/test/weather/flickr.js b/ionic/components/app/test/weather/flickr.js new file mode 100644 index 0000000000..6cb32d9964 --- /dev/null +++ b/ionic/components/app/test/weather/flickr.js @@ -0,0 +1,35 @@ +import {Http} from 'ionic/net/http'; + +let FLICKR_API_KEY = '504fd7414f6275eb5b657ddbfba80a2c'; + +let baseUrl = 'https://api.flickr.com/services/rest/'; + +export class Flickr { + constructor() { + + /* + var flickrSearch = $resource(baseUrl, { + method: 'flickr.groups.pools.getPhotos', + group_id: '1463451@N25', + safe_search: 1, + jsoncallback: 'JSON_CALLBACK', + api_key: FLICKR_API_KEY, + format: 'json' + }, { + get: { + method: 'JSONP' + } + }); + */ + } + + static search(tags, lat, lng) { + return new Promise((resolve, reject) => { + Http.get(baseUrl + '?method=flickr.groups.pools.getPhotos&group_id=1463451@N25&safe_search=1&api_key=' + FLICKR_API_KEY + '&format=json&tags=' + tags + '&lat=' + lat + '&lng=' + lng).then((val) => { + resolve(val); + }, (err) => { + reject(httpResponse); + }) + }) + } +} diff --git a/ionic/components/app/test/weather/geo.js b/ionic/components/app/test/weather/geo.js new file mode 100644 index 0000000000..c56b15e3e8 --- /dev/null +++ b/ionic/components/app/test/weather/geo.js @@ -0,0 +1,56 @@ +export class Geo { + static reverseGeocode(lat, lng) { + return new Promise((resolve, reject) => { + + let geocoder = new google.maps.Geocoder(); + + geocoder.geocode({ + 'latLng': new google.maps.LatLng(lat, lng) + }, (results, status) => { + + if (status == google.maps.GeocoderStatus.OK) { + + console.log('Reverse', results); + + if(results.length > 1) { + var r = results[1]; + var a, types; + var parts = []; + var foundLocality = false; + var foundState = false; + + for(var i = 0; i < r.address_components.length; i++) { + a = r.address_components[i]; + types = a.types; + for(var j = 0; j < types.length; j++) { + if(!foundLocality && types[j] == 'locality') { + foundLocality = true; + parts.push(a.long_name); + } else if(!foundState && types[j] == 'administrative_area_level_1') { + foundState = true; + parts.push(a.short_name); + } + } + } + + console.log('Reverse', parts); + resolve(parts.join(', ')); + } + } else { + console.log('reverse fail', results, status); + reject(results); + } + }); + }); + } + + static getLocation() { + return new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition((position) => { + resolve(position); + }, (error) => { + reject(error); + }) + }); + } +} diff --git a/ionic/components/app/test/weather/index.js b/ionic/components/app/test/weather/index.js new file mode 100644 index 0000000000..01d0cdda66 --- /dev/null +++ b/ionic/components/app/test/weather/index.js @@ -0,0 +1,123 @@ +import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; +import {FormBuilder, Control, ControlGroup, Validators, formDirectives} from 'angular2/forms'; + +import {IonicView, Animation, Modal, NavController, NavParams, IonicComponent} from 'ionic/ionic'; + +import {Geo} from './geo'; +import {Weather} from './weather'; +import {Flickr} from './flickr'; + +console.log('Imported', Geo, Weather, Flickr); + +@Component({ + selector: 'ion-app', + appInjector: [Modal] +}) +@IonicView({ + templateUrl: 'main.html' +}) +class WeatherApp { + constructor(Modal: Modal) { + this.Modal = Modal; + + this.currentLocationString = 'Madison, WI'; + this.current = { + local_tz_short: 'CDT' + }; + + this.activeBgImageIndex = 0; + + /* + $ionicPlatform.ready(function() { + // Hide the status bar + if(window.StatusBar) { + StatusBar.hide(); + } + }); + */ + + } + + onInit() { + this.refreshData(); + } + + showSettings() { + this.Modal.show(SettingsModal).then((settingsModal) => { + this.settingsModal = settingsModal; + }); + } + + getBackgroundImage(lat, lng, locString) { + Flickr.search(locString, lat, lng).then((resp) => { + let photos = resp.photos; + if(photos.photo.length) { + this.bgImages = photos.photo; + this.cycleBgImages(); + } + }, (error) => { + console.error('Unable to get Flickr images', error); + }); + } + + getCurrent(lat, lng, locString) { + Weather.getAtLocation(lat, lng).then((resp) => { + this.current = resp.data; + console.log('GOT CURRENT', this.current); + }, (error) => { + alert('Unable to get current conditions'); + console.error(error); + }); + } + + cycleBgImages() { + setTimeout(() => { + if(this.bgImages) { + this.activeBgImage = this.bgImages[this.activeBgImageIndex++ % this.bgImages.length]; + } + }); + } + + refreshData() { + Geo.getLocation().then((position) => { + let lat = position.coords.latitude; + let lng = position.coords.longitude; + + Geo.reverseGeocode(lat, lng).then((locString) => { + this.currentLocationString = locString; + this.getBackgroundImage(lat, lng, locString); + }); + + this.getCurrent(lat, lng); + }, (error) => { + alert('Unable to get current location: ' + error); + }); + } +} + +/* +.controller('SettingsCtrl', function($scope, Settings) { + $scope.settings = Settings.getSettings(); + + // Watch deeply for settings changes, and save them + // if necessary + $scope.$watch('settings', function(v) { + Settings.save(); + }, true); + + $scope.closeSettings = function() { + $scope.modal.hide(); + }; + +}); +*/ + +@IonicComponent(Modal) +@IonicView({ + template: '' +}) +export class SettingsModal extends Modal {} + +export function main(ionicBootstrap) { + ionicBootstrap(WeatherApp); +} diff --git a/ionic/components/app/test/weather/main.html b/ionic/components/app/test/weather/main.html new file mode 100644 index 0000000000..615b07d5b2 --- /dev/null +++ b/ionic/components/app/test/weather/main.html @@ -0,0 +1,18 @@ + + + + + + {{currentLocationString}}
+ +
+ +
+ + +
+ + +
+
+
diff --git a/ionic/components/app/test/weather/style.css b/ionic/components/app/test/weather/style.css new file mode 100644 index 0000000000..40bf576d32 --- /dev/null +++ b/ionic/components/app/test/weather/style.css @@ -0,0 +1,240 @@ +body { + text-shadow: 1px 1px 0px rgba(0,0,0,0.5); + background-color: black; +} +#wrapper { + background-color: black; +} +#scroller { +} +.bg-image { + position: fixed; + width: 120%; + height: 120%; + background-size: cover; +} + +.bg-fade > .ng-enter { + opacity: 0; + -webkit-transition: opacity 2s ease-in-out; +} +.bg-fade > .ng-enter-active { + opacity: 1; +} +.bg-fade > .ng-leave { + opacity: 1; + -webkit-transition: opacity 2s ease-in-out; +} +.bg-fade > .ng-leave-active { + opacity: 0; +} + +.wunderground-logo { + width: 100px; + height: 14px; + background: url('../img/wunderground.png') no-repeat transparent; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 2) { + .wunderground-logo { + background: url('../img/wunderground@2x.png') no-repeat transparent; + background-size: 100px 14px; + } +} + +h1,h2,h3,h4,h5 { + color: #fff; + font-weight: 300; +} + +#main-content { + color: #fff; + padding: 10px; +} + +.ion-ios7-sunny-outline { + color: yellow; +} + +.ionic-refresher-content { + color: rgb(255,255,255) !important; + text-shadow: none; +} + +/** + * Header + */ +#header { + background-color: transparent !important; + height: 44px; +} +#header > * { + margin-top: 0; +} +#header .title { + font-size: 12px; + line-height: 20px; + margin-top: 4px; +} +#header .title .city { + font-size: 16px; +} + +#city-nav-icon { + font-size: 11px; + margin-right: 2px; +} + +.scroll-refresher { + overflow: visible; +} +.ionic-refresher-content { + background-color: rgba(0,0,0,0.4); + height: 400px; + bottom: 0; +} +.ionic-refresher-content i { + margin-top: 360px; +} +/** + * Current weather + */ + +#current-weather { + height: 180px; + box-sizing: content-box; +} +#current-weather > * { + color: #fff; +} +#current-weather .current-temp { + font-size: 100px; + font-weight: 100; + margin: 0; + padding: 0; + line-height: 80px; +} + + +#current-icon { + font-size: 42px; + vertical-align: middle; + margin-right: 5px; +} + +#temp-hi, #temp-lo { display: inline-block; } +#temp-lo { + margin-left: 10px; +} + +/** + * Forecast and details + */ +.weather-box { + background-color: rgba(0,0,0,0.2); + padding: 9px; + margin: 10px 0px; + color: rgba(255,255,255,0.9); +} + +.weather-box .title { + color: rgba(255,255,255,0.9); + font-weight: normal; + margin: 0; + padding-bottom: 5px; + border-bottom: 1px solid #fff; +} + + +.weather-box .row { + border-bottom: 1px dotted rgba(255,255,255,0.3); + margin: 0; + padding: 0; +} +.weather-box .col { + text-align: center; +} +.weather-box .col:first-child { + text-align: left; +} +.weather-box .col:last-child { + text-align: right; +} + +.weather-box span { + vertical-align: middle; +} + +.weather-box .icon { + font-size: 42px; + line-height: 24px; + vertical-align: middle; +} + +.temp-high { + display: inline-block; + width: 30px; + text-align: right; +} +.temp-low { + display: inline-block; + width: 30px; + text-align: right; + color: #4a87ee; +} + + +.no-header { + top: 0 !important; +} + +#forecast-scroll { + margin: 10px 0px; +} +#hourly-forecast { + width: 2250px; + height: 70px; +} +.hourly-hour { + display: inline-block; + margin-right: 10px; + text-align: center; +} + +#forecast .credit { + float: right; + margin-top: 4px; + margin-right: 4px; +} +#forecast .credit a { + color: #fff; +} + +/** + * Settings modal + */ + +#settings-modal { + background-color: rgba(0,0,0,0.8); +} + +#settings-modal .item { + background-color: rgba(0,0,0,0.9); + border: none; + color: #fff; +} +#settings-modal .input-label { + color: #fff; +} + + +ion-view { + background-color: black !important; +} +ion-content { + background-color: black !important; +} +#header { + background: transparent; + color: #fff; +} diff --git a/ionic/components/app/test/weather/weather.js b/ionic/components/app/test/weather/weather.js new file mode 100644 index 0000000000..0cefbe41c7 --- /dev/null +++ b/ionic/components/app/test/weather/weather.js @@ -0,0 +1,12 @@ +import {Http} from 'ionic/net/http'; + +let WUNDERGROUND_API_KEY = '1cc2d3de40fa5af0'; + +let FORECASTIO_KEY = '4cd3c5673825a361eb5ce108103ee84a'; + +export class Weather { + static getAtLocation(lat, lng) { + let url = 'https://api.forecast.io/forecast/' + FORECASTIO_KEY + '/'; + return Http.get(url + lat + ',' + lng); + } +}