<commit_before>'use strict';

define(["app"], function(app) {

app.controller('ModifColumnController', [
  "$scope", "Network", "$rootScope", "UnifiedRequestUtils", "Visibility",
  "PopupProvider", "ArrayUtils", "$http",
  function($scope, $network, $rootScope, $unifiedRequestUtils, $visibility,
    $popupProvider, $arrayUtils, $http) {

    //chrome memory leak !!!
    $scope.$destroy= function() {
        var parent = this.$parent;

        this.$broadcast('$destroy');

        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;

      //------- my additions -----------------------
      this.$id = null;
      this.$$phase = this.$parent = this.$$watchers =
                     this.$$nextSibling = this.$$prevSibling =
                     this.$$childHead = this.$$childTail = null;
      this['this'] = this.$root =  null;
      this.$$asyncQueue = null; // fixme: how this must be properly cleaned?
      this.$$listeners = null; // fixme: how this must be properly cleaned?

    }

    $scope.showModifyColumn = false;
    $scope.availableSocialNetworksWidth = "90%";
    $scope.column = undefined;
    $scope.selectedSocialNetwork = undefined;
    $scope.providers = undefined;
    $scope.columnsTitle = [];

    $rootScope.$on('displayViewMenu', function(evt, view) {
      if(view !== 'modifColumn') {
        $scope.showModifyColumn = false;
      }
    });

    $rootScope.$on('allColumns', function(evt, columns) {
      //to check unique title
      $scope.$apply(function() {
        for (var i = 0; i < columns.length; i++) {
          $scope.columnsTitle.push(new String(columns[i].title));
        };
      });
    });

    $rootScope.$on('allUnifiedRequests', function(evt, providers) {
      $scope.$apply(function() {
        $scope.providers = providers;
        for (var i = 0; i < providers.length; i++) {
          var provider = providers[i];
          provider.selected = false;
          provider.name = provider.endpoint;
          for (var j = 0; j < provider.services.length; j++) {
            var service = provider.services[j];
            var unifiedRequest = $unifiedRequestUtils.serverToUnifiedRequest(service);
            provider.services[j] = unifiedRequest;
          };
          if($scope.selectedSocialNetwork != undefined && $scope.selectedSocialNetwork.name == provider.name) {
            $scope.selectedSocialNetwork = provider;
            $scope.selectedSocialNetwork.selected = true;
          }
        };
        addGoogleReader();
        $rootScope.$broadcast('loading', {loading: false, translationCode: 'GET_TOKEN_PROGRESS'});
      });
    });

    $rootScope.$on('clientModifyColumn', function(evt, column) {
      $scope.show(JSON.parse(JSON.stringify(column)));//reset view & download providers (if needed)
    });

    $rootScope.$on('addColumn', function(evt, column) {
      $scope.columnsTitle.push(new String(column.title));
    });

    $rootScope.$on('modColumn', function(evt, column) {
      $scope.$apply(function() {
        //refresh name
        for (var i = 0; i < $scope.columnsTitle.length; i++) {
          if($scope.columnsTitle[i] == column.title) {
            $scope.columnsTitle.splice(i, 1);
            $scope.columnsTitle.push(new String(column.column.title));
            break;
          }
        };
      });
    });

    $rootScope.$on('delColumn', function(evt, column) {
      var index = $arrayUtils.indexOfWith($scope.columnsTitle, column, function(inArray, column) {
        return inArray == column.title;
      });
      if(index > -1) {
        $scope.columnsTitle.splice(index, 1);
        $scope.$apply();
      }
    });

    $scope.show = function(column) {
      resetView();
      $scope.showModifyColumn = !$scope.showModifyColumn;
      if ($scope.showModifyColumn == true) {
        if($scope.providers == undefined) {
          $network.send({cmd:"allUnifiedRequests"});
        }
        if(column !== undefined) {//modif column
          $scope.column = column;
          $scope.column.newColumn = false;
          $scope.column.oldTitle = $scope.column.title;
        } else {//new column
          $scope.column = {};
          $scope.column.newColumn = true;
          $scope.column.title = "";
          $scope.column.unifiedRequests = [];
        }
        $rootScope.$broadcast('displayViewMenu', 'modifColumn');
      }
    };

    $scope.selectSocialNetwork = function(socialNetwork) {
      if($scope.selectedSocialNetwork != undefined) {
        $scope.selectedSocialNetwork.selected = false;
      }
      $scope.selectedSocialNetwork = socialNetwork;
      $scope.selectedSocialNetwork.selected = true;
      $scope.availableSocialNetworksWidth = "";
      if(socialNetwork.name == "greader") {
        selectGreader();
      } else {
        $scope.googleReaderSelected = false;
      }
    }

    $scope.addService = function(service) {
      if(service.hasParser == true) {
        if($scope.selectedSocialNetwork.hasToken == true) {
          addService(service);
        } else {
          $popupProvider.openPopup($scope.selectedSocialNetwork, function() {
            addService(service);
            $network.send({cmd:"allUnifiedRequests"});
            $network.send({cmd:"allPosters"});
          });
        }
      }
    }

    function addService(service) {
      console.log(service);
      service.fromServer = false;
      $scope.column.unifiedRequests.push(JSON.parse(JSON.stringify(service)));//clone service
      if($scope.column.title == "") {
        $scope.column.title = service.providerName + " " + service.serviceName;
      }
    }

    $scope.selectOracle = function(arg, value) {
      arg.possibleValues = [];
      arg.value = value.call;
    }

    $scope.cancelCreateColumn = function() {
      resetView();
      $scope.showModifyColumn = false;
    }

    $scope.deleteService = function(service, arg) {
      var found = false;
      for (var i = 0; !found && i < $scope.column.unifiedRequests.length; i++) {
        if($scope.column.unifiedRequests[i].service == service.service &&
            $scope.column.unifiedRequests[i].args.length > 0) {
          for (var j = 0; !found && j < $scope.column.unifiedRequests[i].args.length; j++) {
            var a = $scope.column.unifiedRequests[i].args[j];
            if(arg.key == a.key && arg.value == a.value) {
              found = true;
              $scope.column.unifiedRequests.splice(i,1);
            }
          }
        }
        else if($scope.column.unifiedRequests[i].service == service.service && arg === undefined) {
          found = true;
          $scope.column.unifiedRequests.splice(i,1);
        }
      }
    }

    $scope.validate = function() {
      var json = "";
      var unifiedRequests = [];
      var column = $scope.column;
      for (var i = 0; i < column.unifiedRequests.length; i++) {
        unifiedRequests.push($unifiedRequestUtils.clientToServerUnifiedRequest(column.unifiedRequests[i]));
      };
      if(column.newColumn == false) {
        json = {
          "cmd": "modColumn",
          "body": {
            "title": column.oldTitle,
            "column": {
              "title": column.title,
              "unifiedRequests": unifiedRequests,
              "index": column.index,
              "width": column.width,
              "height": column.height
            }
          }
        };
      } else {
        json = {
          "cmd": "addColumn",
          "body": {
            "title": column.title,
            "unifiedRequests": unifiedRequests,
            "index": $scope.columnsTitle.length,
            "width": -1,
            "height": -1
          }
        };
      }

      $scope.showErrorBlankArg = checkErrorEmptyArg(column);
      $scope.showErrorDoubleParser = checkErrorDoubleParser(column);
      $scope.showErrorTitleRequired = checkErrorEmptyTitle(column);
      $scope.showErrorTitleAlreadyExist = checkErrorTitleAlreadyExist(column);

      if ($scope.showErrorBlankArg == false &&
          $scope.showErrorDoubleParser == false &&
          $scope.showErrorTitleRequired == false &&
          $scope.showErrorTitleAlreadyExist == false) {
        $scope.showModifyColumn = !$scope.showModifyColumn;
        $network.send(json);
      }
    }

    $scope.deleteColumn = function() {
      $network.send({
        "cmd": "delColumn",
        "body": {"title": $scope.column.oldTitle}
      });
      $scope.showModifyColumn = false;
    }

    function resetView() {
      $scope.availableSocialNetworksWidth = "90%";
      if($scope.selectedSocialNetwork != undefined) {
        $scope.selectedSocialNetwork.selected = false;
      }
      $scope.selectedSocialNetwork = undefined;
      $scope.showErrorBlankArg = false;
      $scope.showErrorDoubleParser = false;
      $scope.showErrorTitleRequired = false;
      $scope.showErrorTitleAlreadyExist = false;
      if($scope.column !== undefined) {
        $scope.column.title = $scope.column.oldTitle;
        for (var i = $scope.column.unifiedRequests.length - 1; i >= 0; i--) {
          if($scope.column.unifiedRequests[i].fromServer == false) {
            $scope.column.unifiedRequests.splice(i, 1);
          }
        };
      }
      $scope.column = undefined;
    }

    // ###################################
    // # ERRORS CHECK : ALL CHECK ERROR RETURN TRUE IF ERROR
    // ###################################

    var cleanRegex = /[&\\#,+()$~%'":*?<>{}]/g;

    function checkErrorEmptyArg(column) {
      for (var i = 0; i < column.unifiedRequests.length; i++) {
        for (var j = 0; j < column.unifiedRequests[i].args.length; j++) {
          column.unifiedRequests[i].args[j].value = column.unifiedRequests[i].args[j].value.replace(cleanRegex, '');
          if (column.unifiedRequests[i].args[j].value == "") {
            return true;
          }
        };
      };
      return false;
    }

    function checkErrorDoubleParser(column) {
      var nbServiceFound = 0;
      var nbArgFound = 0;
      for (var i = 0; i < column.unifiedRequests.length; i++) {
        nbServiceFound = 0;
        nbArgFound = 0;
        for (var u = 0; u < column.unifiedRequests.length; u++) {
          if(column.unifiedRequests[i].args.length > 0) {
            for (var j = 0; j < column.unifiedRequests[i].args.length; j++) {
              for (var h = 0; h < column.unifiedRequests[u].args.length; h++) {
                if (column.unifiedRequests[i].service == column.unifiedRequests[u].service &&
                  column.unifiedRequests[i].args[j].value == column.unifiedRequests[u].args[h].value) {
                  nbArgFound++;
                }
              };
              if(nbArgFound > 1) {
                return true;
              }
            };
          } else if(column.unifiedRequests[i].service == column.unifiedRequests[u].service) {
            nbServiceFound++;
          }
        };
        if(nbServiceFound > 1) {
          return true;
        }
      };
      return false;
    }

    function checkErrorEmptyTitle(column) {
      return column.title == "";
    }

    function checkErrorTitleAlreadyExist(column) {
      var nb = 0;
      for (var i = 0; i < $scope.columnsTitle.length; i++) {
        if($scope.columnsTitle[i] == column.title) {
          nb++;
          if(column.newColumn == false && nb > 1) {
            return true;
          } else if(column.newColumn == true) {
            return true;
          }
        }
      };
      return false;
    }

    //GOOGLE READER HACK

    $scope.googleReaderSelected = false;
    $scope.googleReaderFeeds = "";

    function addGoogleReader() {
      $scope.providers.push({
        endpoint: "greader",
        hasToken: true,
        name: "greader",
        selected: false,
        services:[]
      });
    }

    function selectGreader() {
      console.log("show");
      $scope.googleReaderSelected = true;
    }

    $scope.parseGoogleReader = function() {
      console.log("parse");
      var feeds = JSON.parse($scope.googleReaderFeeds).subscriptions;
      for (var i = 0; i < feeds.length; i++) {
        var url = feeds[i].id.substring(5, feeds[i].id.length);
        addService({
          fromServer: false,
          hasArguments: true,
          hasParser: true,
          providerName: "rss",
          service: "rss.rss",
          serviceName: "rss",
          args: [{
            key: "url",
            value: url
          }]
        });
      };
    }

}]);

return app;
});
<commit_msg>fix bug on modif column "title already exist"<commit_after>'use strict';

define(["app"], function(app) {

app.controller('ModifColumnController', [
  "$scope", "Network", "$rootScope", "UnifiedRequestUtils", "Visibility",
  "PopupProvider", "ArrayUtils", "$http",
  function($scope, $network, $rootScope, $unifiedRequestUtils, $visibility,
    $popupProvider, $arrayUtils, $http) {

    //chrome memory leak !!!
    $scope.$destroy= function() {
        var parent = this.$parent;

        this.$broadcast('$destroy');

        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;

      //------- my additions -----------------------
      this.$id = null;
      this.$$phase = this.$parent = this.$$watchers =
                     this.$$nextSibling = this.$$prevSibling =
                     this.$$childHead = this.$$childTail = null;
      this['this'] = this.$root =  null;
      this.$$asyncQueue = null; // fixme: how this must be properly cleaned?
      this.$$listeners = null; // fixme: how this must be properly cleaned?

    }

    $scope.showModifyColumn = false;
    $scope.availableSocialNetworksWidth = "90%";
    $scope.column = undefined;
    $scope.selectedSocialNetwork = undefined;
    $scope.providers = undefined;
    $scope.columnsTitle = [];

    $rootScope.$on('displayViewMenu', function(evt, view) {
      if(view !== 'modifColumn') {
        $scope.showModifyColumn = false;
      }
    });

    $rootScope.$on('allColumns', function(evt, columns) {
      //to check unique title
      $scope.columnsTitle = [];
      $scope.$apply(function() {
        for (var i = 0; i < columns.length; i++) {
          $scope.columnsTitle.push(new String(columns[i].title));
        };
      });
    });

    $rootScope.$on('allUnifiedRequests', function(evt, providers) {
      $scope.$apply(function() {
        $scope.providers = providers;
        for (var i = 0; i < providers.length; i++) {
          var provider = providers[i];
          provider.selected = false;
          provider.name = provider.endpoint;
          for (var j = 0; j < provider.services.length; j++) {
            var service = provider.services[j];
            var unifiedRequest = $unifiedRequestUtils.serverToUnifiedRequest(service);
            provider.services[j] = unifiedRequest;
          };
          if($scope.selectedSocialNetwork != undefined && $scope.selectedSocialNetwork.name == provider.name) {
            $scope.selectedSocialNetwork = provider;
            $scope.selectedSocialNetwork.selected = true;
          }
        };
        addGoogleReader();
        $rootScope.$broadcast('loading', {loading: false, translationCode: 'GET_TOKEN_PROGRESS'});
      });
    });

    $rootScope.$on('clientModifyColumn', function(evt, column) {
      $scope.show(JSON.parse(JSON.stringify(column)));//reset view & download providers (if needed)
    });

    $rootScope.$on('addColumn', function(evt, column) {
      $scope.columnsTitle.push(new String(column.title));
    });

    $rootScope.$on('modColumn', function(evt, column) {
      $scope.$apply(function() {
        //refresh name
        for (var i = 0; i < $scope.columnsTitle.length; i++) {
          if($scope.columnsTitle[i] == column.title) {
            $scope.columnsTitle.splice(i, 1);
            $scope.columnsTitle.push(new String(column.column.title));
            break;
          }
        };
      });
    });

    $rootScope.$on('delColumn', function(evt, column) {
      var index = $arrayUtils.indexOfWith($scope.columnsTitle, column, function(inArray, column) {
        return inArray == column.title;
      });
      if(index > -1) {
        $scope.columnsTitle.splice(index, 1);
        $scope.$apply();
      }
    });

    $scope.show = function(column) {
      resetView();
      $scope.showModifyColumn = !$scope.showModifyColumn;
      if ($scope.showModifyColumn == true) {
        if($scope.providers == undefined) {
          $network.send({cmd:"allUnifiedRequests"});
        }
        if(column !== undefined) {//modif column
          $scope.column = column;
          $scope.column.newColumn = false;
          $scope.column.oldTitle = $scope.column.title;
        } else {//new column
          $scope.column = {};
          $scope.column.newColumn = true;
          $scope.column.title = "";
          $scope.column.unifiedRequests = [];
        }
        $rootScope.$broadcast('displayViewMenu', 'modifColumn');
      }
    };

    $scope.selectSocialNetwork = function(socialNetwork) {
      if($scope.selectedSocialNetwork != undefined) {
        $scope.selectedSocialNetwork.selected = false;
      }
      $scope.selectedSocialNetwork = socialNetwork;
      $scope.selectedSocialNetwork.selected = true;
      $scope.availableSocialNetworksWidth = "";
      if(socialNetwork.name == "greader") {
        selectGreader();
      } else {
        $scope.googleReaderSelected = false;
      }
    }

    $scope.addService = function(service) {
      if(service.hasParser == true) {
        if($scope.selectedSocialNetwork.hasToken == true) {
          addService(service);
        } else {
          $popupProvider.openPopup($scope.selectedSocialNetwork, function() {
            addService(service);
            $network.send({cmd:"allUnifiedRequests"});
            $network.send({cmd:"allPosters"});
          });
        }
      }
    }

    function addService(service) {
      console.log(service);
      service.fromServer = false;
      $scope.column.unifiedRequests.push(JSON.parse(JSON.stringify(service)));//clone service
      if($scope.column.title == "") {
        $scope.column.title = service.providerName + " " + service.serviceName;
      }
    }

    $scope.selectOracle = function(arg, value) {
      arg.possibleValues = [];
      arg.value = value.call;
    }

    $scope.cancelCreateColumn = function() {
      resetView();
      $scope.showModifyColumn = false;
    }

    $scope.deleteService = function(service, arg) {
      var found = false;
      for (var i = 0; !found && i < $scope.column.unifiedRequests.length; i++) {
        if($scope.column.unifiedRequests[i].service == service.service &&
            $scope.column.unifiedRequests[i].args.length > 0) {
          for (var j = 0; !found && j < $scope.column.unifiedRequests[i].args.length; j++) {
            var a = $scope.column.unifiedRequests[i].args[j];
            if(arg.key == a.key && arg.value == a.value) {
              found = true;
              $scope.column.unifiedRequests.splice(i,1);
            }
          }
        }
        else if($scope.column.unifiedRequests[i].service == service.service && arg === undefined) {
          found = true;
          $scope.column.unifiedRequests.splice(i,1);
        }
      }
    }

    $scope.validate = function() {
      var json = "";
      var unifiedRequests = [];
      var column = $scope.column;
      for (var i = 0; i < column.unifiedRequests.length; i++) {
        unifiedRequests.push($unifiedRequestUtils.clientToServerUnifiedRequest(column.unifiedRequests[i]));
      };
      if(column.newColumn == false) {
        json = {
          "cmd": "modColumn",
          "body": {
            "title": column.oldTitle,
            "column": {
              "title": column.title,
              "unifiedRequests": unifiedRequests,
              "index": column.index,
              "width": column.width,
              "height": column.height
            }
          }
        };
      } else {
        json = {
          "cmd": "addColumn",
          "body": {
            "title": column.title,
            "unifiedRequests": unifiedRequests,
            "index": $scope.columnsTitle.length,
            "width": -1,
            "height": -1
          }
        };
      }

      $scope.showErrorBlankArg = checkErrorEmptyArg(column);
      $scope.showErrorDoubleParser = checkErrorDoubleParser(column);
      $scope.showErrorTitleRequired = checkErrorEmptyTitle(column);
      $scope.showErrorTitleAlreadyExist = checkErrorTitleAlreadyExist(column);

      if ($scope.showErrorBlankArg == false &&
          $scope.showErrorDoubleParser == false &&
          $scope.showErrorTitleRequired == false &&
          $scope.showErrorTitleAlreadyExist == false) {
        $scope.showModifyColumn = !$scope.showModifyColumn;
        $network.send(json);
      }
    }

    $scope.deleteColumn = function() {
      $network.send({
        "cmd": "delColumn",
        "body": {"title": $scope.column.oldTitle}
      });
      $scope.showModifyColumn = false;
    }

    function resetView() {
      $scope.availableSocialNetworksWidth = "90%";
      if($scope.selectedSocialNetwork != undefined) {
        $scope.selectedSocialNetwork.selected = false;
      }
      $scope.selectedSocialNetwork = undefined;
      $scope.showErrorBlankArg = false;
      $scope.showErrorDoubleParser = false;
      $scope.showErrorTitleRequired = false;
      $scope.showErrorTitleAlreadyExist = false;
      if($scope.column !== undefined) {
        $scope.column.title = $scope.column.oldTitle;
        for (var i = $scope.column.unifiedRequests.length - 1; i >= 0; i--) {
          if($scope.column.unifiedRequests[i].fromServer == false) {
            $scope.column.unifiedRequests.splice(i, 1);
          }
        };
      }
      $scope.column = undefined;
    }

    // ###################################
    // # ERRORS CHECK : ALL CHECK ERROR RETURN TRUE IF ERROR
    // ###################################

    var cleanRegex = /[&\\#,+()$~%'":*?<>{}]/g;

    function checkErrorEmptyArg(column) {
      for (var i = 0; i < column.unifiedRequests.length; i++) {
        for (var j = 0; j < column.unifiedRequests[i].args.length; j++) {
          column.unifiedRequests[i].args[j].value = column.unifiedRequests[i].args[j].value.replace(cleanRegex, '');
          if (column.unifiedRequests[i].args[j].value == "") {
            return true;
          }
        };
      };
      return false;
    }

    function checkErrorDoubleParser(column) {
      var nbServiceFound = 0;
      var nbArgFound = 0;
      for (var i = 0; i < column.unifiedRequests.length; i++) {
        nbServiceFound = 0;
        nbArgFound = 0;
        for (var u = 0; u < column.unifiedRequests.length; u++) {
          if(column.unifiedRequests[i].args.length > 0) {
            for (var j = 0; j < column.unifiedRequests[i].args.length; j++) {
              for (var h = 0; h < column.unifiedRequests[u].args.length; h++) {
                if (column.unifiedRequests[i].service == column.unifiedRequests[u].service &&
                  column.unifiedRequests[i].args[j].value == column.unifiedRequests[u].args[h].value) {
                  nbArgFound++;
                }
              };
              if(nbArgFound > 1) {
                return true;
              }
            };
          } else if(column.unifiedRequests[i].service == column.unifiedRequests[u].service) {
            nbServiceFound++;
          }
        };
        if(nbServiceFound > 1) {
          return true;
        }
      };
      return false;
    }

    function checkErrorEmptyTitle(column) {
      return column.title == "";
    }

    function checkErrorTitleAlreadyExist(column) {
      var nb = 0;
      for (var i = 0; i < $scope.columnsTitle.length; i++) {
        if($scope.columnsTitle[i] == column.title) {
          nb++;
          if(column.newColumn == false && nb > 1) {
            return true;
          } else if(column.newColumn == true) {
            return true;
          }
        }
      };
      return false;
    }

    //GOOGLE READER HACK

    $scope.googleReaderSelected = false;
    $scope.googleReaderFeeds = "";

    function addGoogleReader() {
      $scope.providers.push({
        endpoint: "greader",
        hasToken: true,
        name: "greader",
        selected: false,
        services:[]
      });
    }

    function selectGreader() {
      console.log("show");
      $scope.googleReaderSelected = true;
    }

    $scope.parseGoogleReader = function() {
      console.log("parse");
      var feeds = JSON.parse($scope.googleReaderFeeds).subscriptions;
      for (var i = 0; i < feeds.length; i++) {
        var url = feeds[i].id.substring(5, feeds[i].id.length);
        addService({
          fromServer: false,
          hasArguments: true,
          hasParser: true,
          providerName: "rss",
          service: "rss.rss",
          serviceName: "rss",
          args: [{
            key: "url",
            value: url
          }]
        });
      };
    }

}]);

return app;
});
<|endoftext|>


<commit_before>/**
 * The UMD loss map layer view.
 *
 * @return BiomassLossLayer class (extends CanvasLayerClass)
 */
define([
  'd3',
  'moment',
  'uri',
  'abstract/layer/CanvasLayerClass',
  'map/presenters/layers/UMDLossLayerPresenter'
], function(d3, moment, UriTemplate, CanvasLayerClass, Presenter) {

  'use strict';

  var BiomassLossLayer = CanvasLayerClass.extend({

    options: {
      threshold: 30,
      dataMaxZoom: 12,
      urlTemplate: 'http://storage.googleapis.com/earthenginepartners-wri/whrc-hansen-carbon-{threshold}-{z}{/x}{/y}.png'
    },

    init: function(layer, options, map) {
      this.presenter = new Presenter(this);
      if (!! options.currentDate && (options.currentDate[0] > options.currentDate[1])) {
        var kllm = options.currentDate[1];
        options.currentDate[1] = options.currentDate[0];
        options.currentDate[0] = kllm;
        kllm = null;
      }
      this.currentDate = options.currentDate || [moment(layer.mindate), moment(layer.maxdate)];
      this.threshold = options.threshold || this.options.threshold;
      this._super(layer, options, map);
    },

    /**
     * Filters the canvas imgdata.
     * @override
     */
    filterCanvasImgdata: function(imgdata, w, h, z) {
      var components = 4;
      var exp = z < 11 ? 0.3 + ((z - 3) / 20) : 1;
      if (! !!this.currentDate[0]._d) {
       this.currentDate[0] = moment(this.currentDate[0]);
       this.currentDate[1] = moment(this.currentDate[1]);
      }
      var yearStart = this.currentDate[0].year();
      var yearEnd = this.currentDate[1].year();

      var myscale = d3.scale.pow()
         .exponent(exp)
         .domain([0,256])
         .range([0,256]);

      for(var i = 0; i < w; ++i) {
       for(var j = 0; j < h; ++j) {
         var pixelPos = (j * w + i) * components;
         var intensity = imgdata[pixelPos+1];
         var yearLoss = 2001 + imgdata[pixelPos];

         //intensity=z < 13 ? (intensity)=Math.pow (2, (12-z)) : intensity;

         if (yearLoss >= yearStart && yearLoss <= yearEnd) {

          imgdata[pixelPos] = 0;
          if (myscale(intensity) < 1){
               imgdata[pixelPos + 3] = imgdata[pixelPos + 2] = imgdata[pixelPos + 1] = 0;
           }
          else if (myscale(intensity) < 50){
               imgdata[pixelPos + 1] = 112;
               imgdata[pixelPos + 2] = 168;
               imgdata[pixelPos + 3] = 256;
          }
          else if (myscale(intensity) < 100){
               imgdata[pixelPos]     = 76;
               imgdata[pixelPos + 1] = 83;
               imgdata[pixelPos + 2] = 122;
               imgdata[pixelPos + 3] = 255;
           }
          else if (myscale(intensity) < 150){
               imgdata[pixelPos]     = 210;
               imgdata[pixelPos + 1] = 31;
               imgdata[pixelPos + 2] = 38;
               imgdata[pixelPos + 3] = 255;
          }
          else if (myscale(intensity) < 200){
               imgdata[pixelPos]     = 241;
               imgdata[pixelPos + 1] = 152;
               imgdata[pixelPos + 2] = 19;
               imgdata[pixelPos + 3] = 255;
          }
          else if (myscale(intensity) < 256){
               imgdata[pixelPos + 3] = imgdata[pixelPos] = 255;
               imgdata[pixelPos + 1] = 208;
               imgdata[pixelPos + 2] = 11;
          }
        } else {
          imgdata[pixelPos + 3] = 0;
        }
       }
      }
    },

    /**
     * Used by UMDLoassLayerPresenter to set the dates for the tile.
     *
     * @param {Array} date 2D array of moment dates [begin, end]
     */
    setCurrentDate: function(date) {
      this.currentDate = date;
      this.updateTiles();
    },

    setThreshold: function(threshold) {
      this.threshold = threshold;
      this.presenter.updateLayer();
    },

    _getUrl: function(x, y, z) {
      return new UriTemplate(this.options.urlTemplate)
        .fillFromObject({x: x, y: y, z: z, threshold: this.threshold});
    }

  });

  return BiomassLossLayer;
});
<commit_msg>cleaning<commit_after>/**
 * The UMD loss map layer view.
 *
 * @return BiomassLossLayer class (extends CanvasLayerClass)
 */
define([
  'd3',
  'moment',
  'uri',
  'abstract/layer/CanvasLayerClass',
  'map/presenters/layers/UMDLossLayerPresenter'
], function(d3, moment, UriTemplate, CanvasLayerClass, Presenter) {

  'use strict';

  var BiomassLossLayer = CanvasLayerClass.extend({

    options: {
      threshold: 30,
      dataMaxZoom: 12,
      urlTemplate: 'http://storage.googleapis.com/earthenginepartners-wri/whrc-hansen-carbon-{threshold}-{z}{/x}{/y}.png'
    },

    init: function(layer, options, map) {
      this.presenter = new Presenter(this);
      if (!! options.currentDate && (options.currentDate[0] > options.currentDate[1])) {
        var kllm = options.currentDate[1];
        options.currentDate[1] = options.currentDate[0];
        options.currentDate[0] = kllm;
        kllm = null;
      }
      this.currentDate = options.currentDate || [moment(layer.mindate), moment(layer.maxdate)];
      this.threshold = options.threshold || this.options.threshold;
      this._super(layer, options, map);
    },

    /**
     * Filters the canvas imgdata.
     * @override
     */
    filterCanvasImgdata: function(imgdata, w, h, z) {
      var components = 4;
      var exp = z < 11 ? 0.3 + ((z - 3) / 20) : 1;
      if (! !!this.currentDate[0]._d) {
       this.currentDate[0] = moment(this.currentDate[0]);
       this.currentDate[1] = moment(this.currentDate[1]);
      }
      var yearStart = this.currentDate[0].year();
      var yearEnd = this.currentDate[1].year();

      var myscale = d3.scale.pow()
         .exponent(exp)
         .domain([0,256])
         .range([0,256]);

      for(var i = 0; i < w; ++i) {
       for(var j = 0; j < h; ++j) {
         var pixelPos = (j * w + i) * components;
         var intensity = imgdata[pixelPos+1];
         var yearLoss = 2001 + imgdata[pixelPos];

         //intensity=z < 13 ? (intensity)=Math.pow (2, (12-z)) : intensity;

         if (yearLoss >= yearStart && yearLoss <= yearEnd) {
          imgdata[pixelPos] = 0;
          if (myscale(intensity) < 1){
               imgdata[pixelPos + 3] = imgdata[pixelPos + 2] = imgdata[pixelPos + 1] = 0;
           }
          else if (myscale(intensity) < 50){
               imgdata[pixelPos + 1] = 112;
               imgdata[pixelPos + 2] = 168;
               imgdata[pixelPos + 3] = 256;
          }
          else if (myscale(intensity) < 100){
               imgdata[pixelPos]     = 76;
               imgdata[pixelPos + 1] = 83;
               imgdata[pixelPos + 2] = 122;
               imgdata[pixelPos + 3] = 255;
           }
          else if (myscale(intensity) < 150){
               imgdata[pixelPos]     = 210;
               imgdata[pixelPos + 1] = 31;
               imgdata[pixelPos + 2] = 38;
               imgdata[pixelPos + 3] = 255;
          }
          else if (myscale(intensity) < 200){
               imgdata[pixelPos]     = 241;
               imgdata[pixelPos + 1] = 152;
               imgdata[pixelPos + 2] = 19;
               imgdata[pixelPos + 3] = 255;
          }
          else if (myscale(intensity) < 256){
               imgdata[pixelPos + 3] = imgdata[pixelPos] = 255;
               imgdata[pixelPos + 1] = 208;
               imgdata[pixelPos + 2] = 11;
          }
        } else {
          imgdata[pixelPos + 3] = 0;
        }
       }
      }
    },

    /**
     * Used by UMDLoassLayerPresenter to set the dates for the tile.
     *
     * @param {Array} date 2D array of moment dates [begin, end]
     */
    setCurrentDate: function(date) {
      this.currentDate = date;
      this.updateTiles();
    },

    setThreshold: function(threshold) {
      this.threshold = threshold;
      this.presenter.updateLayer();
    },

    _getUrl: function(x, y, z) {
      return new UriTemplate(this.options.urlTemplate)
        .fillFromObject({x: x, y: y, z: z, threshold: this.threshold});
    }

  });

  return BiomassLossLayer;
});
<|endoftext|>


<commit_before>const CurrencyMethods = require('./currency_methods');
const GlobalEvents = require('../../shared/global_events');

const Fundraiser = Backbone.View.extend(_.extend(CurrencyMethods, {
  el: '.fundraiser-bar',

  events: {
    'click .fundraiser-bar__step-name--past': 'triggerStepChange',
    'click .fundraiser-bar__step-number--past': 'triggerStepChange',
    'focus .fundraiser-bar__custom-field': 'primeCustom',
    'blur  .fundraiser-bar__custom-field': 'resetCustom',
    'click .fundraiser-bar__amount-button': 'advanceToDetails',
    'click .fundraiser-bar__first-continue': 'advanceToDetails',
    'click .action-form__clear-form': 'showSecondStep',
    'ajax:success form.action-form': 'advanceToNextStep',
    'submit form#hosted-fields': 'disableButton',
    'change select.fundraiser-bar__currency-selector': 'switchCurrency',
    'change input.fundraiser-bar__recurring': 'updateButton',
    'click .fundraiser-bar__engage-currency-switcher': 'showCurrencySwitcher',
    'click .hosted-fields__direct-debit': 'submitDirectDebit',
    'click .fundraiser-bar__submit-one-click': 'submitOneClick',
    'click .fundraiser-bar__toggle-payment-method': 'toggleOneClickVisibility',
  },

  globalEvents: {
    'fundraiser:server_error': 'enableButton',
    'fundraiser:nonce_received': 'submitDonation',
  },

  // options: object with any of the following keys
  //    followUpUrl: the url to redirect to after success
  //    submissionCallback: a function to call after success, receives the
  //      arguments received by the ajax call posting the donation
  //    currency: the three letter capitalized currency code to use
  //    amount: a preselected donation amount, if > 0 the first step will be skipped
  //    showDirectDebit: boolean, whether to show the direct debit option
  //    donationBands: an object with three letter currency codes as keys
  //    recurringDefault: either 'donation', 'recurring', or 'only_recurring'
  //    pageId: the ID of the plugin's page database record.
  //      and array of numbers, integers or floats, to display as donation amounts
  initialize(options = {}) {
    this.initializeCurrency(options.currency, options.donationBands)
    this.changeStep(1);
    this.donationAmount = 0;
    this.followUpUrl = options.followUpUrl;
    if (typeof options.submissionCallback === 'function') {
      this.submissionCallback = options.submissionCallback;
    }
    this.initializeSkipping(options);
    this.pageId = options.pageId;
    this.directDebitOpened = false;
    this.displayDirectDebit(options.showDirectDebit);
    this.initializeRecurring(options.recurringDefault);
    this.updateButton();
    this.paymentMethods = options.paymentMethods || [];
    this.setOneClickVisibility();
    GlobalEvents.bindEvents(this);
  },

  initializeRecurring(recurringDefault) {
    const $checkbox = this.$('input.fundraiser-bar__recurring');
    switch(recurringDefault) {
      case 'only_recurring':
        $checkbox.parents('.form__group').addClass('hidden-irrelevant');
        // deliberate fall-through to next case (no break)
      case 'recurring':
        $checkbox.prop('checked', true);
        break;
      default:
        $checkbox.prop('checked', false);
    }
  },

  initializeSkipping(options){
    if (options.amount > 0) {
      this.setDonationAmount(options.amount);
    }
    this.hidingStepTwo = false;
    let amountKnown = (options.amount > 0); // non-numbers with > are always false
    let formComplete = this.$('.action-form').data('prefilled');
    this.hideSteps(amountKnown, formComplete);
  },

  hideSteps(amountKnown, formComplete) {
    if (amountKnown && formComplete) {
      this.changeStep(3);
      this.hideSecondStep();
    } else if (formComplete) {
      this.hideSecondStep();
    } else if (amountKnown) {
      this.changeStep(2);
    }
  },

  hideSecondStep() {
    this.$('.fundraiser-bar__steps').addClass('fundraiser-bar__steps--two-step');
    this.$('.fundraiser-bar__step-label[data-step="2"]').css('visibility', 'hidden');
    this.$('.fundraiser-bar__step-number[data-step="3"]').text(2);
    this.hidingStepTwo = true;
  },

  showSecondStep() {
    this.$('.fundraiser-bar__steps').removeClass('fundraiser-bar__steps--two-step');
    this.$('.fundraiser-bar__welcome-text').addClass('hidden-irrelevant');
    this.$('.fundraiser-bar__step-label[data-step="2"]').css('visibility', 'visible');
    this.$('.fundraiser-bar__step-number[data-step="3"]').text(3);
    Backbone.trigger('form:clear');
    this.hidingStepTwo = false;
    this.changeStep(2);
  },

  primeCustom(e) {
    let $field = this.$(e.target);
    if ($field.val() == '') {
      $field[0].value = this.CURRENCY_SYMBOLS[this.currency];
    }
    this.$('.fundraiser-bar__first-continue').slideDown(200);
  },

  resetCustom(e) {
    let $field = this.$(e.target);
    let currencySymbols = /^[\$\u20ac\u00a3]*$/; // \u00a3 is £, \u20ac is €
    if (currencySymbols.test($field.val())) {
      $field[0].value = '';
      this.$('.fundraiser-bar__first-continue').slideUp(200);
    };
  },

  advanceToNextStep (e, data) {
    this.changeStep(this.currentStep+1);
  },

  advanceToDetails(e) {
    let amount = this.$(e.target).data('amount') || this.$('.fundraiser-bar__custom-field').val();
    if (typeof amount == 'string') {
      // \u00a3 is £, \u20ac is €
      amount = amount.replace(/[\$\u20ac\u00a3]/g, '');
    }
    this.setDonationAmount(amount);
    if (this.donationAmount > 0) {
      this.hidingStepTwo ? this.changeStep(3) : this.changeStep(2);
    }
  },

  setDonationAmount(amount) {
    let parsed = parseFloat(amount);
    if (parsed > 0){
      this.donationAmount = parsed;
      this.updateButton();
    } else {
      this.changeStep(1);
    }
  },

  updateButton() {
    if (this.donationAmount > 0) {
      let currencySymbol = this.CURRENCY_SYMBOLS[this.currency];
      let digits = (this.donationAmount === Math.floor(this.donationAmount)) ? 0 : 2;
      let donationAmount = `${currencySymbol}${this.donationAmount.toFixed(digits)}`;
      let monthly = this.readRecurring() ? `<span> / ${I18n.t('fundraiser.month')}</span>` : '';
      this.buttonText = `
                         ${I18n.t('fundraiser.donate', {amount: donationAmount})}
                         ${monthly}`;
      this.$('.fundraiser-bar__display-amount').text(donationAmount);
      this.$('.fundraiser-bar__submit-button').html(this.buttonText);
      this.$('.fundraiser-bar__submit-one-click').html(this.buttonText);
    }
  },

  setOneClickVisibility() {
    if (this.paymentMethods.length) {
      // hide braintree widgethide
      $('#hosted-fields').addClass('hidden-irrelevant');
      $('.fundraiser-bar__fields-loading').addClass('hidden-closed');
    } else {
      $('#one-click-form').addClass('hidden-irrelevant');
    }
  },

  toggleOneClickVisibility(event) {
    event.preventDefault();
    $('#one-click-form, #hosted-fields').toggleClass('hidden-irrelevant');
  },

  triggerStepChange(e) {
    const targetStep = this.$(e.target).parent().data('step');
    if (targetStep < this.currentStep) {
      this.changeStep(targetStep);
    }
  },

  changeStep(targetStep) {
    this.changeStepPanel(targetStep);
    this.changeStepNumber(targetStep);
    this.currentStep = targetStep;
    Backbone.trigger('sidebar:height_change');
  },

  changeStepPanel(targetStep) {
    this.$('.fundraiser-bar__step-panel').addClass('hidden-closed');
    this.$(`.fundraiser-bar__step-panel[data-step="${targetStep}"]`).removeClass('hidden-closed');
  },

  changeStepNumber(targetStep) {
    $.each(['number', 'name'], (ii, part) => {
      this.$(`.fundraiser-bar__step-${part}`).
        removeClass(`fundraiser-bar__step-${part}--past`).
        removeClass(`fundraiser-bar__step-${part}--current`).
        removeClass(`fundraiser-bar__step-${part}--upcoming`);
      this.$(`.fundraiser-bar__step-${part}`).each((ii, el) => {
        const step = this.$(el).parent().data('step');
        if ( step < targetStep ) {
          $(el).addClass(`fundraiser-bar__step-${part}--past`);
        } else if ( step == targetStep) {
          $(el).addClass(`fundraiser-bar__step-${part}--current`);
        } else {
          $(el).addClass(`fundraiser-bar__step-${part}--upcoming`);
        }
      });
    });
  },

  donationData() {
    return {
      amount:         this.donationAmount,
      user:           this.serializeUserForm(),
      currency:       this.currency,
      recurring:      this.readRecurring(),
      store_in_vault: this.readStoreInVault(),
    };
  },

  oneClickDonationData() {
    const paymentMethodId = $('#one-click-form input[name=payment_method_id]:checked').val();
    const data = {
      payment: {
        currency: this.currency,
        amount: this.donationAmount,
        recurring: this.readRecurringOneClick(),
        paymentMethodId,
      },
      user: this.serializeUserForm(),
    };

    return data;
  },

  submitDirectDebit() {
    let data = this.donationData();
    data.provider = 'GC';
    let url = `/api/go_cardless/pages/${this.pageId}/start_flow?${$.param(data)}`;
    $.publish('direct_debit:opened');
    this.directDebitOpened = true;
    window.open(url);
  },

  submitDonation(nonce) {
    let data = this.donationData();
    data.payment_method_nonce = nonce;
    $.post(`/api/payment/braintree/pages/${this.pageId}/transaction`, data)
      .then(this.onSubmission.bind(this))
      .then(this.transactionSuccess.bind(this), this.transactionFailed.bind(this));

    if (this.directDebitOpened) {
      $.publish('direct_debit:donated_via_other');
    }
  },

  onSubmission(data, status) {
    if (this.submissionCallback) {
      this.submissionCallback(data, status);
    }
  },

  submitOneClick(event) {
    event.preventDefault();
    const url = `/api/payment/braintree/pages/${this.pageId}/one_click`;
    this.disableOneClickButton();
    $.post(url, this.oneClickDonationData())
      .then(this.onSubmission.bind(this))
      .then(this.onOneClickSuccess.bind(this), this.onOneClickFailed.bind(this));
  },

  onOneClickSuccess() {
    this.followRedirect(this.followUpUrl);
  },

  transactionSuccess() {
    const user = this.serializeUserForm();
    const url = `/api/member_authentication/new?page_id=${this.pageId}&email=${user.email}`;
    this.followRedirect(url);
  },

  onOneClickFailed() {
    this.enableOneClickButton();
  },

  transactionFailed(data, status) {
    this.enableButton();
    let $errors = this.$('.fundraiser-bar__errors');
    $errors.removeClass('hidden-closed');
    $errors.find('.fundraiser-bar__error-detail').remove();
    if (data.status == 422 && data.responseJSON && data.responseJSON.errors) {
      var messages = data.responseJSON.errors.map(function(error){
        if (error.declined) {
          return I18n.t('fundraiser.card_declined')
        } else {
          return error.message;
        }
      });
    } else {
      var messages = [I18n.t('fundraiser.unknown_error')];
    }
    this.showErrors(messages);
    Backbone.trigger('sidebar:height_change');
  },

  enableOneClickButton() {
    this.$('.fundraiser-bar__submit-one-click')
      .html(this.buttonText)
      .removeClass('button--disabled')
      .prop('disabled', false);
  },

  disableOneClickButton() {
    this.$('.fundraiser-bar__submit-one-click')
      .text(I18n.t('form.processing'))
      .addClass('button--disabled')
      .prop('disabled', true);
  },

  showErrors(messages) {
    let $errors = this.$('.fundraiser-bar__errors');
    $errors.removeClass('hidden-closed');
    $errors.find('.fundraiser-bar__error-detail').remove();
    _.each(messages, (error_message) => {
      $errors.append(`<div class="fundraiser-bar__error-detail">${error_message}</div>`);
    });
  },

  serializeUserForm() {
    const list = this.$('form.action-form').serializeArray();
    return _.mapValues(_.keyBy(list, 'name'), 'value');
  },

  readRecurring() {
    return !!this.$('input.fundraiser-bar__recurring').prop('checked');
  },

  readRecurringOneClick() {
    return !!this.$('input.fundraiser-bar__recurring-one-click').prop('checked');
  },

  readStoreInVault() {
    return this.$('input.fundraiser-bar__store-in-vault').prop('checked');
  },

  disableButton() {
    this.$('.fundraiser-bar__errors').addClass('hidden-closed');
    this.$('.fundraiser-bar__submit-button')
      .text(I18n.t('form.processing'))
      .addClass('button--disabled')
      .prop('disabled', true);
  },

  enableButton() {
    this.$('.fundraiser-bar__submit-button')
      .html(this.buttonText)
      .removeClass('button--disabled')
      .prop('disabled', false);
  },

  followRedirect(url) {
    // If we have no redirect URL or submission callback,
    // we display a thank you message
    if (!url && !this.submissionCallback) {
      alert(I18n.t('fundraiser.thank_you'));
      return;
    }

    this.redirectTo(url);
  },

  redirectTo(url) {
    window.location.href = url;
  },

  displayDirectDebit(show) {
    if (show === true) {
      $('.hosted-fields__direct-debit-container').removeClass('hidden-irrelevant');
      this.handleInterTabFollowUp();
    } else {
      $('.hosted-fields__direct-debit-container').addClass('hidden-irrelevant');
    }
  },

  handleInterTabFollowUp() {
    $(window).on('message', (e) => {
      if (typeof e.originalEvent.data === 'object') {
        if (e.originalEvent.data.event === 'follow_up:loaded') {
          this.redirectTo(this.followUpUrl);
          e.originalEvent.source.close();
          $.publish('direct_debit:donated');
        } else if (e.originalEvent.data.event === 'donation:error') {
          const messages = e.originalEvent.data.errors.map(({ message }) => message);
          this.showErrors(messages);
          e.originalEvent.source.close();
        }
      }
    });
  },
}));

module.exports = Fundraiser;
<commit_msg>Clear payment methods when member is reset (#678)<commit_after>const CurrencyMethods = require('./currency_methods');
const GlobalEvents = require('../../shared/global_events');

const Fundraiser = Backbone.View.extend(_.extend(CurrencyMethods, {
  el: '.fundraiser-bar',

  events: {
    'click .fundraiser-bar__step-name--past': 'triggerStepChange',
    'click .fundraiser-bar__step-number--past': 'triggerStepChange',
    'focus .fundraiser-bar__custom-field': 'primeCustom',
    'blur  .fundraiser-bar__custom-field': 'resetCustom',
    'click .fundraiser-bar__amount-button': 'advanceToDetails',
    'click .fundraiser-bar__first-continue': 'advanceToDetails',
    'click .action-form__clear-form': 'resetUser',
    'ajax:success form.action-form': 'advanceToNextStep',
    'submit form#hosted-fields': 'disableButton',
    'change select.fundraiser-bar__currency-selector': 'switchCurrency',
    'change input.fundraiser-bar__recurring': 'updateButton',
    'click .fundraiser-bar__engage-currency-switcher': 'showCurrencySwitcher',
    'click .hosted-fields__direct-debit': 'submitDirectDebit',
    'click .fundraiser-bar__submit-one-click': 'submitOneClick',
    'click .fundraiser-bar__toggle-payment-method': 'toggleOneClickVisibility',
  },

  globalEvents: {
    'fundraiser:server_error': 'enableButton',
    'fundraiser:nonce_received': 'submitDonation',
  },

  // options: object with any of the following keys
  //    followUpUrl: the url to redirect to after success
  //    submissionCallback: a function to call after success, receives the
  //      arguments received by the ajax call posting the donation
  //    currency: the three letter capitalized currency code to use
  //    amount: a preselected donation amount, if > 0 the first step will be skipped
  //    showDirectDebit: boolean, whether to show the direct debit option
  //    donationBands: an object with three letter currency codes as keys
  //    recurringDefault: either 'donation', 'recurring', or 'only_recurring'
  //    pageId: the ID of the plugin's page database record.
  //      and array of numbers, integers or floats, to display as donation amounts
  initialize(options = {}) {
    this.initializeCurrency(options.currency, options.donationBands)
    this.changeStep(1);
    this.donationAmount = 0;
    this.followUpUrl = options.followUpUrl;
    if (typeof options.submissionCallback === 'function') {
      this.submissionCallback = options.submissionCallback;
    }
    this.initializeSkipping(options);
    this.pageId = options.pageId;
    this.directDebitOpened = false;
    this.displayDirectDebit(options.showDirectDebit);
    this.initializeRecurring(options.recurringDefault);
    this.updateButton();
    this.paymentMethods = options.paymentMethods || [];
    this.setOneClickVisibility();
    GlobalEvents.bindEvents(this);
  },

  initializeRecurring(recurringDefault) {
    const $checkbox = this.$('input.fundraiser-bar__recurring');
    switch(recurringDefault) {
      case 'only_recurring':
        $checkbox.parents('.form__group').addClass('hidden-irrelevant');
        // deliberate fall-through to next case (no break)
      case 'recurring':
        $checkbox.prop('checked', true);
        break;
      default:
        $checkbox.prop('checked', false);
    }
  },

  initializeSkipping(options){
    if (options.amount > 0) {
      this.setDonationAmount(options.amount);
    }
    this.hidingStepTwo = false;
    let amountKnown = (options.amount > 0); // non-numbers with > are always false
    let formComplete = this.$('.action-form').data('prefilled');
    this.hideSteps(amountKnown, formComplete);
  },

  hideSteps(amountKnown, formComplete) {
    if (amountKnown && formComplete) {
      this.changeStep(3);
      this.hideSecondStep();
    } else if (formComplete) {
      this.hideSecondStep();
    } else if (amountKnown) {
      this.changeStep(2);
    }
  },

  hideSecondStep() {
    this.$('.fundraiser-bar__steps').addClass('fundraiser-bar__steps--two-step');
    this.$('.fundraiser-bar__step-label[data-step="2"]').css('visibility', 'hidden');
    this.$('.fundraiser-bar__step-number[data-step="3"]').text(2);
    this.hidingStepTwo = true;
  },

  showSecondStep() {
    this.$('.fundraiser-bar__steps').removeClass('fundraiser-bar__steps--two-step');
    this.$('.fundraiser-bar__welcome-text').addClass('hidden-irrelevant');
    this.$('.fundraiser-bar__step-label[data-step="2"]').css('visibility', 'visible');
    this.$('.fundraiser-bar__step-number[data-step="3"]').text(3);
    Backbone.trigger('form:clear');
    this.hidingStepTwo = false;
    this.changeStep(2);
  },

  resetUser() {
    this.showSecondStep();
    this.toggleOneClickVisibility();
    this.$('#one-click-form').remove();
  },

  primeCustom(e) {
    let $field = this.$(e.target);
    if ($field.val() == '') {
      $field[0].value = this.CURRENCY_SYMBOLS[this.currency];
    }
    this.$('.fundraiser-bar__first-continue').slideDown(200);
  },

  resetCustom(e) {
    let $field = this.$(e.target);
    let currencySymbols = /^[\$\u20ac\u00a3]*$/; // \u00a3 is £, \u20ac is €
    if (currencySymbols.test($field.val())) {
      $field[0].value = '';
      this.$('.fundraiser-bar__first-continue').slideUp(200);
    };
  },

  advanceToNextStep (e, data) {
    this.changeStep(this.currentStep+1);
  },

  advanceToDetails(e) {
    let amount = this.$(e.target).data('amount') || this.$('.fundraiser-bar__custom-field').val();
    if (typeof amount == 'string') {
      // \u00a3 is £, \u20ac is €
      amount = amount.replace(/[\$\u20ac\u00a3]/g, '');
    }
    this.setDonationAmount(amount);
    if (this.donationAmount > 0) {
      this.hidingStepTwo ? this.changeStep(3) : this.changeStep(2);
    }
  },

  setDonationAmount(amount) {
    let parsed = parseFloat(amount);
    if (parsed > 0){
      this.donationAmount = parsed;
      this.updateButton();
    } else {
      this.changeStep(1);
    }
  },

  updateButton() {
    if (this.donationAmount > 0) {
      let currencySymbol = this.CURRENCY_SYMBOLS[this.currency];
      let digits = (this.donationAmount === Math.floor(this.donationAmount)) ? 0 : 2;
      let donationAmount = `${currencySymbol}${this.donationAmount.toFixed(digits)}`;
      let monthly = this.readRecurring() ? `<span> / ${I18n.t('fundraiser.month')}</span>` : '';
      this.buttonText = `
                         ${I18n.t('fundraiser.donate', {amount: donationAmount})}
                         ${monthly}`;
      this.$('.fundraiser-bar__display-amount').text(donationAmount);
      this.$('.fundraiser-bar__submit-button').html(this.buttonText);
      this.$('.fundraiser-bar__submit-one-click').html(this.buttonText);
    }
  },

  setOneClickVisibility() {
    if (this.paymentMethods.length) {
      // hide braintree widgethide
      $('#hosted-fields').addClass('hidden-irrelevant');
      $('.fundraiser-bar__fields-loading').addClass('hidden-closed');
    } else {
      $('#one-click-form').addClass('hidden-irrelevant');
    }
  },

  toggleOneClickVisibility(event) {
    if (event) {
      event.preventDefault();
    }
    $('#one-click-form, #hosted-fields').toggleClass('hidden-irrelevant');
  },

  triggerStepChange(e) {
    const targetStep = this.$(e.target).parent().data('step');
    if (targetStep < this.currentStep) {
      this.changeStep(targetStep);
    }
  },

  changeStep(targetStep) {
    this.changeStepPanel(targetStep);
    this.changeStepNumber(targetStep);
    this.currentStep = targetStep;
    Backbone.trigger('sidebar:height_change');
  },

  changeStepPanel(targetStep) {
    this.$('.fundraiser-bar__step-panel').addClass('hidden-closed');
    this.$(`.fundraiser-bar__step-panel[data-step="${targetStep}"]`).removeClass('hidden-closed');
  },

  changeStepNumber(targetStep) {
    $.each(['number', 'name'], (ii, part) => {
      this.$(`.fundraiser-bar__step-${part}`).
        removeClass(`fundraiser-bar__step-${part}--past`).
        removeClass(`fundraiser-bar__step-${part}--current`).
        removeClass(`fundraiser-bar__step-${part}--upcoming`);
      this.$(`.fundraiser-bar__step-${part}`).each((ii, el) => {
        const step = this.$(el).parent().data('step');
        if ( step < targetStep ) {
          $(el).addClass(`fundraiser-bar__step-${part}--past`);
        } else if ( step == targetStep) {
          $(el).addClass(`fundraiser-bar__step-${part}--current`);
        } else {
          $(el).addClass(`fundraiser-bar__step-${part}--upcoming`);
        }
      });
    });
  },

  donationData() {
    return {
      amount:         this.donationAmount,
      user:           this.serializeUserForm(),
      currency:       this.currency,
      recurring:      this.readRecurring(),
      store_in_vault: this.readStoreInVault(),
    };
  },

  oneClickDonationData() {
    const paymentMethodId = $('#one-click-form input[name=payment_method_id]:checked').val();
    const data = {
      payment: {
        currency: this.currency,
        amount: this.donationAmount,
        recurring: this.readRecurringOneClick(),
        paymentMethodId,
      },
      user: this.serializeUserForm(),
    };

    return data;
  },

  submitDirectDebit() {
    let data = this.donationData();
    data.provider = 'GC';
    let url = `/api/go_cardless/pages/${this.pageId}/start_flow?${$.param(data)}`;
    $.publish('direct_debit:opened');
    this.directDebitOpened = true;
    window.open(url);
  },

  submitDonation(nonce) {
    let data = this.donationData();
    data.payment_method_nonce = nonce;
    $.post(`/api/payment/braintree/pages/${this.pageId}/transaction`, data)
      .then(this.onSubmission.bind(this))
      .then(this.transactionSuccess.bind(this), this.transactionFailed.bind(this));

    if (this.directDebitOpened) {
      $.publish('direct_debit:donated_via_other');
    }
  },

  onSubmission(data, status) {
    if (this.submissionCallback) {
      this.submissionCallback(data, status);
    }
  },

  submitOneClick(event) {
    event.preventDefault();
    const url = `/api/payment/braintree/pages/${this.pageId}/one_click`;
    this.disableOneClickButton();
    $.post(url, this.oneClickDonationData())
      .then(this.onSubmission.bind(this))
      .then(this.onOneClickSuccess.bind(this), this.onOneClickFailed.bind(this));
  },

  onOneClickSuccess() {
    this.followRedirect(this.followUpUrl);
  },

  transactionSuccess() {
    const user = this.serializeUserForm();
    const url = `/api/member_authentication/new?page_id=${this.pageId}&email=${user.email}`;
    this.followRedirect(url);
  },

  onOneClickFailed() {
    this.enableOneClickButton();
  },

  transactionFailed(data, status) {
    this.enableButton();
    let $errors = this.$('.fundraiser-bar__errors');
    $errors.removeClass('hidden-closed');
    $errors.find('.fundraiser-bar__error-detail').remove();
    if (data.status == 422 && data.responseJSON && data.responseJSON.errors) {
      var messages = data.responseJSON.errors.map(function(error){
        if (error.declined) {
          return I18n.t('fundraiser.card_declined')
        } else {
          return error.message;
        }
      });
    } else {
      var messages = [I18n.t('fundraiser.unknown_error')];
    }
    this.showErrors(messages);
    Backbone.trigger('sidebar:height_change');
  },

  enableOneClickButton() {
    this.$('.fundraiser-bar__submit-one-click')
      .html(this.buttonText)
      .removeClass('button--disabled')
      .prop('disabled', false);
  },

  disableOneClickButton() {
    this.$('.fundraiser-bar__submit-one-click')
      .text(I18n.t('form.processing'))
      .addClass('button--disabled')
      .prop('disabled', true);
  },

  showErrors(messages) {
    let $errors = this.$('.fundraiser-bar__errors');
    $errors.removeClass('hidden-closed');
    $errors.find('.fundraiser-bar__error-detail').remove();
    _.each(messages, (error_message) => {
      $errors.append(`<div class="fundraiser-bar__error-detail">${error_message}</div>`);
    });
  },

  serializeUserForm() {
    const list = this.$('form.action-form').serializeArray();
    return _.mapValues(_.keyBy(list, 'name'), 'value');
  },

  readRecurring() {
    return !!this.$('input.fundraiser-bar__recurring').prop('checked');
  },

  readRecurringOneClick() {
    return !!this.$('input.fundraiser-bar__recurring-one-click').prop('checked');
  },

  readStoreInVault() {
    return this.$('input.fundraiser-bar__store-in-vault').prop('checked');
  },

  disableButton() {
    this.$('.fundraiser-bar__errors').addClass('hidden-closed');
    this.$('.fundraiser-bar__submit-button')
      .text(I18n.t('form.processing'))
      .addClass('button--disabled')
      .prop('disabled', true);
  },

  enableButton() {
    this.$('.fundraiser-bar__submit-button')
      .html(this.buttonText)
      .removeClass('button--disabled')
      .prop('disabled', false);
  },

  followRedirect(url) {
    // If we have no redirect URL or submission callback,
    // we display a thank you message
    if (!url && !this.submissionCallback) {
      alert(I18n.t('fundraiser.thank_you'));
      return;
    }

    this.redirectTo(url);
  },

  redirectTo(url) {
    window.location.href = url;
  },

  displayDirectDebit(show) {
    if (show === true) {
      $('.hosted-fields__direct-debit-container').removeClass('hidden-irrelevant');
      this.handleInterTabFollowUp();
    } else {
      $('.hosted-fields__direct-debit-container').addClass('hidden-irrelevant');
    }
  },

  handleInterTabFollowUp() {
    $(window).on('message', (e) => {
      if (typeof e.originalEvent.data === 'object') {
        if (e.originalEvent.data.event === 'follow_up:loaded') {
          this.redirectTo(this.followUpUrl);
          e.originalEvent.source.close();
          $.publish('direct_debit:donated');
        } else if (e.originalEvent.data.event === 'donation:error') {
          const messages = e.originalEvent.data.errors.map(({ message }) => message);
          this.showErrors(messages);
          e.originalEvent.source.close();
        }
      }
    });
  },
}));

module.exports = Fundraiser;
<|endoftext|>


<commit_before>const { channels } = Core.bot

/**
 * Represents an item in the queue
 */
class QueueItem {
  /**
   * Instantiates a new queue item
   * @param {object} data
   * @param {GuildQueue} queue
   */
  constructor (data, queue) {
    this._d = data
    this.queue = queue
    /**
     * If set to true, a notification will be sent when this element starts playing.
     * It's set to false after such notification is sent.
     * @type {boolean}
     */
    this.notify = true
    /**
     * If set to true, the stream is considered to have errors and will be skipped by the bot.
     * @type {boolean}
     */
    this.error = false
  }

  /**
   * Unique identifier
   * @type {string}
   */
  get uid () {
    return this._d.uid
  }

  /**
   * Title of the element
   * @type {string}
   */
  get title () {
    return this._d.title
  }

  set title (v) {
    this._d.title = v
  }

  /**
   * Length of the element
   * @type {number}
   */
  get duration () {
    let duration = this._d.duration
    if (!duration) return 0
    // Transform the duration acording to the filters
    this.filters.forEach(filter => {
      if (filter.timeModifier) duration = Core.util.evalExpr(filter.timeModifier, duration)
    })
    return duration
  }

  set duration (v) {
    this._d.duration = parseInt(v)
  }

  /**
   * User that requested the element
   * @type {Discordie.IGuildMember}
   */
  get requestedBy () {
    return this.queue.guild.members.find(m => m === this._d.requestedBy)
  }

  set requestedBy (v) {
    this._d.requestedBy = v.id || v
  }

  /**
   * Voice Channel where the element will be played
   * @type {Discordie.IVoiceChannel}
   */
  get voiceChannel () {
    return channels.find(c => c.id === this._d.voiceChannel)
  }

  set voiceChannel (v) {
    this._d.voiceChannel = v.id || v
  }

  /**
   * Text Channel where the element was requested
   * @type {Discordie.ITextChannel}
   */
  get textChannel () {
    return channels.find(c => m.id === this._d.textChannel)
  }

  set textChannel (v) {
    this._d.textChannel = v.id || v
  }

  /**
   * Volume
   * @type {number}
   */
  get volume () {
    return this.queue.player.volume
  }

  /**
   * Filters
   * @type {AudioFilter[]}
   */
  get filters () {
    const filters = (this._d.filters || [])
    // Append volume filter
    if (this.queue.player.volume !== 1) {
      return filters.concat({
        FFMPEGFilter: `volume=${this.queue.player.volume}`,
        display: ''
      })
    }
    return filters
  }

  set filters (v) {
    let time = this.originalTime
    // Scale the time according to the filters.
    v.forEach(filter => {
      if (filter.timeModifier) time = Core.util.evalExpr(filter.timeModifier, time)
    })
    this._d.time = time
    this._d.filters = v
  }

  /**
   * URL/Path of the file or stream to play
   * @type {string}
   */
  get path () {
    return this._d.path
  }

  set path (v) {
    this._d.path = v
  }

  /**
   * URL of the element's source page
   * @type {string}
   */
  get sauce () {
    return this._d.sauce
  }

  set sauce (v) {
    this._d.sauce = v
  }

  /**
   * URL of the element's thumbnail picture
   * @type {string}
   */
  get thumbnail () {
    return this._d.thumbnail
  }

  set thumbnail (v) {
    this._d.thumbnail = v
  }

  /**
   * Duration of the element, without filters
   * @type {number}
   */
  get originalDuration () {
    if (!this._d.duration) return 0
    return this._d.duration
  }

  /**
   * Users who voted to skip this element
   * @type {string[]}
   */
  get voteSkip () {
    return this._d.voteSkip
  }

  /**
   * Boolean indicating if the element is a radio stream
   * @type {boolean}
   */
  get radioStream () {
    return this._d.radioStream
  }

  set radioStream (v) {
    this._d.radioStream = v
  }

  /**
   * Playback status.
   *
   * Can be either 'playing', 'paused', 'queue', or 'suspended'
   * @type {string}
   */
  get status () {
    return this._d.status
  }

  set status (v) {
    this._d.status = v
  }

  /**
   * Playback position (timestamp)
   * @type {number}
   */
  get time () {
    if (!this._d.time) return 0
    return this._d.time
  }

  set time (v) {
    this._d.time = parseInt(v)
  }

  /**
   * Playback position (without filters)
   * @type {number}
   */
  get originalTime () {
    let time = this._d.time
    if (!time) return 0
    // Transform the time acording to the filters
    this.filters.forEach(filter => {
      if (filter.inverseTime) time = Core.util.evalExpr(filter.inverseTime, time)
    })
    return time
  }

  /**
   * FFMPEG Flags (from filters and playback position)
   * @type {object}
   */
  get flags () {
    const flags = { input: [], output: [] }
    const filters = []
    // Apply the flags of each filter
    this.filters.forEach(filter => {
      if (filter.FFMPEGInputArgs) flags.input = flags.input.concat(filter.FFMPEGInputArgs)
      if (filter.FFMPEGArgs) flags.output = flags.output.concat(filter.FFMPEGArgs)
      if (filter.FFMPEGFilter) filters.push(filter.FFMPEGFilter)
    })
    // Append the filters
    if (filters.length) flags.output.push('-af', filters.join(', '))
    // Current Time
    if (this.originalTime > 0) flags.input.push('-ss', this.originalTime)
    return flags
  }

  /**
   * True if the item contains static filters
   * @type {boolean}
   */
  get stat () {
                        // heh
    return this.filters.filter(filter => filter.avoidRuntime).length
  }
}

module.exports = QueueItem
<commit_msg>Fix incorrect query in player module<commit_after>const { channels } = Core.bot

/**
 * Represents an item in the queue
 */
class QueueItem {
  /**
   * Instantiates a new queue item
   * @param {object} data
   * @param {GuildQueue} queue
   */
  constructor (data, queue) {
    this._d = data
    this.queue = queue
    /**
     * If set to true, a notification will be sent when this element starts playing.
     * It's set to false after such notification is sent.
     * @type {boolean}
     */
    this.notify = true
    /**
     * If set to true, the stream is considered to have errors and will be skipped by the bot.
     * @type {boolean}
     */
    this.error = false
  }

  /**
   * Unique identifier
   * @type {string}
   */
  get uid () {
    return this._d.uid
  }

  /**
   * Title of the element
   * @type {string}
   */
  get title () {
    return this._d.title
  }

  set title (v) {
    this._d.title = v
  }

  /**
   * Length of the element
   * @type {number}
   */
  get duration () {
    let duration = this._d.duration
    if (!duration) return 0
    // Transform the duration acording to the filters
    this.filters.forEach(filter => {
      if (filter.timeModifier) duration = Core.util.evalExpr(filter.timeModifier, duration)
    })
    return duration
  }

  set duration (v) {
    this._d.duration = parseInt(v)
  }

  /**
   * User that requested the element
   * @type {Discordie.IGuildMember}
   */
  get requestedBy () {
    return this.queue.guild.members.find(m => m.id === this._d.requestedBy)
  }

  set requestedBy (v) {
    this._d.requestedBy = v.id || v
  }

  /**
   * Voice Channel where the element will be played
   * @type {Discordie.IVoiceChannel}
   */
  get voiceChannel () {
    return channels.find(c => c.id === this._d.voiceChannel)
  }

  set voiceChannel (v) {
    this._d.voiceChannel = v.id || v
  }

  /**
   * Text Channel where the element was requested
   * @type {Discordie.ITextChannel}
   */
  get textChannel () {
    return channels.find(c => c.id === this._d.textChannel)
  }

  set textChannel (v) {
    this._d.textChannel = v.id || v
  }

  /**
   * Volume
   * @type {number}
   */
  get volume () {
    return this.queue.player.volume
  }

  /**
   * Filters
   * @type {AudioFilter[]}
   */
  get filters () {
    const filters = (this._d.filters || [])
    // Append volume filter
    if (this.queue.player.volume !== 1) {
      return filters.concat({
        FFMPEGFilter: `volume=${this.queue.player.volume}`,
        display: ''
      })
    }
    return filters
  }

  set filters (v) {
    let time = this.originalTime
    // Scale the time according to the filters.
    v.forEach(filter => {
      if (filter.timeModifier) time = Core.util.evalExpr(filter.timeModifier, time)
    })
    this._d.time = time
    this._d.filters = v
  }

  /**
   * URL/Path of the file or stream to play
   * @type {string}
   */
  get path () {
    return this._d.path
  }

  set path (v) {
    this._d.path = v
  }

  /**
   * URL of the element's source page
   * @type {string}
   */
  get sauce () {
    return this._d.sauce
  }

  set sauce (v) {
    this._d.sauce = v
  }

  /**
   * URL of the element's thumbnail picture
   * @type {string}
   */
  get thumbnail () {
    return this._d.thumbnail
  }

  set thumbnail (v) {
    this._d.thumbnail = v
  }

  /**
   * Duration of the element, without filters
   * @type {number}
   */
  get originalDuration () {
    if (!this._d.duration) return 0
    return this._d.duration
  }

  /**
   * Users who voted to skip this element
   * @type {string[]}
   */
  get voteSkip () {
    return this._d.voteSkip
  }

  /**
   * Boolean indicating if the element is a radio stream
   * @type {boolean}
   */
  get radioStream () {
    return this._d.radioStream
  }

  set radioStream (v) {
    this._d.radioStream = v
  }

  /**
   * Playback status.
   *
   * Can be either 'playing', 'paused', 'queue', or 'suspended'
   * @type {string}
   */
  get status () {
    return this._d.status
  }

  set status (v) {
    this._d.status = v
  }

  /**
   * Playback position (timestamp)
   * @type {number}
   */
  get time () {
    if (!this._d.time) return 0
    return this._d.time
  }

  set time (v) {
    this._d.time = parseInt(v)
  }

  /**
   * Playback position (without filters)
   * @type {number}
   */
  get originalTime () {
    let time = this._d.time
    if (!time) return 0
    // Transform the time acording to the filters
    this.filters.forEach(filter => {
      if (filter.inverseTime) time = Core.util.evalExpr(filter.inverseTime, time)
    })
    return time
  }

  /**
   * FFMPEG Flags (from filters and playback position)
   * @type {object}
   */
  get flags () {
    const flags = { input: [], output: [] }
    const filters = []
    // Apply the flags of each filter
    this.filters.forEach(filter => {
      if (filter.FFMPEGInputArgs) flags.input = flags.input.concat(filter.FFMPEGInputArgs)
      if (filter.FFMPEGArgs) flags.output = flags.output.concat(filter.FFMPEGArgs)
      if (filter.FFMPEGFilter) filters.push(filter.FFMPEGFilter)
    })
    // Append the filters
    if (filters.length) flags.output.push('-af', filters.join(', '))
    // Current Time
    if (this.originalTime > 0) flags.input.push('-ss', this.originalTime)
    return flags
  }

  /**
   * True if the item contains static filters
   * @type {boolean}
   */
  get stat () {
                        // heh
    return this.filters.filter(filter => filter.avoidRuntime).length
  }
}

module.exports = QueueItem
<|endoftext|>


<commit_before>SpreeStore.module('Order',function(Order, SpreeStore, Backbone,Marionette,$,_){
  Order.deliveryView = Backbone.Marionette.ItemView.extend({
    template: '#order-delivery-template',

    templateHelpers: {
      displayImage: SpreeStore.helpers.displayImage
    },

    events: {
      "submit .edit_order": "updateOrder",
      "click .shipping-methods input[type='radio']": "hideValidation"
    },

    updateOrder: function(e) {
      e.stopPropagation();
      e.preventDefault();
      if (this.validate()) {
        // TODO: Doing it this way because I don't know how to deal with nested attrs in Backbone
        var data = Backbone.Syphon.serialize(this)
        data['order_token'] = SpreeStore.current_order_token
        $.ajax({
          type: 'PUT',
          dataType: 'json',
          url: '/store/api/checkouts/' + this.model.attributes.number,
          data: data,
          success: function(data) {
            var order = new SpreeStore.Models.Order(data)
            SpreeStore.Checkout.Controller.renderFor(order)
          },
        })
      }
    },

    validate: function() {
      var validation_errors = 0;
      $.each($('.shipping-methods'), function(index, shipping_method_el) {
        shipping_method_el = $(shipping_method_el);
        var validation_error = shipping_method_el.find(".validation-error");
        if (shipping_method_el.find("input[type='radio']:checked").length == 0) {
          validation_errors++;
          validation_error.show();
        } else {
          validation_error.hide();
        }
      })

      return (validation_errors == 0 ? true : false)
    },

    // Hide the validation if it's there.
    hideValidation: function(e) {
      $(e.target).parents('.shipping-methods').find('.validation-error').slideUp();
    }
  })
})<commit_msg>Namespace deliveryView correctly<commit_after>SpreeStore.module('Checkout',function(Checkout, SpreeStore, Backbone,Marionette,$,_){
  Checkout.deliveryView = Backbone.Marionette.ItemView.extend({
    template: '#order-delivery-template',

    templateHelpers: {
      displayImage: SpreeStore.helpers.displayImage
    },

    events: {
      "submit .edit_order": "updateOrder",
      "click .shipping-methods input[type='radio']": "hideValidation"
    },

    updateOrder: function(e) {
      e.stopPropagation();
      e.preventDefault();
      if (this.validate()) {
        // TODO: Doing it this way because I don't know how to deal with nested attrs in Backbone
        var data = Backbone.Syphon.serialize(this)
        data['order_token'] = SpreeStore.current_order_token
        $.ajax({
          type: 'PUT',
          dataType: 'json',
          url: '/store/api/checkouts/' + this.model.attributes.number,
          data: data,
          success: function(data) {
            var order = new SpreeStore.Models.Order(data)
            SpreeStore.Checkout.Controller.renderFor(order)
          },
        })
      }
    },

    validate: function() {
      var validation_errors = 0;
      $.each($('.shipping-methods'), function(index, shipping_method_el) {
        shipping_method_el = $(shipping_method_el);
        var validation_error = shipping_method_el.find(".validation-error");
        if (shipping_method_el.find("input[type='radio']:checked").length == 0) {
          validation_errors++;
          validation_error.show();
        } else {
          validation_error.hide();
        }
      })

      return (validation_errors == 0 ? true : false)
    },

    // Hide the validation if it's there.
    hideValidation: function(e) {
      $(e.target).parents('.shipping-methods').find('.validation-error').slideUp();
    }
  })
})<|endoftext|>


<commit_before>Model.RestPersistence = function(resource, methods) {
  var model_resource = function() {
    this.resource = resource;
  };

  model_resource.prototype = $.extend({
    create: function(model, callback) {
      return this.xhr('POST', this.create_path(model), model, callback);
    },

    create_path: function(model) {
      return this.resource;
    },

    destroy: function(model, callback) {
      return this.xhr('DELETE', this.destroy_path(model), model, callback);
    },

    destroy_path: function(model) {
      return this.update_path(model);
    },

    params: function(model) {
      var params;
      if (model) {
        var attributes = model.attr();
        delete attributes.id;
        params = {};
        params[model._name] = attributes;
      } else {
        params = null;
      }
      return params;
    },

    parseResponseData: function(xhr) {
      try {
        return jQuery.parseJSON(xhr.responseText);
      } catch(e) {
        Model.Log(e);
      };
    },

    update: function(model, callback) {
      return this.xhr('PUT', this.update_path(model), model, callback);
    },

    update_path: function(model) {
      return [this.resource, model.id()].join('/');
    },

    xhr: function(method, url, model, callback) {
      var self = this;

      return $.ajax({
        type: method,
        url: url,
        dataType: "text",
        data: this.params(model),
        complete: function(xhr, textStatus) {
          self.xhrComplete(xhr, textStatus, model, callback);
        }
      });
    },

    xhrComplete: function(xhr, textStatus, model, callback) {
      var data = this.parseResponseData(xhr);
      var success = textStatus == "success";

      if (data) {
        if (success) {
          // Remote data is the definitive source, update model.
          model.attr(data);
        } else if (xhr.status == 422) {
          // Rails' preferred failed validation response code, assume these
          // are errors and replace current model errors with them.
          model.errors.clear();

          for (var attribute in data) {
            for (var i = 0; i < data[attribute].length; i++) {
              model.errors.add(attribute, data[attribute][i]);
            }
          }
        }
      }

      if (callback) callback.call(model, success, xhr);
    }
  }, methods);

  return new model_resource();
};
<commit_msg>Don't bother sending attributes with a DELETE request.<commit_after>Model.RestPersistence = function(resource, methods) {
  var model_resource = function() {
    this.resource = resource;
  };

  model_resource.prototype = $.extend({
    create: function(model, callback) {
      return this.xhr('POST', this.create_path(model), model, callback);
    },

    create_path: function(model) {
      return this.resource;
    },

    destroy: function(model, callback) {
      return this.xhr('DELETE', this.destroy_path(model), model, callback);
    },

    destroy_path: function(model) {
      return this.update_path(model);
    },

    params: function(model) {
      var params;
      if (model) {
        var attributes = model.attr();
        delete attributes.id;
        params = {};
        params[model._name] = attributes;
      } else {
        params = null;
      }
      return params;
    },

    parseResponseData: function(xhr) {
      try {
        return jQuery.parseJSON(xhr.responseText);
      } catch(e) {
        Model.Log(e);
      };
    },

    update: function(model, callback) {
      return this.xhr('PUT', this.update_path(model), model, callback);
    },

    update_path: function(model) {
      return [this.resource, model.id()].join('/');
    },

    xhr: function(method, url, model, callback) {
      var self = this;
      var data = method == "DELETE" ? null : this.params(model);

      return $.ajax({
        type: method,
        url: url,
        dataType: "text",
        data: data,
        complete: function(xhr, textStatus) {
          self.xhrComplete(xhr, textStatus, model, callback);
        }
      });
    },

    xhrComplete: function(xhr, textStatus, model, callback) {
      var data = this.parseResponseData(xhr);
      var success = textStatus == "success";

      if (data) {
        if (success) {
          // Remote data is the definitive source, update model.
          model.attr(data);
        } else if (xhr.status == 422) {
          // Rails' preferred failed validation response code, assume these
          // are errors and replace current model errors with them.
          model.errors.clear();

          for (var attribute in data) {
            for (var i = 0; i < data[attribute].length; i++) {
              model.errors.add(attribute, data[attribute][i]);
            }
          }
        }
      }

      if (callback) callback.call(model, success, xhr);
    }
  }, methods);

  return new model_resource();
};
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React, { Children, cloneElement } from 'react';
import { TRANSITION_DURATION_MS, TRANSITION_SCALE_ADJUSTMENT_Y } from './constants';

const DelayedItems = WrappedComponent => class extends React.PureComponent {

  static propTypes = {
    children: PropTypes.node,
    applyDelays: PropTypes.bool,
    reverse: PropTypes.bool,
  };

  constructor(props) {
    super(props);
    const { children } = this.props;
    this.state = { children };
  }

  componentWillReceiveProps({ applyDelays: nextApplyDelays, children: nextChildren }) {
    const { applyDelays, children } = this.props;
    const isEqualChildren = () => {
      if (children.length !== nextChildren.length) {
        return false;
      }
      let i = children.length;
      if (i !== nextChildren.length) return false;
      while (i > 0) {
        i = i - 1;
        if (children[i] !== nextChildren[i]) return false;
      }
      return true;
    };
    if (applyDelays !== nextApplyDelays) {
      this.setState({
        children: nextApplyDelays ? this.applyTransitionDelays() : children,
      });
    } else if (!isEqualChildren()) {
      this.setState({ children: nextChildren });
    }
  }

  applyTransitionDelays() {
    const { children, reverse } = this.props;
    const numItems = Children.count(children);
    const transitionDuration = TRANSITION_DURATION_MS / 1000;
    const start = TRANSITION_SCALE_ADJUSTMENT_Y;
    const delayedChildren = Children.map(children, (child, index) => {
      let itemDelayFraction;
      if (reverse) {
        itemDelayFraction = (numItems - index) / numItems;
      } else {
        itemDelayFraction = index / numItems;
      }
      const delay = (start + (itemDelayFraction * (1 - start))) * transitionDuration;
      return cloneElement(child, { delay });
    });
    return delayedChildren;
  }

  render() {
    const {
      applyDelays, // eslint-disable-line no-unused-vars
      children, // eslint-disable-line no-unused-vars
      reverse, // eslint-disable-line no-unused-vars
      ...otherProps
    } = this.props;
    return (
      <WrappedComponent
        {...this.state}
        {...otherProps}
      />
    );
  }
};
export default DelayedItems;
<commit_msg>Replace with operator assignment<commit_after>import PropTypes from 'prop-types';
import React, { Children, cloneElement } from 'react';
import { TRANSITION_DURATION_MS, TRANSITION_SCALE_ADJUSTMENT_Y } from './constants';

const DelayedItems = WrappedComponent => class extends React.PureComponent {

  static propTypes = {
    children: PropTypes.node,
    applyDelays: PropTypes.bool,
    reverse: PropTypes.bool,
  };

  constructor(props) {
    super(props);
    const { children } = this.props;
    this.state = { children };
  }

  componentWillReceiveProps({ applyDelays: nextApplyDelays, children: nextChildren }) {
    const { applyDelays, children } = this.props;
    const isEqualChildren = () => {
      if (children.length !== nextChildren.length) {
        return false;
      }
      let i = children.length;
      if (i !== nextChildren.length) return false;
      while (i > 0) {
        i -= 1;
        if (children[i] !== nextChildren[i]) return false;
      }
      return true;
    };
    if (applyDelays !== nextApplyDelays) {
      this.setState({
        children: nextApplyDelays ? this.applyTransitionDelays() : children,
      });
    } else if (!isEqualChildren()) {
      this.setState({ children: nextChildren });
    }
  }

  applyTransitionDelays() {
    const { children, reverse } = this.props;
    const numItems = Children.count(children);
    const transitionDuration = TRANSITION_DURATION_MS / 1000;
    const start = TRANSITION_SCALE_ADJUSTMENT_Y;
    const delayedChildren = Children.map(children, (child, index) => {
      let itemDelayFraction;
      if (reverse) {
        itemDelayFraction = (numItems - index) / numItems;
      } else {
        itemDelayFraction = index / numItems;
      }
      const delay = (start + (itemDelayFraction * (1 - start))) * transitionDuration;
      return cloneElement(child, { delay });
    });
    return delayedChildren;
  }

  render() {
    const {
      applyDelays, // eslint-disable-line no-unused-vars
      children, // eslint-disable-line no-unused-vars
      reverse, // eslint-disable-line no-unused-vars
      ...otherProps
    } = this.props;
    return (
      <WrappedComponent
        {...this.state}
        {...otherProps}
      />
    );
  }
};
export default DelayedItems;
<|endoftext|>