<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
      '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
      '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
      '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
      ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
    // Task configuration.
    concat: {
      options: {
        banner: '<%= banner %>',
        stripBanners: true
      },
      dist: {
        src: ['lib/<%= pkg.name %>.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      dist: {
        src: '<%= concat.dist.dest %>',
        dest: 'dist/<%= pkg.name %>.min.js'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: true,
        boss: true,
        eqnull: true,
        smarttabs: true,
        globals: {}
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      lib_test: {
        src: ['lib/**/*.js', 'test/**/*.js']
      }
    },
    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      },
    },
    karma: {
      unit: {
        configFile: 'karma.config.js',
        singleRun: true
      }
    },
    copy: {
      build: {
        cwd: 'src',
        src: ['**'],
        dest: 'dist',
        expand: true
      },
    },
    clean: {
      build: {
        src: ['dist']
      },
    },
    uglify: {
      build: {
        options: {
          mangle: false
        },
        files: {
          'dist/token.min.js': ['dist/**/*.js']
        },
      },
    },
    ngmin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'dist',
          src: '*.js',
          dest: 'dist'
        }]
      }
    },
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-ngmin');

  // Default task.
  grunt.registerTask('default', ['jshint', 'karma', 'concat', 'uglify']);

  grunt.registerTask('build', [
    'clean',
    'copy',
    'ngmin',
    'uglify',
  ]);

};
<commit_msg>Concat files for distribution<commit_after>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
      '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
      '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
      '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
      ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
    // Task configuration.
    concat: {
      options: {
        banner: '<%= banner %>',
        stripBanners: true
      },
      dist: {
        src: ['src/**/*.js'],
        //dest: 'dist/token.js',
        //src: ['lib/<%= pkg.name %>.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      dist: {
        src: '<%= concat.dist.dest %>',
        dest: 'dist/<%= pkg.name %>.min.js'
      }
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: true,
        boss: true,
        eqnull: true,
        smarttabs: true,
        globals: {}
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      lib_test: {
        src: ['lib/**/*.js', 'test/**/*.js']
      }
    },
    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      },
    },
    karma: {
      unit: {
        configFile: 'karma.config.js',
        singleRun: true
      }
    },
    copy: {
      build: {
        cwd: 'src',
        src: ['*.html'],
        dest: 'dist',
        expand: true
      },
    },
    clean: {
      build: {
        src: ['dist']
      },
    },
//    uglify: {
//      build: {
//        options: {
//          mangle: false
//        },
//        files: {
//          'dist/token.min.js': ['dist/**/*.js']
//        },
//      },
//    },
    ngmin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'dist',
          src: '*.js',
          dest: 'dist'
        }]
      }
    },
//    concat: {
//      options: {
//        separator: ';'
//      },
//      dist: {
//        src: ['src/**/*.js'],
//        dest: 'dist/token.js',
//      },
//    },
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-ngmin');

  // Default task.
  grunt.registerTask('default', ['jshint', 'karma', 'build']);

  grunt.registerTask('build', [
    'clean',
    'copy',
    'concat',
    'ngmin',
    'uglify',
  ]);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  'use strict';

  require('time-grunt')(grunt);

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // define variables for Gruntfile
    config: {
      src:              'src',
      dist:             'dist',
      appFolder:        'app',
      componentsFolder: 'app/components',
      jsFolder:         'app/js',
      cssFolder:        'app/css',
      imgFolder:        'app/img',
      dataFolder:       'app/data',
      cssMainFile:      'styles',
      jsMainFile:       'scripts'
    },

    // run jshint against all javascripts, including Gruntfile
    jshint: {
      files: ['Gruntfile.js', '<%= config.src %>/<%= config.jsFolder %>/*.js']
    },

    // copy assets into root of destination
    copy: {
      data: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.dataFolder %>',
            src: '**',
            dest: '<%= config.dist %>/<%= config.dataFolder %>',
          }
        ]
      },

      img: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.imgFolder %>',
            src: '**',
            dest: '<%= config.dist %>/<%= config.imgFolder %>',
          }
        ]
      },

      js: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.jsFolder %>',
            src: '**/*.js',
            dest: '<%= config.dist %>/<%= config.jsFolder %>',
          }
        ]
      },

      src: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/',
            src: '*',
            dest: '<%= config.dist %>/',
            dot: true
          }
        ]
      },

      // copy bower components as well
      components: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.componentsFolder %>',
            src: '**',
            dest: '<%= config.dist %>/<%= config.componentsFolder %>',
            dot: true
          }
        ]
      }
    },

    // clean out destination folder by brute force
    clean: {
      main: ['<%= config.dist %>/**/*', '<%= config.dist %>/.htaccess', '<%= config.src %>/assemble/<%= config.dataFolder %>/*.json'],
    },

    // compile LESS manifest file into CSS
    less: {
      development: {
        options: {
          compress: false
        },
        files: {
          "<%= config.dist %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.css": "<%= config.src %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.less"
        }
      },
      production: {
        options: {
          compress: true
        },
        files: {
          "<%= config.dist %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.min.css": "<%= config.src %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.less"
        }
      }
    },

    // Use Assemble to generate all HTML pages
    assemble: {
      options: {
        plugins: ['assemble-contrib-permalinks']
      },
      pages: {
        options: {
          flatten: true,
          layout: '<%= config.src %>/assemble/layouts/default.hbs',
          data: '<%= config.src %>/assemble/data/*.{json,yml}',
          partials: '<%= config.src %>/assemble/partials/*.hbs'
        },
        files: {
          '<%= config.dist %>/': ['<%= config.src %>/assemble/pages/**/*.hbs']
        }
      }
    },

    // create connect server
    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost'
      },
      livereload: {
        options: {
          open: true,
          base: [
            '<%= config.dist %>'
          ]
        }
      }
    },

    // watch for file changes and run tasks in response
    watch: {
      js: {
        files: ['<%= jshint.files %>'],
        tasks: ['jshint', 'copy:js']
      },
      assemble: {
        files: ['<%= config.src %>/assemble/**/*.{hbs,yml,json}'],
        tasks: ['assemble']
      },
      less: {
        files: ['<%= config.src %>/<%= cssFolder %>/*.{css,less}'],
        tasks: ['less']
      },
      data: {
        files: ['<%= config.src %>/<%= dataFolder %>/*.csv'],
        tasks: ['convert']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= config.dist %>/**/*.html',
          '<%= config.dist %>/<%= config.cssFolder %>/*.css',
          '<%= config.dist %>/<%= config.jsFolder %>/*.js'
        ]
      }
    },

    // convert all CSV files into JSON files
    convert: {
      csvs: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.dataFolder %>/',
            src: ['*.csv'],
            dest: '<%= config.src %>/assemble/data/',
            ext: '.json'
          }
        ]
      }
    }
  });

  // automatically load all grunt-* tasks in --save-dev
  require('load-grunt-tasks')(grunt);

  // load assemble manually because it doesn't match the grunt-* pattern
  grunt.loadNpmTasks('assemble');

  // create build task
  grunt.registerTask('build', [
    'clean',
    'convert',
    'less',
    'jshint',
    'copy',
    'assemble'
  ]);

  // create server task
  grunt.registerTask('server', [
    'connect',
    'watch'
  ]);

  // set default grunt task
  grunt.registerTask('default', [
    'server'
  ]);
};
<commit_msg>Fix path variables for LESS and data file watching tasks<commit_after>module.exports = function(grunt) {
  'use strict';

  require('time-grunt')(grunt);

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // define variables for Gruntfile
    config: {
      src:              'src',
      dist:             'dist',
      appFolder:        'app',
      componentsFolder: 'app/components',
      jsFolder:         'app/js',
      cssFolder:        'app/css',
      imgFolder:        'app/img',
      dataFolder:       'app/data',
      cssMainFile:      'styles',
      jsMainFile:       'scripts'
    },

    // run jshint against all javascripts, including Gruntfile
    jshint: {
      files: ['Gruntfile.js', '<%= config.src %>/<%= config.jsFolder %>/*.js']
    },

    // copy assets into root of destination
    copy: {
      data: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.dataFolder %>',
            src: '**',
            dest: '<%= config.dist %>/<%= config.dataFolder %>',
          }
        ]
      },

      img: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.imgFolder %>',
            src: '**',
            dest: '<%= config.dist %>/<%= config.imgFolder %>',
          }
        ]
      },

      js: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.jsFolder %>',
            src: '**/*.js',
            dest: '<%= config.dist %>/<%= config.jsFolder %>',
          }
        ]
      },

      src: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/',
            src: '*',
            dest: '<%= config.dist %>/',
            dot: true
          }
        ]
      },

      // copy bower components as well
      components: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.componentsFolder %>',
            src: '**',
            dest: '<%= config.dist %>/<%= config.componentsFolder %>',
            dot: true
          }
        ]
      }
    },

    // clean out destination folder by brute force
    clean: {
      main: ['<%= config.dist %>/**/*', '<%= config.dist %>/.htaccess', '<%= config.src %>/assemble/<%= config.dataFolder %>/*.json'],
    },

    // compile LESS manifest file into CSS
    less: {
      development: {
        options: {
          compress: false
        },
        files: {
          "<%= config.dist %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.css": "<%= config.src %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.less"
        }
      },
      production: {
        options: {
          compress: true
        },
        files: {
          "<%= config.dist %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.min.css": "<%= config.src %>/<%= config.cssFolder %>/<%= config.cssMainFile %>.less"
        }
      }
    },

    // Use Assemble to generate all HTML pages
    assemble: {
      options: {
        plugins: ['assemble-contrib-permalinks']
      },
      pages: {
        options: {
          flatten: true,
          layout: '<%= config.src %>/assemble/layouts/default.hbs',
          data: '<%= config.src %>/assemble/data/*.{json,yml}',
          partials: '<%= config.src %>/assemble/partials/*.hbs'
        },
        files: {
          '<%= config.dist %>/': ['<%= config.src %>/assemble/pages/**/*.hbs']
        }
      }
    },

    // create connect server
    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost'
      },
      livereload: {
        options: {
          open: true,
          base: [
            '<%= config.dist %>'
          ]
        }
      }
    },

    // watch for file changes and run tasks in response
    watch: {
      js: {
        files: ['<%= jshint.files %>'],
        tasks: ['jshint', 'copy:js']
      },
      assemble: {
        files: ['<%= config.src %>/assemble/**/*.{hbs,yml,json}'],
        tasks: ['assemble']
      },
      less: {
        files: ['<%= config.src %>/<%= config.cssFolder %>/*.{css,less}'],
        tasks: ['less']
      },
      data: {
        files: ['<%= config.src %>/<%= config.dataFolder %>/*.csv'],
        tasks: ['convert']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= config.dist %>/**/*.html',
          '<%= config.dist %>/<%= config.cssFolder %>/*.css',
          '<%= config.dist %>/<%= config.jsFolder %>/*.js'
        ]
      }
    },

    // convert all CSV files into JSON files
    convert: {
      csvs: {
        files: [
          {
            expand: true,
            cwd: '<%= config.src %>/<%= config.dataFolder %>/',
            src: ['*.csv'],
            dest: '<%= config.src %>/assemble/data/',
            ext: '.json'
          }
        ]
      }
    }
  });

  // automatically load all grunt-* tasks in --save-dev
  require('load-grunt-tasks')(grunt);

  // load assemble manually because it doesn't match the grunt-* pattern
  grunt.loadNpmTasks('assemble');

  // create build task
  grunt.registerTask('build', [
    'clean',
    'convert',
    'less',
    'jshint',
    'copy',
    'assemble'
  ]);

  // create server task
  grunt.registerTask('server', [
    'connect',
    'watch'
  ]);

  // set default grunt task
  grunt.registerTask('default', [
    'server'
  ]);
};
<|endoftext|>


<commit_before>/**
 * Contains the logic for the export button.
 *
 * @param graphSelector the associated graph svg selector
 * @param ontologyName the ontology name used in the export filename
 * @returns {{}}
 */
webvowlApp.exportMenu = function (graphSelector, ontologyName) {

	var exportMenu = {},
		exportButton;

	/**
	 * Adds the export button to the website.
	 */
	exportMenu.setup = function () {
		exportButton = d3.select("#exportSvg")
			.on("click", exportSVG);
	};

	function exportSVG() {
		// Get the d3js SVG element
		var graphSvg = d3.select(graphSelector).select("svg"),
			graphSvgCode,
			encodedGraphSvgCode;

		// inline the styles, so that the exported svg code contains the css rules
		inlineVowlStyles();

		graphSvgCode = graphSvg.attr("version", 1.1)
			.attr("xmlns", "http://www.w3.org/2000/svg")
			.node().parentNode.innerHTML;

		//btoa(); Creates a base-64 encoded ASCII string from a "string" of binary data.
		encodedGraphSvgCode = "data:image/svg+xml;base64," + btoa(graphSvgCode);

		exportButton.attr("href", encodedGraphSvgCode)
			.attr("download", ontologyName + ".svg");

		// remove graphic styles for interaction to go back to normal
		removeVowlInlineStyles();
	}

	function inlineVowlStyles() {
		d3.selectAll(".text").style("font-family", "Helvetica, Arial, sans-serif").style("font-size", "12px");
		d3.selectAll(".subtext").style("font-size", "9px");
		d3.selectAll(".cardinality").style("font-size", "10px");
		d3.selectAll(".text, .embedded").style("pointer-events", "none");
		d3.selectAll(".class, path").style("stroke-width", "2");
		d3.selectAll(".fineline").style("stroke-width", "1");
		d3.selectAll(".special").style("stroke-dasharray", "8");
		d3.selectAll(".dotted").style("stroke-dasharray", "3");
		d3.selectAll("rect.focused, circle.focused").style("stroke-width", "4px");
		d3.selectAll(".nostroke").style("stroke", "none");
		d3.selectAll(".class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, " +
				".transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty")
			.style("fill", "#acf");
		d3.selectAll(".label .datatype, .datatypeproperty").style("fill", "#9c6");
		d3.selectAll(".rdf, .rdfproperty").style("fill", "#c9c");
		d3.selectAll(".literal, .node .datatype").style("fill", "#fc3");
		d3.selectAll(".deprecated, .deprecatedproperty").style("fill", "#ccc");
		d3.selectAll(".external, .externalproperty").style("fill", "#36c");
		d3.selectAll(".symbol").style("fill", "#69c");
		d3.selectAll(".arrowhead, marker path").style("fill", "#000");
		d3.selectAll(".class, path, .fineline").style("stroke", "#000");
		d3.selectAll(".white, .subclass, .dottedMarker path, .subclassproperty").style("fill", "#fff");
		d3.selectAll("path, .nofill").style("fill", "none");
		d3.selectAll(".class.hovered, .property.hovered, path.arrowhead.hovered, .cardinality.hovered, " +
				".normalMarker path.hovered, .cardinality.focused, .normalMarker path.focused").style("fill", "#f00")
			.style("cursor", "pointer");
		d3.selectAll(".focused, path.hovered").style("stroke", "#f00");
		d3.selectAll(".label .indirectHighlighting").style("fill", "#f90");
		d3.selectAll("#width-test").style("position", "absolute").style("float", "left").style("white-space", "nowrap")
			.style("visibility", "hidden");
		d3.selectAll(".vowlGraph .text tspan:only-child, .vowlGraph .cardinality").style("dominant-baseline", "central");
		d3.selectAll("marker path").style("stroke-dasharray", "50");
	}

	function removeVowlInlineStyles() {
		d3.selectAll(".text, .subtext, .cardinality, .text, .embedded, .class, path, .fineline, .special, .dotted, " +
			"rect.focused, circle.focused, .nostroke, .class, .object, .disjoint, .objectproperty, .disjointwith, " +
			".equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, " +
			".symmetricproperty, .label .datatype, .datatypeproperty, .rdf, .rdfproperty, .literal, .node .datatype, " +
			".deprecated, .deprecatedproperty, .external, .externalproperty, .symbol, .arrowhead, marker path, .class, " +
			"path, .fineline, .white, .subclass, .dottedMarker path, .subclassproperty, path, .nofill, .class.hovered, " +
			".property.hovered, path.arrowhead.hovered, .cardinality.hovered, .normalMarker path.hovered, " +
			".cardinality.focused, .normalMarker path.focused, .focused, path.hovered, .label .indirectHighlighting, " +
			"#width-test, .vowlGraph .text tspan:only-child, .vowlGraph .cardinality, marker path").attr("style", null);
	}

	return exportMenu;
};
<commit_msg>Update style inliner rules for export<commit_after>/**
 * Contains the logic for the export button.
 *
 * @param graphSelector the associated graph svg selector
 * @param ontologyName the ontology name used in the export filename
 * @returns {{}}
 */
webvowlApp.exportMenu = function (graphSelector, ontologyName) {

	var exportMenu = {},
		exportButton;

	/**
	 * Adds the export button to the website.
	 */
	exportMenu.setup = function () {
		exportButton = d3.select("#exportSvg")
			.on("click", exportSVG);
	};

	function exportSVG() {
		// Get the d3js SVG element
		var graphSvg = d3.select(graphSelector).select("svg"),
			graphSvgCode,
			encodedGraphSvgCode;

		// inline the styles, so that the exported svg code contains the css rules
		inlineVowlStyles();

		graphSvgCode = graphSvg.attr("version", 1.1)
			.attr("xmlns", "http://www.w3.org/2000/svg")
			.node().parentNode.innerHTML;

		//btoa(); Creates a base-64 encoded ASCII string from a "string" of binary data.
		encodedGraphSvgCode = "data:image/svg+xml;base64," + btoa(graphSvgCode);

		exportButton.attr("href", encodedGraphSvgCode)
			.attr("download", ontologyName + ".svg");

		// remove graphic styles for interaction to go back to normal
		removeVowlInlineStyles();
	}

	function inlineVowlStyles() {
		d3.selectAll(".text").style("font-family", "Helvetica, Arial, sans-serif").style("font-size", "12px");
		d3.selectAll(".subtext").style("font-size", "9px");
		d3.selectAll(".cardinality").style("font-size", "10px");
		d3.selectAll(".text, .embedded").style("pointer-events", "none");
		d3.selectAll(".class, path, line").style("stroke-width", "2");
		d3.selectAll(".fineline").style("stroke-width", "1");
		d3.selectAll(".special").style("stroke-dasharray", "8");
		d3.selectAll(".dotted").style("stroke-dasharray", "3");
		d3.selectAll("rect.focused, circle.focused").style("stroke-width", "4px");
		d3.selectAll(".nostroke").style("stroke", "none");
		d3.selectAll(".class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty").style("fill", "#acf");
		d3.selectAll(".label .datatype, .datatypeproperty").style("fill", "#9c6");
		d3.selectAll(".rdf, .rdfproperty").style("fill", "#c9c");
		d3.selectAll(".literal, .node .datatype").style("fill", "#fc3");
		d3.selectAll(".deprecated, .deprecatedproperty").style("fill", "#ccc");
		d3.selectAll(".external, .externalproperty").style("fill", "#36c");
		d3.selectAll(".symbol").style("fill", "#69c");
		d3.selectAll(".arrowhead, marker path").style("fill", "#000");
		d3.selectAll(".class, path, line, .fineline").style("stroke", "#000");
		d3.selectAll(".white, .subclass, .dottedMarker path, .subclassproperty").style("fill", "#fff");
		d3.selectAll("path, .nofill").style("fill", "none");
		d3.selectAll(".class.hovered, .property.hovered, path.arrowhead.hovered, .cardinality.hovered, .normalMarker path.hovered, .cardinality.focused, .normalMarker path.focused, circle.pin").style("fill", "#f00").style("cursor", "pointer");
		d3.selectAll(".focused, path.hovered").style("stroke", "#f00");
		d3.selectAll(".label .indirectHighlighting, .feature:hover").style("fill", "#f90");
		d3.selectAll("#width-test").style("position", "absolute").style("float", "left").style("white-space", "nowrap").style("visibility", "hidden");
		d3.selectAll(".vowlGraph .text tspan:only-child, .vowlGraph .cardinality").style("dominant-baseline", "central");
		d3.selectAll("marker path").style("stroke-dasharray", "50");
	}

	function removeVowlInlineStyles() {
		d3.selectAll(".text, .subtext, .cardinality, .text, .embedded, .class, path, line, .fineline, .special, .dotted, rect.focused, circle.focused, .nostroke, .class, .object, .disjoint, .objectproperty, .disjointwith, .equivalentproperty, .transitiveproperty, .functionalproperty, .inversefunctionalproperty, .symmetricproperty, .label .datatype, .datatypeproperty, .rdf, .rdfproperty, .literal, .node .datatype, .deprecated, .deprecatedproperty, .external, .externalproperty, .symbol, .arrowhead, marker path, .class, path, line, .fineline, .white, .subclass, .dottedMarker path, .subclassproperty, path, .nofill, .class.hovered, .property.hovered, path.arrowhead.hovered, .cardinality.hovered, .normalMarker path.hovered, .cardinality.focused, .normalMarker path.focused, circle.pin, .focused, path.hovered, .label .indirectHighlighting, .feature:hover, #width-test, .vowlGraph .text tspan:only-child, .vowlGraph .cardinality, marker path").attr("style", null);
	}

	return exportMenu;
};
<|endoftext|>


<commit_before>/*
 * metaimages
 * https://github.com/traviswimer/metaimages.js
 *
 * Copyright (c) 2014 Travis Wimer
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

	// Project configuration.
	grunt.initConfig({
		jshint: {
			all: [
				'Gruntfile.js',
				'src/*.js',
			],
			options: {
				jshintrc: '.jshintrc',
			},
		},

		// Before generating any new files, remove any previously-created files.
		clean: {
			tests: ['tests/tmp/*']
		},

		// For istanbul
		env: {
			coverage: {
				APP_DIR_FOR_CODE_COVERAGE: '../tests/coverage/instrument/src/'
			}
		},

		// Unit tests.
		mochaTest: {
			test: {
				options: {
					reporter: 'spec',
					timeout: 10000
				},
				src: ['tests/*.js']
			}
		},

		not_constantinople: {
			coverage: {
				options: {
					unitTestTask: "mochaTest",
					directories: {
						root: 'tests',
						coverage: 'coverage',
						sourceFiles: 'src'
					},
					thresholds: {
						'statements': 100,
						'branches': 100,
						'lines': 100,
						'functions': 100
					}
				}
			}
		},

		coveralls: {
			options: {
				force: true
			},
			all: {
				src: 'reports/lcov.info'
			}
		},

		watch: {
			scripts: {
				files: [
					'tests/*.js',
					'src/**/*.js'
				],
				tasks: ['test'],
			},
		},

	});

	// Load grunt tasks
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-env');
	grunt.loadNpmTasks('grunt-mocha-test');
	grunt.loadNpmTasks('grunt-not-constantinople');
	grunt.loadNpmTasks('grunt-coveralls');
	grunt.loadNpmTasks('grunt-contrib-watch');

	// Removes images created from past tests and runs tests
	grunt.registerTask('test', ['jshint', 'clean:tests', 'env:coverage', 'not_constantinople']);

	// Lint and run tests.
	grunt.registerTask('default', ['watch']);

};
<commit_msg>Fixes report path used by coveralls<commit_after>/*
 * metaimages
 * https://github.com/traviswimer/metaimages.js
 *
 * Copyright (c) 2014 Travis Wimer
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

	// Project configuration.
	grunt.initConfig({
		jshint: {
			all: [
				'Gruntfile.js',
				'src/*.js',
			],
			options: {
				jshintrc: '.jshintrc',
			},
		},

		// Before generating any new files, remove any previously-created files.
		clean: {
			tests: ['tests/tmp/*']
		},

		// For istanbul
		env: {
			coverage: {
				APP_DIR_FOR_CODE_COVERAGE: '../tests/coverage/instrument/src/'
			}
		},

		// Unit tests.
		mochaTest: {
			test: {
				options: {
					reporter: 'spec',
					timeout: 10000
				},
				src: ['tests/*.js']
			}
		},

		not_constantinople: {
			coverage: {
				options: {
					unitTestTask: "mochaTest",
					directories: {
						root: 'tests',
						coverage: 'coverage',
						sourceFiles: 'src'
					},
					thresholds: {
						'statements': 100,
						'branches': 100,
						'lines': 100,
						'functions': 100
					}
				}
			}
		},

		coveralls: {
			options: {
				force: true
			},
			all: {
				src: 'tests/coverage/reports/lcov.info'
			}
		},

		watch: {
			scripts: {
				files: [
					'tests/*.js',
					'src/**/*.js'
				],
				tasks: ['test'],
			},
		},

	});

	// Load grunt tasks
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-env');
	grunt.loadNpmTasks('grunt-mocha-test');
	grunt.loadNpmTasks('grunt-not-constantinople');
	grunt.loadNpmTasks('grunt-coveralls');
	grunt.loadNpmTasks('grunt-contrib-watch');

	// Removes images created from past tests and runs tests
	grunt.registerTask('test', ['jshint', 'clean:tests', 'env:coverage', 'not_constantinople']);

	// Lint and run tests.
	grunt.registerTask('default', ['watch']);

};
<|endoftext|>


<commit_before>(function() {
  var domains = [];
  var domainsEnable = [];
  var disabled = false;

  chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
      console.log('We are in the background script...');
      console.log(request);
      // Add domain to domain blocker container
      if (request.validDomain) {
        domains.push(request.validDomain);
        domainsEnable = domains;
      }
      // Remove domain from domain blocker container
      if (request.index) {
        domains.splice(request.index, 1);
        domainsEnable = domains;
      }
      // Remove domain from domain blocker container
      if (request.index == 0) {
        domainsEnable = domains;
        domains.splice(request.index, 1);
      }
      // Enable domain blocker
      if (request.enable == true) {
        if (disabled) {
          domains = domainsEnable;
          disabled = false;
        }
      }
      // Disable domain blocker
      if (request.enable == false) {
        if (!disabled) {
          var domainsDisable = [];
          domainsEnable = domains;
          domains = domainsDisable;
          disabled = true;
        }
      }
    }
  );

  chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
      // Check current tab for URL replacement
      chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
        for (var i = 0; i < domains.length; i++) {
          var reDomain = new RegExp(domains[i], 'i');
          if (reDomain.test(tabs[0].url)) {
            chrome.tabs.update(tabs[0].id, {url: "src/html/home.html" });
            return;
          }
        }
      });

      // Check rest of tabs for URL replacement
      chrome.tabs.query({currentWindow: true}, function (tabs) {
        var currDomain = location.href;
        for (var i = 0; i < domains.length; i++) {
          for (var k = 0; k < tabs.length; k++) {
            var reDomain = new RegExp(domains[i], 'i');
            if (reDomain.test(tabs[k].url)) {
              chrome.tabs.update(tabs[k].id, {url: "src/html/home.html" });
              return;
            }
          }
        }
      });
    }
  });
})();
<commit_msg>es6ify chrome background script<commit_after>(() => {
  let domains = [];
  let domainsEnable = [];
  let disabled = false;

  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    // Add domain to domain blocker container
    if (request.validDomain) {
      domains.push(request.validDomain);
      domainsEnable = domains;
    }
    // Remove domain from domain blocker container
    if (request.index) {
      domains.splice(request.index, 1);
      domainsEnable = domains;
    }
    // Remove domain from domain blocker container
    if (request.index == 0) {
      domainsEnable = domains;
      domains.splice(request.index, 1);
    }
    // Enable domain blocker
    if (request.enable == true) {
      if (disabled) {
        domains = domainsEnable;
        disabled = false;
      }
    }
    // Disable domain blocker
    if (request.enable == false) {
      if (!disabled) {
        let domainsDisable = [];
        domainsEnable = domains;
        domains = domainsDisable;
        disabled = true;
      }
    }
  });

  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.status == 'complete') {
      // Check current tab for URL replacement
      chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
        for (let i = 0; i < domains.length; i++) {
          const reDomain = new RegExp(domains[i], 'i');
          if (reDomain.test(tabs[0].url)) {
            chrome.tabs.update(tabs[0].id, {url: 'src/html/home.html' });
            return;
          }
        }
      });

      // Check rest of tabs for URL replacement
      chrome.tabs.query({currentWindow: true}, (tabs) => {
        for (let i = 0; i < domains.length; i++) {
          for (let k = 0; k < tabs.length; k++) {
            const reDomain = new RegExp(domains[i], 'i');
            if (reDomain.test(tabs[k].url)) {
              chrome.tabs.update(tabs[k].id, {url: 'src/html/home.html' });
              return;
            }
          }
        }
      });
    }
  });
})();
<|endoftext|>


<commit_before>'use strict';
module.exports = function (grunt) {
    grunt.initConfig({
        sass: {
            options: {
                sourceMap: true
            },
            dist: {
                files: {
                    'public/css/app-arena-styles.css': 'source/css/app-arena-styles.scss',
                    'source/css/app-arena-styles.css': 'source/css/app-arena-styles.scss',
                }
            }
        },
        run: {
            options: {},
            // Runt the icon generator https://github.com/Workshape/icon-font-generator
            icon_generator: {
                cmd: 'icon-font-generator',
                args: [
                    'source/icons/svg/*.svg',
                    '--out=source/fonts',
                    '--name=icons',
                    '--prefix=aa-icon',
                    //'--normalize=true',
                    '--tag=aa-icon',
                    '--htmtp=source/icons/font/template/html.hbs', // HTML handlebars template path (Optional)
                    '--csstp=source/icons/font/template/css.hbs', // CSS handlebars template path (Optional)
                    '--round=10e12', // Setup SVG rounding (Default: 10e12)
                    '--descent=150', // Offset applied to the baseline (Default: 0)
                    '--mono=true', // Make font monospace (Default: false)
                    '--height=1000', // Fixed font height value
                    '--center=true', // Center font horizontally
                ]
            }
        }
    });

    grunt.loadNpmTasks('grunt-run');
    grunt.loadTasks('build/scripts/grunt');
    grunt.registerTask('default', ['sass', 'run']);
};<commit_msg>Push icon font generator settings<commit_after>'use strict';
module.exports = function (grunt) {
    grunt.initConfig({
        sass: {
            options: {
                sourceMap: true
            },
            dist: {
                files: {
                    'public/css/app-arena-styles.css': 'source/css/app-arena-styles.scss',
                    'source/css/app-arena-styles.css': 'source/css/app-arena-styles.scss',
                }
            }
        },
        run: {
            options: {},
            // Runt the icon generator https://github.com/Workshape/icon-font-generator
            icon_generator: {
                cmd: 'icon-font-generator',
                args: [
                    'source/icons/svg/*.svg',
                    '--out=source/fonts',
                    '--name=icons',
                    '--prefix=aa-icon',
                    '--normalize=true',
                    '--tag=aa-icon',
                    '--htmtp=source/icons/font/template/html.hbs', // HTML handlebars template path (Optional)
                    '--csstp=source/icons/font/template/css.hbs', // CSS handlebars template path (Optional)
                    '--round=10e12', // Setup SVG rounding (Default: 10e12)
                    '--descent=150', // Offset applied to the baseline (Default: 0)
                    '--mono=true', // Make font monospace (Default: false)
                    '--height=1000', // Fixed font height value
                    '--center=true', // Center font horizontally
                ]
            }
        }
    });

    grunt.loadNpmTasks('grunt-run');
    grunt.loadTasks('build/scripts/grunt');
    grunt.registerTask('default', ['sass', 'run']);
};<|endoftext|>


<commit_before>import $ from 'jquery';
export default class Toolbar {
  constructor(context) {
    this.context = context;

    this.$window = $(window);
    this.$document = $(document);

    this.ui = $.summernote.ui;
    this.$note = context.layoutInfo.note;
    this.$editor = context.layoutInfo.editor;
    this.$toolbar = context.layoutInfo.toolbar;
    this.$editable = context.layoutInfo.editable;
    this.options = context.options;

    this.followScroll = this.followScroll.bind(this);
  }

  shouldInitialize() {
    return !this.options.airMode;
  }

  initialize() {
    this.options.toolbar = this.options.toolbar || [];

    if (!this.options.toolbar.length) {
      this.$toolbar.hide();
    } else {
      this.context.invoke('buttons.build', this.$toolbar, this.options.toolbar);
    }

    if (this.options.toolbarContainer) {
      this.$toolbar.appendTo(this.options.toolbarContainer);
    }

    this.changeContainer(false);

    this.$note.on('summernote.keyup summernote.mouseup summernote.change', () => {
      this.context.invoke('buttons.updateCurrentStyle');
    });

    this.context.invoke('buttons.updateCurrentStyle');
    if (this.options.followingToolbar) {
      this.$window.on('scroll resize', this.followScroll);
    }
  }

  destroy() {
    this.$toolbar.children().remove();

    if (this.options.followingToolbar) {
      this.$window.off('scroll resize', this.followScroll);
    }
  }

  followScroll() {
    if (this.$editor.hasClass('fullscreen')) {
      return false;
    }

    const $toolbarWrapper = this.$toolbar.parent('.note-toolbar-wrapper');
    const editorHeight = this.$editor.outerHeight();
    const editorWidth = this.$editor.width();

    const toolbarHeight = this.$toolbar.height();
    $toolbarWrapper.css({
      height: toolbarHeight,
    });

    // check if the web app is currently using another static bar
    let otherBarHeight = 0;
    if (this.options.otherStaticBar) {
      otherBarHeight = $(this.options.otherStaticBar).outerHeight();
    }

    const currentOffset = this.$document.scrollTop();
    const editorOffsetTop = this.$editor.offset().top;
    const editorOffsetBottom = editorOffsetTop + editorHeight;
    const activateOffset = editorOffsetTop - otherBarHeight;
    const deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight;

    if ((currentOffset > activateOffset) && (currentOffset < deactivateOffsetBottom)) {
      this.$toolbar.css({
        position: 'fixed',
        top: otherBarHeight,
        width: editorWidth,
      });
      this.$editable.css({
        marginTop: this.$toolbar.height() + 5,
      });
    } else {
      this.$toolbar.css({
        position: 'relative',
        top: 0,
        width: '100%',
      });
      this.$editable.css({
        marginTop: '',
      });
    }
  }

  changeContainer(isFullscreen) {
    if (isFullscreen) {
      this.$toolbar.prependTo(this.$editor);
    } else {
      if (this.options.toolbarContainer) {
        this.$toolbar.appendTo(this.options.toolbarContainer);
      }
    }
    this.followScroll();
  }

  updateFullscreen(isFullscreen) {
    this.ui.toggleBtnActive(this.$toolbar.find('.btn-fullscreen'), isFullscreen);

    this.changeContainer(isFullscreen);
  }

  updateCodeview(isCodeview) {
    this.ui.toggleBtnActive(this.$toolbar.find('.btn-codeview'), isCodeview);
    if (isCodeview) {
      this.deactivate();
    } else {
      this.activate();
    }
  }

  activate(isIncludeCodeview) {
    let $btn = this.$toolbar.find('button');
    if (!isIncludeCodeview) {
      $btn = $btn.not('.btn-codeview');
    }
    this.ui.toggleBtn($btn, true);
  }

  deactivate(isIncludeCodeview) {
    let $btn = this.$toolbar.find('button');
    if (!isIncludeCodeview) {
      $btn = $btn.not('.btn-codeview');
    }
    this.ui.toggleBtn($btn, false);
  }
}
<commit_msg>Fix rattle toolbar problem while toggling fixed-relative mode<commit_after>import $ from 'jquery';
export default class Toolbar {
  constructor(context) {
    this.context = context;

    this.$window = $(window);
    this.$document = $(document);

    this.ui = $.summernote.ui;
    this.$note = context.layoutInfo.note;
    this.$editor = context.layoutInfo.editor;
    this.$toolbar = context.layoutInfo.toolbar;
    this.$editable = context.layoutInfo.editable;
    this.$statusbar = context.layoutInfo.statusbar;
    this.options = context.options;

    this.isFollowing = false;
    this.followScroll = this.followScroll.bind(this);
  }

  shouldInitialize() {
    return !this.options.airMode;
  }

  initialize() {
    this.options.toolbar = this.options.toolbar || [];

    if (!this.options.toolbar.length) {
      this.$toolbar.hide();
    } else {
      this.context.invoke('buttons.build', this.$toolbar, this.options.toolbar);
    }

    if (this.options.toolbarContainer) {
      this.$toolbar.appendTo(this.options.toolbarContainer);
    }

    this.changeContainer(false);

    this.$note.on('summernote.keyup summernote.mouseup summernote.change', () => {
      this.context.invoke('buttons.updateCurrentStyle');
    });

    this.context.invoke('buttons.updateCurrentStyle');
    if (this.options.followingToolbar) {
      this.$window.on('scroll resize', this.followScroll);
    }
  }

  destroy() {
    this.$toolbar.children().remove();

    if (this.options.followingToolbar) {
      this.$window.off('scroll resize', this.followScroll);
    }
  }

  followScroll() {
    if (this.$editor.hasClass('fullscreen')) {
      return false;
    }

    const editorHeight = this.$editor.outerHeight();
    const editorWidth = this.$editor.width();
    const toolbarHeight = this.$toolbar.height();
    const statusbarHeight = this.$statusbar.height();

    // check if the web app is currently using another static bar
    let otherBarHeight = 0;
    if (this.options.otherStaticBar) {
      otherBarHeight = $(this.options.otherStaticBar).outerHeight();
    }

    const currentOffset = this.$document.scrollTop();
    const editorOffsetTop = this.$editor.offset().top;
    const editorOffsetBottom = editorOffsetTop + editorHeight;
    const activateOffset = editorOffsetTop - otherBarHeight;
    const deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight - statusbarHeight;

    if (!this.isFollowing &&
      (currentOffset > activateOffset) && (currentOffset < deactivateOffsetBottom - toolbarHeight)) {
      this.isFollowing = true;
      this.$toolbar.css({
        position: 'fixed',
        top: otherBarHeight,
        width: editorWidth,
      });
      this.$editable.css({
        marginTop: this.$toolbar.height() + 5,
      });
    } else if (this.isFollowing &&
      ((currentOffset < activateOffset) || (currentOffset > deactivateOffsetBottom))) {
      this.isFollowing = false;
      this.$toolbar.css({
        position: 'relative',
        top: 0,
        width: '100%',
      });
      this.$editable.css({
        marginTop: '',
      });
    }
  }

  changeContainer(isFullscreen) {
    if (isFullscreen) {
      this.$toolbar.prependTo(this.$editor);
    } else {
      if (this.options.toolbarContainer) {
        this.$toolbar.appendTo(this.options.toolbarContainer);
      }
    }
    this.followScroll();
  }

  updateFullscreen(isFullscreen) {
    this.ui.toggleBtnActive(this.$toolbar.find('.btn-fullscreen'), isFullscreen);

    this.changeContainer(isFullscreen);
  }

  updateCodeview(isCodeview) {
    this.ui.toggleBtnActive(this.$toolbar.find('.btn-codeview'), isCodeview);
    if (isCodeview) {
      this.deactivate();
    } else {
      this.activate();
    }
  }

  activate(isIncludeCodeview) {
    let $btn = this.$toolbar.find('button');
    if (!isIncludeCodeview) {
      $btn = $btn.not('.btn-codeview');
    }
    this.ui.toggleBtn($btn, true);
  }

  deactivate(isIncludeCodeview) {
    let $btn = this.$toolbar.find('button');
    if (!isIncludeCodeview) {
      $btn = $btn.not('.btn-codeview');
    }
    this.ui.toggleBtn($btn, false);
  }
}
<|endoftext|>


<commit_before>/**
 * @file Icosahedron class. Part of the "Age of Space" project.
 * @author github.com/azziliz
 * @author github.com/thyshimrod
 * {@link https://github.com/The-game-craftmen/age-of-space/ Project page}
 * @license MIT
 */

'use strict';
var aos = aos || {};
//debugger;

/**
 * This class is used to render a planet with an icosahedron.
 *
 * @class
 */
aos.Icosahedron = function () {
    this.vertices = [];
    this.triangles = [];
    this.modelMatrix = null;
    this.frustumMatrix = null;
    this.cameraMatrix = null;
    this.rotateY1 = null;
};

aos.Icosahedron.prototype = {

    initialize: function () {
        //identity
        this.modelMatrix = new Float32Array([
                1, 0, 0, 0,
                0, 1, 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1
        ]);

        // http://www.songho.ca/opengl/gl_projectionmatrix.html
        const right = 0.268;
        const top = 0.268;
        const near = 1;
        const far = 100;
        const nf = 1 / (near - far);
        this.frustumMatrix = new Float32Array([
            near / right, 0, 0, 0,
            0, near / top, 0, 0,
            0, 0, (far + near) * nf, -1,
            0, 0, 2 * far * near * nf, 0
        ]);

        // http://www.songho.ca/opengl/gl_camera.html#lookat
        // translate (0, 0, 5)
        const tx = 0;
        const ty = 0;
        const tz = 5;
        this.cameraMatrix = new Float32Array([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            tx, ty, tz, 1
        ]);

        const cos1 = Math.cos(Math.PI / 180);
        const sin1 = Math.sin(Math.PI / 180);
        this.rotateY1 = new Float32Array([
            cos1, 0, -sin1, 0,
            0, 1, 0, 0,
            sin1, 0, cos1, 0,
            0, 0, 0, 1
        ]);

        const invphi = 2 / (1 + Math.sqrt(5));

        // Vertices coordinates: [Xworld, Yworld, Zworld, Zmodel]
        this.vertices.push(new Float32Array([1, invphi, 0, 0]));    // 0
        this.vertices.push(new Float32Array([1, -invphi, 0, 0]));    // 1
        this.vertices.push(new Float32Array([-1, invphi, 0, 0]));    // 2
        this.vertices.push(new Float32Array([-1, -invphi, 0, 0]));    // 3
        this.vertices.push(new Float32Array([0, 1, invphi, 0]));    // 4
        this.vertices.push(new Float32Array([0, 1, -invphi, 0]));    // 5
        this.vertices.push(new Float32Array([0, -1, invphi, 0]));    // 6
        this.vertices.push(new Float32Array([0, -1, -invphi, 0]));    // 7
        this.vertices.push(new Float32Array([invphi, 0, 1, 0]));    // 8
        this.vertices.push(new Float32Array([-invphi, 0, 1, 0]));    // 9
        this.vertices.push(new Float32Array([invphi, 0, -1, 0]));    // 10
        this.vertices.push(new Float32Array([-invphi, 0, -1, 0]));    // 11

        // Triangles arrays: [vertex1, vertex2, vertex3, average Zmodel]
        this.triangles.push([4, 5, 0, 0]);
        this.triangles.push([4, 5, 2, 0]);
        this.triangles.push([6, 7, 1, 0]);
        this.triangles.push([6, 7, 3, 0]);
        this.triangles.push([0, 1, 8, 0]);
        this.triangles.push([0, 1, 10, 0]);
        this.triangles.push([2, 3, 9, 0]);
        this.triangles.push([2, 3, 11, 0]);
        this.triangles.push([8, 9, 4, 0]);
        this.triangles.push([8, 9, 6, 0]);
        this.triangles.push([10, 11, 5, 0]);
        this.triangles.push([10, 11, 7, 0]);
        this.triangles.push([0, 4, 8, 0]); // +++
        this.triangles.push([0, 5, 10, 0]); // ++-
        this.triangles.push([1, 6, 8, 0]); // +-+
        this.triangles.push([1, 7, 10, 0]); // +--
        this.triangles.push([2, 4, 9, 0]); // -++
        this.triangles.push([2, 5, 11, 0]); // -+-
        this.triangles.push([3, 6, 9, 0]); // --+
        this.triangles.push([3, 7, 11, 0]); // ---

        window.addEventListener('animationTick', function (e) {
            const canvas = document.getElementById('planetTestCanvas');
            const ctx = canvas.getContext("2d");

            const newModel = aos.Math.multiply4x4(this.rotateY1, this.modelMatrix);
            this.modelMatrix = newModel;
            const vm = aos.Math.multiply4x4(this.cameraMatrix, this.modelMatrix);
            const pvm = aos.Math.multiply4x4(this.frustumMatrix, vm);

            const halfWidth = canvas.clientWidth / 2;
            const halfHeight = canvas.clientHeight / 2;

            ctx.fillStyle = "#000";
            ctx.fillRect(0, 0, canvas.clientWidth, canvas.clientHeight);

            const screenPoints = [];
            this.vertices.forEach(function (vec3) {
                const screenPoint = aos.Math.transformVector3(vec3, pvm);
                screenPoints.push(screenPoint);
                ctx.fillStyle = "#fff";
                ctx.fillRect(screenPoint[0] * halfWidth + halfWidth, screenPoint[1] * halfHeight + halfHeight, 1, 1);
                const modelPoint = aos.Math.transformVector3(vec3, this.modelMatrix);
                vec3[3] = modelPoint[2];
            }, this);
            this.triangles.forEach(function (tri) {
                tri[3] = this.vertices[tri[0]][3] + this.vertices[tri[1]][3] + this.vertices[tri[2]][3];
            }, this);
            this.triangles.sort(function (a, b) {
                return b[3] - a[3];
            });
            this.triangles.forEach(function (tri) {
                ctx.beginPath();
                ctx.fillStyle = (tri[2] === 0 ? 'blue' : 'red');
                ctx.moveTo(screenPoints[tri[0]][0] * halfWidth + halfWidth, screenPoints[tri[0]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[1]][0] * halfWidth + halfWidth, screenPoints[tri[1]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[2]][0] * halfWidth + halfWidth, screenPoints[tri[2]][1] * halfHeight + halfHeight);
                ctx.closePath();
                ctx.fill();
                ctx.strokeStyle = 'white';
                ctx.lineTo(screenPoints[tri[1]][0] * halfWidth + halfWidth, screenPoints[tri[1]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[2]][0] * halfWidth + halfWidth, screenPoints[tri[2]][1] * halfHeight + halfHeight);
                ctx.closePath();
                ctx.stroke();
            }, this);
        }.bind(this), false);
    },
};<commit_msg>+color<commit_after>/**
 * @file Icosahedron class. Part of the "Age of Space" project.
 * @author github.com/azziliz
 * @author github.com/thyshimrod
 * {@link https://github.com/The-game-craftmen/age-of-space/ Project page}
 * @license MIT
 */

'use strict';
var aos = aos || {};
//debugger;

/**
 * This class is used to render a planet with an icosahedron.
 *
 * @class
 */
aos.Icosahedron = function () {
    this.vertices = [];
    this.triangles = [];
    this.modelMatrix = null;
    this.frustumMatrix = null;
    this.cameraMatrix = null;
    this.rotateY1 = null;
};

aos.Icosahedron.prototype = {

    initialize: function () {
        //identity
        this.modelMatrix = new Float32Array([
                1, 0, 0, 0,
                0, 1, 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1
        ]);

        // http://www.songho.ca/opengl/gl_projectionmatrix.html
        const right = 0.268;
        const top = 0.268;
        const near = 1;
        const far = 100;
        const nf = 1 / (near - far);
        this.frustumMatrix = new Float32Array([
            near / right, 0, 0, 0,
            0, near / top, 0, 0,
            0, 0, (far + near) * nf, -1,
            0, 0, 2 * far * near * nf, 0
        ]);

        // http://www.songho.ca/opengl/gl_camera.html#lookat
        // translate (0, 0, 5)
        const tx = 0;
        const ty = 0;
        const tz = 5;
        this.cameraMatrix = new Float32Array([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            tx, ty, tz, 1
        ]);

        const cos1 = Math.cos(Math.PI / 180);
        const sin1 = Math.sin(Math.PI / 180);
        this.rotateY1 = new Float32Array([
            cos1, 0, -sin1, 0,
            0, 1, 0, 0,
            sin1, 0, cos1, 0,
            0, 0, 0, 1
        ]);

        const invphi = 2 / (1 + Math.sqrt(5));

        // Vertices coordinates: [Xworld, Yworld, Zworld, Zmodel]
        this.vertices.push(new Float32Array([1, invphi, 0, 0]));    // 0
        this.vertices.push(new Float32Array([1, -invphi, 0, 0]));    // 1
        this.vertices.push(new Float32Array([-1, invphi, 0, 0]));    // 2
        this.vertices.push(new Float32Array([-1, -invphi, 0, 0]));    // 3
        this.vertices.push(new Float32Array([0, 1, invphi, 0]));    // 4
        this.vertices.push(new Float32Array([0, 1, -invphi, 0]));    // 5
        this.vertices.push(new Float32Array([0, -1, invphi, 0]));    // 6
        this.vertices.push(new Float32Array([0, -1, -invphi, 0]));    // 7
        this.vertices.push(new Float32Array([invphi, 0, 1, 0]));    // 8
        this.vertices.push(new Float32Array([-invphi, 0, 1, 0]));    // 9
        this.vertices.push(new Float32Array([invphi, 0, -1, 0]));    // 10
        this.vertices.push(new Float32Array([-invphi, 0, -1, 0]));    // 11

        // Triangles arrays: [vertex1, vertex2, vertex3, average Zmodel]
        this.triangles.push([4, 5, 0, 0]);
        this.triangles.push([4, 5, 2, 0]);
        this.triangles.push([6, 7, 1, 0]);
        this.triangles.push([6, 7, 3, 0]);
        this.triangles.push([0, 1, 8, 0]);
        this.triangles.push([0, 1, 10, 0]);
        this.triangles.push([2, 3, 9, 0]);
        this.triangles.push([2, 3, 11, 0]);
        this.triangles.push([8, 9, 4, 0]);
        this.triangles.push([8, 9, 6, 0]);
        this.triangles.push([10, 11, 5, 0]);
        this.triangles.push([10, 11, 7, 0]);
        this.triangles.push([0, 4, 8, 0]); // +++
        this.triangles.push([0, 5, 10, 0]); // ++-
        this.triangles.push([1, 6, 8, 0]); // +-+
        this.triangles.push([1, 7, 10, 0]); // +--
        this.triangles.push([2, 4, 9, 0]); // -++
        this.triangles.push([2, 5, 11, 0]); // -+-
        this.triangles.push([3, 6, 9, 0]); // --+
        this.triangles.push([3, 7, 11, 0]); // ---

        window.addEventListener('animationTick', function (e) {
            const canvas = document.getElementById('planetTestCanvas');
            const ctx = canvas.getContext("2d");

            const newModel = aos.Math.multiply4x4(this.rotateY1, this.modelMatrix);
            this.modelMatrix = newModel;
            const vm = aos.Math.multiply4x4(this.cameraMatrix, this.modelMatrix);
            const pvm = aos.Math.multiply4x4(this.frustumMatrix, vm);

            const halfWidth = canvas.clientWidth / 2;
            const halfHeight = canvas.clientHeight / 2;

            ctx.fillStyle = "#000";
            ctx.fillRect(0, 0, canvas.clientWidth, canvas.clientHeight);

            const screenPoints = [];
            this.vertices.forEach(function (vec3) {
                const screenPoint = aos.Math.transformVector3(vec3, pvm);
                screenPoints.push(screenPoint);
                ctx.fillStyle = "#fff";
                ctx.fillRect(screenPoint[0] * halfWidth + halfWidth, screenPoint[1] * halfHeight + halfHeight, 1, 1);
                const modelPoint = aos.Math.transformVector3(vec3, this.modelMatrix);
                vec3[3] = modelPoint[2];
            }, this);
            this.triangles.forEach(function (tri) {
                tri[3] = this.vertices[tri[0]][3] + this.vertices[tri[1]][3] + this.vertices[tri[2]][3];
            }, this);
            this.triangles.sort(function (a, b) {
                return b[3] - a[3];
            });
            this.triangles.forEach(function (tri) {
                ctx.beginPath();
                ctx.fillStyle = 'rgb(' + (tri[0] * 20) + ', ' + (tri[1] * 20) + ', ' + (tri[2] * 20) + ')';
                ctx.moveTo(screenPoints[tri[0]][0] * halfWidth + halfWidth, screenPoints[tri[0]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[1]][0] * halfWidth + halfWidth, screenPoints[tri[1]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[2]][0] * halfWidth + halfWidth, screenPoints[tri[2]][1] * halfHeight + halfHeight);
                ctx.closePath();
                ctx.fill();
                ctx.strokeStyle = 'white';
                ctx.lineTo(screenPoints[tri[1]][0] * halfWidth + halfWidth, screenPoints[tri[1]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[2]][0] * halfWidth + halfWidth, screenPoints[tri[2]][1] * halfHeight + halfHeight);
                ctx.closePath();
                ctx.stroke();
            }, this);
        }.bind(this), false);
    },
};<|endoftext|>


<commit_before>module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-ts');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-open');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    ts: {
      options: {
        removeComments: false,
      },
      client: {
        src: ['client/**/*.ts'],
        out: 'public/js/ImprovedInitiative.js',
        options: {
          fast: 'never',
          inlineSources: true
        }
      },
      client_prod: {
        src: ['client/**/*.ts'],
        out: 'build/ImprovedInitiative.js'
      },
      server: {
        src: ['server/*.ts'],
        outDir: '.',
        options: {
          module: 'commonjs',
          target: 'es5'
        }
      },
    },
    uglify: {
      options: {
        mangle: false
      },
      prod: {
        files: {
          'public/js/ImprovedInitiative.js': ['build/ImprovedInitiative.js']
        }
      }
    },
    less: {
      default: {
        files: {
          "public/css/improved-initiative.css": ["lesscss/improved-initiative.less"]
        }
      }
    },
    concat: {
      js_dependencies: {
        src: [
          'node_modules/knockout/build/output/knockout-latest.debug.js',
          'node_modules/knockout-mapping/dist/knockout.mapping.js',
          'node_modules/jquery/dist/jquery.js',
          'node_modules/awesomplete/awesomplete.js',
          'node_modules/mousetrap/mousetrap.js',
          'node_modules/socket.io-client/dist/socket.io.js',
          'node_modules/moment/moment.js',
          'node_modules/browser-filesaver/FileSaver.js',
          'node_modules/markdown-it/dist/markdown-it.js'        ],
        dest: 'public/js/dependencies.js',
        sourceMap: true
      },
      js_dependencies_min: {
        src: [
          'node_modules/knockout/build/output/knockout-latest.js',
          'node_modules/knockout-mapping/dist/knockout.mapping.min.js',
          'node_modules/jquery/dist/jquery.min.js',
          'node_modules/awesomplete/awesomplete.min.js',
          'node_modules/mousetrap/mousetrap.min.js',
          'node_modules/socket.io-client/dist/socket.io.min.js',
          'node_modules/moment/min/moment.min.js',
          'node_modules/browser-filesaver/FileSaver.min.js',
          'node_modules/markdown-it/dist/markdown-it.min.js'
        ],
        dest: 'public/js/dependencies.js'
      }
    },
    watch: {
      tsclient: {
        files: 'client/*.ts',
        tasks: ['ts:client']
      },
      tsserver: {
        files: 'server/*.ts',
        tasks: ['ts:server']
      },
      lesscss: {
        files: 'lesscss/*.less',
        tasks: ['less']
      }
    },
    copy: {
      main: {
        files: [
          { expand: true, cwd: 'node_modules/font-awesome/fonts/', src: ['**'], dest: 'public/fonts/' }
        ]
      }
    }
  });

  grunt.registerTask('build_dev', ['ts:client', 'ts:server', 'less', 'concat:js_dependencies']);
  grunt.registerTask('build_min', ['ts:client_prod', 'uglify', 'ts:server', 'less', 'concat:js_dependencies_min']);
  grunt.registerTask('default', ['build_dev', 'watch']);
  grunt.registerTask('postinstall', ['copy', 'build_min']);
};<commit_msg>Add wildcard paths to grunt watch<commit_after>module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-ts');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-open');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    ts: {
      options: {
        removeComments: false,
      },
      client: {
        src: ['client/**/*.ts'],
        out: 'public/js/ImprovedInitiative.js',
        options: {
          fast: 'never',
          inlineSources: true
        }
      },
      client_prod: {
        src: ['client/**/*.ts'],
        out: 'build/ImprovedInitiative.js'
      },
      server: {
        src: ['server/*.ts'],
        outDir: '.',
        options: {
          module: 'commonjs',
          target: 'es5'
        }
      },
    },
    uglify: {
      options: {
        mangle: false
      },
      prod: {
        files: {
          'public/js/ImprovedInitiative.js': ['build/ImprovedInitiative.js']
        }
      }
    },
    less: {
      default: {
        files: {
          "public/css/improved-initiative.css": ["lesscss/improved-initiative.less"]
        }
      }
    },
    concat: {
      js_dependencies: {
        src: [
          'node_modules/knockout/build/output/knockout-latest.debug.js',
          'node_modules/knockout-mapping/dist/knockout.mapping.js',
          'node_modules/jquery/dist/jquery.js',
          'node_modules/awesomplete/awesomplete.js',
          'node_modules/mousetrap/mousetrap.js',
          'node_modules/socket.io-client/dist/socket.io.js',
          'node_modules/moment/moment.js',
          'node_modules/browser-filesaver/FileSaver.js',
          'node_modules/markdown-it/dist/markdown-it.js'        ],
        dest: 'public/js/dependencies.js',
        sourceMap: true
      },
      js_dependencies_min: {
        src: [
          'node_modules/knockout/build/output/knockout-latest.js',
          'node_modules/knockout-mapping/dist/knockout.mapping.min.js',
          'node_modules/jquery/dist/jquery.min.js',
          'node_modules/awesomplete/awesomplete.min.js',
          'node_modules/mousetrap/mousetrap.min.js',
          'node_modules/socket.io-client/dist/socket.io.min.js',
          'node_modules/moment/min/moment.min.js',
          'node_modules/browser-filesaver/FileSaver.min.js',
          'node_modules/markdown-it/dist/markdown-it.min.js'
        ],
        dest: 'public/js/dependencies.js'
      }
    },
    watch: {
      tsclient: {
        files: 'client/**/*.ts',
        tasks: ['ts:client']
      },
      tsserver: {
        files: 'server/**/*.ts',
        tasks: ['ts:server']
      },
      lesscss: {
        files: 'lesscss/**/*.less',
        tasks: ['less']
      }
    },
    copy: {
      main: {
        files: [
          { expand: true, cwd: 'node_modules/font-awesome/fonts/', src: ['**'], dest: 'public/fonts/' }
        ]
      }
    }
  });

  grunt.registerTask('build_dev', ['ts:client', 'ts:server', 'less', 'concat:js_dependencies']);
  grunt.registerTask('build_min', ['ts:client_prod', 'uglify', 'ts:server', 'less', 'concat:js_dependencies_min']);
  grunt.registerTask('default', ['build_dev', 'watch']);
  grunt.registerTask('postinstall', ['copy', 'build_min']);
};<|endoftext|>


<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component, PropTypes } from 'react';
import moment from 'moment';
import KeyboardAccelerators from '../utils/KeyboardAccelerators';
import Drop from '../utils/Drop';
import { findAncestor, isDescendant } from '../utils/DOM';
import Button from './Button';
import ClockIcon from './icons/base/Clock';
import CalendarIcon from './icons/base/Calendar';
import DateTimeDrop from './DateTimeDrop';
import CSSClassnames from '../utils/CSSClassnames';

const CLASS_ROOT = CSSClassnames.DATE_TIME;
const FORM_FIELD = CSSClassnames.FORM_FIELD;
const FORMATS = {
  M: 'months',
  D: 'days',
  Y: 'years',
  H: 'hours',
  h: 'hours',
  m: 'minutes',
  s: 'seconds'
};
const TIME_REGEXP = new RegExp('[hmsa]');

export default class DateTime extends Component {

  constructor(props) {
    super(props);

    this._onInputChange = this._onInputChange.bind(this);
    this._onOpen = this._onOpen.bind(this);
    this._onClose = this._onClose.bind(this);
    this._onNext = this._onNext.bind(this);
    this._onPrevious = this._onPrevious.bind(this);
    this._cursorScope = this._cursorScope.bind(this);
    this._notify = this._notify.bind(this);

    this.state = this._stateFromProps(props);
    this.state.cursor = -1;
    this.state.dropActive = false;
  }

  componentDidMount () {
    this._activation(this.state.dropActive);
  }

  componentWillReceiveProps (newProps) {
    this.setState(this._stateFromProps(newProps));
  }

  componentDidUpdate (prevProps, prevState) {
    // Set up keyboard listeners appropriate to the current state.
    if (prevState.dropActive !== this.state.dropActive) {
      this._activation(this.state.dropActive);
    }

    if (this.state.dropActive) {
      this._drop.render(this._renderDrop());
    }

    if (this.state.cursor >= 0) {
      this.refs.input.setSelectionRange(this.state.cursor,this.state.cursor);
    }
  }

  componentWillUnmount () {
    this._activation(false);
  }

  _stateFromProps (props) {
    const { value, format } = props;
    let result = { current: undefined };
    const date = moment(value, format);
    if (date.isValid()) {
      result.current = date;
    } else {
      result.current = moment().startOf('hour').add(1, 'hour');
    }
    // figure out which scope the step should apply to
    if (format.indexOf('s') !== -1) {
      result.stepScope = 'second';
    } else if (format.indexOf('m') !== -1) {
      result.stepScope = 'minute';
    } else if (format.indexOf('h') !== -1) {
      result.stepScope = 'hour';
    }
    return result;
  }

  _onInputChange (event) {
    const { format, onChange } = this.props;
    const value = event.target.value;
    if (value.length > 0) {
      const date = moment(value, format);
      // Only notify if the value looks valid
      if (date.isValid() && ! date.parsingFlags().charsLeftOver) {
        if (onChange) {
          onChange(value);
        }
      } else if (typeof this.props.value === 'string' &&
        value.length < this.props.value.length) {
        // or if the user is removing characters
        if (onChange) {
          onChange(value);
        }
      }
    } else {
      if (onChange) {
        onChange(value);
      }
    }
  }

  _notify (date) {
    if (this.props.onChange) {
      this.props.onChange(date);
    }
  }

  _onOpen (event) {
    event.preventDefault();
    this.setState({dropActive: true});
  }

  _onClose (event) {
    const drop = document.getElementById('date-time-drop');
    if (! isDescendant(this.refs.component, event.target) &&
      ! isDescendant(drop, event.target)) {
      this.setState({dropActive: false, cursor: -1});
    }
  }

  _onNext (event) {
    event.preventDefault();
    let date = this.state.current.clone();
    const scope = this._cursorScope();
    if ('a' === scope) {
      if (date.hours() < 12) {
        date.add(12, 'hours');
      }
    } else if ('m' === scope) {
      date.add(this.props.step, FORMATS[scope]);
    } else {
      date.add(1, FORMATS[scope]);
    }
    this.setState({ current: date }, this._notify(date));
  }

  _onPrevious (event) {
    event.preventDefault();
    let date = this.state.current.clone();
    const scope = this._cursorScope();
    if ('a' === scope) {
      if (date.hours() >= 12) {
        date.subtract(12, 'hours');
      }
    } else if ('m' === scope) {
      date.subtract(this.props.step, FORMATS[scope]);
    } else {
      date.subtract(1, FORMATS[scope]);
    }
    this.setState({ current: date }, this._notify(date));
  }

  _cursorScope () {
    const { format } = this.props;
    const input = this.refs.input;
    const value = input.value;
    const end = input.selectionEnd;
    this.setState({ cursor: end });
    // Figure out which aspect of the date the cursor is on, so we know what
    // to change.
    const preDate = moment(value.slice(0, end+1), format);
    const formatTokens = format.split(/[^A-Za-z]/);
    const unusedTokens = preDate.parsingFlags().unusedTokens;
    let index = -1;
    while (formatTokens[index+1] !== unusedTokens[0]) {
      index += 1;
    }
    return formatTokens[index][0];
  }

  _activation (dropActive) {

    var listeners = {
      esc: this._onClose,
      tab: this._onClose,
      enter: this._onSelectDate,
      up: this._onPrevious,
      down: this._onNext
    };

    if (dropActive) {

      document.addEventListener('click', this._onClose);
      KeyboardAccelerators.startListeningToKeyboard(this, listeners);

      // If this is inside a FormField, place the drop in reference to it.
      const control =
        findAncestor(this.refs.component, `.${FORM_FIELD}`) || this.refs.component;
      this._drop = Drop.add(control,
        this._renderDrop(), { align: {top: 'bottom', left: 'left'} });

    } else {

      document.removeEventListener('click', this._onClose);
      KeyboardAccelerators.stopListeningToKeyboard(this, listeners);

      if (this._drop) {
        this._drop.remove();
        this._drop = null;
      }
    }
  }

  _renderDrop () {
    return (
      <DateTimeDrop format={this.props.format} value={this.state.current}
        step={this.props.step} onChange={this._notify} />
    );
  }

  render () {
    const { className, format, id, name } = this.props;
    const { dropActive } = this.state;
    let { value } = this.props;
    let classes = [CLASS_ROOT];
    if (dropActive) {
      classes.push(`${CLASS_ROOT}--active`);
    }
    if (className) {
      classes.push(className);
    }
    if (value instanceof Date) {
      value = moment(value).format(format);
    } else if ((value !== null) && (typeof value === 'object')) {
      value = value.format(format);
    }
    const Icon = (TIME_REGEXP.test(format) ? ClockIcon : CalendarIcon);

    return (

        <input ref="input" className={`${CLASS_ROOT}__input`}
          id={id} placeholder={format} name={name} value={value}
          onChange={this._onInputChange} onFocus={this._onOpen} />
        <Button className={`${CLASS_ROOT}__control`} icon={<Icon />}
          onClick={this._onOpen} />

    );
  }

}

DateTime.propTypes = {
  format: PropTypes.string,
  id: PropTypes.string,
  name: PropTypes.string,
  onChange: PropTypes.func,
  step: PropTypes.number,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
};

DateTime.defaultProps = {
  format: 'M/D/YYYY h:mm a',
  step: 1
};
<commit_msg>Stylistic syntax update<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component, PropTypes } from 'react';
import moment from 'moment';
import KeyboardAccelerators from '../utils/KeyboardAccelerators';
import Drop from '../utils/Drop';
import { findAncestor, isDescendant } from '../utils/DOM';
import Button from './Button';
import ClockIcon from './icons/base/Clock';
import CalendarIcon from './icons/base/Calendar';
import DateTimeDrop from './DateTimeDrop';
import CSSClassnames from '../utils/CSSClassnames';

const CLASS_ROOT = CSSClassnames.DATE_TIME;
const FORM_FIELD = CSSClassnames.FORM_FIELD;
const FORMATS = {
  M: 'months',
  D: 'days',
  Y: 'years',
  H: 'hours',
  h: 'hours',
  m: 'minutes',
  s: 'seconds'
};
const TIME_REGEXP = new RegExp('[hmsa]');

export default class DateTime extends Component {

  constructor(props) {
    super(props);

    this._onInputChange = this._onInputChange.bind(this);
    this._onOpen = this._onOpen.bind(this);
    this._onClose = this._onClose.bind(this);
    this._onNext = this._onNext.bind(this);
    this._onPrevious = this._onPrevious.bind(this);
    this._cursorScope = this._cursorScope.bind(this);
    this._notify = this._notify.bind(this);

    this.state = this._stateFromProps(props);
    this.state.cursor = -1;
    this.state.dropActive = false;
  }

  componentDidMount () {
    this._activation(this.state.dropActive);
  }

  componentWillReceiveProps (newProps) {
    this.setState(this._stateFromProps(newProps));
  }

  componentDidUpdate (prevProps, prevState) {
    // Set up keyboard listeners appropriate to the current state.
    if (prevState.dropActive !== this.state.dropActive) {
      this._activation(this.state.dropActive);
    }

    if (this.state.dropActive) {
      this._drop.render(this._renderDrop());
    }

    if (this.state.cursor >= 0) {
      this.refs.input.setSelectionRange(this.state.cursor,this.state.cursor);
    }
  }

  componentWillUnmount () {
    this._activation(false);
  }

  _stateFromProps (props) {
    const { value, format } = props;
    let result = { current: undefined };
    const date = moment(value, format);
    if (date.isValid()) {
      result.current = date;
    } else {
      result.current = moment().startOf('hour').add(1, 'hour');
    }
    // figure out which scope the step should apply to
    if (format.indexOf('s') !== -1) {
      result.stepScope = 'second';
    } else if (format.indexOf('m') !== -1) {
      result.stepScope = 'minute';
    } else if (format.indexOf('h') !== -1) {
      result.stepScope = 'hour';
    }
    return result;
  }

  _onInputChange (event) {
    const { format, onChange } = this.props;
    const value = event.target.value;
    if (value.length > 0) {
      const date = moment(value, format);
      // Only notify if the value looks valid
      if (date.isValid() && ! date.parsingFlags().charsLeftOver) {
        if (onChange) {
          onChange(value);
        }
      } else if (typeof this.props.value === 'string' &&
        value.length < this.props.value.length) {
        // or if the user is removing characters
        if (onChange) {
          onChange(value);
        }
      }
    } else {
      if (onChange) {
        onChange(value);
      }
    }
  }

  _notify (date) {
    if (this.props.onChange) {
      this.props.onChange(date);
    }
  }

  _onOpen (event) {
    event.preventDefault();
    this.setState({dropActive: true});
  }

  _onClose (event) {
    const drop = document.getElementById('date-time-drop');
    if (! isDescendant(this.refs.component, event.target) &&
      ! isDescendant(drop, event.target)) {
      this.setState({dropActive: false, cursor: -1});
    }
  }

  _onNext (event) {
    event.preventDefault();
    let date = this.state.current.clone();
    const scope = this._cursorScope();
    if ('a' === scope) {
      if (date.hours() < 12) {
        date.add(12, 'hours');
      }
    } else if ('m' === scope) {
      date.add(this.props.step, FORMATS[scope]);
    } else {
      date.add(1, FORMATS[scope]);
    }
    this.setState({ current: date }, this._notify(date));
  }

  _onPrevious (event) {
    event.preventDefault();
    let date = this.state.current.clone();
    const scope = this._cursorScope();
    if ('a' === scope) {
      if (date.hours() >= 12) {
        date.subtract(12, 'hours');
      }
    } else if ('m' === scope) {
      date.subtract(this.props.step, FORMATS[scope]);
    } else {
      date.subtract(1, FORMATS[scope]);
    }
    this.setState({ current: date }, this._notify(date));
  }

  _cursorScope () {
    const { format } = this.props;
    const input = this.refs.input;
    const value = input.value;
    const end = input.selectionEnd;
    this.setState({ cursor: end });
    // Figure out which aspect of the date the cursor is on, so we know what
    // to change.
    const preDate = moment(value.slice(0, end+1), format);
    const formatTokens = format.split(/[^A-Za-z]/);
    const unusedTokens = preDate.parsingFlags().unusedTokens;
    let index = -1;
    while (formatTokens[index+1] !== unusedTokens[0]) {
      index += 1;
    }
    return formatTokens[index][0];
  }

  _activation (dropActive) {

    var listeners = {
      esc: this._onClose,
      tab: this._onClose,
      enter: this._onSelectDate,
      up: this._onPrevious,
      down: this._onNext
    };

    if (dropActive) {

      document.addEventListener('click', this._onClose);
      KeyboardAccelerators.startListeningToKeyboard(this, listeners);

      // If this is inside a FormField, place the drop in reference to it.
      const control =
        findAncestor(this.refs.component, `.${FORM_FIELD}`) || this.refs.component;
      this._drop = Drop.add(control,
        this._renderDrop(), { align: {top: 'bottom', left: 'left'} });

    } else {

      document.removeEventListener('click', this._onClose);
      KeyboardAccelerators.stopListeningToKeyboard(this, listeners);

      if (this._drop) {
        this._drop.remove();
        this._drop = null;
      }
    }
  }

  _renderDrop () {
    return (
      <DateTimeDrop format={this.props.format} value={this.state.current}
        step={this.props.step} onChange={this._notify} />
    );
  }

  render () {
    const { className, format, id, name } = this.props;
    const { dropActive } = this.state;
    let { value } = this.props;
    let classes = [CLASS_ROOT];
    if (dropActive) {
      classes.push(`${CLASS_ROOT}--active`);
    }
    if (className) {
      classes.push(className);
    }
    if (value instanceof Date) {
      value = moment(value).format(format);
    } else if (value && typeof value === 'object') {
      value = value.format(format);
    }
    const Icon = (TIME_REGEXP.test(format) ? ClockIcon : CalendarIcon);

    return (

        <input ref="input" className={`${CLASS_ROOT}__input`}
          id={id} placeholder={format} name={name} value={value}
          onChange={this._onInputChange} onFocus={this._onOpen} />
        <Button className={`${CLASS_ROOT}__control`} icon={<Icon />}
          onClick={this._onOpen} />

    );
  }

}

DateTime.propTypes = {
  format: PropTypes.string,
  id: PropTypes.string,
  name: PropTypes.string,
  onChange: PropTypes.func,
  step: PropTypes.number,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
};

DateTime.defaultProps = {
  format: 'M/D/YYYY h:mm a',
  step: 1
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-tizen');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadTasks('tools/grunt-tasks');

  grunt.initConfig({
    packageInfo: grunt.file.readJSON('package.json'),
    chromeInfo: grunt.file.readJSON('data/manifest.json'),

    clean: ['build'],

    tizen_configuration: {
      // location on the device to install the tizen-app.sh script to
      // (default: '/tmp')
      tizenAppScriptDir: '/home/developer/',

      // path to the config.xml file for the Tizen wgt file
      // (default: 'config.xml')
      configFile: 'data/config.xml',

      // path to the sdb command (default: process.env.SDB or 'sdb')
      sdbCmd: 'sdb'
    },

    // minify JS
    uglify: {
      dist: {
        files: {
          'build/app/js/main.js': ['app/js/main.js'],
          'build/app/js/license.js': ['app/js/license.js'],
          'build/app/js/scaleBody.js': ['app/js/scaleBody.js']
        }
      }
    },

    // minify CSS
    cssmin: {
      dist: {
        files: {
          'build/app/css/main.css': ['app/css/main.css'],
          'build/app/css/fonts.css': ['app/css/fonts.css'],
          'build/app/css/license.css': ['app/css/license.css']
        }
      }
    },

    copy: {
      common: {
        files: [
          { expand: true, cwd: '.', src: ['app/lib/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/audio/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['LICENSE'], dest: 'build/app/' },
          { expand: true, cwd: '.', src: ['README.txt'], dest: 'build/app/' },
          { expand: true, cwd: '.', src: ['app/_locales/**'], dest: 'build/' }
        ]
      },
      wgt: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/wgt/' },
          { expand: true, cwd: 'data/', src: ['config.xml'], dest: 'build/wgt/' },
          { expand: true, cwd: '.', src: ['icon_128.png'], dest: 'build/wgt/' }
        ]
      },
      crx: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['manifest.json'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/crx/' }
        ]
      },
      sdk: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/css/', src: ['*.css'], dest: 'build/sdk/css/' },
          { expand: true, cwd: 'app/js/', src: ['*.js'], dest: 'build/sdk/js/' },
          { expand: true, cwd: 'app/', src: ['*.html'], dest: 'build/sdk/' },
          { expand: true, cwd: 'data/', src: ['config.xml'], dest: 'build/sdk/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/sdk/' }
        ]
      }
    },

    htmlmin: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: ['app/*.html'], dest: 'build/' }
        ],
        options: {
          removeComments: true,
          collapseWhitespace: true,
          removeCommentsFromCDATA: false,
          removeCDATASectionsFromCDATA: false,
          removeEmptyAttributes: true,
          removeEmptyElements: false
        }
      }
    },

    imagemin: {
      dist: {
        options: {
          optimizationLevel: 3,
          progressive: true
        },
        files: [
          { expand: true, cwd: '.', src: ['app/images/**'], dest: 'build/' }
        ]
      }
    },

    // make wgt package in build/ directory
    package: {
      wgt: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/wgt/**',
        stripPrefix: 'build/wgt/',
        outDir: 'build',
        suffix: '.wgt',
        addGitCommitId: false
      },
      sdk: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/sdk/**',
        stripPrefix: 'build/sdk/',
        outDir: 'build',
        suffix: '.wgt',
      }
    },

    simple_server: {
      port: 30303,
      dir: 'build/app/'
    },

    tizen: {
      push: {
        action: 'push',
        localFiles: {
          pattern: 'build/*.wgt',
          filter: 'latest'
        },
        remoteDir: '/home/developer/'
      },

      install: {
        action: 'install',
        remoteFiles: {
          pattern: '/home/developer/bubblewrap*.wgt',
          filter: 'latest'
        }
      },

      uninstall: {
        action: 'uninstall'
      },

      start: {
        action: 'start',
        stopOnFailure: true
      },

      stop: {
        action: 'stop',
        stopOnFailure: false
      },

      debug: {
        action: 'debug',
        browserCmd: 'google-chrome %URL%',
        localPort: 9090,
        stopOnFailure: true
      }
    }
  });

  grunt.registerTask('dist', [
    'clean',
    'imagemin:dist',
    'uglify:dist',
    'cssmin:dist',
    'htmlmin:dist',
    'copy:common'
  ]);

  grunt.registerTask('crx', ['dist', 'copy:crx']);
  grunt.registerTask('wgt', ['dist', 'copy:wgt', 'package:wgt']);

  grunt.registerTask('sdk', [
    'clean',
    'imagemin:dist',
    'copy:common',
    'copy:sdk',
    'package:sdk'
  ]);

  grunt.registerTask('perf', [
    'dist',
    'uglify:perf',
    'inline',
    'copy:wgt',
    'package:wgt'
  ]);

  grunt.registerTask('install', [
    'tizen:push',
    'tizen:stop',
    'tizen:uninstall',
    'tizen:install',
    'tizen:start'
  ]);

  grunt.registerTask('wait', function () {
    var done = this.async();
    setTimeout(function () {
      done();
    }, 10000);
  });

  grunt.registerTask('restart', ['tizen:stop', 'tizen:start']);

  grunt.registerTask('server', ['dist', 'simple_server']);

  grunt.registerTask('wgt-install', ['wgt', 'install']);
  grunt.registerTask('sdk-install', ['sdk', 'install']);

  grunt.registerTask('default', 'wgt');
};
<commit_msg>Adjusting sdk grunt target.<commit_after>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-tizen');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-htmlmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadTasks('tools/grunt-tasks');

  grunt.initConfig({
    packageInfo: grunt.file.readJSON('package.json'),
    chromeInfo: grunt.file.readJSON('data/manifest.json'),

    clean: ['build'],

    tizen_configuration: {
      // location on the device to install the tizen-app.sh script to
      // (default: '/tmp')
      tizenAppScriptDir: '/home/developer/',

      // path to the config.xml file for the Tizen wgt file
      // (default: 'config.xml')
      configFile: 'data/config.xml',

      // path to the sdb command (default: process.env.SDB or 'sdb')
      sdbCmd: 'sdb'
    },

    // minify JS
    uglify: {
      dist: {
        files: {
          'build/app/js/main.js': ['app/js/main.js'],
          'build/app/js/license.js': ['app/js/license.js'],
          'build/app/js/scaleBody.js': ['app/js/scaleBody.js']
        }
      }
    },

    // minify CSS
    cssmin: {
      dist: {
        files: {
          'build/app/css/main.css': ['app/css/main.css'],
          'build/app/css/fonts.css': ['app/css/fonts.css'],
          'build/app/css/license.css': ['app/css/license.css']
        }
      }
    },

    copy: {
      common: {
        files: [
          { expand: true, cwd: '.', src: ['app/lib/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['app/audio/**'], dest: 'build/' },
          { expand: true, cwd: '.', src: ['LICENSE'], dest: 'build/app/' },
          { expand: true, cwd: '.', src: ['README.txt'], dest: 'build/app/' },
          { expand: true, cwd: '.', src: ['app/_locales/**'], dest: 'build/' }
        ]
      },
      wgt: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/wgt/' },
          { expand: true, cwd: 'data/', src: ['config.xml'], dest: 'build/wgt/' },
          { expand: true, cwd: '.', src: ['icon_128.png'], dest: 'build/wgt/' }
        ]
      },
      crx: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['manifest.json'], dest: 'build/crx/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/crx/' }
        ]
      },
      sdk: {
        files: [
          { expand: true, cwd: 'build/app/', src: ['**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['js/**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['css/**'], dest: 'build/sdk/' },
          { expand: true, cwd: 'app/', src: ['*.html'], dest: 'build/sdk/' },
          { expand: true, cwd: 'data/', src: ['config.xml'], dest: 'build/sdk/' },
          { expand: true, cwd: '.', src: ['icon*.png'], dest: 'build/sdk/' }
        ]
      }
    },

    htmlmin: {
      dist: {
        files: [
          { expand: true, cwd: '.', src: ['app/*.html'], dest: 'build/' }
        ],
        options: {
          removeComments: true,
          collapseWhitespace: true,
          removeCommentsFromCDATA: false,
          removeCDATASectionsFromCDATA: false,
          removeEmptyAttributes: true,
          removeEmptyElements: false
        }
      }
    },

    imagemin: {
      dist: {
        options: {
          optimizationLevel: 3,
          progressive: true
        },
        files: [
          { expand: true, cwd: '.', src: ['app/images/**'], dest: 'build/' }
        ]
      }
    },

    // make wgt package in build/ directory
    package: {
      wgt: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/wgt/**',
        stripPrefix: 'build/wgt/',
        outDir: 'build',
        suffix: '.wgt',
        addGitCommitId: false
      },
      sdk: {
        appName: '<%= packageInfo.name %>',
        version: '<%= packageInfo.version %>',
        files: 'build/sdk/**',
        stripPrefix: 'build/sdk/',
        outDir: 'build',
        suffix: '.wgt',
      }
    },

    simple_server: {
      port: 30303,
      dir: 'build/app/'
    },

    tizen: {
      push: {
        action: 'push',
        localFiles: {
          pattern: 'build/*.wgt',
          filter: 'latest'
        },
        remoteDir: '/home/developer/'
      },

      install: {
        action: 'install',
        remoteFiles: {
          pattern: '/home/developer/bubblewrap*.wgt',
          filter: 'latest'
        }
      },

      uninstall: {
        action: 'uninstall'
      },

      start: {
        action: 'start',
        stopOnFailure: true
      },

      stop: {
        action: 'stop',
        stopOnFailure: false
      },

      debug: {
        action: 'debug',
        browserCmd: 'google-chrome %URL%',
        localPort: 9090,
        stopOnFailure: true
      }
    }
  });

  grunt.registerTask('dist', [
    'clean',
    'imagemin:dist',
    'uglify:dist',
    'cssmin:dist',
    'htmlmin:dist',
    'copy:common'
  ]);

  grunt.registerTask('crx', ['dist', 'copy:crx']);
  grunt.registerTask('wgt', ['dist', 'copy:wgt', 'package:wgt']);

  grunt.registerTask('sdk', [
    'clean',
    'imagemin:dist',
    'copy:common',
    'copy:sdk',
    'package:sdk'
  ]);

  grunt.registerTask('perf', [
    'dist',
    'uglify:perf',
    'inline',
    'copy:wgt',
    'package:wgt'
  ]);

  grunt.registerTask('install', [
    'tizen:push',
    'tizen:stop',
    'tizen:uninstall',
    'tizen:install',
    'tizen:start'
  ]);

  grunt.registerTask('wait', function () {
    var done = this.async();
    setTimeout(function () {
      done();
    }, 10000);
  });

  grunt.registerTask('restart', ['tizen:stop', 'tizen:start']);

  grunt.registerTask('server', ['dist', 'simple_server']);

  grunt.registerTask('wgt-install', ['wgt', 'install']);
  grunt.registerTask('sdk-install', ['sdk', 'install']);

  grunt.registerTask('default', 'wgt');
};
<|endoftext|>


<commit_before>/** @jsx React.DOM */

var _ = require("underscore");
var React = require("react/addons");

var Dropdown = React.createClass({

  displayName: "Dropdown",

  actions_configuration: {
    state: {
      open: function (isOpen) {
        if (isOpen) {
          return this.props.caption.replace(/\s+/g, "");
        } else {
          return this.props.caption.replace(/\s+/g, "");
        }
      }
    }
  },

  propTypes: {
    caption: React.PropTypes.string,
    handleItemSelection: React.PropTypes.func.isRequired,
    resetElement: React.PropTypes.object,
    items: React.PropTypes.array.isRequired
  },

  getDefaultProps: function () {
    return {
      caption: "Dropdown"
    };
  },

  getInitialState: function () {
    return {
      open: false,
      selectedItem: null
    };
  },

  handleMouseEnter: function () {
    this.preventBlur = true;
  },

  handleMouseLeave: function () {
    this.preventBlur = false;
  },

  handleButtonBlur: function () {
    if (!this.preventBlur) {
      this.setState({open: false});
    }
  },

  handleMenuToggle: function () {
    this.setState({
      open: !this.state.open
    });
  },

  onItemClick: function (item) {
    this.props.handleItemSelection(item);

    this.setState({
      open: false,
      selectedItem: item
    });
  },

  getCurrentItem: function () {
    if (this.state.selectedItem &&
        this.props.resetElement.id !== this.state.selectedItem.id) {
      return this.state.selectedItem.render();
    }

    return this.props.caption;
  },

  getItems: function () {
    return _.map(this.props.items, function (item, i) {
      return (

            {item.render()}

      );
    }, this);
  },

  render: function () {
    var resetElement = this.props.resetElement;

    var dropdownClassSet = React.addons.classSet({
      "dropdown": true,
      "open": this.state.open
    });

    var resetClassSet = React.addons.classSet({
      "clickable": true,
      "hidden": resetElement == null
    });

    return (

        <button type="button"
            className="button button-medium button-inverse dropdown-toggle"
            ref="button"
            onClick={this.handleMenuToggle}
            onBlur={this.handleButtonBlur}>
          {this.getCurrentItem()}
        </button>

                  {resetElement.render()}

            {this.getItems()}

    );
  }
});

module.exports = Dropdown;
<commit_msg>Using children in dropdown<commit_after>/** @jsx React.DOM */

var _ = require("underscore");
var React = require("react/addons");

var InternalStorageMixin = require("../mixins/InternalStorageMixin");

var Dropdown = React.createClass({

  displayName: "Dropdown",

  actions_configuration: {
    state: {
      open: function (isOpen) {
        if (isOpen) {
          return this.props.caption.replace(/\s+/g, "");
        } else {
          return this.props.caption.replace(/\s+/g, "");
        }
      }
    }
  },

  propTypes: {
    caption: React.PropTypes.string,
    defaultKey: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number
    ]),
    getCurrentItem: React.PropTypes.func,
    handleItemSelection: React.PropTypes.func.isRequired
  },

  mixins: [InternalStorageMixin],

  getDefaultProps: function () {
    return {
      caption: "Dropdown",
      getCurrentItem: this.getCurrentItem
    };
  },

  componentWillMount: function () {
    this.internalStorage_set({selectedKey: this.props.defaultKey});
  },

  getInitialState: function () {
    return {
      open: false
    };
  },

  handleMouseEnter: function () {
    this.preventBlur = true;
  },

  handleMouseLeave: function () {
    this.preventBlur = false;
  },

  handleButtonBlur: function () {
    if (!this.preventBlur) {
      this.setState({open: false});
    }
  },

  handleMenuToggle: function () {
    this.setState({
      open: !this.state.open
    });
  },

  onItemClick: function (key) {
    this.props.handleItemSelection(key);

    this.internalStorage_set({selectedKey: key});
    this.setState({
      open: false
    });
  },

  getCurrentItem: function (key, children) {
    return _.find(children, function (item) {
      return item.key === key;
    });
  },

  getItems: function () {
    return _.map(this.props.children, function (item) {
      var key = item.key;
      return (

            {item}

      );
    }, this);
  },

  render: function () {
    var data = this.internalStorage_get();

    var dropdownClassSet = React.addons.classSet({
      "dropdown": true,
      "open": this.state.open
    });

    return (

        <button type="button"
            className="button button-medium button-inverse dropdown-toggle"
            ref="button"
            onClick={this.handleMenuToggle}
            onBlur={this.handleButtonBlur}>
          {this.props.getCurrentItem(data.selectedKey, this.props.children)}
        </button>

            {this.getItems()}

    );
  }
});

module.exports = Dropdown;
<|endoftext|>