<commit_before>//global services go here
angular.module( 'omniwallet' ).factory('userService', ['$rootScope', '$http', function ($rootScope, $http) {
  var service = {
    data: {
      walletKey: '',
      wallet : {},
      loggedIn: false
    },

    login: function(wallet, walletKey) {
      service.data.walletKey = walletKey;
      service.data.wallet = wallet;
      service.data.loggedIn = true;
    },

    logout: function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
      localStorage.clear();
    },

    addAddress: function( address, privKey ) {
      for( var i in service.data.wallet.addresses )
      {
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      }
      service.data.wallet.addresses.push( {
        "address": address,
        "privkey": privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
    },

    getAddress: function(address) {
      for(var i in service.data.wallet.addresses) {
        if(service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses: function () {
      return service.data.wallet.addresses;
    },

    getWallet: function() {
      return service.data.wallet;
    },

    getUUID: function() {
      return service.data.wallet.uuid;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    syncWallet: function() {
      // Strange serialization effects, stringifying wallet initially
      var postData = {
        type: 'SYNCWALLET',
        wallet: JSON.stringify(service.data.wallet)
      };
      return $http({
        url: '/v1/user/wallet/sync/',
        method: 'POST',
        data: postData,
        headers: {'Content-Type': 'application/json'}
      })
    },

    updateWallet: function() {
      var uuid = service.getUUID();
      return $http.get('/flask/challenge?uuid='+uuid)
        .then(function(result) {
          var data = result.data;
          var encryptedWallet = CryptUtil.encryptObject(service.data.wallet, service.data.walletKey);
          var challenge = data.challenge;
          var signature = ""
          console.log(encryptedWallet);

          return $http({
            url: '/flask/update',
            method: 'POST',
            data: { uuid: uuid, wallet: encryptedWallet, challenge: challenge, signature: signature }
          });
        })
    },

    saveSession: function () {
      localStorage["OmniWallet"] = angular.toJson(service.data);
      // service.syncWallet().success(function() { console.log("Success saving"); });
      service.updateWallet().then(function() { console.log("Success saving") });
    },
    restoreSession: function() {
      if( localStorage[ "OmniWallet" ])
        service.data = angular.fromJson(localStorage["OmniWallet"]);
    }
  };

  // $rootScope.$watch('userService.data', function(newVal, oldVal) {
  //   console.log("watched");
  //   $rootScope.$broadcast('savestate');
  // }, true);
  $rootScope.$on("savestate", service.saveSession);
  $rootScope.$on("restorestate", service.restoreSession);

  service.restoreSession();

  return service;
}]);

angular.module( 'omniwallet' ).factory( 'appraiser', ['$rootScope', '$http', function ( $rootScope, $http ) {

  // Rewire to use localstorage
  function AppraiserService() {
    this.conversions = {};
    var self = this;
    function BtcUpdateLoop() {
      self.updateBtcValue( function() {
        setTimeout( BtcUpdateLoop, 30000 );
      } );
    }
    function MscUpdateLoop() {
      self.updateMscValue( function() {
        setTimeout( MscUpdateLoop, 600000 );
      } );
    }
    BtcUpdateLoop();
    MscUpdateLoop();
  };
  AppraiserService.prototype.updateBtcValue = function( callback ) {
    var self = this;
    $http.get( 'https://api.bitcoinaverage.com/all' ).then( function( result ) {
      // Store these things internally as the value of a satoshi.
      self.conversions.BTC = result.data.USD.averages.last / 100000000;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'BTC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateMscValue = function( callback ) {
    var self = this;
    $http.get( 'https://masterxchange.com/api/trades.php' ).then( function( result ) {
      var volume = 0;
      var sum = 0;

      for( var i=0; i<result.data.length; i++ )
      {
        volume += parseFloat( result.data[i].amount );
        sum += parseFloat( result.data[i].amount ) * parseFloat( result.data[i].price );
      }

      self.conversions.MSC = sum / volume;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'MSC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.getValue = function( amount, symbol ) {
    if( symbol == 'TMSC' )
      return 0;
    else if( symbol == 'BTC' )
    {
      if( this.conversions.BTC )
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    }
    else
    {
      if( this.conversions.MSC )
      {
        return this.getValue( this.conversions.MSC * amount, 'BTC' );
      }
      else
        return 'MSC Value Unavailable';
    }
  };

  return new AppraiserService();
}]);
<commit_msg>Update user service to store public private signing pair<commit_after>//global services go here
angular.module( 'omniwallet' ).factory('userService', ['$rootScope', '$http', function ($rootScope, $http) {
  var service = {
    data: {
      walletKey: '',
      asymKey: {},
      wallet : {},
      loggedIn: false
    },

    login: function(wallet, walletKey, asymKey) {
      service.data.walletKey = walletKey;
      service.data.asymKey = asymKey;
      service.data.wallet = wallet;
      service.data.loggedIn = true;
    },

    logout: function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
      localStorage.clear();
    },

    addAddress: function( address, privKey ) {
      for( var i in service.data.wallet.addresses )
      {
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      }
      service.data.wallet.addresses.push( {
        "address": address,
        "privkey": privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
    },

    getAddress: function(address) {
      for(var i in service.data.wallet.addresses) {
        if(service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses: function () {
      return service.data.wallet.addresses;
    },

    getWallet: function() {
      return service.data.wallet;
    },

    getUUID: function() {
      return service.data.wallet.uuid;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    syncWallet: function() {
      // Strange serialization effects, stringifying wallet initially
      var postData = {
        type: 'SYNCWALLET',
        wallet: JSON.stringify(service.data.wallet)
      };
      return $http({
        url: '/v1/user/wallet/sync/',
        method: 'POST',
        data: postData,
        headers: {'Content-Type': 'application/json'}
      })
    },

    updateWallet: function() {
      var uuid = service.getUUID();
      return $http.get('/flask/challenge?uuid='+uuid)
        .then(function(result) {
          var data = result.data;
          var encryptedWallet = CryptUtil.encryptObject(service.data.wallet, service.data.walletKey);
          var challenge = data.challenge;
          var signature = ""
          console.log(encryptedWallet);

          return $http({
            url: '/flask/update',
            method: 'POST',
            data: { uuid: uuid, wallet: encryptedWallet, challenge: challenge, signature: signature }
          });
        })
    },

    saveSession: function () {
      localStorage["OmniWallet"] = angular.toJson(service.data);
      // service.syncWallet().success(function() { console.log("Success saving"); });
      service.updateWallet().then(function() { console.log("Success saving") });
    },
    restoreSession: function() {
      if( localStorage[ "OmniWallet" ])
        service.data = angular.fromJson(localStorage["OmniWallet"]);
    }
  };

  // $rootScope.$watch('userService.data', function(newVal, oldVal) {
  //   console.log("watched");
  //   $rootScope.$broadcast('savestate');
  // }, true);
  $rootScope.$on("savestate", service.saveSession);
  $rootScope.$on("restorestate", service.restoreSession);

  service.restoreSession();

  return service;
}]);

angular.module( 'omniwallet' ).factory( 'appraiser', ['$rootScope', '$http', function ( $rootScope, $http ) {

  // Rewire to use localstorage
  function AppraiserService() {
    this.conversions = {};
    var self = this;
    function BtcUpdateLoop() {
      self.updateBtcValue( function() {
        setTimeout( BtcUpdateLoop, 30000 );
      } );
    }
    function MscUpdateLoop() {
      self.updateMscValue( function() {
        setTimeout( MscUpdateLoop, 600000 );
      } );
    }
    BtcUpdateLoop();
    MscUpdateLoop();
  };
  AppraiserService.prototype.updateBtcValue = function( callback ) {
    var self = this;
    $http.get( 'https://api.bitcoinaverage.com/all' ).then( function( result ) {
      // Store these things internally as the value of a satoshi.
      self.conversions.BTC = result.data.USD.averages.last / 100000000;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'BTC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateMscValue = function( callback ) {
    var self = this;
    $http.get( 'https://masterxchange.com/api/trades.php' ).then( function( result ) {
      var volume = 0;
      var sum = 0;

      for( var i=0; i<result.data.length; i++ )
      {
        volume += parseFloat( result.data[i].amount );
        sum += parseFloat( result.data[i].amount ) * parseFloat( result.data[i].price );
      }

      self.conversions.MSC = sum / volume;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'MSC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.getValue = function( amount, symbol ) {
    if( symbol == 'TMSC' )
      return 0;
    else if( symbol == 'BTC' )
    {
      if( this.conversions.BTC )
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    }
    else
    {
      if( this.conversions.MSC )
      {
        return this.getValue( this.conversions.MSC * amount, 'BTC' );
      }
      else
        return 'MSC Value Unavailable';
    }
  };

  return new AppraiserService();
}]);
<|endoftext|>


<commit_before>//global services go here
angular.module( 'omniwallet' ).factory('userService', ['$rootScope', '$http', function ($rootScope, $http) {
  var service = {
    data: {
      wallet : {},
      loggedIn: false
    },

    login: function(wallet) {
      service.data.wallet = wallet;
      service.data.loggedIn = true;
      service.saveSession();
    },

    logout: function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
      localStorage.clear();
    },

    addAddress: function( address, privKey ) {
      for( var i in service.data.wallet.addresses )
      {
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      }
      service.data.wallet.addresses.push( {
        "address": address,
        "privkey": privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
    },

    getAddress: function(address) {
      for(var i in service.data.wallet.addresses) {
        if(service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses: function () {
      return service.data.wallet.addresses;
    },

    getWallet: function() {
      return service.data.wallet;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    syncWallet: function() {
      // Strange serialization effects, stringifying wallet initially
      var postData = {
        type: 'SYNCWALLET',
        wallet: JSON.stringify(service.data.wallet)
      };
      return $http({
        url: '/v1/user/wallet/sync/',
        method: 'POST',
        data: postData,
        headers: {'Content-Type': 'application/json'}
      })
    },

    saveSession: function () {
      localStorage["OmniWallet"] = angular.toJson(service.data);
      service.syncWallet().success(function() { console.log("Success saving"); });
    },
    restoreSession: function() {
      if( localStorage[ "OmniWallet" ])
        service.data = angular.fromJson(localStorage["OmniWallet"]);
    }
  };

  // $rootScope.$watch('userService.data', function(newVal, oldVal) {
  //   console.log("watched");
  //   $rootScope.$broadcast('savestate');
  // }, true);
  $rootScope.$on("savestate", service.saveSession);
  $rootScope.$on("restorestate", service.restoreSession);

  service.restoreSession();

  return service;
}]);

angular.module( 'omniwallet' ).factory( 'appraiser', ['$rootScope', '$http', function ( $rootScope, $http ) {

  // Rewire to use localstorage
  function AppraiserService() {
    this.conversions = {};
    var self = this;
    function BtcUpdateLoop() {
      self.updateBtcValue( function() {
        setTimeout( BtcUpdateLoop, 30000 );
      } );
    }
    function MscUpdateLoop() {
      self.updateMscValue( function() {
        setTimeout( MscUpdateLoop, 600000 );
      } );
    }
    BtcUpdateLoop();
    MscUpdateLoop();
  };
  AppraiserService.prototype.updateBtcValue = function( callback ) {
    var self = this;
    $http.get( 'https://api.bitcoinaverage.com/all' ).then( function( result ) {
      self.conversions.BTC = result.data.USD.averages.last;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'BTC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateMscValue = function( callback ) {
    var self = this;
    $http.get( 'https://masterxchange.com/api/trades.php' ).then( function( result ) {
      var volume = 0;
      var sum = 0;

      for( var i=0; i<result.data.length; i++ )
      {
        volume += parseFloat( result.data[i].amount );
        sum += parseFloat( result.data[i].amount ) * parseFloat( result.data[i].price );
      }

      self.conversions.MSC = sum / volume;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'MSC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.getValue = function( amount, symbol ) {
    if( symbol == 'TMSC' )
      return 0;
    else if( symbol == 'BTC' )
    {
      if( this.conversions.BTC )
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    }
    else
    {
      if( this.conversions.MSC )
      {
        return this.getValue( this.conversions.MSC * amount, 'BTC' );
      }
      else
        return 'MSC Value Unavailable';
    }
  };

  return new AppraiserService();
}]);
<commit_msg>Store the conversion from BTC to USD in Satoshis.<commit_after>//global services go here
angular.module( 'omniwallet' ).factory('userService', ['$rootScope', '$http', function ($rootScope, $http) {
  var service = {
    data: {
      wallet : {},
      loggedIn: false
    },

    login: function(wallet) {
      service.data.wallet = wallet;
      service.data.loggedIn = true;
      service.saveSession();
    },

    logout: function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
      localStorage.clear();
    },

    addAddress: function( address, privKey ) {
      for( var i in service.data.wallet.addresses )
      {
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      }
      service.data.wallet.addresses.push( {
        "address": address,
        "privkey": privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
    },

    getAddress: function(address) {
      for(var i in service.data.wallet.addresses) {
        if(service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses: function () {
      return service.data.wallet.addresses;
    },

    getWallet: function() {
      return service.data.wallet;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    syncWallet: function() {
      // Strange serialization effects, stringifying wallet initially
      var postData = {
        type: 'SYNCWALLET',
        wallet: JSON.stringify(service.data.wallet)
      };
      return $http({
        url: '/v1/user/wallet/sync/',
        method: 'POST',
        data: postData,
        headers: {'Content-Type': 'application/json'}
      })
    },

    saveSession: function () {
      localStorage["OmniWallet"] = angular.toJson(service.data);
      service.syncWallet().success(function() { console.log("Success saving"); });
    },
    restoreSession: function() {
      if( localStorage[ "OmniWallet" ])
        service.data = angular.fromJson(localStorage["OmniWallet"]);
    }
  };

  // $rootScope.$watch('userService.data', function(newVal, oldVal) {
  //   console.log("watched");
  //   $rootScope.$broadcast('savestate');
  // }, true);
  $rootScope.$on("savestate", service.saveSession);
  $rootScope.$on("restorestate", service.restoreSession);

  service.restoreSession();

  return service;
}]);

angular.module( 'omniwallet' ).factory( 'appraiser', ['$rootScope', '$http', function ( $rootScope, $http ) {

  // Rewire to use localstorage
  function AppraiserService() {
    this.conversions = {};
    var self = this;
    function BtcUpdateLoop() {
      self.updateBtcValue( function() {
        setTimeout( BtcUpdateLoop, 30000 );
      } );
    }
    function MscUpdateLoop() {
      self.updateMscValue( function() {
        setTimeout( MscUpdateLoop, 600000 );
      } );
    }
    BtcUpdateLoop();
    MscUpdateLoop();
  };
  AppraiserService.prototype.updateBtcValue = function( callback ) {
    var self = this;
    $http.get( 'https://api.bitcoinaverage.com/all' ).then( function( result ) {
      // Store these things internally as the value of a satoshi.
      self.conversions.BTC = result.data.USD.averages.last / 100000000;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'BTC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateMscValue = function( callback ) {
    var self = this;
    $http.get( 'https://masterxchange.com/api/trades.php' ).then( function( result ) {
      var volume = 0;
      var sum = 0;

      for( var i=0; i<result.data.length; i++ )
      {
        volume += parseFloat( result.data[i].amount );
        sum += parseFloat( result.data[i].amount ) * parseFloat( result.data[i].price );
      }

      self.conversions.MSC = sum / volume;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'MSC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.getValue = function( amount, symbol ) {
    if( symbol == 'TMSC' )
      return 0;
    else if( symbol == 'BTC' )
    {
      if( this.conversions.BTC )
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    }
    else
    {
      if( this.conversions.MSC )
      {
        return this.getValue( this.conversions.MSC * amount, 'BTC' );
      }
      else
        return 'MSC Value Unavailable';
    }
  };

  return new AppraiserService();
}]);
<|endoftext|>


<commit_before>//global services go here
angular.module( 'omniwallet' ).factory( 'balanceService', [ '$http', '$q',
  function( $http, $q ) {
    var cache = [];
    var service = {
      balance: function( address ) {
        var currentTime = new Date().getTime();
        if( cache[ address ] && ( currentTime - cache[ address ].timestamp ) < 60000 )
          return cache[ address ].deferred.promise;
        else
        {
          var deferred = $q.defer();
          cache[ address ] = {
            deferred: deferred,
            timestamp: currentTime
          }
          $http.post( '/v1/address/addr/', { 'addr': address } )
            .success( function( result ) {
              deferred.resolve( { data: result } );
            }).error ( function( error ) {
              deferred.resolve( {
                data: {
                  address: address,
                  balance: []
                }
              } );
            } );
          return deferred.promise;
        }
      }
    };
    return service;
  }
] );

angular.module('omniwallet').factory('userService', ['$rootScope', '$http', '$injector',
function($rootScope, $http, $injector) {
  var service = {
    data : {
      walletKey : '',
      asymKey : {},
      wallet : {},
      walletMetadata: { currencies : [] },
      loggedIn : false,
      disclaimerSeen : false
    },

    login : function(wallet, walletKey, asymKey, walletMetadata) {
      service.data.walletKey = walletKey;
      service.data.asymKey = asymKey;
      service.data.wallet = wallet;
      service.data.walletMetadata = walletMetadata || service.data.walletMetadata;
      service.data.loggedIn = true;
      service.UpdateLoop();
    },

    logout : function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
      service.data.walletMetadata = {}
    },

    addAddress : function(address, privKey) {
      for (var i in service.data.wallet.addresses ) {
        if (service.data.wallet.addresses[i].address == address) {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      };
      service.data.wallet.addresses.push({
        "address" : address,
        "privkey" : privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
      service.updateCurrencies();
    },

    getAddress : function(address) {
      for (var i in service.data.wallet.addresses) {
        if (service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses : function() {
      return service.data.wallet.addresses;
    },

    getCurrencies : function() {
      currencies = service.data.walletMetadata.currencies.map( function( currency ) {
        return currency.symbol;
      });
      return currencies;
    },

    getWallet : function() {
      return service.data.wallet;
    },

    getUUID : function() {
      return service.data.wallet.uuid;
    },

    getAsymKey: function() {
      return service.data.asymKey;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    loggedIn: function () {
      return service.data.loggedIn;
    },

    UpdateLoop : function() {
      service.updateMetadata(function() {
        setTimeout(service.UpdateLoop, 60000);
      });
    },

    updateWallet: function() {
      var uuid = service.getUUID();
      return $http.get('/v1/user/wallet/challenge?uuid='+uuid)
        .then(function(result) {
          var data = result.data;
          var encryptedWallet = CryptUtil.encryptObject(service.data.wallet, service.data.walletKey);
          var challenge = data.challenge;
          var signature = CryptUtil.createSignedObject(challenge, service.getAsymKey().privKey);

          return $http({
            url: '/v1/user/wallet/update',
            method: 'POST',
            data: { uuid: uuid, wallet: encryptedWallet, signature: signature }
          });
        });
    },

    updateCurrencies : function(){
      var addCurrencies = function(i) {
        if (i < service.data.wallet.addresses.length) {
          $injector.get( 'balanceService' ).balance( service.data.wallet.addresses[i].address ).then(function(result) {
            result.data.balance.forEach(function(balanceItem) {
              var currency = null;
              for( var j = 0; j<service.data.walletMetadata.currencies.length; j++ ) {
                var currencyItem = service.data.walletMetadata.currencies[j];
                if(currencyItem.symbol == balanceItem.symbol) {
                  currency = currencyItem;
                  if(currency.addresses.indexOf(service.data.wallet.addresses[i].address))
                    currency.addresses.push(service.data.wallet.addresses[i].address);
                  break;
                }
              }
              if (currency === null){
                if(balanceItem.symbol.substring(0,2) == "SP"){
                  var propertyID = balanceItem.symbol.substring(2);
                  $http.get('/v1/property/'+propertyID+'.json').then(function(property){
                    currency = { name: property.propertyName, symbol : balanceItem.symbol, addresses : [service.data.wallet.addresses[i].address]};
                    service.data.walletMetadata.currencies.push(currency);
                  });
                } else {
                  currency = { name: balanceItem.symbol, symbol : balanceItem.symbol, addresses : [service.data.wallet.addresses[i].address]};
                  service.data.walletMetadata.currencies.push(currency);
                }
              }
            });
            addCurrencies(i+1);
          });
        } else {
          console.log("Updated Currencies");
        }
      };
      addCurrencies(0);
    },

    updateMetadata : function(callback){
      service.updateCurrencies();
      callback();
    },

    saveSession: function () {
      service.updateWallet().then(function(result) {
        console.log("Success saving")
      },
      function(result) {
        console.log('Failure saving')
      });
    }
  };

  return service;
}]);

angular.module('omniwallet').factory('appraiser', ['$rootScope', '$http','$q', '$injector',
function($rootScope, $http,$q, $injector) {

  function AppraiserService() {
    this.conversions = {};
    this.userService = $injector.get( 'userService' );
    var self = this;
    function UpdateLoop() {
      self.updateValues(function() {
        setTimeout(UpdateLoop, 30000);
      });
    }

    UpdateLoop();
  };
  AppraiserService.prototype.updateValues = function(callback) {
    var self = this;
    var requests =[];
    var coins = this.userService.getCurrencies();
    coins.forEach(function(coin){
      requests.push(
        $http.get('/v1/values/'+coin.symbol+'.json').then(function(response) {
          var currency = response.data[0];
          if (currency.symbol == 'BTC') {
            // Store these things internally as the value of a satoshi.
            self.conversions.BTC = currency.price / 100000000;
            $rootScope.$emit('APPRAISER_VALUE_CHANGED', 'BTC');
          } else {
            self.conversions[currency.symbol] = currency.price;
            $rootScope.$emit('APPRAISER_VALUE_CHANGED', currency.symbol);
          }
        }, function(error) {
          console.log(error);
        })
      );
    });
    $q.all( requests ).then(function(responses){
      callback();
    });
  };
  AppraiserService.prototype.getValue = function(amount, symbol) {
    if (symbol == 'BTC') {
      if (this.conversions.BTC)
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    } else {
      if (this.conversions.hasOwnProperty(symbol)) {
        return this.getValue(this.conversions[symbol] * amount, 'BTC');
      } else
        return symbol + ' Value Unavailable';
    }
  };

  return new AppraiserService();
}]);

angular.module( 'omniwallet' ).factory( 'hashExplorer', function ( ) {
  var tx = '', loc = '', setHash = function(){};
  return {
    tx : tx,
    loc: loc,
    setHash: function(tx) {
      this.tx = JSON.stringify(tx);
      this.loc = window.location.href.split('/').slice(-2).join('/');
    }
  }
});
<commit_msg>Return full currency list, fixed redundant addresses error<commit_after>//global services go here
angular.module( 'omniwallet' ).factory( 'balanceService', [ '$http', '$q',
  function( $http, $q ) {
    var cache = [];
    var service = {
      balance: function( address ) {
        var currentTime = new Date().getTime();
        if( cache[ address ] && ( currentTime - cache[ address ].timestamp ) < 60000 )
          return cache[ address ].deferred.promise;
        else
        {
          var deferred = $q.defer();
          cache[ address ] = {
            deferred: deferred,
            timestamp: currentTime
          }
          $http.post( '/v1/address/addr/', { 'addr': address } )
            .success( function( result ) {
              deferred.resolve( { data: result } );
            }).error ( function( error ) {
              deferred.resolve( {
                data: {
                  address: address,
                  balance: []
                }
              } );
            } );
          return deferred.promise;
        }
      }
    };
    return service;
  }
] );

angular.module('omniwallet').factory('userService', ['$rootScope', '$http', '$injector',
function($rootScope, $http, $injector) {
  var service = {
    data : {
      walletKey : '',
      asymKey : {},
      wallet : {},
      walletMetadata: { currencies : [] },
      loggedIn : false,
      disclaimerSeen : false
    },

    login : function(wallet, walletKey, asymKey, walletMetadata) {
      service.data.walletKey = walletKey;
      service.data.asymKey = asymKey;
      service.data.wallet = wallet;
      service.data.walletMetadata = walletMetadata || service.data.walletMetadata;
      service.data.loggedIn = true;
      service.UpdateLoop();
    },

    logout : function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
      service.data.walletMetadata = {}
    },

    addAddress : function(address, privKey) {
      for (var i in service.data.wallet.addresses ) {
        if (service.data.wallet.addresses[i].address == address) {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      };
      service.data.wallet.addresses.push({
        "address" : address,
        "privkey" : privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
      service.updateCurrencies();
    },

    getAddress : function(address) {
      for (var i in service.data.wallet.addresses) {
        if (service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses : function() {
      return service.data.wallet.addresses;
    },

    getCurrencies : function() {
      return service.data.walletMetadata.currencies;
    },

    getWallet : function() {
      return service.data.wallet;
    },

    getUUID : function() {
      return service.data.wallet.uuid;
    },

    getAsymKey: function() {
      return service.data.asymKey;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    loggedIn: function () {
      return service.data.loggedIn;
    },

    UpdateLoop : function() {
      service.updateMetadata(function() {
        setTimeout(service.UpdateLoop, 60000);
      });
    },

    updateWallet: function() {
      var uuid = service.getUUID();
      return $http.get('/v1/user/wallet/challenge?uuid='+uuid)
        .then(function(result) {
          var data = result.data;
          var encryptedWallet = CryptUtil.encryptObject(service.data.wallet, service.data.walletKey);
          var challenge = data.challenge;
          var signature = CryptUtil.createSignedObject(challenge, service.getAsymKey().privKey);

          return $http({
            url: '/v1/user/wallet/update',
            method: 'POST',
            data: { uuid: uuid, wallet: encryptedWallet, signature: signature }
          });
        });
    },

    updateCurrencies : function(){
      var addCurrencies = function(i) {
        if (i < service.data.wallet.addresses.length) {
          $injector.get( 'balanceService' ).balance( service.data.wallet.addresses[i].address ).then(function(result) {
            result.data.balance.forEach(function(balanceItem) {
              var currency = null;
              for( var j = 0; j<service.data.walletMetadata.currencies.length; j++ ) {
                var currencyItem = service.data.walletMetadata.currencies[j];
                if(currencyItem.symbol == balanceItem.symbol) {
                  currency = currencyItem;
                  if(!currency.addresses.indexOf(service.data.wallet.addresses[i].address))
                    currency.addresses.push(service.data.wallet.addresses[i].address);
                  break;
                }
              }
              if (currency === null){
                if(balanceItem.symbol.substring(0,2) == "SP"){
                  var propertyID = balanceItem.symbol.substring(2);
                  $http.get('/v1/property/'+propertyID+'.json').then(function(property){
                    currency = { name: property.propertyName, symbol : balanceItem.symbol, addresses : [service.data.wallet.addresses[i].address]};
                    service.data.walletMetadata.currencies.push(currency);
                  });
                } else {
                  currency = { name: balanceItem.symbol, symbol : balanceItem.symbol, addresses : [service.data.wallet.addresses[i].address]};
                  service.data.walletMetadata.currencies.push(currency);
                }
              }
            });
            addCurrencies(i+1);
          });
        } else {
          console.log("Updated Currencies");
        }
      };
      addCurrencies(0);
    },

    updateMetadata : function(callback){
      service.updateCurrencies();
      callback();
    },

    saveSession: function () {
      service.updateWallet().then(function(result) {
        console.log("Success saving")
      },
      function(result) {
        console.log('Failure saving')
      });
    }
  };

  return service;
}]);

angular.module('omniwallet').factory('appraiser', ['$rootScope', '$http','$q', '$injector',
function($rootScope, $http,$q, $injector) {

  function AppraiserService() {
    this.conversions = {};
    this.userService = $injector.get( 'userService' );
    var self = this;
    function UpdateLoop() {
      self.updateValues(function() {
        setTimeout(UpdateLoop, 30000);
      });
    }

    UpdateLoop();
  };
  AppraiserService.prototype.updateValues = function(callback) {
    var self = this;
    var requests =[];
    var coins = this.userService.getCurrencies();
    coins.forEach(function(coin){
      requests.push(
        $http.get('/v1/values/'+coin.symbol+'.json').then(function(response) {
          var currency = response.data[0];
          if (currency.symbol == 'BTC') {
            // Store these things internally as the value of a satoshi.
            self.conversions.BTC = currency.price / 100000000;
            $rootScope.$emit('APPRAISER_VALUE_CHANGED', 'BTC');
          } else {
            self.conversions[currency.symbol] = currency.price;
            $rootScope.$emit('APPRAISER_VALUE_CHANGED', currency.symbol);
          }
        }, function(error) {
          console.log(error);
        })
      );
    });
    $q.all( requests ).then(function(responses){
      callback();
    });
  };
  AppraiserService.prototype.getValue = function(amount, symbol) {
    if (symbol == 'BTC') {
      if (this.conversions.BTC)
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    } else {
      if (this.conversions.hasOwnProperty(symbol)) {
        return this.getValue(this.conversions[symbol] * amount, 'BTC');
      } else
        return symbol + ' Value Unavailable';
    }
  };

  return new AppraiserService();
}]);

angular.module( 'omniwallet' ).factory( 'hashExplorer', function ( ) {
  var tx = '', loc = '', setHash = function(){};
  return {
    tx : tx,
    loc: loc,
    setHash: function(tx) {
      this.tx = JSON.stringify(tx);
      this.loc = window.location.href.split('/').slice(-2).join('/');
    }
  }
});
<|endoftext|>


<commit_before>var shell = require('shell')

document.addEventListener('DOMContentLoaded', function (event) {
  var links = document.querySelectorAll('a[href]')
  var array = []
  array.forEach.call(links, function (link) {
    var url = link.getAttribute('href')
    if (url.indexOf('http') > -1) {
      console.log(url)
      link.addEventListener('click', function (e) {
        e.preventDefault()
        shell.openExternal(url)
      })
    }
  })
})
<commit_msg>Aaand remove log<commit_after>var shell = require('shell')

document.addEventListener('DOMContentLoaded', function (event) {
  var links = document.querySelectorAll('a[href]')
  var array = []
  array.forEach.call(links, function (link) {
    var url = link.getAttribute('href')
    if (url.indexOf('http') > -1) {
      link.addEventListener('click', function (e) {
        e.preventDefault()
        shell.openExternal(url)
      })
    }
  })
})
<|endoftext|>


<commit_before>define([
    '/api/config?cb=' + Math.random().toString(16).substring(2),
    '/common/realtime-input.js',
    '/common/crypto.js',
    '/common/TextPatcher.js',
    '/bower_components/jquery/dist/jquery.min.js',
    '/customize/pad.js'
], function (Config, Realtime, Crypto, TextPatcher) {
    // TODO consider adding support for less.js
    var $ = window.jQuery;

    var module = window.APP = {};

    var key;
    var channel = '';
    if (!/#/.test(window.location.href)) {
        key = Crypto.genKey();
    } else {
        var hash = window.location.hash.slice(1);
        channel = hash.slice(0, 32);
        key = hash.slice(32);
    }

    var config = {
        websocketURL: Config.websocketURL,
        channel: channel,
        cryptKey: key,
        crypto: Crypto,
    };

    var userName = module.userName = config.userName = Crypto.rand64(8);

    var lazyDraw = (function () {
        var to,
            delay = 500;
        return function (content) {
            if (to) { clearTimeout(to); }
            to = setTimeout(function () {
                $style.text(content);
            },delay);
        };
    }());

    var draw = function (content) { lazyDraw(content); };

    var initializing = true;

    var onInit = config.onInit = function (info) {
        window.location.hash = info.channel + key;
        var realtime = module.realtime = info.realtime;
        module.patchText = TextPatcher.create({
            realtime: realtime,
            logging: true,
        });

        $(window).on('hashchange', function() {
            window.location.reload();
        });
    };

    var onReady = config.onReady = function (info) {
        var userDoc = module.realtime.getUserDoc();
        draw(userDoc);
        console.log("Ready");
        initializing = false;
    };

    var onRemote = config.onRemote = function () {
        draw(module.realtime.getUserDoc());
    };

    var onAbort = config.onAbort = function (info) {
        // notify the user of the abort
        window.alert("Network Connection Lost");
    };

    var onLocal = config.onLocal = function () {
        // nope
    };

    var $style = $('style').first(),
        $edit = $('#edit');

    $edit.attr('href', '/text/'+ window.location.hash);

    var rt = Realtime.start(config);
});
<commit_msg>fix jshint complain<commit_after>define([
    '/api/config?cb=' + Math.random().toString(16).substring(2),
    '/common/realtime-input.js',
    '/common/crypto.js',
    '/common/TextPatcher.js',
    '/bower_components/jquery/dist/jquery.min.js',
    '/customize/pad.js'
], function (Config, Realtime, Crypto, TextPatcher) {
    // TODO consider adding support for less.js
    var $ = window.jQuery;

    var $style = $('style').first(),
        $edit = $('#edit');

    var module = window.APP = {};

    var key;
    var channel = '';
    if (!/#/.test(window.location.href)) {
        key = Crypto.genKey();
    } else {
        var hash = window.location.hash.slice(1);
        channel = hash.slice(0, 32);
        key = hash.slice(32);
    }

    var config = {
        websocketURL: Config.websocketURL,
        channel: channel,
        cryptKey: key,
        crypto: Crypto,
    };

    var userName = module.userName = config.userName = Crypto.rand64(8);

    var lazyDraw = (function () {
        var to,
            delay = 500;
        return function (content) {
            if (to) { clearTimeout(to); }
            to = setTimeout(function () {
                $style.text(content);
            },delay);
        };
    }());

    var draw = function (content) { lazyDraw(content); };

    var initializing = true;

    var onInit = config.onInit = function (info) {
        window.location.hash = info.channel + key;
        var realtime = module.realtime = info.realtime;
        module.patchText = TextPatcher.create({
            realtime: realtime,
            logging: true,
        });

        $(window).on('hashchange', function() {
            window.location.reload();
        });
    };

    var onReady = config.onReady = function (info) {
        var userDoc = module.realtime.getUserDoc();
        draw(userDoc);
        console.log("Ready");
        initializing = false;
    };

    var onRemote = config.onRemote = function () {
        draw(module.realtime.getUserDoc());
    };

    var onAbort = config.onAbort = function (info) {
        // notify the user of the abort
        window.alert("Network Connection Lost");
    };

    var onLocal = config.onLocal = function () {
        // nope
    };

    $edit.attr('href', '/text/'+ window.location.hash);

    var rt = Realtime.start(config);
});
<|endoftext|>


<commit_before>/**
  Function used to calculate the position of the content of the dropdown.
  @public
  @method calculatePosition
  @param {DomElement} trigger The trigger of the dropdown
  @param {DomElement} content The content of the dropdown
  @param {DomElement} destination The element in which the content is going to be placed.
  @param {Object} options The directives that define how the position is calculated
    - {String} horizontalPosition How the users want the dropdown to be positioned horizontally. Values: right | center | left
    - {String} verticalPosition How the users want the dropdown to be positioned vertically. Values: above | below
    - {Boolean} matchTriggerWidth If the user wants the width of the dropdown to match the width of the trigger
    - {String} previousHorizontalPosition How the dropdown was positioned for the last time. Same values than horizontalPosition, but can be null the first time.
    - {String} previousVerticalPosition How the dropdown was positioned for the last time. Same values than verticalPosition, but can be null the first time.
    - {Boolean} renderInPlace Boolean flat that is truthy if the component is rendered in place.
  @return {Object} How the component is going to be positioned.
    - {String} horizontalPosition The new horizontal position.
    - {String} verticalPosition The new vertical position.
    - {Object} CSS properties to be set on the dropdown. It supports `top`, `left`, `right` and `width`.
*/
export default function(_, _2, _destination, { renderInPlace }) {
  if (renderInPlace) {
    return calculateInPlacePosition(...arguments);
  } else {
    return calculateWormholedPosition(...arguments);
  }
}

export function calculateWormholedPosition(trigger, content, destination, { horizontalPosition, verticalPosition, matchTriggerWidth, previousHorizontalPosition, previousVerticalPosition }) {
  // Collect information about all the involved DOM elements
  let scroll = { left: window.pageXOffset, top: window.pageYOffset };
  let { left: triggerLeft, top: triggerTop, width: triggerWidth, height: triggerHeight } = trigger.getBoundingClientRect();
  let { height: dropdownHeight, width: dropdownWidth } = content.getBoundingClientRect();
  let viewportWidth = self.document.body.clientWidth || self.window.innerWidth;
  let style = {};

  // Apply containers' offset
  let anchorElement = destination.parentNode;
  let anchorPosition = window.getComputedStyle(anchorElement).position;
  while (anchorPosition !== 'relative' && anchorPosition !== 'absolute' && anchorElement.tagName.toUpperCase() !== 'BODY' && destination.parentNode) {
    anchorElement = anchorElement.parentNode;
    anchorPosition = window.getComputedStyle(anchorElement).position;
  }
  if (anchorPosition === 'relative' || anchorPosition === 'absolute') {
    let rect = anchorElement.getBoundingClientRect();
    triggerLeft = triggerLeft - rect.left;
    triggerTop = triggerTop - rect.top;
    let { offsetParent } = anchorElement;
    if (offsetParent) {
      triggerLeft -= anchorElement.offsetParent.scrollLeft;
      triggerTop -= anchorElement.offsetParent.scrollTop;
    }
  }

  // Calculate drop down width
  dropdownWidth = matchTriggerWidth ? triggerWidth : dropdownWidth;
  if (matchTriggerWidth) {
    style.width = dropdownWidth;
  }

  // Calculate horizontal position
  let triggerLeftWithScroll = triggerLeft + scroll.left;
  if (horizontalPosition === 'auto' || horizontalPosition === 'auto-left') {
    // Calculate the number of visible horizontal pixels if we were to place the
    // dropdown on the left and right
    let leftVisible = Math.min(viewportWidth, triggerLeft + dropdownWidth) - Math.max(0, triggerLeft);
    let rightVisible = Math.min(viewportWidth, triggerLeft + triggerWidth) - Math.max(0, triggerLeft + triggerWidth - dropdownWidth);

    if (dropdownWidth > leftVisible && rightVisible > leftVisible) {
      // If the drop down won't fit left-aligned, and there is more space on the
      // right than on the left, then force right-aligned
      horizontalPosition = 'right';
    } else if (dropdownWidth > rightVisible && leftVisible > rightVisible) {
      // If the drop down won't fit right-aligned, and there is more space on
      // the left than on the right, then force left-aligned
      horizontalPosition = 'left';
    } else {
      // Keep same position as previous
      horizontalPosition = previousHorizontalPosition || 'left';
    }
  } else if (horizontalPosition === 'auto-right') {
    // Calculate the number of visible horizontal pixels if we were to place the
    // dropdown on the left and right
    let leftVisible = Math.min(viewportWidth, triggerLeft + dropdownWidth) - Math.max(0, triggerLeft);
    let rightVisible = Math.min(viewportWidth, triggerLeft + triggerWidth) - Math.max(0, triggerLeft + triggerWidth - dropdownWidth);

    if (dropdownWidth > rightVisible && leftVisible > rightVisible) {
      // If the drop down won't fit right-aligned, and there is more space on the
      // left than on the right, then force left-aligned
      horizontalPosition = 'left';
    } else if (dropdownWidth > leftVisible && rightVisible > leftVisible) {
      // If the drop down won't fit left-aligned, and there is more space on
      // the right than on the left, then force right-aligned
      horizontalPosition = 'right';
    } else {
      // Keep same position as previous
      horizontalPosition = previousHorizontalPosition || 'right';
    }
  }
  if (horizontalPosition === 'right') {
    style.right = viewportWidth - (triggerLeftWithScroll + triggerWidth);
  } else if (horizontalPosition === 'center') {
    style.left = triggerLeftWithScroll + (triggerWidth - dropdownWidth) / 2;
  } else {
    style.left = triggerLeftWithScroll;
  }

  // Calculate vertical position
  let triggerTopWithScroll = triggerTop;

  /**
   * Fixes bug where the dropdown always stays on the same position on the screen when
   * the <body> is relatively positioned
   */
  let isBodyPositionRelative = window.getComputedStyle(document.body).getPropertyValue('position') === 'relative';
  if (!isBodyPositionRelative) {
    triggerTopWithScroll += scroll.top;
  }

  if (verticalPosition === 'above') {
    style.top = triggerTopWithScroll - dropdownHeight;
  } else if (verticalPosition === 'below') {
    style.top = triggerTopWithScroll + triggerHeight;
  } else {
    let viewportBottom = scroll.top + self.window.innerHeight;
    let enoughRoomBelow = triggerTopWithScroll + triggerHeight + dropdownHeight < viewportBottom;
    let enoughRoomAbove = triggerTop > dropdownHeight;

    if (previousVerticalPosition === 'below' && !enoughRoomBelow && enoughRoomAbove) {
      verticalPosition = 'above';
    } else if (previousVerticalPosition === 'above' && !enoughRoomAbove && enoughRoomBelow) {
      verticalPosition = 'below';
    } else if (!previousVerticalPosition) {
      verticalPosition = enoughRoomBelow ? 'below' : 'above';
    } else {
      verticalPosition = previousVerticalPosition;
    }
    style.top = triggerTopWithScroll + (verticalPosition === 'below' ? triggerHeight : -dropdownHeight);
  }

  return { horizontalPosition, verticalPosition, style };
}

export function calculateInPlacePosition(trigger, content, destination, { horizontalPosition, verticalPosition }/*, matchTriggerWidth, previousHorizontalPosition, previousVerticalPosition */) {
  let dropdownRect;
  let positionData = {};
  if (horizontalPosition === 'auto') {
    let triggerRect = trigger.getBoundingClientRect();
    dropdownRect = content.getBoundingClientRect();
    let viewportRight = window.pageXOffset + self.window.innerWidth;
    positionData.horizontalPosition = triggerRect.left + dropdownRect.width > viewportRight ? 'right' : 'left';
  } else if (horizontalPosition === 'center') {
    let { width: triggerWidth } = trigger.getBoundingClientRect();
    let { width: dropdownWidth } = content.getBoundingClientRect();
    positionData.style = { left: (triggerWidth - dropdownWidth) / 2 };
  } else if (horizontalPosition === 'auto-right') {
    let triggerRect = trigger.getBoundingClientRect();
    let dropdownRect = content.getBoundingClientRect();
    positionData.horizontalPosition = triggerRect.right > dropdownRect.width ? 'right' : 'left';
  } else if (horizontalPosition === 'right') {
    positionData.horizontalPosition = 'right';
  }

  if (verticalPosition === 'above') {
    positionData.verticalPosition = verticalPosition;
    dropdownRect = dropdownRect || content.getBoundingClientRect();
    positionData.style = { top: -dropdownRect.height };
  } else {
    positionData.verticalPosition = 'below';
  }
  return positionData;
}

export function getScrollParent(element) {
  let style = self.window.getComputedStyle(element);
  let excludeStaticParent = style.position === "absolute";
  let overflowRegex = /(auto|scroll)/;

  if (style.position === "fixed") return document.body;
  for (let parent = element; (parent = parent.parentElement);) {
      style = self.window.getComputedStyle(parent);
      if (excludeStaticParent && style.position === "static") {
          continue;
      }
      if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
        return parent;
      }
  }

  return document.body;
}
<commit_msg>Remove unneeded condition. (#379)<commit_after>/**
  Function used to calculate the position of the content of the dropdown.
  @public
  @method calculatePosition
  @param {DomElement} trigger The trigger of the dropdown
  @param {DomElement} content The content of the dropdown
  @param {DomElement} destination The element in which the content is going to be placed.
  @param {Object} options The directives that define how the position is calculated
    - {String} horizontalPosition How the users want the dropdown to be positioned horizontally. Values: right | center | left
    - {String} verticalPosition How the users want the dropdown to be positioned vertically. Values: above | below
    - {Boolean} matchTriggerWidth If the user wants the width of the dropdown to match the width of the trigger
    - {String} previousHorizontalPosition How the dropdown was positioned for the last time. Same values than horizontalPosition, but can be null the first time.
    - {String} previousVerticalPosition How the dropdown was positioned for the last time. Same values than verticalPosition, but can be null the first time.
    - {Boolean} renderInPlace Boolean flat that is truthy if the component is rendered in place.
  @return {Object} How the component is going to be positioned.
    - {String} horizontalPosition The new horizontal position.
    - {String} verticalPosition The new vertical position.
    - {Object} CSS properties to be set on the dropdown. It supports `top`, `left`, `right` and `width`.
*/
export default function(_, _2, _destination, { renderInPlace }) {
  if (renderInPlace) {
    return calculateInPlacePosition(...arguments);
  } else {
    return calculateWormholedPosition(...arguments);
  }
}

export function calculateWormholedPosition(trigger, content, destination, { horizontalPosition, verticalPosition, matchTriggerWidth, previousHorizontalPosition, previousVerticalPosition }) {
  // Collect information about all the involved DOM elements
  let scroll = { left: window.pageXOffset, top: window.pageYOffset };
  let { left: triggerLeft, top: triggerTop, width: triggerWidth, height: triggerHeight } = trigger.getBoundingClientRect();
  let { height: dropdownHeight, width: dropdownWidth } = content.getBoundingClientRect();
  let viewportWidth = self.document.body.clientWidth || self.window.innerWidth;
  let style = {};

  // Apply containers' offset
  let anchorElement = destination.parentNode;
  let anchorPosition = window.getComputedStyle(anchorElement).position;
  while (anchorPosition !== 'relative' && anchorPosition !== 'absolute' && anchorElement.tagName.toUpperCase() !== 'BODY') {
    anchorElement = anchorElement.parentNode;
    anchorPosition = window.getComputedStyle(anchorElement).position;
  }
  if (anchorPosition === 'relative' || anchorPosition === 'absolute') {
    let rect = anchorElement.getBoundingClientRect();
    triggerLeft = triggerLeft - rect.left;
    triggerTop = triggerTop - rect.top;
    let { offsetParent } = anchorElement;
    if (offsetParent) {
      triggerLeft -= anchorElement.offsetParent.scrollLeft;
      triggerTop -= anchorElement.offsetParent.scrollTop;
    }
  }

  // Calculate drop down width
  dropdownWidth = matchTriggerWidth ? triggerWidth : dropdownWidth;
  if (matchTriggerWidth) {
    style.width = dropdownWidth;
  }

  // Calculate horizontal position
  let triggerLeftWithScroll = triggerLeft + scroll.left;
  if (horizontalPosition === 'auto' || horizontalPosition === 'auto-left') {
    // Calculate the number of visible horizontal pixels if we were to place the
    // dropdown on the left and right
    let leftVisible = Math.min(viewportWidth, triggerLeft + dropdownWidth) - Math.max(0, triggerLeft);
    let rightVisible = Math.min(viewportWidth, triggerLeft + triggerWidth) - Math.max(0, triggerLeft + triggerWidth - dropdownWidth);

    if (dropdownWidth > leftVisible && rightVisible > leftVisible) {
      // If the drop down won't fit left-aligned, and there is more space on the
      // right than on the left, then force right-aligned
      horizontalPosition = 'right';
    } else if (dropdownWidth > rightVisible && leftVisible > rightVisible) {
      // If the drop down won't fit right-aligned, and there is more space on
      // the left than on the right, then force left-aligned
      horizontalPosition = 'left';
    } else {
      // Keep same position as previous
      horizontalPosition = previousHorizontalPosition || 'left';
    }
  } else if (horizontalPosition === 'auto-right') {
    // Calculate the number of visible horizontal pixels if we were to place the
    // dropdown on the left and right
    let leftVisible = Math.min(viewportWidth, triggerLeft + dropdownWidth) - Math.max(0, triggerLeft);
    let rightVisible = Math.min(viewportWidth, triggerLeft + triggerWidth) - Math.max(0, triggerLeft + triggerWidth - dropdownWidth);

    if (dropdownWidth > rightVisible && leftVisible > rightVisible) {
      // If the drop down won't fit right-aligned, and there is more space on the
      // left than on the right, then force left-aligned
      horizontalPosition = 'left';
    } else if (dropdownWidth > leftVisible && rightVisible > leftVisible) {
      // If the drop down won't fit left-aligned, and there is more space on
      // the right than on the left, then force right-aligned
      horizontalPosition = 'right';
    } else {
      // Keep same position as previous
      horizontalPosition = previousHorizontalPosition || 'right';
    }
  }
  if (horizontalPosition === 'right') {
    style.right = viewportWidth - (triggerLeftWithScroll + triggerWidth);
  } else if (horizontalPosition === 'center') {
    style.left = triggerLeftWithScroll + (triggerWidth - dropdownWidth) / 2;
  } else {
    style.left = triggerLeftWithScroll;
  }

  // Calculate vertical position
  let triggerTopWithScroll = triggerTop;

  /**
   * Fixes bug where the dropdown always stays on the same position on the screen when
   * the <body> is relatively positioned
   */
  let isBodyPositionRelative = window.getComputedStyle(document.body).getPropertyValue('position') === 'relative';
  if (!isBodyPositionRelative) {
    triggerTopWithScroll += scroll.top;
  }

  if (verticalPosition === 'above') {
    style.top = triggerTopWithScroll - dropdownHeight;
  } else if (verticalPosition === 'below') {
    style.top = triggerTopWithScroll + triggerHeight;
  } else {
    let viewportBottom = scroll.top + self.window.innerHeight;
    let enoughRoomBelow = triggerTopWithScroll + triggerHeight + dropdownHeight < viewportBottom;
    let enoughRoomAbove = triggerTop > dropdownHeight;

    if (previousVerticalPosition === 'below' && !enoughRoomBelow && enoughRoomAbove) {
      verticalPosition = 'above';
    } else if (previousVerticalPosition === 'above' && !enoughRoomAbove && enoughRoomBelow) {
      verticalPosition = 'below';
    } else if (!previousVerticalPosition) {
      verticalPosition = enoughRoomBelow ? 'below' : 'above';
    } else {
      verticalPosition = previousVerticalPosition;
    }
    style.top = triggerTopWithScroll + (verticalPosition === 'below' ? triggerHeight : -dropdownHeight);
  }

  return { horizontalPosition, verticalPosition, style };
}

export function calculateInPlacePosition(trigger, content, destination, { horizontalPosition, verticalPosition }/*, matchTriggerWidth, previousHorizontalPosition, previousVerticalPosition */) {
  let dropdownRect;
  let positionData = {};
  if (horizontalPosition === 'auto') {
    let triggerRect = trigger.getBoundingClientRect();
    dropdownRect = content.getBoundingClientRect();
    let viewportRight = window.pageXOffset + self.window.innerWidth;
    positionData.horizontalPosition = triggerRect.left + dropdownRect.width > viewportRight ? 'right' : 'left';
  } else if (horizontalPosition === 'center') {
    let { width: triggerWidth } = trigger.getBoundingClientRect();
    let { width: dropdownWidth } = content.getBoundingClientRect();
    positionData.style = { left: (triggerWidth - dropdownWidth) / 2 };
  } else if (horizontalPosition === 'auto-right') {
    let triggerRect = trigger.getBoundingClientRect();
    let dropdownRect = content.getBoundingClientRect();
    positionData.horizontalPosition = triggerRect.right > dropdownRect.width ? 'right' : 'left';
  } else if (horizontalPosition === 'right') {
    positionData.horizontalPosition = 'right';
  }

  if (verticalPosition === 'above') {
    positionData.verticalPosition = verticalPosition;
    dropdownRect = dropdownRect || content.getBoundingClientRect();
    positionData.style = { top: -dropdownRect.height };
  } else {
    positionData.verticalPosition = 'below';
  }
  return positionData;
}

export function getScrollParent(element) {
  let style = self.window.getComputedStyle(element);
  let excludeStaticParent = style.position === "absolute";
  let overflowRegex = /(auto|scroll)/;

  if (style.position === "fixed") return document.body;
  for (let parent = element; (parent = parent.parentElement);) {
      style = self.window.getComputedStyle(parent);
      if (excludeStaticParent && style.position === "static") {
          continue;
      }
      if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
        return parent;
      }
  }

  return document.body;
}
<|endoftext|>


<commit_before>//var TopicController = require("../Controller/TopicController");
var Question = require("../Controller/QuestionController");
var multer = require('multer')
var uploading = multer({dest: __dirname + '../../uploadImage/', limits: {fileSize: 1000000, files:1}})

module.exports = function(app){
    // API
    /*
    app.post('/api/:lang/user/training/question', function(req, res){
        console.log("/api/"+req.params.lang);
        var language = req.params.lang;
        TopicController.getNextQuestion(language, function (result) {
            res.json(result);
        });
    });*/

    app.route('/api/:lang/userquestion')
        .post(Question.createQuestion)
        .put(Question.editQuestion)
        .get(Question.getQuestions);

    app.route('/api/:lang/userquestion/:questionId')
        .get(Question.getQuestion);

    app.route('/api/:lang/usertraining/questionstatistics')
        .put(Question.updatestatisticsQuestion);

};<commit_msg>Question model updated<commit_after>//var TopicController = require("../Controller/TopicController");
var Question = require("../Controller/QuestionController");
var multer = require('multer')
var uploading = multer({dest: __dirname + '../../uploadImage/', limits: {fileSize: 1000000, files:1}})

module.exports = function(app){
    // API
    /*
    app.post('/api/:lang/user/training/question', function(req, res){
        console.log("/api/"+req.params.lang);
        var language = req.params.lang;
        TopicController.getNextQuestion(language, function (result) {
            res.json(result);
        });
    });*/

    app.route('/api/:lang/userquestion',uploading)
        .post(Question.createQuestion)
        .put(Question.editQuestion)
        .get(Question.getQuestions);

    app.route('/api/:lang/userquestion/:questionId')
        .get(Question.getQuestion);

    app.route('/api/:lang/usertraining/questionstatistics')
        .put(Question.updatestatisticsQuestion);

};<|endoftext|>


<commit_before>const Client           = require('../../../../../base/client');
const getMarkets       = require('../../../../../common/active_symbols').getMarkets;
const Table            = require('../../../../../common/attach_dom/table');
const Currency         = require('../../../../../common/currency');
const elementInnerHtml = require('../../../../../../_common/common_functions').elementInnerHtml;
const getElementById   = require('../../../../../../_common/common_functions').getElementById;
const localize         = require('../../../../../../_common/localize').localize;
const findParent       = require('../../../../../../_common/utility').findParent;

const LimitsUI = (() => {
    let $client_limits;

    // if we have value for td, set the value
    // if we don't, make the tr invisible
    const setText = (el, text) => {
        if (text) {
            elementInnerHtml(el, text);
        } else {
            const tr = findParent(el, 'tr');
            if (tr) {
                tr.setVisibility(0);
            }
        }
    };

    const appendRowTable = (localized_name, turnover_limit, padding, font_weight) => {
        const $new_row = $('<tr/>', { class: 'flex-tr' })
            .append($('<td/>', { class: 'flex-tr-child', style: `padding-left: ${padding}; font-weight: ${font_weight};`, text: localized_name }))
            .append($('<td/>', { html: turnover_limit }));
        $client_limits.append($new_row);
    };

    const fillLimitsTable = (limits, response_active_symbols) => {
        const currency = Client.get('currency');

        if (currency) {
            $('.limit').append(` (${Currency.getCurrencyDisplayCode(currency)})`);
        }

        const open_position   = getElementById('open-positions');
        const account_balance = getElementById('account-balance');
        const payout          = getElementById('payout');

        $client_limits = $('#client-limits');

        setText(open_position, 'open_positions' in limits ? limits.open_positions : '');
        setText(account_balance, 'account_balance' in limits ? Currency.formatMoney(currency, limits.account_balance, 1) : '');
        setText(payout, 'payout' in limits ? Currency.formatMoney(currency, limits.payout, 1) : '');

        if (limits.market_specific) {
            const markets = getMarkets(response_active_symbols.active_symbols);
            Object.keys(limits.market_specific).forEach((market) => {
                appendRowTable(markets[market].name, '', 'auto', 'bold');
                limits.market_specific[market].forEach((submarket) => {
                    // submarket name could be (Commodities|Minor Pairs|Major Pairs|Smart FX|Stock Indices|Synthetic Indices)
                    appendRowTable(localize(submarket.name /* localize-ignore */), submarket.turnover_limit !== 'null' ? Currency.formatMoney(currency, submarket.turnover_limit, 1) : 0, '25px', 'normal');
                });
            });
        } else {
            const tr = findParent(getElementById('market_specific'), 'tr');
            if (tr) {
                tr.setVisibility(0);
            }
        }

        const login_id = Client.get('loginid');
        if (login_id) {
            $('#trading-limits').prepend(`${login_id} - `);
            $('#withdrawal-title').prepend(`${login_id} - `);
        }
        $('#limits-title').setVisibility(1);
    };

    const clearTableContent = () => {
        Table.clearTableBody('client-limits');
    };

    const limitsError = (error = {}) => {
        getElementById('withdrawal-title').setVisibility(0);
        getElementById('limits-title').setVisibility(0);
        $('#loading').remove();
        $('#limits_error').html($('<p/>', { class: 'center-text notice-msg', text: error.message || localize('Sorry, an error occurred while processing your request.') }));
    };

    return {
        clearTableContent,
        fillLimitsTable,
        limitsError,
    };
})();

module.exports = LimitsUI;
<commit_msg>Fix inconsistency between limits and active_symbols (#6624)<commit_after>const Client           = require('../../../../../base/client');
const getMarkets       = require('../../../../../common/active_symbols').getMarkets;
const Table            = require('../../../../../common/attach_dom/table');
const Currency         = require('../../../../../common/currency');
const elementInnerHtml = require('../../../../../../_common/common_functions').elementInnerHtml;
const getElementById   = require('../../../../../../_common/common_functions').getElementById;
const localize         = require('../../../../../../_common/localize').localize;
const findParent       = require('../../../../../../_common/utility').findParent;

const LimitsUI = (() => {
    let $client_limits;

    // if we have value for td, set the value
    // if we don't, make the tr invisible
    const setText = (el, text) => {
        if (text) {
            elementInnerHtml(el, text);
        } else {
            const tr = findParent(el, 'tr');
            if (tr) {
                tr.setVisibility(0);
            }
        }
    };

    const appendRowTable = (localized_name, turnover_limit, padding, font_weight) => {
        const $new_row = $('<tr/>', { class: 'flex-tr' })
            .append($('<td/>', { class: 'flex-tr-child', style: `padding-left: ${padding}; font-weight: ${font_weight};`, text: localized_name }))
            .append($('<td/>', { html: turnover_limit }));
        $client_limits.append($new_row);
    };

    const fillLimitsTable = (limits, response_active_symbols) => {
        const currency = Client.get('currency');

        if (currency) {
            $('.limit').append(` (${Currency.getCurrencyDisplayCode(currency)})`);
        }

        const open_position   = getElementById('open-positions');
        const account_balance = getElementById('account-balance');
        const payout          = getElementById('payout');

        $client_limits = $('#client-limits');

        setText(open_position, 'open_positions' in limits ? limits.open_positions : '');
        setText(account_balance, 'account_balance' in limits ? Currency.formatMoney(currency, limits.account_balance, 1) : '');
        setText(payout, 'payout' in limits ? Currency.formatMoney(currency, limits.payout, 1) : '');

        if (limits.market_specific) {
            const markets = getMarkets(response_active_symbols.active_symbols);
            Object.keys(limits.market_specific).forEach((market) => {
                // If the market is not present in active symbols, don't attempt to show it.
                if (markets[market]) {
                    appendRowTable(markets[market].name, '', 'auto', 'bold');
                    limits.market_specific[market].forEach((submarket) => {
                        // submarket name could be (Commodities|Minor Pairs|Major Pairs|Smart FX|Stock Indices|Synthetic Indices)
                        appendRowTable(localize(submarket.name /* localize-ignore */), submarket.turnover_limit !== 'null' ? Currency.formatMoney(currency, submarket.turnover_limit, 1) : 0, '25px', 'normal');
                    });
                }
            });
        } else {
            const tr = findParent(getElementById('market_specific'), 'tr');
            if (tr) {
                tr.setVisibility(0);
            }
        }

        const login_id = Client.get('loginid');
        if (login_id) {
            $('#trading-limits').prepend(`${login_id} - `);
            $('#withdrawal-title').prepend(`${login_id} - `);
        }
        $('#limits-title').setVisibility(1);
    };

    const clearTableContent = () => {
        Table.clearTableBody('client-limits');
    };

    const limitsError = (error = {}) => {
        getElementById('withdrawal-title').setVisibility(0);
        getElementById('limits-title').setVisibility(0);
        $('#loading').remove();
        $('#limits_error').html($('<p/>', { class: 'center-text notice-msg', text: error.message || localize('Sorry, an error occurred while processing your request.') }));
    };

    return {
        clearTableContent,
        fillLimitsTable,
        limitsError,
    };
})();

module.exports = LimitsUI;
<|endoftext|>


<commit_before>/**
 * @exports OSMBuildingLayer
 */
define(['libraries/WebWorldWind/src/WorldWind', 'src/OSMLayer', 'src/GeoJSONParserTriangulation', 'jquery', 'osmtogeojson'], function (WorldWind, OSMLayer, GeoJSONParserTriangulation, $, osmtogeojson) {
  "use strict";

  /**
   * Creates a sublass of the {@link OSMLayer} class.
   * @alias OSMBuildingLayer
   * @constructor
   * @classdesc Fetches OSM buildings, converts them to GeoJSON, and adds them to the WorldWindow.
   * @param {WorldWindow} worldWindow The WorldWindow where the OSMBuildingLayer is added to.
   * @param {Float[]} boundingBox It defines the bounding box of the OSM data for the OSMLayer. The order of coordinates of the bounding box is "x1, y1, x2, y2".
   * @param {Object} configuration Configuration is used to set the attributes of {@link ShapeAttributes}. Four more attributes can be defined, which are "extrude", "heatmap", "altitude" and "altitudeMode".
   */
  var OSMBuildingLayer = function (worldWindow, boundingBox, configuration) {
    OSMLayer.call(this, worldWindow, boundingBox, configuration);
    this.type = "way";
    this.tag = "building";
  };

  OSMBuildingLayer.prototype = Object.create(OSMLayer.prototype);

  /**
   * Sets the attributes of {@link ShapeAttributes} and three more attributes defined specifically for OSMBuildingLayer, which are "extrude", "altitude" and "altitudeMode".
   * @param {GeoJSONGeometry} geometry An object containing the geometry of the OSM data in GeoJSON format for the OSMBuildingLayer.
   * @returns {Object} An object with the attributes {@link ShapeAttributes} and four more attributes, which are "extrude", "heatmap", "altitude" and "altitudeMode", where all of them are defined in the configuration of the OSMBuildingLayer.
   */
  OSMBuildingLayer.prototype.shapeConfigurationCallback = function (geometry) {
    var configuration = OSMLayer.prototype.shapeConfigurationCallback.call(this, geometry);

    configuration.extrude = this.configuration.extrude ? this.configuration.extrude : false;
    configuration.heatmap = this.configuration.heatmap ? this.configuration.heatmap : undefined;
    if (configuration.heatmap) {
      configuration.heatmap.enabled = this.configuration.heatmap.enabled ? this.configuration.heatmap.enabled : false;
      configuration.heatmap.thresholds = this.configuration.heatmap.thresholds ? this.configuration.heatmap.thresholds : [0, 15, 900];
    }
    configuration.altitude = this.configuration.altitude ? this.configuration.altitude : 15;
    configuration.altitudeMode = this.configuration.altitudeMode ? this.configuration.altitudeMode : WorldWind.RELATIVE_TO_GROUND;

   // console.log(JSON.stringify(configuration));

    return configuration;
  };

  /**
   * Using the boundingBox of the OSMBuildingLayer, fetches the OSM building data using Overpass API, converts it to GeoJSON using osmtogeojson API,
   * adds the GeoJSON data to the WorldWindow using the {@link GeoJSONParserTriangulation}.
   */
  OSMBuildingLayer.prototype.add = function () {

    var boundingBox = this.boundingBox;
    var worldWindow = this.worldWindow;
    var _self = this;

    var data = '[out:json][timeout:25];';
    data += '(' + this._type + '[' + this._tag + '](' + boundingBox[0] + ',' + boundingBox[1] + ',' + boundingBox[2] + ',' + boundingBox[3] + '); ';
    // data += 'relation[' + this._tag + '](' + boundingBox[0] + ',' + boundingBox[1] + ',' + boundingBox[2] + ',' + boundingBox[3] + ');); (._;>;); out body qt;';
    data += 'relation[' + this._tag + '](' + boundingBox[0] + ',' + boundingBox[1] + ',' + boundingBox[2] + ',' + boundingBox[3] + ');); out body; >; out skel qt;';
    // console.log("data --> " + data);

    $.ajax({
      url: 'http://overpass-api.de/api/interpreter',
      data: data,
      processData: false,
      contentType: false,
      type: 'POST',
      success: function (dataOverpass) {
        // console.log("dataOverpass --> " + JSON.stringify(dataOverpass));
        // var dataOverpassGeoJSON = osmtogeojson(dataOverpass, {flatProperties: true, polygonFeatures: {"building": true}});
        var dataOverpassGeoJSON = osmtogeojson(dataOverpass);
        var dataOverpassGeoJSONString = JSON.stringify(dataOverpassGeoJSON);
        // console.log("dataOverpassGeoJSONString --> " + dataOverpassGeoJSONString);
        // console.log("dataOverpassGeoJSON.features.length (number of polygons) --> " + dataOverpassGeoJSON.features.length);
        // console.time("creatingOSMBuildingLayer");
        var OSMBuildingLayer = new WorldWind.RenderableLayer("OSMBuildingLayer");
        var OSMBuildingLayerGeoJSON = new GeoJSONParserTriangulation(dataOverpassGeoJSONString);
        // var OSMBuildingLayerGeoJSON = new WorldWind.GeoJSONParser(dataOverpassGeoJSONString);
        OSMBuildingLayerGeoJSON.load(null, _self.shapeConfigurationCallback.bind(_self), OSMBuildingLayer);
        // console.timeEnd("creatingOSMBuildingLayer");
        worldWindow.addLayer(OSMBuildingLayer);
      },
      error: function (e) {
        console.log("Error: " + JSON.stringify(e));
      }
    });
  };

  return OSMBuildingLayer;
});
<commit_msg>added cache for the OSMBuildingLayer<commit_after>/**
 * @exports OSMBuildingLayer
 */
define(['libraries/WebWorldWind/src/WorldWind',
        'libraries/WebWorldWind/src/cache/MemoryCache',
        'src/OSMLayer',
        'src/GeoJSONParserTriangulation',
        'jquery',
        'osmtogeojson'],
       function (WorldWind, MemoryCache, OSMLayer, GeoJSONParserTriangulation, $, osmtogeojson) {
  "use strict";

  /**
   * Creates a sublass of the {@link OSMLayer} class.
   * @alias OSMBuildingLayer
   * @constructor
   * @classdesc Fetches OSM buildings, converts them to GeoJSON, and adds them to the WorldWindow.
   * @param {WorldWindow} worldWindow The WorldWindow where the OSMBuildingLayer is added to.
   * @param {Float[]} boundingBox It defines the bounding box of the OSM data for the OSMLayer. The order of coordinates of the bounding box is "x1, y1, x2, y2".
   * @param {Object} configuration Configuration is used to set the attributes of {@link ShapeAttributes}. Four more attributes can be defined, which are "extrude", "heatmap", "altitude" and "altitudeMode".
   */
  var OSMBuildingLayer = function (worldWindow, boundingBox, configuration) {
    OSMLayer.call(this, worldWindow, boundingBox, configuration);
    this.type = "way";
    this.tag = "building";
    this._geometryCache = new MemoryCache(30000, 24000);
    this._propertiesCache = new MemoryCache(50000, 40000);
  };

  OSMBuildingLayer.prototype = Object.create(OSMLayer.prototype);

  Object.defineProperties (OSMBuildingLayer.prototype, {
    /**
     * The cache for the geometry of each feature of the OSMBuildingLayer.
     * @memberof OSMBuildingLayer.prototype
     * @type {MemoryCache}
     */
    geometryCache: {
      get: function() {
        return this._geometryCache;
      },
      set: function(geometryCache) {
        this._geometryCache = geometryCache;
      }
    },
    /**
     * The cache for the properties of each feature of the OSMBuildingLayer.
     * @memberof OSMBuildingLayer.prototype
     * @type {MemoryCache}
     */
    propertiesCache: {
      get: function() {
        return this._propertiesCache;
      },
      set: function(propertiesCache) {
        this._propertiesCache = propertiesCache;
      }
    }
  });

  OSMBuildingLayer.prototype.cache = function(dataOverpassGeoJSON) {
    // console.log(JSON.stringify(dataOverpassGeoJSON));
    for (var featureIndex = 0; featureIndex < dataOverpassGeoJSON.features.length; featureIndex++) {
      this.geometryCache.putEntry(dataOverpassGeoJSON.features[featureIndex].id, dataOverpassGeoJSON.features[featureIndex].geometry, Object.keys(dataOverpassGeoJSON.features[featureIndex].geometry).length);
      this.propertiesCache.putEntry(dataOverpassGeoJSON.features[featureIndex].id, dataOverpassGeoJSON.features[featureIndex].properties, Object.keys(dataOverpassGeoJSON.features[featureIndex].properties).length);
      /* console.log(Object.keys(dataOverpassGeoJSON.features[featureIndex].geometry).length);
      console.log(dataOverpassGeoJSON.features[featureIndex].geometry);
      console.log(Object.keys(dataOverpassGeoJSON.features[featureIndex].properties).length);
      console.log(dataOverpassGeoJSON.features[featureIndex].properties); */
    }
    /* console.log(this.geometryCache);
    console.log(this.propertiesCache); */
  };

  /**
   * Sets the attributes of {@link ShapeAttributes} and three more attributes defined specifically for OSMBuildingLayer, which are "extrude", "altitude" and "altitudeMode".
   * @param {GeoJSONGeometry} geometry An object containing the geometry of the OSM data in GeoJSON format for the OSMBuildingLayer.
   * @returns {Object} An object with the attributes {@link ShapeAttributes} and four more attributes, which are "extrude", "heatmap", "altitude" and "altitudeMode", where all of them are defined in the configuration of the OSMBuildingLayer.
   */
  OSMBuildingLayer.prototype.shapeConfigurationCallback = function (geometry) {
    var configuration = OSMLayer.prototype.shapeConfigurationCallback.call(this, geometry);

    configuration.extrude = this.configuration.extrude ? this.configuration.extrude : false;
    configuration.heatmap = this.configuration.heatmap ? this.configuration.heatmap : undefined;
    if (configuration.heatmap) {
      configuration.heatmap.enabled = this.configuration.heatmap.enabled ? this.configuration.heatmap.enabled : false;
      configuration.heatmap.thresholds = this.configuration.heatmap.thresholds ? this.configuration.heatmap.thresholds : [0, 15, 900];
    }
    configuration.altitude = this.configuration.altitude ? this.configuration.altitude : 15;
    configuration.altitudeMode = this.configuration.altitudeMode ? this.configuration.altitudeMode : WorldWind.RELATIVE_TO_GROUND;

   // console.log(JSON.stringify(configuration));

    return configuration;
  };

  /**
   * Using the boundingBox of the OSMBuildingLayer, fetches the OSM building data using Overpass API, converts it to GeoJSON using osmtogeojson API,
   * adds the GeoJSON data to the WorldWindow using the {@link GeoJSONParserTriangulation}.
   */
  OSMBuildingLayer.prototype.add = function () {

    var boundingBox = this.boundingBox;
    var worldWindow = this.worldWindow;
    var _self = this;

    var data = '[out:json][timeout:25];';
    data += '(' + this._type + '[' + this._tag + '](' + boundingBox[0] + ',' + boundingBox[1] + ',' + boundingBox[2] + ',' + boundingBox[3] + '); ';
    // data += 'relation[' + this._tag + '](' + boundingBox[0] + ',' + boundingBox[1] + ',' + boundingBox[2] + ',' + boundingBox[3] + ');); (._;>;); out body qt;';
    data += 'relation[' + this._tag + '](' + boundingBox[0] + ',' + boundingBox[1] + ',' + boundingBox[2] + ',' + boundingBox[3] + ');); out body; >; out skel qt;';
    // console.log("data --> " + data);

    $.ajax({
      url: 'http://overpass-api.de/api/interpreter',
      data: data,
      processData: false,
      contentType: false,
      type: 'POST',
      success: function (dataOverpass) {
        // console.log("dataOverpass --> " + JSON.stringify(dataOverpass));
        // var dataOverpassGeoJSON = osmtogeojson(dataOverpass, {flatProperties: true, polygonFeatures: {"building": true}});
        var dataOverpassGeoJSON = osmtogeojson(dataOverpass);
        _self.cache(dataOverpassGeoJSON);
        var dataOverpassGeoJSONString = JSON.stringify(dataOverpassGeoJSON);
        // console.log("dataOverpassGeoJSONString --> " + dataOverpassGeoJSONString);
        // console.log("dataOverpassGeoJSON.features.length (number of polygons) --> " + dataOverpassGeoJSON.features.length);
        // console.time("creatingOSMBuildingLayer");
        var OSMBuildingLayer = new WorldWind.RenderableLayer("OSMBuildingLayer");
        var OSMBuildingLayerGeoJSON = new GeoJSONParserTriangulation(dataOverpassGeoJSONString);
        // var OSMBuildingLayerGeoJSON = new WorldWind.GeoJSONParser(dataOverpassGeoJSONString);
        OSMBuildingLayerGeoJSON.load(null, _self.shapeConfigurationCallback.bind(_self), OSMBuildingLayer);
        // console.timeEnd("creatingOSMBuildingLayer");
        worldWindow.addLayer(OSMBuildingLayer);
      },
      error: function (e) {
        console.log("Error: " + JSON.stringify(e));
      }
    });
  };

  return OSMBuildingLayer;
});
<|endoftext|>


<commit_before>// ensure lightbox is loaded before adding to it
function detailsReady() {
    var promise = new Promise(function(resolve,reject) {
        var inc = 40;
        var detailsListener = function(interval) {
            var lightbox = document.getElementsByClassName("window-title card-detail-title non-empty u-inline editable");
            if (lightbox.length != 0) {
                resolve("true");
            }
            else {
                interval = interval + 1 || 1;
                if (interval < inc) {
                    setTimeout(function() { detailsListener(interval); }, 100);
                } else {
                    reject("Lightbox Number Error");
                }
            }
        };
        detailsListener();
    });

    return promise;
}

// check that url has been added to card after it is created
// this is done asynchronously a few ms later
function hrefReady(obj) {
    var promise = new Promise(function(resolve,reject) {
        var inc = 40;
        var hrefListener = function(interval) {
            if (obj.getAttribute("href") != undefined) {
                resolve(obj.getAttribute("href"));
            } else {
                interval = interval + 1 || 1;
                if (interval < inc) {
                    setTimeout(function() { hrefListener(interval); }, 100);
                } else {
                    reject("Href timeout error");
                }
            }
        };
        hrefListener();
    });

    return promise;
}

function log(data) {
    console.log(data);
}

function addClassToArray(arr,klass) {
    var len = arr.length
    for (var i=0; i < len; i++) {
        var obj = arr[i];
        obj.className = obj.className + " " + klass;
    };
}

function addDisplayToArray(arr,style) {
    var len = arr.length;
    for (var i=0; i < len; i++) {
        var obj = arr[i];
        obj.style.display = style;
    }
}

function addClass(selector, newClass, display) {
    return function() {
        var objects = getByClass(selector);
        addClassToArray(objects, newClass);
        objects = getByClass(newClass);
        addDisplayToArray(objects, display);
    };
}

function hasClass(target, className) {
    className = " " + className + " ";
    if (target.className) {
        return (" " + target.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1
    }
    return false;
}

function getByClass(name) {
    return document.getElementsByClassName(name);
}

function getAncestorBySelector(elem, selector) {
    var node = elem;
    while (node.tagName != "BODY") {
        if (hasClass(node, selector)) {
            return node;
        }
        if (node.parentNode !== "undefined") {
            node = node.parentNode;
        } else {
            return null;
        }
    }
}

window.addEventListener("load", function() {
    var showListNumbers = addClass("list-header-num-cards", "trello-card-numbers-inline-block", "inline-block");
    showListNumbers();
    var showCardIds = addClass("card-short-id", "trello-card-numbers-inline", "inline");
    showCardIds();

    // show card numbers after card is inserted
    var target = document.querySelector("body");

    var config = { attributes: true, childList: true, subtree: true, characterData: true }

    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length > 0) {
                var node = mutation.addedNodes[0];
                var classes = node.classList;
                if (classes && classes.contains("search-result-card")) {
                    showCardIds();
                }
                if (classes) {
                    if ((classes.contains("list-card") && classes.contains("js-member-droppable")) || classes.contains("search-result-card")) {
                        showCardIds();
                        var card = node.querySelectorAll("a.list-card-title.js-card-name")[0];
                        if (card.getAttribute("href") == undefined) {
                            hrefReady(card).then(function(href) {
                                var title = href.split("/");
                                var s = title[title.length-1];
                                var num = s.substr(0,s.indexOf("-"));
                                var shortId = card.querySelector(".card-short-id");
                                shortId.innerHTML = "#" + num + " ";
                            }, function(err) {
                                log(err);
                            });
                        }
                    } else if (classes.contains("list")) {
                        showListNumbers();
                    }
                }
            }
        });
    });

    observer.observe(target,config);

    // add card number to card details lightbox
    document.body.addEventListener("mouseup", function(e) {
        var listCard =  getAncestorBySelector(e.target, 'list-card-details') || getAncestorBySelector(e.target, 'search-result-card');
        if (listCard) {
            var id = listCard.querySelectorAll(".card-short-id")[0].innerHTML;
            detailsReady().then(function() {

                // if/else needed to handle multiple promises
                var header = getByClass("trello-card-numbers-detail-header");
                if (header.length > 0) {
                    header.innerHTML = id;
                } else {
                    var obj = getByClass("window-title card-detail-title non-empty u-inline editable")[0];
                    obj.innerHTML = "
" + id + "
" + obj.innerHTML;
                }
            }, function (err) {
                log(err);
            });
        }
    }, true);
}, false);
<commit_msg>Refactor to use hasClass method, fix queuing ids error<commit_after>// ensure lightbox is loaded before adding to it
function detailsReady() {
    var promise = new Promise(function(resolve,reject) {
        var inc = 40;
        var detailsListener = function(interval) {
            var lightbox = document.getElementsByClassName("window-title card-detail-title non-empty u-inline editable");
            if (lightbox.length != 0) {
                resolve("true");
            }
            else {
                interval = interval + 1 || 1;
                if (interval < inc) {
                    setTimeout(function() { detailsListener(interval); }, 100);
                } else {
                    reject("Lightbox Timeout");
                }
            }
        };
        detailsListener();
    });

    return promise;
}

// check that url has been added to card after it is created
// this is done asynchronously a few ms later
function hrefReady(obj) {
    var promise = new Promise(function(resolve,reject) {
        var inc = 40;
        var hrefListener = function(interval) {
            if (obj.getAttribute("href") != undefined) {
                resolve(obj.getAttribute("href"));
            } else {
                interval = interval + 1 || 1;
                if (interval < inc) {
                    setTimeout(function() { hrefListener(interval); }, 100);
                } else {
                    reject("Href timeout error");
                }
            }
        };
        hrefListener();
    });

    return promise;
}

function log(data) {
    console.log(data);
}

function addClassToArray(arr,klass) {
    var len = arr.length
    for (var i=0; i < len; i++) {
        var obj = arr[i];
        obj.className = obj.className + " " + klass;
    };
}

function addDisplayToArray(arr,style) {
    var len = arr.length;
    for (var i=0; i < len; i++) {
        var obj = arr[i];
        obj.style.display = style;
    }
}

function addClassWithDisplay(selector, newClass, display) {
    return function() {
        var objects = getByClass(selector);
        addClassToArray(objects, newClass);
        objects = getByClass(newClass);
        addDisplayToArray(objects, display);
    };
}

function hasClass(target, className) {
    className = " " + className + " ";
    if (target.className) {
        return (" " + target.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1
    }
    return false;
}

function getByClass(name) {
    return document.getElementsByClassName(name);
}

function getAncestorBySelector(elem, selector) {
    var node = elem;
    while (node.tagName != "BODY") {
        if (hasClass(node, selector)) {
            return node;
        }
        if (node.parentNode !== "undefined") {
            node = node.parentNode;
        } else {
            return null;
        }
    }
}

window.addEventListener("load", function() {
    var showListNumbers = addClassWithDisplay("list-header-num-cards", "trello-card-numbers-inline-block", "inline-block");
    showListNumbers();
    var showCardIds = addClassWithDisplay("card-short-id", "trello-card-numbers-inline", "inline");
    showCardIds();

    // show card numbers after card is inserted
    var target = document.querySelector("body");
    var config = { attributes: true, childList: true, subtree: true, characterData: true }
    var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length > 0) {
                var node = mutation.addedNodes[0];
                var classes = node.classList;
                if (node.classList) {
                    if (hasClass(node, "search-result-card")) {
                        showCardIds();
                    }
                    else if (hasClass(node, "list-card") && hasClass(node, "js-member-droppable")) {
                        showCardIds();
                        var card = node.querySelectorAll("a.list-card-title.js-card-name")[0];
                        if (card.getAttribute("href") == undefined) {
                            hrefReady(card).then(function(href) {
                                var title = href.split("/");
                                var s = title[title.length-1];
                                var num = s.substr(0,s.indexOf("-"));
                                var shortId = card.querySelector(".card-short-id");
                                shortId.innerHTML = "#" + num + " ";
                            }, function(err) {
                                log(err);
                            });
                        }
                    } else if (classes.contains("list")) {
                        showListNumbers();
                    }
                }
            }
        });
    });

    observer.observe(target,config);

    // add card number to card details lightbox
    var id; // must set outside so each click overwrites the last id stored
    document.body.addEventListener("mouseup", function(e) {
        var listCard =  getAncestorBySelector(e.target, 'list-card-details') || getAncestorBySelector(e.target, 'search-result-card');
        if (listCard) {
            var cardId = listCard.querySelectorAll(".card-short-id")[0];
            if (cardId) {
                id = cardId.innerHTML;
                detailsReady().then(function() {

                    // if/else needed to handle multiple promises
                    var header = getByClass("trello-card-numbers-detail-header");
                    if (header.length > 0) {
                        header.innerHTML = id;
                    } else {
                        var obj = getByClass("window-title card-detail-title non-empty u-inline editable")[0];
                        obj.innerHTML = "
" + id + "
" + obj.innerHTML;
                    }
                }, function (err) {
                    null;
                });
            }
        }
    }, true);
}, false);
<|endoftext|>