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

	// Load node-modules;
	grunt.loadNpmTasks( "grunt-contrib-jshint" );
	grunt.loadNpmTasks( "grunt-text-replace" );
	grunt.loadNpmTasks( "grunt-shell" );
	grunt.loadNpmTasks( "grunt-contrib-compress" );
	grunt.loadNpmTasks( "grunt-contrib-uglify" );
	grunt.loadNpmTasks( "grunt-contrib-cssmin" );
	grunt.loadNpmTasks( "grunt-contrib-clean" );
	grunt.loadNpmTasks( "grunt-jscs" );
	grunt.loadTasks( "tasks" );

	var bumpVersion = function( version ) {
			var join = ".",
				level = grunt.option( "level" ) || 2;

			if ( typeof version === "number" ) {
				join = "";
				version = version.toString();
			}

			version = version.split( join ) || [ 0, 0, 0 ];
			version[level]++;
			return version.join( join );
		},
		secrets;

	if ( grunt.file.exists( ".secrets.json" ) ) {
		secrets = grunt.file.readJSON( ".secrets.json" );
	} else {
		secrets = {
				"getLocalization": {
						"username": "",
						"password": ""
				}
		};
	}

	// Project configuration.
	grunt.initConfig( {
		pkg: grunt.file.readJSON( "package.json" ),
		secrets: secrets,

		jshint: {
			main: [ "<%= pkg.main %>", "Gruntfile.js", "www/js/hasher.js", "www/js/home.js", "chrome.js", "test/tests.js" ],
			options: {
				jshintrc: true
			}
		},

		jscs: {
			main: [ "<%= pkg.main %>", "www/js/home.js", "www/js/hasher.js", "chrome.js" ],
			options: {
				config: true,
				fix: true
			}
		},

		blanket_mocha: {
			test: {
				src: [ "test/tests.html" ],
				options: {
					threshold: 5
				}
			}
		},

		compress: {
			makeFW: {
				options: {
					archive: "build/firmware/UI.zip"
				},
				files: [ {
					src: [ "css/**", "js/**", "img/**", "locale/*.js", "*.htm" ],
					cwd: "www/",
					expand: true
				}, {
					src: "res/ios-web/**"
				} ]
			},
			makePGB: {
				options: {
					archive: "build/app.zip"
				},
				files: [ {
					src: [ "config.xml", "res/**", "www/**" ],
					dot: true,
					expand: true
				} ]
			},
			jsAsset: {
				options: {
					mode: "gzip"
				},
				files: [ {
					expand: true,
					src: [ "www/js/app.js", "www/js/jqm.js" ],
					ext: ".jgz"
				} ]
			},
			cssAsset: {
				options: {
					mode: "gzip"
				},
				files: [ {
					expand: true,
					src: [ "www/css/app.css" ],
					ext: ".cgz"
				} ]
			},
			firefox: {
				options: {
					archive: "build/firefox/com.albahra.sprinklers.zip"
				},
				files: [ {
					src: [ "css/**", "js/**", "img/**", "locale/**", "*.htm" ],
					cwd: "www/",
					expand: true
				}, {
					src: [ "manifest.webapp", "res/firefox/**" ]
				} ]
			},
			chrome: {
				options: {
					archive: "build/chrome/com.albahra.sprinklers.zip"
				},
				files: [ {
					src: [ "css/**", "js/**", "img/**", "locale/**", "*.htm" ],
					cwd: "www/",
					expand: true
				}, {
					src: [ "manifest.json", "chrome.js", "res/chrome/**" ]
				} ]
			},
			blackberry10: {
				options: {
					archive: "build/blackberry10/com.albahra.sprinklers.zip"
				},
				files: [ {
					src: [ "bb10app.bar" ],
					cwd: "platforms/blackberry10/build/device/",
					expand: true
				} ]
			}
		},

		shell: {
			updateUI: {
				command: [
					"cd build/firmware",
					"unzip UI.zip",
					"rsync -azp --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r * <%= secrets.firmware.rayshobby.location %>",
					"rsync -azp --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r * <%= secrets.firmware.opensprinkler.location %>"
				].join( "&&" )
			},
			updateBetaUI: {
				command: [
					"cd build/firmware",
					"unzip UI.zip",
					"rsync -azp --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r * <%= secrets.firmware.betaui.location %>"
				].join( "&&" )
			},
			updatePGB: {
				command: "curl -X PUT -F file=@build/app.zip https://build.phonegap.com/api/v1/apps/<%= pkg.phonegap.id %>?auth_token=<%= secrets.phonegap.token %> >/dev/null 2>&1"
			},
			pushEng: {
				command: [
					"xgettext --keyword=_ --output=- www/js/main.js --omit-header --force-po --from-code=UTF-8 --language='Python' | sed '/^\#/d' > .msgjs",
					"sed -E 's/data-translate=(\".*\")/_(\\1)/g' www/index.htm | xgettext --keyword=_ --output=- --language='Python' --omit-header --force-po - | sed '/^\#/d' > .msghtml",
					"msgcat .msgjs .msghtml > www/locale/messages_en.po",
					"rm .msgjs .msghtml",
					"git add www/locale/messages_en.po",
					"git diff-index --quiet HEAD || git commit -m 'Localization: Update English strings'",
					"git push"
				].join( "&&" )
			},
			updateLang: {
				command: [
					"curl --user <%= secrets.getLocalization.username %>:<%= secrets.getLocalization.password %> https://api.getlocalization.com/OpenSprinkler/api/translations/zip/ -o langs.zip",
					"unzip langs.zip",
					"rm langs.zip",
					"find . -type f -maxdepth 1 -iname 'messages_*.po' -print0 | while IFS= read -r -d $'\\0' line; do file=(${line//_/ }); lang=${file[1]}; file=(${lang//-/ }); lang=${file[0]}; file=(${lang//./ }); lang=${file[0]}; mv \"$line\" messages.po; po2json -p messages.po > \"www/locale/$lang.js\"; rm messages.po; done",
					"git add www/locale",
					"git diff-index --quiet HEAD || git commit -m 'Localization: Update languages from getlocalization.com'",
					"git push"
				].join( "&&" )
			},
			startOSPi: {
				command: "test/launch_ospi.sh start"
			},
			stopOSPi: {
				command: [
					"test/launch_ospi.sh stop",
					"rm -r build/firmware/ospi"
				].join( "&&" )
			},
			startDemo: {
				command: "test/launch_osdemo.sh start"
			},
			stopDemo: {
				command: [
					"test/launch_osdemo.sh stop",
					"rm -r build/firmware/unified"
				].join( "&&" )
			},
			symres: {
				command: "cd www && ln -s ../res res && cd .."
			},
			blackberry10: {
				command: "cordova build blackberry10 --release"
			},
			pushBump: {
				command: [
					"git add www/js/main.js source/osx/Resources/OpenSprinkler-Info.plist config.xml manifest.json manifest.webapp package.json",
					"git commit -m 'Base: Increment version number'",
					"git push"
				].join( "&&" )
			}
		},

		replace: {
			about: {
				src: [ "www/js/main.js" ],
				overwrite: true,
				replacements: [ {
					from: /_\("App Version"\)\+": ([\d|\.]+)"/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "_(\"App Version\")+\": " + bumpVersion( regexMatches[0] ) + "\"";
					}
				} ]
			},
			osx: {
				src: [ "source/osx/Resources/OpenSprinkler-Info.plist" ],
				overwrite: true,
				replacements: [ {
					from: /<key>CFBundleShortVersionString<\/key>\n\t<string>([\d|\.]+)<\/string>/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "<key>CFBundleShortVersionString</key>\n\t<string>" + bumpVersion( regexMatches[0] ) + "</string>";
					}
				}, {
					from: /<key>CFBundleVersion<\/key>\n\t<string>(\d+)<\/string>/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "<key>CFBundleVersion<\/key>\n\t<string>" + ( parseInt( regexMatches[0] ) + 1 ) + "<\/string>";
					}
				} ]
			},
			phonegap: {
				src: [ "config.xml" ],
				overwrite: true,
				replacements: [
					{
						from: /version     = "([\d|\.]+)"/g,
						to: function( matchedWord, index, fullText, regexMatches ) {
							return "version     = \"" + bumpVersion( regexMatches[0] ) + "\"";
						}
					}, {
						from: /versionCode = "(\d+)"/g,
						to: function( matchedWord, index, fullText, regexMatches ) {
							return "versionCode = \"" + ( parseInt( regexMatches[0] ) + 1 ) + "\"";
						}
					}, {
						from: /<string>(\d+)<\/string>/g,
						to: function( matchedWord, index, fullText, regexMatches ) {
							return "<string>" + bumpVersion( parseInt( regexMatches[0] ) ) + "</string>";
						}
					} ]
			},
			manifests: {
				src: [ "manifest.json", "manifest.webapp", "package.json" ],
				overwrite: true,
				replacements: [ {
					from: /"version": "([\d|\.]+)"/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "\"version\": \"" + bumpVersion( regexMatches[0] ) + "\"";
					}
				} ]
			}
		},

		uglify: {
			makeFW: {
				files: {
					"www/js/app.js": [ "www/js/jquery.js", "www/js/main.js", "www/js/libs.js" ]
				}
			}
		},

		cssmin: {
			combine: {
				files: {
					"www/css/app.css": [ "www/css/jqm.css", "www/css/main.css" ]
				}
			}
		},

		clean: {
			makeFW: [ "www/js/app.js", "www/css/app.css", "www/css/app.cgz", "www/js/*.jgz" ],
			pushFW: [ "build/firmware/*", "build/app.zip" ],
			symres: [ "www/res" ]
		}
	} );

	// Default task(s).
	grunt.registerTask( "default", [ "jshint", "jscs" ] );
	grunt.registerTask( "test", [ "default", "blanket_mocha" ] );
	grunt.registerTask( "updateLang", [ "shell:updateLang" ] );
	grunt.registerTask( "pushEng", [ "shell:pushEng" ] );
	grunt.registerTask( "makeFW", [ "default", "uglify", "cssmin", "compress:jsAsset", "compress:cssAsset", "compress:makeFW", "clean:makeFW" ] );
	grunt.registerTask( "pushFW", [ "makeFW", "shell:updateUI", "clean:pushFW" ] );
	grunt.registerTask( "pushBetaFW", [ "makeFW", "shell:updateBetaUI", "clean:pushFW" ] );
	grunt.registerTask( "build", [ "default", "shell:symres", "shell:blackberry10", "compress:firefox", "compress:chrome", "compress:blackberry10", "pushFW", "clean:symres" ] );
	grunt.registerTask( "bump", [ "default", "replace:about", "replace:osx", "replace:phonegap", "replace:manifests", "shell:pushBump" ] );

};
<commit_msg>Base: Add Gruntfile.js to JSCS checks<commit_after>module.exports = function( grunt ) {

	// Load node-modules;
	grunt.loadNpmTasks( "grunt-contrib-jshint" );
	grunt.loadNpmTasks( "grunt-text-replace" );
	grunt.loadNpmTasks( "grunt-shell" );
	grunt.loadNpmTasks( "grunt-contrib-compress" );
	grunt.loadNpmTasks( "grunt-contrib-uglify" );
	grunt.loadNpmTasks( "grunt-contrib-cssmin" );
	grunt.loadNpmTasks( "grunt-contrib-clean" );
	grunt.loadNpmTasks( "grunt-jscs" );
	grunt.loadTasks( "tasks" );

	var bumpVersion = function( version ) {
			var join = ".",
				level = grunt.option( "level" ) || 2;

			if ( typeof version === "number" ) {
				join = "";
				version = version.toString();
			}

			version = version.split( join ) || [ 0, 0, 0 ];
			version[level]++;
			return version.join( join );
		},
		secrets;

	if ( grunt.file.exists( ".secrets.json" ) ) {
		secrets = grunt.file.readJSON( ".secrets.json" );
	} else {
		secrets = {
				"getLocalization": {
						"username": "",
						"password": ""
				}
		};
	}

	// Project configuration.
	grunt.initConfig( {
		pkg: grunt.file.readJSON( "package.json" ),
		secrets: secrets,

		jshint: {
			main: [ "<%= pkg.main %>", "Gruntfile.js", "www/js/hasher.js", "www/js/home.js", "chrome.js", "test/tests.js" ],
			options: {
				jshintrc: true
			}
		},

		jscs: {
			main: [ "<%= pkg.main %>", "Gruntfile.js", "www/js/hasher.js", "www/js/home.js", "chrome.js", "test/tests.js" ],
			options: {
				config: true,
				fix: true
			}
		},

		blanket_mocha: {
			test: {
				src: [ "test/tests.html" ],
				options: {
					threshold: 5
				}
			}
		},

		compress: {
			makeFW: {
				options: {
					archive: "build/firmware/UI.zip"
				},
				files: [ {
					src: [ "css/**", "js/**", "img/**", "locale/*.js", "*.htm" ],
					cwd: "www/",
					expand: true
				}, {
					src: "res/ios-web/**"
				} ]
			},
			makePGB: {
				options: {
					archive: "build/app.zip"
				},
				files: [ {
					src: [ "config.xml", "res/**", "www/**" ],
					dot: true,
					expand: true
				} ]
			},
			jsAsset: {
				options: {
					mode: "gzip"
				},
				files: [ {
					expand: true,
					src: [ "www/js/app.js", "www/js/jqm.js" ],
					ext: ".jgz"
				} ]
			},
			cssAsset: {
				options: {
					mode: "gzip"
				},
				files: [ {
					expand: true,
					src: [ "www/css/app.css" ],
					ext: ".cgz"
				} ]
			},
			firefox: {
				options: {
					archive: "build/firefox/com.albahra.sprinklers.zip"
				},
				files: [ {
					src: [ "css/**", "js/**", "img/**", "locale/**", "*.htm" ],
					cwd: "www/",
					expand: true
				}, {
					src: [ "manifest.webapp", "res/firefox/**" ]
				} ]
			},
			chrome: {
				options: {
					archive: "build/chrome/com.albahra.sprinklers.zip"
				},
				files: [ {
					src: [ "css/**", "js/**", "img/**", "locale/**", "*.htm" ],
					cwd: "www/",
					expand: true
				}, {
					src: [ "manifest.json", "chrome.js", "res/chrome/**" ]
				} ]
			},
			blackberry10: {
				options: {
					archive: "build/blackberry10/com.albahra.sprinklers.zip"
				},
				files: [ {
					src: [ "bb10app.bar" ],
					cwd: "platforms/blackberry10/build/device/",
					expand: true
				} ]
			}
		},

		shell: {
			updateUI: {
				command: [
					"cd build/firmware",
					"unzip UI.zip",
					"rsync -azp --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r * <%= secrets.firmware.rayshobby.location %>",
					"rsync -azp --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r * <%= secrets.firmware.opensprinkler.location %>"
				].join( "&&" )
			},
			updateBetaUI: {
				command: [
					"cd build/firmware",
					"unzip UI.zip",
					"rsync -azp --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r * <%= secrets.firmware.betaui.location %>"
				].join( "&&" )
			},
			updatePGB: {
				command: "curl -X PUT -F file=@build/app.zip https://build.phonegap.com/api/v1/apps/<%= pkg.phonegap.id %>?auth_token=<%= secrets.phonegap.token %> >/dev/null 2>&1"
			},
			pushEng: {
				command: [
					"xgettext --keyword=_ --output=- www/js/main.js --omit-header --force-po --from-code=UTF-8 --language='Python' | sed '/^\#/d' > .msgjs",
					"sed -E 's/data-translate=(\".*\")/_(\\1)/g' www/index.htm | xgettext --keyword=_ --output=- --language='Python' --omit-header --force-po - | sed '/^\#/d' > .msghtml",
					"msgcat .msgjs .msghtml > www/locale/messages_en.po",
					"rm .msgjs .msghtml",
					"git add www/locale/messages_en.po",
					"git diff-index --quiet HEAD || git commit -m 'Localization: Update English strings'",
					"git push"
				].join( "&&" )
			},
			updateLang: {
				command: [
					"curl --user <%= secrets.getLocalization.username %>:<%= secrets.getLocalization.password %> https://api.getlocalization.com/OpenSprinkler/api/translations/zip/ -o langs.zip",
					"unzip langs.zip",
					"rm langs.zip",
					"find . -type f -maxdepth 1 -iname 'messages_*.po' -print0 | while IFS= read -r -d $'\\0' line; do file=(${line//_/ }); lang=${file[1]}; file=(${lang//-/ }); lang=${file[0]}; file=(${lang//./ }); lang=${file[0]}; mv \"$line\" messages.po; po2json -p messages.po > \"www/locale/$lang.js\"; rm messages.po; done",
					"git add www/locale",
					"git diff-index --quiet HEAD || git commit -m 'Localization: Update languages from getlocalization.com'",
					"git push"
				].join( "&&" )
			},
			startOSPi: {
				command: "test/launch_ospi.sh start"
			},
			stopOSPi: {
				command: [
					"test/launch_ospi.sh stop",
					"rm -r build/firmware/ospi"
				].join( "&&" )
			},
			startDemo: {
				command: "test/launch_osdemo.sh start"
			},
			stopDemo: {
				command: [
					"test/launch_osdemo.sh stop",
					"rm -r build/firmware/unified"
				].join( "&&" )
			},
			symres: {
				command: "cd www && ln -s ../res res && cd .."
			},
			blackberry10: {
				command: "cordova build blackberry10 --release"
			},
			pushBump: {
				command: [
					"git add www/js/main.js source/osx/Resources/OpenSprinkler-Info.plist config.xml manifest.json manifest.webapp package.json",
					"git commit -m 'Base: Increment version number'",
					"git push"
				].join( "&&" )
			}
		},

		replace: {
			about: {
				src: [ "www/js/main.js" ],
				overwrite: true,
				replacements: [ {
					from: /_\("App Version"\)\+": ([\d|\.]+)"/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "_(\"App Version\")+\": " + bumpVersion( regexMatches[0] ) + "\"";
					}
				} ]
			},
			osx: {
				src: [ "source/osx/Resources/OpenSprinkler-Info.plist" ],
				overwrite: true,
				replacements: [ {
					from: /<key>CFBundleShortVersionString<\/key>\n\t<string>([\d|\.]+)<\/string>/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "<key>CFBundleShortVersionString</key>\n\t<string>" + bumpVersion( regexMatches[0] ) + "</string>";
					}
				}, {
					from: /<key>CFBundleVersion<\/key>\n\t<string>(\d+)<\/string>/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "<key>CFBundleVersion<\/key>\n\t<string>" + ( parseInt( regexMatches[0] ) + 1 ) + "<\/string>";
					}
				} ]
			},
			phonegap: {
				src: [ "config.xml" ],
				overwrite: true,
				replacements: [
					{
						from: /version     = "([\d|\.]+)"/g,
						to: function( matchedWord, index, fullText, regexMatches ) {
							return "version     = \"" + bumpVersion( regexMatches[0] ) + "\"";
						}
					}, {
						from: /versionCode = "(\d+)"/g,
						to: function( matchedWord, index, fullText, regexMatches ) {
							return "versionCode = \"" + ( parseInt( regexMatches[0] ) + 1 ) + "\"";
						}
					}, {
						from: /<string>(\d+)<\/string>/g,
						to: function( matchedWord, index, fullText, regexMatches ) {
							return "<string>" + bumpVersion( parseInt( regexMatches[0] ) ) + "</string>";
						}
					} ]
			},
			manifests: {
				src: [ "manifest.json", "manifest.webapp", "package.json" ],
				overwrite: true,
				replacements: [ {
					from: /"version": "([\d|\.]+)"/g,
					to: function( matchedWord, index, fullText, regexMatches ) {
						return "\"version\": \"" + bumpVersion( regexMatches[0] ) + "\"";
					}
				} ]
			}
		},

		uglify: {
			makeFW: {
				files: {
					"www/js/app.js": [ "www/js/jquery.js", "www/js/main.js", "www/js/libs.js" ]
				}
			}
		},

		cssmin: {
			combine: {
				files: {
					"www/css/app.css": [ "www/css/jqm.css", "www/css/main.css" ]
				}
			}
		},

		clean: {
			makeFW: [ "www/js/app.js", "www/css/app.css", "www/css/app.cgz", "www/js/*.jgz" ],
			pushFW: [ "build/firmware/*", "build/app.zip" ],
			symres: [ "www/res" ]
		}
	} );

	// Default task(s).
	grunt.registerTask( "default", [ "jshint", "jscs" ] );
	grunt.registerTask( "test", [ "default", "blanket_mocha" ] );
	grunt.registerTask( "updateLang", [ "shell:updateLang" ] );
	grunt.registerTask( "pushEng", [ "shell:pushEng" ] );
	grunt.registerTask( "makeFW", [ "default", "uglify", "cssmin", "compress:jsAsset", "compress:cssAsset", "compress:makeFW", "clean:makeFW" ] );
	grunt.registerTask( "pushFW", [ "makeFW", "shell:updateUI", "clean:pushFW" ] );
	grunt.registerTask( "pushBetaFW", [ "makeFW", "shell:updateBetaUI", "clean:pushFW" ] );
	grunt.registerTask( "build", [ "default", "shell:symres", "shell:blackberry10", "compress:firefox", "compress:chrome", "compress:blackberry10", "pushFW", "clean:symres" ] );
	grunt.registerTask( "bump", [ "default", "replace:about", "replace:osx", "replace:phonegap", "replace:manifests", "shell:pushBump" ] );

};
<|endoftext|>


<commit_before>/* Gruntfile.js
 * Grunt workflow for building kick-ass AngularJS applications.
 * @author Calvin Lai <calvin@wunwun.com>
 */

module.exports = function(grunt) {

  var _APP_NAME_ = "CHANGE ME IN Gruntfile.js";

  // initial grunt configuration
  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),
    appDir: 'www',
    tmpDir: 'tmp',
    srcDir: 'src',
    bowerDir: 'vendor',
    vendorDir: 'src/js/vendor',
    releaseDir: '<%= appDir %>',
    connect: {
    	server: {
    		options: {
    			port: 9001,
    			base: '<%= appDir %>'
    		}
    	}
    },
    assets: {
      css: {
        vendor: [

          // Add additional Bower components here
          '<%= bowerDir %>/bootstrap/dist/css/bootstrap.css',
          '<%= bowerDir %>/font-awesome/css/font-awesome.css'

        ],
        // shouldn't need to touch this
        src: [
          '<%= appDir %>/css/vendor.css',
          '<%= appDir %>/css/app.css'
        ]
      },
      js: {
        vendor: [
          // add any Bower components here.
          '<%= bowerDir %>/angular/angular.js',
          '<%= bowerDir %>/angular-route/angular-route.js',
          '<%= bowerDir %>/angular-touch/angular-touch.js'
        ],
        // shouldn't need to touch this.
        src: [
          '<%= appDir %>/js/vendor.js',
          '<%= appDir %>/js/pg.js',
          '<%= appDir %>/js/app.js',
          '<%= appDir %>/js/config.js',
          '<%= appDir %>/js/modules.js',
          '<%= appDir %>/js/directives.js',
          '<%= appDir %>/js/filters.js',
          '<%= appDir %>/js/services.js',
          '<%= appDir %>/js/controllers.js'
        ]
      }
    },

    // concatenate files for angularjs
    concat: {
      vendor: {
        files: {
          '<%= tmpDir %>/css/vendor.css': '<%= assets.css.vendor %>',
          '<%= tmpDir %>/js/vendor.js'  : '<%= assets.js.vendor %>'
        }
      },
      angular: {
        files: {
          '<%= tmpDir %>/js/config.js'      : ['<%= srcDir %>/js/config/*.js'],
          '<%= tmpDir %>/js/modules.js'     : ['<%= srcDir %>/js/modules/*.js', '<%= srcDir %>/js/modules/**/*.js'],
          '<%= tmpDir %>/js/controllers.js' : ['<%= srcDir %>/js/controllers/*.js', '<%= srcDir %>/js/controllers/**/*.js'],
          '<%= tmpDir %>/js/directives.js'  : ['<%= srcDir %>/js/directives/*.js', '<%= srcDir %>/js/directives/**/*.js'],
          '<%= tmpDir %>/js/filters.js'     : ['<%= srcDir %>/js/filters/*.js', '<%= srcDir %>/js/filters/**/*.js'],
          '<%= tmpDir %>/js/modules.js'     : ['<%= srcDir %>/js/modules/*.js', '<%= srcDir %>/js/modules/**/*.js'],
          '<%= tmpDir %>/js/services.js'    : ['<%= srcDir %>/js/services/*.js', '<%= srcDir %>/js/services/**/*.js']
        }
      },
      production: {
        files: {
          '<%= appDir %>/js/application.js': [
            '<%= tmpDir %>/js/production.js',
            '<%= tmpDir %>/js/vendor.js',
            '<%= tmpDir %>/js/pg.js',
            '<%= tmpDir %>/js/app.js',
            '<%= tmpDir %>/js/config.js',
            '<%= tmpDir %>/js/modules.js',
            '<%= tmpDir %>/js/directives.js',
            '<%= tmpDir %>/js/filters.js',
            '<%= tmpDir %>/js/services.js',
            '<%= tmpDir %>/js/controllers.js'
          ]
        }
      }
    },

    // for cleaning builds before re-building
    clean: {
      options: {
        force: true
      },
      tmp: {
        src: ['<%= tmpDir %>'],
      },
      development: {
        src: ['<%= tmpDir %>', '<%= appDir %>']
      },
      production: {
        src: ['<%= tmpDir %>', '<%= releaseDir %>']
      },
      css: {
        src: ['<%= appDir %>/css']
      },
      js: {
        src: ['<%= appDir %>/js']
      },
      img: {
        src: ['<%= appDir %>/img']
      },
      img: {
        src: ['<%= appDir %>/font']
      },
      partials: {
        src: ['<%= appDir %>/html/partials']
      }
    },

    copy: {
      config: {
        files: [
          { src: '<%= srcDir %>/js/config/application.js', dest: '<%= tmpDir %>/js/config/application.js' },
          { src: '<%= srcDir %>/js/app.js', dest: '<%= tmpDir %>/js/app.js' },
          { src: '<%= srcDir %>/js/pg.js', dest: '<%= tmpDir %>/js/pg.js' },
          { src: '<%= srcDir %>/config.xml', dest: '<%= appDir %>/config.xml' }
        ]
      },
      vendor: {
        files: [
          { src: '<%= tmpDir %>/css/vendor.css', dest: '<%= appDir %>/css/vendor.css' },
          { src: '<%= tmpDir %>/js/vendor.js', dest: '<%= appDir %>/js/vendor.js' }
        ]
      },
      img: {
        files: [
          { expand: true, cwd: '<%= srcDir %>/img/', src: ['**'], dest: '<%= appDir %>/img/' }
        ]
      },
      partials: {
        files: [
          { expand: true, cwd: '<%= srcDir %>/html/partials/', src: ['**'], dest: '<%= appDir %>/html/partials/' }
        ]
      },
      fonts: {
        files: [
          { expand: true, cwd: '<%= bowerDir %>/font-awesome/font/', src: ['**'], dest: '<%= appDir %>/font/' }
        ]
      },
      tmp_to_build: {
        files: [
          { expand: true, cwd: '<%= tmpDir %>/js/', src: ['*'], dest: '<%= appDir %>/js/' }
        ]
      },
      development: {
        files: [
          { src: '<%= srcDir %>/js/config/environments/development.js', dest: '<%= appDir %>/js/config/development.js' }
        ]
      },
      production: {
        files: [
          { src: '<%= srcDir %>/js/config/environments/production.js', dest: '<%= tmpDir %>/js/production.js' }
        ]
      }
    },

    // compile LESS files into CSS and store them in temp directories
    less: {
      options: {
        paths: [
          // add any additional paths to LESS components here
          "<%= bowerDir %>/lesshat",
          "<%= srcDir %>/css/config"
        ]
      },
      development: {
        files: {
          // put app.css directly into the build directory for development
          "<%= appDir %>/css/app.css": [
            "<%= srcDir %>/css/common/*.less",
            "<%= srcDir %>/css/*.less"
          ]
        }
      },
      production: {
        files: {
          // put app.css in tmp dir in production, so we can run cssmin on it after
          "<%= tmpDir %>/css/app.css": [
            "<%= srcDir %>/css/common/*.less",
            "<%= srcDir %>/css/*.less"
          ]
        }
      }
    },

    // ngmin for pre-minifying AngularJS apps
    ngmin: {
      routers: {
        src: '<%= tmpDir %>/js/config/router.js',
        dest: '<%= tmpDir %>/js/config/router.js'
      },
      controllers: {
        src: '<%= tmpDir %>/js/controllers.js',
        dest: '<%= tmpDir %>/js/controllers.js'
      },
      directives: {
        src: '<%= tmpDir %>/js/directives.js',
        dest: '<%= tmpDir %>/js/directives.js'
      },
      modules: {
        src: '<%= tmpDir %>/js/modules.js',
        dest: '<%= tmpDir %>/js/modules.js'
      },
      filters: {
        src: '<%= tmpDir %>/js/filters.js',
        dest: '<%= tmpDir %>/js/filters.js'
      },
      services: {
        src: '<%= tmpDir %>/js/services.js',
        dest: '<%= tmpDir %>/js/services.js'
      },
      vendor: {
        src: '<%= tmpDir %>/js/vendor.js',
        dest: '<%= tmpDir %>/js/vendor.js'
      }
    },

    // uglify js for production
    uglify: {
      production: {
        files: {
          '<%= appDir %>/js/application.js': [
            '<%= appDir %>/js/application.js'
          ]
        }
      },
    },

    // minify css for production
    cssmin: {
      production: {
        files: {
          '<%= appDir %>/css/app.css': [
            '<%= tmpDir %>/css/vendor.css',
            '<%= tmpDir %>/css/app.css'
          ],
        }
      }
    },

    // watch files, build on the fly for development
    watch: {
      root: {
        files: ['<%= srcDir %>/*'],
        tasks: ['copy:config']
      },
      scripts: {
        files: ['<%= srcDir %>/js/**','<%= srcDir %>/js/*'],
        tasks: [
          'clean:js', 'concat:angular', 'concat:vendor',
          'copy:development', 'copy:config', 'copy:vendor',
          'copy:tmp_to_build'
        ]
      },
      less: {
        files: [
          '<%= srcDir %>/css/*.less',
          '<%= srcDir %>/css/**/*.less'
        ],
        tasks: [
          'clean:css', 'concat:vendor', 'copy:vendor',
          'less:development'
        ]
      },
      img: {
        files: ['<%= srcDir %>/img/**'],
        tasks: ['clean:img', 'copy:img']
      },
      fonts: {
        files: ['<%= srcDir %>/font/**'],
        tasks: ['clean:fonts', 'copy:fonts']
      },
      partials: {
        files: ['<%= srcDir %>/html/partials/**'],
        tasks: ['clean:partials', 'copy:partials']
      },
      layouts: {
        files: ['<%= srcDir %>/html/layouts/**'],
        tasks: ['layouts:development']
      }
    },

    layouts: {
      options: {
        layout: '<%= srcDir %>/html/layouts/application.tmpl',
      },
      development: {
        options: {
          dest: '<%= appDir %>/index.html'
        },
        files: {
          css: '<%= assets.css.src %>',
          js: '<%= assets.js.src %>'
        }
      },
      production: {
        options: {
          dest: '<%= releaseDir %>/index.html'
        },
        files: {
          css: '<%= assets.css.src %>',
          js: '<%= assets.js.src %>'
        }
      }
    },

    config: {
      options: {
        template: '<%= srcDir %>/config.xml.tmpl',
        dest: '<%= appDir %>/config.xml'
      },
      enterprise: {},
      production: {},
      development: {}
    },

    // main build task (custom) with options
    // this task also builds out the main index.html
    // file based on templates, which are environment-aware
    build: {
      development: {},
      production: {},
      enterprise: {}
    }

  });

  // load grunt npm modules
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-ngmin');
  grunt.loadNpmTasks('grunt-shell');

  grunt.registerTask('dev', ['build:development', 'connect', 'watch']);

  // build HTML files based on target
  grunt.registerMultiTask('layouts', 'Builds an HTML file for angular.', function() {

    var opts = this.options()
      , target = this.target
      , css = this.files[0].src
      , js = this.files[1].src
      , layout = grunt.template.process(grunt.file.read(opts.layout), {
          data: { env: target, js: js, css: css, appName: _APP_NAME_ }
        });

    // generate main index.html file
    grunt.file.write(opts.dest, layout);
    grunt.log.write('Generating ' + opts.dest + '...').ok();

  });

  grunt.registerMultiTask('config', 'Builds the Cordova configuration file from template.', function() {

    var opts = this.options()
      , target = this.target
      , version = this.args[0] || '';

    var template = grunt.template.process(grunt.file.read(opts.template), {
          data: { target: target, appName: _APP_NAME_ }
        });

    // generate main index.html file
    grunt.file.write(opts.dest, template);
    grunt.log.write('Generating ' + opts.dest + '...').ok();

  });

  // task for building main index page based on environment
  grunt.registerMultiTask('build', 'Build the app based on environment.', function() {

    var opts = this.options()
      , target = this.target
      , env = target
      , args = this.args
      , version = args[0];

    if (target == 'enterprise') {
      env = 'production';
    }

    // clean up directories
    grunt.task.run('clean:' + env);

    // build all less files based on environment
    grunt.task.run('less:' + env);

    // concat angular files
    grunt.task.run('concat:angular');

    // use ngmin to pre-minify angular files
    grunt.task.run('ngmin');

    // concat vendor libs
    grunt.task.run('concat:vendor');

    // copy all files
    grunt.task.run('copy:' + env);
    grunt.task.run('copy:config');
    grunt.task.run('copy:partials');
    grunt.task.run('copy:img');
    grunt.task.run('copy:fonts');

    // copy tmp files to development
    if (target == 'development') {
      grunt.task.run('copy:vendor');
      grunt.task.run('copy:tmp_to_build');
    }

    if (target == 'production' || target == 'enterprise') {
      // concat all angular files into a single file
      grunt.task.run('concat:production');
      grunt.task.run('uglify:production');
      grunt.task.run('cssmin:production');
    }

    // build cordova config.xml file, uses target so we
    // can switch from production to enterprise for bundle ID
    grunt.task.run('config:' + target);

    // build main index.html file last
    grunt.task.run('layouts:' + env);

  });

};

<commit_msg>removed unused npm task<commit_after>/* Gruntfile.js
 * Grunt workflow for building kick-ass AngularJS applications.
 * @author Calvin Lai <calvin@wunwun.com>
 */

module.exports = function(grunt) {

  var _APP_NAME_ = "CHANGE ME IN Gruntfile.js";

  // initial grunt configuration
  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),
    appDir: 'www',
    tmpDir: 'tmp',
    srcDir: 'src',
    bowerDir: 'vendor',
    vendorDir: 'src/js/vendor',
    releaseDir: '<%= appDir %>',
    connect: {
    	server: {
    		options: {
    			port: 9001,
    			base: '<%= appDir %>'
    		}
    	}
    },
    assets: {
      css: {
        vendor: [

          // Add additional Bower components here
          '<%= bowerDir %>/bootstrap/dist/css/bootstrap.css',
          '<%= bowerDir %>/font-awesome/css/font-awesome.css'

        ],
        // shouldn't need to touch this
        src: [
          '<%= appDir %>/css/vendor.css',
          '<%= appDir %>/css/app.css'
        ]
      },
      js: {
        vendor: [
          // add any Bower components here.
          '<%= bowerDir %>/angular/angular.js',
          '<%= bowerDir %>/angular-route/angular-route.js',
          '<%= bowerDir %>/angular-touch/angular-touch.js'
        ],
        // shouldn't need to touch this.
        src: [
          '<%= appDir %>/js/vendor.js',
          '<%= appDir %>/js/pg.js',
          '<%= appDir %>/js/app.js',
          '<%= appDir %>/js/config.js',
          '<%= appDir %>/js/modules.js',
          '<%= appDir %>/js/directives.js',
          '<%= appDir %>/js/filters.js',
          '<%= appDir %>/js/services.js',
          '<%= appDir %>/js/controllers.js'
        ]
      }
    },

    // concatenate files for angularjs
    concat: {
      vendor: {
        files: {
          '<%= tmpDir %>/css/vendor.css': '<%= assets.css.vendor %>',
          '<%= tmpDir %>/js/vendor.js'  : '<%= assets.js.vendor %>'
        }
      },
      angular: {
        files: {
          '<%= tmpDir %>/js/config.js'      : ['<%= srcDir %>/js/config/*.js'],
          '<%= tmpDir %>/js/modules.js'     : ['<%= srcDir %>/js/modules/*.js', '<%= srcDir %>/js/modules/**/*.js'],
          '<%= tmpDir %>/js/controllers.js' : ['<%= srcDir %>/js/controllers/*.js', '<%= srcDir %>/js/controllers/**/*.js'],
          '<%= tmpDir %>/js/directives.js'  : ['<%= srcDir %>/js/directives/*.js', '<%= srcDir %>/js/directives/**/*.js'],
          '<%= tmpDir %>/js/filters.js'     : ['<%= srcDir %>/js/filters/*.js', '<%= srcDir %>/js/filters/**/*.js'],
          '<%= tmpDir %>/js/modules.js'     : ['<%= srcDir %>/js/modules/*.js', '<%= srcDir %>/js/modules/**/*.js'],
          '<%= tmpDir %>/js/services.js'    : ['<%= srcDir %>/js/services/*.js', '<%= srcDir %>/js/services/**/*.js']
        }
      },
      production: {
        files: {
          '<%= appDir %>/js/application.js': [
            '<%= tmpDir %>/js/production.js',
            '<%= tmpDir %>/js/vendor.js',
            '<%= tmpDir %>/js/pg.js',
            '<%= tmpDir %>/js/app.js',
            '<%= tmpDir %>/js/config.js',
            '<%= tmpDir %>/js/modules.js',
            '<%= tmpDir %>/js/directives.js',
            '<%= tmpDir %>/js/filters.js',
            '<%= tmpDir %>/js/services.js',
            '<%= tmpDir %>/js/controllers.js'
          ]
        }
      }
    },

    // for cleaning builds before re-building
    clean: {
      options: {
        force: true
      },
      tmp: {
        src: ['<%= tmpDir %>'],
      },
      development: {
        src: ['<%= tmpDir %>', '<%= appDir %>']
      },
      production: {
        src: ['<%= tmpDir %>', '<%= releaseDir %>']
      },
      css: {
        src: ['<%= appDir %>/css']
      },
      js: {
        src: ['<%= appDir %>/js']
      },
      img: {
        src: ['<%= appDir %>/img']
      },
      img: {
        src: ['<%= appDir %>/font']
      },
      partials: {
        src: ['<%= appDir %>/html/partials']
      }
    },

    copy: {
      config: {
        files: [
          { src: '<%= srcDir %>/js/config/application.js', dest: '<%= tmpDir %>/js/config/application.js' },
          { src: '<%= srcDir %>/js/app.js', dest: '<%= tmpDir %>/js/app.js' },
          { src: '<%= srcDir %>/js/pg.js', dest: '<%= tmpDir %>/js/pg.js' },
          { src: '<%= srcDir %>/config.xml', dest: '<%= appDir %>/config.xml' }
        ]
      },
      vendor: {
        files: [
          { src: '<%= tmpDir %>/css/vendor.css', dest: '<%= appDir %>/css/vendor.css' },
          { src: '<%= tmpDir %>/js/vendor.js', dest: '<%= appDir %>/js/vendor.js' }
        ]
      },
      img: {
        files: [
          { expand: true, cwd: '<%= srcDir %>/img/', src: ['**'], dest: '<%= appDir %>/img/' }
        ]
      },
      partials: {
        files: [
          { expand: true, cwd: '<%= srcDir %>/html/partials/', src: ['**'], dest: '<%= appDir %>/html/partials/' }
        ]
      },
      fonts: {
        files: [
          { expand: true, cwd: '<%= bowerDir %>/font-awesome/font/', src: ['**'], dest: '<%= appDir %>/font/' }
        ]
      },
      tmp_to_build: {
        files: [
          { expand: true, cwd: '<%= tmpDir %>/js/', src: ['*'], dest: '<%= appDir %>/js/' }
        ]
      },
      development: {
        files: [
          { src: '<%= srcDir %>/js/config/environments/development.js', dest: '<%= appDir %>/js/config/development.js' }
        ]
      },
      production: {
        files: [
          { src: '<%= srcDir %>/js/config/environments/production.js', dest: '<%= tmpDir %>/js/production.js' }
        ]
      }
    },

    // compile LESS files into CSS and store them in temp directories
    less: {
      options: {
        paths: [
          // add any additional paths to LESS components here
          "<%= bowerDir %>/lesshat",
          "<%= srcDir %>/css/config"
        ]
      },
      development: {
        files: {
          // put app.css directly into the build directory for development
          "<%= appDir %>/css/app.css": [
            "<%= srcDir %>/css/common/*.less",
            "<%= srcDir %>/css/*.less"
          ]
        }
      },
      production: {
        files: {
          // put app.css in tmp dir in production, so we can run cssmin on it after
          "<%= tmpDir %>/css/app.css": [
            "<%= srcDir %>/css/common/*.less",
            "<%= srcDir %>/css/*.less"
          ]
        }
      }
    },

    // ngmin for pre-minifying AngularJS apps
    ngmin: {
      routers: {
        src: '<%= tmpDir %>/js/config/router.js',
        dest: '<%= tmpDir %>/js/config/router.js'
      },
      controllers: {
        src: '<%= tmpDir %>/js/controllers.js',
        dest: '<%= tmpDir %>/js/controllers.js'
      },
      directives: {
        src: '<%= tmpDir %>/js/directives.js',
        dest: '<%= tmpDir %>/js/directives.js'
      },
      modules: {
        src: '<%= tmpDir %>/js/modules.js',
        dest: '<%= tmpDir %>/js/modules.js'
      },
      filters: {
        src: '<%= tmpDir %>/js/filters.js',
        dest: '<%= tmpDir %>/js/filters.js'
      },
      services: {
        src: '<%= tmpDir %>/js/services.js',
        dest: '<%= tmpDir %>/js/services.js'
      },
      vendor: {
        src: '<%= tmpDir %>/js/vendor.js',
        dest: '<%= tmpDir %>/js/vendor.js'
      }
    },

    // uglify js for production
    uglify: {
      production: {
        files: {
          '<%= appDir %>/js/application.js': [
            '<%= appDir %>/js/application.js'
          ]
        }
      },
    },

    // minify css for production
    cssmin: {
      production: {
        files: {
          '<%= appDir %>/css/app.css': [
            '<%= tmpDir %>/css/vendor.css',
            '<%= tmpDir %>/css/app.css'
          ],
        }
      }
    },

    // watch files, build on the fly for development
    watch: {
      root: {
        files: ['<%= srcDir %>/*'],
        tasks: ['copy:config']
      },
      scripts: {
        files: ['<%= srcDir %>/js/**','<%= srcDir %>/js/*'],
        tasks: [
          'clean:js', 'concat:angular', 'concat:vendor',
          'copy:development', 'copy:config', 'copy:vendor',
          'copy:tmp_to_build'
        ]
      },
      less: {
        files: [
          '<%= srcDir %>/css/*.less',
          '<%= srcDir %>/css/**/*.less'
        ],
        tasks: [
          'clean:css', 'concat:vendor', 'copy:vendor',
          'less:development'
        ]
      },
      img: {
        files: ['<%= srcDir %>/img/**'],
        tasks: ['clean:img', 'copy:img']
      },
      fonts: {
        files: ['<%= srcDir %>/font/**'],
        tasks: ['clean:fonts', 'copy:fonts']
      },
      partials: {
        files: ['<%= srcDir %>/html/partials/**'],
        tasks: ['clean:partials', 'copy:partials']
      },
      layouts: {
        files: ['<%= srcDir %>/html/layouts/**'],
        tasks: ['layouts:development']
      }
    },

    layouts: {
      options: {
        layout: '<%= srcDir %>/html/layouts/application.tmpl',
      },
      development: {
        options: {
          dest: '<%= appDir %>/index.html'
        },
        files: {
          css: '<%= assets.css.src %>',
          js: '<%= assets.js.src %>'
        }
      },
      production: {
        options: {
          dest: '<%= releaseDir %>/index.html'
        },
        files: {
          css: '<%= assets.css.src %>',
          js: '<%= assets.js.src %>'
        }
      }
    },

    config: {
      options: {
        template: '<%= srcDir %>/config.xml.tmpl',
        dest: '<%= appDir %>/config.xml'
      },
      enterprise: {},
      production: {},
      development: {}
    },

    // main build task (custom) with options
    // this task also builds out the main index.html
    // file based on templates, which are environment-aware
    build: {
      development: {},
      production: {},
      enterprise: {}
    }

  });

  // load grunt npm modules
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-ngmin');

  grunt.registerTask('dev', ['build:development', 'connect', 'watch']);

  // build HTML files based on target
  grunt.registerMultiTask('layouts', 'Builds an HTML file for angular.', function() {

    var opts = this.options()
      , target = this.target
      , css = this.files[0].src
      , js = this.files[1].src
      , layout = grunt.template.process(grunt.file.read(opts.layout), {
          data: { env: target, js: js, css: css, appName: _APP_NAME_ }
        });

    // generate main index.html file
    grunt.file.write(opts.dest, layout);
    grunt.log.write('Generating ' + opts.dest + '...').ok();

  });

  grunt.registerMultiTask('config', 'Builds the Cordova configuration file from template.', function() {

    var opts = this.options()
      , target = this.target
      , version = this.args[0] || '';

    var template = grunt.template.process(grunt.file.read(opts.template), {
          data: { target: target, appName: _APP_NAME_ }
        });

    // generate main index.html file
    grunt.file.write(opts.dest, template);
    grunt.log.write('Generating ' + opts.dest + '...').ok();

  });

  // task for building main index page based on environment
  grunt.registerMultiTask('build', 'Build the app based on environment.', function() {

    var opts = this.options()
      , target = this.target
      , env = target
      , args = this.args
      , version = args[0];

    if (target == 'enterprise') {
      env = 'production';
    }

    // clean up directories
    grunt.task.run('clean:' + env);

    // build all less files based on environment
    grunt.task.run('less:' + env);

    // concat angular files
    grunt.task.run('concat:angular');

    // use ngmin to pre-minify angular files
    grunt.task.run('ngmin');

    // concat vendor libs
    grunt.task.run('concat:vendor');

    // copy all files
    grunt.task.run('copy:' + env);
    grunt.task.run('copy:config');
    grunt.task.run('copy:partials');
    grunt.task.run('copy:img');
    grunt.task.run('copy:fonts');

    // copy tmp files to development
    if (target == 'development') {
      grunt.task.run('copy:vendor');
      grunt.task.run('copy:tmp_to_build');
    }

    if (target == 'production' || target == 'enterprise') {
      // concat all angular files into a single file
      grunt.task.run('concat:production');
      grunt.task.run('uglify:production');
      grunt.task.run('cssmin:production');
    }

    // build cordova config.xml file, uses target so we
    // can switch from production to enterprise for bundle ID
    grunt.task.run('config:' + target);

    // build main index.html file last
    grunt.task.run('layouts:' + env);

  });

};

<|endoftext|>


<commit_before>// APEX Gulp Stack
// - - - - - - - - - - - - - - -
// This file processes all of the assets in the "src" folder
// and outputs the finished files in the "dist" folder.

// 1. LIBRARIES
// - - - - - - - - - - - - - - -
var gulp = require('gulp'),
    plugins = require('gulp-load-plugins')(),
    del = require('del'),
    runSequence = require('run-sequence'),
    browserSync = require('browser-sync').create(),
    config = require('./config.json'),
    http = require('http'),
    https = require('https'),
    getLocalIp = require('node-localip');

// 2. SETTINGS VARIABLES
// - - - - - - - - - - - - - - -
var paths = {
        src: 'src/',
        dist: 'dist/',
        sourcemaps: './'
    },
    assets = {
        js: 'js/',
        css: 'css/',
        scss: 'scss/',
        img: 'img/',
        lib: 'lib/'
    },
    files = {
        js: '**/*.js',
        css: '**/*.css',
        scss: '**/*.scss',
        map: '**/*.map',
        all: '**/*.*',
    },
    sizeOptions = {
        showFiles: true
    },
    renameOptions = {
        suffix: '.min'
    },
    sourcemapsOptions = {
        loadMaps: true
    },
    sassOptions = {
        errLogToConsole: true,
        sourcemap: true
    };;

// 3. TASKS
// - - - - - - - - - - - - - - -
// Cleans the dist directory
gulp.task('clean-dist', function() {
    return del([paths.dist]);
});

// Compiles the JavaScript (error handling via plumber)
gulp.task('js', function() {
    return gulp.src(paths.src + assets.js + files.js)
        .pipe(plugins.plumber())
        .pipe(plugins.jshint())
        .pipe(plugins.jshint.reporter('jshint-stylish'))
        .pipe(plugins.sourcemaps.init())
        .pipe(plugins.concat('app.js'))
        .pipe(plugins.size(sizeOptions))
        .pipe(plugins.sourcemaps.write(paths.sourcemaps))
        .pipe(gulp.dest(paths.dist + assets.js))
        .pipe(plugins.uglify()).on('error', function(e) {})
        .pipe(plugins.rename(renameOptions))
        .pipe(plugins.size(sizeOptions))
        .pipe(gulp.dest(paths.dist + assets.js));
});

// Compiles the JavaScript with Browsersync
gulp.task('js-browsersync', ['js'], function() {
    browserSync.reload();
});

// Compiles scss, adds autoprefixer and sourcemaps
gulp.task('scss', function() {
    return gulp.src(paths.src + assets.scss + files.scss)
        .pipe(plugins.plumber())
        .pipe(plugins.sourcemaps.init(sourcemapsOptions))
        .pipe(plugins.sass(sassOptions))
        .pipe(plugins.autoprefixer())
        .pipe(plugins.size(sizeOptions))
        .pipe(plugins.sourcemaps.write(paths.sourcemaps))
        .pipe(gulp.dest(paths.src + assets.css));
});

// Minifies css, injects the browser's css if Browsersync is enabled
gulp.task('css', function() {
    // copy un-minified css and map file to dist folder
    gulp.src(paths.src + assets.css + files.all)
        .pipe(gulp.dest(paths.dist + assets.css));

    // minify css
    return gulp.src(paths.src + assets.css + files.css)
        .pipe(plugins.plumber())
        .pipe(plugins.minifyCss())
        .pipe(plugins.rename(renameOptions))
        .pipe(plugins.size(sizeOptions))
        .pipe(gulp.dest(paths.dist + assets.css))
        .pipe(plugins.if(config.enableBrowsersync, browserSync.stream({match: files.css})));
});

// Optimizes img files
gulp.task('img', function() {
    return gulp.src(paths.src + assets.img + files.all)
        .pipe(gulp.dest(paths.dist + assets.img));
});

// Copies lib files as is
gulp.task('lib', function() {
    return gulp.src(paths.src + assets.lib + files.all)
        .pipe(gulp.dest(paths.dist + assets.lib));
});

// Static server
gulp.task('browser-sync', function() {
    getLocalIp( function ( err, host ) {
        // build the proxy
        var proxy = (config.browsersync.apex.https ? "https://" : "http://") +
                    config.browsersync.apex.host +
                    config.browsersync.apex.path + "f?p=" +
                    config.browsersync.apex.appID;

        // launch browsersync
        browserSync.init({
            host: host,
            port: config.browsersync.port,
            notify: config.browsersync.notify,
            proxy: {
                target: proxy,
                middleware: function (req, res, next) {
                    res.setHeader('Access-Control-Allow-Origin', '*');
                    next();
                  }
            },
            serveStatic: ['.']
        });

        if (config.browsersync.rest.enabled) {
            /**
             * REST POST
             */
            // create a JSON object
            var jsonObject = JSON.stringify({});

            // build the proxy
            var browsersyncHost = (config.browsersync.apex.https ? "https://" : "http://") + host + ':' + config.browsersync.port + "/";

            // prepare the header
            var postheaders = {
                'Content-Type' : 'application/json',
                'Content-Length' : Buffer.byteLength(jsonObject, 'utf8'),
                'Browsersync-Host' : browsersyncHost
            };

            // the POST options
            var optionspost = {
                host : config.browsersync.apex.host,
                port : config.browsersync.rest.port,
                path : config.browsersync.apex.path +
                        config.browsersync.rest.schema +
                        '/browsersync/host',
                method : 'POST',
                headers : postheaders
            };

            // do the POST call
            var reqPost;

            if (config.browsersync.apex.https) {
                reqPost = https.request(optionspost, function(res) {
                    // console.log("statusCode: ", res.statusCode);

                    res.on('data', function(d) {
                        console.info('POST result:\n');
                        process.stdout.write(d);
                        console.info('\n\nPOST completed');
                    });
                });
            } else {
                reqPost = http.request(optionspost, function(res) {
                    // console.log("statusCode: ", res.statusCode);

                    res.on('data', function(d) {
                        console.info('POST result:\n');
                        process.stdout.write(d);
                        console.info('\n\nPOST completed');
                    });
                });
            }

            // write the json data
            reqPost.write(jsonObject);
            reqPost.end();
            reqPost.on('error', function(e) {
                console.error(e);
            });
        }
    });
});

// Watch for changes and recompiles
gulp.task('watch', function() {
    // browsersync support
    var jsWatch = (config.enableBrowsersync ? ['js-browsersync'] : ['js']);

    // sass support
    if (config.enableSass) {
        gulp.watch(paths.src + assets.scss + files.scss, ['scss']);
    }

    gulp.watch(paths.src + assets.css + files.css, ['css']);
    gulp.watch(paths.src + assets.js + files.js, jsWatch);
    gulp.watch(paths.src + assets.img + files.all, ['img']);
    gulp.watch(paths.src + assets.lib + files.all, ['lib']);
});

// Default task: builds your app
gulp.task('default', function() {
    // default task order
    var tasks = ['js', 'img', 'lib'];

    // sass support
    if (config.enableSass) {
        tasks.unshift('scss');
    } else {
        tasks.unshift('css');
    }

    // browsersync support
    if (config.enableBrowsersync) {
        tasks.unshift('browser-sync');
    }

    // run tasks
    runSequence('clean-dist', 'watch', tasks, function() {
        console.log("Successfully built!");
    });
});
<commit_msg>Gulpfile refactoring and better SCSS handling<commit_after>// APEX Gulp Stack
// - - - - - - - - - - - - - - -
// This file processes all of the assets in the "src" folder
// and outputs the finished files in the "dist" folder.

// 1. LIBRARIES
// - - - - - - - - - - - - - - -
var gulp = require('gulp'),
    plugins = require('gulp-load-plugins')(),
    del = require('del'),
    runSequence = require('run-sequence'),
    browserSync = require('browser-sync').create(),
    config = require('./config.json'),
    http = require('http'),
    https = require('https'),
    getLocalIp = require('node-localip');

// 2. SETTINGS VARIABLES
// - - - - - - - - - - - - - - -
var paths = {
        src: 'src/',
        dist: 'dist/',
        sourcemaps: './'
    },
    assets = {
        js: 'js/',
        css: 'css/',
        scss: 'scss/',
        img: 'img/',
        lib: 'lib/'
    },
    files = {
        js: '**/*.js',
        css: '**/*.css',
        scss: '**/*.scss',
        map: '**/*.map',
        all: '**/*.*',
    },
    sizeOptions = {
        showFiles: true
    },
    renameOptions = {
        suffix: '.min'
    },
    sourcemapsOptions = {
        loadMaps: true
    },
    sassOptions = {
        errLogToConsole: true,
        sourcemap: true
    };;

// 3. TASKS
// - - - - - - - - - - - - - - -
// Cleans the dist directory
gulp.task('clean-dist', function() {
    return del([paths.dist]);
});

// Compiles the JavaScript (error handling via plumber)
gulp.task('js', function() {
    return gulp.src(paths.src + assets.js + files.js)
        .pipe(plugins.plumber())
        .pipe(plugins.jshint())
        .pipe(plugins.jshint.reporter('jshint-stylish'))
        .pipe(plugins.sourcemaps.init())
        .pipe(plugins.concat('app.js'))
        .pipe(plugins.size(sizeOptions))
        .pipe(plugins.sourcemaps.write(paths.sourcemaps))
        .pipe(gulp.dest(paths.dist + assets.js))
        .pipe(plugins.uglify()).on('error', function(e) {})
        .pipe(plugins.rename(renameOptions))
        .pipe(plugins.size(sizeOptions))
        .pipe(gulp.dest(paths.dist + assets.js));
});

// Compiles the JavaScript with Browsersync
gulp.task('js-browsersync', ['js'], function() {
    browserSync.reload();
});

// Compiles scss, adds autoprefixer and sourcemaps
gulp.task('scss', function() {
    return gulp.src(paths.src + assets.scss + files.scss)
        .pipe(plugins.plumber())
        .pipe(plugins.sourcemaps.init(sourcemapsOptions))
        .pipe(plugins.sass(sassOptions))
        .pipe(plugins.autoprefixer())
        .pipe(plugins.size(sizeOptions))
        .pipe(plugins.sourcemaps.write(paths.sourcemaps))
        .pipe(gulp.dest(paths.src + assets.css));
});

// Minifies css, injects the browser's css if Browsersync is enabled
gulp.task('css', function() {
    // copy un-minified css and map file to dist folder
    gulp.src(paths.src + assets.css + files.all)
        .pipe(gulp.dest(paths.dist + assets.css));

    // minify css
    return gulp.src(paths.src + assets.css + files.css)
        .pipe(plugins.plumber())
        .pipe(plugins.minifyCss())
        .pipe(plugins.rename(renameOptions))
        .pipe(plugins.size(sizeOptions))
        .pipe(gulp.dest(paths.dist + assets.css))
        .pipe(plugins.if(config.enableBrowsersync, browserSync.stream({match: files.css})));
});

// Sequentially run tasks 'scss' and 'css'
gulp.task('scss-css', function() {
    runSequence('scss', 'css', function() {});
});

// Copies img files as is
gulp.task('img', function() {
    return gulp.src(paths.src + assets.img + files.all)
        .pipe(gulp.dest(paths.dist + assets.img));
});

// Copies lib files as is
gulp.task('lib', function() {
    return gulp.src(paths.src + assets.lib + files.all)
        .pipe(gulp.dest(paths.dist + assets.lib));
});

// Static server
gulp.task('browser-sync', function() {
    getLocalIp( function ( err, host ) {
        // build the proxy
        var proxy = (config.browsersync.apex.https ? "https://" : "http://") +
                    config.browsersync.apex.host +
                    config.browsersync.apex.path + "f?p=" +
                    config.browsersync.apex.appID;

        // launch browsersync
        browserSync.init({
            host: host,
            port: config.browsersync.port,
            notify: config.browsersync.notify,
            proxy: {
                target: proxy,
                middleware: function (req, res, next) {
                    res.setHeader('Access-Control-Allow-Origin', '*');
                    next();
                  }
            },
            serveStatic: ['.']
        });

        if (config.browsersync.rest.enabled) {
            // build the proxy
            var browsersyncHost = (config.browsersync.apex.https ? "https://" : "http://") + host + ':' + config.browsersync.port + "/";

            // POST Body
            var postBody = JSON.stringify({});

            // POST Headers
            var postHeaders = {
                'Content-Type' : 'application/json',
                'Content-Length' : Buffer.byteLength(postBody, 'utf8'),
                'Browsersync-Host' : browsersyncHost
            };

            // POST Options
            var postOptions = {
                host : config.browsersync.apex.host,
                port : config.browsersync.rest.port,
                path : config.browsersync.apex.path +
                        config.browsersync.rest.schema +
                        '/browsersync/host',
                method : 'POST',
                headers : postHeaders
            };

            // do the POST call
            var restPOST;

            if (config.browsersync.apex.https) {
                restPOST = https.request(postOptions, function(res) {
                    res.on('data', function(d) {
                        console.log('POST result:');
                        console.log(d);
                    });
                });
            } else {
                restPOST = http.request(postOptions, function(res) {
                    res.on('data', function(d) {
                        console.log('POST result:');
                        console.log(d);
                    });
                });
            }

            // write the POST body
            restPOST.write(postBody);
            restPOST.end();
            restPOST.on('error', function(e) {
                console.error(e);
            });
        }
    });
});

// Watch for changes and recompiles
gulp.task('watch', function() {
    // browsersync support
    var jsWatch = (config.enableBrowsersync ? ['js-browsersync'] : ['js']);

    gulp.watch(paths.src + assets.js + files.js, jsWatch);

    // sass support
    if (config.enableSass) {
        gulp.watch(paths.src + assets.scss + files.scss, ['scss-css']);
    } else {
        gulp.watch(paths.src + assets.css + files.css, ['css']);
    }

    gulp.watch(paths.src + assets.img + files.all, ['img']);
    gulp.watch(paths.src + assets.lib + files.all, ['lib']);
});

// Default task: builds your app
gulp.task('default', function() {
    // default task order
    var tasks = ['js', 'img', 'lib'];

    // sass support
    if (config.enableSass) {
        tasks.unshift('scss-css');
    } else {
        tasks.unshift('css');
    }

    // browsersync support
    if (config.enableBrowsersync) {
        tasks.unshift('browser-sync');
    }

    // run tasks
    runSequence('clean-dist', 'watch', tasks, function() {
        console.log("Successfully built!");
    });
});
<|endoftext|>


<commit_before>'use strict';
var path = require('path');

// the actual "static" directory path, relative to this Gruntfile.
// should be updated as necessary, if this moves
var staticDir = 'static';

module.exports = function(grunt) {
    // Project configuration
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-filerev');
    grunt.loadNpmTasks('grunt-regex-replace');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-coveralls');

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

        // Compile the requirejs stuff into a single, uglified file.
        // the options below are taken verbatim from a standard build.js file
        // used for r.js (if we were doing this outside of a grunt build)
        requirejs: {
            compile: {
                options: {
                    baseUrl: "./static",
                    mainConfigFile: "static/narrative_paths.js",
                    findNestedDependencies: true,
                    optimize: "uglify2",
                    generateSourceMaps: true,
                    preserveLicenseComments: false,
                    name: "narrative_paths",
                    out: "static/dist/kbase-narrative-min.js"
                }
            }
        },

        // Put a 'revision' stamp on the output file. This attaches an 8-character
        // md5 hash to the end of the requirejs built file.
        filerev: {
            options: {
                algorithm: 'md5',
                length: 8
            },
            source: {
                files: [{
                    src: [
                        'static/dist/kbase-narrative-min.js', //kbase/js/kbase-narrative.min.js',
                    ],
                    dest: 'static/dist/' // 'static/kbase/js'
                }]
            }
        },

        // Once we have a revved file, this inserts that reference into page.html at
        // the right spot (near the top, the narrative_paths reference)
        'regex-replace': {
            dist: {
                src: ['page.html'],
                actions: [
                    {
                        name: 'requirejs-onefile',
                        search: 'narrative_paths',
                        replace: function(match) {
                            // do a little sneakiness here. we just did the filerev thing, so get that mapping
                            // and return that (minus the .js on the end)
                            var revvedFile = grunt.filerev.summary['static/dist/kbase-narrative-min.js'];
                            // starts with 'static/' and ends with '.js' so return all but the first 7 and last 3 characters
                            return revvedFile.substr(7, revvedFile.length - 10);
                        },
                        flags: ''
                    }
                ]
            }
        },

        // Testing with Karma!
        'karma': {
            unit: {
                configFile: 'test/unit/karma.conf.js',
                reporters: ['progress', 'coverage'],
                coverageReporter: {
                    dir: 'build/test-coverage/',
                    reporters: [
                        {
                            type: 'html', subdir: 'html'
                        }
                    ]
                }
            },
            dev: {
                // to do - add watch here
                configFile: 'test/unit/karma.conf.js',
                reporters: ['progress', 'coverage'],
                coverageReporter: {
                    dir: 'build/test-coverage/',
                    reporters: [
                        { type: 'html', subdir: 'html' },
                    ],
                },

                autoWatch: true,
                singleRun: false,

            }
        },

        // Run coveralls and send the info.
        'coveralls': {
            options: {
                force: true,
            },
            'ui-common': {
                src: 'build/test-coverage/lcov/**/*.info',
            },
        },

    });

    grunt.registerTask('build', [
        'requirejs',
        'filerev',
        'regex-replace'
    ]);

    grunt.registerTask('test', [
        'karma:unit',
    ]);

    // Does a single unit test run, then sends
    // the lcov results to coveralls. Intended for running
    // from travis-ci.
    grunt.registerTask('test-travis', [
        'karma:unit',
        'coveralls'
    ]);

    // Does an ongoing test run in a watching development
    // mode.
    grunt.registerTask('develop', [
        'karma:dev',
    ]);
};
<commit_msg>modify gruntfile for new minification<commit_after>'use strict';
var path = require('path');

// the actual "static" directory path, relative to this Gruntfile.
// should be updated as necessary, if this moves
var staticDir = 'static';

module.exports = function(grunt) {
    // Project configuration
    grunt.loadNpmTasks('grunt-contrib-requirejs');
    grunt.loadNpmTasks('grunt-filerev');
    grunt.loadNpmTasks('grunt-regex-replace');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-coveralls');

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

        // Compile the requirejs stuff into a single, uglified file.
        // the options below are taken verbatim from a standard build.js file
        // used for r.js (if we were doing this outside of a grunt build)
        requirejs: {
            compile: {
                options: {
                    appDir: 'kbase-extension',
                    dir: 'kbase-extension-built',
                    // baseUrl: "./static",
                    mainConfigFile: "static/narrative_paths.js",
                    findNestedDependencies: true,
                    optimize: "uglify2",
                    generateSourceMaps: true,
                    preserveLicenseComments: false,
                    name: "narrative_paths",
                    out: "static/dist/kbase-narrative-min.js"
                }
            }
        },

        // Put a 'revision' stamp on the output file. This attaches an 8-character
        // md5 hash to the end of the requirejs built file.
        filerev: {
            options: {
                algorithm: 'md5',
                length: 8
            },
            source: {
                files: [{
                    src: [
                        'static/dist/kbase-narrative-min.js', //kbase/js/kbase-narrative.min.js',
                    ],
                    dest: 'static/dist/' // 'static/kbase/js'
                }]
            }
        },

        // Once we have a revved file, this inserts that reference into page.html at
        // the right spot (near the top, the narrative_paths reference)
        'regex-replace': {
            dist: {
                src: ['page.html'],
                actions: [
                    {
                        name: 'requirejs-onefile',
                        search: 'narrative_paths',
                        replace: function(match) {
                            // do a little sneakiness here. we just did the filerev thing, so get that mapping
                            // and return that (minus the .js on the end)
                            var revvedFile = grunt.filerev.summary['static/dist/kbase-narrative-min.js'];
                            // starts with 'static/' and ends with '.js' so return all but the first 7 and last 3 characters
                            return revvedFile.substr(7, revvedFile.length - 10);
                        },
                        flags: ''
                    }
                ]
            }
        },

        // Testing with Karma!
        'karma': {
            unit: {
                configFile: 'test/unit/karma.conf.js',
                reporters: ['progress', 'coverage'],
                coverageReporter: {
                    dir: 'build/test-coverage/',
                    reporters: [
                        {
                            type: 'html', subdir: 'html'
                        }
                    ]
                }
            },
            dev: {
                // to do - add watch here
                configFile: 'test/unit/karma.conf.js',
                reporters: ['progress', 'coverage'],
                coverageReporter: {
                    dir: 'build/test-coverage/',
                    reporters: [
                        { type: 'html', subdir: 'html' },
                    ],
                },

                autoWatch: true,
                singleRun: false,

            }
        },

        // Run coveralls and send the info.
        'coveralls': {
            options: {
                force: true,
            },
            'ui-common': {
                src: 'build/test-coverage/lcov/**/*.info',
            },
        },

    });

    grunt.registerTask('minify', [
        'requirejs'
    ]);

    grunt.registerTask('build', [
        'requirejs',
        'filerev',
        'regex-replace'
    ]);

    grunt.registerTask('test', [
        'karma:unit',
    ]);

    // Does a single unit test run, then sends
    // the lcov results to coveralls. Intended for running
    // from travis-ci.
    grunt.registerTask('test-travis', [
        'karma:unit',
        'coveralls'
    ]);

    // Does an ongoing test run in a watching development
    // mode.
    grunt.registerTask('develop', [
        'karma:dev',
    ]);
};
<|endoftext|>


<commit_before>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
 * http://scratchdisk.com/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

 /**
  * @name Component
  * @class
  */
var Component = Base.extend(Callback, /** @lends Component# */{
    _class: 'Component',
    _events: [ 'onChange', 'onClick' ],

    // DOCS: All!

    // Meta-information, by type. This is stored in _meta on the components.
    _types: {
        'boolean': {
            type: 'checkbox',
            value: 'checked'
        },

        string: {
            type: 'text'
        },

        number: {
            type: 'number',
            number: true
        },

        button: {
            type: 'button'
        },

        text: {
            tag: 'div',
            // This will return the native textContent through DomElement.get():
            value: 'text'
        },

        slider: {
            type: 'range',
            number: true
        },

        list: {
            tag: 'select',

            setOptions: function() {
                DomElement.removeChildren(this._input);
                DomElement.create(Base.each(this._options, function(option) {
                    this.push('option', { value: option, text: option });
                }, []), this._input);
            }
        },

        color: {
            type: 'color',

            getValue: function(value) {
                // Always convert internal string representation back to a
                // paper.js color object.
                return new Color(value);
            },

            setValue: function(value) {
                // Only enfore hex values if the input field is indeed of
                // color type. This allows sketch.paperjs.org to plug in
                // the Spectrum.js library with alpha support.
                return new Color(value).toCSS(
                        DomElement.get(this._input, 'type') === 'color');
            }
        },

        row: {},
        pane: {}
    },

    // Default values for internals
    _visible: true,
    _enabled: true,

    initialize: function Component(pane, name, props, values, row, parent) {
        if (!name)
            name = 'component-' + this._id;
        var value = Base.pick(values[name], props.value);
        this._id = Component._id = (Component._id || 0) + 1;
        this._pane = pane;
        this._name = name;
        this._row = row;
        this._parent = parent; // The parent component, if any.
        this._nested = !!parent;
        if (!parent || parent._type !== 'row')
            DomElement.set(row, 'id', 'palettejs-row-' + name);
        var type = this._type = props.type in this._types
                ? props.type
                : 'options' in props
                    ? 'list'
                    : 'onClick' in props
                        ? 'button'
                        : typeof value,
            meta = this._meta = this._types[type] || { type: type },
            that = this,
            create = DomElement.create,
            element = null,
            isRow = type === 'row',
            isPane = type === 'pane';
        if (isRow || isPane) {
            var childPane = this._childPane = new Pane(props, values, this,
                    isRow && row);
            if (isRow) {
                pane._numCells = childPane._numCells;
            } else { // isPane
                element = childPane._table;
            }
        } else {
            element = this._input = create(meta.tag || 'input', {
                class: 'palettejs-input',
                id: 'palettejs-input-' + name,
                type: meta.type,
                events: {
                    change: function() {
                        that.setValue(DomElement.get(this,
                                meta.value || 'value'));
                    },
                    click: function() {
                        that.fire('click');
                    }
                }
            });
        }
        if (element) {
            DomElement.addChildren(row, [
                this._labelCell = create('td', {
                    class: 'palettejs-label',
                    id: 'palettejs-label-' + name
                }),
                this._cell = create('td', {
                    class: 'palettejs-component palettejs-type-' + type,
                    id: 'palettejs-component-' + name
                }, [ element ])
            ]);
            // We just added two cells to the row:
            pane._numCells += 2;
        }

        // Attach default 'change' even that delegates to palette
        this.attach('change', function(value) {
            if (!this._dontFire)
                pane.fire('change', this, this._name, value);
        });
        this._dontFire = true;
        // Now that everything is set up, copy over values fro, props.
        // NOTE: This triggers setters, which is why we set _dontFire = true,
        // and why we can only call this after everything else is set up (e.g.
        // setLabel() requires this._labelCell).
        // Exclude name because it's already set, and value since we want to set
        // it after range.
        this._set(props, { name: true, value: true });
        this.setValue(value);
        // Start firing change events after we have initialized.
        this._dontFire = false;
        //  Store link to component in the pane's components object.
        pane._components[name] = this;
        values[name] = this._defaultValue = this._value;
    },

    getType: function() {
        return this._type;
    },

    getName: function() {
        return this._name;
    },

    _setLabel: function(label, nodeName, parent) {
        if (parent) {
            this[nodeName] = DomElement.set(this[nodeName]
                    || parent.appendChild(DomElement.create('label',
                        { 'for': 'palettejs-input-' + this._name })),
                    'text', label);
        }
    },

    getLabel: function() {
        return this._label;
    },

    setLabel: function(label) {
        this._label = label;
        this._setLabel(label, '_labelNode', this._labelCell);
    },

    getSuffix: function() {
        return this._suffix;
    },

    setSuffix: function(suffix) {
        this._suffix = suffix;
        this._setLabel(suffix, '_suffixNode', this._cell);
    },

    getOptions: function() {
        return this._options;
    },

    setOptions: function(options) {
        this._options = options;
        var setOptions = this._meta.setOptions;
        if (setOptions)
            setOptions.call(this);
    },

    getValue: function() {
        var value = this._value,
            getValue = this._meta.getValue;
        return getValue ? getValue.call(this, value) : value;
    },

    setValue: function(value) {
        if (this._childPane)
            return;
        var meta = this._meta,
            key = meta.value || 'value',
            setValue = meta.setValue;
        if (setValue)
            value = setValue.call(this, value);
        DomElement.set(this._input, key, value);
        // Read back and convert from input again, to make sure we're in sync
        value = DomElement.get(this._input, key);
        if (meta.number)
            value = parseFloat(value, 10);
        if (this._value !== value) {
            this._value = value;
            if (!this._dontFire)
                this.fire('change', this.getValue());
        }
    },

    getVisible: function() {
        return this._visible;
    },

    setVisible: function(visible) {
        // NOTE: Only set the visibility of the whole row if this is a row item,
        // in which case this._input is not defined.
        DomElement.toggleClass(this._cell || this._row, 'hidden', !visible);
        DomElement.toggleClass(this._labelCell, 'hidden', !visible);
        this._visible = !!visible;
    },

    getEnabled: function() {
        return this._enabled;
    },

    setEnabled: function(enabled, _fromPalette) {
        if (_fromPalette) {
            // When called from Palette#setEnabled, we have to remember the
            // component's previous enabled state when disabling the palette,
            // so we can restore it when enabling the palette again.
            var prev = Base.pick(this._previousEnabled, this._enabled);
            this._previousEnabled = enabled ? undefined : prev; // clear
            enabled = enabled && prev;
        }
        if (this._input) {
            DomElement.set(this._input, 'disabled', !enabled);
        } else if (this._childPane) {
            this._childPane.setEnabled(enabled);
        }
        this._enabled = !!enabled;
    },

    getRange: function() {
        return [parseFloat(DomElement.get(this._input, 'min')),
                parseFloat(DomElement.get(this._input, 'max'))];
    },

    setRange: function(min, max) {
        var range = Array.isArray(min) ? min : [min, max];
        DomElement.set(this._input, { min: range[0], max: range[1] });
    },

    getMin: function() {
        return this.getRange()[0];
    },

    setMin: function(min) {
        this.setRange(min, this.getMax());
    },

    getMax: function() {
        return this.getRange()[1];
    },

    setMax: function(max) {
        this.setRange(this.getMin(), max);
    },

    getStep: function() {
        return parseFloat(DomElement.get(this._input, 'step'));
    },

    setStep: function(step) {
        DomElement.set(this._input, 'step', step);
    },

    reset: function() {
        if (this._childPane) {
            this._childPane.reset();
        } else {
            this.setValue(this._defaultValue);
        }
    }
});
<commit_msg>Expose child components.<commit_after>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
 * http://scratchdisk.com/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

 /**
  * @name Component
  * @class
  */
var Component = Base.extend(Callback, /** @lends Component# */{
    _class: 'Component',
    _events: [ 'onChange', 'onClick' ],

    // DOCS: All!

    // Meta-information, by type. This is stored in _meta on the components.
    _types: {
        'boolean': {
            type: 'checkbox',
            value: 'checked'
        },

        string: {
            type: 'text'
        },

        number: {
            type: 'number',
            number: true
        },

        button: {
            type: 'button'
        },

        text: {
            tag: 'div',
            // This will return the native textContent through DomElement.get():
            value: 'text'
        },

        slider: {
            type: 'range',
            number: true
        },

        list: {
            tag: 'select',

            setOptions: function() {
                DomElement.removeChildren(this._input);
                DomElement.create(Base.each(this._options, function(option) {
                    this.push('option', { value: option, text: option });
                }, []), this._input);
            }
        },

        color: {
            type: 'color',

            getValue: function(value) {
                // Always convert internal string representation back to a
                // paper.js color object.
                return new Color(value);
            },

            setValue: function(value) {
                // Only enfore hex values if the input field is indeed of
                // color type. This allows sketch.paperjs.org to plug in
                // the Spectrum.js library with alpha support.
                return new Color(value).toCSS(
                        DomElement.get(this._input, 'type') === 'color');
            }
        },

        row: {},
        pane: {}
    },

    // Default values for internals
    _visible: true,
    _enabled: true,

    initialize: function Component(pane, name, props, values, row, parent) {
        if (!name)
            name = 'component-' + this._id;
        var value = Base.pick(values[name], props.value);
        this._id = Component._id = (Component._id || 0) + 1;
        this._pane = pane;
        this._name = name;
        this._row = row;
        this._parent = parent; // The parent component, if any.
        this._nested = !!parent;
        if (!parent || parent._type !== 'row')
            DomElement.set(row, 'id', 'palettejs-row-' + name);
        var type = this._type = props.type in this._types
                ? props.type
                : 'options' in props
                    ? 'list'
                    : 'onClick' in props
                        ? 'button'
                        : typeof value,
            meta = this._meta = this._types[type] || { type: type },
            that = this,
            create = DomElement.create,
            element = null,
            isRow = type === 'row',
            isPane = type === 'pane';
        if (isRow || isPane) {
            var childPane = this._childPane = new Pane(props, values, this,
                    isRow && row);
            if (isRow) {
                pane._numCells = childPane._numCells;
            } else { // isPane
                element = childPane._table;
            }
            // Add child components directly to this component, so we can access
            // it through the same path as in the components object literal that
            // was passed.
            Base.set(this, childPane._components);
        } else {
            element = this._input = create(meta.tag || 'input', {
                class: 'palettejs-input',
                id: 'palettejs-input-' + name,
                type: meta.type,
                events: {
                    change: function() {
                        that.setValue(DomElement.get(this,
                                meta.value || 'value'));
                    },
                    click: function() {
                        that.fire('click');
                    }
                }
            });
        }
        if (element) {
            DomElement.addChildren(row, [
                this._labelCell = create('td', {
                    class: 'palettejs-label',
                    id: 'palettejs-label-' + name
                }),
                this._cell = create('td', {
                    class: 'palettejs-component palettejs-type-' + type,
                    id: 'palettejs-component-' + name
                }, [ element ])
            ]);
            // We just added two cells to the row:
            pane._numCells += 2;
        }

        // Attach default 'change' even that delegates to palette
        this.attach('change', function(value) {
            if (!this._dontFire)
                pane.fire('change', this, this._name, value);
        });
        this._dontFire = true;
        // Now that everything is set up, copy over values fro, props.
        // NOTE: This triggers setters, which is why we set _dontFire = true,
        // and why we can only call this after everything else is set up (e.g.
        // setLabel() requires this._labelCell).
        // Exclude name because it's already set, and value since we want to set
        // it after range.
        this._set(props, { name: true, value: true });
        this.setValue(value);
        // Start firing change events after we have initialized.
        this._dontFire = false;
        //  Store link to component in the pane's components object.
        pane._components[name] = this;
        values[name] = this._defaultValue = this._value;
    },

    getType: function() {
        return this._type;
    },

    getName: function() {
        return this._name;
    },

    _setLabel: function(label, nodeName, parent) {
        if (parent) {
            this[nodeName] = DomElement.set(this[nodeName]
                    || parent.appendChild(DomElement.create('label',
                        { 'for': 'palettejs-input-' + this._name })),
                    'text', label);
        }
    },

    getLabel: function() {
        return this._label;
    },

    setLabel: function(label) {
        this._label = label;
        this._setLabel(label, '_labelNode', this._labelCell);
    },

    getSuffix: function() {
        return this._suffix;
    },

    setSuffix: function(suffix) {
        this._suffix = suffix;
        this._setLabel(suffix, '_suffixNode', this._cell);
    },

    getOptions: function() {
        return this._options;
    },

    setOptions: function(options) {
        this._options = options;
        var setOptions = this._meta.setOptions;
        if (setOptions)
            setOptions.call(this);
    },

    getValue: function() {
        var value = this._value,
            getValue = this._meta.getValue;
        return getValue ? getValue.call(this, value) : value;
    },

    setValue: function(value) {
        if (this._childPane)
            return;
        var meta = this._meta,
            key = meta.value || 'value',
            setValue = meta.setValue;
        if (setValue)
            value = setValue.call(this, value);
        DomElement.set(this._input, key, value);
        // Read back and convert from input again, to make sure we're in sync
        value = DomElement.get(this._input, key);
        if (meta.number)
            value = parseFloat(value, 10);
        if (this._value !== value) {
            this._value = value;
            if (!this._dontFire)
                this.fire('change', this.getValue());
        }
    },

    getVisible: function() {
        return this._visible;
    },

    setVisible: function(visible) {
        // NOTE: Only set the visibility of the whole row if this is a row item,
        // in which case this._input is not defined.
        DomElement.toggleClass(this._cell || this._row, 'hidden', !visible);
        DomElement.toggleClass(this._labelCell, 'hidden', !visible);
        this._visible = !!visible;
    },

    getEnabled: function() {
        return this._enabled;
    },

    setEnabled: function(enabled, _fromPalette) {
        if (_fromPalette) {
            // When called from Palette#setEnabled, we have to remember the
            // component's previous enabled state when disabling the palette,
            // so we can restore it when enabling the palette again.
            var prev = Base.pick(this._previousEnabled, this._enabled);
            this._previousEnabled = enabled ? undefined : prev; // clear
            enabled = enabled && prev;
        }
        if (this._input) {
            DomElement.set(this._input, 'disabled', !enabled);
        } else if (this._childPane) {
            this._childPane.setEnabled(enabled);
        }
        this._enabled = !!enabled;
    },

    getRange: function() {
        return [parseFloat(DomElement.get(this._input, 'min')),
                parseFloat(DomElement.get(this._input, 'max'))];
    },

    setRange: function(min, max) {
        var range = Array.isArray(min) ? min : [min, max];
        DomElement.set(this._input, { min: range[0], max: range[1] });
    },

    getMin: function() {
        return this.getRange()[0];
    },

    setMin: function(min) {
        this.setRange(min, this.getMax());
    },

    getMax: function() {
        return this.getRange()[1];
    },

    setMax: function(max) {
        this.setRange(this.getMin(), max);
    },

    getStep: function() {
        return parseFloat(DomElement.get(this._input, 'step'));
    },

    setStep: function(step) {
        DomElement.set(this._input, 'step', step);
    },

    reset: function() {
        if (this._childPane) {
            this._childPane.reset();
        } else {
            this.setValue(this._defaultValue);
        }
    }
});
<|endoftext|>