<commit_before>'use strict';
angular.module('dashboard-semaforos')
  .controller('DistributionCtrl', ['$scope', function barChartCtrl($scope) {
    $scope.areas = [
      { name: "1-SWARCO", assigned: false },
      { name: "2-TELVENT", assigned: false },
      { name: "3-MANTELECTRIC", assigned: false },
      { name: "4-AUTOTROL", assigned: false },
      { name: "5A-AUTOTROL", assigned: false },
      { name: "5B-AUTOTROL", assigned: false },
      { name: "6-AUTOTROL", assigned: false },
      { name: "7-MANTELECTRIC", assigned: false },
      { name: "8-LESKO", assigned: false },
      { name: "9-SUTEC", assigned: false }
    ];

    $scope.dropzones = [
      { name: "1", areas: [] },
      { name: "2", areas: [] },
      { name: "3", areas: [] },
      { name: "4", areas: [] },
      { name: "5", areas: [] },
      { name: "6", areas: [] }
    ]

    $scope.$on('drop', function(event, args) {
      var index = $scope.dropzones.indexOf(args.target);
      var target = $scope.dropzones[index];
      var source = $scope.areas.find(function(el) {
        return el.name === args.source;
      });

      target.areas.push(source);
      source.assigned = true;

      $scope.$apply();

    });
  }]);
<commit_msg>fake data<commit_after>'use strict';
angular.module('dashboard-semaforos')
  .controller('DistributionCtrl', ['$scope', function barChartCtrl($scope) {
    $scope.areas = [{
      name: "1-SWARCO",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "2-TELVENT",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "3-MANTELECTRIC",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "4-AUTOTROL",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "5A-AUTOTROL",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "5B-AUTOTROL",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "6-AUTOTROL",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "7-MANTELECTRIC",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "8-LESKO",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }, {
      name: "9-SUTEC",
      assigned: false,
      values: {
        A: {
          amount: 1900,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE INSTALACIONES', amount: 700 },
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE EQUIPAMIENTO', amount: 1200 }
          ]
        },
        B: {
          amount: 3000,
          subcategories: [
            { name: 'MANTENIMIENTO PREVENTIVO Y CORRECTIVO MENSUAL DE COMANDOS DE ÁREA Y SISTEMAS', amount: 900 },
            { name: 'MODERNIZACIÓN DE LOS SISTEMAS DE TRÁNSITO', amount: 1100 },
            { name: 'IMPLANTACIÓN DE NUEVO SISTEMA DE TRÁNSITO', amount: 1000 }
          ]
        },
        C: {
          amount: 5000,
          subcategories: [
            { name: 'CONSTRUCCIÓN DE NUEVOS CRUCES SEMAFORIZADOS', amount: 2500 },
            { name: 'DAÑOS, TRASLADOS Y REMODELACIONES', amount: 800 },
            { name: 'REPARACIÓN DE EQUIPOS CONTROLADORES', amount: 700 },
            { name: 'OBRAS VARIAS Y ACTIVIDADES RESTANTES', amount: 1000 }
          ]
        }
      }
    }];

    $scope.dropzones = [
      { name: "1", areas: [] },
      { name: "2", areas: [] },
      { name: "3", areas: [] },
      { name: "4", areas: [] },
      { name: "5", areas: [] },
      { name: "6", areas: [] }
    ]

    $scope.$on('drop', function(event, args) {
      var index = $scope.dropzones.indexOf(args.target);
      var target = $scope.dropzones[index];
      var source = $scope.areas.find(function(el) {
        return el.name === args.source;
      });

      target.areas.push(source);
      source.assigned = true;

      $scope.$apply();

    });
  }]);
<|endoftext|>


<commit_before>// Copyright © 2011 Aapo Laitinen <aapo.laitinen@iki.fi> unless otherwise noted

define(['dep/glmatrix/glmatrix', 'engine/util/webgllib', 'engine/util/Program!engine/shaders/uivector.vert!engine/shaders/uivector.frag'], function (glmatrix, webgllib, vectorProgram) {

	function UIRenderer() {
		this._linePoints = new Float32Array(UIRenderer.LINE_MAX_POINTS);
		this._linePointCount = 0;
	}

	UIRenderer.LINE_MAX_POINTS = 1000;

	UIRenderer.positionBuffer = null;

	UIRenderer.tempVec41 = glmatrix.Vec4.create();
	UIRenderer.tempVec42 = glmatrix.Vec4.create();
	UIRenderer.tempVec43 = glmatrix.Vec4.create();
	UIRenderer.tempVec44 = glmatrix.Vec4.create();

	UIRenderer.tempMat4 = glmatrix.Mat4.create();

	UIRenderer.prototype.addRectScreen4zw = function (vec1, vec2, vec3, vec4) {
		var lps = this._linePoints;
		var lpc = this._linePointCount;
		if (lpc + 32 > lps.length) {
			// FIXME: Show error in console
			return;
		}
		// Top side
		lps.set(vec1, lpc);
		lps.set(vec2, lpc + 4);
		// Right side
		lps.set(vec2, lpc + 8);
		lps.set(vec3, lpc + 12);
		// Bottom side
		lps.set(vec3, lpc + 16);
		lps.set(vec4, lpc + 20);
		// Left side
		lps.set(vec4, lpc + 24);
		lps.set(vec1, lpc + 28);
		this._linePointCount += 32;
	};

	UIRenderer.prototype.addRectScreen4 = function (x1, y1, x2, y2, x3, y3, x4, y4) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var vec4 = UIRenderer.tempVec44;

		vec1[0] = x1;
		vec1[1] = y1;
		vec1[2] = 0;
		vec1[3] = 1;

		vec2[0] = x2;
		vec2[1] = y2;
		vec2[2] = 0;
		vec2[3] = 1;

		vec3[0] = x3;
		vec3[1] = y3;
		vec3[2] = 0;
		vec3[3] = 1;

		vec4[0] = x4;
		vec4[1] = y4;
		vec4[2] = 0;
		vec4[3] = 1;

		this.addRectScreen4zw(vec1, vec2, vec3, vec4);
	};

	UIRenderer.prototype.addRectScreen = function (x1, y1, x2, y2) {
		this.addRectScreen4(x1, y1, x2, y1, x2, y2, x1, y2);
	};

	UIRenderer.prototype.addRectModel = function (worldToClip, modelToWorld, w, h) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var vec4 = UIRenderer.tempVec44;

		var mat = UIRenderer.tempMat4;

		glmatrix.Mat4.set(worldToClip, mat);
		glmatrix.Mat4.multiply(mat, modelToWorld, mat);

		var half_w = w / 2;
		var half_h = h / 2;

		vec1[0] = -half_w;
		vec1[1] = -half_h;
		vec1[2] = 0;
		vec1[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec1, vec1);

		vec2[0] = half_w;
		vec2[1] = -half_h;
		vec2[2] = 0;
		vec2[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec2, vec2);

		vec3[0] = half_w;
		vec3[1] = half_h;
		vec3[2] = 0;
		vec3[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec3, vec3);

		vec4[0] = -half_w;
		vec4[1] = half_h;
		vec4[2] = 0;
		vec4[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec4, vec4);

		this.addRectScreen4zw(vec1, vec2, vec3, vec4);
	};

	UIRenderer.prototype.addRectWorld = function (worldToClip, x1, y1, x2, y2, z) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var vec4 = UIRenderer.tempVec44;

		z = z || 0;

		vec1[0] = x1;
		vec1[1] = y1;
		vec1[2] = z;
		vec1[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec1, vec1);

		vec2[0] = x2;
		vec2[1] = y1;
		vec2[2] = z;
		vec2[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec2, vec2);

		vec3[0] = x2;
		vec3[1] = y2;
		vec3[2] = z;
		vec3[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec3, vec3);

		vec4[0] = x1;
		vec4[1] = y2;
		vec4[2] = z;
		vec4[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec4, vec4);

		this.addRectScreen4zw(vec1, vec2, vec3, vec4);
	};

	UIRenderer.prototype.draw = function (gl) {
		// Cache all relevant variables
		var lps = this._linePoints;
		var lpc = this._linePointCount;

		// FIXME: Put this somewhere else. This must be recreated if the WebGL
		// context is lost.
		var positionBuffer = UIRenderer.positionBuffer;
		if (!positionBuffer) {
			positionBuffer = webgllib.createArrayBuffer(gl, lps, gl.DYNAMIC_DRAW);
			UIRenderer.positionBuffer = positionBuffer;
		}

		// Line rendering pass
		if (lpc) {
			gl.useProgram(vectorProgram.prepare(gl));
			gl.enable(gl.BLEND);
			gl.blendFunc(gl.SRC_ALPHA, gl.DST_COLOR);
			gl.enableVertexAttribArray(vectorProgram.vertexPosition);
			gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
			gl.bufferSubData(gl.ARRAY_BUFFER, 0, lps);
			gl.vertexAttribPointer(vectorProgram.vertexPosition, 4, gl.FLOAT, false, 0, 0);
			gl.bindBuffer(gl.ARRAY_BUFFER, null);

			gl.vertexAttrib4f(vectorProgram.fillColor, 0, 1, 1, 1);

			gl.drawArrays(gl.LINES, 0, lpc);

			gl.disableVertexAttribArray(vectorProgram.vertexPosition);
			gl.disable(gl.BLEND);
			gl.useProgram(null);
			this._linePointCount = 0;
		}
	};

	return UIRenderer;

});<commit_msg>World-space polygon drawing support for UIRenderer<commit_after>// Copyright © 2011 Aapo Laitinen <aapo.laitinen@iki.fi> unless otherwise noted

define(['dep/glmatrix/glmatrix', 'engine/util/webgllib', 'engine/util/Program!engine/shaders/uivector.vert!engine/shaders/uivector.frag'], function (glmatrix, webgllib, vectorProgram) {

	function UIRenderer() {
		this._linePoints = new Float32Array(UIRenderer.LINE_MAX_POINTS);
		this._linePointCount = 0;
	}

	UIRenderer.LINE_MAX_POINTS = 1000;

	UIRenderer.positionBuffer = null;

	UIRenderer.tempVec41 = glmatrix.Vec4.create();
	UIRenderer.tempVec42 = glmatrix.Vec4.create();
	UIRenderer.tempVec43 = glmatrix.Vec4.create();
	UIRenderer.tempVec44 = glmatrix.Vec4.create();

	UIRenderer.tempMat4 = glmatrix.Mat4.create();

	UIRenderer.prototype.addRectScreen4zw = function (vec1, vec2, vec3, vec4) {
		var lps = this._linePoints;
		var lpc = this._linePointCount;
		if (lpc + 32 > lps.length) {
			// FIXME: Show error in console
			return;
		}
		// Top side
		lps.set(vec1, lpc);
		lps.set(vec2, lpc + 4);
		// Right side
		lps.set(vec2, lpc + 8);
		lps.set(vec3, lpc + 12);
		// Bottom side
		lps.set(vec3, lpc + 16);
		lps.set(vec4, lpc + 20);
		// Left side
		lps.set(vec4, lpc + 24);
		lps.set(vec1, lpc + 28);
		this._linePointCount += 32;
	};

	UIRenderer.prototype.addRectScreen4 = function (x1, y1, x2, y2, x3, y3, x4, y4) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var vec4 = UIRenderer.tempVec44;

		vec1[0] = x1;
		vec1[1] = y1;
		vec1[2] = 0;
		vec1[3] = 1;

		vec2[0] = x2;
		vec2[1] = y2;
		vec2[2] = 0;
		vec2[3] = 1;

		vec3[0] = x3;
		vec3[1] = y3;
		vec3[2] = 0;
		vec3[3] = 1;

		vec4[0] = x4;
		vec4[1] = y4;
		vec4[2] = 0;
		vec4[3] = 1;

		this.addRectScreen4zw(vec1, vec2, vec3, vec4);
	};

	UIRenderer.prototype.addRectScreen = function (x1, y1, x2, y2) {
		this.addRectScreen4(x1, y1, x2, y1, x2, y2, x1, y2);
	};

	UIRenderer.prototype.addRectModel = function (worldToClip, modelToWorld, w, h) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var vec4 = UIRenderer.tempVec44;

		var mat = UIRenderer.tempMat4;

		glmatrix.Mat4.set(worldToClip, mat);
		glmatrix.Mat4.multiply(mat, modelToWorld, mat);

		var half_w = w / 2;
		var half_h = h / 2;

		vec1[0] = -half_w;
		vec1[1] = -half_h;
		vec1[2] = 0;
		vec1[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec1, vec1);

		vec2[0] = half_w;
		vec2[1] = -half_h;
		vec2[2] = 0;
		vec2[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec2, vec2);

		vec3[0] = half_w;
		vec3[1] = half_h;
		vec3[2] = 0;
		vec3[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec3, vec3);

		vec4[0] = -half_w;
		vec4[1] = half_h;
		vec4[2] = 0;
		vec4[3] = 1;
		glmatrix.Mat4.multiplyVec4(mat, vec4, vec4);

		this.addRectScreen4zw(vec1, vec2, vec3, vec4);
	};

	UIRenderer.prototype.addRectWorld = function (worldToClip, x1, y1, x2, y2, z) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var vec4 = UIRenderer.tempVec44;

		z = z || 0;

		vec1[0] = x1;
		vec1[1] = y1;
		vec1[2] = z;
		vec1[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec1, vec1);

		vec2[0] = x2;
		vec2[1] = y1;
		vec2[2] = z;
		vec2[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec2, vec2);

		vec3[0] = x2;
		vec3[1] = y2;
		vec3[2] = z;
		vec3[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec3, vec3);

		vec4[0] = x1;
		vec4[1] = y2;
		vec4[2] = z;
		vec4[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec4, vec4);

		this.addRectScreen4zw(vec1, vec2, vec3, vec4);
	};

	UIRenderer.prototype.addPolyWorld = function (worldToClip, poly, z) {
		var vec1 = UIRenderer.tempVec41;
		var vec2 = UIRenderer.tempVec42;
		var vec3 = UIRenderer.tempVec43;
		var lps = this._linePoints;
		var lpc = this._linePointCount;

		z = z || 0;

		if (poly.length < 2) {
			return;
		}
		if (lpc + poly.length * 8 > lps.length) {
			// FIXME: Show error in console
			return;
		}

		vec1[0] = poly[0];
		vec1[1] = poly[1];
		vec1[2] = z;
		vec1[3] = 1;
		glmatrix.Mat4.multiplyVec4(worldToClip, vec1, vec1);
		glmatrix.Mat4.set(vec1, vec2);

		for (var i = 2; i < poly.length; i += 2) {
			vec3[0] = poly[i];
			vec3[1] = poly[i + 1];
			vec3[2] = z;
			vec3[3] = 1;
			glmatrix.Mat4.multiplyVec4(worldToClip, vec3, vec3);

			lps.set(vec2, lpc);
			lps.set(vec3, lpc + 4);
			lpc += 8;

			glmatrix.Mat4.set(vec3, vec2);
		}

		lps.set(vec2, lpc);
		lps.set(vec1, lpc + 4);
		lpc += 8;

		this._linePointCount = lpc;
	};

	UIRenderer.prototype.draw = function (gl) {
		// Cache all relevant variables
		var lps = this._linePoints;
		var lpc = this._linePointCount;

		// FIXME: Put this somewhere else. This must be recreated if the WebGL
		// context is lost.
		var positionBuffer = UIRenderer.positionBuffer;
		if (!positionBuffer) {
			positionBuffer = webgllib.createArrayBuffer(gl, lps, gl.DYNAMIC_DRAW);
			UIRenderer.positionBuffer = positionBuffer;
		}

		// Line rendering pass
		if (lpc) {
			gl.useProgram(vectorProgram.prepare(gl));
			gl.enable(gl.BLEND);
			gl.blendFunc(gl.SRC_ALPHA, gl.DST_COLOR);
			gl.enableVertexAttribArray(vectorProgram.vertexPosition);
			gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
			gl.bufferSubData(gl.ARRAY_BUFFER, 0, lps);
			gl.vertexAttribPointer(vectorProgram.vertexPosition, 4, gl.FLOAT, false, 0, 0);
			gl.bindBuffer(gl.ARRAY_BUFFER, null);

			gl.vertexAttrib4f(vectorProgram.fillColor, 0, 1, 1, 1);

			gl.drawArrays(gl.LINES, 0, lpc);

			gl.disableVertexAttribArray(vectorProgram.vertexPosition);
			gl.disable(gl.BLEND);
			gl.useProgram(null);
			this._linePointCount = 0;
		}
	};

	return UIRenderer;

});<|endoftext|>


<commit_before>import { service, send } from "connectors";
import SendPage from "./Page";
import ErrorScreen from "ErrorScreen";
import { FormattedMessage as T } from "react-intl";
import { spring, presets } from "react-motion";
import OutputRow from "./OutputRow";
import { DescriptionHeader } from "layout";

export const SendTabHeader = service(({ isTestNet }) => (
  <DescriptionHeader
    description={
      isTestNet ? (
        <T
          id="transactions.description.send.testnet"
          m={
            "Testnet Decred addresses always begin with letter T and contain 26-35 alphanumeric characters\n(e.g. TxxXXXXXxXXXxXXXXxxx0XxXXXxxXxXxX0)."
          }
        />
      ) : (
        <T
          id="transactions.description.send.mainnet"
          m={
            "Mainnet Decred addresses always begin with letter D and contain 26-35 alphanumeric characters\n(e.g. DxxXXXXXxXXXxXXXXxxx0XxXXXxxXxXxX0X)."
          }
        />
      )
    }
  />
));

@autobind
class Send extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isShowingConfirm: false,
      isSendAll: false,
      isSendSelf: false,
      outputs: [{ key: "output_0", data: this.getBaseOutput() }],
      sendAllAmount: this.props.totalSpent,
      unsignedRawTx: null,
      account: this.props.defaultSpendingAccount,
      insuficientFunds: false
    };
  }

  componentDidUpdate(prevProps) {
    const {
      constructTxLowBalance,
      unsignedRawTx,
      isWatchingOnly,
      nextAddress,
      publishTxResponse
    } = this.props;
    const { isSendSelf, outputs } = this.state;
    let newOutputs;
    if (
      publishTxResponse &&
      publishTxResponse !== prevProps.publishTxResponse
    ) {
      newOutputs = [{ key: "output_0", data: this.getBaseOutput() }];
      this.setState({ isSendAll: false });
    }
    if (isSendSelf && prevProps.nextAddress != nextAddress) {
      newOutputs = (newOutputs || outputs).map((o) => ({
        ...o,
        data: { ...o.data, destination: nextAddress }
      }));
    }
    if (newOutputs) {
      this.setState(
        { outputs: newOutputs },
        this.onAttemptConstructTransaction
      );
    }
    if (constructTxLowBalance !== prevProps.constructTxLowBalance) {
      if (constructTxLowBalance) {
        this.setState({ insuficientFunds: true });
      } else {
        this.setState({ insuficientFunds: false });
      }
    }
    if (unsignedRawTx !== prevProps.unsignedRawTx && isWatchingOnly) {
      this.setState({ unsignedRawTx });
    }
  }

  render() {
    if (!this.props.walletService) {
      return <ErrorScreen />;
    }

    const {
      onChangeAccount,
      onShowConfirm,
      onShowSendAll,
      onHideSendAll,
      onShowSendSelf,
      onShowSendOthers,
      onAttemptConstructTransaction,
      onAddOutput,
      onValidateAmount,
      willEnter,
      willLeave,
      getStyles,
      getDefaultStyles,
      onKeyDown,
      resetShowPassphraseModal
    } = this;
    const isValid = this.getIsValid();
    const showPassphraseModal = this.getShowPassphraseModal();

    return (
      <SendPage
        {...{ ...this.props, ...this.state }}
        {...{
          isValid,
          onKeyDown,
          onChangeAccount,
          onShowConfirm,
          onShowSendAll,
          onHideSendAll,
          onShowSendSelf,
          onShowSendOthers,
          onAttemptConstructTransaction,
          onAddOutput,
          onValidateAmount,
          willEnter,
          willLeave,
          getStyles,
          getDefaultStyles,
          showPassphraseModal,
          resetShowPassphraseModal
        }}
      />
    );
  }

  getBaseOutput() {
    return {
      destination: "",
      amount: null,
      error: { address: null, amount: null }
    };
  }

  getDefaultStyles() {
    return this.state.outputs.map((output) => ({
      ...output,
      style: { height: 0, opacity: 1 }
    }));
  }

  getStyles() {
    const {
      outputs,
      isSendAll,
      sendAllAmount,
      isSendSelf,
      account
    } = this.state;
    const { totalSpent } = this.props;
    const {
      onChangeAccount,
      onShowSendSelf,
      onShowSendOthers,
      onKeyDown,
      onAddOutput
    } = this;
    const {
      onValidateAddress,
      onValidateAmount,
      onRemoveOutput,
      onShowSendAll,
      onHideSendAll
    } = this;
    return outputs.map((output, index) => ({
      data: (
        <OutputRow
          {...{
            ...this.props,
            index,
            outputs,
            account,
            ...output.data,
            isSendAll,
            isSendSelf,
            totalSpent,
            sendAllAmount,
            onValidateAddress,
            onValidateAmount,
            onShowSendAll,
            onHideSendAll,
            onRemoveOutput,
            onChangeAccount,
            onShowSendSelf,
            onShowSendOthers,
            onAddOutput,
            onKeyDown
          }}
        />
      ),
      key: "output_" + index,
      style: {
        opacity: spring(1, presets.gentle)
      }
    }));
  }

  willEnter() {
    return {
      opacity: 0
    };
  }

  willLeave() {
    return {
      opacity: spring(0, { stiffness: 210, damping: 20 })
    };
  }

  onChangeAccount(account) {
    this.setState({ account }, this.onAttemptConstructTransaction);
  }

  onClearTransaction() {
    this.props.onClearTransaction();
  }
  onShowSendAll() {
    const { account, outputs } = this.state;
    const newOutputs = [
      { ...outputs[0], data: { ...outputs[0].data, amount: account.spendable } }
    ];
    this.setState(
      { isSendAll: true, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }
  onHideSendAll() {
    const { outputs } = this.state;
    const newOutputs = [
      { ...outputs[0], data: { ...outputs[0].data, amount: null } }
    ];
    this.setState(
      { isSendAll: false, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }
  onShowConfirm() {
    if (!this.getIsValid()) return;
    this.setState({ isShowingConfirm: true });
  }
  onShowSendSelf() {
    const { outputs } = this.state;
    const newOutputs = [{ ...outputs[0], data: this.getBaseOutput() }];
    this.setState(
      { isSendSelf: true, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }
  onShowSendOthers() {
    const { outputs } = this.state;
    const newOutputs = [{ ...outputs[0], data: this.getBaseOutput() }];
    this.setState(
      { isSendSelf: false, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }

  onAttemptConstructTransaction() {
    const { onAttemptConstructTransaction } = this.props;
    const { isSendAll, outputs, account } = this.state;
    const confirmations = 0;

    this.setState({ sendAllAmount: account.spendable });

    if (this.getIsInvalid()) return;

    if (!isSendAll) {
      onAttemptConstructTransaction &&
        onAttemptConstructTransaction(
          account.value,
          confirmations,
          outputs.map(({ data }) => ({
            amount: data.amount,
            destination: data.destination
          }))
        );
    } else {
      onAttemptConstructTransaction &&
        onAttemptConstructTransaction(
          account.value,
          confirmations,
          outputs,
          true
        );
    }
  }

  onAddOutput() {
    const { outputs, isSendSelf } = this.state;
    if (isSendSelf) return;
    outputs.push({
      key: "output_" + outputs.length,
      data: this.getBaseOutput()
    });
    this.setState({ outputs });
  }

  onRemoveOutput(index) {
    const { outputs } = this.state;
    outputs.splice(index, 1);
    this.setState({ outputs }, this.onAttemptConstructTransaction);
  }

  onKeyDown(e) {
    if (e.keyCode === 13 && this.getIsValid()) {
      this.setState({ showPassphraseModal: true });
    }
  }

  getShowPassphraseModal() {
    return this.state.showPassphraseModal;
  }

  resetShowPassphraseModal() {
    this.setState({ showPassphraseModal: false });
  }

  onValidateAmount(data) {
    const { atomValue, index } = data;
    let error;
    if (!atomValue || isNaN(atomValue)) {
      error = (
        <T id="send.errors.invalidAmount" m="Please enter a valid amount" />
      );
    }
    if (atomValue <= 0) {
      error = (
        <T
          id="send.errors.negativeAmount"
          m="Please enter a valid amount (> 0)"
        />
      );
    }
    const ref = this.state.outputs[index];
    ref.data.amount = atomValue;

    ref.data.error.amount = error;

    this.setState({ [ref]: ref }, this.onAttemptConstructTransaction());
  }

  async onValidateAddress(data) {
    const { address, index } = data;
    let error;
    const ref = this.state.outputs[index];
    ref.data.destination = address;
    if (!address) {
      error = (
        <T id="send.errors.invalidAddress" m="Please enter a valid address" />
      );
    }
    try {
      const validated = await this.props.validateAddress(address);
      if (!validated.getIsValid()) {
        error = (
          <T id="send.errors.invalidAddress" m="Please enter a valid address" />
        );
      }
      ref.data.error.address = error;

      this.setState({ [ref]: ref }, this.onAttemptConstructTransaction());
    } catch (err) {
      this.setState({ [ref]: ref });
      return err;
    }
  }

  getIsInvalid() {
    let hasError = false;
    this.state.outputs.forEach((o) => {
      if (
        !o.data.amount ||
        o.data.destination.length === 0 ||
        o.data.error.amount ||
        o.data.error.address
      ) {
        hasError = true;
        return;
      }
    });

    return hasError;
  }

  getIsValid() {
    return !!(
      !this.getIsInvalid() &&
      this.props.unsignedTransaction &&
      !this.props.isConstructingTransaction
    );
  }
}

export default service(send(Send));
<commit_msg>[send[ Restore last address when switching to send to account (#2496)<commit_after>import { service, send } from "connectors";
import SendPage from "./Page";
import ErrorScreen from "ErrorScreen";
import { FormattedMessage as T } from "react-intl";
import { spring, presets } from "react-motion";
import OutputRow from "./OutputRow";
import { DescriptionHeader } from "layout";

export const SendTabHeader = service(({ isTestNet }) => (
  <DescriptionHeader
    description={
      isTestNet ? (
        <T
          id="transactions.description.send.testnet"
          m={
            "Testnet Decred addresses always begin with letter T and contain 26-35 alphanumeric characters\n(e.g. TxxXXXXXxXXXxXXXXxxx0XxXXXxxXxXxX0)."
          }
        />
      ) : (
        <T
          id="transactions.description.send.mainnet"
          m={
            "Mainnet Decred addresses always begin with letter D and contain 26-35 alphanumeric characters\n(e.g. DxxXXXXXxXXXxXXXXxxx0XxXXXxxXxXxX0X)."
          }
        />
      )
    }
  />
));

@autobind
class Send extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isShowingConfirm: false,
      isSendAll: false,
      isSendSelf: false,
      outputs: [{ key: "output_0", data: this.getBaseOutput() }],
      sendAllAmount: this.props.totalSpent,
      unsignedRawTx: null,
      account: this.props.defaultSpendingAccount,
      insuficientFunds: false
    };
  }

  componentDidUpdate(prevProps, prevState) {
    const {
      constructTxLowBalance,
      unsignedRawTx,
      isWatchingOnly,
      nextAddress,
      publishTxResponse,
      nextAddressAccount,
      getNextAddressAttempt
    } = this.props;
    const { isSendSelf, outputs } = this.state;
    let newOutputs;
    if (
      publishTxResponse &&
      publishTxResponse !== prevProps.publishTxResponse
    ) {
      if (isSendSelf) {
        getNextAddressAttempt(nextAddressAccount.value);
      }
      newOutputs = [{ key: "output_0", data: this.getBaseOutput() }];
      this.setState({ isSendAll: false });
    }
    if (
      isSendSelf &&
      (prevProps.nextAddress != nextAddress ||
        (prevState.isSendSelf != isSendSelf && nextAddress))
    ) {
      newOutputs = (newOutputs || outputs).map((o) => ({
        ...o,
        data: { ...o.data, destination: nextAddress }
      }));
    }
    if (newOutputs) {
      this.setState(
        { outputs: newOutputs },
        this.onAttemptConstructTransaction
      );
    }
    if (constructTxLowBalance !== prevProps.constructTxLowBalance) {
      if (constructTxLowBalance) {
        this.setState({ insuficientFunds: true });
      } else {
        this.setState({ insuficientFunds: false });
      }
    }
    if (unsignedRawTx !== prevProps.unsignedRawTx && isWatchingOnly) {
      this.setState({ unsignedRawTx });
    }
  }

  render() {
    if (!this.props.walletService) {
      return <ErrorScreen />;
    }

    const {
      onChangeAccount,
      onShowConfirm,
      onShowSendAll,
      onHideSendAll,
      onShowSendSelf,
      onShowSendOthers,
      onAttemptConstructTransaction,
      onAddOutput,
      onValidateAmount,
      willEnter,
      willLeave,
      getStyles,
      getDefaultStyles,
      onKeyDown,
      resetShowPassphraseModal
    } = this;
    const isValid = this.getIsValid();
    const showPassphraseModal = this.getShowPassphraseModal();

    return (
      <SendPage
        {...{ ...this.props, ...this.state }}
        {...{
          isValid,
          onKeyDown,
          onChangeAccount,
          onShowConfirm,
          onShowSendAll,
          onHideSendAll,
          onShowSendSelf,
          onShowSendOthers,
          onAttemptConstructTransaction,
          onAddOutput,
          onValidateAmount,
          willEnter,
          willLeave,
          getStyles,
          getDefaultStyles,
          showPassphraseModal,
          resetShowPassphraseModal
        }}
      />
    );
  }

  getBaseOutput() {
    return {
      destination: "",
      amount: null,
      error: { address: null, amount: null }
    };
  }

  getDefaultStyles() {
    return this.state.outputs.map((output) => ({
      ...output,
      style: { height: 0, opacity: 1 }
    }));
  }

  getStyles() {
    const {
      outputs,
      isSendAll,
      sendAllAmount,
      isSendSelf,
      account
    } = this.state;
    const { totalSpent } = this.props;
    const {
      onChangeAccount,
      onShowSendSelf,
      onShowSendOthers,
      onKeyDown,
      onAddOutput
    } = this;
    const {
      onValidateAddress,
      onValidateAmount,
      onRemoveOutput,
      onShowSendAll,
      onHideSendAll
    } = this;
    return outputs.map((output, index) => ({
      data: (
        <OutputRow
          {...{
            ...this.props,
            index,
            outputs,
            account,
            ...output.data,
            isSendAll,
            isSendSelf,
            totalSpent,
            sendAllAmount,
            onValidateAddress,
            onValidateAmount,
            onShowSendAll,
            onHideSendAll,
            onRemoveOutput,
            onChangeAccount,
            onShowSendSelf,
            onShowSendOthers,
            onAddOutput,
            onKeyDown
          }}
        />
      ),
      key: "output_" + index,
      style: {
        opacity: spring(1, presets.gentle)
      }
    }));
  }

  willEnter() {
    return {
      opacity: 0
    };
  }

  willLeave() {
    return {
      opacity: spring(0, { stiffness: 210, damping: 20 })
    };
  }

  onChangeAccount(account) {
    this.setState({ account }, this.onAttemptConstructTransaction);
  }

  onClearTransaction() {
    this.props.onClearTransaction();
  }
  onShowSendAll() {
    const { account, outputs } = this.state;
    const newOutputs = [
      { ...outputs[0], data: { ...outputs[0].data, amount: account.spendable } }
    ];
    this.setState(
      { isSendAll: true, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }
  onHideSendAll() {
    const { outputs } = this.state;
    const newOutputs = [
      { ...outputs[0], data: { ...outputs[0].data, amount: null } }
    ];
    this.setState(
      { isSendAll: false, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }
  onShowConfirm() {
    if (!this.getIsValid()) return;
    this.setState({ isShowingConfirm: true });
  }
  onShowSendSelf() {
    const { outputs } = this.state;
    const newOutputs = [{ ...outputs[0], data: this.getBaseOutput() }];
    this.setState(
      { isSendSelf: true, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }
  onShowSendOthers() {
    const { outputs } = this.state;
    const newOutputs = [{ ...outputs[0], data: this.getBaseOutput() }];
    this.setState(
      { isSendSelf: false, outputs: newOutputs },
      this.onAttemptConstructTransaction
    );
  }

  onAttemptConstructTransaction() {
    const { onAttemptConstructTransaction } = this.props;
    const { isSendAll, outputs, account } = this.state;
    const confirmations = 0;

    this.setState({ sendAllAmount: account.spendable });

    if (this.getIsInvalid()) return;

    if (!isSendAll) {
      onAttemptConstructTransaction &&
        onAttemptConstructTransaction(
          account.value,
          confirmations,
          outputs.map(({ data }) => ({
            amount: data.amount,
            destination: data.destination
          }))
        );
    } else {
      onAttemptConstructTransaction &&
        onAttemptConstructTransaction(
          account.value,
          confirmations,
          outputs,
          true
        );
    }
  }

  onAddOutput() {
    const { outputs, isSendSelf } = this.state;
    if (isSendSelf) return;
    outputs.push({
      key: "output_" + outputs.length,
      data: this.getBaseOutput()
    });
    this.setState({ outputs });
  }

  onRemoveOutput(index) {
    const { outputs } = this.state;
    outputs.splice(index, 1);
    this.setState({ outputs }, this.onAttemptConstructTransaction);
  }

  onKeyDown(e) {
    if (e.keyCode === 13 && this.getIsValid()) {
      this.setState({ showPassphraseModal: true });
    }
  }

  getShowPassphraseModal() {
    return this.state.showPassphraseModal;
  }

  resetShowPassphraseModal() {
    this.setState({ showPassphraseModal: false });
  }

  onValidateAmount(data) {
    const { atomValue, index } = data;
    let error;
    if (!atomValue || isNaN(atomValue)) {
      error = (
        <T id="send.errors.invalidAmount" m="Please enter a valid amount" />
      );
    }
    if (atomValue <= 0) {
      error = (
        <T
          id="send.errors.negativeAmount"
          m="Please enter a valid amount (> 0)"
        />
      );
    }
    const ref = this.state.outputs[index];
    ref.data.amount = atomValue;

    ref.data.error.amount = error;

    this.setState({ [ref]: ref }, this.onAttemptConstructTransaction());
  }

  async onValidateAddress(data) {
    const { address, index } = data;
    let error;
    const ref = this.state.outputs[index];
    ref.data.destination = address;
    if (!address) {
      error = (
        <T id="send.errors.invalidAddress" m="Please enter a valid address" />
      );
    }
    try {
      const validated = await this.props.validateAddress(address);
      if (!validated.getIsValid()) {
        error = (
          <T id="send.errors.invalidAddress" m="Please enter a valid address" />
        );
      }
      ref.data.error.address = error;

      this.setState({ [ref]: ref }, this.onAttemptConstructTransaction());
    } catch (err) {
      this.setState({ [ref]: ref });
      return err;
    }
  }

  getIsInvalid() {
    let hasError = false;
    this.state.outputs.forEach((o) => {
      if (
        !o.data.amount ||
        o.data.destination.length === 0 ||
        o.data.error.amount ||
        o.data.error.address
      ) {
        hasError = true;
        return;
      }
    });

    return hasError;
  }

  getIsValid() {
    return !!(
      !this.getIsInvalid() &&
      this.props.unsignedTransaction &&
      !this.props.isConstructingTransaction
    );
  }
}

export default service(send(Send));
<|endoftext|>


<commit_before>var React = require('react');
var ReactDOM = require('react-dom');
var ReactDOMServer = require('react-dom/server');

var baseHtml = require('app/common/BaseHtml');
var homePage = require('app/homescreen/HomePage');
var loginPage = require('app/login/LoginPage');
var trainingsPage = require('app/trainings/TrainingsPage');
var assessmentsPage = require('app/assessments/AssessmentsPage');
var reportsPage = require('app/reports/ReportsPage');
var seasonsPage = require('app/seasons/SeasonsPage');
var termsPage = require('app/static/TermsPage');
var aboutPage = require('app/static/AboutPage');

var trainerReportsPage = require('app/trainer/reports/TrainerReportsPage');

import { StyleProvider } from 'global/StyleProvider';

/**
 * Controller for switching between pages.
 * @param {Object} i18next controller to translations
 * @author Matheus
 * @since 1.0.0
 */
function PageSwitcher(i18next) {
  this.i18n = i18next;

  if (typeof window !== 'undefined') {
    window.onpopstate = this.popSwitch.bind(this);
  }
}

const getPageReactClass = function(pageTitle) {
  switch (pageTitle) {
    case 'aboutPage':
      return aboutPage;
    case 'termsPage':
      return termsPage;
    case 'seasonsPage':
      return seasonsPage;
    case 'reportsPage':
      return reportsPage;
    case 'assessmentsPage':
      return assessmentsPage;
    case 'trainingsPage':
      return trainingsPage;
    case 'homePage':
      return homePage;
    case 'loginPage':
      return loginPage;
    case 'trainerReportsPage':
      return trainerReportsPage;
    default:
      console.error(new ReferenceError("Page not found!"));
      return undefined;
  }
};

// TODO find a better way to do universal rendering without conflict.
const getPageNamespaces = function(pageTitle) {
  switch (pageTitle) {
    case 'aboutPage':
      return ['common', 'about'];
    case 'termsPage':
      return ['common', 'terms'];
    case 'seasonsPage':
      return ['common', 'season'];
    case 'reportsPage':
      return ['common', 'season', 'report'];
    case 'assessmentsPage':
      return ['common', 'assessment'];
    case 'trainingsPage':
      return ['common', 'training'];
    case 'homePage':
      return ['common', 'home'];
    case 'loginPage':
      return ['common', 'login'];
    case 'trainerReportsPage':
      return ['common', 'report', 'trainer'];
    default:
      console.error(new ReferenceError("Page not found!"));
      return [];
  }
};

function getPageUrlPath(pageTitle) {
  switch (pageTitle) {
    case 'aboutPage':
      return 'about';
    case 'termsPage':
      return 'terms';
    case 'seasonsPage':
      return 'seasons';
    case 'reportsPage':
      return 'reports';
    case 'assessmentsPage':
      return 'assessments';
    case 'trainingsPage':
      return 'trainings';
    case 'homePage':
      return 'home';
    case 'loginPage':
      return 'login';
    case 'trainerReportsPage':
      return 'trainer-reports';
    default:
      console.error(new ReferenceError("Page not found!"));
      return [];
  }
}

PageSwitcher.prototype.getPageUrlPath = getPageUrlPath;

PageSwitcher.prototype.renderPage = function(pageTitle, callback) {
  // var renderParent = document.getElementById('aaa-baseLayout').parentNode;
  var renderParent = document.getElementsByTagName('html')[0].parentNode;
  // TODO move this to constants to share between server/app
  const props = {
    switcher: this,
    userAgent: navigator.userAgent,
    styleProvider: new StyleProvider(navigator.userAgent),
    i18n: this.i18n,
  };

  props.container = getPageReactClass(pageTitle);
  this.i18n.loadNamespaces(getPageNamespaces(pageTitle), function(err, t) {
    if (!err) {
      props.title = props.i18n.t(['common:pageTitle.', pageTitle].join(''));
      ReactDOM.render(React.createElement(baseHtml, props), renderParent);
      props.styleProvider.loadScreenSizes();

      const sizes = {}
      window.addEventListener('TextFieldBlurred', (event) => {
        const width = parseInt(window.innerWidth);
        const height = parseInt(window.innerHeight);
        if(sizes.height < height * 0.95 ||
           sizes.height > height * 1.05 ||
           sizes.width < width * 0.95 ||
           sizes.width > width * 1.05){
          ReactDOM.render(React.createElement(baseHtml, props), renderParent);
          sizes.width = width;
          sizes.height = height;
        }
      });
      window.addEventListener('TextFieldFocused', (event) => {
        sizes.width = parseInt(window.innerWidth);
        sizes.height = parseInt(window.innerHeight);
      });
      callback();
      return;
    }
    console.error('Namespaces could not be loaded to switch!', err);
  });
};

PageSwitcher.prototype.switchTo = function switchTo(pageTitle) {
  this.renderPage(pageTitle, function() {
    window.history.pushState({pageTitle}, pageTitle, getPageUrlPath(pageTitle));
  });
};

PageSwitcher.prototype.popSwitch = function popSwitch(e) {
  if (e.state) {
    this.renderPage(e.state.pageTitle, function() {});
  }
};

PageSwitcher.prototype.loadClient = function loadClient(pageTitle) {
  this.renderPage(pageTitle, function() {
    window.history.pushState({pageTitle}, pageTitle, getPageUrlPath(pageTitle));
  });
};

PageSwitcher.prototype.serverString = function serverString(pageTitle,
                                                            request) {
  // TODO move this to constants to share between server/app
  const props = {
    switcher: this,
    userAgent: request.headers['user-agent'],
    styleProvider: new StyleProvider(request.headers['user-agent']),
    i18n: request.i18n,
    title: request.i18n.t(['common:pageTitle.', pageTitle].join(''))
  };
  props.container = getPageReactClass(pageTitle);
  return ReactDOMServer.renderToString(React.createElement(baseHtml, props));
};

module.exports = PageSwitcher;
<commit_msg>Fixing rendering.<commit_after>var React = require('react');
var ReactDOM = require('react-dom');
var ReactDOMServer = require('react-dom/server');

var baseHtml = require('app/common/BaseHtml');
var homePage = require('app/homescreen/HomePage');
var loginPage = require('app/login/LoginPage');
var trainingsPage = require('app/trainings/TrainingsPage');
var assessmentsPage = require('app/assessments/AssessmentsPage');
var reportsPage = require('app/reports/ReportsPage');
var seasonsPage = require('app/seasons/SeasonsPage');
var termsPage = require('app/static/TermsPage');
var aboutPage = require('app/static/AboutPage');

var trainerReportsPage = require('app/trainer/reports/TrainerReportsPage');

import { StyleProvider } from 'global/StyleProvider';

/**
 * Controller for switching between pages.
 * @param {Object} i18next controller to translations
 * @author Matheus
 * @since 1.0.0
 */
function PageSwitcher(i18next) {
  this.i18n = i18next;

  if (typeof window !== 'undefined') {
    window.onpopstate = this.popSwitch.bind(this);
  }
}

const getPageReactClass = function(pageTitle) {
  switch (pageTitle) {
    case 'aboutPage':
      return aboutPage;
    case 'termsPage':
      return termsPage;
    case 'seasonsPage':
      return seasonsPage;
    case 'reportsPage':
      return reportsPage;
    case 'assessmentsPage':
      return assessmentsPage;
    case 'trainingsPage':
      return trainingsPage;
    case 'homePage':
      return homePage;
    case 'loginPage':
      return loginPage;
    case 'trainerReportsPage':
      return trainerReportsPage;
    default:
      console.error(new ReferenceError("Page not found!"));
      return undefined;
  }
};

// TODO find a better way to do universal rendering without conflict.
const getPageNamespaces = function(pageTitle) {
  switch (pageTitle) {
    case 'aboutPage':
      return ['common', 'about'];
    case 'termsPage':
      return ['common', 'terms'];
    case 'seasonsPage':
      return ['common', 'season'];
    case 'reportsPage':
      return ['common', 'season', 'report'];
    case 'assessmentsPage':
      return ['common', 'assessment'];
    case 'trainingsPage':
      return ['common', 'training'];
    case 'homePage':
      return ['common', 'home'];
    case 'loginPage':
      return ['common', 'login'];
    case 'trainerReportsPage':
      return ['common', 'report', 'trainer'];
    default:
      console.error(new ReferenceError("Page not found!"));
      return [];
  }
};

function getPageUrlPath(pageTitle) {
  switch (pageTitle) {
    case 'aboutPage':
      return 'about';
    case 'termsPage':
      return 'terms';
    case 'seasonsPage':
      return 'seasons';
    case 'reportsPage':
      return 'reports';
    case 'assessmentsPage':
      return 'assessments';
    case 'trainingsPage':
      return 'trainings';
    case 'homePage':
      return 'home';
    case 'loginPage':
      return 'login';
    case 'trainerReportsPage':
      return 'trainer-reports';
    default:
      console.error(new ReferenceError("Page not found!"));
      return [];
  }
}

PageSwitcher.prototype.getPageUrlPath = getPageUrlPath;

PageSwitcher.prototype.renderPage = function(pageTitle, callback) {
  // var renderParent = document.getElementById('aaa-baseLayout').parentNode;
  var renderParent = document.getElementsByTagName('html')[0].parentNode;
  // TODO move this to constants to share between server/app
  const props = {
    switcher: this,
    userAgent: 'Mozilla/5.0 (Fixed) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Safari/537.36',
    styleProvider: new StyleProvider(navigator.userAgent),
    i18n: this.i18n,
  };

  props.container = getPageReactClass(pageTitle);
  this.i18n.loadNamespaces(getPageNamespaces(pageTitle), function(err, t) {
    if (!err) {
      props.title = props.i18n.t(['common:pageTitle.', pageTitle].join(''));

      const created = React.createElement(baseHtml, props);
      ReactDOM.render(created, renderParent);

      props.styleProvider.loadScreenSizes();

      const sizes = {}
      window.addEventListener('TextFieldBlurred', (event) => {
        const width = parseInt(window.innerWidth);
        const height = parseInt(window.innerHeight);
        if(sizes.height < height * 0.95 ||
           sizes.height > height * 1.05 ||
           sizes.width < width * 0.95 ||
           sizes.width > width * 1.05){
          ReactDOM.render(React.cloneElement(created,{}), renderParent);
          sizes.width = width;
          sizes.height = height;
        }
      });
      window.addEventListener('TextFieldFocused', (event) => {
        sizes.width = parseInt(window.innerWidth);
        sizes.height = parseInt(window.innerHeight);
      });
      callback();
      return;
    }
    console.error('Namespaces could not be loaded to switch!', err);
  });
};

PageSwitcher.prototype.switchTo = function switchTo(pageTitle) {
  this.renderPage(pageTitle, function() {
    window.history.pushState({pageTitle}, pageTitle, getPageUrlPath(pageTitle));
  });
};

PageSwitcher.prototype.popSwitch = function popSwitch(e) {
  if (e.state) {
    this.renderPage(e.state.pageTitle, function() {});
  }
};

PageSwitcher.prototype.loadClient = function loadClient(pageTitle) {
  this.renderPage(pageTitle, function() {
    window.history.pushState({pageTitle}, pageTitle, getPageUrlPath(pageTitle));
  });
};

PageSwitcher.prototype.serverString = function serverString(pageTitle,
                                                            request) {
  // TODO move this to constants to share between server/app
  const props = {
    switcher: this,
    userAgent: 'Mozilla/5.0 (Fixed) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Safari/537.36',
    styleProvider: new StyleProvider(request.headers['user-agent']),
    i18n: request.i18n,
    title: request.i18n.t(['common:pageTitle.', pageTitle].join(''))
  };
  props.container = getPageReactClass(pageTitle);
  return ReactDOMServer.renderToString(React.createElement(baseHtml, props));
};

module.exports = PageSwitcher;
<|endoftext|>


<commit_before>var concat = require('concat-stream')
var Router = require('routes-router')
var ecstatic = require('ecstatic')
var redis = require('redis')

module.exports = function(opts){

  console.log('using redis server')

  var port = opts.redis_port || process.env.USE_REDIS_PORT || 6379
  var host = opts.redis_host || process.env.USE_REDIS_HOST || 'redis'

  var connectionStatus = false

  var client = redis.createClient(port, host, {})
  client.on('error', function(err){
    connectionStatus = false
    console.log('Error from the redis connection:')
    console.log(err)
  })
  client.on('end', function(err){
    connectionStatus = false
    console.log('Lost connection to Redis server')
  })
  client.on('ready', function(err){
    connectionStatus = true
    console.log('Connection made to the Redis server')
  })

  console.log('-------------------------------------------');
  console.log('have host: ' + host)
  console.log('have port: ' + port)

  var router = Router()
  var fileServer = ecstatic({ root: __dirname + '/client' })

  router.addRoute("/v1/ping", {
    GET: function(req, res){
      res.setHeader('Content-type', 'application/json')
      res.end(JSON.stringify({
        connected:connectionStatus
      }))
    }
  })

  router.addRoute("/v1/whales", {
    GET: function (req, res) {

      client.lrange('whales', 0, -1, function(err, data){
        res.setHeader('Content-type', 'application/json')
        res.end(JSON.stringify(data))
      })
    },
    POST: function (req, res) {
      req.pipe(concat(function(data){
        data = data.toString()

        client.rpush('whales', data, function(){
          client.save(function(){
            res.end('ok')
          })
        })

      }))
    }
  })

  router.addRoute("/*", fileServer)

  return router
}
<commit_msg>adds clicks<commit_after>var concat = require('concat-stream')
var Router = require('routes-router')
var ecstatic = require('ecstatic')
var redis = require('redis')

module.exports = function(opts){

  console.log('using redis server')

  var port = opts.redis_port || process.env.USE_REDIS_PORT || 6379
  var host = opts.redis_host || process.env.USE_REDIS_HOST || 'redis'

  var connectionStatus = false

  var client = redis.createClient(port, host, {})
  client.on('error', function(err){
    connectionStatus = false
    console.log('Error from the redis connection:')
    console.log(err)
  })
  client.on('end', function(err){
    connectionStatus = false
    console.log('Lost connection to Redis server')
  })
  client.on('ready', function(err){
    connectionStatus = true
    console.log('Connection made to the Redis server')
  })

  console.log('-------------------------------------------');
  console.log('have host: ' + host)
  console.log('have port: ' + port)

  var router = Router()
  var fileServer = ecstatic({ root: __dirname + '/client' })

  router.addRoute("/v1/ping", {
    GET: function(req, res){
      res.setHeader('Content-type', 'application/json')
      res.end(JSON.stringify({
        connected:connectionStatus
      }))
    }
  })

  router.addRoute("/v1/whales", {
    GET: function (req, res) {

      client.lrange('whales', 0, -1, function(err, data){
        res.setHeader('Content-type', 'application/json')
        res.end(JSON.stringify(data))
      })
    },
    POST: function (req, res) {
      req.pipe(concat(function(data){
        data = data.toString()

        client.rpush('whales', data, function(){
          client.save(function(){
            console.log("1 click")
            res.end('ok')
          })
        })

      }))
    }
  })

  router.addRoute("/*", fileServer)

  return router
}
<|endoftext|>


<commit_before> var test = require('mocha').it,
    expect = require('chai').expect, // Use `expect(X).to.be` et al
    assert = require('chai').assert;  // OR use `assert.equal` etc

test('getting a list of multiples of 3', function(){
  assert.isDefined(threes);
  assert.isFunction(threes);
  expect(threes(0)).to.eql([]);
  expect(threes(3)).to.eql([]);
  expect(threes(6)).to.eql([3]);
  expect(threes(10)).to.eql([3, 6, 9]);
  expect(threes(20)).to.eql([3, 6, 9, 12, 15, 18]);
  expect(threes(50)).to.eql([3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39,
   42, 45, 48]);
}); // END test 3s

function threes(N) {//return a list of muliples of 3 below N.
  var multiplesOfThree = []
  for (count = 1; count < N; count ++) {
    if (count % 3 === 0){
      multiplesOfThree.push(count);
    }
  }
  return multiplesOfThree;
}

test('getting a list of multiples of 5', function(){
  assert.isDefined(fives);
  assert.isFunction(fives);
  expect(fives(0)).to.eql([]);
  expect(fives(10)).to.eql([5]);
  expect(fives(20)).to.eql([5, 10, 15]);
  expect(fives(30)).to.eql([5, 10, 15, 20, 25]);
  expect(fives(50)).to.eql([5, 10, 15, 20, 25, 30, 35, 40, 45]);
}); // END test 3s

function fives(N) {//return a list of muliples of 5 below N.
  var multiplesOfThree = []
  for (count = 1; count < N; count ++) {
    if (count % 5 === 0){
      multiplesOfThree.push(count);
    }
  }
  return multiplesOfThree;
}
<commit_msg>finished function that returns list of threes and fives...next up, adding them together<commit_after> var test = require('mocha').it,
    expect = require('chai').expect, // Use `expect(X).to.be` et al
    assert = require('chai').assert;  // OR use `assert.equal` etc

test('getting a list of multiples of 3', function(){
  assert.isDefined(threes);
  assert.isFunction(threes);
  expect(threes(0)).to.eql([]);
  expect(threes(3)).to.eql([]);
  expect(threes(6)).to.eql([3]);
  expect(threes(10)).to.eql([3, 6, 9]);
  expect(threes(20)).to.eql([3, 6, 9, 12, 15, 18]);
  expect(threes(50)).to.eql([3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39,
   42, 45, 48]);
}); // END test 3s

function threes(N) {//return a list of muliples of 3 below N.
  var multiplesOfThree = []
  for (count = 1; count < N; count ++) {
    if (count % 3 === 0){
      multiplesOfThree.push(count);
    }
  }
  return multiplesOfThree;
}

test('getting a list of multiples of 5', function(){
  assert.isDefined(fives);
  assert.isFunction(fives);
  expect(fives(0)).to.eql([]);
  expect(fives(10)).to.eql([5]);
  expect(fives(20)).to.eql([5, 10, 15]);
  expect(fives(30)).to.eql([5, 10, 15, 20, 25]);
  expect(fives(50)).to.eql([5, 10, 15, 20, 25, 30, 35, 40, 45]);
}); // END test 5s

function fives(N) {//return a list of muliples of 5 below N.
  var multiplesOfFive = []
  for (count = 1; count < N; count ++) {
    if (count % 5 === 0){
      multiplesOfFive.push(count);
    }
  }
  return multiplesOfFive;
}

/* now we want to make a function that returns a list of numbers that multiples of 3's
and/or 5's below N.
*/

test('merging the threes and fives', function(){
  assert.isDefined(threesAndFives);
  assert.isFunction(threesAndFives);
  expect(threesAndFives(0)).to.eql([]);
  expect(threesAndFives(5)).to.eql([3]);
  expect(threesAndFives(10)).to.eql([3, 5, 6, 9]);
  expect(threesAndFives(20)).to.eql([3, 5, 6, 9, 10, 12, 15, 18]);
  expect(threesAndFives(30)).to.eql([3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27]);
  expect(threesAndFives(50)).to.eql([3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27,
    30, 33, 35, 36, 39, 40, 42, 45, 48]);
 }); // END test threesAndFives

function threesAndFives(N) {
  var multiplesOfThreeAndFive = [];
  for (count = 1; count < N; count ++) {
    if (count % 3 === 0 || count % 5 === 0) {
      multiplesOfThreeAndFive.push(count);
    }
  }
  return multiplesOfThreeAndFive;
}
<|endoftext|>


<commit_before>'use strict';

angular.module('users').controller('ProfileBookmarksController', [
  '$scope',
  'UserApi',
  'Action',
  'ngDialog',
  'toastr',
  function($scope, UserApi, Action, dialog, toast) {
    $scope.polls = [];
    $scope.page = 0;
    $scope.busy = false;
    $scope.stopped = false;
    $scope.new_data = [];

    $scope.get_polls = get_polls;
    function get_polls() {
      if ($scope.busy || $scope.stopped) {
        return;
      }
      $scope.busy = true;
      UserApi.get_bookmarks($scope.profile._id, $scope.page)
        .then(res => {
          if (!res.data.length || res.data.length === 0) {
            $scope.busy = false;
            $scope.stopped = true;
            return;
          }
          console.log(res);
          // res.forEach(item => {
          //   if (item.poll) {
          //     $scope.new_data.push(item.poll);
          //   }
          // });
          $scope.new_data = res.data || [];
          var promises = [];
          $scope.new_data.forEach(poll => {
            poll.isCurrentUserOwner = $scope.isLogged && $scope.user._id === poll.user._id;
            promises.push(get_poll_report(poll));
            promises.push(get_opts(poll));
            promises.push(get_owner_follow(poll));
            promises.push(get_reported(poll));
            promises.push(get_bookmarked(poll));
          });
          return Promise.all(promises);
        })
        .then(res => {
          // Gán data vào list hiện tại
          $scope.polls = _.union($scope.polls, $scope.new_data);
          $scope.page += 1;
          $scope.busy = false;
          $scope.new_data = [];
        })
        .catch(err => {
          $scope.busy = false;
          $scope.stopped = true;
          toast.error(err.message, 'Error!');
        });
    }
    function get_poll_report(poll) {
      return new Promise((resolve, reject) => {
        Action.get_poll_report(poll._id)
          .then(res => {
            poll.report = res.data;
            return resolve(res);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_opts(poll) {
      return new Promise((resolve, reject) => {
        Action.get_opts(poll._id)
          .then(res => {
            poll.opts = _.where(res.data, { status: 1 }) || [];
            return get_vote_for_poll(poll);
          })
          .then(res => {
            return resolve(poll);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_vote_for_poll(poll) {
      return new Promise((resolve, reject) => {
        Action.get_voteopts(poll._id)
          .then(res => {
            poll.chart = {
              options: { responsive: true },
              colors: [],
              labels: [],
              data: []
            };
            poll.votes = res.data.votes || [];
            poll.voteopts = res.data.voteopts || [];
            poll.total = poll.voteopts.length;
            poll.opts.forEach(opt => {
              opt.voteCnt = _.where(poll.voteopts, { opt: opt._id }).length || 0;
              opt.progressVal = calPercen(poll.total, opt.voteCnt);
              poll.chart.data.push(opt.voteCnt);
              poll.chart.colors.push(opt.color);
              poll.chart.labels.push(opt.title);
            });
            return resolve(poll);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_owner_follow(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.follow = {};
          return resolve();
        }
        Action.get_follow(poll._id)
          .then(res => {
            poll.follow = res.data || { poll: poll._id };
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_reported(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.reported = false;
          return resolve();
        }
        Action.get_report(poll._id)
          .then(res => {
            poll.reported = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_bookmarked(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.bookmarked = false;
          return resolve();
        }
        Action.get_bookmark(poll._id)
          .then(res => {
            poll.bookmarked = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    $scope.poll_filter = poll => {
      if (poll.isPublic) {
        return true;
      } else {
        return $scope.isCurrentOwner;
      }
    };
    // Tính phần trăm tỉ lệ vote cho opt
    function calPercen(total, value) {
      if (total === 0) {
        return 0;
      }
      return Math.floor(value * 100 / total) || 0;
    }
  }
]);
<commit_msg>Commited from lenh at Thu, Jul 20, 2017 10:22:35 AM<commit_after>'use strict';

angular.module('users').controller('ProfileBookmarksController', [
  '$scope',
  'UserApi',
  'Action',
  'ngDialog',
  'toastr',
  function($scope, UserApi, Action, dialog, toast) {
    $scope.polls = [];
    $scope.page = 0;
    $scope.busy = false;
    $scope.stopped = false;
    $scope.new_data = [];

    $scope.get_polls = get_polls;
    function get_polls() {
      if ($scope.busy || $scope.stopped) {
        return;
      }
      $scope.busy = true;
      UserApi.get_bookmarks($scope.profile._id, $scope.page)
        .then(res => {
          if (!res.data.length || res.data.length === 0) {
            $scope.busy = false;
            $scope.stopped = true;
            return;
          }
          res.data.forEach(item => {
            if (item.poll) {
              $scope.new_data.push(item.poll);
            }
          });
          var promises = [];
          $scope.new_data.forEach(poll => {
            poll.isCurrentUserOwner = $scope.isLogged && $scope.user._id === poll.user._id;
            promises.push(get_poll_report(poll));
            promises.push(get_opts(poll));
            promises.push(get_owner_follow(poll));
            promises.push(get_reported(poll));
            promises.push(get_bookmarked(poll));
          });
          return Promise.all(promises);
        })
        .then(res => {
          // Gán data vào list hiện tại
          $scope.polls = _.union($scope.polls, $scope.new_data);
          $scope.page += 1;
          $scope.busy = false;
          $scope.new_data = [];
        })
        .catch(err => {
          $scope.busy = false;
          $scope.stopped = true;
          toast.error(err.message, 'Error!');
        });
    }
    function get_poll_report(poll) {
      return new Promise((resolve, reject) => {
        Action.get_poll_report(poll._id)
          .then(res => {
            poll.report = res.data;
            return resolve(res);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_opts(poll) {
      return new Promise((resolve, reject) => {
        Action.get_opts(poll._id)
          .then(res => {
            poll.opts = _.where(res.data, { status: 1 }) || [];
            return get_vote_for_poll(poll);
          })
          .then(res => {
            return resolve(poll);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_vote_for_poll(poll) {
      return new Promise((resolve, reject) => {
        Action.get_voteopts(poll._id)
          .then(res => {
            poll.chart = {
              options: { responsive: true },
              colors: [],
              labels: [],
              data: []
            };
            poll.votes = res.data.votes || [];
            poll.voteopts = res.data.voteopts || [];
            poll.total = poll.voteopts.length;
            poll.opts.forEach(opt => {
              opt.voteCnt = _.where(poll.voteopts, { opt: opt._id }).length || 0;
              opt.progressVal = calPercen(poll.total, opt.voteCnt);
              poll.chart.data.push(opt.voteCnt);
              poll.chart.colors.push(opt.color);
              poll.chart.labels.push(opt.title);
            });
            return resolve(poll);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_owner_follow(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.follow = {};
          return resolve();
        }
        Action.get_follow(poll._id)
          .then(res => {
            poll.follow = res.data || { poll: poll._id };
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_reported(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.reported = false;
          return resolve();
        }
        Action.get_report(poll._id)
          .then(res => {
            poll.reported = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    function get_bookmarked(poll) {
      return new Promise((resolve, reject) => {
        if (!$scope.isLogged) {
          poll.bookmarked = false;
          return resolve();
        }
        Action.get_bookmark(poll._id)
          .then(res => {
            poll.bookmarked = (res.data) ? res.data : false;
            return resolve(res.data);
          })
          .catch(err => {
            return reject(err);
          });
      });
    }
    $scope.poll_filter = poll => {
      if (poll.isPublic) {
        return true;
      } else {
        return $scope.isCurrentOwner;
      }
    };
    // Tính phần trăm tỉ lệ vote cho opt
    function calPercen(total, value) {
      if (total === 0) {
        return 0;
      }
      return Math.floor(value * 100 / total) || 0;
    }
  }
]);
<|endoftext|>


<commit_before>/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

const {Token} = require('./Token');
const Recognizer = require('./Recognizer');
const CommonTokenFactory = require('./CommonTokenFactory');
const {RecognitionException} = require('./error/Errors');
const {LexerNoViableAltException} = require('./error/Errors');

class TokenSource {}

/**
 * A lexer is recognizer that draws input symbols from a character stream.
 * lexer grammars result in a subclass of this object. A Lexer object
 * uses simplified match() and error recovery mechanisms in the interest of speed.
 */
class Lexer extends Recognizer {
	constructor(input) {
		super();
		this._input = input;
		this._factory = CommonTokenFactory.DEFAULT;
		this._tokenFactorySourcePair = [ this, input ];

		this._interp = null; // child classes must populate this

		/**
		 * The goal of all lexer rules/methods is to create a token object.
		 * this is an instance variable as multiple rules may collaborate to
		 * create a single token. nextToken will return this object after
		 * matching lexer rule(s). If you subclass to allow multiple token
		 * emissions, then set this to the last token to be matched or
		 * something nonnull so that the auto token emit mechanism will not
		 * emit another token.
		 */
		this._token = null;

		/**
		 * What character index in the stream did the current token start at?
		 * Needed, for example, to get the text for current token. Set at
		 * the start of nextToken.
		 */
		this._tokenStartCharIndex = -1;

		// The line on which the first character of the token resides///
		this._tokenStartLine = -1;

		// The character position of first character within the line///
		this._tokenStartColumn = -1;

		// Once we see EOF on char stream, next token will be EOF.
		// If you have DONE : EOF ; then you see DONE EOF.
		this._hitEOF = false;

		// The channel number for the current token///
		this._channel = Token.DEFAULT_CHANNEL;

		// The token type for the current token///
		this._type = Token.INVALID_TYPE;

		this._modeStack = [];
		this._mode = Lexer.DEFAULT_MODE;

		/**
		 * You can set the text for the current token to override what is in
		 * the input char buffer. Use setText() or can set this instance var.
		 */
		this._text = null;
	}

	reset() {
		// wack Lexer state variables
		if (this._input !== null) {
			this._input.seek(0); // rewind the input
		}
		this._token = null;
		this._type = Token.INVALID_TYPE;
		this._channel = Token.DEFAULT_CHANNEL;
		this._tokenStartCharIndex = -1;
		this._tokenStartColumn = -1;
		this._tokenStartLine = -1;
		this._text = null;

		this._hitEOF = false;
		this._mode = Lexer.DEFAULT_MODE;
		this._modeStack = [];

		this._interp.reset();
	}

// Return a token from this source; i.e., match a token on the char stream.
	nextToken() {
		if (this._input === null) {
			throw "nextToken requires a non-null input stream.";
		}

		/**
		 * Mark start location in char stream so unbuffered streams are
		 * guaranteed at least have text of current token
		 */
		const tokenStartMarker = this._input.mark();
		try {
			while (true) {
				if (this._hitEOF) {
					this.emitEOF();
					return this._token;
				}
				this._token = null;
				this._channel = Token.DEFAULT_CHANNEL;
				this._tokenStartCharIndex = this._input.index;
				this._tokenStartColumn = this._interp.column;
				this._tokenStartLine = this._interp.line;
				this._text = null;
				let continueOuter = false;
				while (true) {
					this._type = Token.INVALID_TYPE;
					let ttype = Lexer.SKIP;
					try {
						ttype = this._interp.match(this._input, this._mode);
					} catch (e) {
						if(e instanceof RecognitionException) {
							this.notifyListeners(e); // report error
							this.recover(e);
						} else {
							console.log(e.stack);
							throw e;
						}
					}
					if (this._input.LA(1) === Token.EOF) {
						this._hitEOF = true;
					}
					if (this._type === Token.INVALID_TYPE) {
						this._type = ttype;
					}
					if (this._type === Lexer.SKIP) {
						continueOuter = true;
						break;
					}
					if (this._type !== Lexer.MORE) {
						break;
					}
				}
				if (continueOuter) {
					continue;
				}
				if (this._token === null) {
					this.emit();
				}
				return this._token;
			}
		} finally {
			// make sure we release marker after match or
			// unbuffered char stream will keep buffering
			this._input.release(tokenStartMarker);
		}
	}

	/**
	 * Instruct the lexer to skip creating a token for current lexer rule
	 * and look for another token. nextToken() knows to keep looking when
	 * a lexer rule finishes with token set to SKIP_TOKEN. Recall that
	 * if token==null at end of any token rule, it creates one for you
	 * and emits it.
	 */
	skip() {
		this._type = Lexer.SKIP;
	}

	more() {
		this._type = Lexer.MORE;
	}

	mode(m) {
		this._mode = m;
	}

	pushMode(m) {
		if (this._interp.debug) {
			console.log("pushMode " + m);
		}
		this._modeStack.push(this._mode);
		this.mode(m);
	}

	popMode() {
		if (this._modeStack.length === 0) {
			throw "Empty Stack";
		}
		if (this._interp.debug) {
			console.log("popMode back to " + this._modeStack.slice(0, -1));
		}
		this.mode(this._modeStack.pop());
		return this._mode;
	}

	/**
	 * By default does not support multiple emits per nextToken invocation
	 * for efficiency reasons. Subclass and override this method, nextToken,
	 * and getToken (to push tokens into a list and pull from that list
	 * rather than a single variable as this implementation does).
	 */
	emitToken(token) {
		this._token = token;
	}

	/**
	 * The standard method called to automatically emit a token at the
	 * outermost lexical rule. The token object should point into the
	 * char buffer start..stop. If there is a text override in 'text',
	 * use that to set the token's text. Override this method to emit
	 * custom Token objects or provide a new factory.
	 */
	emit() {
		const t = this._factory.create(this._tokenFactorySourcePair, this._type,
				this._text, this._channel, this._tokenStartCharIndex, this
						.getCharIndex() - 1, this._tokenStartLine,
				this._tokenStartColumn);
		this.emitToken(t);
		return t;
	}

	emitEOF() {
		const cpos = this.column;
		const lpos = this.line;
		const eof = this._factory.create(this._tokenFactorySourcePair, Token.EOF,
				null, Token.DEFAULT_CHANNEL, this._input.index,
				this._input.index - 1, lpos, cpos);
		this.emitToken(eof);
		return eof;
	}

// What is the index of the current character of lookahead?///
	getCharIndex() {
		return this._input.index;
	}

	/**
	 * Return a list of all Token objects in input char stream.
	 * Forces load of all tokens. Does not include EOF token.
	 */
	getAllTokens() {
		const tokens = [];
		let t = this.nextToken();
		while (t.type !== Token.EOF) {
			tokens.push(t);
			t = this.nextToken();
		}
		return tokens;
	}

	notifyListeners(e) {
		const start = this._tokenStartCharIndex;
		const stop = this._input.index;
		const text = this._input.getText(start, stop);
		const msg = "token recognition error at: '" + this.getErrorDisplay(text) + "'";
		const listener = this.getErrorListenerDispatch();
		listener.syntaxError(this, null, this._tokenStartLine,
				this._tokenStartColumn, msg, e);
	}

	getErrorDisplay(s) {
		const d = [];
		for (let i = 0; i < s.length; i++) {
			d.push(s[i]);
		}
		return d.join('');
	}

	getErrorDisplayForChar(c) {
		if (c.charCodeAt(0) === Token.EOF) {
			return "<EOF>";
		} else if (c === '\n') {
			return "\\n";
		} else if (c === '\t') {
			return "\\t";
		} else if (c === '\r') {
			return "\\r";
		} else {
			return c;
		}
	}

	getCharErrorDisplay(c) {
		return "'" + this.getErrorDisplayForChar(c) + "'";
	}

	/**
	 * Lexers can normally match any char in it's vocabulary after matching
	 * a token, so do the easy thing and just kill a character and hope
	 * it all works out. You can instead use the rule invocation stack
	 * to do sophisticated error recovery if you are in a fragment rule.
	 */
	recover(re) {
		if (this._input.LA(1) !== Token.EOF) {
			if (re instanceof LexerNoViableAltException) {
				// skip a char and try again
				this._interp.consume(this._input);
			} else {
				// TODO: Do we lose character or line position information?
				this._input.consume();
			}
		}
	}

	get inputStream(){
		return this._input;
	}

	set inputStream(input) {
		this._input = null;
		this._tokenFactorySourcePair = [ this, this._input ];
		this.reset();
		this._input = input;
		this._tokenFactorySourcePair = [ this, this._input ];
	}

	get sourceName(){
		return this._input.sourceName;
	}

	get type(){
		return this.type;
	}

	set type(type) {
		this._type = type;
	}

	get line(){
		return this._interp.line;
	}

	set line(line) {
		this._interp.line = line;
	}

	get column(){
		return this._interp.column;
	}

	set column(column) {
		this._interp.column = column;
	}

	get text(){
		if (this._text !== null) {
			return this._text;
		} else {
			return this._interp.getText(this._input);
		}
	}

	set text(text) {
		this._text = text;
	}
}

Lexer.DEFAULT_MODE = 0;
Lexer.MORE = -2;
Lexer.SKIP = -3;

Lexer.DEFAULT_TOKEN_CHANNEL = Token.DEFAULT_CHANNEL;
Lexer.HIDDEN = Token.HIDDEN_CHANNEL;
Lexer.MIN_CHAR_VALUE = 0x0000;
Lexer.MAX_CHAR_VALUE = 0x10FFFF;

// Set the char stream and reset the lexer

module.exports = Lexer;
<commit_msg>Fix stack overflow exception when using Lexer.type in JavaScript fixes #3328<commit_after>/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

const {Token} = require('./Token');
const Recognizer = require('./Recognizer');
const CommonTokenFactory = require('./CommonTokenFactory');
const {RecognitionException} = require('./error/Errors');
const {LexerNoViableAltException} = require('./error/Errors');

class TokenSource {}

/**
 * A lexer is recognizer that draws input symbols from a character stream.
 * lexer grammars result in a subclass of this object. A Lexer object
 * uses simplified match() and error recovery mechanisms in the interest of speed.
 */
class Lexer extends Recognizer {
	constructor(input) {
		super();
		this._input = input;
		this._factory = CommonTokenFactory.DEFAULT;
		this._tokenFactorySourcePair = [ this, input ];

		this._interp = null; // child classes must populate this

		/**
		 * The goal of all lexer rules/methods is to create a token object.
		 * this is an instance variable as multiple rules may collaborate to
		 * create a single token. nextToken will return this object after
		 * matching lexer rule(s). If you subclass to allow multiple token
		 * emissions, then set this to the last token to be matched or
		 * something nonnull so that the auto token emit mechanism will not
		 * emit another token.
		 */
		this._token = null;

		/**
		 * What character index in the stream did the current token start at?
		 * Needed, for example, to get the text for current token. Set at
		 * the start of nextToken.
		 */
		this._tokenStartCharIndex = -1;

		// The line on which the first character of the token resides///
		this._tokenStartLine = -1;

		// The character position of first character within the line///
		this._tokenStartColumn = -1;

		// Once we see EOF on char stream, next token will be EOF.
		// If you have DONE : EOF ; then you see DONE EOF.
		this._hitEOF = false;

		// The channel number for the current token///
		this._channel = Token.DEFAULT_CHANNEL;

		// The token type for the current token///
		this._type = Token.INVALID_TYPE;

		this._modeStack = [];
		this._mode = Lexer.DEFAULT_MODE;

		/**
		 * You can set the text for the current token to override what is in
		 * the input char buffer. Use setText() or can set this instance var.
		 */
		this._text = null;
	}

	reset() {
		// wack Lexer state variables
		if (this._input !== null) {
			this._input.seek(0); // rewind the input
		}
		this._token = null;
		this._type = Token.INVALID_TYPE;
		this._channel = Token.DEFAULT_CHANNEL;
		this._tokenStartCharIndex = -1;
		this._tokenStartColumn = -1;
		this._tokenStartLine = -1;
		this._text = null;

		this._hitEOF = false;
		this._mode = Lexer.DEFAULT_MODE;
		this._modeStack = [];

		this._interp.reset();
	}

// Return a token from this source; i.e., match a token on the char stream.
	nextToken() {
		if (this._input === null) {
			throw "nextToken requires a non-null input stream.";
		}

		/**
		 * Mark start location in char stream so unbuffered streams are
		 * guaranteed at least have text of current token
		 */
		const tokenStartMarker = this._input.mark();
		try {
			while (true) {
				if (this._hitEOF) {
					this.emitEOF();
					return this._token;
				}
				this._token = null;
				this._channel = Token.DEFAULT_CHANNEL;
				this._tokenStartCharIndex = this._input.index;
				this._tokenStartColumn = this._interp.column;
				this._tokenStartLine = this._interp.line;
				this._text = null;
				let continueOuter = false;
				while (true) {
					this._type = Token.INVALID_TYPE;
					let ttype = Lexer.SKIP;
					try {
						ttype = this._interp.match(this._input, this._mode);
					} catch (e) {
						if(e instanceof RecognitionException) {
							this.notifyListeners(e); // report error
							this.recover(e);
						} else {
							console.log(e.stack);
							throw e;
						}
					}
					if (this._input.LA(1) === Token.EOF) {
						this._hitEOF = true;
					}
					if (this._type === Token.INVALID_TYPE) {
						this._type = ttype;
					}
					if (this._type === Lexer.SKIP) {
						continueOuter = true;
						break;
					}
					if (this._type !== Lexer.MORE) {
						break;
					}
				}
				if (continueOuter) {
					continue;
				}
				if (this._token === null) {
					this.emit();
				}
				return this._token;
			}
		} finally {
			// make sure we release marker after match or
			// unbuffered char stream will keep buffering
			this._input.release(tokenStartMarker);
		}
	}

	/**
	 * Instruct the lexer to skip creating a token for current lexer rule
	 * and look for another token. nextToken() knows to keep looking when
	 * a lexer rule finishes with token set to SKIP_TOKEN. Recall that
	 * if token==null at end of any token rule, it creates one for you
	 * and emits it.
	 */
	skip() {
		this._type = Lexer.SKIP;
	}

	more() {
		this._type = Lexer.MORE;
	}

	mode(m) {
		this._mode = m;
	}

	pushMode(m) {
		if (this._interp.debug) {
			console.log("pushMode " + m);
		}
		this._modeStack.push(this._mode);
		this.mode(m);
	}

	popMode() {
		if (this._modeStack.length === 0) {
			throw "Empty Stack";
		}
		if (this._interp.debug) {
			console.log("popMode back to " + this._modeStack.slice(0, -1));
		}
		this.mode(this._modeStack.pop());
		return this._mode;
	}

	/**
	 * By default does not support multiple emits per nextToken invocation
	 * for efficiency reasons. Subclass and override this method, nextToken,
	 * and getToken (to push tokens into a list and pull from that list
	 * rather than a single variable as this implementation does).
	 */
	emitToken(token) {
		this._token = token;
	}

	/**
	 * The standard method called to automatically emit a token at the
	 * outermost lexical rule. The token object should point into the
	 * char buffer start..stop. If there is a text override in 'text',
	 * use that to set the token's text. Override this method to emit
	 * custom Token objects or provide a new factory.
	 */
	emit() {
		const t = this._factory.create(this._tokenFactorySourcePair, this._type,
				this._text, this._channel, this._tokenStartCharIndex, this
						.getCharIndex() - 1, this._tokenStartLine,
				this._tokenStartColumn);
		this.emitToken(t);
		return t;
	}

	emitEOF() {
		const cpos = this.column;
		const lpos = this.line;
		const eof = this._factory.create(this._tokenFactorySourcePair, Token.EOF,
				null, Token.DEFAULT_CHANNEL, this._input.index,
				this._input.index - 1, lpos, cpos);
		this.emitToken(eof);
		return eof;
	}

// What is the index of the current character of lookahead?///
	getCharIndex() {
		return this._input.index;
	}

	/**
	 * Return a list of all Token objects in input char stream.
	 * Forces load of all tokens. Does not include EOF token.
	 */
	getAllTokens() {
		const tokens = [];
		let t = this.nextToken();
		while (t.type !== Token.EOF) {
			tokens.push(t);
			t = this.nextToken();
		}
		return tokens;
	}

	notifyListeners(e) {
		const start = this._tokenStartCharIndex;
		const stop = this._input.index;
		const text = this._input.getText(start, stop);
		const msg = "token recognition error at: '" + this.getErrorDisplay(text) + "'";
		const listener = this.getErrorListenerDispatch();
		listener.syntaxError(this, null, this._tokenStartLine,
				this._tokenStartColumn, msg, e);
	}

	getErrorDisplay(s) {
		const d = [];
		for (let i = 0; i < s.length; i++) {
			d.push(s[i]);
		}
		return d.join('');
	}

	getErrorDisplayForChar(c) {
		if (c.charCodeAt(0) === Token.EOF) {
			return "<EOF>";
		} else if (c === '\n') {
			return "\\n";
		} else if (c === '\t') {
			return "\\t";
		} else if (c === '\r') {
			return "\\r";
		} else {
			return c;
		}
	}

	getCharErrorDisplay(c) {
		return "'" + this.getErrorDisplayForChar(c) + "'";
	}

	/**
	 * Lexers can normally match any char in it's vocabulary after matching
	 * a token, so do the easy thing and just kill a character and hope
	 * it all works out. You can instead use the rule invocation stack
	 * to do sophisticated error recovery if you are in a fragment rule.
	 */
	recover(re) {
		if (this._input.LA(1) !== Token.EOF) {
			if (re instanceof LexerNoViableAltException) {
				// skip a char and try again
				this._interp.consume(this._input);
			} else {
				// TODO: Do we lose character or line position information?
				this._input.consume();
			}
		}
	}

	get inputStream(){
		return this._input;
	}

	set inputStream(input) {
		this._input = null;
		this._tokenFactorySourcePair = [ this, this._input ];
		this.reset();
		this._input = input;
		this._tokenFactorySourcePair = [ this, this._input ];
	}

	get sourceName(){
		return this._input.sourceName;
	}

	get type(){
		return this._type;
	}

	set type(type) {
		this._type = type;
	}

	get line(){
		return this._interp.line;
	}

	set line(line) {
		this._interp.line = line;
	}

	get column(){
		return this._interp.column;
	}

	set column(column) {
		this._interp.column = column;
	}

	get text(){
		if (this._text !== null) {
			return this._text;
		} else {
			return this._interp.getText(this._input);
		}
	}

	set text(text) {
		this._text = text;
	}
}

Lexer.DEFAULT_MODE = 0;
Lexer.MORE = -2;
Lexer.SKIP = -3;

Lexer.DEFAULT_TOKEN_CHANNEL = Token.DEFAULT_CHANNEL;
Lexer.HIDDEN = Token.HIDDEN_CHANNEL;
Lexer.MIN_CHAR_VALUE = 0x0000;
Lexer.MAX_CHAR_VALUE = 0x10FFFF;

// Set the char stream and reset the lexer

module.exports = Lexer;
<|endoftext|>


<commit_before>export default () => {
    document.addEventListener('keydown', e => {
        const keyCode = e.which;
        const header = e.target.closest('.sc-navigation-v2');
        if (!header) {
            return;
        }
        if(keyCode === 9) {
            header.classList.add('sc-focus-visible-only');
        } else if(keyCode === 27) {
            e.target.closest('.sc-navigation-v2  nav li.open').classList.remove('open');
        }
    });

    document.addEventListener('click', e => {
        const header = e.target.closest('.sc-navigation-v2');

        if(!header) {
            return;
        }

        const menuOpener = e.target.closest('.sc-navigation-v2 nav li');
        if (menuOpener) {
            toggleSubmenu(menuOpener);
            return;
        }

        const menuItemOpener = e.target.closest('.sc-navigation-v2 .sc-btn-mobile-menu');
        if (menuItemOpener) {
            toggleMenu(header);
            return;
        }
    });

    const toggleMenu = (header) => {
        header.classList.toggle('open');
    };

    const toggleSubmenu = (menu) => {
        const activeMenu = document.querySelector('.sc-navigation-v2 nav li.open');
        if (activeMenu) {
            activeMenu.classList.remove('open');
        }
        if (activeMenu !== menu) {
            menu.classList.toggle('open');
        }
    };
};
<commit_msg>brought back expanded-aria labels<commit_after>export default () => {
    document.addEventListener('keydown', e => {
        const keyCode = e.which;
        const header = e.target.closest('.sc-navigation-v2');
        if (!header) {
            return;
        }
        if(keyCode === 9) {
            // TAB
            header.classList.add('sc-focus-visible-only');
        } else if(keyCode === 27) {
            // ESCAPE
            e.target.closest('.sc-navigation-v2 nav li.open').classList.remove('open');
        }
    });

    document.addEventListener('click', e => {
        const header = e.target.closest('.sc-navigation-v2');
        console.log('header?', e.target);

        // 1. click outside header closes all the menus
        // 2. click hamburger button opens the main menu
        // 3. click on submenu opens/closes the submenu
        // 4. click on header outside submenus/hamburger button closes all the menus
        // 5. click on a link inside of submenu closes this submenu
        // 6*. click anywhere in the header not listed above -> no actions

        // 1
        if(!header) {
            closeAllOpenedSubmenus();
            return;
        }

        // 2
        const mobileButton = e.target.closest('.sc-navigation-v2 .sc-btn-mobile-menu');
        if (mobileButton) {
            toggleMenu(header, mobileButton);
            return;
        }

        // 3
        const menuOpener = e.target.closest('.sc-navigation-v2 nav li');
        const menuButton = e.target.closest('.sc-navigation-v2 nav li button');
        if (menuOpener && menuButton) {
            toggleSubmenu(menuOpener, menuButton);
            return;
        }

        // 4
        const openedLi = e.target.closest('.sc-navigation-v2 nav li.open');
        if (!openedLi) {
            closeAllOpenedSubmenus();
            return;
        }

        // 5
        const anyLink = e.target.closest('.sc-navigation-v2 nav a');
        if (anyLink) {
            closeAllOpenedSubmenus();
            return;
        }

    });

    const toggleSubmenu = (opener, button) => {
        const activeMenu = document.querySelector('.sc-navigation-v2 nav li.open');
        if (activeMenu) {
            closeMenu(activeMenu);
        }
        if (activeMenu !== opener) {
            button.setAttribute('aria-expanded', true);
            opener.classList.toggle('open');
        }
    };

    const toggleMenu = (header, menuItemOpener) => {
        menuItemOpener.setAttribute('aria-expanded', header.classList.contains('open'));
        header.classList.toggle('open');
    };

    const closeMenu = (menu) => {
        menu.querySelector('button').setAttribute('aria-expanded', false);
        menu.classList.remove('open');
    };

    const closeAllOpenedSubmenus = () => {
        [...document.querySelectorAll('.sc-navigation-v2 nav li.open')].forEach(openedMenu => closeMenu(openedMenu));
    };
};
<|endoftext|>