<commit_before>/**
 * @name Hydra-event-bus
 * @summary Hydra-event-bus Hydra service entry point
 * @description Provides the Event Bus for Hydra microservices
 */
'use strict';

const version = require('./package.json').version;
const hydraExpress = require('hydra-express');
let config = require('fwsp-config');
const util = require('./src/util');
const HydraExpressLogger = require('fwsp-logger').HydraExpressLogger;
const bodyParser = require('body-parser');
let hydraLogger = new HydraExpressLogger();
hydraExpress.use(hydraLogger);
const MAX_POST_SIZE = '5mb';

/**
 * Load configuration file
 */
config
  .init('./config/config.json')
  .then(() => {
    config.version = version;
    config.hydra.serviceVersion = version;
    /**
     * Initialize hydra
     */
    const app = hydraExpress.getExpressApp();
    app.use(bodyParser({limit: MAX_POST_SIZE}));

    return hydraExpress.init(config.getObject(), version, () => {
      hydraExpress.registerRoutes({
        '/api/v1/hydra-event-bus': require('./routes/hydra-event-v1-routes')
      });
    })
  })
  .then(serviceInfo => {
    let logEntry = `Starting ${config.hydra.serviceName} (v.${config.version})`;
    const hydra = hydraExpress.getHydra();
    hydra.sendToHealthLog('info', logEntry);
    util.updateAllPatterns();

    hydra.on('message', (umf) => {
      if (umf.typ !== 'event-bus')
        return;

      const body = umf.bdy;

      util.registerPatternsForService(body);
      util.unregisterPatternsForService(body);
      util.dispatchEventUMF(body);

      const frmParts = umf.frm.split('@');
      if (frmParts.length != 2 || frmParts[0] != hydra.instanceID) {
        util.updatePatterns(body);
      }
    });
  })
  .catch((err) => {
    hydra.sendToHealthLog('error', err);
  });
<commit_msg>remove prefix api<commit_after>/**
 * @name Hydra-event-bus
 * @summary Hydra-event-bus Hydra service entry point
 * @description Provides the Event Bus for Hydra microservices
 */
'use strict';

const version = require('./package.json').version;
const hydraExpress = require('hydra-express');
let config = require('fwsp-config');
const util = require('./src/util');
const HydraExpressLogger = require('fwsp-logger').HydraExpressLogger;
const bodyParser = require('body-parser');
let hydraLogger = new HydraExpressLogger();
hydraExpress.use(hydraLogger);
const MAX_POST_SIZE = '5mb';

/**
 * Load configuration file
 */
config
  .init('./config/config.json')
  .then(() => {
    config.version = version;
    config.hydra.serviceVersion = version;
    /**
     * Initialize hydra
     */
    const app = hydraExpress.getExpressApp();
    app.use(bodyParser({limit: MAX_POST_SIZE}));

    return hydraExpress.init(config.getObject(), version, () => {
      hydraExpress.registerRoutes({
        '/v1/hydra-event-bus': require('./routes/hydra-event-v1-routes')
      });
    })
  })
  .then(serviceInfo => {
    let logEntry = `Starting ${config.hydra.serviceName} (v.${config.version})`;
    const hydra = hydraExpress.getHydra();
    hydra.sendToHealthLog('info', logEntry);
    util.updateAllPatterns();

    hydra.on('message', (umf) => {
      if (umf.typ !== 'event-bus')
        return;

      const body = umf.bdy;

      util.registerPatternsForService(body);
      util.unregisterPatternsForService(body);
      util.dispatchEventUMF(body);

      const frmParts = umf.frm.split('@');
      if (frmParts.length != 2 || frmParts[0] != hydra.instanceID) {
        util.updatePatterns(body);
      }
    });
  })
  .catch((err) => {
    hydra.sendToHealthLog('error', err);
  });
<|endoftext|>


<commit_before>(function () {
  'use strict';

  angular
    .module('app')
    .factory('OfflineTilesFactory', OfflineTilesFactory);

  OfflineTilesFactory.$inject = ['$http', '$ionicLoading', '$ionicPopup', '$log', '$q', 'LocalStorageFactory'];

  // used to determine what the map provider is before we archive a tileset
  function OfflineTilesFactory($http, $ionicLoading, $ionicPopup, $log, $q, LocalStorageFactory) {
    var downloadErrors = 0;
    var offlineMaps = [];

    return {
      'checkValidMapName': checkValidMapName,
      'clear': clear,
      'deleteMap': deleteMap,
      'getOfflineMaps': getOfflineMaps,
      'getOfflineTileCount': getOfflineTileCount,
      'read': read,
      'renameMap': renameMap,
      'saveMap': saveMap
    };

    /**
     *  Private Functions
     */

    function downloadTile(mapToSave, tile) {
      var deferred = $q.defer(); // init promise

      var url = _.sample(mapToSave.url);
      if (mapToSave.source === 'mapbox_classic') url = url + mapToSave.id + '/';
      else if (mapToSave.source === 'mapbox_styles') url = url + mapToSave.id + '/tiles/256/';
      else if (mapToSave.source === 'map_warper') url = url + mapToSave.id + '/';
      var imageUrl = url + tile;
      if (mapToSave.imageType) imageUrl += '.' + mapToSave.imageType;
      if (mapToSave.key) imageUrl = imageUrl + '?access_token=' + mapToSave.key;

      var request = $http({
        'method': 'get',
        'url': imageUrl,
        'responseType': 'arraybuffer'
      });
      request.then(function (response) {
        var blob = new Blob([response.data], {
          'type': mapToSave.mime
        });
        writeTile(mapToSave, tile, blob).then(function (size) {
          deferred.resolve(size);
        });
      }, function (response) {
        // Request Failure
        downloadErrors += 1;
        deferred.reject(response);
      });
      return deferred.promise;
    }

    function writeMap(mapToSave, mapSize) {
      var deferred = $q.defer(); // init promise
      var mapNameData = {
        'source': mapToSave.source,
        'id': mapToSave.id,
        'title': mapToSave.title,
        'tileArray': mapToSave.tiles.saved,
        'size': mapSize,
        'date': new Date().toLocaleString()
      };

      // If there's already a maps with this name (if appending) remove maps first
      offlineMaps = _.reject(offlineMaps, function (offlineMap) {
        return offlineMap.name === mapToSave.name;
      });

      LocalStorageFactory.getDb().mapNamesDb.setItem(mapToSave.name, mapNameData).then(function () {
        offlineMaps.push(_.extend(mapNameData, {'name': mapToSave.name}));
        deferred.resolve();
      });
      return deferred.promise;
    }

    // Write tile to storage
    function writeTile(mapToSave, tile, blob) {
      var deferred = $q.defer(); // init promise

      // note that tileId is prefixed with map_id, tile itself is not
      var tileId = mapToSave.id + '/' + tile;
      LocalStorageFactory.getDb().mapTilesDb.setItem(tileId, blob).then(function () {
        deferred.resolve(blob.size);
      });
      return deferred.promise;
    }

    /**
     * Public Functions
     */

    function checkValidMapName(map) {
      var deferred = $q.defer(); // init promise
      var foundOfflineMap = _.find(offlineMaps, function (offlineMap) {
        return offlineMap.name === map.name;
      });
      if (foundOfflineMap && map.id === foundOfflineMap.id) {
        var confirmPopup = $ionicPopup.confirm({
          'title': 'Append Tiles?',
          'template': 'Append the current tiles to saved map ' + map.name + '?'
        });
        confirmPopup.then(function (res) {
          if (res) {
            $ionicLoading.show({'template': '<ion-spinner></ion-spinner>'});
            var savedTilesUnion = _.union(map.tiles.saved, foundOfflineMap.tileArray);
            map.tiles.saved = _.uniq(savedTilesUnion, false, 'tile');
            deferred.resolve();
          }
          else deferred.reject();
        });
      }
      else if (foundOfflineMap && map.id !== foundOfflineMap.id) {
        $ionicPopup.alert({
          'title': 'Append Error!',
          'template': 'Cannot append the selected new tiles to the saved map ' + map.name + ' since the map' +
          ' tile provider is not the same. A new map name must be given if you wish to use a different tile provider.'
        });
        deferred.reject();
      }
      // If the map name doesn't exist yet, create it with a size 0
      else {
        $ionicLoading.show({'template': '<ion-spinner></ion-spinner>'});
        writeMap(map, 0).then(function () {
          deferred.resolve();
        });
      }
      return deferred.promise;
    }

    // Wipe the offline database
    function clear(callback) {
      // deletes all offline tiles
      offlineMaps = [];
      LocalStorageFactory.getDb().mapTilesDb.clear(function (err) {
        if (err) callback(err);
        else {
          // then delete all map names
          LocalStorageFactory.getDb().mapNamesDb.clear(function (err) {
            if (err) callback(err);
            else callback();
          });
        }
      });
    }

    function deleteTile(tile) {
      var deferred = $q.defer();
      LocalStorageFactory.getDb().mapTilesDb.removeItem(tile).then(function () {
        deferred.resolve();
      });
      return deferred.promise;
    }

    function deleteMap(mapToDelete) {
      var deferred = $q.defer();
      var promises = [];
      var tiles = mapToDelete.tileArray;
      var tilesStillUsed = [];

      _.each(offlineMaps, function (offlineMap) {
        if (mapToDelete.name !== offlineMap.name) {
          var offlineMapTiles = angular.fromJson(angular.toJson(offlineMap.tileArray));
          _.each(offlineMapTiles, function (offlineMapTile) {
            offlineMapTile.map_id = offlineMap.id;
          });
          _.extend(tilesStillUsed, offlineMapTiles);
        }
      });
      _.uniq(tilesStillUsed);

      _.each(tiles, function (tile) {
        var found = _.find(tilesStillUsed, function (tileStillUsed) {
          return (tileStillUsed.id === mapToDelete.id && tileStillUsed.tile === tile.tile);
        });
        if (!found) promises.push(deleteTile(mapToDelete.id + '/' + tile.tile));
      });

      // All tiles associated with this maps name and not used in another maps have been deleted
      // now delete the actual map name if there were actually any tiles deleted
      $q.all(promises).then(function () {
        LocalStorageFactory.getDb().mapNamesDb.removeItem(mapToDelete.name).then(function () {
          // Map is deleted, and this is now fully resolved
          offlineMaps = _.reject(offlineMaps, function (offlineMap) {
            return offlineMap.name === mapToDelete.name;
          });
          deferred.resolve();
        });
      });
      return deferred.promise;
    }

    function getOfflineMaps() {
      var deferred = $q.defer();

      if (_.isEmpty(offlineMaps)) {
        LocalStorageFactory.getDb().mapNamesDb.iterate(function (value, key) {
          var map = _.extend(value, {'name': key});
          offlineMaps.push(map);
        }, function () {
          deferred.resolve(offlineMaps);
        });
      }
      else deferred.resolve(offlineMaps);
      return deferred.promise;
    }

    // Get the number of tiles from offline storage
    function getOfflineTileCount(callback) {
      LocalStorageFactory.getDb().mapTilesDb.length(function (err, numberOfKeys) {
        callback(err || numberOfKeys);
      });
    }

    // Read from storage
    function read(mapProvider, tile, callback) {
      var tileId = mapProvider + '/' + tile;
      LocalStorageFactory.getDb().mapTilesDb.getItem(tileId).then(function (blob) {
        callback(blob);
      });
    }

    function renameMap(mapToRename, newMapName) {
      var deferred = $q.defer();

      offlineMaps = _.reject(offlineMaps, function (offlineMap) {
        return offlineMap.name === mapToRename.name;
      });

      LocalStorageFactory.getDb().mapNamesDb.removeItem(mapToRename.name).then(function () {
        delete mapToRename.name;
        LocalStorageFactory.getDb().mapNamesDb.setItem(newMapName, mapToRename).then(function () {
          offlineMaps.push(_.extend(mapToRename, {'name': newMapName}));
          deferred.resolve();
        });
      });
      return deferred.promise;
    }

    function saveMap(mapToSave) {
      var deferred = $q.defer(); // init promise
      downloadErrors = 0;
      var tilesDownloaded = {'success': [], 'failed': []};
      var promises = [];

      if (mapToSave.tiles.need.length > 0) {
        $log.log('Requesting to download', mapToSave.tiles.need.length, 'tiles from ', mapToSave.id,
          'for map', mapToSave.name);
        _.each(mapToSave.tiles.need, function (tile) {
          var promise = downloadTile(mapToSave, tile).then(function (size) {
            tilesDownloaded.success.push(tile);
            mapToSave.tiles.saved.push({'tile': tile, 'size': size});
            deferred.notify(tilesDownloaded);
          }, function (err) {
            $log.log('Error downloading tile:', err);
            tilesDownloaded.failed.push(tile);
            deferred.notify(tilesDownloaded);
          });
          promises.push(promise);
        });
      }

      $q.all(promises).then(function () {
        $log.log('Number of errors:', downloadErrors);
        if (downloadErrors !== 0 && downloadErrors === mapToSave.tiles.need.length) deferred.reject();
        else {
          // Calculate the size of tiles we have in storage for this map
          var mapSize = _.reduce(_.pluck(mapToSave.tiles.saved, 'size'), function (memo, num) {
            return memo + num;
          }, 0);
          writeMap(mapToSave, mapSize).then(function () {
            $log.log('Saved map:', mapToSave.name, 'with tiles from', mapToSave.title, 'of size',
              mapSize, ':',
              mapToSave.tiles.saved);
            deferred.resolve();
          });
        }
      });
      return deferred.promise;
    }
  }
}());
<commit_msg>Archive Tiles: Write map properties after each tile download<commit_after>(function () {
  'use strict';

  angular
    .module('app')
    .factory('OfflineTilesFactory', OfflineTilesFactory);

  OfflineTilesFactory.$inject = ['$http', '$ionicLoading', '$ionicPopup', '$log', '$q', 'LocalStorageFactory'];

  // used to determine what the map provider is before we archive a tileset
  function OfflineTilesFactory($http, $ionicLoading, $ionicPopup, $log, $q, LocalStorageFactory) {
    var downloadErrors = 0;
    var offlineMaps = [];

    return {
      'checkValidMapName': checkValidMapName,
      'clear': clear,
      'deleteMap': deleteMap,
      'getOfflineMaps': getOfflineMaps,
      'getOfflineTileCount': getOfflineTileCount,
      'read': read,
      'renameMap': renameMap,
      'saveMap': saveMap
    };

    /**
     *  Private Functions
     */

    function downloadTile(mapToSave, tile) {
      var deferred = $q.defer(); // init promise

      var url = _.sample(mapToSave.url);
      if (mapToSave.source === 'mapbox_classic') url = url + mapToSave.id + '/';
      else if (mapToSave.source === 'mapbox_styles') url = url + mapToSave.id + '/tiles/256/';
      else if (mapToSave.source === 'map_warper') url = url + mapToSave.id + '/';
      var imageUrl = url + tile;
      if (mapToSave.imageType) imageUrl += '.' + mapToSave.imageType;
      if (mapToSave.key) imageUrl = imageUrl + '?access_token=' + mapToSave.key;

      var request = $http({
        'method': 'get',
        'url': imageUrl,
        'responseType': 'arraybuffer'
      });
      request.then(function (response) {
        var blob = new Blob([response.data], {
          'type': mapToSave.mime
        });
        writeTile(mapToSave, tile, blob).then(function (size) {
          deferred.resolve(size);
        });
      }, function (response) {
        // Request Failure
        downloadErrors += 1;
        deferred.reject(response);
      });
      return deferred.promise;
    }

    function writeMap(mapToSave, mapSize) {
      var deferred = $q.defer(); // init promise
      var mapNameData = {
        'source': mapToSave.source,
        'id': mapToSave.id,
        'title': mapToSave.title,
        'tileArray': mapToSave.tiles.saved,
        'size': mapSize,
        'date': new Date().toLocaleString()
      };

      // If there's already a maps with this name (if appending) remove maps first
      offlineMaps = _.reject(offlineMaps, function (offlineMap) {
        return offlineMap.name === mapToSave.name;
      });

      LocalStorageFactory.getDb().mapNamesDb.setItem(mapToSave.name, mapNameData).then(function () {
        offlineMaps.push(_.extend(mapNameData, {'name': mapToSave.name}));
        deferred.resolve();
      });
      return deferred.promise;
    }

    // Write tile to storage
    function writeTile(mapToSave, tile, blob) {
      var deferred = $q.defer(); // init promise

      // note that tileId is prefixed with map_id, tile itself is not
      var tileId = mapToSave.id + '/' + tile;
      LocalStorageFactory.getDb().mapTilesDb.setItem(tileId, blob).then(function () {
        deferred.resolve(blob.size);
      });
      return deferred.promise;
    }

    /**
     * Public Functions
     */

    function checkValidMapName(map) {
      var deferred = $q.defer(); // init promise
      var foundOfflineMap = _.find(offlineMaps, function (offlineMap) {
        return offlineMap.name === map.name;
      });
      if (foundOfflineMap && map.id === foundOfflineMap.id) {
        var confirmPopup = $ionicPopup.confirm({
          'title': 'Append Tiles?',
          'template': 'Append the current tiles to saved map ' + map.name + '?'
        });
        confirmPopup.then(function (res) {
          if (res) {
            $ionicLoading.show({'template': '<ion-spinner></ion-spinner>'});
            var savedTilesUnion = _.union(map.tiles.saved, foundOfflineMap.tileArray);
            map.tiles.saved = _.uniq(savedTilesUnion, false, 'tile');
            deferred.resolve();
          }
          else deferred.reject();
        });
      }
      else if (foundOfflineMap && map.id !== foundOfflineMap.id) {
        $ionicPopup.alert({
          'title': 'Append Error!',
          'template': 'Cannot append the selected new tiles to the saved map ' + map.name + ' since the map' +
          ' tile provider is not the same. A new map name must be given if you wish to use a different tile provider.'
        });
        deferred.reject();
      }
      // If the map name doesn't exist yet, create it with a size 0
      else {
        $ionicLoading.show({'template': '<ion-spinner></ion-spinner>'});
        writeMap(map, 0).then(function () {
          deferred.resolve();
        });
      }
      return deferred.promise;
    }

    // Wipe the offline database
    function clear(callback) {
      // deletes all offline tiles
      offlineMaps = [];
      LocalStorageFactory.getDb().mapTilesDb.clear(function (err) {
        if (err) callback(err);
        else {
          // then delete all map names
          LocalStorageFactory.getDb().mapNamesDb.clear(function (err) {
            if (err) callback(err);
            else callback();
          });
        }
      });
    }

    function deleteTile(tile) {
      var deferred = $q.defer();
      LocalStorageFactory.getDb().mapTilesDb.removeItem(tile).then(function () {
        deferred.resolve();
      });
      return deferred.promise;
    }

    function deleteMap(mapToDelete) {
      var deferred = $q.defer();
      var promises = [];
      var tiles = mapToDelete.tileArray;
      var tilesStillUsed = [];

      _.each(offlineMaps, function (offlineMap) {
        if (mapToDelete.name !== offlineMap.name) {
          var offlineMapTiles = angular.fromJson(angular.toJson(offlineMap.tileArray));
          _.each(offlineMapTiles, function (offlineMapTile) {
            offlineMapTile.map_id = offlineMap.id;
          });
          _.extend(tilesStillUsed, offlineMapTiles);
        }
      });
      _.uniq(tilesStillUsed);

      _.each(tiles, function (tile) {
        var found = _.find(tilesStillUsed, function (tileStillUsed) {
          return (tileStillUsed.id === mapToDelete.id && tileStillUsed.tile === tile.tile);
        });
        if (!found) promises.push(deleteTile(mapToDelete.id + '/' + tile.tile));
      });

      // All tiles associated with this maps name and not used in another maps have been deleted
      // now delete the actual map name if there were actually any tiles deleted
      $q.all(promises).then(function () {
        LocalStorageFactory.getDb().mapNamesDb.removeItem(mapToDelete.name).then(function () {
          // Map is deleted, and this is now fully resolved
          offlineMaps = _.reject(offlineMaps, function (offlineMap) {
            return offlineMap.name === mapToDelete.name;
          });
          deferred.resolve();
        });
      });
      return deferred.promise;
    }

    function getOfflineMaps() {
      var deferred = $q.defer();

      if (_.isEmpty(offlineMaps)) {
        LocalStorageFactory.getDb().mapNamesDb.iterate(function (value, key) {
          var map = _.extend(value, {'name': key});
          offlineMaps.push(map);
        }, function () {
          deferred.resolve(offlineMaps);
        });
      }
      else deferred.resolve(offlineMaps);
      return deferred.promise;
    }

    // Get the number of tiles from offline storage
    function getOfflineTileCount(callback) {
      LocalStorageFactory.getDb().mapTilesDb.length(function (err, numberOfKeys) {
        callback(err || numberOfKeys);
      });
    }

    // Read from storage
    function read(mapProvider, tile, callback) {
      var tileId = mapProvider + '/' + tile;
      LocalStorageFactory.getDb().mapTilesDb.getItem(tileId).then(function (blob) {
        callback(blob);
      });
    }

    function renameMap(mapToRename, newMapName) {
      var deferred = $q.defer();

      offlineMaps = _.reject(offlineMaps, function (offlineMap) {
        return offlineMap.name === mapToRename.name;
      });

      LocalStorageFactory.getDb().mapNamesDb.removeItem(mapToRename.name).then(function () {
        delete mapToRename.name;
        LocalStorageFactory.getDb().mapNamesDb.setItem(newMapName, mapToRename).then(function () {
          offlineMaps.push(_.extend(mapToRename, {'name': newMapName}));
          deferred.resolve();
        });
      });
      return deferred.promise;
    }

    function saveMap(mapToSave) {
      var deferred = $q.defer(); // init promise
      downloadErrors = 0;
      var tilesDownloaded = {'success': [], 'failed': []};
      var promises = [];

      if (mapToSave.tiles.need.length > 0) {
        $log.log('Requesting to download', mapToSave.tiles.need.length, 'tiles from', mapToSave.id,
          'for map', mapToSave.name);
        _.each(mapToSave.tiles.need, function (tile) {
          var promise = downloadTile(mapToSave, tile).then(function (size) {
            tilesDownloaded.success.push(tile);
            mapToSave.tiles.saved.push({'tile': tile, 'size': size});
            var mapSize = _.reduce(_.pluck(mapToSave.tiles.saved, 'size'), function (memo, num) {
              return memo + num;
            }, 0);
            return writeMap(mapToSave, mapSize).then(function() {
              /*$log.log('Saved map:', mapToSave.name, 'with tiles from', mapToSave.title, 'of size',
                mapSize, ':',
                mapToSave.tiles.saved);*/
              deferred.notify(tilesDownloaded);
            });
          }, function (err) {
            $log.log('Error downloading tile:', err);
            tilesDownloaded.failed.push(tile);
            deferred.notify(tilesDownloaded);
          });
          promises.push(promise);
        });
      }

      $q.all(promises).then(function () {
        $log.log('Number of errors:', downloadErrors);
        if (downloadErrors !== 0 && downloadErrors === mapToSave.tiles.need.length) deferred.reject();
        else {
          // Calculate the size of tiles we have in storage for this map
          var mapSize = _.reduce(_.pluck(mapToSave.tiles.saved, 'size'), function (memo, num) {
            return memo + num;
          }, 0);
          writeMap(mapToSave, mapSize).then(function () {
            $log.log('Saved map:', mapToSave.name, 'with tiles from', mapToSave.title, 'of size',
              mapSize, ':',
              mapToSave.tiles.saved);
            deferred.resolve();
          });
        }
      });
      return deferred.promise;
    }
  }
}());
<|endoftext|>


<commit_before>(function ($) {
    // Used to instantiate clickable urls in dynamically generated items
    $.fn.urlClickable = function () {
        var item = $(this);

        if (item.find(".isUrlClickable").length) {
            return this;    // Items already initiated
        }

        var originalText = item.text().trim();
        var newText = originalText;

        // Regular expression to find FTP, HTTP(S) and email URLs.
        var regexToken = /(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)|((mailto:)?[_.\w-]+@([\w][\w\-]+\.)+[a-zA-Z]{2,3})/g;

        // Extract all URL occurrences
        var matchArray;
        var urls = [];

        while ((matchArray = regexToken.exec(originalText)) !== null) {
            if (matchArray[0].slice(-1) === "." || matchArray[0].slice(-1) === ",") {
                urls.push(matchArray[0].slice(0, -1))
            }
            else {
                urls.push(matchArray[0]);
            }
        }

        // Get a list of unique URLs
        var uniqueUrls = [];
        $.each(urls, function (i, el) {
            if ($.inArray(el, uniqueUrls) === -1) {
                uniqueUrls.push(el);
            }
        });

        // Replace all URLs for links
        for (var i = 0; i < uniqueUrls.length; i++) {
            var currentUrl = uniqueUrls[i];

            var replacedString = "" +
                "" + currentUrl + "";

            var regex = new RegExp(currentUrl, "g");
            newText = newText.replace(regex, replacedString);
        }

        $(this).html(newText);

        return item;
    }
})(jQuery);

// Formats dates from "yyyy-mm-dd" to "mm/dd/yyyy"
(function ($) {
    $.fn.formatDate = function () {
        var item = $(this);
        var dateString = item.attr("data-date").trim().substr(0, 10).split("-");    // original format: yyyy-mm-dd (10 characters)
        var formattedDate = dateString[1] + "/" + dateString[2] + "/" + dateString[0];
        item.text(formattedDate);

        return item;
    }
})(jQuery);

$(document).ready(function () {
    // Search box toggle
    // =================
    $('#search-btn').on('click', function () {
        $("#search-icon").toggleClass('fa-times margin-2');
        $("#search-box").toggleClass('display-block animated fadeInUp');
    });

    // Smooth scrolling for UI elements page
    // =====================================

    $('a[href*=#buttons],a[href*=#panels], a[href*=#info-boards], a[href*=#navs], a[href*=#alerts], a[href*=#thumbnails], a[href*=#social], a[href*=#section-header],a[href*=#page-tip], a[href*=#block-header]').bind("click", function (e) {
        var anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $(anchor.attr('href')).offset().top
        }, 1000);
        e.preventDefault();
    });

    // 404 error page
    // ====================
    $('#search-404').on('click', function () {
        $("#smile").removeClass("fa-meh-o");
        $("#smile").addClass("fa-smile-o");
    });

    // Sign up popovers
    // ================
    $(function () {
        $('#exampleInputName1').popover();
    });

    $(function () {
        $('#exampleInputUsername1').popover();
    });

    $(function () {
        $('#exampleInputEmail1').popover();
    });

    $(function () {
        $('#exampleInputPassword1').popover();
    });

    $(function () {
        $('#exampleInputPassword2').popover();
    });

    // Profile - Status Update
    // =======================

    $('#update-status').on('click', function () {
        $(".user-status > p").toggleClass("show hidden");
        $(".user-status > form").toggleClass("hidden show");
        return false;
    });

    $('.user-status > form > button').on('click', function () {
        $(".user-status > p").toggleClass("show hidden");
        $(".user-status > form").toggleClass("hidden show");
        return false;
    });

    // Lost password form
    //===================

    $('.pwd-lost > .pwd-lost-q > a').on('click', function () {
        $(".pwd-lost > .pwd-lost-q").toggleClass("show hidden");
        $(".pwd-lost > .pwd-lost-f").toggleClass("hidden show");
        return false;
    });

    // Prevents nav dropdowns from closing when clicking on elements inside
    $('#hs-nav-bar .dropdown-menu').on('click', function (e) {
        e.stopPropagation();
    });

	// Close buttons for notification messages
	$(".btn-close-message").click(function() {
		$(this).parent().parent().parent().parent().hide(400);
	});

	// Initialize tooltips
	$('[data-toggle="tooltip"]').tooltip();

    // Format the dates before displaying them
    $(".format-date").each(function () {
        $(this).formatDate();
    });

    function popup_profile_alert(uid, fields) {
        if ($("#publish").length) {
                $("#publish").toggleClass("disabled", true);
                $("#publish").removeAttr("data-toggle");   // Disable the agreement modal
                $("#publish > [data-toggle='tooltip']").attr("data-original-title",
                    "Your profile information must be complete before you can formally publish resources.");
            }
            missing_field_str = fields.join(', ')

            var message = 'Your profile is nearly complete. Please fill in the '
                + '' + missing_field_str + ' fields'
                + ' on the User Profile page';

            customAlert("Profile", message, "info", 10000);
    }

    $.ajax({
        url: "/hsapi/userInfo/",
        success: function(user) {
            var missing_profile_fields = [];
            if(!user.organization)
                missing_profile_fields.push('Organization')
            if(!user.state)
                missing_profile_fields.push('State')
            if(!user.country)
                missing_profile_fields.push('Country')
            if(!user.user_type)
                missing_profile_fields.push('User Type')
            if(missing_profile_fields.length) {
                // Disable publishing resources
                popup_profile_alert(user.id, missing_profile_fields)
            }
        },
        error: function(response) {
            console.log(response);
        }
    });

    $(".author-preview").click(function() {
        resetAuthorPreview();
        var preview = $("#view-author-modal");
        var data = jQuery.extend(true, {}, $(this).data());
        var identifiers = ["googlescholarid", "orcid", "researchgateid", "researcerid"];
        var fields = ["name", "organization", "email", "address", "phone"];

        // If entry is an organization, hide name and profile rows
        preview.find("[data-name]").closest("tr").toggleClass("hidden", !data["name"]);
        preview.find("[data-profileurl]").closest("tr").toggleClass("hidden", !data["profileurl"]);

        // Populate profile url
        if (data["profileurl"]) {
            preview.find("[data-profileurl]").attr("href", data["profileurl"]);
        }
        delete data["profileurl"];

        // Populate homepage url
        if (data["homepage"]) {
            preview.find("[data-homepage]").attr("href", data["homepage"]);
            preview.find("[data-homepage]").text(data["homepage"]);
            preview.find("[data-homepage]").show();
        }
        delete data["homepage"];

        // Populate rest of the fields
        for (var item in data) {
            if ($.inArray(item, fields) != -1) {
                var content = data[item];
                var field = preview.find("[data-" + item + "]");
                field.text(content);
            }
            else if ($.inArray(item, identifiers) != -1) {
                var ident = preview.find("[data-" + item + "]");
                ident.show();
                preview.find(".externalprofiles-wrapper").show();
                ident.attr("href", data[item]);
            }
        }
    });

    function resetAuthorPreview(){
        var preview = $("#view-author-modal");
        preview.find(".identifier-icon").hide();
        preview.find("[data-name]").parent().show();
        preview.find("[data-profileurl]").parent().show();
    }

    $(".submenu-trigger").click(function (e) {
        $(this).next('ul').toggle();
        e.stopPropagation();
        e.preventDefault();
    });

    // Abstract collapse toggle
    $(".toggle-abstract").click(function () {
        if ($(this).parent().find(".activity-description").css("max-height") == "50px") {
            var block = $(this).parent().find(".activity-description");

            block.css("max-height", "initial"); // Set max-height to initial temporarily.
            var maxHeight = block.height();    // Save the max height
            block.css("max-height", "50px");    // Restore

            block.animate({'max-height': maxHeight}, 300); // Animate to max height
        }
        else {
            $(this).parent().find(".activity-description").animate({'max-height': "50px"}, 300);
        }
    });

    // Toggle for stats button
    $(".btn-show-more").click(function() {
        var caption = ["Show Less", "Show More"];
        var current = $(this).text() == caption[0] ? 1 : 0;
        $(this).text(caption[current]);
    });

    // Fixes positioning of user and group autocomplete input.
    // Solution found here: https://github.com/yourlabs/django-autocomplete-light/issues/253#issuecomment-35863432
    yourlabs.Autocomplete.prototype.fixPosition = function (html) {
        // Make sure overflow won't hide the select
        this.input.parents().filter(function () {
            return $(this).css('overflow') === 'hidden';
        }).first().css('overflow', 'visible');

        this.box.insertAfter(this.input).css({top: 35, left: 0});
    };

    // Prevent clicking on list items dismissing the modal window
    $(".autocomplete-light-widget > input.autocomplete").each(function (i, el) {
        $(el).yourlabsAutocomplete()
            .input.bind('selectChoice', function (e, choice, autocomplete) {
            e.stopPropagation();
        });
    });

    // Can be used to obtain an element's HTML including itself and not just its content
    jQuery.fn.outerHTML = function () {
        return jQuery('
').append(this.eq(0).clone()).html();
    };
});

// Alert Types: "error", "success", "info"
// pass a duration value of -1 for persistent alerts
function customAlert(alertTitle, alertMessage, alertType, duration) {
    alertType = alertType || "success";
    var el = document.createElement("div");
    var top = 200;
    var style = "top:" + top + "px";
    var alertTypes = {
        success: {class: "alert alert-success", icon: "fa fa-check"},
        error: {class: "alert alert-danger", icon: "fa fa-exclamation-triangle"},
        info: {class: "alert alert-info", icon: "fa fa-exclamation-circle"}
    };
    el.setAttribute("style", style);
    el.setAttribute("class", "custom-alert shadow-md " + alertTypes[alertType].class);
    alertMessage = ' '
        + alertTitle + '
' + alertMessage;
    el.innerHTML = alertMessage;
    if (duration !== -1) {
        setTimeout(function () {
            $(el).fadeOut(300, function () {
                $(this).remove();
            });
        }, duration);
    }
    $(el).appendTo("body > .main-container > .container");
    $(el).hide().fadeIn(400);
}
<commit_msg>[#4215] profile alert dismissable<commit_after>(function ($) {
    // Used to instantiate clickable urls in dynamically generated items
    $.fn.urlClickable = function () {
        var item = $(this);

        if (item.find(".isUrlClickable").length) {
            return this;    // Items already initiated
        }

        var originalText = item.text().trim();
        var newText = originalText;

        // Regular expression to find FTP, HTTP(S) and email URLs.
        var regexToken = /(((ftp|https?):\/\/)[\-\w@:%_\+.~#?,&\/\/=]+)|((mailto:)?[_.\w-]+@([\w][\w\-]+\.)+[a-zA-Z]{2,3})/g;

        // Extract all URL occurrences
        var matchArray;
        var urls = [];

        while ((matchArray = regexToken.exec(originalText)) !== null) {
            if (matchArray[0].slice(-1) === "." || matchArray[0].slice(-1) === ",") {
                urls.push(matchArray[0].slice(0, -1))
            }
            else {
                urls.push(matchArray[0]);
            }
        }

        // Get a list of unique URLs
        var uniqueUrls = [];
        $.each(urls, function (i, el) {
            if ($.inArray(el, uniqueUrls) === -1) {
                uniqueUrls.push(el);
            }
        });

        // Replace all URLs for links
        for (var i = 0; i < uniqueUrls.length; i++) {
            var currentUrl = uniqueUrls[i];

            var replacedString = "" +
                "" + currentUrl + "";

            var regex = new RegExp(currentUrl, "g");
            newText = newText.replace(regex, replacedString);
        }

        $(this).html(newText);

        return item;
    }
})(jQuery);

// Formats dates from "yyyy-mm-dd" to "mm/dd/yyyy"
(function ($) {
    $.fn.formatDate = function () {
        var item = $(this);
        var dateString = item.attr("data-date").trim().substr(0, 10).split("-");    // original format: yyyy-mm-dd (10 characters)
        var formattedDate = dateString[1] + "/" + dateString[2] + "/" + dateString[0];
        item.text(formattedDate);

        return item;
    }
})(jQuery);

$(document).ready(function () {
    // Search box toggle
    // =================
    $('#search-btn').on('click', function () {
        $("#search-icon").toggleClass('fa-times margin-2');
        $("#search-box").toggleClass('display-block animated fadeInUp');
    });

    // Smooth scrolling for UI elements page
    // =====================================

    $('a[href*=#buttons],a[href*=#panels], a[href*=#info-boards], a[href*=#navs], a[href*=#alerts], a[href*=#thumbnails], a[href*=#social], a[href*=#section-header],a[href*=#page-tip], a[href*=#block-header]').bind("click", function (e) {
        var anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $(anchor.attr('href')).offset().top
        }, 1000);
        e.preventDefault();
    });

    // 404 error page
    // ====================
    $('#search-404').on('click', function () {
        $("#smile").removeClass("fa-meh-o");
        $("#smile").addClass("fa-smile-o");
    });

    // Sign up popovers
    // ================
    $(function () {
        $('#exampleInputName1').popover();
    });

    $(function () {
        $('#exampleInputUsername1').popover();
    });

    $(function () {
        $('#exampleInputEmail1').popover();
    });

    $(function () {
        $('#exampleInputPassword1').popover();
    });

    $(function () {
        $('#exampleInputPassword2').popover();
    });

    // Profile - Status Update
    // =======================

    $('#update-status').on('click', function () {
        $(".user-status > p").toggleClass("show hidden");
        $(".user-status > form").toggleClass("hidden show");
        return false;
    });

    $('.user-status > form > button').on('click', function () {
        $(".user-status > p").toggleClass("show hidden");
        $(".user-status > form").toggleClass("hidden show");
        return false;
    });

    // Lost password form
    //===================

    $('.pwd-lost > .pwd-lost-q > a').on('click', function () {
        $(".pwd-lost > .pwd-lost-q").toggleClass("show hidden");
        $(".pwd-lost > .pwd-lost-f").toggleClass("hidden show");
        return false;
    });

    // Prevents nav dropdowns from closing when clicking on elements inside
    $('#hs-nav-bar .dropdown-menu').on('click', function (e) {
        e.stopPropagation();
    });

	// Close buttons for notification messages
	$(".btn-close-message").click(function() {
		$(this).parent().parent().parent().parent().hide(400);
	});

	// Initialize tooltips
	$('[data-toggle="tooltip"]').tooltip();

    // Format the dates before displaying them
    $(".format-date").each(function () {
        $(this).formatDate();
    });

    function popup_profile_alert(uid, fields) {
        if ($("#publish").length) {
                $("#publish").toggleClass("disabled", true);
                $("#publish").removeAttr("data-toggle");   // Disable the agreement modal
                $("#publish > [data-toggle='tooltip']").attr("data-original-title",
                    "Your profile information must be complete before you can formally publish resources.");
            }
            missing_field_str = fields.join(', ')

            var message = 'Your profile is nearly complete. Please fill in the '
                + '' + missing_field_str + ' fields'
                + ' on the User Profile page';

            customAlert("Profile", message, "info", 10000, true);
    }

    $.ajax({
        url: "/hsapi/userInfo/",
        success: function(user) {
            var missing_profile_fields = [];
            if(!user.organization)
                missing_profile_fields.push('Organization')
            if(!user.state)
                missing_profile_fields.push('State')
            if(!user.country)
                missing_profile_fields.push('Country')
            if(!user.user_type)
                missing_profile_fields.push('User Type')
            if(missing_profile_fields.length) {
                // Disable publishing resources
                popup_profile_alert(user.id, missing_profile_fields)
            }
        },
        error: function(response) {
            console.log(response);
        }
    });

    $(".author-preview").click(function() {
        resetAuthorPreview();
        var preview = $("#view-author-modal");
        var data = jQuery.extend(true, {}, $(this).data());
        var identifiers = ["googlescholarid", "orcid", "researchgateid", "researcerid"];
        var fields = ["name", "organization", "email", "address", "phone"];

        // If entry is an organization, hide name and profile rows
        preview.find("[data-name]").closest("tr").toggleClass("hidden", !data["name"]);
        preview.find("[data-profileurl]").closest("tr").toggleClass("hidden", !data["profileurl"]);

        // Populate profile url
        if (data["profileurl"]) {
            preview.find("[data-profileurl]").attr("href", data["profileurl"]);
        }
        delete data["profileurl"];

        // Populate homepage url
        if (data["homepage"]) {
            preview.find("[data-homepage]").attr("href", data["homepage"]);
            preview.find("[data-homepage]").text(data["homepage"]);
            preview.find("[data-homepage]").show();
        }
        delete data["homepage"];

        // Populate rest of the fields
        for (var item in data) {
            if ($.inArray(item, fields) != -1) {
                var content = data[item];
                var field = preview.find("[data-" + item + "]");
                field.text(content);
            }
            else if ($.inArray(item, identifiers) != -1) {
                var ident = preview.find("[data-" + item + "]");
                ident.show();
                preview.find(".externalprofiles-wrapper").show();
                ident.attr("href", data[item]);
            }
        }
    });

    function resetAuthorPreview(){
        var preview = $("#view-author-modal");
        preview.find(".identifier-icon").hide();
        preview.find("[data-name]").parent().show();
        preview.find("[data-profileurl]").parent().show();
    }

    $(".submenu-trigger").click(function (e) {
        $(this).next('ul').toggle();
        e.stopPropagation();
        e.preventDefault();
    });

    // Abstract collapse toggle
    $(".toggle-abstract").click(function () {
        if ($(this).parent().find(".activity-description").css("max-height") == "50px") {
            var block = $(this).parent().find(".activity-description");

            block.css("max-height", "initial"); // Set max-height to initial temporarily.
            var maxHeight = block.height();    // Save the max height
            block.css("max-height", "50px");    // Restore

            block.animate({'max-height': maxHeight}, 300); // Animate to max height
        }
        else {
            $(this).parent().find(".activity-description").animate({'max-height': "50px"}, 300);
        }
    });

    // Toggle for stats button
    $(".btn-show-more").click(function() {
        var caption = ["Show Less", "Show More"];
        var current = $(this).text() == caption[0] ? 1 : 0;
        $(this).text(caption[current]);
    });

    // Fixes positioning of user and group autocomplete input.
    // Solution found here: https://github.com/yourlabs/django-autocomplete-light/issues/253#issuecomment-35863432
    yourlabs.Autocomplete.prototype.fixPosition = function (html) {
        // Make sure overflow won't hide the select
        this.input.parents().filter(function () {
            return $(this).css('overflow') === 'hidden';
        }).first().css('overflow', 'visible');

        this.box.insertAfter(this.input).css({top: 35, left: 0});
    };

    // Prevent clicking on list items dismissing the modal window
    $(".autocomplete-light-widget > input.autocomplete").each(function (i, el) {
        $(el).yourlabsAutocomplete()
            .input.bind('selectChoice', function (e, choice, autocomplete) {
            e.stopPropagation();
        });
    });

    // Can be used to obtain an element's HTML including itself and not just its content
    jQuery.fn.outerHTML = function () {
        return jQuery('
').append(this.eq(0).clone()).html();
    };
});

// Alert Types: "error", "success", "info"
// pass a duration value of -1 for persistent alerts
function customAlert(alertTitle, alertMessage, alertType, duration, dismissable=false) {
    alertType = alertType || "success";
    var el = document.createElement("div");
    var top = 200;
    var style = "top:" + top + "px";
    var alertTypes = {
        success: {class: "alert alert-success", icon: "fa fa-check"},
        error: {class: "alert alert-danger", icon: "fa fa-exclamation-triangle"},
        info: {class: "alert alert-info", icon: "fa fa-exclamation-circle"}
    };
    el.setAttribute("style", style);
    el.setAttribute("class", "custom-alert shadow-md " + alertTypes[alertType].class);
    alertMessage = ' '
        + alertTitle + '
' + alertMessage;
    if(dismissable){
        alertMessage = '<button type="button" class="close" data-dismiss="alert" aria-label="Close">×</button> ' + alertMessage;
        el.classList.add("alert-dissmissable");
    }
    el.innerHTML = alertMessage;
    if (duration !== -1) {
        setTimeout(function () {
            $(el).fadeOut(300, function () {
                $(this).remove();
            });
        }, duration);
    }
    $(el).appendTo("body > .main-container > .container");
    $(el).hide().fadeIn(400);
}
<|endoftext|>


<commit_before>var colors;

var plantCoords = [
  {"lat": 14.446363, "longi" : -87.265564, "name":"Agalteca", "code":"aga"},
  {"lat": 13.852931, "longi" : -86.685029, "name":"Alauca","code":"ala"},
  {"lat": 14.929551, "longi" : -88.490029, "name":"Atima", "code":"ati"},
  {"lat": 14.248744, "longi" : -87.412891, "name":"Cuatro Comunidades", "code":"ccom"},
  {"lat": 14.492795, "longi" : -87.977579, "name":"Jesus de Otoro", "code":"doto"},
  {"lat": 14.156052, "longi" : -88.036309, "name":"Marcala", "code":"mar1"},
  {"lat": 14.123442, "longi" : -86.869707, "name":"Moroceli", "code":"moro"},
  {"lat": 13.980974, "longi" : -86.623315, "name":"San Matias", "code":"smat"},
  {"lat": 15.000367, "longi" : -88.731957, "name":"San Nicolas", "code":"snic"},
  {"lat": 14.189934, "longi" : -87.331426, "name":"Tamara", "code":"tam"}
];

var units = {
 "raw_turb":"NTU",
 "settled_turb":"NTU",
 "coagulant":"mg/L",
 "flow_rate":"L/s",
};

var prettyNames = {
 "raw_turb":"Raw Turbidity",
 "settled_turb":"Settled Turbidity",
 "coagulant":"Coagulant",
 "flow_rate":"Flow Rate",
};

//Hardcoded to just be Moroceli for now...
var codeList = ["moro"]; //list of currently chosen plants (by code)

var data;
var svg;
var plantDataDict = {};
/* Create plot .........................................................*/
var height = 350;
var width = 290;
var plot_padding_right = 42;
var plot_padding_left = 42;
var plot_padding_bottom = 62;
var plot_padding_top = 20;

// Attempt to get the data stored locally
function getData(onSuccess) {
  // Try to get locally
  data = retrieveAllPlantData();
  // If not locally stored, prompt the user? Maybe check date and say "data since xx/xx/xxxx displayed?"
  if (data == null) {
    updatePlantData(onSuccess);
  }
}

function visualize(data) {
  // data =rows;
  console.log(data)
  data = data.sort(sortByDateAscending);
  /* Nest and display data ...............................................*/

  //Sort array by plant
  var plantData = d3.nest()
    .key(function(d) { return d.code; })
    .entries(data);

  //Associative array
  plantData.forEach(function(plant){
    plantDataDict[plant.key] = plant.values;
  });

  //D3 Color Scale using 20 distinct colors
  //Get the 11 dimensions
  var dataFields = Object.keys(plantDataDict[Object.keys(plantDataDict)[0]][0]);
  dataFields.splice(0,1); //Assumes pid is first and gets rid of it
  colors = d3.scale.category10().domain( dataFields );

  svg = d3.select("#plot").append("svg")
    .attr("height", height)
    .attr("width", width);

  /* Create and draw axes ................................................*/
  var xScale; var yScale; var xAxis; var yAxis0;

  drawPlot("moro", ["raw_turb"]);
}

/* Sort input data by date .............................................*/
function sortByDateAscending(a, b) {
  // Dates will be cast to numbers automagically:
  return new Date(a.date_submitted) - new Date(b.date_submitted);
}

makeXScale = function(data){
  //Can take first and last because they are already sorted
  var xMin = new Date(data[0].date_submitted);
  var xMax = new Date(data[data.length-1].date_submitted);
  xScale = d3.time.scale()
    .domain([xMin, xMax])
    .range([plot_padding_left, width-plot_padding_right]);
  return xScale;
}

drawXAxis = function(xScale){
  var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom");

  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate("+0+", " + (height-plot_padding_bottom) + ")")
    .call(xAxis)
    .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", ".15em")
      .attr("transform", function(d) {
          return "rotate(-65)"
          });
  svg.append("text")
    .attr("class", "x label")
    .attr("text-anchor", "middle")
    .attr("x", (width- plot_padding_left - plot_padding_right)/2.0 + plot_padding_left)
    .attr("y", height - 6)
    .text("Time");
}

makeYScale = function(data, attr_name){
  var yScale = d3.scale.linear()
    .domain([0, d3.max(data, function (d) {return d[attr_name]; })])
    .range([height-plot_padding_bottom, plot_padding_top]);
  return yScale;
}

drawYAxis = function(yScale, attr_name){
  var yAxis = d3.svg.axis().scale(yScale).orient("left");
  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + plot_padding_left + ", "+ 0+")")
    .call(yAxis);

  svg.append("text")
    .attr("class", "y label 1")
    .attr("text-anchor", "middle")
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90) translate("+ (-(height - plot_padding_top - plot_padding_bottom)/2.0 - plot_padding_top) +" 3)")

    .text( prettyNames[attr_name] + " (" + units[attr_name] + ")");
}

drawSecondYAxis = function(yScale, attr_name){
  var yAxis = d3.svg.axis().scale(yScale).orient("right");
  svg.append("g")
    .attr("class", "axis")
    .attr("id", "secondaxis")
    .attr("transform", "translate(" + (width - plot_padding_right) + ", "+ 0+")")
    .call(yAxis);

  svg.append("text")
    .attr("class", "y label 2")
    .attr("text-anchor", "middle")
    .attr("dy", ".75em")
    .attr("transform", "rotate(-270) translate( "+((height - plot_padding_bottom - plot_padding_top)/2.0 + plot_padding_top) +" "+(-width+3)+")")
    .text( prettyNames[attr_name] + " (" + units[attr_name] + ")");
}

/* Make the line graph .................................................*/
function drawLines(data, xScale, yScale, attr_name, codeList){
  var lineGen = d3.svg.line()
    .x(function(d) {
        return xScale(new Date(d.date_submitted));
    })
    .y(function(d) {
        return yScale(d[attr_name]);
    })
    .defined(function(d) {
      return !isNaN(d[attr_name]);
    });

  //Draw the line graph for each plant with code in codelist
  svg.selectAll("#linegraphline"+attr_name).remove();

  //Check if this code was selected in order to draw it
  plantCode = data[0].code;

  if ($.inArray(plantCode, codeList)>-1){
    svg.append('g').append("path")
      .attr('d', lineGen(data))
      .attr('stroke', function(){
        return colors(attr_name);
      })
      .attr('stroke-width', 2)
      .attr('fill', 'none')
      .attr("id", "linegraphline"+attr_name);
  }
}

/* code =
 * selectedList = len 1 or 2 of checkboxes that have been checked
 */
function drawPlot(code, selectedList){
  svg.selectAll(".axis").remove();
  svg.selectAll("path").remove();
  svg.selectAll("text").remove();

  xScale = makeXScale(plantDataDict[code]);
  drawXAxis(xScale);

  if (selectedList.length>=1){
    attr1 = selectedList[0];

    if (selectedList.length==2 && selectedList[0].substr(selectedList[0].length - 4) == "turb"
        && (selectedList[1].substr(selectedList[1].length - 4) == "turb")){
      yScale = makeYScale(plantDataDict[code], 'raw_turb');
    }else{
      yScale = makeYScale(plantDataDict[code], attr1);
    }
    drawYAxis(yScale, attr1);
    drawLines(plantDataDict[code], xScale, yScale, attr1, codeList);

    //Double axes part of plot
    if (selectedList.length==2){
      attr2 = selectedList[1];
      if (selectedList[0].substr(selectedList[0].length - 4) == "turb"
        && (selectedList[1].substr(selectedList[1].length - 4) == "turb")){
        yScale2 = makeYScale(plantDataDict[code], 'raw_turb');
      }else{
        yScale2 = makeYScale(plantDataDict[code], attr2);
      }
      drawSecondYAxis(yScale2, attr2);
      drawLines(plantDataDict[code], xScale, yScale2, attr2, codeList);
    }
  }
}

$(document).ready(function() {
  getData(visualize);
  var matches = ["raw_turb"];
  $(".filled-in").on("click", function() {
    if ($.inArray(this.value, matches)==-1){
      matches.push(this.value);
    }else{
      ind = matches.indexOf(this.value);
      matches.splice(ind,1);
    }

    if (matches.length == 3){
      removed = matches.shift();
      $(".filled-in").prop("checked", false);

    }
    matches.forEach(function(m){
      $('#'+m).prop("checked", true);

    });
    drawPlot("moro", matches);
  });
});

//Wouldn't it be cool if they could sweep a vertical bar over the data and
//see what the exact values were?<commit_msg>check if data list is empty rather than null<commit_after>var colors;

var plantCoords = [
  {"lat": 14.446363, "longi" : -87.265564, "name":"Agalteca", "code":"aga"},
  {"lat": 13.852931, "longi" : -86.685029, "name":"Alauca","code":"ala"},
  {"lat": 14.929551, "longi" : -88.490029, "name":"Atima", "code":"ati"},
  {"lat": 14.248744, "longi" : -87.412891, "name":"Cuatro Comunidades", "code":"ccom"},
  {"lat": 14.492795, "longi" : -87.977579, "name":"Jesus de Otoro", "code":"doto"},
  {"lat": 14.156052, "longi" : -88.036309, "name":"Marcala", "code":"mar1"},
  {"lat": 14.123442, "longi" : -86.869707, "name":"Moroceli", "code":"moro"},
  {"lat": 13.980974, "longi" : -86.623315, "name":"San Matias", "code":"smat"},
  {"lat": 15.000367, "longi" : -88.731957, "name":"San Nicolas", "code":"snic"},
  {"lat": 14.189934, "longi" : -87.331426, "name":"Tamara", "code":"tam"}
];

var units = {
 "raw_turb":"NTU",
 "settled_turb":"NTU",
 "coagulant":"mg/L",
 "flow_rate":"L/s",
};

var prettyNames = {
 "raw_turb":"Raw Turbidity",
 "settled_turb":"Settled Turbidity",
 "coagulant":"Coagulant",
 "flow_rate":"Flow Rate",
};

//Hardcoded to just be Moroceli for now...
var codeList = ["moro"]; //list of currently chosen plants (by code)

var data;
var svg;
var plantDataDict = {};
/* Create plot .........................................................*/
var height = 350;
var width = 290;
var plot_padding_right = 42;
var plot_padding_left = 42;
var plot_padding_bottom = 62;
var plot_padding_top = 20;
/* Create and draw axes ................................................*/
var xScale; var yScale; var xAxis; var yAxis0;
var xMin;
var xMax;

// Attempt to get the data stored locally
function getData(onSuccess) {
  // Try to get locally
  data = retrieveAllPlantData();
  // If not locally stored, prompt the user? Maybe check date and say "data since xx/xx/xxxx displayed?"
  if (data.length == 0) {
    updatePlantData(onSuccess);
  }
}

function visualize(data) {
  // data =rows;
  console.log(data)
  data = data.sort(sortByDateAscending);
  /* Nest and display data ...............................................*/

  //Sort array by plant
  var plantData = d3.nest()
    .key(function(d) { return d.code; })
    .entries(data);

  //Associative array
  plantData.forEach(function(plant){
    plantDataDict[plant.key] = plant.values;
  });

  //D3 Color Scale using 20 distinct colors
  //Get the 11 dimensions
  var dataFields = Object.keys(plantDataDict[Object.keys(plantDataDict)[0]][0]);
  dataFields.splice(0,1); //Assumes pid is first and gets rid of it
  colors = d3.scale.category10().domain( dataFields );

  svg = d3.select("#plot").append("svg")
    .attr("height", height)
    .attr("width", width);

  drawPlot("moro", ["raw_turb"]);
}

/* Sort input data by date .............................................*/
function sortByDateAscending(a, b) {
  // Dates will be cast to numbers automagically:
  return new Date(a.date_submitted) - new Date(b.date_submitted);
}

makeXScale = function(data){
  //Can take first and last because they are already sorted
  xMin = new Date(data[0].date_submitted);
  xMax = new Date(data[data.length-1].date_submitted);
  xScale = d3.time.scale()
    .domain([xMin, xMax])
    .range([plot_padding_left, width-plot_padding_right]);
  return xScale;
}

drawXAxis = function(xScale){
  var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom");

  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate("+0+", " + (height-plot_padding_bottom) + ")")
    .call(xAxis)
    .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", ".15em")
      .attr("transform", function(d) {
          return "rotate(-65)"
          });
  svg.append("text")
    .attr("class", "x label")
    .attr("text-anchor", "middle")
    .attr("x", (width- plot_padding_left - plot_padding_right)/2.0 + plot_padding_left)
    .attr("y", height - 6)
    .text("Time");
}

makeYScale = function(data, attr_name){
  var yScale = d3.scale.linear()
    .domain([0, d3.max(data, function (d) {return d[attr_name]; })])
    .range([height-plot_padding_bottom, plot_padding_top]);
  return yScale;
}

drawYAxis = function(yScale, attr_name){
  var yAxis = d3.svg.axis().scale(yScale).orient("left");
  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + plot_padding_left + ", "+ 0+")")
    .call(yAxis);

  svg.append("text")
    .attr("class", "y label 1")
    .attr("text-anchor", "middle")
    .attr("dy", ".75em")
    .attr("transform", "rotate(-90) translate("+ (-(height - plot_padding_top - plot_padding_bottom)/2.0 - plot_padding_top) +" 3)")

    .text( prettyNames[attr_name] + " (" + units[attr_name] + ")");
}

drawSecondYAxis = function(yScale, attr_name){
  var yAxis = d3.svg.axis().scale(yScale).orient("right");
  svg.append("g")
    .attr("class", "axis")
    .attr("id", "secondaxis")
    .attr("transform", "translate(" + (width - plot_padding_right) + ", "+ 0+")")
    .call(yAxis);

  svg.append("text")
    .attr("class", "y label 2")
    .attr("text-anchor", "middle")
    .attr("dy", ".75em")
    .attr("transform", "rotate(-270) translate( "+((height - plot_padding_bottom - plot_padding_top)/2.0 + plot_padding_top) +" "+(-width+3)+")")
    .text( prettyNames[attr_name] + " (" + units[attr_name] + ")");
}

/* Make the line graph .................................................*/
function drawLines(data, xScale, yScale, attr_name, codeList){
  var lineGen = d3.svg.line()
    .x(function(d) {
        return xScale(new Date(d.date_submitted));
    })
    .y(function(d) {
        return yScale(d[attr_name]);
    })
    .defined(function(d) {
      return !isNaN(d[attr_name]);
    });

  //Draw the line graph for each plant with code in codelist
  svg.selectAll("#linegraphline"+attr_name).remove();

  //Check if this code was selected in order to draw it
  plantCode = data[0].code;

  if ($.inArray(plantCode, codeList)>-1){
    svg.append('g').append("path")
      .attr('d', lineGen(data))
      .attr('stroke', function(){
        return colors(attr_name);
      })
      .attr('stroke-width', 2)
      .attr('fill', 'none')
      .attr("id", "linegraphline"+attr_name);
  }
}

/* code =
 * selectedList = len 1 or 2 of checkboxes that have been checked
 */
function drawPlot(code, selectedList){
  svg.selectAll(".axis").remove();
  svg.selectAll("path").remove();
  svg.selectAll("text").remove();

  xScale = makeXScale(plantDataDict[code]);
  drawXAxis(xScale);

  if (selectedList.length>=1){
    attr1 = selectedList[0];

    if (selectedList.length==2 && selectedList[0].substr(selectedList[0].length - 4) == "turb"
        && (selectedList[1].substr(selectedList[1].length - 4) == "turb")){
      yScale = makeYScale(plantDataDict[code], 'raw_turb');
    }else{
      yScale = makeYScale(plantDataDict[code], attr1);
    }
    drawYAxis(yScale, attr1);
    drawLines(plantDataDict[code], xScale, yScale, attr1, codeList);

    //Double axes part of plot
    if (selectedList.length==2){
      attr2 = selectedList[1];
      if (selectedList[0].substr(selectedList[0].length - 4) == "turb"
        && (selectedList[1].substr(selectedList[1].length - 4) == "turb")){
        yScale2 = makeYScale(plantDataDict[code], 'raw_turb');
      }else{
        yScale2 = makeYScale(plantDataDict[code], attr2);
      }
      drawSecondYAxis(yScale2, attr2);
      drawLines(plantDataDict[code], xScale, yScale2, attr2, codeList);
    }
  }
}

$(document).ready(function() {
  getData(visualize);
  var matches = ["raw_turb"];
  $(".filled-in").on("click", function() {
    if ($.inArray(this.value, matches)==-1){
      matches.push(this.value);
    }else{
      ind = matches.indexOf(this.value);
      matches.splice(ind,1);
    }

    if (matches.length == 3){
      removed = matches.shift();
      $(".filled-in").prop("checked", false);

    }
    matches.forEach(function(m){
      $('#'+m).prop("checked", true);

    });
    drawPlot("moro", matches);
  });
});

//Wouldn't it be cool if they could sweep a vertical bar over the data and
//see what the exact values were?<|endoftext|>


<commit_before>/*
 * 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.
 */
var app = {
    // Application Constructor
    state: "startAppNoRotate",

    initialize: function() {
        this.bindEvents();
        //    alert("goingState =" +  app.goingState);
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', app.onDeviceReady, false);
        //    alert ("Первый Eventlistener");
        document.addEventListener('online', app.onOnline, false);
        document.addEventListener('offline', app.onOffline, false);
        //    alert("Еще два листенера");

    },
    // deviceready Event Handler

    onDeviceReady: function() {

        /*    function onOffline(){
         app.goingState = "no-internet";
         //   app.stopRotation();
         alert("Keine Internet Verbindung!");
         }

         function onOnline(){
         app.goingState = "connected";
         //   app.stopRotation();
         alert("Verbinden!");
         }
         */
        //   alert(app.goingState);
        if (app.onOnline() == true) {
            //     alert(app.goingState);
        //    var ref = cordova.InAppBrowser.open('http://v2.pizza-web.de/', '_system', 'location=no,hidden=yes,closebuttoncaption=Done,toolbar=no');
            app.goingState = "loading";
            var loadStopCallback = function (event) {
                //     alert('stop: ' + event.url);
                // setTimeout(function(){ app.stopRotation()},40);
                app.stopRotation();
                ref.show();
                app.goingState = "show-shop";
            }
            ref.addEventListener('loadstop', loadStopCallback);
        }

    },

    stopRotation: function(){
        //    alert("Попали в stopRotation");
        //    app.goingState = "stopped";
        var circularProgressContainer = document.querySelector('#circular-progress');
        circularProgressContainer.classList.remove("visible");
        circularProgressContainer.classList.add("not-visible");
    },

    startRotation: function(){
        var circularProgressContainer = document.querySelector('#circular-progress');
        circularProgressContainer.classList.remove("not-visible");
        circularProgressContainer.classList.add("visible");
    },

    onOffline: function(){
        app.goingState = "no-internet";
        app.stopRotation();
        alert("Leider gibt es keine Internetverbindung.  Die Bestellung konnte nicht aufgegeben werden. Schließen Sie bitee die App um später zu probieren.");
        var noInternetMsgContainer = document.querySelector('#no-internet-msg-container');
        noInternetMsgContainer.classList.remove("not-visible");
        noInternetMsgContainer.classList.add("visible");
    },

    onOnline: function(){
        app.goingState = "connected";
        //  app.startRotation();
        //    alert("Verbinden!");
        var noInternetMsgContainer = document.querySelector('#no-internet-msg-container');
        noInternetMsgContainer.classList.remove("visible");
        noInternetMsgContainer.classList.add("not-visible");
        return true;
    },

    get goingState() {
        return this.state;
    },

    set goingState(value){
        this.state = value;
        //   alert("Только что присвоили state = " + this.state)
    },

};
<commit_msg>Changes 190616 1703<commit_after>/*
 * 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.
 */
var app = {
    // Application Constructor
    state: "startAppNoRotate",

    initialize: function() {
        this.bindEvents();
        //    alert("goingState =" +  app.goingState);
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', app.onDeviceReady, false);
        //    alert ("Первый Eventlistener");
        document.addEventListener('online', app.onOnline, false);
        document.addEventListener('offline', app.onOffline, false);
        //    alert("Еще два листенера");

    },
    // deviceready Event Handler

    onDeviceReady: function() {

        /*    function onOffline(){
         app.goingState = "no-internet";
         //   app.stopRotation();
         alert("Keine Internet Verbindung!");
         }

         function onOnline(){
         app.goingState = "connected";
         //   app.stopRotation();
         alert("Verbinden!");
         }
         */
        //   alert(app.goingState);
        if (app.onOnline() == true) {
            //     alert(app.goingState);
            var ref = cordova.InAppBrowser.open('http://v2.pizza-web.de/', '_system', 'location=no,hidden=yes,closebuttoncaption=Done,toolbar=no');
            app.goingState = "loading";
            var loadStopCallback = function (event) {
                //     alert('stop: ' + event.url);
                // setTimeout(function(){ app.stopRotation()},40);
                app.stopRotation();
                ref.show();
                app.goingState = "show-shop";
            }
            ref.addEventListener('loadstop', loadStopCallback);
        }

    },

    stopRotation: function(){
        //    alert("Попали в stopRotation");
        //    app.goingState = "stopped";
        var circularProgressContainer = document.querySelector('#circular-progress');
        circularProgressContainer.classList.remove("visible");
        circularProgressContainer.classList.add("not-visible");
    },

    startRotation: function(){
        var circularProgressContainer = document.querySelector('#circular-progress');
        circularProgressContainer.classList.remove("not-visible");
        circularProgressContainer.classList.add("visible");
    },

    onOffline: function(){
        app.goingState = "no-internet";
        app.stopRotation();
        alert("Leider gibt es keine Internetverbindung.  Die Bestellung konnte nicht aufgegeben werden. Schließen Sie bitee die App um später zu probieren.");
        var noInternetMsgContainer = document.querySelector('#no-internet-msg-container');
        noInternetMsgContainer.classList.remove("not-visible");
        noInternetMsgContainer.classList.add("visible");
    },

    onOnline: function(){
        app.goingState = "connected";
        //  app.startRotation();
        //    alert("Verbinden!");
        var noInternetMsgContainer = document.querySelector('#no-internet-msg-container');
        noInternetMsgContainer.classList.remove("visible");
        noInternetMsgContainer.classList.add("not-visible");
        return true;
    },

    get goingState() {
        return this.state;
    },

    set goingState(value){
        this.state = value;
        //   alert("Только что присвоили state = " + this.state)
    },

};
<|endoftext|>


<commit_before>/*
 * 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.
 */
var app = {
    initialize: function() {
        this.bind();
    },
    bind: function() {
        document.addEventListener('deviceready', this.deviceready, false);
    },
    deviceready: function() {
        // This is an event handler function, which means the scope is the event.
        // So, we must explicitly called `app.report()` instead of `this.report()`.
        app.report('deviceready');
    },
    report: function(id) {
        // Report the event in the console
        console.log("Report: " + id);

        // Toggle the state from "pending" to "complete" for the reported ID.
        // Accomplished by adding .hide to the pending element and removing
        // .hide from the complete element.
        document.querySelector('#' + id + ' .pending').className += ' hide';
        var completeElem = document.querySelector('#' + id + ' .complete');
        completeElem.className = completeElem.className.split('hide').join('');
        //testing out lawnchair.js
        $(function(e) {
            var beers = Lawnchair({name:'beers'},function(e){
                console.log('storage open');
            });
            // uncomment to clear the database
            //beers.nuke();
            beers.all(function(arrBeers){
                for(var i = 0; i<arrBeers.length;i++)
                {
                    console.log(arrBeers.length);
                    var listdiv = document.createElement('li');
                        listdiv.setAttribute('id','listdiv');
                        listdiv.innerHTML = arrBeers[i].value.name;
                    $('#beer_list').append(listdiv);
                }
                $('#beer_list').listview("refresh");
            });
            function reload_list(){
                beers.all(function(arrBeers){
                    $('#beer_list').empty();
                    for(var i = 0; i<arrBeers.length;i++)
                    {
                        console.log(arrBeers.length);
                        var lyo = make_article_layout();
                        cur_a = arrBeers[i].value;
                        lyo.find("#title").text(cur_a["title"]);
                        lyo.id = cur_a["_id"];
                        lyo.find("#body").text(cur_a["body"]);
                        lyo.find("#published_at").contents(cur_a["published_at"] + " | ");
                        lyo.find("#author").contents(cur_a["author"] + " | ");
                        lyo.find("#source").contents("paper_id:"+cur_a["paper_id"]+" | "+cur_a["url"]);
                    }
                });
            }

            function inject_article(ui_container, json){
                $(ui_container).find('#body').text(json["body"]);
            }

            $('#reload_list').click(function(e){
                reload_list();
            });
            $('#count').click(function(e){
                beers.all(function(arrBeers){
                    $('#status').innerHTML(arrBeers.length+" items in the database");
                });
            });
            $('#save').click(function(e){
                var nm = $("#entry_name").val();
                var desc = $("#entry_description").val();
                var cur_key = "";
                if(nm != "" && desc != ""){
                    beers.all(function(arrBeers){
                        cur_key = arrBeers.length.toString();
                    });
                    var obj1 = {"name":nm,"description":desc};
                    beers.save({key:cur_key,value:obj1});
                }
            });
            $('#retrieve').click(function(e){
                var cur_key = "0";
                beers.all(function(arrBeers){
                    cur_key = arrBeers.length.toString();
                });
                beers.get(cur_key,function(obj){
                    var resul = JSON.stringify(obj);
                    console.log(resul);
                    alert(resul);
                });
            });
            // function initTimestamp(){
            //     //sets the time stamp to a year before now
            //     var d = new Date();
            //     d.setFullYear(d.getFullYear() - 1);
            //     obj = {};
            //     //validate that this would actually work
            //     obj["time"] = Math.round(d.valueOf() / 1000).toString();
            //     obj["cur_state"] = "FINISHED";
            //     beers.save({key:"timestamp", value:obj});
            // }
            // function checkLatest(){
            //     // the object im using will be:
            //     // "timestamp":{"time":"INT_TIME_AS_STRING", "cur_state":"STARTED/DOWNLOADING/FINISHED"}
            //     var last_update_time = "0";
            //     beers.get("timestamp",function(thisobj){
            //         console.log(JSON.stringify(thisobj));
            //         var obj = {};
            //             obj = thisobj.value;
            //             obj["cur_state"] = "STARTED";
            //         last_update_time = obj["time"]
            //         //check for null somehow
            //         //initTimestamp() if not there
            //         //done with the null case
            //         beers.save({key:thisobj.key,value:obj});
            //     });
            //     var url = latest_articles_path(last_update_time);
            //     get_latest_from_url(url, function(jsondata){
            //         //should be a json array atm
            //         $.each(jsondata, function(index, data) {
            //             var article = data;
            //             add_article_to_db(data);
            //         });
            //     });
            // }
            function latest_articles_path(timestamp_as_int){
                return "http://www.extempengine.com/articles/latest?int_time="+timestamp_as_int;
            }
            // below could be bad
            // function get_latest_from_url(url, callback_function){
            //     //wrap with callback due to same origin BS
            //     url = wrap_with_bs(url);
            //     jQuery.getJSON(url, function(data){
            //         var retval = JSON.stringify(data));
            //         console.log("via getJSON > "+retval);
            //         callback_function(data);
            //     });
            // }
            // everything below works
            function wrap_with_bs(url){
                if (url.indexOf("?") == -1) {
                    url = url + "&callback=?";
                } else {
                    url = url + "?callback=?";
                }
                return url;
            }
            function add_article_to_db(article_as_json){
                beers.save({key:article_as_json["_id"],value:article_as_json});
            }
            var article_url = "http://extempengine.com/articles/latest.js";
            $('#get_from_server').click(function(e) {
                console.log("starting article search");
                jQuery.getJSON(article_url+"?callback=?&limit=3", function(jsondata){
                    console.log("callback "+JSON.stringify(jsondata));
                    $.each(jsondata, function(index, data) {
                        //var article = data;
                        add_article_to_db(data);
                    });
                    alert("done updating articles");
                    //add_article_to_db(data);
                });
                console.log("jquery getjson was just initiated search");
            });
            // $('#initTimestamp').click(function(e) {
            //     initTimestamp();
            // });
            $('#modify').click(function(e) {
                beers.get("1",function(thisobj){
                    console.log(thisobj);
                    var obj = {};
                        obj = thisobj.value;
                        obj.name = "Modified Value";
                    beers.save({key:thisobj.key,value:obj});
                });
            });
            $('#clone_row').click(function(e) {
                make_article_layout();
            });
            function make_article_layout(){
                var template = $("#article_template");
                var cont = $("#beer_list");
                var n = template.clone();
                n.appendTo(cont);
                return n;
            }
            $("#clear_db").click(function(e){
                beers.nuke();
            });
        }); // end lawnchair shit
    }
};
<commit_msg>se7en<commit_after>/*
 * 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.
 */
var app = {
    initialize: function() {
        this.bind();
    },
    bind: function() {
        document.addEventListener('deviceready', this.deviceready, false);
    },
    deviceready: function() {
        // This is an event handler function, which means the scope is the event.
        // So, we must explicitly called `app.report()` instead of `this.report()`.
        app.report('deviceready');
    },
    report: function(id) {
        // Report the event in the console
        console.log("Report: " + id);

        // Toggle the state from "pending" to "complete" for the reported ID.
        // Accomplished by adding .hide to the pending element and removing
        // .hide from the complete element.
        document.querySelector('#' + id + ' .pending').className += ' hide';
        var completeElem = document.querySelector('#' + id + ' .complete');
        completeElem.className = completeElem.className.split('hide').join('');
        //testing out lawnchair.js
        $(function(e) {
            var beers = Lawnchair({name:'beers'},function(e){
                console.log('storage open');
            });
            // uncomment to clear the database
            //beers.nuke();
            function reload_list(){
                beers.all(function(arrBeers){
                    $('#beer_list').empty();
                    for(var i = 0; i<arrBeers.length;i++)
                    {
                        console.log(arrBeers.length);
                        var lyo = make_article_layout();
                        cur_a = arrBeers[i].value;
                        lyo.find("#title").text(cur_a["title"]);
                        lyo.id = cur_a["_id"];
                        lyo.find("#body").text(cur_a["body"]);
                        lyo.find("#published_at").contents(cur_a["published_at"] + " | ");
                        lyo.find("#author").contents(cur_a["author"] + " | ");
                        lyo.find("#source").contents("paper_id:"+cur_a["paper_id"]+" | "+cur_a["url"]);
                    }
                });
            }
            function inject_article(ui_container, json){
                $(ui_container).find('#body').text(json["body"]);
            }

            $('#reload_list').click(function(e){
                reload_list();
            });
            $('#count').click(function(e){
                beers.all(function(arrBeers){
                    $('#status').innerHTML(arrBeers.length+" items in the database");
                });
            });
            $('#save').click(function(e){
                var nm = $("#entry_name").val();
                var desc = $("#entry_description").val();
                var cur_key = "";
                if(nm != "" && desc != ""){
                    beers.all(function(arrBeers){
                        cur_key = arrBeers.length.toString();
                    });
                    var obj1 = {"name":nm,"description":desc};
                    beers.save({key:cur_key,value:obj1});
                }
            });
            $('#retrieve').click(function(e){
                var cur_key = "0";
                beers.all(function(arrBeers){
                    cur_key = arrBeers.length.toString();
                });
                beers.get(cur_key,function(obj){
                    var resul = JSON.stringify(obj);
                    console.log(resul);
                    alert(resul);
                });
            });
            // function initTimestamp(){
            //     //sets the time stamp to a year before now
            //     var d = new Date();
            //     d.setFullYear(d.getFullYear() - 1);
            //     obj = {};
            //     //validate that this would actually work
            //     obj["time"] = Math.round(d.valueOf() / 1000).toString();
            //     obj["cur_state"] = "FINISHED";
            //     beers.save({key:"timestamp", value:obj});
            // }
            // function checkLatest(){
            //     // the object im using will be:
            //     // "timestamp":{"time":"INT_TIME_AS_STRING", "cur_state":"STARTED/DOWNLOADING/FINISHED"}
            //     var last_update_time = "0";
            //     beers.get("timestamp",function(thisobj){
            //         console.log(JSON.stringify(thisobj));
            //         var obj = {};
            //             obj = thisobj.value;
            //             obj["cur_state"] = "STARTED";
            //         last_update_time = obj["time"]
            //         //check for null somehow
            //         //initTimestamp() if not there
            //         //done with the null case
            //         beers.save({key:thisobj.key,value:obj});
            //     });
            //     var url = latest_articles_path(last_update_time);
            //     get_latest_from_url(url, function(jsondata){
            //         //should be a json array atm
            //         $.each(jsondata, function(index, data) {
            //             var article = data;
            //             add_article_to_db(data);
            //         });
            //     });
            // }
            function latest_articles_path(timestamp_as_int){
                return "http://www.extempengine.com/articles/latest?int_time="+timestamp_as_int;
            }
            // below could be bad
            // function get_latest_from_url(url, callback_function){
            //     //wrap with callback due to same origin BS
            //     url = wrap_with_bs(url);
            //     jQuery.getJSON(url, function(data){
            //         var retval = JSON.stringify(data));
            //         console.log("via getJSON > "+retval);
            //         callback_function(data);
            //     });
            // }
            // everything below works
            function wrap_with_bs(url){
                if (url.indexOf("?") == -1) {
                    url = url + "&callback=?";
                } else {
                    url = url + "?callback=?";
                }
                return url;
            }
            function add_article_to_db(article_as_json){
                beers.save({key:article_as_json["_id"],value:article_as_json});
            }
            var article_url = "http://extempengine.com/articles/latest.js";
            $('#get_from_server').click(function(e) {
                console.log("starting article search");
                jQuery.getJSON(article_url+"?callback=?&limit=3", function(jsondata){
                    console.log("callback "+JSON.stringify(jsondata));
                    $.each(jsondata, function(index, data) {
                        //var article = data;
                        add_article_to_db(data);
                    });
                    alert("done updating articles");
                    //add_article_to_db(data);
                });
                console.log("jquery getjson was just initiated search");
            });
            // $('#initTimestamp').click(function(e) {
            //     initTimestamp();
            // });
            $('#modify').click(function(e) {
                beers.get("1",function(thisobj){
                    console.log(thisobj);
                    var obj = {};
                        obj = thisobj.value;
                        obj.name = "Modified Value";
                    beers.save({key:thisobj.key,value:obj});
                });
            });
            $('#clone_row').click(function(e) {
                make_article_layout();
            });
            function make_article_layout(){
                var template = $("#article_template");
                var cont = $("#beer_list");
                var n = template.clone();
                n.appendTo(cont);
                return n;
            }
            $("#clear_db").click(function(e){
                beers.nuke();
            });
            reload_list();
        }); // end lawnchair shit
    }
};
<|endoftext|>