<commit_before>// Generated on 2015-10-28 using generator-angular 0.14.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  grunt.loadNpmTasks('grunt-autoprefixer');
  grunt.loadNpmTasks('grunt-ng-annotate');

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: '../public'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      proxies: [
        {
          context: '/api',
          host: 'localhost',
          port: 3000
        }
      ],
      livereload: {
        options: {
          open: true,
          middleware: function (connect, options) {
            if (!Array.isArray(options.base)) {
              options.base = [options.base];
            }

            // Setup the proxy
            var middlewares = [
              require('grunt-connect-proxy/lib/utils').proxyRequest,
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];

            // Make directory browse-able.
            var directory = options.directory || options.base[options.base.length - 1];
            middlewares.push(connect.directory(directory));

            return middlewares;
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images']
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ngmin tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer',
      'configureProxies',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'concurrent:test',
    'autoprefixer',
    'configureProxies',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);

  grunt.loadNpmTasks('grunt-connect-proxy');
};
<commit_msg>Register grunt build task for Heroku:production<commit_after>// Generated on 2015-10-28 using generator-angular 0.14.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  grunt.loadNpmTasks('grunt-autoprefixer');
  grunt.loadNpmTasks('grunt-ng-annotate');

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: '../public'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      proxies: [
        {
          context: '/api',
          host: 'localhost',
          port: 3000
        }
      ],
      livereload: {
        options: {
          open: true,
          middleware: function (connect, options) {
            if (!Array.isArray(options.base)) {
              options.base = [options.base];
            }

            // Setup the proxy
            var middlewares = [
              require('grunt-connect-proxy/lib/utils').proxyRequest,
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];

            // Make directory browse-able.
            var directory = options.directory || options.base[options.base.length - 1];
            middlewares.push(connect.directory(directory));

            return middlewares;
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images']
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    // ngmin tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'fonts/*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer',
      'configureProxies',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'concurrent:test',
    'autoprefixer',
    'configureProxies',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);

  grunt.registerTask('heroku:production', 'build');

  grunt.loadNpmTasks('grunt-connect-proxy');
};
<|endoftext|>


<commit_before>/**
 * Created by tigran on 1/27/17.
 */

getDataTerminals();
const GET = 'GET';
const POST = 'POST';
var slugItem;
function addByBag(getId, state, slug){
    if(typeof slug=='undefined'){
        slug = slugItem
    }
//        console.log(slug);
    var id=0, count;
    if(state == 0){
        id = parseInt(getId.replace(/add_/g, ''));
    } else if (state == 1){
        id = parseInt(getId.replace(/remove_/g, ''));
    }

    var my_input = $('#used_count_'+id);
    my_input.css({'border': "2px inset"}).closest('.grid-column-buy_count').children('div.help-text').html('');
    if(state == 1){
        count = 0;
    }else {

        count = my_input.val();
    }
//            slug = $('#slug_'+id).val();
    var data = {'slug': slug, 'count':count};
    sendRequest(data, POST);
    $('#add_'+id).hide();
//        }
}

function updateData(getId, status){

    var id = parseInt(getId.replace(/used_count_/g, '')), slug, count;

    var my_input = $('#used_count_'+id);
    if(my_input.val()<=0 && status == 0){
        my_input.css({'border': "red solid 1px"}).closest('.grid-column-buy_count').children('div.help-text').html('Please add count.')
        $('#add_'+id).show();
    }else {
        var price = my_input.closest('tr').children('td.grid-column-price').text();
        count = my_input.val();
        var totl_itom = parseFloat(price) * count;
        if(status != 1){
            $('#add_'+id).show();
            my_input.css({'border': "2px inset"}).closest('.grid-column-buy_count').children('div.help-text').html(''+ totl_itom +'$');
        }else {
            my_input.css({'border': "2px inset"}).closest('.grid-column-buy_count').children('div.help-text').html('');
        }
    }
}

function writeOrder(orders){
    var unt;
    switch (orders.product.product_item.unit){
        case 0:
            unt = ' ct';
            break;
        case 1:
            unt = ' ml';
            break;
        case 2:
            unt = ' s ea';
            break;
        case 3:
            unt = ' gm';
            break;
        default:
            break;

    }

    slugItem = orders.product.slug;

    $('table.order>tbody').append('
 '+ orders.product.name +'	' +
        '' + orders.product.product_item.size + ' ' + unt +'	' +
        '' + orders.product.price +' $	'+
        '' + orders.count +' 	'+
        '' + orders.sub_total +' $	'+
        ' <button id="remove_' + orders.product.id +'" onclick="addByBag(this.id, 1)" class="btn btn-danger">' +
        '' +
        '</button>' +
        '	' +
        '
')

}
/**
 * This function use to get data
 */
function getDataTerminals() {

    jQuery.ajax({
        url: "/api/bag/my/bag",
        type: "GET",
        contentType: 'application/json; charset=utf-8',
        async: true,
        success: function (resultData) {
            var result = resultData, counts;
            var total = 0;

            $('table.order>tbody').html('');
            for (var i = 0; i < result.length; i++)
            {
                total += parseFloat(result[i].sub_total);
                $('#used_count_'+result[i].product.id).val(result[i].count);
                writeOrder(result[i]);
            }

            $('.total-count').html('Items Count  '+result.length);
            $('.total-price').html('Total price ' + total + ' $');
            $('.selected_infos').html('My Bag '+result.length+'')
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(jqXHR, textStatus, errorThrown);
        }
    });
}

/**
 *
 * @param data
 * @param method
 */
function sendRequest(data, method)
{
    jQuery.ajax({
        url: '/api/bags/datas',
        type: "POST",
        contentType: 'application/json; charset=utf-8',
        async: true,
        dataType:"json",

        data: JSON.stringify(data),
        success:function(ansvwe)
        {
            getDataTerminals();

        }
    });
}<commit_msg>fixes<commit_after>/**
 * Created by tigran on 1/27/17.
 */

getDataTerminals();
const GET = 'GET';
const POST = 'POST';
var slugItem;
function addByBag(getId, state, slug){
    if(typeof slug=='undefined'){
        slug = slugItem
    }
//        console.log(slug);
    var id=0, count;
    if(state == 0){
        id = parseInt(getId.replace(/add_/g, ''));
    } else if (state == 1){
        id = parseInt(getId.replace(/remove_/g, ''));
    }

    var my_input = $('#used_count_'+id);
    my_input.css({'border': "2px inset"}).closest('.grid-column-buy_count').children('div.help-text').html('');
    if(state == 1){
        count = 0;
    }else {

        count = my_input.val();
    }
//            slug = $('#slug_'+id).val();
    var data = {'slug': slug, 'count':count};
    sendRequest(data, POST);
    $('#add_'+id).hide();
//        }
}

function updateData(getId, status){

    var id = parseInt(getId.replace(/used_count_/g, '')), slug, count;

    var my_input = $('#used_count_'+id);
    if(my_input.val()<=0 && status == 0){
        my_input.css({'border': "red solid 1px"}).closest('.grid-column-buy_count').children('div.help-text').html('Please add count.')
        $('#add_'+id).show();
    }else {
        var price = my_input.closest('tr').children('td.grid-column-price').text();
        count = my_input.val();
        var totl_itom = parseFloat(price) * count;
        if(status != 1){
            $('#add_'+id).show();
            my_input.css({'border': "2px inset"}).closest('.grid-column-buy_count').children('div.help-text').html(''+ totl_itom +'$');
        }else {
            my_input.css({'border': "2px inset"}).closest('.grid-column-buy_count').children('div.help-text').html('');
        }
    }
}

function writeOrder(orders){
    var unt;
    switch (orders.product.product_item.unit){
        case 0:
            unt = ' ct';
            break;
        case 1:
            unt = ' ml';
            break;
        case 2:
            unt = ' s ea';
            break;
        case 3:
            unt = ' gm';
            break;
        default:
            break;

    }

    slugItem = orders.product.slug;

    $('table.order>tbody').append('
 '+ orders.product.name +'	' +
        '' + orders.product.product_item.size + ' ' + unt +'	' +
        '' + orders.product.price +' $	'+
        '' + orders.count +' 	'+
        '' + orders.sub_total +' $	'+
        ' <button id="remove_' + orders.product.id +'" onclick="addByBag(this.id, 1)" class="btn btn-danger">' +
        '' +
        '</button>' +
        '	' +
        '
')

}
/**
 * This function use to get data
 */
function getDataTerminals() {

    jQuery.ajax({
        url: "/api/bag/my/bag",
        type: "GET",
        contentType: 'application/json; charset=utf-8',
        async: true,
        success: function (resultData) {
            var result = resultData, counts;
            var total = 0;

            $('table.order>tbody').html('');
            for (var i = 0; i < result.length; i++)
            {
                total += parseFloat(result[i].sub_total);
                $('#used_count_'+result[i].product.id).val(result[i].count);
                writeOrder(result[i]);
            }

            $('.total-count').html('Items Count  '+result.length);
            $('.total-price').html('Total price ' + total + ' $');
            $('.selected_infos').html('My Bag '+result.length+'')
        },
        error: function (jqXHR, textStatus, errorThrown) {
            if(errorThrown==='Not Found'){
                $('table.order>tbody').html('');
            }
            console.log(jqXHR, textStatus, errorThrown);
        }
    });
}

/**
 *
 * @param data
 * @param method
 */
function sendRequest(data, method)
{
    jQuery.ajax({
        url: '/api/bags/datas',
        type: "POST",
        contentType: 'application/json; charset=utf-8',
        async: true,
        dataType:"json",

        data: JSON.stringify(data),
        success:function(ansvwe)
        {
            getDataTerminals();

        }
    });
}<|endoftext|>


<commit_before>var _ = require('lodash');

var Git  = require('../model/git'),
    view = require('../view/main');

var editor = require('./editor'),
    log    = require('./log'),
    diff   = require('./diff');

// model control
var git = new Git(__dirname);

var main = {
  git   : git,
  screen: view.screen,

  moveToStaged: function (index) {
    view.list.staged.interactive   = true;
    view.list.unstaged.interactive = false;
    view.list.staged.select(index !== undefined ? index : view.list.unstaged.selected);
    view.list.staged.focus();
    view.screen.render();
  },

  moveToUnstaged: function (index) {
    view.list.staged.interactive   = false;
    view.list.unstaged.interactive = true;
    view.list.unstaged.select(index !== undefined ? index : view.list.staged.selected);
    view.list.unstaged.focus();
    view.screen.render();
  },

  next: function () {
    this.move(1);
    view.screen.render();
  },

  // TODO: Fix crash if there is no item
  toggle: function () {
    var selected = git.isSelected(this.name, this.selected);

    if (selected) {
      git.deselect(this.name, this.selected);
      main.unmark.call(this);
    } else {
      git.select(this.name, this.selected);
      main.mark.call(this);
    }

    view.screen.render();
  },

  selectAll: function () {
    var type = view.list.staged.focused ? view.list.staged.name : view.list.unstaged.name;

    var selected = git.isSelected(type);

    if (selected) {
      git.deselect(type);
      main.setItems(git);
    } else {
      git.select(type);
      main.setItems(git);
    }

    view.screen.render();
  },

  lockScreen: function () {
    main.prevFocused = view.screen.focused;
  },

  unlockScreen: function () {
    if (main.prevFocused) {
      main.prevFocused.focus();
    }
  },

  show: function (controller) {
    if (_.isBoolean(controller) && controller === true) {
      main.reload();
      view.screen.render();
    } else if (_.isObject(controller)) {
      main.lockScreen();
      controller.show();
    } else {
      main.unlockScreen();
      view.screen.render();
    }
  },

  // initialize
  reload: function () {
    git.status();

    main.setItems();

    main.moveToUnstaged(0);

    view.loading.stop();

    view.screen.render();
  },

  // utility functions
  formatItem: function (selected, symbol, file) {
    var prefix = selected ? " * " : "   ";
    return prefix + symbol + " " + file;
  },

  buildItemListByType: function (type) {
    return _.reduce(git.files[type], function (result, val, index) {
      result.push(main.formatItem(git.selected[type][index], git.symbols[type][index], val));
      return result;
    }, []);
  },

  setItems: function () {
    view.list.staged.setItems(main.buildItemListByType('staged'));
    view.list.unstaged.setItems(main.buildItemListByType('unstaged'));
  },

  mark: function () {
    var selectedItem = this.getItem(this.selected);
    if (selectedItem === undefined) {
      return;
    }

    var content = selectedItem.content;
    this.setItem(this.selected, " * " + content.substr(3));
  },

  unmark: function () {
    var selectedItem = this.getItem(this.selected);
    if (selectedItem === undefined) {
      return;
    }

    var content = this.getItem(this.selected).content;
    this.setItem(this.selected, "   " + content.substr(3));
  }
};

// bind editor
editor.init(main);

// bind log viewer
log.init(main);

// bind diff viewer
diff.init(main);

// bind keys
// TODO: Need to refactor
_.each(view.list, function (elem) {
  elem.key(['space'], function () {
    main.toggle.call(this);
    main.next.call(this);
  });

  elem.key(['enter'], function () {
    main.selectAll();
  });

  elem.key(['escape', 'q'], function () {
    return process.exit(0);
  });

  // git commands
  elem.key(['C-a'], function () {
    git.add();
    main.reload();
  });

  elem.key(['C-r'], function () {
    git.reset();
    main.reload();
  });

  elem.key(['C-c'], function () {
    if (git.getStagedFiles().length < 1) {
      // TODO: alert
      return;
    }

    main.show(editor);
  });

  elem.key(['C-l'], function () {
    main.show(log);
  });

  //elem.unkey(['C-d']);

  elem.key(['C-d'], function () {
    main.show(diff);
  });

  elem.key(['left'], function () {
    main.moveToStaged();
  });

  elem.key(['right'], function () {
    main.moveToUnstaged();
  });
});

module.exports = main;

<commit_msg>Fix #21 crash on diff command<commit_after>var _ = require('lodash');

var Git  = require('../model/git'),
    view = require('../view/main');

var editor = require('./editor'),
    log    = require('./log'),
    diff   = require('./diff');

// model control
var git = new Git(__dirname);

var main = {
  git   : git,
  screen: view.screen,

  moveToStaged: function (index) {
    view.list.staged.interactive   = true;
    view.list.unstaged.interactive = false;
    view.list.staged.select(index !== undefined ? index : view.list.unstaged.selected);
    view.list.staged.focus();
    view.screen.render();
  },

  moveToUnstaged: function (index) {
    view.list.staged.interactive   = false;
    view.list.unstaged.interactive = true;
    view.list.unstaged.select(index !== undefined ? index : view.list.staged.selected);
    view.list.unstaged.focus();
    view.screen.render();
  },

  next: function () {
    this.move(1);
    view.screen.render();
  },

  // TODO: Fix crash if there is no item
  toggle: function () {
    var selected = git.isSelected(this.name, this.selected);

    if (selected) {
      git.deselect(this.name, this.selected);
      main.unmark.call(this);
    } else {
      git.select(this.name, this.selected);
      main.mark.call(this);
    }

    view.screen.render();
  },

  selectAll: function () {
    var type = view.list.staged.focused ? view.list.staged.name : view.list.unstaged.name;

    var selected = git.isSelected(type);

    if (selected) {
      git.deselect(type);
      main.setItems(git);
    } else {
      git.select(type);
      main.setItems(git);
    }

    view.screen.render();
  },

  lockScreen: function () {
    main.prevFocused = view.screen.focused;
  },

  unlockScreen: function () {
    if (main.prevFocused) {
      main.prevFocused.focus();
    }
  },

  show: function (controller) {
    if (_.isBoolean(controller) && controller === true) {
      main.reload();
      view.screen.render();
    } else if (_.isObject(controller)) {
      main.lockScreen();
      controller.show();
    } else {
      main.unlockScreen();
      view.screen.render();
    }
  },

  // initialize
  reload: function () {
    git.status();

    main.setItems();

    main.moveToUnstaged(0);

    view.loading.stop();

    view.screen.render();
  },

  // utility functions
  formatItem: function (selected, symbol, file) {
    var prefix = selected ? " * " : "   ";
    return prefix + symbol + " " + file;
  },

  buildItemListByType: function (type) {
    return _.reduce(git.files[type], function (result, val, index) {
      result.push(main.formatItem(git.selected[type][index], git.symbols[type][index], val));
      return result;
    }, []);
  },

  setItems: function () {
    view.list.staged.setItems(main.buildItemListByType('staged'));
    view.list.unstaged.setItems(main.buildItemListByType('unstaged'));
  },

  mark: function () {
    var selectedItem = this.getItem(this.selected);
    if (selectedItem === undefined) {
      return;
    }

    var content = selectedItem.content;
    this.setItem(this.selected, " * " + content.substr(3));
  },

  unmark: function () {
    var selectedItem = this.getItem(this.selected);
    if (selectedItem === undefined) {
      return;
    }

    var content = this.getItem(this.selected).content;
    this.setItem(this.selected, "   " + content.substr(3));
  }
};

// bind editor
editor.init(main);

// bind log viewer
log.init(main);

// bind diff viewer
diff.init(main);

// bind keys
// TODO: Need to refactor
_.each(view.list, function (elem) {
  elem.key(['space'], function () {
    main.toggle.call(this);
    main.next.call(this);
  });

  elem.key(['enter'], function () {
    main.selectAll();
  });

  elem.key(['escape', 'q'], function () {
    return process.exit(0);
  });

  // git commands
  elem.key(['C-a'], function () {
    git.add();
    main.reload();
  });

  elem.key(['C-r'], function () {
    git.reset();
    main.reload();
  });

  elem.key(['C-c'], function () {
    if (git.getStagedFiles().length < 1) {
      // TODO: alert
      return;
    }

    main.show(editor);
  });

  elem.key(['C-l'], function () {
    main.show(log);
  });

  //elem.unkey(['C-d']);

  elem.key(['C-d'], function () {
    if (this.getItem(this.selected) === undefined) {
      return;
    }

    main.show(diff);
  });

  elem.key(['left'], function () {
    main.moveToStaged();
  });

  elem.key(['right'], function () {
    main.moveToUnstaged();
  });
});

module.exports = main;

<|endoftext|>


<commit_before>var secrets = require('../config/secrets');
var User = require('../models/User');
var querystring = require('querystring');
var async = require('async');
var cheerio = require('cheerio');
var request = require('request');
var _ = require('underscore');
var graph = require('fbgraph');
var LastFmNode = require('lastfm').LastFmNode;
var tumblr = require('tumblr.js');
var foursquare = require('node-foursquare')({ secrets: secrets.foursquare });
var Github = require('github-api');
var Twit = require('twit');
var paypal = require('paypal-rest-sdk');

/**
 * GET /api
 * List of API examples.
 */

exports.getApi = function(req, res) {
  res.render('api/index', {
    title: 'API Browser'
  });
};

/**
 * GET /api/foursquare
 * Foursquare API example.
 */

exports.getFoursquare = function(req, res, next) {
  var token = _.findWhere(req.user.tokens, { kind: 'foursquare' });
  async.parallel({
    trendingVenues: function(callback) {
      foursquare.Venues.getTrending('40.7222756', '-74.0022724', { limit: 50 }, token.accessToken, function(err, results) {
        callback(err, results);
      });
    },
    venueDetail: function(callback) {
      foursquare.Venues.getVenue('49da74aef964a5208b5e1fe3', token.accessToken, function(err, results) {
        callback(err, results);
      });
    },
    userCheckins: function(callback) {
      foursquare.Users.getCheckins('self', null, token.accessToken, function(err, results) {
        callback(err, results);
      });
    }
  },
  function(err, results) {
    if (err) return next(err);
    res.render('api/foursquare', {
      title: 'Foursquare API',
      trendingVenues: results.trendingVenues,
      venueDetail: results.venueDetail,
      userCheckins: results.userCheckins
    });
  });
};

/**
 * GET /api/tumblr
 * Tumblr API example.
 */

exports.getTumblr = function(req, res) {
  var token = _.findWhere(req.user.tokens, { kind: 'tumblr' });
  var client = tumblr.createClient({
    consumer_key: secrets.tumblr.consumerKey,
    consumer_secret: secrets.tumblr.consumerSecret,
    token: token.accessToken,
    token_secret: token.tokenSecret
  });
  client.posts('goddess-of-imaginary-light.tumblr.com', { type: 'photo' }, function(err, data) {
    res.render('api/tumblr', {
      title: 'Tumblr API',
      blog: data.blog,
      photoset: data.posts[0].photos
    });
  });
};

/**
 * GET /api/facebook
 * Facebook API example.
 */

exports.getFacebook = function(req, res, next) {
  var token = _.findWhere(req.user.tokens, { kind: 'facebook' });
  graph.setAccessToken(token.accessToken);
  async.parallel({
    getMe: function(done) {
      graph.get(req.user.facebook, function(err, me) {
        done(err, me);
      });
    },
    getMyFriends: function(done) {
      graph.get(req.user.facebook + '/friends', function(err, friends) {
        done(err, friends.data);
      });
    }
  },
  function(err, results) {
    if (err) return next(err);
    res.render('api/facebook', {
      title: 'Facebook API',
      me: results.getMe,
      friends: results.getMyFriends
    });
  });
};

/**
 * GET /api/scraping
 * Web scraping example using Cheerio library.
 */

exports.getScraping = function(req, res, next) {
  request.get('https://news.ycombinator.com/', function(err, request, body) {
    if (err) return next(err);
    var $ = cheerio.load(body);
    var links = [];
    $('.title a').each(function() {
      links.push($(this));
    });
    res.render('api/scraping', {
      title: 'Web Scraping',
      links: links
    });
  });
};

/**
 * GET /api/github
 * GitHub API Example.
 */
exports.getGithub = function(req, res) {
  var token = _.findWhere(req.user.tokens, { kind: 'github' });
  var github = new Github({ token: token.accessToken });
  var repo = github.getRepo('sahat', 'requirejs-library');
  repo.show(function(err, repo) {
    res.render('api/github', {
      title: 'GitHub API',
      repo: repo
    });
  });

};

/**
 * GET /api/aviary
 * Aviary image processing example.
 */

exports.getAviary = function(req, res) {
  res.render('api/aviary', {
    title: 'Aviary API'
  });
};

/**
 * GET /api/nyt
 * New York Times API example.
 */

exports.getNewYorkTimes = function(req, res, next) {
  var query = querystring.stringify({ 'api-key': secrets.nyt.key, 'list-name': 'young-adult' });
  var url = 'http://api.nytimes.com/svc/books/v2/lists?' + query;
  request.get(url, function(error, request, body) {
    if (request.statusCode === 403) return next(Error('Missing or Invalid New York Times API Key'));
    var bestsellers = JSON.parse(body);
    res.render('api/nyt', {
      title: 'New York Times API',
      books: bestsellers.results
    });
  });
};

/**
 * GET /api/lastfm
 * Last.fm API example.
 */

exports.getLastfm = function(req, res, next) {
  var lastfm = new LastFmNode(secrets.lastfm);
  async.parallel({
    artistInfo: function(done) {
      lastfm.request("artist.getInfo", {
        artist: 'Epica',
        handlers: {
          success: function(data) {
            done(null, data);
          },
          error: function(err) {
            done(err);
          }
        }
      });
    },
    artistTopAlbums: function(done) {
      lastfm.request("artist.getTopAlbums", {
        artist: 'Epica',
        handlers: {
          success: function(data) {
            var albums = [];
            _.each(data.topalbums.album, function(album) {
              albums.push(album.image.slice(-1)[0]['#text']);
            });
            done(null, albums.slice(0,4));
          },
          error: function(err) {
            done(err);
          }
        }
      });
    }
  },
  function(err, results) {
    if (err) return next(err.message);
    var artist = {
      name: results.artistInfo.artist.name,
      image: results.artistInfo.artist.image.slice(-1)[0]['#text'],
      tags: results.artistInfo.artist.tags.tag,
      bio: results.artistInfo.artist.bio.summary,
      stats: results.artistInfo.artist.stats,
      similar: results.artistInfo.artist.similar.artist,
      topAlbums: results.artistTopAlbums
    };
    res.render('api/lastfm', {
      title: 'Last.fm API',
      artist: artist
    });
  });
};

/**
 * GET /api/twitter
 * Twiter API example.
 */

exports.getTwitter = function(req, res, next) {
  var token = _.findWhere(req.user.tokens, { kind: 'twitter' });
  var T = new Twit({
    consumer_key: secrets.twitter.consumerKey,
    consumer_secret: secrets.twitter.consumerSecret,
    access_token: token.accessToken,
    access_token_secret: token.tokenSecret
  });
  T.get('search/tweets', { q: 'hackathon since:2013-01-01', geocode: '40.71448,-74.00598,5mi', count: 50 }, function(err, reply) {
    if (err) return next(err);
    res.render('api/twitter', {
      title: 'Twitter API',
      tweets: reply.statuses
    });
  });
};

/**
 * GET /api/paypal
 * PayPal SDK example
 */

exports.getPayPal = function(req, res, next) {
  paypal.configure(secrets.paypal);
  var payment_details = {
    'intent': 'sale',
    'payer': {
      'payment_method': 'paypal'
    },
    'redirect_urls': {
      'return_url': secrets.paypal.returnUrl,
      'cancel_url': secrets.paypal.cancelUrl
    },
    'transactions': [{
      'description': 'Node.js Boilerplate',
      'amount': {
        'currency': 'USD',
        'total': '2.99'
      }
    }]
  };
  paypal.payment.create(payment_details, function (error, payment) {
    if(error){
      console.log(error);
    } else {
      req.session.payment_id = payment.id;
      var links = payment.links;
      for (var i = 0; i < links.length; i++) {
        if (links[i].rel === 'approval_url') {
          res.render('api/paypal', {
            approval_url: links[i].href
          });
        }
      }
    }
  });
};

/**
 * GET /api/paypal/success
 * PayPal SDK example
 */

exports.getPayPalSuccess = function(req, res, next) {
  var payment_id = req.session.payment_id;
  var payment_details = { 'payer_id': req.query.PayerID };
  paypal.payment.execute(payment_id, payment_details, function(error, payment){
    if(error){
      res.render('api/paypal', {
        result: true,
        success: false
      });
    } else {
      res.render('api/paypal', {
        result: true,
        success: true
      });
    }
  });
};

/**
 * GET /api/paypal/cancel
 * PayPal SDK example
 */

exports.getPayPalCancel = function(req, res, next) {
  req.session.payment_id = null;
  res.render('api/paypal', {
    result: true,
    canceled: true
  });
};

/**
 * GET /api/steam
 * Steam API example.
 */

exports.getSteam = function(req, res) {
  var defaultSteamId = '76561197992403307';
  var steamId = _.findWhere(req.user.tokens, { kind: 'steam' }).steamId || defaultSteamId;
  var query = { l: 'english', steamid: steamId, key: secrets.steam.apiKey };

  async.parallel([
    function (callback) {
      builtQuery = querystring.stringify(query);
      request.get({url:'http://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v0001/?' + builtQuery, json:true}, function(err, request, body) {
        if (err) return next(err);
        callback(null, body);
      });
    },
    function (callback) {
      query.appid = '570'; // Dota 2
      builtQuery = querystring.stringify(query);
      request.get({url:'http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?' + builtQuery, json:true}, function(err, request, body) {
        if (err) return next(err);
        delete query.appid;
        callback(null, body);
      });
    },
    function (callback) {
      query.appid = '219640'; //Chivalry: Medieval Warfare
      builtQuery = querystring.stringify(query);
      request.get({url:'http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?' + builtQuery, json:true}, function(err, request, body) {
        if (err) return next(err);
        delete query.appid;
        callback(null, body);
      });
    },
    function (callback) {
      delete query.steamid;
      query.steamids = steamId; //this request can be supplied a set of comma seperated steam ids
      builtQuery = querystring.stringify(query);
      request.get({url:'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?' + builtQuery, json:true}, function(err, request, body) {
        if (err) return next(err);
        callback(null, body);
      });
    },
  ],
  function (err, results) {
    console.log(require('util').inspect(results, false, null));
    if (err) return next(err);
    else res.render('api/steam', {
      title: 'Steam Web API',
      items: results });
  });
};<commit_msg>Steam API code refactoring, added ownedGames API call<commit_after>var secrets = require('../config/secrets');
var User = require('../models/User');
var querystring = require('querystring');
var async = require('async');
var cheerio = require('cheerio');
var request = require('request');
var _ = require('underscore');
var graph = require('fbgraph');
var LastFmNode = require('lastfm').LastFmNode;
var tumblr = require('tumblr.js');
var foursquare = require('node-foursquare')({ secrets: secrets.foursquare });
var Github = require('github-api');
var Twit = require('twit');
var paypal = require('paypal-rest-sdk');

/**
 * GET /api
 * List of API examples.
 */

exports.getApi = function(req, res) {
  res.render('api/index', {
    title: 'API Browser'
  });
};

/**
 * GET /api/foursquare
 * Foursquare API example.
 */

exports.getFoursquare = function(req, res, next) {
  var token = _.findWhere(req.user.tokens, { kind: 'foursquare' });
  async.parallel({
      trendingVenues: function(callback) {
        foursquare.Venues.getTrending('40.7222756', '-74.0022724', { limit: 50 }, token.accessToken, function(err, results) {
          callback(err, results);
        });
      },
      venueDetail: function(callback) {
        foursquare.Venues.getVenue('49da74aef964a5208b5e1fe3', token.accessToken, function(err, results) {
          callback(err, results);
        });
      },
      userCheckins: function(callback) {
        foursquare.Users.getCheckins('self', null, token.accessToken, function(err, results) {
          callback(err, results);
        });
      }
    },
    function(err, results) {
      if (err) return next(err);
      res.render('api/foursquare', {
        title: 'Foursquare API',
        trendingVenues: results.trendingVenues,
        venueDetail: results.venueDetail,
        userCheckins: results.userCheckins
      });
    });
};

/**
 * GET /api/tumblr
 * Tumblr API example.
 */

exports.getTumblr = function(req, res) {
  var token = _.findWhere(req.user.tokens, { kind: 'tumblr' });
  var client = tumblr.createClient({
    consumer_key: secrets.tumblr.consumerKey,
    consumer_secret: secrets.tumblr.consumerSecret,
    token: token.accessToken,
    token_secret: token.tokenSecret
  });
  client.posts('goddess-of-imaginary-light.tumblr.com', { type: 'photo' }, function(err, data) {
    res.render('api/tumblr', {
      title: 'Tumblr API',
      blog: data.blog,
      photoset: data.posts[0].photos
    });
  });
};

/**
 * GET /api/facebook
 * Facebook API example.
 */

exports.getFacebook = function(req, res, next) {
  var token = _.findWhere(req.user.tokens, { kind: 'facebook' });
  graph.setAccessToken(token.accessToken);
  async.parallel({
      getMe: function(done) {
        graph.get(req.user.facebook, function(err, me) {
          done(err, me);
        });
      },
      getMyFriends: function(done) {
        graph.get(req.user.facebook + '/friends', function(err, friends) {
          done(err, friends.data);
        });
      }
    },
    function(err, results) {
      if (err) return next(err);
      res.render('api/facebook', {
        title: 'Facebook API',
        me: results.getMe,
        friends: results.getMyFriends
      });
    });
};

/**
 * GET /api/scraping
 * Web scraping example using Cheerio library.
 */

exports.getScraping = function(req, res, next) {
  request.get('https://news.ycombinator.com/', function(err, request, body) {
    if (err) return next(err);
    var $ = cheerio.load(body);
    var links = [];
    $('.title a').each(function() {
      links.push($(this));
    });
    res.render('api/scraping', {
      title: 'Web Scraping',
      links: links
    });
  });
};

/**
 * GET /api/github
 * GitHub API Example.
 */
exports.getGithub = function(req, res) {
  var token = _.findWhere(req.user.tokens, { kind: 'github' });
  var github = new Github({ token: token.accessToken });
  var repo = github.getRepo('sahat', 'requirejs-library');
  repo.show(function(err, repo) {
    res.render('api/github', {
      title: 'GitHub API',
      repo: repo
    });
  });

};

/**
 * GET /api/aviary
 * Aviary image processing example.
 */

exports.getAviary = function(req, res) {
  res.render('api/aviary', {
    title: 'Aviary API'
  });
};

/**
 * GET /api/nyt
 * New York Times API example.
 */

exports.getNewYorkTimes = function(req, res, next) {
  var query = querystring.stringify({ 'api-key': secrets.nyt.key, 'list-name': 'young-adult' });
  var url = 'http://api.nytimes.com/svc/books/v2/lists?' + query;
  request.get(url, function(error, request, body) {
    if (request.statusCode === 403) return next(Error('Missing or Invalid New York Times API Key'));
    var bestsellers = JSON.parse(body);
    res.render('api/nyt', {
      title: 'New York Times API',
      books: bestsellers.results
    });
  });
};

/**
 * GET /api/lastfm
 * Last.fm API example.
 */

exports.getLastfm = function(req, res, next) {
  var lastfm = new LastFmNode(secrets.lastfm);
  async.parallel({
      artistInfo: function(done) {
        lastfm.request("artist.getInfo", {
          artist: 'Epica',
          handlers: {
            success: function(data) {
              done(null, data);
            },
            error: function(err) {
              done(err);
            }
          }
        });
      },
      artistTopAlbums: function(done) {
        lastfm.request("artist.getTopAlbums", {
          artist: 'Epica',
          handlers: {
            success: function(data) {
              var albums = [];
              _.each(data.topalbums.album, function(album) {
                albums.push(album.image.slice(-1)[0]['#text']);
              });
              done(null, albums.slice(0, 4));
            },
            error: function(err) {
              done(err);
            }
          }
        });
      }
    },
    function(err, results) {
      if (err) return next(err.message);
      var artist = {
        name: results.artistInfo.artist.name,
        image: results.artistInfo.artist.image.slice(-1)[0]['#text'],
        tags: results.artistInfo.artist.tags.tag,
        bio: results.artistInfo.artist.bio.summary,
        stats: results.artistInfo.artist.stats,
        similar: results.artistInfo.artist.similar.artist,
        topAlbums: results.artistTopAlbums
      };
      res.render('api/lastfm', {
        title: 'Last.fm API',
        artist: artist
      });
    });
};

/**
 * GET /api/twitter
 * Twiter API example.
 */

exports.getTwitter = function(req, res, next) {
  var token = _.findWhere(req.user.tokens, { kind: 'twitter' });
  var T = new Twit({
    consumer_key: secrets.twitter.consumerKey,
    consumer_secret: secrets.twitter.consumerSecret,
    access_token: token.accessToken,
    access_token_secret: token.tokenSecret
  });
  T.get('search/tweets', { q: 'hackathon since:2013-01-01', geocode: '40.71448,-74.00598,5mi', count: 50 }, function(err, reply) {
    if (err) return next(err);
    res.render('api/twitter', {
      title: 'Twitter API',
      tweets: reply.statuses
    });
  });
};

/**
 * GET /api/paypal
 * PayPal SDK example.
 */

exports.getPayPal = function(req, res, next) {
  paypal.configure(secrets.paypal);
  var payment_details = {
    'intent': 'sale',
    'payer': {
      'payment_method': 'paypal'
    },
    'redirect_urls': {
      'return_url': secrets.paypal.returnUrl,
      'cancel_url': secrets.paypal.cancelUrl
    },
    'transactions': [
      {
        'description': 'Node.js Boilerplate',
        'amount': {
          'currency': 'USD',
          'total': '2.99'
        }
      }
    ]
  };
  paypal.payment.create(payment_details, function(error, payment) {
    if (error) {
      console.log(error);
    } else {
      req.session.payment_id = payment.id;
      var links = payment.links;
      for (var i = 0; i < links.length; i++) {
        if (links[i].rel === 'approval_url') {
          res.render('api/paypal', {
            approval_url: links[i].href
          });
        }
      }
    }
  });
};

/**
 * GET /api/paypal/success
 * PayPal SDK example.
 */

exports.getPayPalSuccess = function(req, res, next) {
  var payment_id = req.session.payment_id;
  var payment_details = { 'payer_id': req.query.PayerID };
  paypal.payment.execute(payment_id, payment_details, function(error, payment) {
    if (error) {
      res.render('api/paypal', {
        result: true,
        success: false
      });
    } else {
      res.render('api/paypal', {
        result: true,
        success: true
      });
    }
  });
};

/**
 * GET /api/paypal/cancel
 * PayPal SDK example.
 */

exports.getPayPalCancel = function(req, res, next) {
  req.session.payment_id = null;
  res.render('api/paypal', {
    result: true,
    canceled: true
  });
};

/**
 * GET /api/steam
 * Steam API example.
 */

exports.getSteam = function(req, res) {
  var steamId = '76561197982488301';
  var query = { l: 'english', steamid: steamId, key: secrets.steam.apiKey };

  async.parallel({
    playerAchievements: function(done) {
      query.appid = '49520';
      var qs = querystring.stringify(query);
      request.get({ url: 'http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?' + qs, json: true }, function(error, request, body) {
        done(error, body.playerstats);
      });
    },
    playerSummaries: function(done) {
      query.steamids = steamId;
      var qs = querystring.stringify(query);
      request.get({ url: 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?' + qs, json: true }, function(error, request, body) {
        done(error, body);
      });
    },
    ownedGames: function(done) {
      var qs = querystring.stringify(query);
      request.get({ url: 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?' + qs, json: true }, function(error, request, body) {
        done(error, body);
      });
    }
  },
  function(err, results) {
    if (err) return next(err);
    console.log(results.ownedGames);
    console.log(results.playerSummaries);
    res.render('api/steam', {
      title: 'Steam Web API',
      ownedGames: results.ownedGames,
      playerAchievemments: results.playerAchievements,
      playerSummaries: results.playerSummaries
    });
  });
};<|endoftext|>


<commit_before>/*
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

var assert = require('chai').assert;
var sinon = require('sinon');

var eventEmitter = require('minimal-event-emitter');
var inherits = require('../../src/util/inherits');

var Stage = require('../../src/stages/Stage');

// Stage is an abstract class and cannot be instantiated directly.
// We must stub methods and properties expected to be implemented by subclasses.
function TestStage() {
  this.constructor.super_.call(this);
  this.validateLayer = sinon.stub();
  this.setSizeForType = sinon.spy();
  this.createRenderer = function() {};
  this.destroyRenderer = function() {};
  this.registerRenderer('fake', 'fake', function() {});
}

inherits(TestStage, Stage);

// Mock layer.
var nextId = 0;
function MockLayer() {
  this.geometry = function() { return {type: 'fake'} };
  this.view = function() { return {type: 'fake'} };
}

eventEmitter(MockLayer);

suite('Stage', function() {

  test('manages the layer stack correctly', function() {
    var stage = new TestStage();

    var layer1 = new MockLayer();
    var layer2 = new MockLayer();
    var layer3 = new MockLayer();

    assert.isFalse(stage.hasLayer(layer1));
    assert.sameOrderedMembers([], stage.listLayers());
    assert.throws(function() { stage.addLayer(layer1, 1); });
    assert.throws(function() { stage.moveLayer(layer1, 1); });
    assert.throws(function() { stage.removeLayer(layer1); });

    stage.addLayer(layer1);
    assert.isTrue(stage.hasLayer(layer1));
    assert.sameOrderedMembers([layer1], stage.listLayers());

    stage.addLayer(layer2, 1);
    assert.isTrue(stage.hasLayer(layer2));
    assert.sameOrderedMembers([layer1, layer2], stage.listLayers());

    assert.throws(function() { stage.addLayer(layer3, -1); });
    assert.throws(function() { stage.addLayer(layer3, 3); });

    stage.addLayer(layer3, 1);
    assert.isTrue(stage.hasLayer(layer3));
    assert.sameOrderedMembers([layer1, layer3, layer2], stage.listLayers());

    assert.throws(function() { stage.moveLayer(layer1, -1); });
    assert.throws(function() { stage.moveLayer(layer1, 3); });

    stage.moveLayer(layer1, 2);
    assert.isTrue(stage.hasLayer(layer1));
    assert.sameOrderedMembers([layer3, layer2, layer1], stage.listLayers());

    stage.removeLayer(layer2);
    assert.isFalse(stage.hasLayer(layer2));
    assert.sameOrderedMembers([layer3, layer1], stage.listLayers());

    stage.removeLayer(layer1);
    assert.isFalse(stage.hasLayer(layer1));
    assert.sameOrderedMembers([layer3], stage.listLayers());
  });

  test('throws if layer validation fails', function() {
    var stage = new TestStage();
    var layer = new MockLayer();

    stage.validateLayer.throws();
    assert.throws(function() { stage.addLayer(layer); });
  });

  test('emits invalidation event', function() {
    var stage = new TestStage();
    var layer = new MockLayer();

    var spy = sinon.spy();
    stage.addEventListener('renderInvalid', spy);

    stage.addLayer(layer);
    assert.equal(spy.callCount, 1);

    layer.emit('viewChange');
    layer.emit('effectsChange');
    layer.emit('fixedLevelChange');
    layer.emit('textureStoreChange');
    assert.equal(spy.callCount, 5);

    stage.moveLayer(layer, 0);
    assert.equal(spy.callCount, 6);

    stage.removeLayer(layer);
    assert.equal(spy.callCount, 7);

    layer.emit('viewChange');
    layer.emit('effectsChange');
    layer.emit('fixedLevelChange');
    layer.emit('textureStoreChange');
    assert.equal(spy.callCount, 7);
  });

  test('size', function() {
    var stage = new TestStage();

    var size = {};

    assert.strictEqual(size, stage.size(size));
    assert.equal(size.width, 0);
    assert.equal(size.height, 0);

    stage.setSize({width: 200, height: 100});
    assert.isTrue(stage.setSizeForType.called);

    size = stage.size();
    assert.equal(size.width, 200);
    assert.equal(size.height, 100);
  });
});
<commit_msg>Add tests for Stage#render.<commit_after>/*
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

var assert = require('chai').assert;
var sinon = require('sinon');
sinon.assert.expose(assert, {prefix: ''});

var eventEmitter = require('minimal-event-emitter');
var inherits = require('../../src/util/inherits');

var Stage = require('../../src/stages/Stage');

var CubeGeometry = require('../../src/geometries/Cube');
var CubeTile = CubeGeometry.TileClass;
var EquirectGeometry = require('../../src/geometries/Equirect');
var EquirectTile = EquirectGeometry.TileClass;

// Stage is an abstract class and cannot be instantiated directly.
// We must stub methods and properties expected to be implemented by subclasses.
function TestStage() {
  var renderers = [].slice.apply(arguments);
  var nextRendererIndex = 0;
  this.constructor.super_.call(this);
  this.validateLayer = sinon.stub();
  this.setSizeForType = sinon.stub();
  this.startFrame = sinon.stub();
  this.endFrame = sinon.stub();
  this.createRenderer = function() { return renderers[nextRendererIndex++]; };
  this.destroyRenderer = sinon.stub();
  this.registerRenderer('fake', 'fake', function() {});
}

inherits(TestStage, Stage);

function MockLayer(mockTextureStore) {
  this.geometry = sinon.stub().returns(new MockGeometry());
  this.view = sinon.stub().returns(new MockView());
  this.effects = sinon.stub().returns({});
  this.visibleTiles = sinon.stub();
  this.textureStore = function() {
    return mockTextureStore;
  };
}

eventEmitter(MockLayer);

function MockView() {
  this.type = 'fake';
  this.setSize = sinon.stub();
}

function MockGeometry() {
  this.type = 'fake';
}

function MockRenderer() {
  this.startLayer = sinon.stub();
  this.renderTile = sinon.stub();
  this.endLayer = sinon.stub();
}

function MockTextureStore() {
  this.texture = sinon.stub();
  this.startFrame = sinon.stub();
  this.markTile = sinon.stub();
  this.endFrame = sinon.stub();
}

suite('Stage', function() {

  test('manages the layer stack correctly', function() {
    var stage = new TestStage();

    var layer1 = new MockLayer();
    var layer2 = new MockLayer();
    var layer3 = new MockLayer();

    assert.isFalse(stage.hasLayer(layer1));
    assert.sameOrderedMembers([], stage.listLayers());
    assert.throws(function() { stage.addLayer(layer1, 1); });
    assert.throws(function() { stage.moveLayer(layer1, 1); });
    assert.throws(function() { stage.removeLayer(layer1); });

    stage.addLayer(layer1);
    assert.isTrue(stage.hasLayer(layer1));
    assert.sameOrderedMembers([layer1], stage.listLayers());

    stage.addLayer(layer2, 1);
    assert.isTrue(stage.hasLayer(layer2));
    assert.sameOrderedMembers([layer1, layer2], stage.listLayers());

    assert.throws(function() { stage.addLayer(layer3, -1); });
    assert.throws(function() { stage.addLayer(layer3, 3); });

    stage.addLayer(layer3, 1);
    assert.isTrue(stage.hasLayer(layer3));
    assert.sameOrderedMembers([layer1, layer3, layer2], stage.listLayers());

    assert.throws(function() { stage.moveLayer(layer1, -1); });
    assert.throws(function() { stage.moveLayer(layer1, 3); });

    stage.moveLayer(layer1, 2);
    assert.isTrue(stage.hasLayer(layer1));
    assert.sameOrderedMembers([layer3, layer2, layer1], stage.listLayers());

    stage.removeLayer(layer2);
    assert.isFalse(stage.hasLayer(layer2));
    assert.sameOrderedMembers([layer3, layer1], stage.listLayers());

    stage.removeLayer(layer1);
    assert.isFalse(stage.hasLayer(layer1));
    assert.sameOrderedMembers([layer3], stage.listLayers());
  });

  test('throws if layer validation fails', function() {
    var stage = new TestStage();
    var layer = new MockLayer();

    stage.validateLayer.throws();
    assert.throws(function() { stage.addLayer(layer); });
  });

  test('emits invalidation event', function() {
    var stage = new TestStage();
    var layer = new MockLayer();

    var spy = sinon.spy();
    stage.addEventListener('renderInvalid', spy);

    stage.addLayer(layer);
    assert.equal(spy.callCount, 1);

    layer.emit('viewChange');
    layer.emit('effectsChange');
    layer.emit('fixedLevelChange');
    layer.emit('textureStoreChange');
    assert.equal(spy.callCount, 5);

    stage.moveLayer(layer, 0);
    assert.equal(spy.callCount, 6);

    stage.removeLayer(layer);
    assert.equal(spy.callCount, 7);

    layer.emit('viewChange');
    layer.emit('effectsChange');
    layer.emit('fixedLevelChange');
    layer.emit('textureStoreChange');
    assert.equal(spy.callCount, 7);
  });

  test('gets and sets size', function() {
    var stage = new TestStage();

    var size = {};

    assert.strictEqual(size, stage.size(size));
    assert.equal(size.width, 0);
    assert.equal(size.height, 0);

    stage.setSize({width: 200, height: 100});
    assert.isTrue(stage.setSizeForType.called);

    size = stage.size();
    assert.equal(size.width, 200);
    assert.equal(size.height, 100);
  });

  test('renders a single layer', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var tile = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture = {};
    var store = new MockTextureStore();
    store.texture.withArgs(tile).returns(texture);
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(tile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.callOrder(
      stage.startFrame,
      renderer.startLayer,
      renderer.renderTile,
      renderer.endLayer,
      stage.endFrame);

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, tile, texture, layer, 1);

    assert.calledOnce(store.markTile);
    assert.calledWith(store.markTile, tile);
    assert.callOrder(store.startFrame, store.markTile, store.endFrame);
  });

  test('renders multiple layers', function() {
    var renderer1 = new MockRenderer();
    var renderer2 = new MockRenderer();
    var stage = new TestStage(renderer1, renderer2);

    var tile1 = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture1 = {};
    var store1 = new MockTextureStore();
    store1.texture.withArgs(tile1).returns(texture1);
    var layer1 = new MockLayer(store1);
    layer1.visibleTiles.callsFake(function(result) {
      result.push(tile1);
    });

    var tile2 = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture2 = {};
    var store2 = new MockTextureStore();
    store2.texture.withArgs(tile2).returns(texture2);
    var layer2 = new MockLayer(store2);
    layer2.visibleTiles.callsFake(function(result) {
      result.push(tile2);
    });

    stage.addLayer(layer1);
    stage.addLayer(layer2);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.callOrder(
      stage.startFrame,
      renderer1.startLayer,
      renderer1.renderTile,
      renderer1.endLayer,
      renderer2.startLayer,
      renderer2.renderTile,
      renderer2.endLayer,
      stage.endFrame);

    assert.calledOnce(stage.startFrame);
    assert.calledOnce(stage.endFrame);

    assert.calledOnce(renderer1.startLayer);
    assert.calledOnce(renderer1.endLayer);
    assert.calledOnce(renderer1.renderTile);
    assert.calledWith(renderer1.renderTile, tile1, texture1, layer1, 2);

    assert.calledOnce(renderer2.startLayer);
    assert.calledOnce(renderer2.endLayer);
    assert.calledOnce(renderer2.renderTile);
    assert.calledWith(renderer2.renderTile, tile2, texture2, layer2, 1);

    assert.calledOnce(store1.markTile);
    assert.calledWith(store1.markTile, tile1);
    assert.callOrder(store1.startFrame, store1.markTile, store1.endFrame);

    assert.calledOnce(store2.markTile);
    assert.calledWith(store2.markTile, tile2);
    assert.callOrder(store2.startFrame, store2.markTile, store2.endFrame);
  });

  test('renders multiple layers with the same renderer', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer, renderer);

    var tile1 = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture1 = {};
    var store1 = new MockTextureStore();
    store1.texture.withArgs(tile1).returns(texture1);
    var layer1 = new MockLayer(store1);
    layer1.visibleTiles.callsFake(function(result) {
      result.push(tile1);
    });

    var tile2 = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture2 = {};
    var store2 = new MockTextureStore();
    store2.texture.withArgs(tile2).returns(texture2);
    var layer2 = new MockLayer(store2);
    layer2.visibleTiles.callsFake(function(result) {
      result.push(tile2);
    });

    stage.addLayer(layer1);
    stage.addLayer(layer2);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.callOrder(
      stage.startFrame,
      renderer.startLayer,
      renderer.renderTile,
      renderer.endLayer,
      stage.endFrame);

    assert.calledOnce(stage.startFrame);
    assert.calledOnce(stage.endFrame);

    assert.calledTwice(renderer.startLayer);
    assert.calledTwice(renderer.endLayer);
    assert.calledTwice(renderer.renderTile);
    assert.calledWith(renderer.renderTile, tile1, texture1, layer1, 2);
    assert.calledWith(renderer.renderTile, tile2, texture2, layer2, 1);

    assert.calledOnce(store1.markTile);
    assert.calledWith(store1.markTile, tile1);
    assert.callOrder(store1.startFrame, store1.markTile, store1.endFrame);

    assert.calledOnce(store2.markTile);
    assert.calledWith(store2.markTile, tile2);
    assert.callOrder(store2.startFrame, store2.markTile, store2.endFrame);
  });

  test('renders multiple layers with the same texture store', function() {
    var renderer1 = new MockRenderer();
    var renderer2 = new MockRenderer();
    var stage = new TestStage(renderer1, renderer2);

    var store = new MockTextureStore();

    var tile1 = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture1 = {};
    store.texture.withArgs(tile1).returns(texture1);
    var layer1 = new MockLayer(store);
    layer1.visibleTiles.callsFake(function(result) {
      result.push(tile1);
    });

    var tile2 = new EquirectTile(0, new EquirectGeometry([{ width: 1 }]));
    var texture2 = {};
    store.texture.withArgs(tile2).returns(texture2);
    var layer2 = new MockLayer(store);
    layer2.visibleTiles.callsFake(function(result) {
      result.push(tile2);
    });

    stage.addLayer(layer1);
    stage.addLayer(layer2);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledTwice(store.startFrame);
    assert.calledTwice(store.endFrame);
    assert.calledTwice(store.markTile);
    assert.calledWith(store.markTile, tile1);
    assert.calledWith(store.markTile, tile2);
    assert.callOrder(store.startFrame, store.markTile, store.endFrame);
  });

  test('falls back to a parent tile', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 }
    ]);
    var visibleTile = new CubeTile('f', 0, 0, 2, geometry);
    var parentTile = new CubeTile('f', 0, 0, 1, geometry);
    var store = new MockTextureStore();
    store.texture.returns(null).withArgs(parentTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, parentTile);

    assert.calledTwice(store.markTile);
    assert.calledWith(store.markTile, visibleTile);
    assert.calledWith(store.markTile, parentTile);
  });

  test('falls back to a grandparent tile', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 }
    ]);
    var visibleTile = new CubeTile('f', 0, 0, 2, geometry);
    var grandparentTile = new CubeTile('f', 0, 0, 0, geometry);
    var store = new MockTextureStore();
    store.texture.returns(null).withArgs(grandparentTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, grandparentTile);

    assert.calledTwice(store.markTile);
    assert.calledWith(store.markTile, visibleTile);
    assert.calledWith(store.markTile, grandparentTile);
  });

  test('falls back to children tiles', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 }
    ]);
    var visibleTile = new CubeTile('f', 0, 0, 1, geometry);
    var parentTile = new CubeTile('f', 0, 0, 0, geometry);
    var childTile1 = new CubeTile('f', 0, 0, 2, geometry);
    var childTile2 = new CubeTile('f', 0, 1, 2, geometry);
    var childTile3 = new CubeTile('f', 1, 0, 2, geometry);
    var childTile4 = new CubeTile('f', 1, 1, 2, geometry);
    var store = new MockTextureStore();
    store.texture
      .returns(null)
      .withArgs(parentTile).returns({})
      .withArgs(childTile1).returns({})
      .withArgs(childTile2).returns({})
      .withArgs(childTile3).returns({})
      .withArgs(childTile4).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.callCount(renderer.renderTile, 4);
    assert.calledWith(renderer.renderTile, childTile1);
    assert.calledWith(renderer.renderTile, childTile2);
    assert.calledWith(renderer.renderTile, childTile3);
    assert.calledWith(renderer.renderTile, childTile4);

    assert.callCount(store.markTile, 5);
    assert.calledWith(store.markTile, visibleTile);
    assert.calledWith(store.markTile, childTile1);
    assert.calledWith(store.markTile, childTile2);
    assert.calledWith(store.markTile, childTile3);
    assert.calledWith(store.markTile, childTile4);
  });

  test('falls back to both children and parent tiles', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 }
    ]);
    var visibleTile = new CubeTile('f', 0, 0, 1, geometry);
    var parentTile = new CubeTile('f', 0, 0, 0, geometry);
    var childTile1 = new CubeTile('f', 0, 0, 2, geometry);
    var childTile2 = new CubeTile('f', 0, 1, 2, geometry);
    var childTile3 = new CubeTile('f', 1, 0, 2, geometry);
    var store = new MockTextureStore();
    store.texture
      .returns(null)
      .withArgs(parentTile).returns({})
      .withArgs(childTile1).returns({})
      .withArgs(childTile2).returns({})
      .withArgs(childTile3).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.callCount(renderer.renderTile, 4);
    assert.calledWith(renderer.renderTile, childTile1);
    assert.calledWith(renderer.renderTile, childTile2);
    assert.calledWith(renderer.renderTile, childTile3);
    assert.calledWith(renderer.renderTile, parentTile);

    assert.callCount(store.markTile, 5);
    assert.calledWith(store.markTile, visibleTile);
    assert.calledWith(store.markTile, childTile1);
    assert.calledWith(store.markTile, childTile2);
    assert.calledWith(store.markTile, childTile3);
    assert.calledWith(store.markTile, parentTile);
  });

  test('falls back to grandchildren tiles on trivial geometries', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new EquirectGeometry([
      { width: 512 },
      { width: 1024 },
      { width: 2048 }
    ]);
    var visibleTile = new EquirectTile(0, geometry);
    var grandchildTile = new EquirectTile(2, geometry);
    var store = new MockTextureStore();
    store.texture
      .returns(null)
      .withArgs(grandchildTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, grandchildTile);

    assert.calledTwice(store.markTile);
    assert.calledWith(store.markTile, visibleTile);
    assert.calledWith(store.markTile, grandchildTile);
  });

  test('does not fall back to grandchildren tiles on nontrivial geometries', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 },
      { tileSize: 512, size: 4096 },
    ]);
    var visibleTile = new CubeTile('f', 0, 0, 1, geometry);
    var parentTile = new CubeTile('f', 0, 0, 0, geometry);
    var grandchildTile = new CubeTile('f', 0, 0, 3, geometry);
    var store = new MockTextureStore();
    store.texture
      .returns(null)
      .withArgs(parentTile).returns({})
      .withArgs(grandchildTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, parentTile);

    assert.calledTwice(store.markTile);
    assert.calledWith(store.markTile, visibleTile);
    assert.calledWith(store.markTile, parentTile);
  });

  test('does not render a fallback tile more than once', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 }
    ]);
    var visibleTile1 = new CubeTile('f', 0, 0, 2, geometry);
    var visibleTile2 = new CubeTile('f', 1, 1, 2, geometry);
    var parentTile = new CubeTile('f', 0, 0, 1, geometry);
    var store = new MockTextureStore();
    store.texture.returns(null).withArgs(parentTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile1, visibleTile2);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, parentTile);

    assert.calledThrice(store.markTile);
    assert.calledWith(store.markTile, visibleTile1);
    assert.calledWith(store.markTile, visibleTile2);
    assert.calledWith(store.markTile, parentTile);
  });

  test('does not fall back when unnecessary', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 }
    ]);
    var visibleTile = new CubeTile('f', 0, 0, 1, geometry);
    var parentTile = new CubeTile('f', 0, 0, 0, geometry);
    var childTile = new CubeTile('f', 0, 0, 2, geometry);
    var store = new MockTextureStore();
    store.texture
        .returns(null)
        .withArgs(visibleTile).returns({})
        .withArgs(parentTile).returns({})
        .withArgs(childTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.calledOnce(renderer.renderTile);
    assert.calledWith(renderer.renderTile, visibleTile);

    assert.calledOnce(store.markTile);
    assert.calledWith(store.markTile, visibleTile);
  });

  test('renders fallbacks in the right order', function() {
    var renderer = new MockRenderer();
    var stage = new TestStage(renderer);

    var geometry = new CubeGeometry([
      { tileSize: 512, size: 512 },
      { tileSize: 512, size: 1024 },
      { tileSize: 512, size: 2048 },
      { tileSize: 512, size: 4096 },
    ]);
    // `visibleTile1` falls back to child and parent.
    // `visibleTile2` does not need a fallback.
    // `visibleTile3` falls back to grandparent.
    var visibleTile1 = new CubeTile('f', 0, 0, 2, geometry);
    var visibleTile2 = new CubeTile('f', 0, 1, 2, geometry);
    var visibleTile3 = new CubeTile('f', 0, 2, 2, geometry);
    var grandparentTile = new CubeTile('f', 0, 0, 0, geometry);
    var parentTile = new CubeTile('f', 0, 0, 1, geometry);
    var childTile = new CubeTile('f', 0, 0, 3, geometry);
    var store = new MockTextureStore();
    store.texture
      .returns(null)
      .withArgs(visibleTile2).returns({})
      .withArgs(grandparentTile).returns({})
      .withArgs(parentTile).returns({})
      .withArgs(childTile).returns({});
    var layer = new MockLayer(store);
    layer.visibleTiles.callsFake(function(result) {
      result.push(visibleTile1, visibleTile2, visibleTile3);
    });

    stage.addLayer(layer);
    stage.setSize({width: 100, height: 100});
    stage.render();

    assert.callCount(renderer.renderTile, 4);
    assert.calledWith(renderer.renderTile.getCall(0), visibleTile2);
    assert.calledWith(renderer.renderTile.getCall(1), childTile);
    assert.calledWith(renderer.renderTile.getCall(2), parentTile);
    assert.calledWith(renderer.renderTile.getCall(3), grandparentTile);
  });
});
<|endoftext|>