aleksoft1
1/12/2014 - 5:19 PM

app.js

<!doctype html>
<html data-ng-app="myApp" data-ng-csp="">
<head>
  <meta charset="UTF-8">
  <title>Presently</title>
  <link rel="stylesheet" href="css/bootstrap.min.css">
  <link rel="stylesheet" href="css/main.css">
</head>
<body>
  
  <div class="container">
    <div data-ng-view></div>
    <div id="actionbar">
      <ul class="list-inline">
        <li><a class="glyphicon glyphicon-home" href="#/"></a></li>
        <li><a class="glyphicon glyphicon-list" href="#/settings"></a></li>
      </ul>
    </div>
  </div>
  
  <script src="./js/vendor/angular.min.js"></script>
  <script src="./js/vendor/angular-route.min.js"></script>
  <script src="./js/app.js"></script>
</body>
</html>
<h2>Settings</h2>

<form ng-submit="save()">
  <input type="text"
          ng-model="user.location"
          timezone="user.timezone"
          auto-fill="fetchCities"
          autocomplete="off"
          placeholder="Location" />
  <input class="btn btn-primary" 
        type="submit" value="Save" />
</form>
{
  "manifest_version": 2,
  "name": "Presently",
  "description": "A currently clone",
  "version": "0.1",
  "permissions": [
    "http://api.wunderground.com/api/"
  ],
  "background": {
    "scripts": ["js/vendor/angular.min.js"]
  },
  "content_security_policy": "script-src 'self'; object-src 'self'",
  "chrome_url_overrides" : {
    "newtab": "tab.html"
  }
}
/* Include this file in your html if you are using the CSP mode. */

@charset "UTF-8";

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
  display: none !important;
}

ng\:form {
  display: block;
}

body {
  background-color: #eee;
  font-family: 'Actor', sans-serif;
  color: #444;
}

#datetime {
  text-align: center;
}

#datetime h1 {
  font-size: 6.1em;
}

#datetime h2 {
  font-size: 1.0em;
}

@font-face {
  font-family: 'Actor';
  src: url('chrome-extension://__MSG_@@extension_id__/fonts/DroidSansMono.ttf');
}

#forecast ul li {
  font-size: 4.5em;
  text-align: center;
}

#forecast ul li img {
}

#forecast ul li h3 {
  font-size: 1.5em;
}

#actionbar {
  position: absolute;
  bottom: 0.5em;
  right: 1.0em;
}

#actionbar a {
  font-size: 2.2rem;
  color: #000;
}

.typeahead ul {
  max-height: 150px;
  border: 1px solid #333;
  padding: 3px;
  overflow: auto;
}
<div>
  <div id="datetime">
    <h1>{{ date.tz | date:'hh mm ss' }}</h1>
    <h2>{{ date.tz | date:'EEEE, MMMM yyyy' }}</h2>
  </div>

  <div id="forecast">
    <ul class="row list-unstyled">
      <li ng-repeat="day in weather.forecast.forecastday" class="col-md-3">
        <span ng-class="{today: $index == 0}">
          <img class="{{ day.icon }}" ng-src="{{ day.icon_url }}" />
          <h3>{{ day.high.fahrenheit }}</h3>
          <h4 ng-if="$index == 0">Now</h4>
          <h4 ng-if="$index != 0">{{ day.date.weekday }}</h4>
        </span>
      </li>
    </ul>
  </div>
</div>
angular.module('myApp', ['ngRoute'])
.provider('Weather', function() {
  var apiKey = "";

  this.getUrl = function(type, ext) {
    return "http://api.wunderground.com/api/" + 
      this.apiKey + "/" + type + "/q/" +
      ext + '.json';
  };

  this.setApiKey = function(key) {
    if (key) this.apiKey = key;
  };

  this.$get = function($q, $http) {
    var self = this;
    return {
      getWeatherForecast: function(city) {
        var d = $q.defer();
        $http({
          method: 'GET',
          url: self.getUrl("forecast", city),
          cache: true
        }).success(function(data) {
          d.resolve(data.forecast.simpleforecast);
        }).error(function(err) {
          d.reject(err);
        });
        return d.promise;
      },
      getCityDetails: function(query) {
        var d = $q.defer();
        $http({
          method: 'GET',
          url: "http://autocomplete.wunderground.com/aq?query=" +
                query
        }).success(function(data) {
          d.resolve(data.RESULTS);
        }).error(function(err) {
          d.reject(err);
        });
        return d.promise;
      }
    }
  }
})
.factory('UserService', function() {
  var defaults = {
    location: 'autoip'
  };

  var service = {
    user: {},
    save: function() {
      sessionStorage.presently =
        angular.toJson(service.user);
    },
    restore: function() {
      service.user = 
        angular.fromJson(sessionStorage.presently) || defaults

      return service.user;
    }
  };
  service.restore();
  return service;
})
.config(function(WeatherProvider) {
  WeatherProvider.setApiKey('REPLACE_WITH_YOUR_KEY');
})
.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/', {
      templateUrl: 'templates/home.html', 
      controller: 'MainCtrl'
    })
    .when('/settings', {
      templateUrl: 'templates/settings.html',
      controller: 'SettingsCtrl'
    })
    .otherwise({redirectTo: '/'});
}])
.directive('autoFill', function($timeout, Weather) {
  return {
    restrict: 'EA',
    scope: {
      autoFill: '&',
      ngModel: '=',
      timezone: '='
    },
    compile: function(tEle, tAttrs) {
      var tplEl = angular.element('<div class="typeahead">' +
      '<input type="text" autocomplete="off" />' +
      '<ul id="autolist" ng-show="reslist">' +
        '<li ng-repeat="res in reslist" ' +
          '>{{res.name}}</li>' +
      '</ul>' +
      '</div>');
      var input = tplEl.find('input');
      input.attr('type', tAttrs.type);
      input.attr('ng-model', tAttrs.ngModel);
      input.attr('timezone', tAttrs.timezone);
      tEle.replaceWith(tplEl);
      return function(scope, ele, attrs, ctrl) {
        var minKeyCount = attrs.minKeyCount || 3,
            timer;

        ele.bind('keyup', function(e) {
          val = ele.val();
          if (val.length < minKeyCount) {
            if (timer) $timeout.cancel(timer);
            scope.reslist = null;
            return;
          } else {
            if (timer) $timeout.cancel(timer);
            timer = $timeout(function() {
              scope.autoFill()(val)
              .then(function(data) {
                if (data && data.length > 0) {
                  scope.reslist = data;
                  scope.ngModel = data[0].zmw;
                  scope.timezone = data[0].tz;
                }
              });
            }, 300);
          }
        });

        // Hide the reslist on blur
        input.bind('blur', function(e) {
          scope.reslist = null;
          scope.$digest();
        });
      }
    }
  }
})
.controller('MainCtrl', 
  function($scope, $timeout, Weather, UserService) {
    $scope.date = {};

    var updateTime = function() {
      $scope.date.tz = new Date(new Date()
        .toLocaleString("en-US", {timeZone: $scope.user.timezone}));
      $timeout(updateTime, 1000);
    }

    $scope.weather = {}
    $scope.user = UserService.user;
    Weather.getWeatherForecast($scope.user.location)
    .then(function(data) {
      $scope.weather.forecast = data;
    });
    updateTime();
})
.controller('SettingsCtrl', 
  function($scope, $location, Weather, UserService) {
    $scope.user = UserService.user;

    $scope.save = function() {
      UserService.save();
      $location.path('/');
    }
    $scope.fetchCities = Weather.getCityDetails;
});