<commit_before>/*
*	Take in an image, convert it to a bunch of colourful nodes painted onto a canvas then animate those notes so they
* dynamically move away from the mouse while hovering or towards it while the left mouse button is held down.
* Adam Hartwell 2014.
*/

/*** Shim for ensuring animation always works ***/
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
//
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

/*** Contain within a module for re-usability ***/
var Nodulator = {

	settings: {
		inputID: 'imageLoader', // ID of image input element to add listener to
		canvasID: 'nodeBox',

		nodeSparsity: 12,       // Distance(px) between nodes on creation
		drawThreshold: 220,     // Grayscale threshold; pixels whiter than this value will not be converted to nodes (0-255)

		nodeRadius: 5,          // Radius(px) of nodes when drawn
		pushRating: 150,        // To minimise computation these ratings are used; fairly arbitary
		pullRating: 50,         // higher number = greater push/pull strength
		returnPercent: 0.05,    // Percentage of distance moved back towards starting point each frame

		mouseOutDistance: -9999 // When off canvas assume mouse is arbitrarily too far away to affect nodes
	},

	canvas: null, // Canvas data
	ctx: null,    // Canvas context data

	nodes: [],    // Array for nodes; each node is an object containing current and initial X & Y co-ordinates and the nodes colour

	mouse: {      // Mouse starting set up as far as canvas is concerned
		x: -9999,
		y: -9999,
		down: false
	},

	/*** Add listeners then start animating using a default image ***/
	init: function() {
		this.canvas = document.getElementById(this.settings.canvasID);
		this.ctx = this.canvas.getContext('2d');

		this.ctx.canvas.width  = window.innerWidth; //Set canvas to current window size - minus space for image input
		this.ctx.canvas.height = window.innerHeight - 50;

		document.getElementById(this.settings.inputID).addEventListener('change', this.updateImage, false);

		/* Mouse listeners */
		window.addEventListener('mouseup',   this.mouseUp,   false);	// Detect mouse up/down anywhere
		window.addEventListener('mousedown', this.mouseDown, false);
		this.canvas.addEventListener('mouseout',  this.mouseLeave,  false);
		this.canvas.addEventListener('mousemove', this.mouseMove, false);

		/* Touch screen listeners */
		var touchable = 'createTouch' in document; // Check whether to add the relevant listeners

		if(touchable) {
			this.canvas.addEventListener("touchstart", this.mouseMove, false);
			this.canvas.addEventListener("touchmove", this.mouseMove, false);
			this.canvas.addEventListener("touchend", this.mouseUp, false);
			this.canvas.addEventListener("touchcancel", this.mouseLeave, false);
			this.canvas.addEventListener("touchleave", this.mouseLeave, false);
		}

		this.generateNodes('default.jpg'); 	// Create nodes based on default image and start animating
	},

	/*** Recursive animation of nodes ***/
	animate: function() {
		 this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); //Clear

		 /* Update and redraw */
		 this.updateNodes();
		 this.drawNodes();

		 requestAnimationFrame(function(){ Nodulator.animate() }); //Get new frame (see below for compatability shim)
	},

	/*** Calculate how far nodes should move to avoid the mouse - update positions accordingly ***/
	updateNodes: function() { // Work in polar format with radians (save conversions) where the node is in relation to the mouse
		var i, angle, distance;
		for (i = 0; i < this.nodes.length; i++ ){
			angle = Math.atan2(this.nodes[i].y - this.mouse.y, this.nodes[i].x - this.mouse.x);
			distance =  Math.sqrt(Math.pow(this.mouse.x - this.nodes[i].x,2) + Math.pow(this.mouse.y - this.nodes[i].y,2));

			/* Calculate new position for nodes based on distance from mouse and from its origin */
			if (!this.mouse.down) { // Move away from mouse
				this.nodes[i].x += Math.cos(angle) * (this.settings.pushRating / distance) + (this.nodes[i].initX - this.nodes[i].x)
					* this.settings.returnPercent;
				this.nodes[i].y += Math.sin(angle) * (this.settings.pushRating / distance) + (this.nodes[i].initY - this.nodes[i].y)
					* this.settings.returnPercent;
			} else if (distance > 10) { // Suck towards mouse if pull is sufficient (and mouse down) - stop moving when near to mouse
				this.nodes[i].x += Math.cos(angle) * -(this.settings.pullRating / distance) + (this.nodes[i].initX - this.nodes[i].x)
					* this.settings.returnPercent;
				this.nodes[i].y += Math.sin(angle) * -(this.settings.pullRating / distance) + (this.nodes[i].initY - this.nodes[i].y)
					* this.settings.returnPercent;
			}
		}
	},

	/*** Draw each node ***/
	drawNodes: function() {
		for(var i = 0; i < this.nodes.length; i++) {
			this.ctx.fillStyle = this.nodes[i].colour;
			this.ctx.strokeStyle = this.nodes[i].colour;
			this.ctx.beginPath();
			this.ctx.arc(this.nodes[i].x, this.nodes[i].y, this.settings.nodeRadius ,0 , 6.284); //6.284 instead of 2*pi used for effeciency
			this.ctx.closePath();
			this.ctx.fill();
		}
	},

	/*** Mouse functions ***/
	mouseDown: function(e) { // Note that mouse is down
		Nodulator.mouse.down = true;
	},

	mouseMove: function(e) { // Save mouse position (using whichever method works in current browser)
		Nodulator.mouse.x = e.offsetX || (e.layerX - Nodulator.canvas.offsetLeft);
		Nodulator.mouse.y = e.offsetY || (e.layerY - Nodulator.canvas.offsetTop);
	},

	mouseUp: function(e) {   // Note that mouse is up
		Nodulator.mouse.down = false;
	},

	mouseLeave: function(e) { // Move mouse far enough away to not affect nodes
		Nodulator.mouse.x = Nodulator.settings.mouseOutDistance;
		Nodulator.mouse.y = Nodulator.settings.mouseOutDistance;
	},

	/*** Load in new image and move on to generation nodes and animating immediately ***/
	updateImage: function(e) {
		var reader = new FileReader();
		reader.onload = function(event){
			Nodulator.generateNodes(event.target.result);
		}
		reader.readAsDataURL(e.target.files[0]);
	},

	/*** Take in an image source and convert it into the titular nodes***/
	generateNodes: function(src) {
		var img = new Image();

		img.onload = function() { // Draw onto canvas to access pixel data
			Nodulator.nodes =[];  // Flush any existing nodes

			Nodulator.ctx.clearRect(0, 0, Nodulator.canvas.width, Nodulator.canvas.height); // Clear canvas

			var offsetX = Math.floor((Nodulator.canvas.width - img.width) / 2);             // Center image within canvas
			var offsetY = Math.floor((Nodulator.canvas.height - img.height) / 2);

			Nodulator.ctx.drawImage(img, offsetX, offsetY); // Actual drawing

			/* Get image data and associated pixel data to work with */
			var imageData = Nodulator.ctx.getImageData(0, 0, Nodulator.canvas.width, Nodulator.canvas.height);
			var pixelData = imageData.data;
			var i, j, pos, colour, node; // Variables for loop

			/* Loop to check each pixel in a grid with spaces defined by this.nodeSparsity*/
			for (i = 0; i < Nodulator.canvas.width; i += Nodulator.settings.nodeSparsity) {
				for (j = 0; j < Nodulator.canvas.height; j += Nodulator.settings.nodeSparsity) {
					pos = (i + (j * imageData.width)) * 4;
					/* Data set up in 1D array: R-G-B-A and repeat */
					if (pixelData[pos] > Nodulator.settings.drawThreshold && pixelData[pos + 1] > Nodulator.settings.drawThreshold
					&& pixelData[pos + 2] > Nodulator.settings.drawThreshold  || pixelData[pos + 3] === 0) {
						continue; // Ignore pixels that are too white or are transparent (canvas background)
					} else {

						colour = 'rgba(' + pixelData[pos] + ',' + pixelData[pos + 1] + ',' + pixelData[pos + 2] + ',' + '1)';

						node = { // Node object literal
							x: i,
							y: j,
							initX: i,
							initY: j,
							colour: colour
						}
						Nodulator.nodes.push(node); // Append to the array of nodes
					}
				}
			}
			Nodulator.animate(); // Place here to ensure only started once node generation is complete
		};
		img.src = src;
	}
}

Nodulator.init(); //Start the Nodulator!!
<commit_msg>A little more prettification<commit_after>/*
* Take in an image, convert it to a bunch of colourful nodes painted onto a canvas then animate those notes so they
* dynamically move away from the mouse while hovering or towards it while the left mouse button is held down.
* Adam Hartwell 2014.
*/

/*** Shim for ensuring animation always works ***/
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
//
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

/*** Contain within a module for re-usability ***/
var Nodulator = {

	settings: {
		inputID: 'imageLoader', // ID of image input element to add listener to
		canvasID: 'nodeBox',

		nodeSparsity: 12,       // Distance(px) between nodes on creation
		drawThreshold: 220,     // Grayscale threshold; pixels whiter than this value will not be converted to nodes

		nodeRadius: 5,          // Radius(px) of nodes when drawn
		pushRating: 150,        // To minimise computation these ratings are used; fairly arbitary
		pullRating: 50,         // higher number = greater push/pull strength
		returnPercent: 0.05,    // Percentage of distance moved back towards starting point each frame

		mouseOutDistance: -9999 // When off canvas assume mouse is arbitrarily too far away to affect nodes
	},

	canvas: null, // Canvas data
	ctx: null,    // Canvas context data

	nodes: [],    // Array for nodes; each node contains current and initial X & Y co-ordinates and the nodes colour

	mouse: {      // Mouse starting set up as far as canvas is concerned
		x: -9999,
		y: -9999,
		down: false
	},

	/*** Add listeners then start animating using a default image ***/
	init: function() {
		this.canvas = document.getElementById(this.settings.canvasID);
		this.ctx = this.canvas.getContext('2d');

		this.ctx.canvas.width  = window.innerWidth; //Set canvas to current window size - minus space for image input
		this.ctx.canvas.height = window.innerHeight - 50;

		document.getElementById(this.settings.inputID).addEventListener('change', this.updateImage, false);

		/* Mouse listeners */
		window.addEventListener('mouseup',   this.mouseUp,   false);	// Detect mouse up/down anywhere
		window.addEventListener('mousedown', this.mouseDown, false);
		this.canvas.addEventListener('mouseout',  this.mouseLeave,  false);
		this.canvas.addEventListener('mousemove', this.mouseMove, false);

		/* Touch screen listeners */
		var touchable = 'createTouch' in document; // Check whether to add the relevant listeners

		if(touchable) {
			this.canvas.addEventListener("touchstart", this.mouseMove, false);
			this.canvas.addEventListener("touchmove", this.mouseMove, false);
			this.canvas.addEventListener("touchend", this.mouseUp, false);
			this.canvas.addEventListener("touchcancel", this.mouseLeave, false);
			this.canvas.addEventListener("touchleave", this.mouseLeave, false);
		}

		this.generateNodes('default.jpg'); 	// Create nodes based on default image and start animating
	},

	/*** Recursive animation of nodes ***/
	animate: function() {
		 this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); //Clear

		 /* Update and redraw */
		 this.updateNodes();
		 this.drawNodes();

		 requestAnimationFrame(function(){ Nodulator.animate() }); //Get new frame (see below for compatability shim)
	},

	/*** Calculate how far nodes should move to avoid the mouse - update positions accordingly ***/
	updateNodes: function() { // Work in polar format with radians where the node is in relation to the mouse
		var i, angle, distance;
		for (i = 0; i < this.nodes.length; i++ ){
			angle = Math.atan2(this.nodes[i].y - this.mouse.y, this.nodes[i].x - this.mouse.x);
			distance = Math.sqrt(Math.pow(this.mouse.x - this.nodes[i].x,2)
				+ Math.pow(this.mouse.y - this.nodes[i].y,2));

			/* Calculate new position for nodes based on distance from mouse and from its origin */
			if (!this.mouse.down) { // Move away from mouse
				this.nodes[i].x += Math.cos(angle) * (this.settings.pushRating / distance)
					+ (this.nodes[i].initX - this.nodes[i].x) * this.settings.returnPercent;
				this.nodes[i].y += Math.sin(angle) * (this.settings.pushRating / distance)
					+ (this.nodes[i].initY - this.nodes[i].y) * this.settings.returnPercent;
			} else if (distance > 10) { // Suck towards mouse if pull is sufficient - stop moving when near to mouse
				this.nodes[i].x += Math.cos(angle) * -(this.settings.pullRating / distance)
					+ (this.nodes[i].initX - this.nodes[i].x) * this.settings.returnPercent;
				this.nodes[i].y += Math.sin(angle) * -(this.settings.pullRating / distance)
					+ (this.nodes[i].initY - this.nodes[i].y) * this.settings.returnPercent;
			}
		}
	},

	/*** Draw each node ***/
	drawNodes: function() {
		for(var i = 0; i < this.nodes.length; i++) {
			this.ctx.fillStyle = this.nodes[i].colour;
			this.ctx.strokeStyle = this.nodes[i].colour;
			this.ctx.beginPath();
			this.ctx.arc(this.nodes[i].x, this.nodes[i].y, this.settings.nodeRadius ,0 , 6.284);
			this.ctx.closePath(); // 6.284 instead of 2*pi used for effeciency
			this.ctx.fill();
		}
	},

	/*** Mouse functions ***/
	mouseDown: function(e) { // Note that mouse is down
		Nodulator.mouse.down = true;
	},

	mouseMove: function(e) { // Save mouse position (using whichever method works in current browser)
		Nodulator.mouse.x = e.offsetX || (e.layerX - Nodulator.canvas.offsetLeft);
		Nodulator.mouse.y = e.offsetY || (e.layerY - Nodulator.canvas.offsetTop);
	},

	mouseUp: function(e) {   // Note that mouse is up
		Nodulator.mouse.down = false;
	},

	mouseLeave: function(e) { // Move mouse far enough away to not affect nodes
		Nodulator.mouse.x = Nodulator.settings.mouseOutDistance;
		Nodulator.mouse.y = Nodulator.settings.mouseOutDistance;
	},

	/*** Load in new image and move on to generation nodes and animating immediately ***/
	updateImage: function(e) {
		var reader = new FileReader();
		reader.onload = function(event){
			Nodulator.generateNodes(event.target.result);
		}
		reader.readAsDataURL(e.target.files[0]);
	},

	/*** Take in an image source and convert it into the titular nodes***/
	generateNodes: function(src) {
		var img = new Image();

		img.onload = function() { // Draw onto canvas to access pixel data
			Nodulator.nodes =[];  // Flush any existing nodes

			Nodulator.ctx.clearRect(0, 0, Nodulator.canvas.width, Nodulator.canvas.height); // Clear canvas

			var offsetX = Math.floor((Nodulator.canvas.width - img.width) / 2);             // Center image
			var offsetY = Math.floor((Nodulator.canvas.height - img.height) / 2);

			Nodulator.ctx.drawImage(img, offsetX, offsetY); // Actual drawing

			/* Get image data and associated pixel data to work with */
			var imageData = Nodulator.ctx.getImageData(0, 0, Nodulator.canvas.width, Nodulator.canvas.height);
			var pixelData = imageData.data;
			var i, j, pos, colour, node; // Variables for loop

			/* Loop to check each pixel in a grid with spaces defined by this.nodeSparsity*/
			for (i = 0; i < Nodulator.canvas.width; i += Nodulator.settings.nodeSparsity) {
				for (j = 0; j < Nodulator.canvas.height; j += Nodulator.settings.nodeSparsity) {
					pos = (i + (j * imageData.width)) * 4;
					/* Data set up in 1D array: R-G-B-A and repeat */
					if (pixelData[pos] > Nodulator.settings.drawThreshold
						&& pixelData[pos + 1] > Nodulator.settings.drawThreshold
						&& pixelData[pos + 2] > Nodulator.settings.drawThreshold  || pixelData[pos + 3] === 0) {
							continue; // Ignore pixels that are too white or are transparent (canvas background)
					} else {

						colour = 'rgba(' + pixelData[pos] +','+ pixelData[pos + 1] +','+ pixelData[pos + 2] +','+ '1)';

						node = { // Node object literal
							x: i,
							y: j,
							initX: i,
							initY: j,
							colour: colour
						}
						Nodulator.nodes.push(node); // Append to the array of nodes
					}
				}
			}
			Nodulator.animate(); // Place here to ensure only started once node generation is complete
		};
		img.src = src;
	}
}

Nodulator.init(); // Start the Nodulator!!
<|endoftext|>


<commit_before>// Copyright 2015, University of Colorado Boulder

/**
 * Full PhET-iO build including phet version, phet-io version and accompanying material.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */

// modules
var assert = require( 'assert' );
var copyDirectory = require( '../../../chipper/js/grunt/copyDirectory' );
var child_process = require( 'child_process' );
var ChipperStringUtils = require( '../../../chipper/js/common/ChipperStringUtils' );

/**
 * @param grunt the grunt instance
 * @param {Object} buildConfig
 */
module.exports = function( grunt, buildConfig ) {
  'use strict';

  var cwd = process.cwd();

  var phetioBuildDir = cwd + '/build-phet-io';
  var buildDir = cwd + '/build';

  // Clean
  if ( grunt.file.exists( phetioBuildDir ) ) {
    grunt.file.delete( phetioBuildDir );
  }
  grunt.file.mkdir( phetioBuildDir );

  var createOtherPhETIOFiles = function() {

    // create devguide/
    grunt.file.mkdir( 'build/phet-io/devguide' );
    copyDirectory( grunt, '../sherpa/lib/highlight.js-9.1.0', 'build/phet-io/devguide/lib/highlight.js-9.1.0' );
    copyDirectory( grunt, '../phet-io/doc/devguide', 'build/phet-io/devguide', function( abspath, contents ) {
      if ( abspath.indexOf( '.html' ) >= 0 ) {
        return ChipperStringUtils.replaceAll( contents, '../../../sherpa/lib/highlight.js-9.1.0', 'lib/highlight.js-9.1.0' );
      }
    } );

    // create protected/
    grunt.file.mkdir( 'build/phet-io/protected' );
    grunt.file.mkdir( 'build/phet-io/protected/lib' );
    grunt.file.mkdir( 'build/phet-io/protected/api' );
    grunt.file.mkdir( 'build/phet-io/protected/wrappers' );

    copyDirectory( grunt, '../phet-io/html/wrappers', 'build/phet-io/protected/wrappers' );

    var wrapperHTML = grunt.file.read( '../phet-io/templates/wrappers.html' );
    wrapperHTML = ChipperStringUtils.replaceAll( wrapperHTML, '$SIM$', buildConfig.name );
    wrapperHTML = ChipperStringUtils.replaceAll( wrapperHTML, '$VERSION$', buildConfig.version );
    wrapperHTML = ChipperStringUtils.replaceAll( wrapperHTML, '$PHET_IO_HTML_SIM_FILENAME$', buildConfig.name + '_en-phetio.html' );
    console.log( wrapperHTML );
    grunt.file.write( 'build/phet-io/protected/wrappers.html', wrapperHTML );

    // TODO: chipper#101 eek, this is scary! we are importing from the repository dir. ideally we should just have uglify-js installed once in chipper?
    var uglify = require( '../../../' + buildConfig.name + '/node_modules/uglify-js' );

    var destinationPath = 'build/phet-io/protected/lib';

    var minifyAndWrite = function( filename, precode ) {
      var minified = uglify.minify( [ '../phet-io/js/' + filename ], {
        mangle: true,
        output: {
          inline_script: true, // escape </script
          beautify: false
        },
        compress: {
          global_defs: {}
        }
      } ).code;

      var copyrightHeader = '// Copyright 2002-2016, University of Colorado Boulder\n' +
                            '// This PhET-iO file requires a license\n' +
                            '// USE WITHOUT A LICENSE AGREEMENT IS STRICTLY PROHIBITED.\n' +
                            '// For licensing, please contact phethelp@colorado.edu';
      grunt.file.write( destinationPath + '/' + filename, copyrightHeader + '\n\n' + precode + minified );
    };

    minifyAndWrite( 'SimIFrameClient.js', '' );

    // Determine which sim versions will be pointed to by SimWrapperUtils
    minifyAndWrite( 'SimWrapperUtils.js', 'window.useRelativeSimPath=true;' );
  };

  if ( grunt.option( 'skipBuild' ) ) {
    grunt.file.mkdir( 'build/phet-io' );
    createOtherPhETIOFiles();
  }
  else {
    var done = grunt.task.current.async();
    var command1 = 'grunt --brand=phet-io';
    var command2 = 'grunt --brand=phet';
    grunt.log.writeln( 'Starting command: ' + command1 + '...' );
    child_process.exec( command1, { cwd: cwd }, function( error1, stdout1, stderr1 ) {
      assert( !error1, 'error in ' + command1 + '\n' + error1 );
      grunt.log.writeln( stdout1 );
      grunt.log.writeln( stderr1 );
      grunt.log.writeln( 'Finished command: ' + command1 );
      copyDirectory( grunt, buildDir, phetioBuildDir );

      grunt.log.writeln( 'Starting command: ' + command2 + '...' );
      child_process.exec( command2, { cwd: cwd }, function( error2, stdout2, stderr2 ) {
        assert( !error2, 'error in ' + command2 + '\n' + error2 );
        grunt.log.writeln( stdout2 );
        grunt.log.writeln( stderr2 );
        grunt.log.writeln( 'Finished command: ' + command2 );
        copyDirectory( grunt, phetioBuildDir, buildDir + '/phet-io' );

        createOtherPhETIOFiles();
        done();
      } );
    } );
  }
};<commit_msg>Fixed paths for wrappers, see https://github.com/phetsims/chipper/issues/440<commit_after>// Copyright 2015, University of Colorado Boulder

/**
 * Full PhET-iO build including phet version, phet-io version and accompanying material.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */

// modules
var assert = require( 'assert' );
var copyDirectory = require( '../../../chipper/js/grunt/copyDirectory' );
var child_process = require( 'child_process' );
var ChipperStringUtils = require( '../../../chipper/js/common/ChipperStringUtils' );

/**
 * @param grunt the grunt instance
 * @param {Object} buildConfig
 */
module.exports = function( grunt, buildConfig ) {
  'use strict';

  var cwd = process.cwd();

  var phetioBuildDir = cwd + '/build-phet-io';
  var buildDir = cwd + '/build';

  // Clean
  if ( grunt.file.exists( phetioBuildDir ) ) {
    grunt.file.delete( phetioBuildDir );
  }
  grunt.file.mkdir( phetioBuildDir );

  var createOtherPhETIOFiles = function() {

    // create devguide/
    grunt.file.mkdir( 'build/phet-io/devguide' );
    copyDirectory( grunt, '../sherpa/lib/highlight.js-9.1.0', 'build/phet-io/devguide/lib/highlight.js-9.1.0' );
    copyDirectory( grunt, '../phet-io/doc/devguide', 'build/phet-io/devguide', function( abspath, contents ) {
      if ( abspath.indexOf( '.html' ) >= 0 ) {
        return ChipperStringUtils.replaceAll( contents, '../../../sherpa/lib/highlight.js-9.1.0', 'lib/highlight.js-9.1.0' );
      }
    } );

    // create protected/
    grunt.file.mkdir( 'build/phet-io/protected' );
    grunt.file.mkdir( 'build/phet-io/protected/lib' );
    grunt.file.mkdir( 'build/phet-io/protected/api' );
    grunt.file.mkdir( 'build/phet-io/protected/wrappers' );

    copyDirectory( grunt, '../phet-io/html/wrappers', 'build/phet-io/protected/wrappers', function( abspath, contents ) {
      if ( abspath.indexOf( '.html' ) >= 0 ) {
        return ChipperStringUtils.replaceAll( contents, '../../js/', '../lib/' );
      }
    } );

    var wrapperHTML = grunt.file.read( '../phet-io/templates/wrappers.html' );
    wrapperHTML = ChipperStringUtils.replaceAll( wrapperHTML, '$SIM$', buildConfig.name );
    wrapperHTML = ChipperStringUtils.replaceAll( wrapperHTML, '$VERSION$', buildConfig.version );
    wrapperHTML = ChipperStringUtils.replaceAll( wrapperHTML, '$PHET_IO_HTML_SIM_FILENAME$', buildConfig.name + '_en-phetio.html' );
    grunt.file.write( 'build/phet-io/protected/wrappers.html', wrapperHTML );

    // TODO: chipper#101 eek, this is scary! we are importing from the repository dir. ideally we should just have uglify-js installed once in chipper?
    var uglify = require( '../../../' + buildConfig.name + '/node_modules/uglify-js' );

    var destinationPath = 'build/phet-io/protected/lib';

    var minifyAndWrite = function( filename, precode ) {
      var minified = uglify.minify( [ '../phet-io/js/' + filename ], {
        mangle: true,
        output: {
          inline_script: true, // escape </script
          beautify: false
        },
        compress: {
          global_defs: {}
        }
      } ).code;

      var copyrightHeader = '// Copyright 2002-2016, University of Colorado Boulder\n' +
                            '// This PhET-iO file requires a license\n' +
                            '// USE WITHOUT A LICENSE AGREEMENT IS STRICTLY PROHIBITED.\n' +
                            '// For licensing, please contact phethelp@colorado.edu';
      grunt.file.write( destinationPath + '/' + filename, copyrightHeader + '\n\n' + precode + minified );
    };

    minifyAndWrite( 'SimIFrameClient.js', '' );

    // Determine which sim versions will be pointed to by SimWrapperUtils
    minifyAndWrite( 'SimWrapperUtils.js', 'window.useRelativeSimPath=true;' );
  };

  if ( grunt.option( 'skipBuild' ) ) {
    grunt.file.mkdir( 'build/phet-io' );
    createOtherPhETIOFiles();
  }
  else {
    var done = grunt.task.current.async();
    var command1 = 'grunt --brand=phet-io';
    var command2 = 'grunt --brand=phet';
    grunt.log.writeln( 'Starting command: ' + command1 + '...' );
    child_process.exec( command1, { cwd: cwd }, function( error1, stdout1, stderr1 ) {
      assert( !error1, 'error in ' + command1 + '\n' + error1 );
      grunt.log.writeln( stdout1 );
      grunt.log.writeln( stderr1 );
      grunt.log.writeln( 'Finished command: ' + command1 );
      copyDirectory( grunt, buildDir, phetioBuildDir );

      grunt.log.writeln( 'Starting command: ' + command2 + '...' );
      child_process.exec( command2, { cwd: cwd }, function( error2, stdout2, stderr2 ) {
        assert( !error2, 'error in ' + command2 + '\n' + error2 );
        grunt.log.writeln( stdout2 );
        grunt.log.writeln( stderr2 );
        grunt.log.writeln( 'Finished command: ' + command2 );
        copyDirectory( grunt, phetioBuildDir, buildDir + '/phet-io' );

        createOtherPhETIOFiles();
        done();
      } );
    } );
  }
};<|endoftext|>


<commit_before>// Copyright 2020, University of Colorado Boulder

/**
 * Sorts imports for a given file
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

'use strict';

// 3rd-party packages
const _ = require( 'lodash' ); // eslint-disable-line require-statement-match
const fs = require( 'fs' );

// constants
const disallowedComments = [
  '// modules',
  '// images',
  '// strings',
  '// mipmaps'
];
const isImport = line => line.startsWith( 'import ' );

/**
 * @param {string} file
 */
module.exports = function( file ) {
  let contents = fs.readFileSync( file, 'utf-8' );
  let lines = contents.split( /\r?\n/ );

  // remove the grouping comments
  lines = lines.filter( ( line, i ) => {
    return !disallowedComments.includes( line ) || !lines[ i + 1 ] || !isImport( lines[ i + 1 ] );
  } );

  // pull out and sort imports
  const firstImportIndex = _.findIndex( lines, isImport );
  const importLines = lines.filter( isImport );
  const nonImportLines = lines.filter( _.negate( isImport ) );
  lines = [
    ...nonImportLines.slice( 0, firstImportIndex ),
    ..._.sortBy( importLines, line => line.slice( line.indexOf( '\'' ) ) ), // sort after the first '
    ...nonImportLines.slice( firstImportIndex )
  ];

  // get rid of blank lines
  const lastImportIndex = _.findLastIndex( lines, isImport );
  while ( lines[ lastImportIndex + 1 ].length === 0 && lines[ lastImportIndex + 2 ].length === 0 ) {
    lines.splice( lastImportIndex + 1, 1 );
  }

  // add a blank line after imports if there was none
  if ( lines[ lastImportIndex + 1 ].length !== 0 ) {
    lines.splice( lastImportIndex + 1, 0, '' );
  }

  contents = lines.join( '\n' );
  fs.writeFileSync( file, contents, 'utf-8' );
};
<commit_msg>toLowerCase things in the sort-by for sorting import statements<commit_after>// Copyright 2020, University of Colorado Boulder

/**
 * Sorts imports for a given file
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

'use strict';

// 3rd-party packages
const _ = require( 'lodash' ); // eslint-disable-line require-statement-match
const fs = require( 'fs' );

// constants
const disallowedComments = [
  '// modules',
  '// images',
  '// strings',
  '// mipmaps'
];
const isImport = line => line.startsWith( 'import ' );

/**
 * @param {string} file
 */
module.exports = function( file ) {
  let contents = fs.readFileSync( file, 'utf-8' );
  let lines = contents.split( /\r?\n/ );

  // remove the grouping comments
  lines = lines.filter( ( line, i ) => {
    return !disallowedComments.includes( line ) || !lines[ i + 1 ] || !isImport( lines[ i + 1 ] );
  } );

  // pull out and sort imports
  const firstImportIndex = _.findIndex( lines, isImport );
  const importLines = lines.filter( isImport );
  const nonImportLines = lines.filter( _.negate( isImport ) );
  lines = [
    ...nonImportLines.slice( 0, firstImportIndex ),
    ..._.sortBy( importLines, line => line.slice( line.indexOf( '\'' ) ).toLowerCase() ), // sort after the first '
    ...nonImportLines.slice( firstImportIndex )
  ];

  // get rid of blank lines
  const lastImportIndex = _.findLastIndex( lines, isImport );
  while ( lines[ lastImportIndex + 1 ].length === 0 && lines[ lastImportIndex + 2 ].length === 0 ) {
    lines.splice( lastImportIndex + 1, 1 );
  }

  // add a blank line after imports if there was none
  if ( lines[ lastImportIndex + 1 ].length !== 0 ) {
    lines.splice( lastImportIndex + 1, 0, '' );
  }

  contents = lines.join( '\n' );
  fs.writeFileSync( file, contents, 'utf-8' );
};
<|endoftext|>


<commit_before>/*
 * freepano - WebGL panorama viewer
 *
 * Copyright (c) 2014-2015 FOXEL SA - http://foxel.ch
 * Please read <http://foxel.ch/license> for more information.
 *
 *
 * Author(s):
 *
 *      Luc Deschenaux <l.deschenaux@foxel.ch>
 *
 *
 * This file is part of the FOXEL project <http://foxel.ch>.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 * Additional Terms:
 *
 *      You are required to preserve legal notices and author attributions in
 *      that material or in the Appropriate Legal Notices displayed by works
 *      containing it.
 *
 *      You are required to attribute the work as explained in the "Usage and
 *      Attribution" section of <http://foxel.ch/license>.
 */

 /**
 * ImageFilter(options)
 *
 * ImageFilter object constructor
 *
 * @param options.target  target canvas selector or element
 * @param options.widgetType   widget type, defaults to 'slider'
 * @param options.container  widget dom container
 * @param options.filterType  canman filter type (see ImageFilter.filterTypeAvailable)
 * @param options.filter  filter name (see ImageFilter.list)
 * @param options.settings to override default filter settings
 *
 */
function ImageFilter(options) {
  if (!(this instanceof ImageFilter)) {
    return new ImageFilter(options);
  }
  $.extend(true,this,this.defaults,options);
  this.init();
}

$.extend(true,ImageFilter.prototype,{
  defaults: {
    widgetType: 'slider',
    filterType: 'glfx',
    group: 'filters'
  },

  // instantiate imageFilter widget list
  init: function imageFilter_init() {

    var imageFilter=this;

    // extend default filter settings with specified ones
    var settings=$.extend(true,{},imageFilter.list[imageFilter.filterType][imageFilter.filter],imageFilter.settings);
    if (!settings.parameters) {
      throw "filter not found: "+imageFilter.filterType+'.'+imageFilter.filter;
    }

    // instantiate imageFilter parameter widgets and append to imageFilter container
    $.each(settings.parameters,function(widgetName,settings){

      var widget_container=$('
');
      $(imageFilter.container).append(widget_container);

      imageFilter.widget.push(new ImageFilterWidget({
        imageFilter: imageFilter,
        name: widgetName,
        settings: settings
      }));

    });

    // append this imageFilter instance to static data
    var staticData=imageFilter.getStaticData();
    staticData[imageFilter.filterType].list.push(imageFilter);
    imageFilter.saveStaticData(staticData);

  }, // imageFilter_init

  saveStaticData: function imageFilter_saveStaticData(data) {
    var imageFilter=this;
    $(imageFilter.target).parent().data(imageFilter.group,data);
  }, // imageFilter_saveStaticData

  // get image
  getStaticData: function imageFilter_getStaticData() {
    var imageFilter=this;
    return $(imageFilter.target).parent().data(imageFilter.group) || imageFilter.staticData;
  }, // imageFilter_getStaticData

  // imageFilterWidget list
  widget: [],

  // available filter types
  filterTypeAvailable: ['caman','glfx'],

  staticData: {

     caman: {
      list: [],
      process: function(widget) {
        var filters=this;
        if (!filters.caman.instance) {
          filters.caman.instance=Caman(widget.imageFilter.target);
        }
        var caman=filters.caman.instance;

        // revert canvas content without updating display
        caman.revert(false);

        // apply filters
        $.each(filters.caman.list,function(){
          var widget=this;
          switch(widget.name) {
            default:
              try {
//                    console.log(widget.name,widget.value);
                caman[widget.name](parseInt(widget.value||0,10));
              } catch(e) {}
              break;
          }
        });
        caman.render(function callback(){
        });
      },
    },

    glfx: {
      list: [],
      process: function(staticData,widget) {
        var glfx=staticData.glfx;
        var isupdate=true;

        if (!glfx.canvas) {
          glfx.canvas=fx.canvas();
          isupdate=false;
        }

        if (staticData.canvas_setup) {
          staticData.canvas_setup(glfx.canvas,isupdate);
        }

        if (isupdate) {
          var oldStyle=glfx.canvas.oldStyle;
          if (oldStyle) {
            if (
              oldStyle.left!=glfx.canvas.style.left ||
              oldStyle.top!=glfx.canvas.style.top ||
              oldStyle.width!=glfx.canvas.style.width ||
              oldStyle.bottom!=glfx.canvas.style.bottom
            ) {
              glfx.texture.destroy();
              glfx.texture=null;
            }
          }

        } else {
          var style=glfx.canvas.style;
          glfx.canvas.oldStyle={
            left: style.left,
            top: style.top,
            width: style.width,
            height: style.height
          }

        }

        if (!glfx.texture) {
          glfx.texture=glfx.canvas.texture($(widget.imageFilter.target)[0]);
        }

        var texture;
        $.each(staticData.glfx.list,function(index,filter){

          function getParameterList(){
            var list=[];
            $.each(filter.widget,function(){
                list.push(parseFloat(this.value,10)||0);
            });
            return list;
          }

          switch(filter.filter) {
            default:
              try {

                 if (filter.disabled) {
                   return;
                 }

                // use resulting canvas texture for subsequent passes
                if (index) {
                  texture=glfx.canvas.contents();
                }

                (glfx.canvas.draw(texture||glfx.texture))[filter.filter].apply(glfx.canvas,getParameterList()).update();

                if (texture) {
                  texture.destroy();
                }

              } catch(e) {
                console.log(e);
              }
              break;
          }
        });
      }
    }
  },

  // list of filters per filterType
  list: {

    // filterType
    caman: {

      // filter name
      brightness: {

        // filter parameters list
        parameters: {

          // filter parameter name and settings
          brightness: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      contrast: {
        parameters: {
          contrast: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      saturation: {
        parameters: {
          saturation: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      vibrance: {
        parameters: {
          vibrance: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      exposure: {
        parameters: {
          exposure: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      hue: {
        parameters: {
          hue: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      sepia: {
        parameters: {
          sepia: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      gamma: {
        parameters: {
          min: 0,
          max: 10,
          step: 0.1
        }
      },

      noise: {
        parameters: {
          noise: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      clip: {
        parameters: {
          clip: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      sharpen: {
        parameters: {
          sharpen: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      stackBlur: {
        parameters: {
          stackBlur: {
            min: 0,
            max: 20,
            step: 1
          }
        }
      }

    },

    glfx: {
      brightnessContrast: {
        parameters: {
          brightness: {
            min: -1,
            max: 1,
            step: 0.02
          },
          contrast: {
            min: -1,
            max: 1,
            step: 0.02
          }
        }
      },

      denoise: {
        parameters: {
          denoise: {
            min: 0,
            max: 50,
            step: 0.5
          }
        }
      },

      hueSaturation: {
        parameters: {
          hue: {
            min: -1,
            max: 1,
            step: 0.05
          },
          saturation: {
            min: -1,
            max: 1,
            step: 0.05
          }
        }
      },

      sepia: {
        parameters: {
          sepia: {
            min: 0,
            max: 1,
            step: 0.01
          }
        }
      },

      vibrance: {
        parameters: {
          vibrance: {
            min: -1,
            max: 1,
            step: 0.05
          }
        }
      },

      vignette: {
        parameters: {
          vignette: {
            min: -1,
            max: 1,
            step: 0.05
          }
        }
      }
    }

  } // filterSettings

});

 /**
 * ImageFilterWidget(options)
 *
 * ImageFilterWidget object constructor
 *
 * @param options.target  target canvas selector or element
 * @param options.type   widget type, defaults to 'slider'
 * @param options.container  widget dom container
 * @param options.filter  canman filter name (see ImageFilterWidget.filterSettings)
 *
 */

function ImageFilterWidget(options) {
  if (!(this instanceof ImageFilterWidget)) {
    return new ImageFilterWidget(options);
  }
  $.extend(true,this,this.defaults,options);
  this.init();
}

$.extend(true,ImageFilterWidget.prototype,{

  defaults: {
    type: 'slider'
  },

  init: function imageFilterWidget_init() {

    var widget=this;

    $('.'+widget.name,widget.imageFilter.container).html(widget.html[widget.type].call(widget));

    $('.'+widget.name+' input',widget.imageFilter.container)
    .off('.imageFilterWidget')
    .on('input.imageFilterWidget change.imageFilterWidget', widget.onchange)
    .closest('div.parameter')
    .data('imageFilterWidget',widget);

  },

  onchange: function imageFilterWidget_onchange(e){
    var div=$(e.target).closest('div.parameter');
    var widget=div.data('imageFilterWidget');
    var panel=$(div).closest('#imagefilters');

    var value=$(e.target).val();

    widget.value=value;

    $('.parameter_value',div).text(widget.value);

    var staticData=widget.imageFilter.getStaticData();

    $.each(staticData,function() {
      var imageFilters=this;
      if (imageFilters.list && imageFilters.list.length && imageFilters.process) {
        imageFilters.process(staticData,widget);
      }
    });

  },

  html: {
      slider: function imageFilterWidget_sliderHtml() {
        var widget=this;
        var settings=widget.settings;
        return '
'
        + '
'
        + '
'+widget.name+'
'
        + '
'
        + '
'
        + '<input type="range" min="'+settings.min+'" max="'+settings.max+'" step="'+settings.step+'" value="'+(settings.value||0)+'" data-filter="'+widget.name+'">'
        + ''+(settings.value||0)+''
        + '
'
        + '
';
      }
  },

});
<commit_msg>updated imageFilterWidget.js<commit_after>/*
 * freepano - WebGL panorama viewer
 *
 * Copyright (c) 2014-2015 FOXEL SA - http://foxel.ch
 * Please read <http://foxel.ch/license> for more information.
 *
 *
 * Author(s):
 *
 *      Luc Deschenaux <l.deschenaux@foxel.ch>
 *
 *
 * This file is part of the FOXEL project <http://foxel.ch>.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 * Additional Terms:
 *
 *      You are required to preserve legal notices and author attributions in
 *      that material or in the Appropriate Legal Notices displayed by works
 *      containing it.
 *
 *      You are required to attribute the work as explained in the "Usage and
 *      Attribution" section of <http://foxel.ch/license>.
 */

 /**
 * ImageFilter(options)
 *
 * ImageFilter object constructor
 *
 * @param options.target  target canvas selector or element
 * @param options.widgetType   widget type, defaults to 'slider'
 * @param options.container  widget dom container
 * @param options.filterType  canman filter type (see ImageFilter.filterTypeAvailable)
 * @param options.filter  filter name (see ImageFilter.list)
 * @param options.settings to override default filter settings
 *
 */
function ImageFilter(options) {
  if (!(this instanceof ImageFilter)) {
    return new ImageFilter(options);
  }
  $.extend(true,this,this.defaults,options);
  this.init();
}

$.extend(true,ImageFilter.prototype,{
  defaults: {
    widgetType: 'slider',
    filterType: 'glfx',
    group: 'filters'
  },

  // instantiate imageFilter widget list
  init: function imageFilter_init() {

    var imageFilter=this;

    // extend default filter settings with specified ones
    var settings=$.extend(true,{},imageFilter.list[imageFilter.filterType][imageFilter.filter],imageFilter.settings);
    if (!settings.parameters) {
      throw "filter not found: "+imageFilter.filterType+'.'+imageFilter.filter;
    }

    // instantiate imageFilter parameter widgets and append to imageFilter container
    $.each(settings.parameters,function(widgetName,settings){

      var widget_container=$('
');
      $(imageFilter.container).append(widget_container);

      imageFilter.widget.push(new ImageFilterWidget({
        imageFilter: imageFilter,
        name: widgetName,
        settings: settings
      }));

    });

    // append this imageFilter instance to static data
    var staticData=imageFilter.getStaticData();
    staticData[imageFilter.filterType].list.push(imageFilter);
    imageFilter.saveStaticData(staticData);

  }, // imageFilter_init

  saveStaticData: function imageFilter_saveStaticData(data) {
    var imageFilter=this;
    $(imageFilter.target).parent().data(imageFilter.group,data);
  }, // imageFilter_saveStaticData

  // get image
  getStaticData: function imageFilter_getStaticData() {
    var imageFilter=this;
    return $(imageFilter.target).parent().data(imageFilter.group) || imageFilter.staticData;
  }, // imageFilter_getStaticData

  // imageFilterWidget list
  widget: [],

  // available filter types
  filterTypeAvailable: ['caman','glfx'],

  staticData: {

     caman: {
      list: [],
      process: function(staticData,widget) {
        var caman=staticData.caman.instance;
        var canvas=$(widget.imageFilter.target)[0];
        var isupdate;

        if (!caman) {

          // copy original canvas

          var caman_canvas=document.createElement('canvas');
          $(caman_canvas).appendTo('body');

          caman_canvas.textureCopy=function(canvas) {
            var caman_canvas=this;
            caman_canvas.width=canvas.width;
            caman_canvas.height=canvas.height;
            var ctx=caman_canvas.getContext('2d');
            ctx.drawImage(canvas,0,0);
          }

          caman_canvas.textureCopy(canvas);

          // instantiate caman object
          caman=staticData.caman.instance=Caman(caman_canvas);
          caman.canvas=caman_canvas;
          isupdate=false;

        } else {
          // revert canvas content without updating display
//          caman.revert(false);
                    caman.reloadCanvasData();

          isupdate=true;
        }

        if (staticData.canvas_setup) {
          staticData.canvas_setup(caman.canvas,isupdate);
        }

        if (isupdate) {
          var oldStyle=caman.canvas.oldStyle;
          if (oldStyle) {
            if (
              oldStyle.left!=caman.canvas.style.left ||
              oldStyle.top!=caman.canvas.style.top ||
              oldStyle.width!=caman.canvas.style.width ||
              oldStyle.height!=caman.canvas.style.height
            ) {
              caman.canvasNeedsUpdate=true;
            }
          }
        }

        var style=caman.canvas.style;
        caman.canvas.oldStyle={
          left: style.left,
          top: style.top,
          width: style.width,
          height: style.height
        }

        if (caman.canvasNeedsUpdate) {
          caman.canvas.textureCopy($(widget.imageFilter.target)[0]);
          caman.reloadCanvasData();
          caman.canvasNeedsUpdate=false;
        }

        // apply filters
        $.each(staticData.caman.list,function(index,filter){

          function getParameterList(){
            var list=[];
            $.each(filter.widget,function(){
                list.push(parseFloat(this.value,10)||0);
            });
            return list;
          }

          switch(filter.filter) {
            default:
              try {
//                    console.log(widget.name,widget.value);
                caman[filter.filter].apply(caman,getParameterList());
              } catch(e) {}
              break;
          }
        });
        caman.render(function callback(){
        });
      },
    },

    glfx: {
      list: [],
      process: function(staticData,widget) {
        var glfx=staticData.glfx;
        var isupdate=true;

        if (!glfx.canvas) {
          glfx.canvas=fx.canvas();
          isupdate=false;
        }

        if (staticData.canvas_setup) {
          staticData.canvas_setup(glfx.canvas,isupdate);
        }

        if (isupdate) {
          var oldStyle=glfx.canvas.oldStyle;
          if (oldStyle) {
            if (
              oldStyle.left!=glfx.canvas.style.left ||
              oldStyle.top!=glfx.canvas.style.top ||
              oldStyle.width!=glfx.canvas.style.width ||
              oldStyle.height!=glfx.canvas.style.height
            ) {
              glfx.texture.destroy();
              glfx.texture=null;
            }
          }
        }

        var style=glfx.canvas.style;
        glfx.canvas.oldStyle={
          left: style.left,
          top: style.top,
          width: style.width,
          height: style.height
        }

        if (!glfx.texture) {
          glfx.texture=glfx.canvas.texture($(widget.imageFilter.target)[0]);
        }

        var texture;
        $.each(staticData.glfx.list,function(index,filter){

          function getParameterList(filterName){
            var list=[];
            $.each(filter.widget,function(){
                if (this.imageFilter.filter==filterName) {
                  list.push(parseFloat(this.value,10)||0);
                }
            });
            return list;
          }

          switch(filter.filter) {
            default:
              try {

                 if (filter.disabled) {
                   return;
                 }

                // use resulting canvas texture for subsequent passes
                if (index) {
                  texture=glfx.canvas.contents();
                }

                (glfx.canvas.draw(texture||glfx.texture))[filter.filter].apply(glfx.canvas,getParameterList(filter.filter)).update();

                if (texture) {
                  texture.destroy();
                }

              } catch(e) {
                console.log(e);
              }
              break;
          }
        });
      }
    }
  },

  // list of filters per filterType
  list: {

    // filterType
    caman: {

      // filter name
      brightness: {

        // filter parameters list
        parameters: {

          // filter parameter name and settings
          brightness: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      contrast: {
        parameters: {
          contrast: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      saturation: {
        parameters: {
          saturation: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      vibrance: {
        parameters: {
          vibrance: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      exposure: {
        parameters: {
          exposure: {
            min: -100,
            max: 100,
            step: 1
          }
        }
      },

      hue: {
        parameters: {
          hue: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      sepia: {
        parameters: {
          sepia: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      gamma: {
        parameters: {
          gamma: {
            min: 0,
            max: 10,
            step: 0.1
          }
        }
      },

      noise: {
        parameters: {
          noise: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      clip: {
        parameters: {
          clip: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      sharpen: {
        parameters: {
          sharpen: {
            min: 0,
            max: 100,
            step: 1
          }
        }
      },

      stackBlur: {
        parameters: {
          stackBlur: {
            min: 0,
            max: 20,
            step: 1
          }
        }
      }

    },

    glfx: {
      brightnessContrast: {
        parameters: {
          brightness: {
            min: -1,
            max: 1,
            step: 0.02
          },
          contrast: {
            min: -1,
            max: 1,
            step: 0.02
          }
        }
      },

      denoise: {
        parameters: {
          denoise: {
            min: 0,
            max: 50,
            step: 0.5
          }
        }
      },

      hueSaturation: {
        parameters: {
          hue: {
            min: -1,
            max: 1,
            step: 0.05
          },
          saturation: {
            min: -1,
            max: 1,
            step: 0.05
          }
        }
      },

      sepia: {
        parameters: {
          sepia: {
            min: 0,
            max: 1,
            step: 0.01
          }
        }
      },

      vibrance: {
        parameters: {
          vibrance: {
            min: -1,
            max: 1,
            step: 0.05
          }
        }
      },

      vignette: {
        parameters: {
          vignette: {
            min: -1,
            max: 1,
            step: 0.05
          }
        }
      }
    }

  } // filterSettings

});

 /**
 * ImageFilterWidget(options)
 *
 * ImageFilterWidget object constructor
 *
 * @param options.target  target canvas selector or element
 * @param options.type   widget type, defaults to 'slider'
 * @param options.container  widget dom container
 * @param options.filter  canman filter name (see ImageFilterWidget.filterSettings)
 *
 */

function ImageFilterWidget(options) {
  if (!(this instanceof ImageFilterWidget)) {
    return new ImageFilterWidget(options);
  }
  $.extend(true,this,this.defaults,options);
  this.init();
}

$.extend(true,ImageFilterWidget.prototype,{

  defaults: {
    type: 'slider'
  },

  init: function imageFilterWidget_init() {

    var widget=this;

    $('.'+widget.name,widget.imageFilter.container).html(widget.html[widget.type].call(widget));

    $('.'+widget.name+' input',widget.imageFilter.container)
    .off('.imageFilterWidget')
    .on('input.imageFilterWidget change.imageFilterWidget', widget.onchange)
    .closest('div.parameter')
    .data('imageFilterWidget',widget);

  },

  onchange: function imageFilterWidget_onchange(e){
    var div=$(e.target).closest('div.parameter');
    var widget=div.data('imageFilterWidget');
    var panel=$(div).closest('#imagefilters');

    var value=$(e.target).val();

    widget.value=value;

    $('.parameter_value',div).text(widget.value);

    var staticData=widget.imageFilter.getStaticData();

    $.each(staticData,function() {
      var imageFilters=this;
      if (imageFilters.list && imageFilters.list.length && imageFilters.process) {
        imageFilters.process(staticData,widget);
      }
    });

  },

  html: {
      slider: function imageFilterWidget_sliderHtml() {
        var widget=this;
        var settings=widget.settings;
        return '
'
        + '
'
        + '
'+widget.name+'
'
        + '
'
        + '
'
        + '<input type="range" min="'+settings.min+'" max="'+settings.max+'" step="'+settings.step+'" value="'+(settings.value||0)+'" data-filter="'+widget.name+'">'
        + ''+(settings.value||0)+''
        + '
'
        + '
';
      }
  },

});
<|endoftext|>


<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2014 Phu Nguyen (me@phu.bar)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*******************************************************************************/
(function ($) {

    // Helper function to get average value in array
    function getAvg(arr) {
        var cnt, tot, i;
        cnt = arr.length;
        tot = i = 0;
        while (i < cnt) tot+= arr[i++];
        return tot / cnt;
    }

    $.fn.audiolizer = function(options) {

        var settings = $.extend({
            // These are the defaults.
            fftSize: 1024 * 2,
            width: this.width(),
            circleColor: 'black',
            barColor: 'black',
            lineColor: 'white',

            // Callback for when a song is starting
            onStart: null,
            // Callback for when a song is resumed from pause
            onResume: null,
            // Callback for when a song is paused
            onPause: null,
            // Callback for when a song ends
            onEnd: null,
            // Callback for when a song is still being loaded
            onLoad: null
        }, options );

        settings.radius = (options && options.radius) ? options.radius : settings.width/2 * 0.7;
        settings.circumference = 2 * Math.pi * settings.radius;

        var STATE_PLAY = 3,
            STATE_PAUSE = 2,
            STATE_STOP = 0;

        var context = createAudioContext();
        var audioBuffer;
        var analyser;
        var javascriptNode;
        var fftSize = 1024 * 2;
        var state = STATE_STOP;

        // Used to pause and play the media file
        var startOffset = 0;
        var startTime = 0;

        // get the context from the canvas to draw on
        var ctx = this.get()[0].getContext("2d");

        // load the sound
        setupAudioNodes();

        function createAudioContext() {
            if ('webkitAudioContext' in window) {
               return new webkitAudioContext();
            } else if ('AudioContext' in window) {
                return new AudioContext();
            }
        }

        function setupAudioNodes() {

            // setup a javascript node
            window.javascriptNode = context.createScriptProcessor(2048, 1, 1);
            // connect to destination, else it isn't called
            window.javascriptNode.connect(context.destination);

            // setup a analyzer
            analyser = context.createAnalyser();
            analyser.smoothingTimeConstant = 0.5;
            analyser.fftSize = fftSize;

            // create a buffer source node
            sourceNode = context.createBufferSource();
            sourceNode.connect(analyser);
            analyser.connect(window.javascriptNode);

            sourceNode.connect(context.destination);
        }

        // load the specified sound
        function loadSoundFromUrl(url, callback) {
            var request = new XMLHttpRequest();
            request.open('GET', url, true);
            request.responseType = 'arraybuffer';

            // When loaded decode the data
            request.onload = function() {

                // decode the data
                context.decodeAudioData(request.response, function(buffer) {
                    // when the audio is decoded play the sound
                    audioBuffer = buffer;
                    if (callback) {
                        callback();
                    }
                }, onError);
            }
            request.send();
        }

        function loadAudioData(buffer, play) {
            if (context.decodeAudioData) {
                context.decodeAudioData(buffer, function(b) {
                    audioBuffer = b;
                    startOffset = 0;
                    startTime = 0;

                    if (play) playSound();
                });
            }
        }

        function playOrPause() {
          if (state == STATE_PLAY) {
              pauseSound();
          } else {
              playSound();
          }
        }

        function pauseSound() {
            if (state == STATE_PLAY) {
                startOffset += context.currentTime - startTime;
                sourceNode.stop(startOffset);
                state = STATE_PAUSE;
                if (settings.onPause) {
                    settings.onPause();
                }
            }
        }

        function playSound() {
            if (!audioBuffer && settings.defaultAudioUrl) {
                loadSoundFromUrl(settings.defaultAudioUrl, playSound);
                return;
            } else if (!audioBuffer) {
                return;
            }

            if (state == STATE_PLAY) {
                state = STATE_STOP;
                sourceNode.stop();
            }
            startTime = context.currentTime;
            sourceNode = context.createBufferSource();
            sourceNode.buffer = audioBuffer;
            sourceNode.connect(analyser);
            sourceNode.connect(context.destination);
            // Start playback, but make sure we stay in bound of the buffer.
            sourceNode.start(0, startOffset % audioBuffer.duration);
            state = STATE_PLAY;
            if (settings.onResume) {
                settings.onResume();
            }
        }

        // log if an error occurs
        function onError(e) {
            console.log(e);
        }

        // when the javascript node is called
        // we use information from the analyzer node
        // to draw the volume
        window.javascriptNode.onaudioprocess = function() {

            // Analyzer uses FFT to analyze all fo the frequencies real time
            // frequency bin count is basically the number of frequencies it's analyzing
            var freqDomain =  new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteFrequencyData(freqDomain);
            var timeDomain = new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteTimeDomainData(timeDomain);

            // clear the current state
            ctx.clearRect(0, 0, settings.width, settings.width);

            ctx.beginPath();
            ctx.arc(settings.width/2, settings.width/2, settings.radius, 0, 2 * Math.PI, false);
            ctx.fillStyle = settings.circleColor;
            ctx.fill();
            ctx.strokeStyle = settings.circleColor;
            ctx.lineWidth = 0;
            ctx.stroke();
            drawSpectrum(freqDomain);
            drawTimeSpectrum(timeDomain);
        }

        function drawSpectrum(array) {
            var cut = getAvg(array) * 2/3;
            for (var i = 0; i < (array.length/8-32); i++) {
                var value = array[i*8+16] - cut;
                if (value < 0) value = 0;
                var percent = value / (256 - cut);
                var angle = (2*Math.PI/(array.length/8-32)) * (i+1);
                var cx = settings.width/2 + settings.radius * Math.cos(angle);
                var cy = settings.width/2 + settings.radius * Math.sin(angle);
                var length = settings.width * 0.15 * percent;
                var x = cx + (length) * Math.cos(angle);
                var y = cy + (length) * Math.sin(angle);
                ctx.beginPath();
                ctx.strokeStyle = settings.barColor;
                ctx.lineWidth = settings.width * 0.018;
                ctx.moveTo(cx, cy);
                ctx.lineTo(x, y);
                ctx.stroke();
            }
        };

        function drawTimeSpectrum(array) {
            var points = [];
            for (var i = 0; i < (array.length); i++) {
                var value = array[i];
                var percent = value / 256;
                var angle = (2*Math.PI/array.length) * (i+1);
                var length = settings.radius/2 * percent;
                var x = settings.width/2 + (settings.radius * 3/4 + length) * Math.cos(angle);
                var y = settings.width/2 + (settings.radius * 3/4 + length) * Math.sin(angle);
                points.push({'x': x, 'y': y});
            }

            ctx.beginPath();
            ctx.strokeStyle = settings.lineColor;
            ctx.lineWidth = 2;
            ctx.moveTo(points[0].x, points[0].y);

            for (var i = 1; i < points.length-2; i++) {
                var xc = (points[i].x + points[i + 1].x) / 2;
                var yc = (points[i].y + points[i + 1].y) / 2;
                ctx.quadraticCurveTo(points[i].x, points[i].y, xc, yc);
            }
            // curve through the last two points
            ctx.quadraticCurveTo(points[i].x, points[i].y, points[i+1].x,points[i+1].y);
            ctx.quadraticCurveTo(points[i+1].x, points[i+1].y, points[0].x,points[0].y);
            ctx.stroke();
        }

        return {
            playOrPause: function() {
                playOrPause();
            },
            loadAudioData: function(buffer, play) {
                loadAudioData(buffer, play);
            }
        }
    }
}(jQuery));
<commit_msg>Cleaned JS<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2014 Phu Nguyen (me@phu.bar)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*******************************************************************************/
(function ($) {

    // Helper function to get average value in array
    function getAvg(arr) {
        var cnt, tot, i;
        cnt = arr.length;
        tot = i = 0;
        while (i < cnt) tot+= arr[i++];
        return tot / cnt;
    }

    $.fn.audiolizer = function(options) {

        var settings = $.extend({
            // These are the defaults.
            fftSize: 1024 * 2,
            width: this.width(),
            circleColor: 'black',
            barColor: 'black',
            lineColor: 'white',

            // Callback for when a song is starting
            onStart: null,
            // Callback for when a song is resumed from pause
            onResume: null,
            // Callback for when a song is paused
            onPause: null,
            // Callback for when a song ends
            onEnd: null,
            // TODO: Callback for when a song is still being loaded
            onLoad: null
        }, options );

        settings.radius = (options && options.radius) ? options.radius : settings.width/2 * 0.7;
        settings.circumference = 2 * Math.pi * settings.radius;

        var STATE_PLAY = 3,
            STATE_PAUSE = 2,
            STATE_STOP = 0;

        var context = createAudioContext();
        var audioBuffer;
        var analyser;
        var javascriptNode;
        var fftSize = 1024 * 2;
        var state = STATE_STOP;

        // Used to pause and play the media file
        var startOffset = 0;
        var startTime = 0;

        var ctx = this.get()[0].getContext("2d");

        setupAudioNodes();

        function createAudioContext() {
            if ('webkitAudioContext' in window) {
               return new webkitAudioContext();
            } else if ('AudioContext' in window) {
                return new AudioContext();
            }
        }

        function setupAudioNodes() {
            window.javascriptNode = context.createScriptProcessor(2048, 1, 1);
            window.javascriptNode.connect(context.destination);

            analyser = context.createAnalyser();
            analyser.smoothingTimeConstant = 0.5;
            analyser.fftSize = fftSize;

            sourceNode = context.createBufferSource();
            sourceNode.connect(analyser);
            sourceNode.connect(context.destination);

            analyser.connect(window.javascriptNode);
        }

        function loadFromUrl(url, callback) {
            var request = new XMLHttpRequest();

            request.open('GET', url, true);
            request.responseType = 'arraybuffer';
            request.onload = function() {
                context.decodeAudioData(request.response, function(buffer) {
                    audioBuffer = buffer;
                    if (callback) {
                        callback();
                    }
                }, onError);
            }
            request.send();
        }

        function loadAudioData(buffer, play) {
            if (context.decodeAudioData) {
                context.decodeAudioData(buffer, function(b) {
                    audioBuffer = b;
                    startOffset = 0;
                    startTime = 0;

                    if (play) playSound();
                });
            }
        }

        function playOrPause() {
          if (state == STATE_PLAY) {
              pauseSound();
          } else {
              playSound();
          }
        }

        function pauseSound() {
            if (state == STATE_PLAY) {
                startOffset += context.currentTime - startTime;
                sourceNode.stop(startOffset);
                state = STATE_PAUSE;

                if (settings.onPause) settings.onPause();
            }
        }

        function playSound() {
            if (!audioBuffer && settings.defaultAudioUrl) {
                loadFromUrl(settings.defaultAudioUrl, playSound);
                return;
            } else if (!audioBuffer) {
                return;
            }

            if (state == STATE_PLAY) {
                state = STATE_STOP;
                sourceNode.stop();
            }
            startTime = context.currentTime;
            sourceNode = context.createBufferSource();
            sourceNode.buffer = audioBuffer;
            sourceNode.connect(analyser);
            sourceNode.connect(context.destination);
            // Start playback, but make sure we stay in bound of the buffer.
            sourceNode.start(0, startOffset % audioBuffer.duration);
            state = STATE_PLAY;
            if (settings.onResume) {
                settings.onResume();
            }
        }

        function onError(e) {
            console.log(e);
        }

        window.javascriptNode.onaudioprocess = function() {
            var freqDomain = new Uint8Array(analyser.frequencyBinCount),
                timeDomain = new Uint8Array(analyser.frequencyBinCount);

            analyser.getByteFrequencyData(freqDomain);
            analyser.getByteTimeDomainData(timeDomain);

            ctx.clearRect(0, 0, settings.width, settings.width);

            ctx.beginPath();
            ctx.arc(settings.width/2, settings.width/2, settings.radius, 0, 2 * Math.PI, false);
            ctx.fillStyle = settings.circleColor;
            ctx.fill();
            ctx.strokeStyle = settings.circleColor;
            ctx.lineWidth = 0;
            ctx.stroke();

            drawSpectrum(freqDomain);
            drawTimeSpectrum(timeDomain);
        }

        function drawSpectrum(array) {
            for (var i = 0; i < (array.length/8-32); i++) {
                var cut = getAvg(array) * 2/3,
                    value = array[i*8+16] - cut;

                if (value < 0) value = 0;

                var percent = value / (256 - cut),
                    angle = (2*Math.PI/(array.length/8-32)) * (i+1),
                    cx = settings.width/2 + settings.radius * Math.cos(angle),
                    cy = settings.width/2 + settings.radius * Math.sin(angle),
                    length = settings.width * 0.15 * percent,
                    x = cx + (length) * Math.cos(angle),
                    y = cy + (length) * Math.sin(angle);

                ctx.beginPath();
                ctx.strokeStyle = settings.barColor;
                ctx.lineWidth = settings.width * 0.018;
                ctx.moveTo(cx, cy);
                ctx.lineTo(x, y);
                ctx.stroke();
            }
        };

        function drawTimeSpectrum(array) {
            var points = [];
            for (var i = 0; i < (array.length); i++) {
                var value = array[i],
                    percent = value / 256,
                    angle = (2*Math.PI/array.length) * (i+1),
                    length = settings.radius/2 * percent,
                    x = settings.width/2 + (settings.radius * 3/4 + length) * Math.cos(angle),
                    y = settings.width/2 + (settings.radius * 3/4 + length) * Math.sin(angle);

                points.push({'x': x, 'y': y});
            }

            ctx.beginPath();
            ctx.strokeStyle = settings.lineColor;
            ctx.lineWidth = 2;
            ctx.moveTo(points[0].x, points[0].y);

            for (var i = 1; i < points.length-2; i++) {
                var xc = (points[i].x + points[i + 1].x) / 2,
                    yc = (points[i].y + points[i + 1].y) / 2;

                ctx.quadraticCurveTo(points[i].x, points[i].y, xc, yc);
            }

            // Connect the circle
            ctx.quadraticCurveTo(points[i].x, points[i].y, points[i+1].x,points[i+1].y);
            ctx.quadraticCurveTo(points[i+1].x, points[i+1].y, points[0].x,points[0].y);
            ctx.stroke();
        }

        return {
            playOrPause: function() {
                playOrPause();
            },
            loadAudioData: function(buffer, play) {
                loadAudioData(buffer, play);
            }
        }
    }
}(jQuery));
<|endoftext|>


<commit_before>// jquery.imuplo.js v0.7.15
(function($){$.fn.Imuplo=function(opt){if(typeof opt!=="object")opt={};var $options=$.extend({},$.fn.Imuplo.defaults,opt),$files,$fileObj={},$elCounter=0,$error="",$locked=false,$publicStatus="Image is not selected";$.each(["onChange","onReadyForUpload","onError"],function(i,e){if(typeof $options[e]!=="function")$options[e]=function(){}});$(this).each(function(){var $this=$(this);if($this.data("Imuplo"))return;$elCounter++;$this.data("Imuplo",$elCounter);$this.click(function(){if($locked)return;var $parentContainer=$this.parent(),fileInputID="imuplo-input-file"+$elCounter;if(isElExist(fileInputID)){$("#"+fileInputID).remove()}$parentContainer.append('<input type="file" id="'+fileInputID+'" accept="'+$options.acceptFileTypes+'" multiple="'+$options.multiple+'" style="display: none;" />');$("#"+fileInputID).click();$("#"+fileInputID).bind({change:function(){if($options.multiple&&false)$files=this.files;else $files=this.files[0];if(isValidFiles($files)){$publicStatus=$files.name+" selected for upload";$options.onChange.call($this,$publicStatus);if(window.File&&window.FileReader&&window.FileList&&window.Blob){getFileData($files,$parentContainer);$parentContainer.bind("dataReady",function(){$parentContainer.unbind("dataReady");if($options.previewContainerID!==false){showImage($options.previewContainerID,$fileObj.src)}$options.onReadyForUpload.call(this,$fileObj)})}else{$error="The File APIs are not supported in your browser";$options.onError.call($this,$error);$options.onReadyForUpload.call($this,{size:$files.size,name:$files.name,type:$files.type,src:null,width:null,height:null,blob:$files})}}else{$publicStatus="Image is not selected";$options.onError.call($this,$error)}$("#"+fileInputID).remove()}})})});function isElExist(id){var el=document.getElementById(id);if(typeof el!="undefined"&&el!=null){return true}return false}function getFileData(f,el){var reader=new FileReader;reader.onload=function(event){var img=new Image;img.src=event.target.result;img.onload=function(){var fileObj={size:f.size,name:f.name,type:f.type,src:img.src,width:img.width,height:img.height,blob:f};$fileObj=fileObj;el.trigger("dataReady")}};reader.readAsDataURL(f)}function showImage(c,src){if(isElExist(c)){$("#"+c).html('');$("#"+c+"-img").ready(function(){$("#"+c+"-img").css("max-width",$("#"+c).css("width"));$("#"+c+"-img").css("max-height",$("#"+c).css("height"))});$("#"+c).show()}}function isValidFiles(f){if($options.maxFileSize>0)if(f.size>$options.maxFileSize){$error="File too big";return false}var ftypes=$options.acceptFileTypes,ftype=f.type,imageTypeRX=/^image\//;if(ftypes.indexOf(ftype)===-1||!imageTypeRX.test(ftype)){$error="Wrong type of file";return false}return true}};$.fn.Imuplo.defaults={acceptFileTypes:"image/jpeg,image/png",maxFileSize:0,multiple:false,previewContainerID:false,resize:false,resizeMethod:"crop",maxImageSize:[480,480],minImageSize:[120,120],onChange:function(){},onReadyForUpload:function(){},onError:function(){}}})(jQuery);<commit_msg>update 0.07.15.02<commit_after>(function($){$.fn.Imuplo=function(opt){if(typeof opt!=="object")opt={};var $options=$.extend({},$.fn.Imuplo.defaults,opt),$files,$fileObj={},$elCounter=0,$error="",$locked=false,$publicStatus="Image is not selected";$.each(["onChange","onReadyForUpload","onError"],function(i,e){if(typeof $options[e]!=="function")$options[e]=function(){}});$(this).each(function(){var $this=$(this);if($this.data("Imuplo"))return;$elCounter++;$this.data("Imuplo",$elCounter);$this.click(function(){if($locked)return;var $parentContainer=$this.parent(),fileInputID="imuplo-input-file"+$elCounter;if(isElExist(fileInputID)){$("#"+fileInputID).remove()}$parentContainer.append('<input type="file" id="'+fileInputID+'" accept="'+$options.acceptFileTypes+'" multiple="'+$options.multiple+'" style="display: none;" />');$("#"+fileInputID).click();$("#"+fileInputID).bind({change:function(){if($options.multiple&&false)$files=this.files;else $files=this.files[0];if(isValidFiles($files)){$publicStatus=$files.name+" selected for upload";$options.onChange.call($this,$publicStatus);if(window.File&&window.FileReader&&window.FileList&&window.Blob){getFileData($files,$parentContainer);$parentContainer.bind("dataReady",function(){$parentContainer.unbind("dataReady");if(!isValidImage([$fileObj.width,$fileObj.height])){killAll($elCounter,$options.previewContainerID);$options.onError.call(this,$error);return}if($options.resize&&$options.resizeMethod!==false){var newImg;if(newImg=imageResize($fileObj,$options.resizeMethod,$parentContainer)){$fileObj=newImg}else{$options.onError.call(this,$error)}}if($options.previewContainerID!==false){showImage($options.previewContainerID,$fileObj.src)}$options.onReadyForUpload.call(this,$fileObj)})}else{$error="The File APIs are not supported in your browser";$options.onError.call($this,$error);$options.onReadyForUpload.call($this,{size:$files.size,name:$files.name,type:$files.type,src:null,width:null,height:null,blob:$files})}}else{$publicStatus="Image is not selected";$options.onError.call($this,$error)}$("#"+fileInputID).remove()}})})});function isElExist(id){var el=document.getElementById(id);if(typeof el!="undefined"&&el!=null){return true}return false}function imageResize(o,method,wrapper){var ob={},wrapperId=wrapper.attr("id"),w=o.width,h=o.height,sx=$options.scaleTo[0],sy=$options.scaleTo[1],aspectRX=1,aspectRY=1,nw=w,nh=h,centreX=0,centreY=0;if(!sx||!sy){$error='Option "scaleTo" is undefined';return false}if(wrapperId==undefined){wrapperId="imuplo-tc-wrapper";wrapper.attr("id",wrapperId)}else{if(wrapperId.length()<1){wrapperId="imuplo-tc-wrapper";wrapper.attr("id",wrapperId)}}switch(method){case"standart":aspectRX=w/sx;aspectRY=h/sy;if(w>=h){nw=sx*aspectRY|0;if(nw>w)nw=w;nh=h;centreX=w/2-nw/2|0;centreY=0}else{nw=w;nh=sy*aspectRX|0;if(nh>h)nh=h;centreX=0;centreY=h/2-nh/2|0}wrapper.append('<canvas id="imuplo-tmp-canvas" style="display: none;"></canvas>');canv=document.getElementById("imuplo-tmp-canvas");canv.width=sx;canv.height=sy;canv.getContext("2d").drawImage(o.imobj,centreX,centreY,nw,nh,0,0,sx,sy);ob.src=canv.toDataURL(o.type,.8);ob.width=sx;ob.height=sy;ob.blob=dataURItoBlob(ob.src);$("#imuplo-tmp-canvas").remove();break;case"Jcrop":break;default:$error="Unknown resize method";return false}return $.extend(o,ob)}function getFileData(f,el){var reader=new FileReader;reader.onload=function(event){var img=new Image;img.src=event.target.result;img.onload=function(){var fileObj={size:f.size,name:f.name,type:f.type,src:img.src,width:img.width,height:img.height,blob:dataURItoBlob(img.src),imobj:img};$fileObj=fileObj;el.trigger("dataReady")}};reader.readAsDataURL(f)}function dataURItoBlob(dataURI){var byteString;if(dataURI.split(",")[0].indexOf("base64")>=0)byteString=atob(dataURI.split(",")[1]);else byteString=unescape(dataURI.split(",")[1]);var mimeString=dataURI.split(",")[0].split(":")[1].split(";")[0];var ia=new Uint8Array(byteString.length);for(var i=0;i<byteString.length;i++){ia[i]=byteString.charCodeAt(i)}return new Blob([ia],{type:mimeString})}function showImage(c,src){if(isElExist(c)){$("#"+c).html('');$("#"+c+"-img").ready(function(){$("#"+c+"-img").css("max-width",$("#"+c).css("width"));$("#"+c+"-img").css("max-height",$("#"+c).css("height"))});$("#"+c).show()}}function isValidFiles(f){if($options.maxFileSize>0)if(f.size>$options.maxFileSize){$error="File too big";return false}var ftypes=$options.acceptFileTypes,ftype=f.type,imageTypeRX=/^image\//;if(ftypes.indexOf(ftype)===-1||!imageTypeRX.test(ftype)){$error="Wrong type of file";return false}return true}function isValidImage(img){if($options.minImageSize[0]&&img[0]<$options.minImageSize[0]||$options.minImageSize[1]&&img[1]<$options.minImageSize[1]){$error="Image too small";return false}if($options.maxImageSize[0]&&img[0]>$options.maxImageSize[0]||$options.maxImageSize[1]&&img[1]>$options.maxImageSize[1]){$error="Image too big";return false}return true}function killAll(i,c){$fileObj={};$publicStatus="Image is not selected";if(isElExist(c+"-img")){$("#"+c+"-img").remove();$("#"+c).hide()}if(isElExist("imuplo-tmp-canvas")){$("#imuplo-tmp-canvas").remove()}$options.onChange.call(this,$publicStatus)}};$.fn.Imuplo.defaults={acceptFileTypes:"image/jpeg,image/png",maxFileSize:0,multiple:false,previewContainerID:false,resize:false,resizeMethod:"standart",maxImageSize:[],minImageSize:[],scaleTo:[],onChange:function(){},onReadyForUpload:function(){},onError:function(){}}})(jQuery);<|endoftext|>


<commit_before>base.registerModule('play', function() {
  var util = base.importModule('util');

  var PIECES_IN_QUEUE = 5;
  var rand = new Phaser.RandomDataGenerator();

  var PlayState = util.extend(Phaser.State, 'PlayState', {
    constructor: function PlayState() {
      this.playGame = null;
    },

    create: function create() {
      this.playGame = new PlayGame(this.game);
      this.game.world.add(this.playGame);
    },

    update: function update() {
      //this.playGame.update();
    },

    shutdown: function shutdown() {
      util.clearBitmapCache();
    }
  });

  /**
   * creates the placements of things on the screen
   */
  function makePlacements(width, height) {
    var places = {
      //place to spawn pieces for left queue
      leftSpawn: [-50, -50], //topleft corner
      //where the pieces in the queue go to join
      queueTarget: [width / 2, height / 2], //screen center
      //center of the rings
      ringCenter: [width / 2, height / 2] //screen center
    }
    var names = Object.getOwnPropertyNames(places);
    var ret = {}
    for(var i=0; i<names.length; i++) {
      var name = names[i];
      var coord = places[name];
      var point = new Phaser.Point(coord[0], coord[1]);
      ret[name] = point;
    }
    return ret;
  }

  /**
   * the play area
   */
  var PlayGame = util.extend(Phaser.Group, 'PlayGame', {
    constructor: function PlayGame(game) {
      this.constructor$Group(game);
      //what goes where
      this.placements = makePlacements(game.scale.width, game.scale.height);
      //speed at which to send pieces
      this.speed = 5000;

      this.queueLeft = new PieceQueue(game, this, Side.Left); //line of shapes on the left
      this.queueRight = null; //line of shapes on the right
      this.goals = null; //shapes to specify what goes where
      this.health = new Ring(game, this, 100, 20, '#000000'); //ring for a timer and health
      this.add(this.health);
    },
    /**
     * send shapes to their destination
     */
    sendShapes: function sendShapes() {
    },
  });

  var Side = {
    Left: 0,
    Right: 1
  }

  /**
   * holds shapes that will be played
   */
  var PieceQueue = util.extend(Phaser.Group, 'PieceQueue', {
    constructor: function PieceQueue(game, parent, side) {
      this.constructor$Group(game, parent);
      this.parent = parent; //parent spite (PlayGame)
      this.side = side; //which way the queue is facing
      this.onAddPiece = new Phaser.Signal(); //when piece added
      this.onTake = new Phaser.Signal(); //signal fired when a shape is taken

      this.onAddPiece.add(this.doAddPiece.bind(this));
      this.onAddPiece.dispatch();
    },
    doAddPiece: function doAddPiece() {
      var piece = Piece.randomPiece(this.game, this.getSpawn().x, this.getSpawn().y);
      var tween = this.game.add.tween(piece);
      tween.to({
        x: this.parent.placements.queueTarget.x,
        y: this.parent.placements.queueTarget.y
      }, this.parent.speed);
      tween.start();
      this.add(piece);
      this.game.time.events.add(this.parent.speed / PIECES_IN_QUEUE,
          this.onAddPiece.dispatch, this.onAddPiece);
    },
    getSpawn: function getSpawn() {
      switch(this.side) {
        case Side.Left: return this.parent.placements.leftSpawn;
        case Side.Right: return this.parent.placements.rightSpawn;
      }
    },
    /**
     * returns the next shape in line for the center and moves everyone up
     */
    takeNext: function takeNext() {
      //TODO
    }
  });

  /**
   * place where the shapes are supposed to go
   */
  var Goal = util.extend(Phaser.Sprite, 'Goal', {
    constructor: function Goal() {
      this.onRightShape = null; //signal fired when right shape recieved
      this.onWrongShape = null; //signal fired when wrong shape recieved
      this.leftKey = null; //key to press to send a shape from the left queue
      this.rightKey = null; //key to pressed to send a shape from the right queue
    }
  });

  var Score = util.extend(Phaser.Group, 'Score', {
    constructor: function Score() {
      this.timer = null; //right for time
      this.health = null; //ring for health
    }
  });

  var Ring = util.extend(Phaser.Sprite, 'Ring', {
    constructor: function Ring(game, parent, radius, thickness, color) {
      var outer = radius + thickness;
      this.bitmap = util.createBitmap(game, 2 * outer, 2 * outer);
      this.constructor$Sprite(game, parent.placements.ringCenter.x,
          parent.placements.ringCenter.y, this.bitmap);
      this.anchor.x = 0.5;
      this.anchor.y = 0.5;
      this.radius = radius;
      this.thickness = thickness;
      this.color = color;
    },
    update: function update() {
      var centerx = this.bitmap.canvas.width / 2;
      var centery = this.bitmap.canvas.height / 2;
      var context = this.bitmap.context;
      var angle = this.game.math.degToRad(90);
      var total = this.radius + this.thickness;

      context.fillStyle = this.color;
      context.strokeStyle = this.color;

      context.beginPath();
      context.arc(centerx, centery, this.radius, 0, angle);

      var end = this.getEndPoint(angle);
      context.lineTo(end.x, end.y);

      context.arc(centerx, centery, total, angle, 0, true);
      context.closePath();

      context.fill();
      context.stroke();
      context.restore();
    },
    getEndPoint: function getEndPoint(angle) {
      var centerx = this.bitmap.canvas.width / 2;
      var centery = this.bitmap.canvas.height / 2;
      var total = this.radius + this.thickness;
      var tmp = util.normalWithAngle(angle);
      tmp = Phaser.Point.multiply(tmp, new Phaser.Point(total, total));
      tmp.add(centerx, centery);
      return tmp;
    }
  });

  var Piece = util.extend(Phaser.Sprite, 'Piece', {
    constructor: function Piece(game, x, y, shape, color) {
      var texture = util.getTextureFromCache(game, Piece.getTextureName(shape, color));
      this.constructor$Sprite(game, x, y, texture);
      this.shape = shape;
      this.color = color;
    }
  });
  Piece.randomPiece = function randomPiece(game, x, y) {
    return new Piece(game, x, y, Shape.randomShape(), Color.randomColor());
  };
  Piece.getTextureName = function getTextureName(shape, color) {
    return 'piece-' + shape.name + '-' + color.name;
  }

  var Shape = util.extend(Object, 'Shape', {
    constructor: function Shape(name, texture) {
      this.name = name;
      this.texture = texture;
    }
  });
  Shape.shapes = [
    new Shape('triangle', 'images/triangle'),
    new Shape('square', 'images/square'),
    new Shape('circle', 'images/circle'),
    new Shape('pentagon', 'images/pentagon')
  ];
  Shape.randomShape = function randomShape() {
    return rand.pick(Shape.shapes);
  }

  var Color = util.extend(Object, 'Color', {
    constructor: function Color(name, shade) {
      this.name = name;
      this.shade = shade;
    }
  });
  Color.colors = [
    new Color('red', '#FF0000'),
    new Color('blue', '#0000FF'),
    new Color('yellow', '#FFFF00'),
    new Color('green', '#00FF00')
  ]
  Color.randomColor = function randomColor() {
    return rand.pick(Color.colors)
  }

  return {
    PlayState: PlayState,
    Shape: Shape,
    Color: Color,
    Piece: Piece
  }
});
<commit_msg>Ring cleanup<commit_after>base.registerModule('play', function() {
  var util = base.importModule('util');

  var PIECES_IN_QUEUE = 5;
  var rand = new Phaser.RandomDataGenerator();

  var PlayState = util.extend(Phaser.State, 'PlayState', {
    constructor: function PlayState() {
      this.playGame = null;
    },

    create: function create() {
      this.playGame = new PlayGame(this.game);
      this.game.world.add(this.playGame);
    },

    update: function update() {
      //this.playGame.update();
    },

    shutdown: function shutdown() {
      util.clearBitmapCache();
    }
  });

  /**
   * creates the placements of things on the screen
   */
  function makePlacements(width, height) {
    var places = {
      //place to spawn pieces for left queue
      leftSpawn: [-50, -50], //topleft corner
      //where the pieces in the queue go to join
      queueTarget: [width / 2, height / 2], //screen center
      //center of the rings
      ringCenter: [width / 2, height / 2] //screen center
    }
    var names = Object.getOwnPropertyNames(places);
    var ret = {}
    for(var i=0; i<names.length; i++) {
      var name = names[i];
      var coord = places[name];
      var point = new Phaser.Point(coord[0], coord[1]);
      ret[name] = point;
    }
    return ret;
  }

  /**
   * the play area
   */
  var PlayGame = util.extend(Phaser.Group, 'PlayGame', {
    constructor: function PlayGame(game) {
      this.constructor$Group(game);
      //what goes where
      this.placements = makePlacements(game.scale.width, game.scale.height);
      //speed at which to send pieces
      this.speed = 5000;

      this.queueLeft = new PieceQueue(game, this, Side.Left); //line of shapes on the left
      this.queueRight = null; //line of shapes on the right
      this.goals = null; //shapes to specify what goes where
      this.health = new Ring(game, this, 100, 5, '#000000'); //ring for a timer and health
      this.add(this.health);
    },
    /**
     * send shapes to their destination
     */
    sendShapes: function sendShapes() {
    },
  });

  var Side = {
    Left: 0,
    Right: 1
  }

  /**
   * holds shapes that will be played
   */
  var PieceQueue = util.extend(Phaser.Group, 'PieceQueue', {
    constructor: function PieceQueue(game, parent, side) {
      this.constructor$Group(game, parent);
      this.parent = parent; //parent spite (PlayGame)
      this.side = side; //which way the queue is facing
      this.onAddPiece = new Phaser.Signal(); //when piece added
      this.onTake = new Phaser.Signal(); //signal fired when a shape is taken

      this.onAddPiece.add(this.doAddPiece.bind(this));
      this.onAddPiece.dispatch();
    },
    doAddPiece: function doAddPiece() {
      var piece = Piece.randomPiece(this.game, this.getSpawn().x, this.getSpawn().y);
      var tween = this.game.add.tween(piece);
      tween.to({
        x: this.parent.placements.queueTarget.x,
        y: this.parent.placements.queueTarget.y
      }, this.parent.speed);
      tween.start();
      this.add(piece);
      this.game.time.events.add(this.parent.speed / PIECES_IN_QUEUE,
          this.onAddPiece.dispatch, this.onAddPiece);
    },
    getSpawn: function getSpawn() {
      switch(this.side) {
        case Side.Left: return this.parent.placements.leftSpawn;
        case Side.Right: return this.parent.placements.rightSpawn;
      }
    },
    /**
     * returns the next shape in line for the center and moves everyone up
     */
    takeNext: function takeNext() {
      //TODO
    }
  });

  /**
   * place where the shapes are supposed to go
   */
  var Goal = util.extend(Phaser.Sprite, 'Goal', {
    constructor: function Goal() {
      this.onRightShape = null; //signal fired when right shape recieved
      this.onWrongShape = null; //signal fired when wrong shape recieved
      this.leftKey = null; //key to press to send a shape from the left queue
      this.rightKey = null; //key to pressed to send a shape from the right queue
    }
  });

  var Score = util.extend(Phaser.Group, 'Score', {
    constructor: function Score() {
      this.timer = null; //right for time
      this.health = null; //ring for health
    }
  });

  var Ring = util.extend(Phaser.Sprite, 'Ring', {
    constructor: function Ring(game, parent, radius, thickness, color) {
      var outer = radius + thickness;
      this.bitmap = util.createBitmap(game, 2 * outer, 2 * outer);
      this.constructor$Sprite(game, parent.placements.ringCenter.x,
          parent.placements.ringCenter.y, this.bitmap);
      this.anchor.x = 0.5;
      this.anchor.y = 0.5;
      this.radius = radius;
      this.thickness = thickness;
      this.color = color;
    },
    update: function update() {
      var context = this.bitmap.context;
      var angle = this.game.math.degToRad(360);

      context.fillStyle = this.color;
      context.strokeStyle = this.color;

      context.beginPath();
      context.arc(this.center().x, this.center().y, this.radius, 0, angle);

      var end = this.getEndPoint(angle);
      context.lineTo(end.x, end.y);

      context.arc(this.center().x, this.center().y, this.totalRadius(), angle, 0, true);
      context.closePath();

      context.fill();
      context.stroke();
      context.restore();
    },
    getEndPoint: function getEndPoint(angle) {
      var tmp = util.normalWithAngle(angle);
      tmp = Phaser.Point.multiply(tmp, new Phaser.Point(this.totalRadius(), this.totalRadius()));
      tmp.add(this.center().x, this.center().y);
      return tmp;
    },
    center: function center() {
      return new Phaser.Point(this.bitmap.canvas.width / 2,
          this.bitmap.canvas.height / 2);
    },
    totalRadius: function totalRadius() {
      return this.radius + this.thickness;
    }
  });

  var Piece = util.extend(Phaser.Sprite, 'Piece', {
    constructor: function Piece(game, x, y, shape, color) {
      var texture = util.getTextureFromCache(game, Piece.getTextureName(shape, color));
      this.constructor$Sprite(game, x, y, texture);
      this.shape = shape;
      this.color = color;
    }
  });
  Piece.randomPiece = function randomPiece(game, x, y) {
    return new Piece(game, x, y, Shape.randomShape(), Color.randomColor());
  };
  Piece.getTextureName = function getTextureName(shape, color) {
    return 'piece-' + shape.name + '-' + color.name;
  }

  var Shape = util.extend(Object, 'Shape', {
    constructor: function Shape(name, texture) {
      this.name = name;
      this.texture = texture;
    }
  });
  Shape.shapes = [
    new Shape('triangle', 'images/triangle'),
    new Shape('square', 'images/square'),
    new Shape('circle', 'images/circle'),
    new Shape('pentagon', 'images/pentagon')
  ];
  Shape.randomShape = function randomShape() {
    return rand.pick(Shape.shapes);
  }

  var Color = util.extend(Object, 'Color', {
    constructor: function Color(name, shade) {
      this.name = name;
      this.shade = shade;
    }
  });
  Color.colors = [
    new Color('red', '#FF0000'),
    new Color('blue', '#0000FF'),
    new Color('yellow', '#FFFF00'),
    new Color('green', '#00FF00')
  ]
  Color.randomColor = function randomColor() {
    return rand.pick(Color.colors)
  }

  return {
    PlayState: PlayState,
    Shape: Shape,
    Color: Color,
    Piece: Piece
  }
});
<|endoftext|>