WeatherApp

A more lovable weather app than your standard type.

by Sam Fereday

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/1.1.3/mithril.min.js"></script>
<link rel="stylesheet" href="https://erikflowers.github.io/weather-icons/css/weather-icons.css">
<div class="container">
  <div id="app-container"></div>
</div>

CSS

/*
* Skeleton V2.0.4
* Copyright 2014, Dave Gamache
* www.getskeleton.com
* Free to use under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
* 12/29/2014
*/


/* Table of contents
––––––––––––––––––––––––––––––––––––––––––––––––––
- Grid
- Base Styles
- Typography
- Links
- Buttons
- Forms
- Lists
- Code
- Tables
- Spacing
- Utilities
- Clearing
- Media Queries
*/


/* Grid
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.container {
  position: relative;
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}

.column,
.columns {
  width: 100%;
  float: left;
  box-sizing: border-box;
}


/* For devices larger than 400px */

@media (min-width: 400px) {
  .container {
    width: 85%;
    padding: 0;
  }
}


/* For devices larger than 550px */

@media (min-width: 550px) {
  .container {
    width: 80%;
  }
  .column,
  .columns {
    margin-left: 4%;
  }
  .column:first-child,
  .columns:first-child {
    margin-left: 0;
  }
  .one.column,
  .one.columns {
    width: 4.66666666667%;
  }
  .two.columns {
    width: 13.3333333333%;
  }
  .three.columns {
    width: 22%;
  }
  .four.columns {
    width: 30.6666666667%;
  }
  .five.columns {
    width: 39.3333333333%;
  }
  .six.columns {
    width: 48%;
  }
  .seven.columns {
    width: 56.6666666667%;
  }
  .eight.columns {
    width: 65.3333333333%;
  }
  .nine.columns {
    width: 74.0%;
  }
  .ten.columns {
    width: 82.6666666667%;
  }
  .eleven.columns {
    width: 91.3333333333%;
  }
  .twelve.columns {
    width: 100%;
    margin-left: 0;
  }
  .one-third.column {
    width: 30.6666666667%;
  }
  .two-thirds.column {
    width: 65.3333333333%;
  }
  .one-half.column {
    width: 48%;
  }
  /* Offsets */
  .offset-by-one.column,
  .offset-by-one.columns {
    margin-left: 8.66666666667%;
  }
  .offset-by-two.column,
  .offset-by-two.columns {
    margin-left: 17.3333333333%;
  }
  .offset-by-three.column,
  .offset-by-three.columns {
  ...

JavaScript

// For ref: https://mithril.js.org/hyperscript.html
// Weather API: https://www.apixu.com/
// Types use: https://erikflowers.github.io/weather-icons/ - This will need cleaning up, as types shouldn't have anything to do with css classes
// Data bit
const dictionary = {
  "en": {
    "currentSummary": "Summary:",
    "currentTemp": "Current Temperature:",
    "loading": "Checking The Weather...",
    "postcode": "Postcode",
    "update": "Update",
    "currentLoc": "Current Location:",
    "notfound": "Not recognized..."
  }
}

// Still loads missing, but it's start.
const types = {
  "wi-day-sunny": 1000, // Sunny
  "wi-fog": 1030,
  "wi-sprinkle": 1153, // drizzle
  "wi-rain-mix": 1183 // light rain
}

let weatherData = null,
  currentlocation = "n10";

class Helpers {

  static first(arr) {
    return arr[0] ? arr[0] : null;
  }

}

class API {

  static getLatestWeather(location) {
    return m.request({
      method: "GET",
      url: "https://api.apixu.com/v1/current.json?key=ad1aa0f4b4644911ab5104146172509&q=" + location
    });
  }

  static getCharacterMood(code) {
    let type = Object.entries(types).find(x => x[1] === code);
    return type && type.length > 0 ? type[0] : "wi wi-na";
  }

}

// App bit
let AppRoot = {
  view: () => {
    return weatherData ? m("main", [
      m("span", {
        class: "character wi " + API.getCharacterMood(weatherData.current.condition.code).toLowerCase()
      }),
      m("p", {
        class: "summary"
      }, dictionary.en.currentSummary + " " + weatherData.current.condition.text),
      m("p", {
        class: "temp"
      }, dictionary.en.currentTemp + " " + weatherData.current.feelslike_c + "c"),
      m("p", {
        class: "current-location"
      }, dictionary.en.currentLoc + " " + weatherData.location.name + ", " + weatherData.location.region + ", " + weatherData.location.country),
      m("div", {
        class: "row"
      }, [
        m("div", {
          class: "row"
        }, [
          m("input", {
  ...