You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@climate.apache.org by jo...@apache.org on 2014/01/28 23:18:20 UTC
svn commit: r1562255 [3/19] - in /incubator/climate/trunk/ocw-ui: ./
frontend/ frontend/app/ frontend/app/css/ frontend/app/css/lib/
frontend/app/font/ frontend/app/img/ frontend/app/js/
frontend/app/js/controllers/ frontend/app/js/directives/ frontend...
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.svg
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.ttf
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.ttf?rev=1562255&view=auto
==============================================================================
Files incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.ttf (added) and incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.ttf Tue Jan 28 22:18:16 2014 differ
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.ttf
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.woff
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.woff?rev=1562255&view=auto
==============================================================================
Files incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.woff (added) and incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.woff Tue Jan 28 22:18:16 2014 differ
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/font/fontawesome-webfont.woff
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/img/globe.png
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/img/globe.png?rev=1562255&view=auto
==============================================================================
Files incubator/climate/trunk/ocw-ui/frontend/app/img/globe.png (added) and incubator/climate/trunk/ocw-ui/frontend/app/img/globe.png Tue Jan 28 22:18:16 2014 differ
Added: incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings-white.png
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings-white.png?rev=1562255&view=auto
==============================================================================
Files incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings-white.png (added) and incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings-white.png Tue Jan 28 22:18:16 2014 differ
Added: incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings.png
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings.png?rev=1562255&view=auto
==============================================================================
Files incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings.png (added) and incubator/climate/trunk/ocw-ui/frontend/app/img/glyphicons-halflings.png Tue Jan 28 22:18:16 2014 differ
Added: incubator/climate/trunk/ocw-ui/frontend/app/index.html
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/index.html?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/index.html (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/index.html Tue Jan 28 22:18:16 2014
@@ -0,0 +1,125 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<!doctype html>
+<html lang="en" ng-app="ocw">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>OCW UI</title>
+ <link rel="stylesheet" href="css/lib/bootstrap.min.css"/>
+ <link rel="stylesheet" href="css/lib/bootstrap-responsive.min.css"/>
+ <link rel="stylesheet" href="css/lib/font-awesome.min.css"/>
+ <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />
+ <link rel="stylesheet" href="css/lib/timeline.css"/>
+ <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/ui-lightness/jquery-ui.min.css" type="text/css"/>
+ <!--[if lte IE 8]>
+ <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
+ <![endif]-->
+ <link rel="stylesheet" href="css/app.css"/>
+</head>
+<body ng-cloak>
+
+<div class="container">
+ <div class="row-fluid">
+ <div class="span12">
+ <!-- Title -->
+ <div class="row-fluid">
+ <div class="span12">
+ <br><br>
+ <div id="header">
+ <img id="header-img" src=""/>
+ <h3 id="header-title">Project Name</h3>
+ <h5 id="OCW-powered">Powered by Apache Open Climate Workbench</h5>
+ </div>
+ </div>
+ </div>
+ <!-- Navigation bar -->
+ <div class="row-fluid">
+ <div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="brand" href="#">OCW UI</a>
+ <ul class="nav">
+ <li ng-class="{ active: $state.includes('main') }"><a href="#">Evaluate</a></li>
+ <li ng-class="{ active: $state.includes('results') }"><a href="#/results">Results</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- Main Content -->
+ <div id="main-container" class="container" ui-view ng-animate="{enter:'fade-enter'}"></div>
+</div>
+
+ <!--Libraries-->
+ <script src="js/lib/jquery/jquery-1.10.1.js"></script>
+ <script src="js/lib/jquery/jquery-ui/jquery-ui-1.10.3.min.js"></script>
+ <script src="js/lib/angular/angular.min.js"></script>
+ <script src="js/lib/angular-ui/angular-ui-0.4-tpls.js"></script>
+ <script src="js/lib/jquery/jquery-ui/datepicker-wrapper/date.js"></script>
+ <script src="js/lib/bootstrap/bootstrap.js"></script>
+ <script src="js/lib/leaflet/leaflet-0.5.js"></script>
+ <script src="http://www.google.com/jsapi"></script>
+ <script src="js/lib/timeline/timeline.js"></script>
+ <script src="js/lib/angular-ui/angular-ui-router.min.js"></script>
+ <script src="js/lib/angular-ui/ui-bootstrap-tpls-0.5.0.min.js"></script>
+ <!--Timeline refuses to initialize nicely so we're doing this as a workaround-->
+ <script type="text/javascript">google.load("visualization", "1");</script>
+
+ <!--General-->
+ <script src="js/app.js"></script>
+
+ <!--Services-->
+ <script src="js/services/SelectedDatasetInformation.js"></script>
+ <script src="js/services/RegionSelectParams.js"></script>
+ <script src="js/services/EvaluationSettings.js"></script>
+
+ <!--Controllers-->
+ <script src="js/controllers/WorldMapCtrl.js"></script>
+ <script src="js/controllers/ParameterSelectCtrl.js"></script>
+ <script src="js/controllers/DatasetDisplayCtrl.js"></script>
+ <script src="js/controllers/ObservationSelectCtrl.js"></script>
+ <script src="js/controllers/RcmedSelectionCtrl.js"></script>
+ <script src="js/controllers/SettingsCtrl.js"></script>
+ <script src="js/controllers/TimelineCtrl.js"></script>
+ <script src="js/controllers/DatasetSelectCtrl.js"></script>
+ <script src="js/controllers/ResultCtrl.js"></script>
+ <script src="js/controllers/ResultDetailCtrl.js"></script>
+
+ <!--Directives-->
+ <script src="js/directives/LeafletMap.js"></script>
+ <script src="js/directives/PreviewMap.js"></script>
+ <script src="js/directives/BootstrapModal.js"></script>
+ <script src="js/directives/BootstrapModalOpen.js"></script>
+ <script src="js/directives/PredictiveFileBrowserInput.js"></script>
+ <script src="js/directives/OnBlur.js"></script>
+ <script src="js/directives/Timeline.js"></script>
+
+ <!--Filters-->
+ <script src="js/filters/ISODateToMiddleEndian.js"></script>
+</body>
+<footer class="container well well-small" style="margin-top: 40px">
+ <div class="span4 offset1">
+ <h6>Powered by Apache Open Climate Workbench</h6>
+ </div>
+</footer>
+</html>
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/index.html
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/app.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/app.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/app.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/app.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+'use strict';
+
+// We're creating a "global" application object. This allows us to keep module
+// names isolated to a single location as well as simplifying future init code.
+var App = App || {};
+
+App.Services = angular.module('ocw.services', []);
+App.Directives = angular.module('ocw.directives', []);
+App.Controllers = angular.module('ocw.controllers', []);
+App.Filters = angular.module('ocw.filters', []);
+
+angular.module('ocw', ['ocw.services', 'ocw.directives', 'ocw.controllers', 'ocw.filters', 'ui.date', 'ui.bootstrap', 'ui.compat', 'ui.state'])
+.config(
+ [ '$stateProvider', '$routeProvider', '$urlRouterProvider',
+ function ($stateProvider, $routeProvider, $urlRouterProvider) {
+ $urlRouterProvider
+ .when('/r?id', '/results/:id')
+ .otherwise('/');
+
+ $routeProvider
+ .when('/evaluation/:id', {
+ redirectTo: '/results/:id',
+ })
+ .when('/', {
+ redirectTo: '/evaluate',
+ });
+
+ $stateProvider
+ .state('main',{
+ url: '/evaluate',
+ templateUrl: 'partials/main.html',
+ })
+ .state('results', {
+ url: '/results',
+ abstract: true,
+ templateUrl: 'partials/results.html',
+ controller: 'ResultCtrl'
+ })
+ .state('results.list', {
+ // parent: 'results',
+ url: '',
+ templateUrl: 'partials/results.list.html',
+ })
+ .state('results.detail', {
+ // parent: 'results',
+ url: '/{resultId}',
+ views: {
+ '': {
+ templateUrl: 'partials/results.detail.html',
+ controller: 'ResultDetailCtrl'
+ },
+ 'menu': {
+ templateProvider:
+ [ '$stateParams',
+ function ($stateParams){
+ return '<hr><small class="muted">result ID: ' + $stateParams.resultId + '</small>';
+ }],
+ },
+ },
+ });
+ }])
+.run(
+ [ '$rootScope', '$state', '$stateParams',
+ function ($rootScope, $state, $stateParams) {
+ $rootScope.$state = $state;
+ $rootScope.$stateParams = $stateParams;
+ $rootScope.evalResults = "";
+ $rootScope.fillColors = ['#ff0000', '#00c90d', '#cd0074', '#f3fd00'];
+ $rootScope.surroundColors = ['#a60000', '#008209', '#8f004b', '#93a400']
+ $rootScope.baseURL = 'http://localhost:8082';
+}]);
+
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/js/app.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetDisplayCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetDisplayCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetDisplayCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetDisplayCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for dataset display
+App.Controllers.controller('DatasetDisplayCtrl', ['$rootScope', '$scope', 'selectedDatasetInformation',
+function($rootScope, $scope, selectedDatasetInformation) {
+ $scope.datasets = selectedDatasetInformation.getDatasets();
+
+ $scope.removeDataset = function($index) {
+ selectedDatasetInformation.removeDataset($index);
+ }
+
+ $scope.setRegridBase = function(index) {
+ for (var i = 0; i < $scope.datasets.length; i++) {
+ $scope.datasets[i].regrid = ((i == index) ? $scope.datasets[i].regrid : false);
+ }
+ }
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetSelectCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetSelectCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetSelectCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/DatasetSelectCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for dataset selection/modification
+App.Controllers.controller('DatasetSelectCtrl', ['$scope', 'selectedDatasetInformation',
+function($scope, selectedDatasetInformation) {
+
+ // Grab a copy of the datasets so we can display a count to the user!
+ $scope.datasetCount = selectedDatasetInformation.getDatasets();
+
+ $scope.shouldDisableClearButton = function() {
+ return (selectedDatasetInformation.getDatasetCount() == 0);
+ }
+
+ $scope.clearDatasets = function() {
+ selectedDatasetInformation.clearDatasets();
+ }
+
+ $scope.open = function () {
+ $scope.datasetSelect = true;
+ }
+
+ $scope.close = function () {
+ $scope.datasetSelect = false;
+ }
+
+ $scope.opts = {
+ backdropFade: true,
+ dialogFade:true
+ };
+
+ $scope.templates =
+ [ { title:'Local File', url: 'partials/selectObservation.html'}
+ , { title:'RCMED', url: 'partials/selectRcmed.html'}
+ , { title:'ESG', disabled: true } ];
+
+ $scope.template = $scope.templates[0];
+
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ObservationSelectCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ObservationSelectCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ObservationSelectCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ObservationSelectCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for observation selection in modal
+App.Controllers.controller('ObservationSelectCtrl', ['$rootScope', '$scope', '$http', '$q', '$timeout', 'selectedDatasetInformation',
+function($rootScope, $scope, $http, $q, $timeout, selectedDatasetInformation) {
+ // Grab a copy of the datasets so we can display a count to the user!
+ $scope.datasetCount = selectedDatasetInformation.getDatasets();
+
+ // Initalize the option arrays and default to the first element
+ $scope.params = ["Please select a file above"];
+ $scope.paramSelect = $scope.params[0];
+ $scope.lats = ["Please select a file above"];
+ $scope.latsSelect = $scope.lats[0];
+ $scope.lons = ["Please select a file above"];
+ $scope.lonsSelect = $scope.lons[0];
+ $scope.times = ["Please select a file above"];
+ $scope.timeSelect = $scope.times[0];
+
+ // Grab the path leader information that the webserver is using to limit directory access.
+ $scope.pathLeader = 'False';
+ $http.jsonp($rootScope.baseURL + '/getPathLeader/?callback=JSON_CALLBACK').
+ success(function(data) {
+ $scope.pathLeader = data.leader;
+ });
+
+ // Toggle load button view depending on upload state of selected files
+ $scope.loadingFile = false;
+
+ // Toggle display of a confirmation when loading a dataset
+ $scope.fileAdded = false;
+
+ $scope.latLonVals = [];
+ $scope.timeVals = [];
+ $scope.localSelectForm = {};
+
+ $scope.uploadLocalFile = function() {
+ $scope.loadingFile = true;
+
+ // TODO: Need to try to validate the input a bit. At least make sure we're not
+ // pointing at a directory perhaps?
+
+ // TODO: Two-way binding with ng-model isn't being used here because it fails to update
+ // properly with the auto-complete that we're using on the input box. So we're doing
+ // it the wrong way temporarily...
+ var input = $('#observationFileInput').val();
+
+ // If the backend is limiting directory access we need to add that leader to our path
+ // so it remains valid!
+ if ($scope.pathLeader != 'False') {
+ input = $scope.pathLeader + input
+ }
+
+ // TODO: We're not really handling the case where there is a failure here at all.
+ // Should check for fails and allow the user to make changes.
+ //
+ // Get model variables
+ var varsPromise = $http.jsonp($rootScope.baseURL + '/list/vars/"' + input + '"?callback=JSON_CALLBACK');
+ // Get Lat and Lon variables
+ var latlonPromise = $http.jsonp($rootScope.baseURL + '/list/latlon/"' + input + '"?callback=JSON_CALLBACK');
+ // Get Time variables
+ var timesPromise = $http.jsonp($rootScope.baseURL + '/list/time/"' + input + '"?callback=JSON_CALLBACK');
+
+ $q.all([varsPromise, latlonPromise, timesPromise]).then(
+ // Handle success fetches!
+ function(arrayOfResults) {
+ $scope.loadingFile = false;
+
+ // Handle lat/lon results
+ var data = arrayOfResults[1].data;
+ $scope.lats = [data.latname];
+ $scope.lons = [data.lonname];
+ $scope.latLonVals = [data.latMin, data.latMax, data.lonMin, data.lonMax];
+
+ // If there is more than one option for the user, tell them they need to pick one!
+ if ($scope.lats.length > 1) $scope.lats.splice(0, 0, "Please select an option");
+ if ($scope.lons.length > 1) $scope.lons.splice(0, 0, "Please select an option");
+ // Default the display to the first available option.
+ $scope.latsSelect = $scope.lats[0];
+ $scope.lonsSelect = $scope.lons[0];
+
+ // Handle time results
+ var data = arrayOfResults[2].data
+ $scope.times = [data.timename];
+ $scope.timeVals = [data.start_time, data.end_time];
+
+ if ($scope.times.length > 1) $scope.times.splice(0, 0, "Please select an option");
+ $scope.timeSelect = $scope.times[0];
+
+ // Handle parameter results
+ var data = arrayOfResults[0].data.variables;
+ $scope.params = (data instanceof Array) ? data : [data];
+ $scope.params = $.grep($scope.params,
+ function(val) {
+ return ($.inArray(val, $scope.lats) != 0 &&
+ $.inArray(val, $scope.lons) != 0 &&
+ $.inArray(val, $scope.times) != 0);
+ });
+
+ if ($scope.params.length > 1) $scope.params.splice(0, 0, "Please select an option");
+ $scope.paramSelect = $scope.params[0];
+ },
+ // Uh oh! AT LEAST on of our fetches failed
+ function(arrayOfFailure) {
+ $scope.loadingFile = false;
+
+ $scope.params = ["Unable to load variable(s)"];
+ $scope.paramSelect = $scope.params[0];
+ $scope.lats = ["Unable to load variable(s)"];
+ $scope.latsSelect = $scope.lats[0];
+ $scope.lons = ["Unable to load variable(s)"];
+ $scope.lonsSelect = $scope.lons[0];
+ $scope.times = ["Unable to load variable(s)"];
+ $scope.timeSelect = $scope.times[0];
+ }
+ );
+ };
+
+ $scope.addDataSet = function() {
+ // TODO: Need to verify that all the variables selected are correct!!!
+ // TODO: We shouldn't allow different parameters to match the same variables!!
+
+ var newDataset = {};
+ var input = $('#observationFileInput').val();
+
+ // If the backend is limiting directory access we need to add that leader to our path
+ // so it remains valid!
+ if ($scope.pathLeader != 'False') {
+ input = $scope.pathLeader + input
+ }
+
+ newDataset['isObs'] = 0;
+ // Save the model path. Note that the path is effectively the "id" for the model.
+ newDataset['id'] = input;
+ // Grab the file name later for display purposes.
+ var splitFilePath = input.split('/');
+ newDataset['name'] = splitFilePath[splitFilePath.length - 1];
+ // Save the model parameter variable. We save it twice for consistency and display convenience.
+ newDataset['param'] = $scope.paramSelect;
+ newDataset['paramName'] = newDataset['param'];
+ // Save the lat/lon information
+ newDataset['lat'] = $scope.latsSelect;
+ newDataset['lon'] = $scope.lonsSelect;
+
+ newDataset['latlonVals'] = {"latMin": $scope.latLonVals[0], "latMax": $scope.latLonVals[1],
+ "lonMin": $scope.latLonVals[2], "lonMax": $scope.latLonVals[3]};
+ // Get the time information
+ newDataset['time'] = $scope.timeSelect;
+ newDataset['timeVals'] = {"start": $scope.timeVals[0], "end": $scope.timeVals[1]};
+
+ selectedDatasetInformation.addDataset(newDataset);
+
+ // Reset all the fields!!
+ $scope.params = ["Please select a file above"];
+ $scope.paramSelect = $scope.params[0];
+ $scope.lats = ["Please select a file above"];
+ $scope.latsSelect = $scope.lats[0];
+ $scope.lons = ["Please select a file above"];
+ $scope.lonsSelect = $scope.lons[0];
+ $scope.times = ["Please select a file above"];
+ $scope.timeSelect = $scope.times[0];
+ $scope.latLonVals = [];
+ $scope.timeVals = [];
+
+ // Clear the input box
+ $('#observationFileInput').val("");
+
+ // Display a confirmation message for a little bit
+ $scope.fileAdded = true;
+ $timeout(function() {
+ $scope.fileAdded = false;
+ }, 2000);
+ }
+
+ $scope.shouldDisableLoadButton = function() {
+ return $scope.loadingFile;
+ }
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ParameterSelectCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ParameterSelectCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ParameterSelectCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ParameterSelectCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for dataset parameter selection/modification
+App.Controllers.controller('ParameterSelectCtrl', ['$rootScope', '$scope', '$http', '$timeout',
+ 'selectedDatasetInformation', 'regionSelectParams', 'evaluationSettings',
+function($rootScope, $scope, $http, $timeout, selectedDatasetInformation, regionSelectParams, evaluationSettings) {
+ $scope.datasets = selectedDatasetInformation.getDatasets();
+
+ // The min/max lat/lon values from the selected datasets
+ $scope.latMin = -90;
+ $scope.latMax = 90;
+ $scope.lonMin = -180;
+ $scope.lonMax = 180;
+ $scope.start = "1980-01-01 00:00:00";
+ $scope.end = "2030-01-01 00:00:00";
+
+ // The min/max lat/lon values that are displayed
+ $scope.displayParams = regionSelectParams.getParameters();
+
+ $scope.runningEval = false;
+
+ // Flag for toggling re-grid controls based on whether or not the user has selected a grid
+ // base from the selected datasets. By default we have no datasets so we don't need to show
+ // the controls!
+ $scope.areInUserRegridState = false;
+
+ // Initialization for the lat/lon grid step sliders
+ // TODO There has to be a better way of dealing with this. Perhaps a directive??
+ $scope.latSliderVal = 0;
+ $scope.lonSliderVal = 0;
+
+ $('#latSlider').slider({
+ value: 0,
+ step: 0.25,
+ min: 0.25,
+ max: 180,
+ slide: function(event, ui) {
+ $scope.updateLatSliderDisplayValue(ui.value);
+ },
+ });
+
+ $('#lonSlider').slider({
+ value: 0,
+ step: 0.25,
+ min: 0.25,
+ max: 360,
+ slide: function(event, ui) {
+ $scope.updateLonSliderDisplayValue(ui.value);
+ },
+ });
+
+ $scope.updateLatSliderDisplayValue = function(value) {
+ $scope.latSliderVal = value;
+ $scope.$apply();
+ };
+
+ $scope.updateLonSliderDisplayValue = function(value) {
+ $scope.lonSliderVal = value;
+ $scope.$apply();
+ };
+
+ // Settings for jQuery datepicker directives!
+ $scope.datepickerSettings = {
+ changeMonth: true,
+ changeYear: true,
+ };
+
+ $scope.shouldDisableControls = function() {
+ return (selectedDatasetInformation.getDatasetCount() < 2);
+ }
+
+ $scope.shouldDisableEvaluateButton = function() {
+ return ($scope.shouldDisableControls() || $scope.runningEval);
+ }
+
+ $scope.shouldDisableResultsView = function() {
+ var res = false;
+
+ if ($rootScope.evalResults == "")
+ res = true;
+
+ return res;
+ }
+
+ $scope.runEvaluation = function() {
+ $scope.runningEval = true;
+
+ // Containers for dataset information
+ var obsDatasetIds = [],
+ obsDatasetParameterIds = [],
+ modelDatasetIds = [],
+ modelDatasetParameterIds = [],
+ modelDatasetTimes = [],
+ modelDatasetLats = [],
+ modelDatasetLons = [];
+
+ // Populate containers with information for each selected dataset
+ for (var i = 0; i < $scope.datasets.length; i++) {
+ console.log($scope.datasets[i].id)
+ if ($scope.datasets[i]['isObs'] == 1) {
+ obsDatasetIds.push($scope.datasets[i].datasetId)
+ obsDatasetParameterIds.push($scope.datasets[i].id)
+ } else {
+ modelDatasetIds.push($scope.datasets[i].id)
+ modelDatasetParameterIds.push($scope.datasets[i].param)
+ modelDatasetTimes.push($scope.datasets[i].time)
+ modelDatasetLats.push($scope.datasets[i].lat)
+ modelDatasetLons.push($scope.datasets[i].lon)
+ }
+ }
+
+ // TODO At the moment we aren't running all the metrics that the user selected. We're only
+ // running the first available metric that the user provides. If the user un-checks all
+ // metrics then the default of 'bias' is used.
+ var metricToRun = 'bias';
+ var settings = evaluationSettings.getSettings().metrics;
+ for (var i = 0; i < settings.length; i++) {
+ var setting = settings[i];
+
+ if (setting.select) {
+ metricToRun = setting.name;
+ break;
+ }
+ };
+
+ // Prepare information to send to backend service
+ var data = {params: {
+ 'obsDatasetIds' : obsDatasetIds,
+ 'obsParameterIds' : obsDatasetParameterIds,
+
+ 'startTime' : $scope.displayParams.start + " 00:00:00",
+ 'endTime' : $scope.displayParams.end + " 00:00:00",
+ 'latMin' : $scope.displayParams.latMin,
+ 'latMax' : $scope.displayParams.latMax,
+ 'lonMin' : $scope.displayParams.lonMin,
+ 'lonMax' : $scope.displayParams.lonMax,
+
+ 'filelist' : modelDatasetIds,
+ 'modelVarName' : modelDatasetParameterIds,
+ 'modelTimeVarName' : modelDatasetTimes,
+ 'modelLatVarName' : modelDatasetLats,
+ 'modelLonVarName' : modelDatasetLons,
+
+ 'regridOption' : ((evaluationSettings.getSettings().spatialSelect.isObs) ? 'obs' : 'model'),
+ 'regridBasis' : evaluationSettings.getSettings().spatialSelect.id,
+ 'timeRegridOption' : evaluationSettings.getSettings().temporal.selected,
+ 'metricOption' : metricToRun, // Should be a list of metrics to run
+ 'subregionFile' : evaluationSettings.getSettings().subregionFile,
+ 'callback' : 'JSON_CALLBACK',
+ }};
+
+ $http.jsonp($rootScope.baseURL + '/rcmes/run/', data).
+ success(function(data) {
+ var evalWorkDir = data['evalWorkDir'];
+
+ $scope.runningEval = false;
+
+ $timeout(function() {
+ if (evalWorkDir !== undefined) {
+ window.location = "#/results/"+evalWorkDir;
+ } else {
+ window.location = "#/results";
+ }
+ }, 100);
+
+ }).error(function() {
+ $scope.runningEval = false;
+ });
+ };
+
+ // Check the Parameter selection boxes after the user has changed input to ensure that valid
+ // values were entered
+ $scope.checkParameters = function() {
+ if (parseFloat($scope.displayParams.latMin) < parseFloat($scope.latMin))
+ $scope.displayParams.latMin = $scope.latMin;
+
+ if (parseFloat($scope.displayParams.latMax) > parseFloat($scope.latMax))
+ $scope.displayParams.latMax = $scope.latMax;
+
+ if (parseFloat($scope.displayParams.lonMin) < parseFloat($scope.lonMin))
+ $scope.displayParams.lonMin = $scope.lonMin;
+
+ if (parseFloat($scope.displayParams.lonMax) > parseFloat($scope.lonMax))
+ $scope.displayParams.lonMax = $scope.lonMax;
+
+ if ($scope.displayParams.start < $scope.start)
+ $scope.displayParams.start = $scope.start;
+
+ if ($scope.displayParams.end > $scope.end)
+ $scope.displayParams.end = $scope.end;
+
+ $scope.$apply();
+ $rootScope.$broadcast('redrawOverlays', []);
+ }
+
+ $scope.unwatchDatasets = $scope.$watch('datasets',
+ function() {
+ var numDatasets = $scope.datasets.length;
+ $scope.displayParams.areValid = false;
+ $scope.areInUserRegridState = false;
+
+ if (numDatasets) {
+ var latMin = -90,
+ latMax = 90,
+ lonMin = -180,
+ lonMax = 180,
+ start = "1980-01-01 00:00:00",
+ end = "2030-01-01 00:00:00",
+ datasetRegrid = false;
+ // Get the valid lat/lon range in the selected datasets.
+ for (var i = 0; i < numDatasets; i++) {
+ var curDataset = $scope.datasets[i];
+
+ latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+ latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+ lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+ lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+ start = (curDataset['timeVals']['start'] > start) ? curDataset['timeVals']['start'] : start;
+ end = (curDataset['timeVals']['end'] < end) ? curDataset['timeVals']['end'] : end;
+
+ datasetRegrid = datasetRegrid || curDataset.regrid;
+
+ }
+
+ $scope.areInUserRegridState = !datasetRegrid
+ }
+
+ // Update the display parameters with the new valid overlap that we've found!
+ $scope.displayParams.latMin = latMin;
+ $scope.displayParams.latMax = latMax;
+ $scope.displayParams.lonMin = lonMin;
+ $scope.displayParams.lonMax = lonMax;
+ $scope.displayParams.start = (typeof start == 'undefined') ? "" : start.split(" ")[0];
+ $scope.displayParams.end = (typeof end == 'undefined') ? "" : end.split(" ")[0];
+
+ // Update the local store values!
+ $scope.latMin = latMin;
+ $scope.latMax = latMax;
+ $scope.lonMin = lonMin;
+ $scope.lonMax = lonMax;
+ $scope.start = (typeof start == 'undefined') ? "" : start.split(" ")[0];
+ $scope.end = (typeof end == 'undefined') ? "" : end.split(" ")[0];
+
+ $scope.displayParams.areValid = true;
+ $rootScope.$broadcast('redrawOverlays', []);
+ }, true);
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/RcmedSelectionCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/RcmedSelectionCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/RcmedSelectionCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/RcmedSelectionCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+App.Controllers.controller('RcmedSelectionCtrl', ['$rootScope', '$scope', '$http', '$timeout', 'selectedDatasetInformation',
+function($rootScope, $scope, $http, $timeout, selectedDatasetInformation) {
+ // Grab a copy of the datasets so we can display a count to the user!
+ $scope.datasetCount = selectedDatasetInformation.getDatasets();
+ $scope.fileAdded = false;
+
+ $scope.getObservations = function() {
+ $http.jsonp($rootScope.baseURL + '/getObsDatasets?callback=JSON_CALLBACK').
+ success(function(data) {
+ $scope.availableObs = data;
+ $scope.availableObs.splice(0, 0, {longname: 'Please select an option'});
+ $scope.datasetSelection = $scope.availableObs[0];
+ }).
+ error(function(data) {
+ $scope.availableObs = ["Unable to query RCMED"]
+ });
+ };
+
+ $scope.getObservationTimeRange = function(datasetID) {
+ var times = {
+ '1' : {'start' : '1989-01-01 00:00:00','end' : '2009-12-31 00:00:00'}, // ERA-Interim
+ '2' : {'start' : '2002-08-31 00:00:00','end' : '2010-01-01 00:00:00'}, // AIRS
+ '3' : {'start' : '1998-01-01 00:00:00','end' : '2010-01-01 00:00:00'}, // TRMM
+ '4' : {'start' : '1948-01-01 00:00:00','end' : '2010-01-01 00:00:00'}, // URD
+ '5' : {'start' : '2000-02-24 00:00:00','end' : '2010-05-30 00:00:00'}, // MODIS
+ '6' : {'start' : '1901-01-01 00:00:00','end' : '2006-12-01 00:00:00'} // CRU
+ };
+
+ return ((datasetID in times) ? times[datasetID] : false);
+ };
+
+ $scope.dataSelectUpdated = function() {
+ var urlString = $rootScope.baseURL + '/getDatasetParam?dataset=' +
+ $scope.datasetSelection["shortname"] +
+ "&callback=JSON_CALLBACK";
+ $http.jsonp(urlString).
+ success(function(data) {
+ $scope.retrievedObsParams = data;
+ if ($scope.retrievedObsParams.length > 1)
+ $scope.retrievedObsParams.splice(0, 0, {shortname: 'Please select a parameter'});
+ $scope.parameterSelection = $scope.retrievedObsParams[0];
+ });
+ };
+
+ $scope.addObservation = function() {
+ // This is a horrible hack for temporarily getting a valid time range
+ // for the selected observation. Eventually we need to handle this more
+ // elegantly than indexing into an array...
+ var timeRange = $scope.getObservationTimeRange($scope.datasetSelection["dataset_id"]);
+
+ var newDataset = {};
+
+ newDataset['isObs'] = 1;
+ // Save the dataset id (the important part) and name (for display purposes)
+ newDataset['datasetId'] = $scope.datasetSelection['dataset_id'];
+ newDataset['name'] = $scope.datasetSelection['longname'];
+ // Save the parameter id (the important part) and name (for display purposes)
+ newDataset['id'] = $scope.parameterSelection['parameter_id'];
+ newDataset['param'] = $scope.parameterSelection['parameter_id'];
+ newDataset['paramName'] = $scope.parameterSelection['longname'];
+ // Save the (fake) lat/lon information. We test with the TRMM dataset. RCMED currently
+ // doesn't return bounding information. This functionality is being added soon. When that
+ // is the case these hard coded values should be removed.
+ newDataset['latlonVals'] = {"latMin": -49.875, "latMax": 49.875, "lonMin": -179.875, "lonMax": 179.875};
+ // Set some defaults for lat/lon variable names. This just helps us display stuff later.
+ newDataset['lat'] = "N/A";
+ newDataset['lon'] = "N/A";
+ // Save time range information. If we don't have saved data for this observation then
+ // we set the values to extreme values so they'll be ignored when calculating overlaps.
+ newDataset['timeVals'] = {"start": (timeRange) ? timeRange['start'] : "1901-01-01 00:00:00",
+ "end": (timeRange) ? timeRange['end'] : "2050-01-01 00:00:00"};
+ // Set a default for the time variable names for display convenience.
+ newDataset['time'] = "N/A";
+
+ selectedDatasetInformation.addDataset(newDataset);
+
+ // Clear the user selections by requery-ing RCMED. This is really hacky, but it works for now...
+ $scope.availableObs = [];
+ $scope.retrievedObsParams = [];
+ $scope.getObservations();
+
+ // Display a confirmation message for a little bit
+ $scope.fileAdded = true;
+ $timeout(function() {
+ $scope.fileAdded = false;
+ }, 2000);
+ };
+
+ // Grab the available observations from RCMED
+ $scope.getObservations();
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for result page
+App.Controllers.controller('ResultCtrl', ['$rootScope', '$scope', '$http',
+function($rootScope, $scope, $http) {
+
+ $scope.results = [];
+
+ // Get all evaluation directories
+ $http.jsonp($rootScope.baseURL + '/getResultDirInfo?callback=JSON_CALLBACK')
+ .success(function(data) {
+ var removeItem = "/cache";
+ data.splice( $.inArray(removeItem,data) ,1 );
+ $scope.results = data.sort().reverse();
+ });
+
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultDetailCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultDetailCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultDetailCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/ResultDetailCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for result page
+App.Controllers.controller('ResultDetailCtrl', ['$rootScope', '$scope', '$http', '$stateParams',
+function($rootScope, $scope, $http, $stateParams) {
+
+ // Grab all figures
+ $scope.result = $stateParams.resultId;
+
+ $http.jsonp($rootScope.baseURL + '/getResults//' + $scope.result + '?callback=JSON_CALLBACK')
+ .success(function(data) {
+ if (data.length < 1){
+ $scope.figures = null;
+ $scope.alertMessage = "No results found.";
+ $scope.alertClass = "alert alert-danger";
+ } else {
+ $scope.figures = data;
+ }
+ });
+
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/SettingsCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/SettingsCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/SettingsCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/SettingsCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+App.Controllers.controller('SettingsCtrl', ['$scope', 'evaluationSettings', 'selectedDatasetInformation',
+function($scope, evaluationSettings, selectedDatasetInformation) {
+ $scope.settings = evaluationSettings.getSettings();
+ $scope.datasets = selectedDatasetInformation.getDatasets();
+}]);
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/SettingsCtrl.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/TimelineCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/TimelineCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/TimelineCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/TimelineCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,92 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Controller for the OCW Timeline Widget
+App.Controllers.controller('TimelineCtrl', ['$rootScope', '$scope', 'selectedDatasetInformation', 'regionSelectParams',
+function($rootScope, $scope, selectedDatasetInformation, regionSelectParams) {
+ $scope.datasets = selectedDatasetInformation.getDatasets();
+ $scope.regionParams = regionSelectParams.getParameters();
+
+ $scope.updateTimeline = function() {
+ // Clear timeline data if it exists
+ if ("timeline" in $rootScope) {
+ $rootScope.timeline.deleteAllItems();
+ }
+
+ // Don't process if no datasets have been added
+ if ($scope.datasets.length == 0 || !("timeline" in $rootScope))
+ return;
+
+ // Create DataTable to add data to timeline
+ var data = new google.visualization.DataTable();
+ data.addColumn('datetime', 'start');
+ data.addColumn('datetime', 'end');
+ data.addColumn('string', 'content');
+
+ // Loop through datasets and find the overlapping start/end time range
+ var start = $scope.datasets[0].timeVals.start;
+ var end = $scope.datasets[0].timeVals.end;
+ for (var i = 0; i < $scope.datasets.length; i++) {
+ var possibleNewStart = $scope.datasets[i].timeVals.start;
+ var possibleNewEnd = $scope.datasets[i].timeVals.end;
+
+ start = (possibleNewStart > start) ? possibleNewStart : start;
+ end = (possibleNewEnd < end) ? possibleNewEnd : end;
+ }
+
+ // Set the timeline extent to the overlapping time range
+ //
+ // NOTE: The month value substring is expected to be 0-based (hence the -1)
+ $rootScope.timeline.setVisibleChartRange(new Date(start.substr(0, 4), start.substr(5, 2) - 1, start.substr(8, 2)),
+ new Date(end.substr(0, 4), end.substr(5, 2) - 1, end.substr(8, 2)));
+
+ // Add user selected bounds to timeline
+ if ($scope.regionParams.areValid) {
+
+ var userStart = $scope.regionParams.start;
+ var userEnd = $scope.regionParams.end;
+
+ // Add color to user selected bounds
+ var style = 'background-color: #000000; border: 2px solid;';
+ var ocwBar = '<div class="ocw-bar timeline-event-range" style="' + style + '"></div>';
+
+ // Add row to DataTable: object with start and end date
+ // note: subtract one from month since indexes from 0 to 11
+ data.addRow([new Date(userStart.substr(0,4), userStart.substr(5,2)-1, userStart.substr(8,2)),
+ new Date(userEnd.substr(0,4), userEnd.substr(5,2)-1, userEnd.substr(8,2)),
+ ocwBar ]);
+ }
+
+ var options = {
+ "width": "100%",
+ "showCurrentTime": false,
+ "moveable": false,
+ "zoomable": false,
+ };
+
+ // Draw timeline with data (DataTable) and options (a name-value map)
+ $rootScope.timeline.draw(data, options);
+ };
+
+ $scope.$on('redrawOverlays', function(event, parameters) {
+ $scope.updateTimeline();
+ });
+
+ $scope.$watch('datasets', function() {
+ $scope.updateTimeline();
+ }, true);
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/WorldMapCtrl.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/WorldMapCtrl.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/WorldMapCtrl.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/controllers/WorldMapCtrl.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for the world map
+App.Controllers.controller('WorldMapCtrl', ['$rootScope', '$scope', 'selectedDatasetInformation', 'regionSelectParams',
+function($rootScope, $scope, selectedDatasetInformation, regionSelectParams) {
+ $scope.datasets = selectedDatasetInformation.getDatasets();
+ $scope.regionParams = regionSelectParams.getParameters();
+
+ $scope.updateMap = function() {
+ // Clear Group of layers from map if it exists
+ if ("rectangleGroup" in $rootScope) {
+ $rootScope.rectangleGroup.clearLayers();
+ }
+
+ // Don't process if we don't have any datasets added or if the map doesn't exist!!
+ if ($scope.datasets.length == 0 || !("map" in $rootScope))
+ return;
+
+ // Create a group that we'll draw overlays to
+ $rootScope.rectangleGroup = L.layerGroup();
+ // Add rectangle Group to map
+ $rootScope.rectangleGroup.addTo($rootScope.map);
+
+ // Calculate the overlap region and set the map to show the new overlap
+ var latMin = -90,
+ latMax = 90,
+ lonMin = -180,
+ lonMax = 180;
+
+ // Get the valid lat/lon range in the selected datasets.
+ for (var i = 0; i < selectedDatasetInformation.getDatasetCount(); i++) {
+ var curDataset = $scope.datasets[i];
+
+ latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+ latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+ lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+ lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+ }
+
+ var overlapBounds = [[latMax, lonMin], [latMin, lonMax]];
+ $rootScope.map.fitBounds(overlapBounds, {padding: [0, 0]});
+
+ // Draw border around overlap region
+ var overlapBorder = L.rectangle(overlapBounds, {
+ color: '#000000',
+ opacity: 1.0,
+ fill: false,
+ weight: 2,
+ dashArray: "10 10",
+ });
+
+ $rootScope.rectangleGroup.addLayer(overlapBorder);
+
+ // Draw user selected region
+ if ($scope.regionParams.areValid) {
+
+ var bounds = [[$scope.regionParams.latMax, $scope.regionParams.lonMin],
+ [$scope.regionParams.latMin, $scope.regionParams.lonMax]];
+
+ var polygon = L.rectangle(bounds, {
+ color: '#000000',
+ opacity: .3,
+ stroke: false,
+ fill: true,
+ });
+
+ $rootScope.rectangleGroup.addLayer(polygon);
+ }
+ };
+
+ $scope.$on('redrawOverlays', function(event, parameters) {
+ $scope.updateMap();
+ });
+
+ $scope.$watch('datasets', function() {
+ $scope.updateMap();
+ }, true);
+}]);
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModal.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModal.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModal.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModal.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Directive for inserting bootstrap modals
+App.Directives.directive('bootstrapModal', function($timeout) {
+ var link = function(scope, elem, attrs) {
+ var escapeEvent;
+ var openModal;
+ var closeModal;
+
+ escapeEvent = function(e) {
+ if (e.which == 27)
+ closeModal();
+ }
+
+ openModal = function(event, toggleBackground, toggleKeyboardEscape) {
+ // Grab the current modal tag based on the modalId attribute in the bootstrapModal tag
+ var modal = $('#' + attrs.modalId);
+
+ // Make all the modal's children of class "close" call the appropriate function for closing!
+ $('.close', modal).bind('click', closeModal);
+
+ modal.modal({
+ show: true,
+ backdrop: toggleBackground,
+ keyboard: toggleKeyboardEscape,
+ });
+ };
+
+ closeModal = function(event) {
+ $('#' + attrs.modalId).modal('hide');
+
+ };
+
+ // We need to bind the close and open modal events so outside elements can trigger the modal.
+ // This has to wait until the template has been fully inserted, so just wait a bit of time
+ // before we set them. I'm sure there's a better way of handling this...
+ $timeout(function() {
+ $('#' + attrs.modalId).
+ bind('modalOpen', openModal).
+ bind('modalClose', closeModal);
+ }, 100);
+ };
+
+ return {
+ link: link,
+ replace: true,
+ restrict: 'E',
+ scope: {
+ modalId: '@'
+ },
+ template: '<div id="{{modalId}}" class="modal hide fade" tabindex="-1"><div ng-transclude></div></div>',
+ transclude: true
+ };
+});
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModalOpen.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModalOpen.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModalOpen.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/BootstrapModalOpen.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// This directive processes bootstrap-modal-open attributes. This lets the user bind
+// the opening of a specific modal to a button/link. It also lets the user specify
+// what features the modal should have. The user can turn off the semi-opaque background
+// by having the background attribute set to 'false'. The user can also turn off the
+// ability to close the modal with ESC by having the keyboard attribute set to 'false'.
+App.Directives.directive('bootstrapModalOpen', function() {
+ return {
+ restrict: 'A',
+ link: function(scope, elem, attrs) {
+ // Default to showing the background if the user didn't specify a value for this.
+ var hasBackground = (attrs.background === undefined ? true : (attrs.background == "true"));
+ // Enable keyboard closing of modal with escape key.
+ var hasKeyboardEscape = (attrs.keyboard === undefined ? true : (attrs.keyboard == "true"));
+
+ $(elem).bind('click', function() {
+ $('#' + attrs.bootstrapModalOpen).trigger('modalOpen', [hasBackground, hasKeyboardEscape]);
+ });
+ }
+ };
+});
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/LeafletMap.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/LeafletMap.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/LeafletMap.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/LeafletMap.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Directive for dealing with the Leaflet map
+App.Directives.directive('leafletMap', function($rootScope) {
+ return {
+ restrict: 'E',
+ replace: true,
+ template: '<div></div>',
+ link: function(scope, element, attrs) {
+ $rootScope.map = L.map(attrs.id, {
+ center: [40, 0],
+ zoom: 2,
+ scrollWheelZoom: false,
+ attributionControl: false,
+ worldCopyJump: true,
+ });
+
+ //create a CloudMade tile layer and add it to the map
+ L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {}).addTo($rootScope.map);
+ }
+ };
+});
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/OnBlur.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/OnBlur.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/OnBlur.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/OnBlur.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// The onBlur directive calls a passed function when a field's "blur" event is called.
+// The function should be passed as part of the "on-blur" attribute and be defined in
+// the containing scope.
+//
+// Consider the test function "testFunc". If you wanted this to run on the blur event
+// for an input box you would use the following:
+// <input type="text" on-blur="testFunc();" />
+App.Directives.directive('onBlur', function() {
+ return {
+ restrict: 'A',
+ link: function($scope, $elem, $attrs) {
+ $elem.bind('blur', function() {
+ $scope.$eval($attrs.onBlur);
+ });
+ },
+ };
+ });
Propchange: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/OnBlur.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PredictiveFileBrowserInput.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PredictiveFileBrowserInput.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PredictiveFileBrowserInput.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PredictiveFileBrowserInput.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Setup a text input that the user will use to input a path to a local file.
+App.Directives.directive('predictiveFileBrowserInput', function() {
+ var link = function($scope, $elem, $attrs) {
+ $scope.autocomplete = [];
+
+ // Set id to use this directive correctly in multiple places
+ $scope.id = 'autoCompletePath'+ $elem.context.id
+ /*
+ * We need a place to dump our auto-completion options
+ */
+ $($elem).parent().append('<ul id="' + $scope.id +'"><ul>');
+
+ // Handle user clicks on auto-complete path options
+ $(document).on('click', '#' +$scope.id+ ' li span', function(e) {
+ // Set the input text box's value to that of the user selected path
+ var val = $(e.target).text();
+ $($elem).val(val);
+ // Need to trigger the input box's "input" event so Angular updates the model!
+ $elem.trigger('input');
+
+ // If the user selected a directory, find more results..
+ if (val[val.length - 1] == '/') {
+ $scope.fetchFiles($($elem).val());
+ // Otherwise, remove the auto-complete options...
+ } else {
+ $('#' +$scope.id+ ' li').remove();
+ }
+ });
+
+ /*
+ * Handle key-down events on the input box
+ *
+ * We need to ignore <TAB> presses here so we can auto-complete with <TAB>.
+ * If we don't ignore here then <TAB> will move the user to the next field
+ * in the form and our common-prefix-fill won't work later.
+ */
+ $($elem).keydown(function(e) {
+ var code = e.keyCode || e.which;
+ var BACKSPACE = 8,
+ TAB = 9;
+
+ if (code == TAB)
+ return false;
+ });
+
+ /*
+ * Handle key-up events on the input box
+ */
+ $($elem).keyup(function(e) {
+ var code = e.keyCode || e.which;
+ var BACKSPACE = 8,
+ TAB = 9,
+ FORWARD_SLASH = 191;
+
+ if (code === FORWARD_SLASH) {
+ // Fetch new directory information from the server.
+ $scope.fetchFiles($(this).val());
+ } else if (code === TAB) {
+ // Attempt to auto-fill for the user.
+ $scope.handleTabPress();
+ } else if (code == BACKSPACE) {
+ // Need to properly handle the removal of directory information
+ // and the displaying of auto-complete options
+ $scope.handleBackSpace();
+ } else {
+ // Filter auto-complete options based on user input..
+ $scope.handleMiscKeyPress();
+ }
+
+ // This is being used so we can handle backspacing. The user might hold
+ // down the backspace key or select a section of text and delete. This allows
+ // us to compare the result to its prior state, which makes handling
+ // backspaces easier.
+ $scope.lastInputContents = $elem.val();
+ });
+
+ /*
+ * Grab additional path information from the web-server
+ *
+ * Params:
+ * path - The path to get a directory listing of.
+ */
+ // TODO Make this use $HTTP
+ $scope.fetchFiles = function(path) {
+ $.get($scope.baseURL + '/getDirInfo/' + path, {},
+ function(data) {
+ $scope.setNewData(data);
+ $scope.updateAutoComplete();
+ }, 'json');
+ };
+
+ /*
+ * Grab additional path information from the web-server and filter the
+ * results based on the current input text.
+ *
+ * Params:
+ * path - The path to get a directory listing of.
+ *
+ * This is needed to handle deletion of selected text. It is possible that
+ * the user will select text and delete only part of a word. The results
+ * need to be filtered based on this partial input.
+ */
+ // TODO Why isn't this using $http?!?!?! Because I copy and pasted!!!!
+ $scope.fetchFilesAndFilter = function(path) {
+ $.get($scope.baseURL + '/getDirInfo/' + path, {},
+ function(data) {
+ $scope.setNewData(data);
+ $scope.filterResults();
+ $scope.updateAutoComplete();
+ }, 'json');
+ };
+
+ /*
+ * Handle directory data from the server.
+ *
+ * We store the entire directory information along with the remaining
+ * possible options given the users current input. This lets us avoid
+ * unnecessary calls to the server for directory information every time
+ * the user deletes something.
+ */
+ $scope.setNewData = function(data) {
+ $scope.autocomplete = data.sort();
+ $scope.possibleCompletes = $scope.autocomplete;
+ };
+
+ /*
+ * Handle <TAB> presses.
+ *
+ * Attempt to auto-complete options when the user presses <TAB>.
+ */
+ $scope.handleTabPress = function() {
+ // If there's only one option available there's no points in trying to
+ // find a common prefix! Just set the value!
+ if ($scope.possibleCompletes.length === 1) {
+ $elem.val($scope.possibleCompletes[0]);
+
+ // Make sure more options are displayed if a directory was selected.
+ $scope.checkForMoreOptions();
+ $scope.updateAutoComplete();
+ return;
+ }
+
+ // Find the greatest common prefix amongst the remaining choices and set
+ // the input text to it.
+ var prefix = $scope.getLargestCommonPrefix($scope.possibleCompletes);
+ $elem.val(prefix);
+ $scope.updateAutoComplete();
+ };
+
+ /*
+ * Handle Backspacing and option displaying.
+ *
+ * The auto-complete options needs to be displayed correctly when the user
+ * removes directory information.
+ */
+ $scope.handleBackSpace = function() {
+ var curInputVal = $elem.val();
+
+ // If the user deletes everything in the input box all we need to do
+ // is make sure that the auto-complete options aren't displayed.
+ if (curInputVal.length === 0) {
+ $('#' +$scope.id+ ' li').remove();
+ return;
+ }
+
+ // Figure out how much text the user removed from the input box.
+ var lengthDiff = $scope.lastInputContents.length - curInputVal.length;
+ // Grab the removed text.
+ var removedText = $scope.lastInputContents.substr(-lengthDiff);
+
+ // If the user deleted over a directory we need to fetch information on the
+ // previous directory for auto-completion.
+ if (removedText.indexOf('/') !== -1) {
+ var lastSlashIndex = curInputVal.lastIndexOf('/');
+
+ // If the remaining path still contains a directory...
+ if (lastSlashIndex !== -1) {
+ // Grab the section of the path that points to a valid directory,
+ // fetch the listing, and update the results.
+ var pathToSearch = curInputVal.slice(0, lastSlashIndex + 1);
+ $scope.fetchFilesAndFilter(pathToSearch);
+ } else {
+ // Delete the old auto-complete information in the case where the user
+ // completely removed path information.
+ $('#' +$scope.id+ ' li').remove();
+ }
+ } else {
+ // Otherwise, we just need to filter results based on the remaining input.
+ $scope.filterResults();
+ $scope.updateAutoComplete();
+ }
+ };
+
+ /*
+ * Handle all other key presses in the input box
+ *
+ * Filter the auto-complete options as the user types to ensure that only options
+ * which are possible given the current input text are still displayed.
+ */
+ $scope.handleMiscKeyPress = function() {
+ // Safely exit when there are no options available.
+ if ($scope.autocomplete === [])
+ return;
+
+ // Otherwise, filter the results.
+ $scope.filterResults();
+ $scope.updateAutoComplete();
+ };
+
+ /*
+ * When a path is auto-completed with <TAB> we need to check to see if it points
+ * to a directory. If it does, we still need to fetch results!
+ */
+ $scope.checkForMoreOptions = function() {
+ var path = $elem.val();
+ if (path[path.length - 1] === '/') {
+ $scope.fetchFiles(path);
+ }
+ };
+
+ /*
+ * Calculate the greatest common prefix of the passed options.
+ *
+ * Params:
+ * Options - An array of strings in which the greatest common prefix
+ * should be found
+ *
+ * Returns:
+ * The greatest common prefix of the strings.
+ *
+ *
+ * Note - For us, there will always be a prefix of at least '/' since this can't
+ * possible be called without the users entering a starting directory. As a result,
+ * we don't explicitly handle the case where there is 0 length common prefix.
+ */
+ $scope.getLargestCommonPrefix = function(options) {
+ var index = 1;
+ var shortestString = options.reduce(function(a, b) { return a.length < b.length ? a : b; });
+ var longestString = options.reduce(function(a, b) { return a.length > b.length ? a : b; });
+ var substringToCheck = shortestString[0];
+
+ while (longestString.indexOf(substringToCheck) !== -1) {
+ substringToCheck = shortestString.slice(0, ++index);
+ }
+
+ return longestString.slice(0, index - 1);
+ };
+
+ /*
+ * Filter the auto-complete options based on the current input.
+ */
+ $scope.filterResults = function() {
+ $scope.possibleCompletes = $scope.autocomplete.filter(function(item, index, array) {
+ return (~item.indexOf($($elem).val()));
+ });
+
+ $scope.possibleCompletes.sort();
+ };
+
+ /*
+ * Update the display of auto-complete options.
+ */
+ $scope.updateAutoComplete = function() {
+ // Remove all the existing options
+ $('#' +$scope.id+ ' li').remove();
+
+ // We don't need to show anything if the user has completely selected
+ // the only existing option available.
+ if ($scope.possibleCompletes.length === 1) {
+ if ($scope.possibleCompletes[0] === $elem.val()) {
+ return;
+ }
+ }
+
+ // Display all the possible completes
+ $.each($scope.possibleCompletes, function(i, v) {
+ $('#' +$scope.id+ '').append($('<li>').html($('<span>').text(v)));
+ });
+ };
+ };
+
+ return {
+ link: link,
+ scope: true,
+ restrict: 'A'
+ };
+});
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PreviewMap.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PreviewMap.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PreviewMap.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/PreviewMap.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+App.Directives.directive('previewMap', function($rootScope) {
+ return {
+ restrict: 'A',
+ replace: true,
+ scope: {dataset: '=previewMap', index: '=index'},
+ template: '<div id="{{dataset.name}}" class="preview-map"></div>',
+ replace: true,
+ link: function(scope, element, attrs) {
+
+ // Any attribute that contains {{}} interpolation will be set to null in the attrs
+ // parameter during the link function since the first $digest since the compilation
+ // has yet to run to evaluate it! We can't run a $digest in the middle of compilation,
+ // so using an $observe (or $watch) is the best way to get the values.
+ attrs.$observe('id', function(newId) {
+ var map = L.map(attrs.id, {
+ zoom: 0,
+ scrollWheelZoom: false,
+ zoomControl: false,
+ attributionControl: false,
+ worldCopyJump: true,
+ });
+
+ //create a CloudMade tile layer and add it to the map
+ L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {}).addTo(map);
+
+ // Zoom the map to the dataset bound regions (or at least try our best to do so)
+ var datasetBounds = [[scope.dataset.latlonVals.latMax, scope.dataset.latlonVals.lonMin],
+ [scope.dataset.latlonVals.latMin, scope.dataset.latlonVals.lonMax]];
+ map.fitBounds(datasetBounds, {});
+
+ // Draw a colored overlay on the region of the map
+ var maplatlon = scope.dataset.latlonVals;
+ var bounds = [[maplatlon.latMax, maplatlon.lonMin], [maplatlon.latMin, maplatlon.lonMax]];
+
+ var polygon = L.rectangle(bounds,{
+ stroke: false,
+ fillColor: $rootScope.fillColors[1],
+ fillOpacity: 0.6
+ });
+
+ // Add layer to Group
+ var rectangleGroup = L.layerGroup();
+ rectangleGroup.addLayer(polygon);
+
+ // Add the overlay to the map
+ rectangleGroup.addTo(map);
+ });
+ }
+ };
+});
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/directives/Timeline.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/directives/Timeline.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/directives/Timeline.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/directives/Timeline.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,44 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Directive for dealing with the Leaflet map
+App.Directives.directive('timeline', function($rootScope, $window) {
+ return {
+ restrict: 'C',
+ replace: true,
+ transclude: true,
+ template: '<div id="OCWtimeline"></div>',
+ link: function(scope, element, attrs) {
+ // Instantiate timeline object.
+ $rootScope.timeline = new links.Timeline(document.getElementById('OCWtimeline'));
+
+ // Redraw the timeline whenever the window is resized
+ angular.element($window).bind('resize', function() {
+ $rootScope.timeline.checkResize();
+ });
+
+ var options = {
+ "width": "100%",
+ "showCurrentTime": false,
+ "moveable": false,
+ "zoomable": false
+ };
+
+ $rootScope.timeline.draw([], options);
+ }
+ }
+});
Added: incubator/climate/trunk/ocw-ui/frontend/app/js/filters/ISODateToMiddleEndian.js
URL: http://svn.apache.org/viewvc/incubator/climate/trunk/ocw-ui/frontend/app/js/filters/ISODateToMiddleEndian.js?rev=1562255&view=auto
==============================================================================
--- incubator/climate/trunk/ocw-ui/frontend/app/js/filters/ISODateToMiddleEndian.js (added)
+++ incubator/climate/trunk/ocw-ui/frontend/app/js/filters/ISODateToMiddleEndian.js Tue Jan 28 22:18:16 2014
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+'use strict';
+
+// Convert a date in ISO format (or slightly modified such that 'T' is replace by ' ') into
+// a 'Middle Endian'/U.S. style date.
+App.Filters.filter('ISODateToMiddleEndian', function() {
+ return function(input) {
+ var original = input;
+
+ // Strip whitespace from the start and end of the string
+ input = input.replace(/(^\s+|\s+$)/g, '');
+
+ // ISO Standard says time is separated from Date with a 'T'. Our timestamps
+ // slightly modify that and use a space. We'll check for both here and prefer
+ // to split on a 'T' if it's available.
+ if (input.indexOf('T') != -1 || input.indexOf(' ') != -1) {
+ input = (input.indexOf('T') != -1) ? input.split('T')[0] : input.split(' ')[0];
+ }
+
+ // The components of the date should be split with hyphens. If we can't find them
+ // then the string is poorly formed.
+ if (input.indexOf('-') == -1 || input.split('-').length - 1 != 2) {
+ return original;
+ }
+
+ // At this point the date is probably valid and we should try to convert it!
+ var components = input.split('-');
+ return (components[1] + "/" + components[2] + "/" + components[0]);
+ };
+});