<commit_before>/*jslint bitwise: true*/
define(['jquery'], function($) {
    'use strict';
    function WebGlSpiral() {
        this.unboundDraw = $.proxy(this.draw, this);
        window.requestAnimationFrame = Modernizr.prefixed('requestAnimationFrame', window) || function(proc) { window.setTimeout(proc, 1000 / 30); };

        if (!Modernizr.webgl) {
            throw 'webgl unsupported';
        }
        this.canvas = document.createElement('canvas');
        this.context = this.canvas.getContext('webgl') || this.canvas.getContext('experimental-webgl');
        if (!this.context) {
            throw 'webgl unsupported';
        }
        $(this.canvas).attr({id: 'web-gl-spiral'}).prependTo(document.body);

        var psh = this.context.createShader(this.context.FRAGMENT_SHADER);
        var vsh = this.context.createShader(this.context.VERTEX_SHADER);
        this.context.shaderSource(psh, '#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\nuniform vec4 color;varying vec2 ptexcoord;uniform sampler2D sampler;void main(void){gl_FragColor=color*texture2D(sampler,ptexcoord);}');
        this.context.shaderSource(vsh, 'attribute vec2 pos;attribute vec2 texcoord;uniform float rot;uniform vec2 scale;uniform vec2 aspect;varying vec2 ptexcoord;void main(void){vec2 scaled=scale*pos;float crot=cos(rot);float srot=sin(rot);gl_Position=vec4(aspect*vec2(scaled.x*crot-scaled.y*srot,scaled.x*srot+scaled.y*crot),0.0,1.0);ptexcoord=texcoord;}');
        this.context.compileShader(psh);
        this.context.compileShader(vsh);
        if (!this.context.getShaderParameter(psh, this.context.COMPILE_STATUS)) {
            console.log(this.context.getShaderInfoLog(psh));
            throw 'psh init failed';
        }
        if (!this.context.getShaderParameter(vsh, this.context.COMPILE_STATUS)) {
            console.log(this.context.getShaderInfoLog(vsh));
            throw 'vsh init failed';
        }
        this.shader = this.context.createProgram();
        this.context.attachShader(this.shader, vsh);
        this.context.attachShader(this.shader, psh);
        this.context.linkProgram(this.shader);
        if (!this.context.getProgramParameter(this.shader, this.context.LINK_STATUS)) {
            throw 'shader init failed';
        }
        this.context.useProgram(this.shader);
        this.shader.pos = this.context.getAttribLocation(this.shader, 'pos');
        this.context.enableVertexAttribArray(this.shader.pos);
        this.shader.texcoord = this.context.getAttribLocation(this.shader, 'texcoord');
        this.context.enableVertexAttribArray(this.shader.texcoord);
        this.shader.rot = this.context.getUniformLocation(this.shader, 'rot');
        this.shader.aspectScale = this.context.getUniformLocation(this.shader, 'aspect');
        this.shader.scale = this.context.getUniformLocation(this.shader, 'scale');
        this.shader.color = this.context.getUniformLocation(this.shader, 'color');
        this.shader.texture = this.context.getUniformLocation(this.shader, 'sampler');
        this.context.uniform2fv(this.shader.aspectScale, this.aspectScale);

        this.quad = this.context.createBuffer();
        this.context.bindBuffer(this.context.ARRAY_BUFFER, this.quad);
        this.context.bufferData(this.context.ARRAY_BUFFER, new Float32Array([
            1.0, 1.0,
            -1.0, 1.0,
            1.0, -1.0,
            -1.0, -1.0
        ]), this.context.STATIC_DRAW);
        this.context.vertexAttribPointer(this.shader.pos, 2, this.context.FLOAT, false, 0, 0);

        this.quadtex = this.context.createBuffer();
        this.context.bindBuffer(this.context.ARRAY_BUFFER, this.quadtex);
        this.context.bufferData(this.context.ARRAY_BUFFER, new Float32Array([
            1.0, 0.0,
            0.0, 0.0,
            1.0, 1.0,
            0.0, 1.0
        ]), this.context.STATIC_DRAW);
        this.context.vertexAttribPointer(this.shader.texcoord, 2, this.context.FLOAT, false, 0, 0);

        this.context.blendFunc(this.context.SRC_ALPHA, this.context.ONE_MINUS_SRC_ALPHA);
        this.context.enable(this.context.BLEND);

        this.setBackground([0, 0, 0]);

        this.spiralTexture = this.context.createTexture();
        this.imageTexture = this.context.createTexture();
        this.setSpiralImage(this.blankImageData);
        this.clearImage();

        $(window).resize({spiral: this}, function(event) { event.data.spiral.resize($(window).width(), $(window).height()); });
        this.resize($(window).width(), $(window).height());
        this.draw();
    }
    WebGlSpiral.prototype = {
        canvas: null,
        context: null,
        shader: null,
        spiralScale: [0.95, 0.95],
        imageScale: [0.95, 0.95],
        aspectScale: [0.5, 1.0],
        spiralColor: [1.0, 1.0, 1.0, 1.0],
        imageColor: [1.0, 1.0, 1.0, 1.0],
        spiralTexture: null,
        imageTexture: null,
        unboundDraw: null,
        baseTime: 0,
        baseRot: 0,
        rotPeriod: 10000,
        blankImageData: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQIHWNgYAAAAAMAAU9ICq8AAAAASUVORK5CYII=',
        draw: function() {
            window.requestAnimationFrame(this.unboundDraw);
            var context = this.context, canvas = this.canvas, shader = this.shader;

            context.viewport(0, 0, canvas.width, canvas.height);

            context.clear(context.COLOR_BUFFER_BIT);

            context.uniform2fv(shader.scale, this.imageScale);
            context.uniform1f(shader.rot, 0.0);
            context.uniform4fv(shader.color, this.imageColor);
            context.uniform1i(shader.texture, 1);
            context.drawArrays(context.TRIANGLE_STRIP, 0, 4);

            context.uniform2fv(shader.scale, this.spiralScale);
            context.uniform1f(shader.rot, this.baseRot + -2.0 * Math.PI * (($.now() - this.baseTime) % this.rotPeriod) / this.rotPeriod);
            context.uniform4fv(shader.color, this.spiralColor);
            context.uniform1i(shader.texture, 0);
            context.drawArrays(context.TRIANGLE_STRIP, 0, 4);
        },
        resize: function(w, h) {
            this.canvas.width = w;
            this.canvas.height = h;
            if (w > h) {
                this.aspectScale = [h / w, 1.0];
            } else {
                this.aspectScale = [1.0, w / h];
            }
            this.context.uniform2fv(this.shader.aspectScale, this.aspectScale);
        },
        loadTexture: function(texture, num, src) {
            var img = new Image();
            var context = this.context;
            $(img).load(function() {
                var bits = 0;
                // check for power of two
                for (var i = 0; i < 32; i++) {
                    bits += 1 & (img.width >> i);
                }
                if (img.width !== img.height || bits !== 1) {
                    var width = img.width;
                    var height = img.height;
                    var maxImg = Math.max(img.width, img.height);
                    var target = maxImg;
                    // convert to power of 2
                    for (i = 1; i < target; i = i << 1) {}
                    target = i;
                    // clamp
                    target = Math.min(target, context.getParameter(context.MAX_TEXTURE_SIZE));
                    width *= target / maxImg;
                    height *= target / maxImg;
                    var x = 0;
                    var y = 0;
                    if (width > height) {
                        y = (width - height) * 0.5;
                    } else {
                        x = (height - width) * 0.5;
                    }
                    console.log({x: x, y: y, width: width, height: height});
                    var canvas = document.createElement('canvas');
                    canvas.width = canvas.height = target;
                    var context2d = canvas.getContext('2d');
                    context2d.drawImage(img, x, y, width, height);
                    img = canvas;
                }
                context.activeTexture(num);
                context.bindTexture(context.TEXTURE_2D, texture);
                context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, context.RGBA, context.UNSIGNED_BYTE, img);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MAG_FILTER, context.LINEAR);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.LINEAR_MIPMAP_NEAREST);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_S, context.CLAMP_TO_EDGE);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_T, context.CLAMP_TO_EDGE);
                context.generateMipmap(context.TEXTURE_2D);
            });
            $(img).error({gls: this}, function(event) {
                event.data.gls.loadTexture(texture, num, event.data.gls.blankImageData);
            });
            img.src = src;
        },
        setBackground: function(r, g, b) {
            this.context.clearColor(r, g, b, 1.0);
        },
        setSpiralImage: function(img) {
            this.loadTexture(this.spiralTexture, this.context.TEXTURE0, img);
        },
        setImage: function(img) {
            this.loadTexture(this.imageTexture, this.context.TEXTURE1, img);
        },
        setSpiralColor: function(r, g, b) {
            this.spiralColor[0] = r;
            this.spiralColor[1] = g;
            this.spiralColor[2] = b;
        },
        setSpiralAlpha: function(a) {
            this.spiralColor[3] = a;
        },
        setImageColor: function(r, g, b) {
            this.imageColor[0] = r;
            this.imageColor[1] = g;
            this.imageColor[2] = b;
        },
        setImageAlpha: function(a) {
            this.imageColor[3] = a;
        },
        setSpiralScale: function(x, y) {
            this.imageScale[0] = x;
            this.imageScale[1] = y;
        },
        setImageScale: function(x, y) {
            this.imageScale[0] = x;
            this.imageScale[1] = y;
        },
        setRotationPeriod: function(wl) {
            var time = $.now();
            this.baseRot += -2.0 * Math.PI * ((time - this.baseTime) % this.rotPeriod) / this.rotPeriod;
            this.baseTime = time;
            while (this.baseRot < 0.0) {
                this.baseRot += 2.0 * Math.PI;
            }
            while (this.baseRot >= 2.0 * Math.PI) {
                this.baseRot -= 2.0 * Math.PI;
            }
            this.rotPeriod = wl * 1000;
        },
        clearImage: function() {
            this.setImage(this.blankImageData);
        }
    };
    return WebGlSpiral;
});
<commit_msg>render spiral correctly when dip != px<commit_after>/*jslint bitwise: true*/
define(['jquery'], function($) {
    'use strict';
    function WebGlSpiral() {
        this.unboundDraw = $.proxy(this.draw, this);
        window.requestAnimationFrame = Modernizr.prefixed('requestAnimationFrame', window) || function(proc) { window.setTimeout(proc, 1000 / 30); };

        if (!Modernizr.webgl) {
            throw 'webgl unsupported';
        }
        this.canvas = document.createElement('canvas');
        this.context = this.canvas.getContext('webgl') || this.canvas.getContext('experimental-webgl');
        if (!this.context) {
            throw 'webgl unsupported';
        }
        $(this.canvas).attr({id: 'web-gl-spiral'}).prependTo(document.body);

        var psh = this.context.createShader(this.context.FRAGMENT_SHADER);
        var vsh = this.context.createShader(this.context.VERTEX_SHADER);
        this.context.shaderSource(psh, '#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\nuniform vec4 color;varying vec2 ptexcoord;uniform sampler2D sampler;void main(void){gl_FragColor=color*texture2D(sampler,ptexcoord);}');
        this.context.shaderSource(vsh, 'attribute vec2 pos;attribute vec2 texcoord;uniform float rot;uniform vec2 scale;uniform vec2 aspect;varying vec2 ptexcoord;void main(void){vec2 scaled=scale*pos;float crot=cos(rot);float srot=sin(rot);gl_Position=vec4(aspect*vec2(scaled.x*crot-scaled.y*srot,scaled.x*srot+scaled.y*crot),0.0,1.0);ptexcoord=texcoord;}');
        this.context.compileShader(psh);
        this.context.compileShader(vsh);
        if (!this.context.getShaderParameter(psh, this.context.COMPILE_STATUS)) {
            console.log(this.context.getShaderInfoLog(psh));
            throw 'psh init failed';
        }
        if (!this.context.getShaderParameter(vsh, this.context.COMPILE_STATUS)) {
            console.log(this.context.getShaderInfoLog(vsh));
            throw 'vsh init failed';
        }
        this.shader = this.context.createProgram();
        this.context.attachShader(this.shader, vsh);
        this.context.attachShader(this.shader, psh);
        this.context.linkProgram(this.shader);
        if (!this.context.getProgramParameter(this.shader, this.context.LINK_STATUS)) {
            throw 'shader init failed';
        }
        this.context.useProgram(this.shader);
        this.shader.pos = this.context.getAttribLocation(this.shader, 'pos');
        this.context.enableVertexAttribArray(this.shader.pos);
        this.shader.texcoord = this.context.getAttribLocation(this.shader, 'texcoord');
        this.context.enableVertexAttribArray(this.shader.texcoord);
        this.shader.rot = this.context.getUniformLocation(this.shader, 'rot');
        this.shader.aspectScale = this.context.getUniformLocation(this.shader, 'aspect');
        this.shader.scale = this.context.getUniformLocation(this.shader, 'scale');
        this.shader.color = this.context.getUniformLocation(this.shader, 'color');
        this.shader.texture = this.context.getUniformLocation(this.shader, 'sampler');
        this.context.uniform2fv(this.shader.aspectScale, this.aspectScale);

        this.quad = this.context.createBuffer();
        this.context.bindBuffer(this.context.ARRAY_BUFFER, this.quad);
        this.context.bufferData(this.context.ARRAY_BUFFER, new Float32Array([
            1.0, 1.0,
            -1.0, 1.0,
            1.0, -1.0,
            -1.0, -1.0
        ]), this.context.STATIC_DRAW);
        this.context.vertexAttribPointer(this.shader.pos, 2, this.context.FLOAT, false, 0, 0);

        this.quadtex = this.context.createBuffer();
        this.context.bindBuffer(this.context.ARRAY_BUFFER, this.quadtex);
        this.context.bufferData(this.context.ARRAY_BUFFER, new Float32Array([
            1.0, 0.0,
            0.0, 0.0,
            1.0, 1.0,
            0.0, 1.0
        ]), this.context.STATIC_DRAW);
        this.context.vertexAttribPointer(this.shader.texcoord, 2, this.context.FLOAT, false, 0, 0);

        this.context.blendFunc(this.context.SRC_ALPHA, this.context.ONE_MINUS_SRC_ALPHA);
        this.context.enable(this.context.BLEND);

        this.setBackground([0, 0, 0]);

        this.spiralTexture = this.context.createTexture();
        this.imageTexture = this.context.createTexture();
        this.setSpiralImage(this.blankImageData);
        this.clearImage();

        $(window).resize({spiral: this}, function(event) { event.data.spiral.resize($(window).width(), $(window).height()); });
        this.resize($(window).width(), $(window).height());
        this.draw();
    }
    WebGlSpiral.prototype = {
        canvas: null,
        context: null,
        shader: null,
        spiralScale: [0.95, 0.95],
        imageScale: [0.95, 0.95],
        aspectScale: [0.5, 1.0],
        spiralColor: [1.0, 1.0, 1.0, 1.0],
        imageColor: [1.0, 1.0, 1.0, 1.0],
        spiralTexture: null,
        imageTexture: null,
        unboundDraw: null,
        baseTime: 0,
        baseRot: 0,
        rotPeriod: 10000,
        blankImageData: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQIHWNgYAAAAAMAAU9ICq8AAAAASUVORK5CYII=',
        draw: function() {
            window.requestAnimationFrame(this.unboundDraw);
            var context = this.context, canvas = this.canvas, shader = this.shader;

            context.viewport(0, 0, canvas.width, canvas.height);

            context.clear(context.COLOR_BUFFER_BIT);

            context.uniform2fv(shader.scale, this.imageScale);
            context.uniform1f(shader.rot, 0.0);
            context.uniform4fv(shader.color, this.imageColor);
            context.uniform1i(shader.texture, 1);
            context.drawArrays(context.TRIANGLE_STRIP, 0, 4);

            context.uniform2fv(shader.scale, this.spiralScale);
            context.uniform1f(shader.rot, this.baseRot + -2.0 * Math.PI * (($.now() - this.baseTime) % this.rotPeriod) / this.rotPeriod);
            context.uniform4fv(shader.color, this.spiralColor);
            context.uniform1i(shader.texture, 0);
            context.drawArrays(context.TRIANGLE_STRIP, 0, 4);
        },
        resize: function(w, h) {
            var multiplier = window.devicePixelRatio || 1.0;
            this.canvas.width = w * multiplier;
            this.canvas.height = h * multiplier;
            this.canvas.style.width = w + 'px';
            this.canvas.style.height = h + 'px';
            if (w > h) {
                this.aspectScale = [h / w, 1.0];
            } else {
                this.aspectScale = [1.0, w / h];
            }
            this.context.uniform2fv(this.shader.aspectScale, this.aspectScale);
        },
        loadTexture: function(texture, num, src) {
            var img = new Image();
            var context = this.context;
            $(img).load(function() {
                var bits = 0;
                // check for power of two
                for (var i = 0; i < 32; i++) {
                    bits += 1 & (img.width >> i);
                }
                if (img.width !== img.height || bits !== 1) {
                    var width = img.width;
                    var height = img.height;
                    var maxImg = Math.max(img.width, img.height);
                    var target = maxImg;
                    // convert to power of 2
                    for (i = 1; i < target; i = i << 1) {}
                    target = i;
                    // clamp
                    target = Math.min(target, context.getParameter(context.MAX_TEXTURE_SIZE));
                    width *= target / maxImg;
                    height *= target / maxImg;
                    var x = 0;
                    var y = 0;
                    if (width > height) {
                        y = (width - height) * 0.5;
                    } else {
                        x = (height - width) * 0.5;
                    }
                    console.log({x: x, y: y, width: width, height: height});
                    var canvas = document.createElement('canvas');
                    canvas.width = canvas.height = target;
                    var context2d = canvas.getContext('2d');
                    context2d.drawImage(img, x, y, width, height);
                    img = canvas;
                }
                context.activeTexture(num);
                context.bindTexture(context.TEXTURE_2D, texture);
                context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, context.RGBA, context.UNSIGNED_BYTE, img);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MAG_FILTER, context.LINEAR);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.LINEAR_MIPMAP_NEAREST);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_S, context.CLAMP_TO_EDGE);
                context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_T, context.CLAMP_TO_EDGE);
                context.generateMipmap(context.TEXTURE_2D);
            });
            $(img).error({gls: this}, function(event) {
                event.data.gls.loadTexture(texture, num, event.data.gls.blankImageData);
            });
            img.src = src;
        },
        setBackground: function(r, g, b) {
            this.context.clearColor(r, g, b, 1.0);
        },
        setSpiralImage: function(img) {
            this.loadTexture(this.spiralTexture, this.context.TEXTURE0, img);
        },
        setImage: function(img) {
            this.loadTexture(this.imageTexture, this.context.TEXTURE1, img);
        },
        setSpiralColor: function(r, g, b) {
            this.spiralColor[0] = r;
            this.spiralColor[1] = g;
            this.spiralColor[2] = b;
        },
        setSpiralAlpha: function(a) {
            this.spiralColor[3] = a;
        },
        setImageColor: function(r, g, b) {
            this.imageColor[0] = r;
            this.imageColor[1] = g;
            this.imageColor[2] = b;
        },
        setImageAlpha: function(a) {
            this.imageColor[3] = a;
        },
        setSpiralScale: function(x, y) {
            this.imageScale[0] = x;
            this.imageScale[1] = y;
        },
        setImageScale: function(x, y) {
            this.imageScale[0] = x;
            this.imageScale[1] = y;
        },
        setRotationPeriod: function(wl) {
            var time = $.now();
            this.baseRot += -2.0 * Math.PI * ((time - this.baseTime) % this.rotPeriod) / this.rotPeriod;
            this.baseTime = time;
            while (this.baseRot < 0.0) {
                this.baseRot += 2.0 * Math.PI;
            }
            while (this.baseRot >= 2.0 * Math.PI) {
                this.baseRot -= 2.0 * Math.PI;
            }
            this.rotPeriod = wl * 1000;
        },
        clearImage: function() {
            this.setImage(this.blankImageData);
        }
    };
    return WebGlSpiral;
});
<|endoftext|>


<commit_before>// Copyright 2017-2018, University of Colorado Boulder

/*
 * IMPORTANT: This file was auto-generated by "grunt generate-config". Please do not modify this directly. Instead
 * please modify phet-core/package.json to control dependencies.
 *
 * RequireJS configuration file for the phet-core sim.
 * Paths are relative to the location of this file.
 */

require.config( {

  deps: [ 'phet-core-tests' ],

  paths: {

    // Third-party libs
    text: '../../sherpa/lib/text-2.0.12',

    // PhET plugins
    audio: '../../chipper/js/requirejs-plugins/audio',
    image: '../../chipper/js/requirejs-plugins/image',
    mipmap: '../../chipper/js/requirejs-plugins/mipmap',
    string: '../../chipper/js/requirejs-plugins/string',
    ifphetio: '../../chipper/js/requirejs-plugins/ifphetio',

    // PhET libs, uppercase names to identify them in require.js imports.
    // IMPORTANT: DO NOT modify. This file is auto-generated. See documentation at the top.
    AXON: '../../axon/js',
    BRAND: '../../brand/' + phet.chipper.brand + '/js',
    DOT: '../../dot/js',
    JOIST: '../../joist/js',
    KITE: '../../kite/js',
    PHETCOMMON: '../../phetcommon/js',
    PHET_CORE: '.',
    PHET_IO: '../../phet-io/js',
    REPOSITORY: '..',
    SCENERY: '../../scenery/js',
    SCENERY_PHET: '../../scenery-phet/js',
    SUN: '../../sun/js',
    TAMBO: '../../tambo/js',
    TANDEM: '../../tandem/js'
  },

  // optional cache buster to make browser refresh load all included scripts, can be disabled with ?cacheBuster=false
  urlArgs: phet.chipper.getCacheBusterArgs()
} );
<commit_msg>renamed "audio" plugin to "sound"<commit_after>// Copyright 2017-2018, University of Colorado Boulder

/*
 * IMPORTANT: This file was auto-generated by "grunt generate-config". Please do not modify this directly. Instead
 * please modify phet-core/package.json to control dependencies.
 *
 * RequireJS configuration file for the phet-core sim.
 * Paths are relative to the location of this file.
 */

require.config( {

  deps: [ 'phet-core-tests' ],

  paths: {

    // Third-party libs
    text: '../../sherpa/lib/text-2.0.12',

    // PhET plugins
    sound: '../../chipper/js/requirejs-plugins/sound',
    image: '../../chipper/js/requirejs-plugins/image',
    mipmap: '../../chipper/js/requirejs-plugins/mipmap',
    string: '../../chipper/js/requirejs-plugins/string',
    ifphetio: '../../chipper/js/requirejs-plugins/ifphetio',

    // PhET libs, uppercase names to identify them in require.js imports.
    // IMPORTANT: DO NOT modify. This file is auto-generated. See documentation at the top.
    AXON: '../../axon/js',
    BRAND: '../../brand/' + phet.chipper.brand + '/js',
    DOT: '../../dot/js',
    JOIST: '../../joist/js',
    KITE: '../../kite/js',
    PHETCOMMON: '../../phetcommon/js',
    PHET_CORE: '.',
    PHET_IO: '../../phet-io/js',
    REPOSITORY: '..',
    SCENERY: '../../scenery/js',
    SCENERY_PHET: '../../scenery-phet/js',
    SUN: '../../sun/js',
    TAMBO: '../../tambo/js',
    TANDEM: '../../tandem/js'
  },

  // optional cache buster to make browser refresh load all included scripts, can be disabled with ?cacheBuster=false
  urlArgs: phet.chipper.getCacheBusterArgs()
} );
<|endoftext|>


<commit_before>
var lift = require('lift-result')
var browserModules = require('browser-builtins')
var browserResolve = require('browser-resolve')
var natives = process.binding('natives')
var toRegex = require('glob-to-regexp')
var resolve = require('resolve-module')
var detect = require('detect/series')
var reduce = require('reduce/series')
var filter = require('filter/async')
var lazy = require('lazy-property')
var fs = require('lift-result/fs')
var extend = require('extensible')
var own = Object.hasOwnProperty
var unique = require('unique')
var Result = require('result')
var map = require('map/async')
var mine = require('mine')
var path = require('path')
var unbox = Result.unbox
var when = Result.when
var join = path.join

var requires = lift(function(js){
  return mine(js).map(function(r){ return r.name })
})

function File(path, cache){
  this.cache = cache || {}
  this.id = path
}

File.extend = extend

var file = File.prototype

file.create = function(real, Class){
  var file = this.cache[real]
  if (!(file instanceof File)) {
    Class = Class || File
    file = new Class(real, this.cache)
    file.opts = this.opts
    this.cache[real] = file
  }
  return file
}

lazy(file, 'aliases', Array)

lazy(file, 'transforms', function(){
  var name = this.id
  var opts = this.opts
  return when(this.meta, function(meta){
    return when(meta.json, function(pkg){
      var transforms = pkg.transpile || []
      if (opts && Array.isArray(opts.transpile)) {
        transforms = transforms.concat(opts.transpile)
      }
      for (var i = 0, len = transforms.length; i < len;) {
        var glob = transforms[i++]
        var mods = transforms[i++]
        if (!match(glob, name)) continue
        if (!Array.isArray(mods)) mods = [mods]
        return mods.map(function(mod){
          if (typeof mod != 'string') return mod
          if (/^!sourcegraph\/(\w+->\w+)/.test(mod)) {
            return require(__dirname + '/transforms/' + RegExp.$1)
          }
          return require(resolve(name, mod))
        })
      }
      return []
    })
  }, function(){ return [] })
})

lazy(file, 'javascript', function(){
  var mods = this.transforms
  var path = this.id
  return when(this.source, function(src){
    return when(mods, function(mods){
      if (!mods) return src
      return reduce(mods, function(src, fn){
        return fn(src, path)
      }, src)
    })
  })
}, 'enumerable')

lazy(file, 'source', function(){
  return fs.readFile(this.id, 'utf8')
}, 'enumerable')

lazy(file, 'requires', function(){
  var req = when(requires(this.javascript), unique)
  if (this.opts && this.opts.env == 'node') {
    req = filter(req, function(name){
      return /^[.\/]/.test(name) || !(name in natives)
    }, this)
  }
  return req
}, 'enumerable')

lazy(file, 'dependencies', function(){
  var path = this.id

  if (this.opts && this.opts.env == 'node') {
    return map(this.requires, function(name){
      return resolve(path, name)
    })
  }

  var options = {
    filename: path,
    modules: browserModules,
    extensions: ['.js', '.json']
  }

  return map(this.requires, function(name){
    var result = new Result
    browserResolve(name, options, function(e, path){
      if (e) result.error(e)
      else result.write(path)
    })
    return result
  })
}, 'enumerable')

lazy(file, 'meta', function(){
  var self = this
  var files = parents(path.dirname(this.id)).map(function(dir){
    return join(dir, 'package.json')
  })
  var file = detect(files, function(file){
    return file in self.cache || isFile(file)
  })
  return file
    .then(fs.realpath, function(){
      throw new Error('couldn\'t find meta file for ' + self.id)
    })
    .then(function(real){
      return self.create(real, MetaFile)
    })
})

lazy(file, 'children', function(){
  var self = this
  return map(this.dependencies, function(path){
    if (path in self.cache) return self.cache[path]
    return self.cache[path] = fs.realpath(path).then(function(real){
      var file = self.create(real)
      // symlink
      if (real != path) {
        file.aliases.push(path)
        self.cache[path] = file
      }
      return file
    })
  })
})

file.toJSON = function(){
  var children = unbox(this.children)
  return {
    id: this.id,
    source: unbox(this.javascript),
    aliases: own.call(this, 'aliases') ? this.aliases : undefined,
    deps: unbox(this.requires).reduce(function(deps, name, i){
      deps[name] = children[i].id
      return deps
    }, {})
  }
}

var MetaFile = File.extend()

lazy(MetaFile.prototype, 'requires', function(){
  return when(this.json, function(pkg){
    var res = [pkg.main || './index']
    if (pkg.extras) res = res.concat(pkg.extras)
    return res.map(function(name){
      if (/^[^.\/]/.test(name)) return './' + name
      return name
    })
  })
})

lazy(MetaFile.prototype, 'json', function(){
  return when(this.source, JSON.parse)
})

lazy(MetaFile.prototype, 'javascript', function(){
  return when(this.source, function(src){
    return 'module.exports = ' + src
  })
})

function match(glob, file){
  return toRegex(glob).test(file)
}

function isFile(path){
  return fs.stat(path).then(function(stat){
    return stat.isFile()
  }, no)
}

function no(){ return false }

function parents(dir){
  var res = [dir]
  do res.push(dir = path.dirname(dir))
  while (dir != '/')
  return res
}

/**
 * expose File
 */

module.exports = exports = File
exports.Meta = MetaFile
<commit_msg>fix relative paths in transpile array<commit_after>
var lift = require('lift-result')
var browserModules = require('browser-builtins')
var browserResolve = require('browser-resolve')
var natives = process.binding('natives')
var toRegex = require('glob-to-regexp')
var resolve = require('resolve-module')
var detect = require('detect/series')
var reduce = require('reduce/series')
var filter = require('filter/async')
var lazy = require('lazy-property')
var fs = require('lift-result/fs')
var extend = require('extensible')
var own = Object.hasOwnProperty
var unique = require('unique')
var Result = require('result')
var map = require('map/async')
var mine = require('mine')
var path = require('path')
var unbox = Result.unbox
var when = Result.when
var join = path.join

var requires = lift(function(js){
  return mine(js).map(function(r){ return r.name })
})

function File(path, cache){
  this.cache = cache || {}
  this.id = path
}

File.extend = extend

var file = File.prototype

file.create = function(real, Class){
  var file = this.cache[real]
  if (!(file instanceof File)) {
    Class = Class || File
    file = new Class(real, this.cache)
    file.opts = this.opts
    this.cache[real] = file
  }
  return file
}

lazy(file, 'aliases', Array)

lazy(file, 'transforms', function(){
  var name = this.id
  var opts = this.opts
  return when(this.meta, function(meta){
    return when(meta.json, function(pkg){
      var transforms = pkg.transpile || []
      if (opts && Array.isArray(opts.transpile)) {
        transforms = transforms.concat(opts.transpile)
      }
      for (var i = 0, len = transforms.length; i < len;) {
        var glob = transforms[i++]
        var mods = transforms[i++]
        if (!match(glob, name)) continue
        if (!Array.isArray(mods)) mods = [mods]
        return mods.map(function(mod){
          if (typeof mod != 'string') return mod
          if (/^!sourcegraph\/(\w+->\w+)/.test(mod)) {
            return require(__dirname + '/transforms/' + RegExp.$1)
          }
          try {
            return require(resolve(meta.id, mod))
          } catch (e) {
            throw new Error('requiring ' + mod + ' from ' + meta.id)
          }
        })
      }
      return []
    })
  }, function(){ return [] })
})

lazy(file, 'javascript', function(){
  var mods = this.transforms
  var path = this.id
  return when(this.source, function(src){
    return when(mods, function(mods){
      if (!mods) return src
      return reduce(mods, function(src, fn){
        return fn(src, path)
      }, src)
    })
  })
}, 'enumerable')

lazy(file, 'source', function(){
  return fs.readFile(this.id, 'utf8')
}, 'enumerable')

lazy(file, 'requires', function(){
  var req = when(requires(this.javascript), unique)
  if (this.opts && this.opts.env == 'node') {
    req = filter(req, function(name){
      return /^[.\/]/.test(name) || !(name in natives)
    }, this)
  }
  return req
}, 'enumerable')

lazy(file, 'dependencies', function(){
  var path = this.id

  if (this.opts && this.opts.env == 'node') {
    return map(this.requires, function(name){
      return resolve(path, name)
    })
  }

  var options = {
    filename: path,
    modules: browserModules,
    extensions: ['.js', '.json']
  }

  return map(this.requires, function(name){
    var result = new Result
    browserResolve(name, options, function(e, path){
      if (e) result.error(e)
      else result.write(path)
    })
    return result
  })
}, 'enumerable')

lazy(file, 'meta', function(){
  var self = this
  var files = parents(path.dirname(this.id)).map(function(dir){
    return join(dir, 'package.json')
  })
  var file = detect(files, function(file){
    return file in self.cache || isFile(file)
  })
  return file
    .then(fs.realpath, function(){
      throw new Error('couldn\'t find meta file for ' + self.id)
    })
    .then(function(real){
      return self.create(real, MetaFile)
    })
})

lazy(file, 'children', function(){
  var self = this
  return map(this.dependencies, function(path){
    if (path in self.cache) return self.cache[path]
    return self.cache[path] = fs.realpath(path).then(function(real){
      var file = self.create(real)
      // symlink
      if (real != path) {
        file.aliases.push(path)
        self.cache[path] = file
      }
      return file
    })
  })
})

file.toJSON = function(){
  var children = unbox(this.children)
  return {
    id: this.id,
    source: unbox(this.javascript),
    aliases: own.call(this, 'aliases') ? this.aliases : undefined,
    deps: unbox(this.requires).reduce(function(deps, name, i){
      deps[name] = children[i].id
      return deps
    }, {})
  }
}

var MetaFile = File.extend()

lazy(MetaFile.prototype, 'requires', function(){
  return when(this.json, function(pkg){
    var res = [pkg.main || './index']
    if (pkg.extras) res = res.concat(pkg.extras)
    return res.map(function(name){
      if (/^[^.\/]/.test(name)) return './' + name
      return name
    })
  })
})

lazy(MetaFile.prototype, 'json', function(){
  return when(this.source, JSON.parse)
})

lazy(MetaFile.prototype, 'javascript', function(){
  return when(this.source, function(src){
    return 'module.exports = ' + src
  })
})

function match(glob, file){
  return toRegex(glob).test(file)
}

function isFile(path){
  return fs.stat(path).then(function(stat){
    return stat.isFile()
  }, no)
}

function no(){ return false }

function parents(dir){
  var res = [dir]
  do res.push(dir = path.dirname(dir))
  while (dir != '/')
  return res
}

/**
 * expose File
 */

module.exports = exports = File
exports.Meta = MetaFile
<|endoftext|>


<commit_before>(function(ShoppingCart) {

    ShoppingCart.processCheckoutFormSubmission = function processCheckoutFormSubmission() {
        var that = this;

        /********************************************************/
        /* Function called if I later can go on with the checkout
        /********************************************************/
        var _goOnWithCheckout = function _goOnWithCheckout() {

            var processRandomToken = function processRandomToken() {
                var randomToken = function randomToken(length) {
                    var upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                    var lower = 'abcdefghijklmnopqrstuvwxyz';
                    var number = '0123456789';
                    var token = '', i;
                    var seed = upper + lower + number;
                    length = length || 13;

                    for (i = 0; i < length; i++) {
                        token += seed[Math.floor(Math.random() * (seed.length - 1))];
                    }

                    return token;
                };

                storejs.set('grav-shoppingcart-order-token', { token: randomToken(10) });
            };

            var processShippingMethod = function processShippingMethod() {
                var shippingMethod = {
                    method: '',
                    cost: 0
                };

                if (ShoppingCart.settings.shipping.methods.length === 1) {
                    shippingMethod = {
                        method: ShoppingCart.settings.shipping.methods[0].name,
                        cost: ShoppingCart.settings.shipping.methods[0].price
                    };
                } else {
                    shippingMethod = {
                        method: jQuery('.js__shipping__method').val(),
                        cost: ShoppingCart.shippingPrice
                    };
                }

                //Store in localstorage
                storejs.set('grav-shoppingcart-shipping-method', shippingMethod);
            };

            var calculateTotalOrderPrice = function calculateTotalOrderPrice () {
                //Calculate the order price
                var orderPrice = ShoppingCart.totalOrderPriceIncludingTaxes;
                if (!orderPrice) {
                    orderPrice = 0;
                    var i = 0;
                    var cart = ShoppingCart.items;

                    while (i < cart.length) {
                        orderPrice += cart[i].product.price * cart[i].quantity;
                        i++;
                    }
                }

                //////////////////////////////////////////////////////////
                //Add shipping costs to the order price
                //////////////////////////////////////////////////////////
                ShoppingCart.generateShippingPrice();
                orderPrice = parseFloat(parseFloat(orderPrice) + parseFloat(ShoppingCart.shippingPrice)).toFixed(2);
                ShoppingCart.totalOrderPrice = orderPrice;
            };

            processRandomToken();
            processShippingMethod();
            calculateTotalOrderPrice ();

            jQuery(that).attr('disabled', 'disabled');
            jQuery(document).trigger('proceedToPayment', ShoppingCart);
        };

        var data = {};

        ShoppingCart.checkout_form_fields.forEach(function(checkout_form_field) {
            if (typeof checkout_form_field.name !== 'undefined') {
                data[checkout_form_field.name] = jQuery(checkout_form_field.classes).val();
            }
        });

        var customProcessingOfCheckoutForm = function customProcessingOfCheckoutForm() {
            if (data.country != 'US') {
                if (!data.province) {
                    alert(window.PLUGIN_SHOPPINGCART.translations.PLEASE_FILL_ALL_THE_REQUIRED_FIELDS);
                    return;
                }
            }
        };

        customProcessingOfCheckoutForm();

        ShoppingCart.checkout_form_data = data;
        storejs.set('grav-shoppingcart-checkout-form-data', data); //Store data info in cookie

        ShoppingCart.gateway = jQuery('.js__payment__method').val();

        _goOnWithCheckout();
    };

    /***********************************************************/
    /* Get the shipping options based on the settings
    /***********************************************************/
    ShoppingCart.populateShippingOptions = function populateShippingOptions() {
        var shippingMethods = [];
        for (index in ShoppingCart.settings.shipping.methods) {
            shippingMethods[index] = ShoppingCart.settings.shipping.methods[index];
        }

        var methodIsAllowedInCountry = function methodIsAllowedInCountry(method, country) {
            for (index in method.allowed_countries) {
                if (method.allowed_countries[index] == country) return true;
                if (method.allowed_countries[index] == '*') return true;
            }
            return false;
        };

        var ifIsGenericThereIsNoCountrySpecificMethod = function ifIsGenericThereIsNoCountrySpecificMethod(method, country) {
            return true;
        };

        var orderWeightIsAllowedForThisMethod = function orderWeightIsAllowedForThisMethod(method) {
            return true;
        };

        var orderPriceIsAllowedForThisMethod = function orderPriceIsAllowedForThisMethod(method) {
            return true;
        };

        if (jQuery('.js__billing__country').val() === 'US') {
            jQuery('.js__billing__state__control').show();
            jQuery('.js__billing__province__control').hide();
        } else {
            jQuery('.js__billing__state__control').hide();
            jQuery('.js__billing__province__control').show();
        }

        if (shippingMethods.length === 0) {
            jQuery('.checkout-choose-shipping-block').hide();
        } else if (shippingMethods.length === 1) {

            var priceBlock = shippingMethods[0].price + ' ' + ShoppingCart.getCurrentCurrencySymbol();
            if (ShoppingCart.settings.ui.currency_symbol_position === 'before') {
                priceBlock = ShoppingCart.getCurrentCurrencySymbol() + ' ' + shippingMethods[0].price;
            }

            jQuery('.checkout-choose-shipping-block .form-select-wrapper').html(shippingMethods[0].name + ' - ' + priceBlock);
            jQuery('.checkout-choose-shipping-block').show();
        } else {
            var select = document.getElementById('js__shipping__method');

            if (select) {
                //Calculate shipping methods for the shipping country
                select.options.length = 0;

                ShoppingCart.generateShippingPrice();

                for (index in shippingMethods) {
                    if (shippingMethods.hasOwnProperty(index)) {
                        method = shippingMethods[index];
                        if (methodIsAllowedInCountry(method, ShoppingCart.checkout_form_data.country) &&
                                ifIsGenericThereIsNoCountrySpecificMethod(method, ShoppingCart.checkout_form_data.country) &&
                                orderWeightIsAllowedForThisMethod(method) &&
                                orderPriceIsAllowedForThisMethod(method)) {

                            var priceBlock = method.price + ' ' + ShoppingCart.getCurrentCurrencySymbol();
                            if (ShoppingCart.settings.ui.currency_symbol_position === 'before') {
                                priceBlock = ShoppingCart.getCurrentCurrencySymbol() + ' ' + method.price;
                            }

                            select.options[select.options.length] = new Option(method.name + ' - ' + priceBlock, method.name);
                        }
                    }
                }
            }

            jQuery('.checkout-choose-shipping-block').show();
        }
    };

    /***********************************************************/
    /* Get the payment options based on the settings
    /***********************************************************/
    ShoppingCart.populatePaymentOptions = function populatePaymentOptions() {
        jQuery('.checkout-choose-payment-block').hide();
        jQuery('.checkout-choose-payment-block-title').hide();

        var paymentMethods = [];
        for (index in ShoppingCart.settings.payment.methods) {
            paymentMethods[index] = ShoppingCart.settings.payment.methods[index];
        }

        var paymentMethodsCount = 0;
        for (index in paymentMethods) {
            if (paymentMethods.hasOwnProperty(index)) {
                paymentMethodsCount++;
            }
        }

        var select = document.getElementById('js__payment__method');

        if (select) {
            select.options.length = 0;

            for (index in paymentMethods) {
                if (paymentMethods.hasOwnProperty(index)) {
                    method = paymentMethods[index];

                    select.options[select.options.length] = new Option(method.name, index);
                }
            }
        }

        if (paymentMethodsCount > 1) {
            jQuery('.checkout-choose-payment-block').show();
            jQuery('.checkout-choose-payment-block-title').show();
        }
    };

    /***********************************************************/
    /* Setup the checkout page
    /***********************************************************/
    ShoppingCart.setupCheckout = function setupCheckout() {
        if (!storejs.get('grav-shoppingcart-basket-data') || storejs.get('grav-shoppingcart-basket-data').length == 0) {
            jQuery('.js__checkout__block').html(window.PLUGIN_SHOPPINGCART.translations.NO_ITEMS_IN_CART);
            jQuery('.js__checkout__block').show();
            return;
        }

        jQuery('.js__checkout__block').show();

        //I have items in the cart, I can go on

        var countries = ShoppingCart.getCountries();
        var select = document.getElementById('js__billing__country');
        if (select) {
            for (index in countries) {
                if (ShoppingCart.countryCanBuy(countries[index].code)) {
                    select.options[select.options.length] = new Option(countries[index].name, countries[index].code);
                }
            }
        }

        var states = ShoppingCart.getUSAStates();
        select = document.getElementById('js__billing__state');
        if (select) {
            for (var i = 0; i < states.length; i++) {
                select.options[select.options.length] = new Option(states[i].name, states[i].code);
            }
        }

        var stateChanged = function stateChanged() {
            //Calculate immediately the shipping address, so it's used for taxes
            if (!ShoppingCart.checkout_form_data) {
                ShoppingCart.checkout_form_data = {
                    state: jQuery('.js__billing__state').val(),
                };
            } else {
                ShoppingCart.checkout_form_data.state = jQuery('.js__billing__state').val();
            }
            ShoppingCart.calculateTotalPriceIncludingTaxes();
            ShoppingCart.calculateTotalPriceIncludingTaxesAndShipping();
            ShoppingCart.renderCart();
        };

        /***********************************************************/
        /* Called when first populating the country field with the default
        /* country, and when the user changes the country.
        /* Used to calculate the default shipping price too.
        /***********************************************************/
        var countryChanged = function countryChanged() {
            //Calculate immediately the shipping price, so it's shown in the cart
            if (!ShoppingCart.checkout_form_data) {
                ShoppingCart.checkout_form_data = {
                    country: jQuery('.js__billing__country').val(),
                };
            } else {
                ShoppingCart.checkout_form_data.country = jQuery('.js__billing__country').val();
            }

            ShoppingCart.populateShippingOptions();

            ShoppingCart.generateShippingPrice();

            if (jQuery('.js__billing__country').val() === 'US') {
                jQuery('.js__billing__state__control').show();
                jQuery('.js__billing__province__control').hide();
            } else {
                jQuery('.js__billing__state__control').hide();
                jQuery('.js__billing__province__control').show();
            }
            ShoppingCart.calculateTotalPriceIncludingTaxes();
            ShoppingCart.calculateTotalPriceIncludingTaxesAndShipping();
            ShoppingCart.renderCart();
        };

        jQuery("#js__billing__country").val(ShoppingCart.settings.general.default_country || 'US');
        countryChanged();

        ShoppingCart.populatePaymentOptions();

        if ((ShoppingCart.settings.general.default_country || 'US') === 'US') {
            jQuery('.js__billing__state__control').show();
            stateChanged();
        } else {
            jQuery('.js__billing__province__control').show();
        }

        jQuery(document).delegate('.js__billing__country', 'change', function() {
            countryChanged();
        });

        jQuery(document).delegate('.js__billing__state', 'change', function() {
            stateChanged();
        });

    };

})(window.ShoppingCart);
<commit_msg>Clean unused data<commit_after>(function(ShoppingCart) {

    ShoppingCart.processCheckoutFormSubmission = function processCheckoutFormSubmission() {
        var that = this;

        /********************************************************/
        /* Function called if I later can go on with the checkout
        /********************************************************/
        var _goOnWithCheckout = function _goOnWithCheckout() {

            var processRandomToken = function processRandomToken() {
                var randomToken = function randomToken(length) {
                    var upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                    var lower = 'abcdefghijklmnopqrstuvwxyz';
                    var number = '0123456789';
                    var token = '', i;
                    var seed = upper + lower + number;
                    length = length || 13;

                    for (i = 0; i < length; i++) {
                        token += seed[Math.floor(Math.random() * (seed.length - 1))];
                    }

                    return token;
                };

                storejs.set('grav-shoppingcart-order-token', { token: randomToken(10) });
            };

            var processShippingMethod = function processShippingMethod() {
                var shippingMethod = {
                    method: '',
                    cost: 0
                };

                if (ShoppingCart.settings.shipping.methods.length === 1) {
                    shippingMethod = {
                        method: ShoppingCart.settings.shipping.methods[0].name,
                        cost: ShoppingCart.settings.shipping.methods[0].price
                    };
                } else {
                    shippingMethod = {
                        method: jQuery('.js__shipping__method').val(),
                        cost: ShoppingCart.shippingPrice
                    };
                }

                //Store in localstorage
                storejs.set('grav-shoppingcart-shipping-method', shippingMethod);
            };

            var calculateTotalOrderPrice = function calculateTotalOrderPrice () {
                //Calculate the order price
                var orderPrice = ShoppingCart.totalOrderPriceIncludingTaxes;
                if (!orderPrice) {
                    orderPrice = 0;
                    var i = 0;
                    var cart = ShoppingCart.items;

                    while (i < cart.length) {
                        orderPrice += cart[i].product.price * cart[i].quantity;
                        i++;
                    }
                }

                //////////////////////////////////////////////////////////
                //Add shipping costs to the order price
                //////////////////////////////////////////////////////////
                ShoppingCart.generateShippingPrice();
                orderPrice = parseFloat(parseFloat(orderPrice) + parseFloat(ShoppingCart.shippingPrice)).toFixed(2);
                ShoppingCart.totalOrderPrice = orderPrice;
            };

            processRandomToken();
            processShippingMethod();
            calculateTotalOrderPrice ();

            jQuery(that).attr('disabled', 'disabled');
            jQuery(document).trigger('proceedToPayment', ShoppingCart);
        };

        var data = {};

        ShoppingCart.checkout_form_fields.forEach(function(checkout_form_field) {
            if (typeof checkout_form_field.name !== 'undefined') {
                data[checkout_form_field.name] = jQuery(checkout_form_field.classes).val();
            }
        });

        var customProcessingOfCheckoutForm = function customProcessingOfCheckoutForm() {
            if (data.country === 'US') {
                if (data.hasOwnProperty("province")) {
                    delete data.province;
                }
            } else {
                if (data.hasOwnProperty("state")) {
                    delete data.state;
                }

                if (!data.province) {
                    alert(window.PLUGIN_SHOPPINGCART.translations.PLEASE_FILL_ALL_THE_REQUIRED_FIELDS);
                    return;
                }
            }
        };

        customProcessingOfCheckoutForm();

        ShoppingCart.checkout_form_data = data;
        storejs.set('grav-shoppingcart-checkout-form-data', data); //Store data info in cookie

        ShoppingCart.gateway = jQuery('.js__payment__method').val();

        _goOnWithCheckout();
    };

    /***********************************************************/
    /* Get the shipping options based on the settings
    /***********************************************************/
    ShoppingCart.populateShippingOptions = function populateShippingOptions() {
        var shippingMethods = [];
        for (index in ShoppingCart.settings.shipping.methods) {
            shippingMethods[index] = ShoppingCart.settings.shipping.methods[index];
        }

        var methodIsAllowedInCountry = function methodIsAllowedInCountry(method, country) {
            for (index in method.allowed_countries) {
                if (method.allowed_countries[index] == country) return true;
                if (method.allowed_countries[index] == '*') return true;
            }
            return false;
        };

        var ifIsGenericThereIsNoCountrySpecificMethod = function ifIsGenericThereIsNoCountrySpecificMethod(method, country) {
            return true;
        };

        var orderWeightIsAllowedForThisMethod = function orderWeightIsAllowedForThisMethod(method) {
            return true;
        };

        var orderPriceIsAllowedForThisMethod = function orderPriceIsAllowedForThisMethod(method) {
            return true;
        };

        if (jQuery('.js__billing__country').val() === 'US') {
            jQuery('.js__billing__state__control').show();
            jQuery('.js__billing__province__control').hide();
        } else {
            jQuery('.js__billing__state__control').hide();
            jQuery('.js__billing__province__control').show();
        }

        if (shippingMethods.length === 0) {
            jQuery('.checkout-choose-shipping-block').hide();
        } else if (shippingMethods.length === 1) {

            var priceBlock = shippingMethods[0].price + ' ' + ShoppingCart.getCurrentCurrencySymbol();
            if (ShoppingCart.settings.ui.currency_symbol_position === 'before') {
                priceBlock = ShoppingCart.getCurrentCurrencySymbol() + ' ' + shippingMethods[0].price;
            }

            jQuery('.checkout-choose-shipping-block .form-select-wrapper').html(shippingMethods[0].name + ' - ' + priceBlock);
            jQuery('.checkout-choose-shipping-block').show();
        } else {
            var select = document.getElementById('js__shipping__method');

            if (select) {
                //Calculate shipping methods for the shipping country
                select.options.length = 0;

                ShoppingCart.generateShippingPrice();

                for (index in shippingMethods) {
                    if (shippingMethods.hasOwnProperty(index)) {
                        method = shippingMethods[index];
                        if (methodIsAllowedInCountry(method, ShoppingCart.checkout_form_data.country) &&
                                ifIsGenericThereIsNoCountrySpecificMethod(method, ShoppingCart.checkout_form_data.country) &&
                                orderWeightIsAllowedForThisMethod(method) &&
                                orderPriceIsAllowedForThisMethod(method)) {

                            var priceBlock = method.price + ' ' + ShoppingCart.getCurrentCurrencySymbol();
                            if (ShoppingCart.settings.ui.currency_symbol_position === 'before') {
                                priceBlock = ShoppingCart.getCurrentCurrencySymbol() + ' ' + method.price;
                            }

                            select.options[select.options.length] = new Option(method.name + ' - ' + priceBlock, method.name);
                        }
                    }
                }
            }

            jQuery('.checkout-choose-shipping-block').show();
        }
    };

    /***********************************************************/
    /* Get the payment options based on the settings
    /***********************************************************/
    ShoppingCart.populatePaymentOptions = function populatePaymentOptions() {
        jQuery('.checkout-choose-payment-block').hide();
        jQuery('.checkout-choose-payment-block-title').hide();

        var paymentMethods = [];
        for (index in ShoppingCart.settings.payment.methods) {
            paymentMethods[index] = ShoppingCart.settings.payment.methods[index];
        }

        var paymentMethodsCount = 0;
        for (index in paymentMethods) {
            if (paymentMethods.hasOwnProperty(index)) {
                paymentMethodsCount++;
            }
        }

        var select = document.getElementById('js__payment__method');

        if (select) {
            select.options.length = 0;

            for (index in paymentMethods) {
                if (paymentMethods.hasOwnProperty(index)) {
                    method = paymentMethods[index];

                    select.options[select.options.length] = new Option(method.name, index);
                }
            }
        }

        if (paymentMethodsCount > 1) {
            jQuery('.checkout-choose-payment-block').show();
            jQuery('.checkout-choose-payment-block-title').show();
        }
    };

    /***********************************************************/
    /* Setup the checkout page
    /***********************************************************/
    ShoppingCart.setupCheckout = function setupCheckout() {
        if (!storejs.get('grav-shoppingcart-basket-data') || storejs.get('grav-shoppingcart-basket-data').length == 0) {
            jQuery('.js__checkout__block').html(window.PLUGIN_SHOPPINGCART.translations.NO_ITEMS_IN_CART);
            jQuery('.js__checkout__block').show();
            return;
        }

        jQuery('.js__checkout__block').show();

        //I have items in the cart, I can go on

        var countries = ShoppingCart.getCountries();
        var select = document.getElementById('js__billing__country');
        if (select) {
            for (index in countries) {
                if (ShoppingCart.countryCanBuy(countries[index].code)) {
                    select.options[select.options.length] = new Option(countries[index].name, countries[index].code);
                }
            }
        }

        var states = ShoppingCart.getUSAStates();
        select = document.getElementById('js__billing__state');
        if (select) {
            for (var i = 0; i < states.length; i++) {
                select.options[select.options.length] = new Option(states[i].name, states[i].code);
            }
        }

        var stateChanged = function stateChanged() {
            //Calculate immediately the shipping address, so it's used for taxes
            if (!ShoppingCart.checkout_form_data) {
                ShoppingCart.checkout_form_data = {
                    state: jQuery('.js__billing__state').val(),
                };
            } else {
                ShoppingCart.checkout_form_data.state = jQuery('.js__billing__state').val();
            }
            ShoppingCart.calculateTotalPriceIncludingTaxes();
            ShoppingCart.calculateTotalPriceIncludingTaxesAndShipping();
            ShoppingCart.renderCart();
        };

        /***********************************************************/
        /* Called when first populating the country field with the default
        /* country, and when the user changes the country.
        /* Used to calculate the default shipping price too.
        /***********************************************************/
        var countryChanged = function countryChanged() {
            //Calculate immediately the shipping price, so it's shown in the cart
            if (!ShoppingCart.checkout_form_data) {
                ShoppingCart.checkout_form_data = {
                    country: jQuery('.js__billing__country').val(),
                };
            } else {
                ShoppingCart.checkout_form_data.country = jQuery('.js__billing__country').val();
            }

            ShoppingCart.populateShippingOptions();

            ShoppingCart.generateShippingPrice();

            if (jQuery('.js__billing__country').val() === 'US') {
                jQuery('.js__billing__state__control').show();
                jQuery('.js__billing__province__control').hide();
            } else {
                jQuery('.js__billing__state__control').hide();
                jQuery('.js__billing__province__control').show();
            }
            ShoppingCart.calculateTotalPriceIncludingTaxes();
            ShoppingCart.calculateTotalPriceIncludingTaxesAndShipping();
            ShoppingCart.renderCart();
        };

        jQuery("#js__billing__country").val(ShoppingCart.settings.general.default_country || 'US');
        countryChanged();

        ShoppingCart.populatePaymentOptions();

        if ((ShoppingCart.settings.general.default_country || 'US') === 'US') {
            jQuery('.js__billing__state__control').show();
            stateChanged();
        } else {
            jQuery('.js__billing__province__control').show();
        }

        jQuery(document).delegate('.js__billing__country', 'change', function() {
            countryChanged();
        });

        jQuery(document).delegate('.js__billing__state', 'change', function() {
            stateChanged();
        });

    };

})(window.ShoppingCart);
<|endoftext|>


<commit_before>/*
 * vim: ts=4:sw=4:expandtab
 */
(function () {
    'use strict';
    window.Whisper = window.Whisper || {};

    Whisper.FileSizeToast = Whisper.ToastView.extend({
        templateName: 'file-size-modal',
        render_attributes: function() {
            return {
                'file-size-warning': i18n('fileSizeWarning'),
                limit: this.model.limit,
                units: this.model.units
            };
        }
    });
    Whisper.UnsupportedFileTypeToast = Whisper.ToastView.extend({
        template: i18n('unsupportedFileType')
    });

    Whisper.FileInputView = Backbone.View.extend({
        tagName: 'span',
        className: 'file-input',
        initialize: function(options) {
            this.$input = this.$('input[type=file]');
            this.thumb = new Whisper.AttachmentPreviewView();
            this.$el.addClass('file-input');
            this.window = options.window;
        },

        events: {
            'change': 'previewImages',
            'click .close': 'deleteFiles',
            'click .choose-file': 'open',
            'drop': 'openDropped',
            'dragover': 'showArea',
            'dragleave': 'hideArea'
        },

        open: function() {
            // hack
            if (this.window && this.window.chrome && this.window.chrome.fileSystem) {
                this.window.chrome.fileSystem.chooseEntry({type: 'openFile'}, function(entry) {
                    if (!entry) {
                        return;
                    }
                    entry.file(function(file) {
                        this.file = file;
                        this.previewImages();
                    }.bind(this));
                }.bind(this));
            } else {
                this.$input.click();
            }
        },

        addThumb: function(src) {
            this.$('.avatar').hide();
            this.thumb.src = src;
            this.$('.attachment-previews').append(this.thumb.render().el);
            this.thumb.$('img')[0].onload = function() {
                this.$el.trigger('force-resize');
            }.bind(this);
        },

        autoScale: function(file) {
            if (file.type.split('/')[0] !== 'image' || file.type === 'image/gif') {
                // nothing to do
                return Promise.resolve(file);
            }

            return new Promise(function(resolve, reject) {
                var url = URL.createObjectURL(file);
                var img = document.createElement('img');
                img.onerror = reject;
                img.onload = function () {
                    URL.revokeObjectURL(url);

                    var maxSize = 420 * 1024;
                    var maxHeight = 1280;
                    var maxWidth = 1280;
                    if (img.width <= maxWidth && img.height <= maxHeight &&
                        file.size <= maxSize) {
                        resolve(file);
                        return;
                    }

                    // loadImage.scale -> components/blueimp-load-image
                    var canvas = loadImage.scale(img, {
                        canvas: true, maxWidth: maxWidth, maxHeight: maxHeight
                    });

                    var quality = 0.95;
                    var i = 4;
                    var blob;
                    do {
                        i = i - 1;
                        // dataURLtoBlob -> components/blueimp-canvas-to-blob
                        blob = dataURLtoBlob(
                            canvas.toDataURL('image/jpeg', quality)
                        );
                        quality = quality * maxSize / blob.size;
                        if (quality < 50) {
                            quality = 50;
                        }
                    } while (i > 0 && blob.size > maxSize);

                    resolve(blob);
                };
                img.src = url;
            });
        },

        previewImages: function() {
            this.clearForm();
            var file = this.file || this.$input.prop('files')[0];
            if (!file) { return; }

            var type = file.type.split('/')[0];
            switch (type) {
                case 'audio': this.addThumb('/images/audio.svg'); break;
                case 'video': this.addThumb('/images/video.svg'); break;
                case 'image':
                    this.oUrl = URL.createObjectURL(file);
                    this.addThumb(this.oUrl);
                    break;
                default:
                    var toast = new Whisper.UnsupportedFileTypeToast();
                    toast.$el.insertAfter(this.$el);
                    toast.render();
                    this.deleteFiles();
                    return;
            }

            this.autoScale(file).then(function(blob) {
                var limitKb = 1000000;
                var blobType = file.type === 'image/gif' ? 'gif' : type;
                switch (blobType) {
                    case 'image':
                        limitKb = 420; break;
                    case 'gif':
                        limitKb = 5000; break;
                    case 'audio':
                        limitKb = 100000; break;
                    case 'video':
                        limitKb = 100000; break;
                }
                if ((blob.size/1024).toFixed(4) >= limitKb) {
                    var units = ['kB','MB','GB'];
                    var u = -1;
                    var limit = limitKb * 1000;
                    do {
                      limit /= 1000;
                      ++u;
                    } while (limit >= 1000 && u < units.length - 1);
                    var toast = new Whisper.FileSizeToast({
                        model: {limit: limit, units: units[u]}
                    });
                    toast.$el.insertAfter(this.$el);
                    toast.render();
                    this.deleteFiles();
                }
            }.bind(this));
        },

        hasFiles: function() {
            var files = this.file ? [this.file] : this.$input.prop('files');
            return files && files.length && files.length > 0;
        },

        getFiles: function() {
            var promises = [];
            var files = this.file ? [this.file] : this.$input.prop('files');
            for (var i = 0; i < files.length; i++) {
                promises.push(this.getFile(files[i]));
            }
            this.clearForm();
            return Promise.all(promises);
        },

        getFile: function(file) {
            file = file || this.file || this.$input.prop('files')[0];
            if (file === undefined) { return Promise.resolve(); }
            return this.autoScale(file).then(this.readFile);
        },

        getThumbnail: function() {
            // Scale and crop an image to 256px square
            var size = 256;
            var file = this.file || this.$input.prop('files')[0];
            if (file === undefined || file.type.split('/')[0] !== 'image' || file.type === 'image/gif') {
                // nothing to do
                return Promise.resolve();
            }

            return new Promise(function(resolve, reject) {
                var url = URL.createObjectURL(file);
                var img = document.createElement('img');
                img.onerror = reject;
                img.onload = function () {
                    URL.revokeObjectURL(url);
                    // loadImage.scale -> components/blueimp-load-image
                    // scale, then crop.
                    var canvas = loadImage.scale(img, {
                        canvas: true, maxWidth: size, maxHeight: size,
                        cover: true, minWidth: size, minHeight: size
                    });
                    canvas = loadImage.scale(canvas, {
                        canvas: true, maxWidth: size, maxHeight: size,
                        crop: true, minWidth: size, minHeight: size
                    });

                    // dataURLtoBlob -> components/blueimp-canvas-to-blob
                    var blob = dataURLtoBlob(canvas.toDataURL('image/png'));

                    resolve(blob);
                };
                img.src = url;
            }).then(this.readFile);
        },

        readFile: function(file) {
            var contentType = file.type;
            return new Promise(function(resolve, reject) {
                var FR = new FileReader();
                FR.onload = function(e) {
                    resolve({data: e.target.result, contentType: contentType});
                };
                FR.readAsArrayBuffer(file);
            });
        },

        clearForm: function() {
            if (this.oUrl) {
                URL.revokeObjectURL(this.oUrl);
                this.oUrl = null;
            }
            this.thumb.remove();
            this.$('.avatar').show();
            this.$el.trigger('force-resize');
        },

        deleteFiles: function(e) {
            if (e) { e.stopPropagation(); }
            this.clearForm();
            this.$input.wrap('<form>').parent('form').trigger('reset');
            this.$input.unwrap();
            this.file = null;
        },

        openDropped: function(e) {
            if (e.originalEvent.dataTransfer.types[0] != 'Files') {
                return;
            }

            e.stopPropagation();
            e.preventDefault();
            this.file = e.originalEvent.dataTransfer.files[0];
            this.previewImages();
            this.$el.removeClass('dropoff');
        },

        showArea: function(e) {
            if (e.originalEvent.dataTransfer.types[0] != 'Files') {
                return;
            }

            e.stopPropagation();
            e.preventDefault();
            this.$el.addClass('dropoff');
        },

        hideArea: function(e) {
            if (e.originalEvent.dataTransfer.types[0] != 'Files') {
                return;
            }

            e.stopPropagation();
            e.preventDefault();
            this.$el.removeClass('dropoff');
        }
    });
})();
<commit_msg>Fix typo of quality argument in image compression<commit_after>/*
 * vim: ts=4:sw=4:expandtab
 */
(function () {
    'use strict';
    window.Whisper = window.Whisper || {};

    Whisper.FileSizeToast = Whisper.ToastView.extend({
        templateName: 'file-size-modal',
        render_attributes: function() {
            return {
                'file-size-warning': i18n('fileSizeWarning'),
                limit: this.model.limit,
                units: this.model.units
            };
        }
    });
    Whisper.UnsupportedFileTypeToast = Whisper.ToastView.extend({
        template: i18n('unsupportedFileType')
    });

    Whisper.FileInputView = Backbone.View.extend({
        tagName: 'span',
        className: 'file-input',
        initialize: function(options) {
            this.$input = this.$('input[type=file]');
            this.thumb = new Whisper.AttachmentPreviewView();
            this.$el.addClass('file-input');
            this.window = options.window;
        },

        events: {
            'change': 'previewImages',
            'click .close': 'deleteFiles',
            'click .choose-file': 'open',
            'drop': 'openDropped',
            'dragover': 'showArea',
            'dragleave': 'hideArea'
        },

        open: function() {
            // hack
            if (this.window && this.window.chrome && this.window.chrome.fileSystem) {
                this.window.chrome.fileSystem.chooseEntry({type: 'openFile'}, function(entry) {
                    if (!entry) {
                        return;
                    }
                    entry.file(function(file) {
                        this.file = file;
                        this.previewImages();
                    }.bind(this));
                }.bind(this));
            } else {
                this.$input.click();
            }
        },

        addThumb: function(src) {
            this.$('.avatar').hide();
            this.thumb.src = src;
            this.$('.attachment-previews').append(this.thumb.render().el);
            this.thumb.$('img')[0].onload = function() {
                this.$el.trigger('force-resize');
            }.bind(this);
        },

        autoScale: function(file) {
            if (file.type.split('/')[0] !== 'image' || file.type === 'image/gif') {
                // nothing to do
                return Promise.resolve(file);
            }

            return new Promise(function(resolve, reject) {
                var url = URL.createObjectURL(file);
                var img = document.createElement('img');
                img.onerror = reject;
                img.onload = function () {
                    URL.revokeObjectURL(url);

                    var maxSize = 420 * 1024;
                    var maxHeight = 1280;
                    var maxWidth = 1280;
                    if (img.width <= maxWidth && img.height <= maxHeight &&
                        file.size <= maxSize) {
                        resolve(file);
                        return;
                    }

                    // loadImage.scale -> components/blueimp-load-image
                    var canvas = loadImage.scale(img, {
                        canvas: true, maxWidth: maxWidth, maxHeight: maxHeight
                    });

                    var quality = 0.95;
                    var i = 4;
                    var blob;
                    do {
                        i = i - 1;
                        // dataURLtoBlob -> components/blueimp-canvas-to-blob
                        blob = dataURLtoBlob(
                            canvas.toDataURL('image/jpeg', quality)
                        );
                        quality = quality * maxSize / blob.size;
                        if (quality < 0.5) {
                            quality = 0.5;
                        }
                    } while (i > 0 && blob.size > maxSize);

                    resolve(blob);
                };
                img.src = url;
            });
        },

        previewImages: function() {
            this.clearForm();
            var file = this.file || this.$input.prop('files')[0];
            if (!file) { return; }

            var type = file.type.split('/')[0];
            switch (type) {
                case 'audio': this.addThumb('/images/audio.svg'); break;
                case 'video': this.addThumb('/images/video.svg'); break;
                case 'image':
                    this.oUrl = URL.createObjectURL(file);
                    this.addThumb(this.oUrl);
                    break;
                default:
                    var toast = new Whisper.UnsupportedFileTypeToast();
                    toast.$el.insertAfter(this.$el);
                    toast.render();
                    this.deleteFiles();
                    return;
            }

            this.autoScale(file).then(function(blob) {
                var limitKb = 1000000;
                var blobType = file.type === 'image/gif' ? 'gif' : type;
                switch (blobType) {
                    case 'image':
                        limitKb = 420; break;
                    case 'gif':
                        limitKb = 5000; break;
                    case 'audio':
                        limitKb = 100000; break;
                    case 'video':
                        limitKb = 100000; break;
                }
                if ((blob.size/1024).toFixed(4) >= limitKb) {
                    var units = ['kB','MB','GB'];
                    var u = -1;
                    var limit = limitKb * 1000;
                    do {
                      limit /= 1000;
                      ++u;
                    } while (limit >= 1000 && u < units.length - 1);
                    var toast = new Whisper.FileSizeToast({
                        model: {limit: limit, units: units[u]}
                    });
                    toast.$el.insertAfter(this.$el);
                    toast.render();
                    this.deleteFiles();
                }
            }.bind(this));
        },

        hasFiles: function() {
            var files = this.file ? [this.file] : this.$input.prop('files');
            return files && files.length && files.length > 0;
        },

        getFiles: function() {
            var promises = [];
            var files = this.file ? [this.file] : this.$input.prop('files');
            for (var i = 0; i < files.length; i++) {
                promises.push(this.getFile(files[i]));
            }
            this.clearForm();
            return Promise.all(promises);
        },

        getFile: function(file) {
            file = file || this.file || this.$input.prop('files')[0];
            if (file === undefined) { return Promise.resolve(); }
            return this.autoScale(file).then(this.readFile);
        },

        getThumbnail: function() {
            // Scale and crop an image to 256px square
            var size = 256;
            var file = this.file || this.$input.prop('files')[0];
            if (file === undefined || file.type.split('/')[0] !== 'image' || file.type === 'image/gif') {
                // nothing to do
                return Promise.resolve();
            }

            return new Promise(function(resolve, reject) {
                var url = URL.createObjectURL(file);
                var img = document.createElement('img');
                img.onerror = reject;
                img.onload = function () {
                    URL.revokeObjectURL(url);
                    // loadImage.scale -> components/blueimp-load-image
                    // scale, then crop.
                    var canvas = loadImage.scale(img, {
                        canvas: true, maxWidth: size, maxHeight: size,
                        cover: true, minWidth: size, minHeight: size
                    });
                    canvas = loadImage.scale(canvas, {
                        canvas: true, maxWidth: size, maxHeight: size,
                        crop: true, minWidth: size, minHeight: size
                    });

                    // dataURLtoBlob -> components/blueimp-canvas-to-blob
                    var blob = dataURLtoBlob(canvas.toDataURL('image/png'));

                    resolve(blob);
                };
                img.src = url;
            }).then(this.readFile);
        },

        readFile: function(file) {
            var contentType = file.type;
            return new Promise(function(resolve, reject) {
                var FR = new FileReader();
                FR.onload = function(e) {
                    resolve({data: e.target.result, contentType: contentType});
                };
                FR.readAsArrayBuffer(file);
            });
        },

        clearForm: function() {
            if (this.oUrl) {
                URL.revokeObjectURL(this.oUrl);
                this.oUrl = null;
            }
            this.thumb.remove();
            this.$('.avatar').show();
            this.$el.trigger('force-resize');
        },

        deleteFiles: function(e) {
            if (e) { e.stopPropagation(); }
            this.clearForm();
            this.$input.wrap('<form>').parent('form').trigger('reset');
            this.$input.unwrap();
            this.file = null;
        },

        openDropped: function(e) {
            if (e.originalEvent.dataTransfer.types[0] != 'Files') {
                return;
            }

            e.stopPropagation();
            e.preventDefault();
            this.file = e.originalEvent.dataTransfer.files[0];
            this.previewImages();
            this.$el.removeClass('dropoff');
        },

        showArea: function(e) {
            if (e.originalEvent.dataTransfer.types[0] != 'Files') {
                return;
            }

            e.stopPropagation();
            e.preventDefault();
            this.$el.addClass('dropoff');
        },

        hideArea: function(e) {
            if (e.originalEvent.dataTransfer.types[0] != 'Files') {
                return;
            }

            e.stopPropagation();
            e.preventDefault();
            this.$el.removeClass('dropoff');
        }
    });
})();
<|endoftext|>


<commit_before>angular
  .module('app')
  .controller('VisualizerController', VisualizerController);

VisualizerController.$inject = ['$rootScope','$scope', 'SERIAL'];

function VisualizerController($rootScope, $scope, SERIAL) {
  'use strict';

  var vm             = this,
      connectionPath = '',
      serialObject   = {},
      connectionInfo,
      connectionId;

  vm.devices = [];

  // Lists available serial devices and appends them to vm.devices and connects to the device.
  SERIAL.getDevices(onGetDevices);

  // Listen for data from device.
  SERIAL.onReceive.addListener(onRecieveCallback);

  // Listens for errors from data stream.
  SERIAL.onReceiveError.addListener(onReceiveErrorCallback);

  // Pauses & unpauses the data stream.
  document.querySelector('body').onclick = pauser;

  function onGetDevices(ports) {
    for (var i = 0; i < ports.length; i++) {
      vm.devices.push(ports[i].path);
    }
    connectionPath = vm.connectionPath = vm.devices[5];
    SERIAL.connect(connectionPath, {receiveTimeout: 3000}, onConnect);
    $scope.$apply();
  }

  function onConnect(info) {
    // The serial port has been opened. Save its id to use later.
    connectionId = vm.id = info.connectionId;
    connectionInfo = vm.connectionInfo = info;
  }

  function onRecieveCallback (arrayBuffer) {
    // _.delay(function () {
      var  u8view       = new Uint8Array(arrayBuffer.data),
           parsedKVPArr = [],
           str          = '',
           sync         = false;

      // Convert ArrayBuffer to a string then an Array.
      str = String.fromCharCode.apply(null, u8view);

      parsedKVPArr = str.replace(/(\r\n|\n|\r)/gm, ',').replace(/(\s)/g, '').split(',').slice(0, -1);

      // Convert Parsed Array into an obj with 24 values starting from 0

      for (var c = 0; c < parsedKVPArr.length; c++) {
        var tempArr = parsedKVPArr[c].split(':');

        if (!!tempArr[0] && !!tempArr[1]) {
          if (sync) {
            serialObject[tempArr[0]] = parseInt(tempArr[1], 16);
            if (Object.keys(serialObject).length === 24){
                vm.data = d3.entries(serialObject);
                $rootScope.$broadcast('dataChanged');
                serialObject = {};
            }
          } else if (tempArr[0] === '0') {
            serialObject[tempArr[0]] = parseInt(tempArr[1], 16);
            sync = true;
          }
        } else {
          console.log('Dropped a Value/Out of Sync??? ' + parseInt(tempArr[0], 16));
        }
      }
    // }, 100);
  }

  function onReceiveErrorCallback(info) {
    console.log(info);
  }

  function pauser () {
    if (connectionInfo.paused) {
      SERIAL.setPaused(connectionId, false, function(){});
      connectionInfo.paused = vm.connectionInfo.paused = false;
    } else {
      SERIAL.setPaused(connectionId, true, function(){console.log('Paused');});
      connectionInfo.paused = vm.connectionInfo.paused = true;
    }
    $scope.$apply();
  }

}
<commit_msg>It's Alive and updating the dom sluggishy at 50ms !!!!!!! Woooo Hooooo!!!!<commit_after>angular
  .module('app')
  .controller('VisualizerController', VisualizerController);

VisualizerController.$inject = ['$rootScope','$scope', 'SERIAL'];

function VisualizerController($rootScope, $scope, SERIAL) {
  'use strict';

  var vm             = this,
      connectionPath = '',
      serialObject   = {},
      connectionInfo,
      connectionId;

  vm.devices = [];

  setInterval(function(){
    $rootScope.$broadcast('dataChanged');
  }, 50);

  // Lists available serial devices and appends them to vm.devices and connects to the device.
  SERIAL.getDevices(onGetDevices);

  // Listen for data from device.
  SERIAL.onReceive.addListener(onRecieveCallback);

  // Listens for errors from data stream.
  SERIAL.onReceiveError.addListener(onReceiveErrorCallback);

  // Pauses & unpauses the data stream.
  document.querySelector('body').onclick = pauser;

  function onGetDevices(ports) {
    for (var i = 0; i < ports.length; i++) {
      vm.devices.push(ports[i].path);
    }
    connectionPath = vm.connectionPath = vm.devices[5];
    SERIAL.connect(connectionPath, {receiveTimeout: 3000}, onConnect);
    $scope.$apply();
  }

  function onConnect(info) {
    // The serial port has been opened. Save its id to use later.
    connectionId = vm.id = info.connectionId;
    connectionInfo = vm.connectionInfo = info;
  }

  function onRecieveCallback (arrayBuffer) {
    // _.delay(function () {
      var  u8view       = new Uint8Array(arrayBuffer.data),
           parsedKVPArr = [],
           str          = '',
           sync         = false;

      // Convert ArrayBuffer to a string then an Array.
      str = String.fromCharCode.apply(null, u8view);

      parsedKVPArr = str.replace(/(\r\n|\n|\r)/gm, ',').replace(/(\s)/g, '').split(',').slice(0, -1);

      // Convert Parsed Array into an obj with 24 values starting from 0

      for (var c = 0; c < parsedKVPArr.length; c++) {
        var tempArr = parsedKVPArr[c].split(':');

        if (!!tempArr[0] && !!tempArr[1]) {
          if (sync) {
            serialObject[tempArr[0]] = parseInt(tempArr[1], 16);
            if (Object.keys(serialObject).length === 24){
              vm.data = d3.entries(serialObject);
              serialObject = {};
            }
          } else if (tempArr[0] === '0') {
            serialObject[tempArr[0]] = parseInt(tempArr[1], 16);
            sync = true;
          }
        } else {
          console.log('Dropped a Value/Out of Sync??? ' + parseInt(tempArr[0], 16));
        }
      }
    // }, 100);
  }

  function onReceiveErrorCallback(info) {
    console.log(info);
  }

  function pauser () {
    if (connectionInfo.paused) {
      SERIAL.setPaused(connectionId, false, function(){});
      connectionInfo.paused = vm.connectionInfo.paused = false;
    } else {
      SERIAL.setPaused(connectionId, true, function(){console.log('Paused');});
      connectionInfo.paused = vm.connectionInfo.paused = true;
    }
    $scope.$apply();
  }

}
<|endoftext|>


<commit_before>openerp.report = function(instance) {

    instance.web.ActionManager = instance.web.ActionManager.extend({
        ir_actions_report_xml: function(action, options) {
            var self = this;
            instance.web.blockUI();
            action = _.clone(action);
            var eval_contexts = ([instance.session.user_context] || []).concat([action.context]);
            action.context = instance.web.pyeval.eval('contexts',eval_contexts);
            _t =  instance.web._t;

            // QWeb reports
            if ('report_type' in action && (action.report_type == 'qweb-html' || action.report_type == 'qweb-pdf' || action.report_type == 'controller')) {

                var report_url = ''
                switch (action.report_type) {
                    case 'qweb-html':
                        report_url = '/report/' + action.report_name;
                        break;
                    case 'qweb-pdf':
                        report_url = '/report/pdf/report/' + action.report_name;
                        break;
                    case 'controller':
                        report_url = action.report_file;
                        break;
                    default:
                        report_url = '/report/' + action.report_name;
                        break;
                }

                // single/multiple id(s): no query string
                // wizard: query string of action.datas.form
                if (!('datas' in action)) {
                    if ('active_ids' in action.context) {
                        report_url += "/" + action.context.active_ids.join(',');
                    }
                } else {
                    _.each(action.datas.form, function(value, key) {
                        // will be erased when all wizards are rewritten
                        if (key.substring(0, 12) === 'used_context') {
                            delete action.datas.form[key];
                        }

                        if ($.type(value) === 'array') {
                            action.datas.form[key] = value.join(',');
                        }
                    });
                    report_url += "?" + $.param(action.datas.form);
                }
                if (action.report_type == 'qweb-html') {
                    // Open the html report in a popup
                    window.open(report_url, '_blank', 'height=768,width=1024');
                    instance.web.unblockUI();
                    return;
                } else {
                    // Trigger the download of the pdf/custom controller report
                    var c = openerp.webclient.crashmanager;
                    var response = new Array()
                    response[0] = report_url
                    response[1] = action.report_type

                    openerp.session.rpc('/report/check_wkhtmltopdf').then(function (presence) {
                        // Fallback of qweb-pdf if wkhtmltopdf is not installed
                        if (!presence && action.report_type == 'qweb-pdf') {
                            self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this system. The report will be shown in html.'), true);
                            window.open(report_url.substring(12), '_blank', 'height=768,width=1024');
                            instance.web.unblockUI();
                        }
                        else {
                            if (presence == 'upgrade') {
                                self.do_notify(_t('Report'), _t('You should upgrade your version of Wkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as support for table-breaking between pages.'), true);
                            }
                            self.session.get_file({
                                url: '/report/download',
                                data: {data: JSON.stringify(response)},
                                complete: openerp.web.unblockUI,
                                error: c.rpc_error.bind(c)
                            });
                        }
                    });
                }
            } else {
                return self._super(action, options);
            }
        }
    });
};
<commit_msg>[IMP] Add link to wkhtmltopdf.org in the webclient notifications<commit_after>openerp.report = function(instance) {

    instance.web.ActionManager = instance.web.ActionManager.extend({
        ir_actions_report_xml: function(action, options) {
            var self = this;
            instance.web.blockUI();
            action = _.clone(action);
            var eval_contexts = ([instance.session.user_context] || []).concat([action.context]);
            action.context = instance.web.pyeval.eval('contexts',eval_contexts);
            _t =  instance.web._t;

            // QWeb reports
            if ('report_type' in action && (action.report_type == 'qweb-html' || action.report_type == 'qweb-pdf' || action.report_type == 'controller')) {

                var report_url = ''
                switch (action.report_type) {
                    case 'qweb-html':
                        report_url = '/report/' + action.report_name;
                        break;
                    case 'qweb-pdf':
                        report_url = '/report/pdf/report/' + action.report_name;
                        break;
                    case 'controller':
                        report_url = action.report_file;
                        break;
                    default:
                        report_url = '/report/' + action.report_name;
                        break;
                }

                // single/multiple id(s): no query string
                // wizard: query string of action.datas.form
                if (!('datas' in action)) {
                    if ('active_ids' in action.context) {
                        report_url += "/" + action.context.active_ids.join(',');
                    }
                } else {
                    _.each(action.datas.form, function(value, key) {
                        // will be erased when all wizards are rewritten
                        if (key.substring(0, 12) === 'used_context') {
                            delete action.datas.form[key];
                        }

                        if ($.type(value) === 'array') {
                            action.datas.form[key] = value.join(',');
                        }
                    });
                    report_url += "?" + $.param(action.datas.form);
                }
                if (action.report_type == 'qweb-html') {
                    // Open the html report in a popup
                    window.open(report_url, '_blank', 'height=768,width=1024');
                    instance.web.unblockUI();
                    return;
                } else {
                    // Trigger the download of the pdf/custom controller report
                    var c = openerp.webclient.crashmanager;
                    var response = new Array()
                    response[0] = report_url
                    response[1] = action.report_type

                    openerp.session.rpc('/report/check_wkhtmltopdf').then(function (presence) {
                        // Fallback of qweb-pdf if wkhtmltopdf is not installed
                        if (!presence && action.report_type == 'qweb-pdf') {
                            self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \
system. The report will be shown in html.

\
wkhtmltopdf.org'), true);
                            window.open(report_url.substring(12), '_blank', 'height=768,width=1024');
                            instance.web.unblockUI();
                        }
                        else {
                            if (presence == 'upgrade') {
                                self.do_notify(_t('Report'), _t('You should upgrade your version of\
 Wkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as\
 support for table-breaking between pages.

wkhtmltopdf.org'), true);
                            }
                            self.session.get_file({
                                url: '/report/download',
                                data: {data: JSON.stringify(response)},
                                complete: openerp.web.unblockUI,
                                error: c.rpc_error.bind(c)
                            });
                        }
                    });
                }
            } else {
                return self._super(action, options);
            }
        }
    });
};
<|endoftext|>