<commit_before>/**
 * @author alteredq / http://alteredqualia.com/
 */

THREE.ShadowMapPlugin = function () {

	var _gl,
	_renderer,
	_lights, _webglObjects, _webglObjectsImmediate,
	_depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,

	_frustum = new THREE.Frustum(),
	_projScreenMatrix = new THREE.Matrix4(),

	_min = new THREE.Vector3(),
	_max = new THREE.Vector3(),

	_matrixPosition = new THREE.Vector3(),

	_renderList = [];

	this.init = function ( renderer, lights, webglObjects, webglObjectsImmediate ) {

		_gl = renderer.context;
		_renderer = renderer;
		_lights = lights;

		_webglObjects = webglObjects;
		_webglObjectsImmediate = webglObjectsImmediate;

		var depthShader = THREE.ShaderLib[ "depthRGBA" ];
		var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );

		_depthMaterial = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader
		 } );

		_depthMaterialMorph = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader,
			morphTargets: true
		} );

		_depthMaterialSkin = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader,
			skinning: true
		} );

		_depthMaterialMorphSkin = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader,
			morphTargets: true,
			skinning: true
		} );

		_depthMaterial._shadowPass = true;
		_depthMaterialMorph._shadowPass = true;
		_depthMaterialSkin._shadowPass = true;
		_depthMaterialMorphSkin._shadowPass = true;

	};

	this.render = function ( scene, camera ) {

		if ( _renderer.shadowMapEnabled === false || _renderer.shadowMapAutoUpdate === false ) return;

		this.update( scene, camera );

	};

	this.update = function ( scene, camera ) {

		var i, il, j, jl, n,

		shadowMap, shadowMatrix, shadowCamera,
		program, buffer, material,
		webglObject, object, light,

		lights = [],
		k = 0,

		fog = null;

		// set GL state for depth map

		_gl.clearColor( 1, 1, 1, 1 );
		_gl.disable( _gl.BLEND );

		_gl.enable( _gl.CULL_FACE );
		_gl.frontFace( _gl.CCW );

		if ( _renderer.shadowMapCullFace === THREE.CullFaceFront ) {

			_gl.cullFace( _gl.FRONT );

		} else {

			_gl.cullFace( _gl.BACK );

		}

		_renderer.setDepthTest( true );

		// preprocess lights
		// 	- skip lights that are not casting shadows
		//	- create virtual lights for cascaded shadow maps

		for ( i = 0, il = _lights.length; i < il; i ++ ) {

			light = _lights[ i ];

			if ( ! light.castShadow ) continue;

			if ( ( light instanceof THREE.DirectionalLight ) && light.shadowCascade ) {

				for ( n = 0; n < light.shadowCascadeCount; n ++ ) {

					var virtualLight;

					if ( ! light.shadowCascadeArray[ n ] ) {

						virtualLight = createVirtualLight( light, n );
						virtualLight.originalCamera = camera;

						var gyro = new THREE.Gyroscope();
						gyro.position.copy( light.shadowCascadeOffset );

						gyro.add( virtualLight );
						gyro.add( virtualLight.target );

						camera.add( gyro );

						light.shadowCascadeArray[ n ] = virtualLight;

						console.log( "Created virtualLight", virtualLight );

					} else {

						virtualLight = light.shadowCascadeArray[ n ];

					}

					updateVirtualLight( light, n );

					lights[ k ] = virtualLight;
					k ++;

				}

			} else {

				lights[ k ] = light;
				k ++;

			}

		}

		// render depth map

		for ( i = 0, il = lights.length; i < il; i ++ ) {

			light = lights[ i ];

			if ( ! light.shadowMap ) {

				var shadowFilter = THREE.LinearFilter;

				if ( _renderer.shadowMapType === THREE.PCFSoftShadowMap ) {

					shadowFilter = THREE.NearestFilter;

				}

				var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };

				light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
				light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );

				light.shadowMatrix = new THREE.Matrix4();

			}

			if ( ! light.shadowCamera ) {

				if ( light instanceof THREE.SpotLight ) {

					light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );

				} else if ( light instanceof THREE.DirectionalLight ) {

					light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );

				} else {

					console.error( "Unsupported light type for shadow" );
					continue;

				}

				scene.add( light.shadowCamera );

				if ( scene.autoUpdate === true ) scene.updateMatrixWorld();

			}

			if ( light.shadowCameraVisible && ! light.cameraHelper ) {

				light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
				light.shadowCamera.add( light.cameraHelper );

			}

			if ( light.isVirtual && virtualLight.originalCamera == camera ) {

				updateShadowCamera( camera, light );

			}

			shadowMap = light.shadowMap;
			shadowMatrix = light.shadowMatrix;
			shadowCamera = light.shadowCamera;

			shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
			_matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
			shadowCamera.lookAt( _matrixPosition );
			shadowCamera.updateMatrixWorld();

			shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );

			if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
			if ( light.shadowCameraVisible ) light.cameraHelper.update();

			// compute shadow matrix

			shadowMatrix.set(
				0.5, 0.0, 0.0, 0.5,
				0.0, 0.5, 0.0, 0.5,
				0.0, 0.0, 0.5, 0.5,
				0.0, 0.0, 0.0, 1.0
			);

			shadowMatrix.multiply( shadowCamera.projectionMatrix );
			shadowMatrix.multiply( shadowCamera.matrixWorldInverse );

			// update camera matrices and frustum

			_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
			_frustum.setFromMatrix( _projScreenMatrix );

			// render shadow map

			_renderer.setRenderTarget( shadowMap );
			_renderer.clear();

			// set object matrices & frustum culling

			_renderList.length = 0;
			projectObject(scene,scene,shadowCamera);

			// render regular objects

			var objectMaterial, useMorphing, useSkinning;

			for ( j = 0, jl = _renderList.length; j < jl; j ++ ) {

				webglObject = _renderList[ j ];

				object = webglObject.object;
				buffer = webglObject.buffer;

				// culling is overriden globally for all objects
				// while rendering depth map

				// need to deal with MeshFaceMaterial somehow
				// in that case just use the first of material.materials for now
				// (proper solution would require to break objects by materials
				//  similarly to regular rendering and then set corresponding
				//  depth materials per each chunk instead of just once per object)

				objectMaterial = getObjectMaterial( object );

				useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
				useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;

				if ( object.customDepthMaterial ) {

					material = object.customDepthMaterial;

				} else if ( useSkinning ) {

					material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;

				} else if ( useMorphing ) {

					material = _depthMaterialMorph;

				} else {

					material = _depthMaterial;

				}

				_renderer.setMaterialFaces( objectMaterial );

				if ( buffer instanceof THREE.BufferGeometry ) {

					_renderer.renderBufferDirect( shadowCamera, _lights, fog, material, buffer, object );

				} else {

					_renderer.renderBuffer( shadowCamera, _lights, fog, material, buffer, object );

				}

			}

			// set matrices and render immediate objects

			for ( j = 0, jl = _webglObjectsImmediate.length; j < jl; j ++ ) {

				webglObject = _webglObjectsImmediate[ j ];
				object = webglObject.object;

				if ( object.visible && object.castShadow ) {

					object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );

					_renderer.renderImmediateObject( shadowCamera, _lights, fog, _depthMaterial, object );

				}

			}

		}

		// restore GL state

		var clearColor = _renderer.getClearColor(),
		clearAlpha = _renderer.getClearAlpha();

		_gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
		_gl.enable( _gl.BLEND );

		if ( _renderer.shadowMapCullFace === THREE.CullFaceFront ) {

			_gl.cullFace( _gl.BACK );

		}

		_renderer.resetGLState();

	};

	function projectObject(scene, object,shadowCamera){

		if ( object.visible ) {

			var webglObjects = _webglObjects[object.id];

			if (webglObjects && object.castShadow && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {

				for (var i = 0, l = webglObjects.length; i < l; i++){

					var webglObject = webglObjects[i];

					object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
					_renderList.push(webglObject);

				}
			}

			for(var i = 0, l = object.children.length; i < l; i++) {

				projectObject(scene, object.children[i],shadowCamera);
			}

		}
	}

	function createVirtualLight( light, cascade ) {

		var virtualLight = new THREE.DirectionalLight();

		virtualLight.isVirtual = true;

		virtualLight.onlyShadow = true;
		virtualLight.castShadow = true;

		virtualLight.shadowCameraNear = light.shadowCameraNear;
		virtualLight.shadowCameraFar = light.shadowCameraFar;

		virtualLight.shadowCameraLeft = light.shadowCameraLeft;
		virtualLight.shadowCameraRight = light.shadowCameraRight;
		virtualLight.shadowCameraBottom = light.shadowCameraBottom;
		virtualLight.shadowCameraTop = light.shadowCameraTop;

		virtualLight.shadowCameraVisible = light.shadowCameraVisible;

		virtualLight.shadowDarkness = light.shadowDarkness;

		virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
		virtualLight.shadowMapWidth = light.shadowCascadeWidth[ cascade ];
		virtualLight.shadowMapHeight = light.shadowCascadeHeight[ cascade ];

		virtualLight.pointsWorld = [];
		virtualLight.pointsFrustum = [];

		var pointsWorld = virtualLight.pointsWorld,
			pointsFrustum = virtualLight.pointsFrustum;

		for ( var i = 0; i < 8; i ++ ) {

			pointsWorld[ i ] = new THREE.Vector3();
			pointsFrustum[ i ] = new THREE.Vector3();

		}

		var nearZ = light.shadowCascadeNearZ[ cascade ];
		var farZ = light.shadowCascadeFarZ[ cascade ];

		pointsFrustum[ 0 ].set( - 1, - 1, nearZ );
		pointsFrustum[ 1 ].set(  1, - 1, nearZ );
		pointsFrustum[ 2 ].set( - 1,  1, nearZ );
		pointsFrustum[ 3 ].set(  1,  1, nearZ );

		pointsFrustum[ 4 ].set( - 1, - 1, farZ );
		pointsFrustum[ 5 ].set(  1, - 1, farZ );
		pointsFrustum[ 6 ].set( - 1,  1, farZ );
		pointsFrustum[ 7 ].set(  1,  1, farZ );

		return virtualLight;

	}

	// Synchronize virtual light with the original light

	function updateVirtualLight( light, cascade ) {

		var virtualLight = light.shadowCascadeArray[ cascade ];

		virtualLight.position.copy( light.position );
		virtualLight.target.position.copy( light.target.position );
		virtualLight.lookAt( virtualLight.target );

		virtualLight.shadowCameraVisible = light.shadowCameraVisible;
		virtualLight.shadowDarkness = light.shadowDarkness;

		virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];

		var nearZ = light.shadowCascadeNearZ[ cascade ];
		var farZ = light.shadowCascadeFarZ[ cascade ];

		var pointsFrustum = virtualLight.pointsFrustum;

		pointsFrustum[ 0 ].z = nearZ;
		pointsFrustum[ 1 ].z = nearZ;
		pointsFrustum[ 2 ].z = nearZ;
		pointsFrustum[ 3 ].z = nearZ;

		pointsFrustum[ 4 ].z = farZ;
		pointsFrustum[ 5 ].z = farZ;
		pointsFrustum[ 6 ].z = farZ;
		pointsFrustum[ 7 ].z = farZ;

	}

	// Fit shadow camera's ortho frustum to camera frustum

	function updateShadowCamera( camera, light ) {

		var shadowCamera = light.shadowCamera,
			pointsFrustum = light.pointsFrustum,
			pointsWorld = light.pointsWorld;

		_min.set( Infinity, Infinity, Infinity );
		_max.set( - Infinity, - Infinity, - Infinity );

		for ( var i = 0; i < 8; i ++ ) {

			var p = pointsWorld[ i ];

			p.copy( pointsFrustum[ i ] );
			p.unproject( camera );

			p.applyMatrix4( shadowCamera.matrixWorldInverse );

			if ( p.x < _min.x ) _min.x = p.x;
			if ( p.x > _max.x ) _max.x = p.x;

			if ( p.y < _min.y ) _min.y = p.y;
			if ( p.y > _max.y ) _max.y = p.y;

			if ( p.z < _min.z ) _min.z = p.z;
			if ( p.z > _max.z ) _max.z = p.z;

		}

		shadowCamera.left = _min.x;
		shadowCamera.right = _max.x;
		shadowCamera.top = _max.y;
		shadowCamera.bottom = _min.y;

		// can't really fit near/far
		//shadowCamera.near = _min.z;
		//shadowCamera.far = _max.z;

		shadowCamera.updateProjectionMatrix();

	}

	// For the moment just ignore objects that have multiple materials with different animation methods
	// Only the first material will be taken into account for deciding which depth material to use for shadow maps

	function getObjectMaterial( object ) {

		return object.material instanceof THREE.MeshFaceMaterial
			? object.material.materials[ 0 ]
			: object.material;

	};

};
<commit_msg>ShadowMapPlugin: Fixed shadowCamera. Fixes #5448.<commit_after>/**
 * @author alteredq / http://alteredqualia.com/
 */

THREE.ShadowMapPlugin = function () {

	var _gl,
	_renderer,
	_lights, _webglObjects, _webglObjectsImmediate,
	_depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,

	_frustum = new THREE.Frustum(),
	_projScreenMatrix = new THREE.Matrix4(),

	_min = new THREE.Vector3(),
	_max = new THREE.Vector3(),

	_matrixPosition = new THREE.Vector3(),

	_renderList = [];

	this.init = function ( renderer, lights, webglObjects, webglObjectsImmediate ) {

		_gl = renderer.context;
		_renderer = renderer;
		_lights = lights;

		_webglObjects = webglObjects;
		_webglObjectsImmediate = webglObjectsImmediate;

		var depthShader = THREE.ShaderLib[ "depthRGBA" ];
		var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );

		_depthMaterial = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader
		 } );

		_depthMaterialMorph = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader,
			morphTargets: true
		} );

		_depthMaterialSkin = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader,
			skinning: true
		} );

		_depthMaterialMorphSkin = new THREE.ShaderMaterial( {
			uniforms: depthUniforms,
			vertexShader: depthShader.vertexShader,
			fragmentShader: depthShader.fragmentShader,
			morphTargets: true,
			skinning: true
		} );

		_depthMaterial._shadowPass = true;
		_depthMaterialMorph._shadowPass = true;
		_depthMaterialSkin._shadowPass = true;
		_depthMaterialMorphSkin._shadowPass = true;

	};

	this.render = function ( scene, camera ) {

		if ( _renderer.shadowMapEnabled === false || _renderer.shadowMapAutoUpdate === false ) return;

		this.update( scene, camera );

	};

	this.update = function ( scene, camera ) {

		var i, il, j, jl, n,

		shadowMap, shadowMatrix, shadowCamera,
		program, buffer, material,
		webglObject, object, light,

		lights = [],
		k = 0,

		fog = null;

		// set GL state for depth map

		_gl.clearColor( 1, 1, 1, 1 );
		_gl.disable( _gl.BLEND );

		_gl.enable( _gl.CULL_FACE );
		_gl.frontFace( _gl.CCW );

		if ( _renderer.shadowMapCullFace === THREE.CullFaceFront ) {

			_gl.cullFace( _gl.FRONT );

		} else {

			_gl.cullFace( _gl.BACK );

		}

		_renderer.setDepthTest( true );

		// preprocess lights
		// 	- skip lights that are not casting shadows
		//	- create virtual lights for cascaded shadow maps

		for ( i = 0, il = _lights.length; i < il; i ++ ) {

			light = _lights[ i ];

			if ( ! light.castShadow ) continue;

			if ( ( light instanceof THREE.DirectionalLight ) && light.shadowCascade ) {

				for ( n = 0; n < light.shadowCascadeCount; n ++ ) {

					var virtualLight;

					if ( ! light.shadowCascadeArray[ n ] ) {

						virtualLight = createVirtualLight( light, n );
						virtualLight.originalCamera = camera;

						var gyro = new THREE.Gyroscope();
						gyro.position.copy( light.shadowCascadeOffset );

						gyro.add( virtualLight );
						gyro.add( virtualLight.target );

						camera.add( gyro );

						light.shadowCascadeArray[ n ] = virtualLight;

						console.log( "Created virtualLight", virtualLight );

					} else {

						virtualLight = light.shadowCascadeArray[ n ];

					}

					updateVirtualLight( light, n );

					lights[ k ] = virtualLight;
					k ++;

				}

			} else {

				lights[ k ] = light;
				k ++;

			}

		}

		// render depth map

		for ( i = 0, il = lights.length; i < il; i ++ ) {

			light = lights[ i ];

			if ( ! light.shadowMap ) {

				var shadowFilter = THREE.LinearFilter;

				if ( _renderer.shadowMapType === THREE.PCFSoftShadowMap ) {

					shadowFilter = THREE.NearestFilter;

				}

				var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };

				light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
				light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );

				light.shadowMatrix = new THREE.Matrix4();

			}

			if ( ! light.shadowCamera ) {

				if ( light instanceof THREE.SpotLight ) {

					light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );

				} else if ( light instanceof THREE.DirectionalLight ) {

					light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );

				} else {

					console.error( "Unsupported light type for shadow" );
					continue;

				}

				scene.add( light.shadowCamera );

				if ( scene.autoUpdate === true ) scene.updateMatrixWorld();

			}

			if ( light.shadowCameraVisible && ! light.cameraHelper ) {

				light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
				scene.add( light.cameraHelper );

			}

			if ( light.isVirtual && virtualLight.originalCamera == camera ) {

				updateShadowCamera( camera, light );

			}

			shadowMap = light.shadowMap;
			shadowMatrix = light.shadowMatrix;
			shadowCamera = light.shadowCamera;

			shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
			_matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
			shadowCamera.lookAt( _matrixPosition );
			shadowCamera.updateMatrixWorld();

			shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );

			if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
			if ( light.shadowCameraVisible ) light.cameraHelper.update();

			// compute shadow matrix

			shadowMatrix.set(
				0.5, 0.0, 0.0, 0.5,
				0.0, 0.5, 0.0, 0.5,
				0.0, 0.0, 0.5, 0.5,
				0.0, 0.0, 0.0, 1.0
			);

			shadowMatrix.multiply( shadowCamera.projectionMatrix );
			shadowMatrix.multiply( shadowCamera.matrixWorldInverse );

			// update camera matrices and frustum

			_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
			_frustum.setFromMatrix( _projScreenMatrix );

			// render shadow map

			_renderer.setRenderTarget( shadowMap );
			_renderer.clear();

			// set object matrices & frustum culling

			_renderList.length = 0;
			projectObject(scene,scene,shadowCamera);

			// render regular objects

			var objectMaterial, useMorphing, useSkinning;

			for ( j = 0, jl = _renderList.length; j < jl; j ++ ) {

				webglObject = _renderList[ j ];

				object = webglObject.object;
				buffer = webglObject.buffer;

				// culling is overriden globally for all objects
				// while rendering depth map

				// need to deal with MeshFaceMaterial somehow
				// in that case just use the first of material.materials for now
				// (proper solution would require to break objects by materials
				//  similarly to regular rendering and then set corresponding
				//  depth materials per each chunk instead of just once per object)

				objectMaterial = getObjectMaterial( object );

				useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
				useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;

				if ( object.customDepthMaterial ) {

					material = object.customDepthMaterial;

				} else if ( useSkinning ) {

					material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;

				} else if ( useMorphing ) {

					material = _depthMaterialMorph;

				} else {

					material = _depthMaterial;

				}

				_renderer.setMaterialFaces( objectMaterial );

				if ( buffer instanceof THREE.BufferGeometry ) {

					_renderer.renderBufferDirect( shadowCamera, _lights, fog, material, buffer, object );

				} else {

					_renderer.renderBuffer( shadowCamera, _lights, fog, material, buffer, object );

				}

			}

			// set matrices and render immediate objects

			for ( j = 0, jl = _webglObjectsImmediate.length; j < jl; j ++ ) {

				webglObject = _webglObjectsImmediate[ j ];
				object = webglObject.object;

				if ( object.visible && object.castShadow ) {

					object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );

					_renderer.renderImmediateObject( shadowCamera, _lights, fog, _depthMaterial, object );

				}

			}

		}

		// restore GL state

		var clearColor = _renderer.getClearColor(),
		clearAlpha = _renderer.getClearAlpha();

		_gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
		_gl.enable( _gl.BLEND );

		if ( _renderer.shadowMapCullFace === THREE.CullFaceFront ) {

			_gl.cullFace( _gl.BACK );

		}

		_renderer.resetGLState();

	};

	function projectObject(scene, object,shadowCamera){

		if ( object.visible ) {

			var webglObjects = _webglObjects[object.id];

			if (webglObjects && object.castShadow && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {

				for (var i = 0, l = webglObjects.length; i < l; i++){

					var webglObject = webglObjects[i];

					object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
					_renderList.push(webglObject);

				}
			}

			for(var i = 0, l = object.children.length; i < l; i++) {

				projectObject(scene, object.children[i],shadowCamera);
			}

		}
	}

	function createVirtualLight( light, cascade ) {

		var virtualLight = new THREE.DirectionalLight();

		virtualLight.isVirtual = true;

		virtualLight.onlyShadow = true;
		virtualLight.castShadow = true;

		virtualLight.shadowCameraNear = light.shadowCameraNear;
		virtualLight.shadowCameraFar = light.shadowCameraFar;

		virtualLight.shadowCameraLeft = light.shadowCameraLeft;
		virtualLight.shadowCameraRight = light.shadowCameraRight;
		virtualLight.shadowCameraBottom = light.shadowCameraBottom;
		virtualLight.shadowCameraTop = light.shadowCameraTop;

		virtualLight.shadowCameraVisible = light.shadowCameraVisible;

		virtualLight.shadowDarkness = light.shadowDarkness;

		virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
		virtualLight.shadowMapWidth = light.shadowCascadeWidth[ cascade ];
		virtualLight.shadowMapHeight = light.shadowCascadeHeight[ cascade ];

		virtualLight.pointsWorld = [];
		virtualLight.pointsFrustum = [];

		var pointsWorld = virtualLight.pointsWorld,
			pointsFrustum = virtualLight.pointsFrustum;

		for ( var i = 0; i < 8; i ++ ) {

			pointsWorld[ i ] = new THREE.Vector3();
			pointsFrustum[ i ] = new THREE.Vector3();

		}

		var nearZ = light.shadowCascadeNearZ[ cascade ];
		var farZ = light.shadowCascadeFarZ[ cascade ];

		pointsFrustum[ 0 ].set( - 1, - 1, nearZ );
		pointsFrustum[ 1 ].set(  1, - 1, nearZ );
		pointsFrustum[ 2 ].set( - 1,  1, nearZ );
		pointsFrustum[ 3 ].set(  1,  1, nearZ );

		pointsFrustum[ 4 ].set( - 1, - 1, farZ );
		pointsFrustum[ 5 ].set(  1, - 1, farZ );
		pointsFrustum[ 6 ].set( - 1,  1, farZ );
		pointsFrustum[ 7 ].set(  1,  1, farZ );

		return virtualLight;

	}

	// Synchronize virtual light with the original light

	function updateVirtualLight( light, cascade ) {

		var virtualLight = light.shadowCascadeArray[ cascade ];

		virtualLight.position.copy( light.position );
		virtualLight.target.position.copy( light.target.position );
		virtualLight.lookAt( virtualLight.target );

		virtualLight.shadowCameraVisible = light.shadowCameraVisible;
		virtualLight.shadowDarkness = light.shadowDarkness;

		virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];

		var nearZ = light.shadowCascadeNearZ[ cascade ];
		var farZ = light.shadowCascadeFarZ[ cascade ];

		var pointsFrustum = virtualLight.pointsFrustum;

		pointsFrustum[ 0 ].z = nearZ;
		pointsFrustum[ 1 ].z = nearZ;
		pointsFrustum[ 2 ].z = nearZ;
		pointsFrustum[ 3 ].z = nearZ;

		pointsFrustum[ 4 ].z = farZ;
		pointsFrustum[ 5 ].z = farZ;
		pointsFrustum[ 6 ].z = farZ;
		pointsFrustum[ 7 ].z = farZ;

	}

	// Fit shadow camera's ortho frustum to camera frustum

	function updateShadowCamera( camera, light ) {

		var shadowCamera = light.shadowCamera,
			pointsFrustum = light.pointsFrustum,
			pointsWorld = light.pointsWorld;

		_min.set( Infinity, Infinity, Infinity );
		_max.set( - Infinity, - Infinity, - Infinity );

		for ( var i = 0; i < 8; i ++ ) {

			var p = pointsWorld[ i ];

			p.copy( pointsFrustum[ i ] );
			p.unproject( camera );

			p.applyMatrix4( shadowCamera.matrixWorldInverse );

			if ( p.x < _min.x ) _min.x = p.x;
			if ( p.x > _max.x ) _max.x = p.x;

			if ( p.y < _min.y ) _min.y = p.y;
			if ( p.y > _max.y ) _max.y = p.y;

			if ( p.z < _min.z ) _min.z = p.z;
			if ( p.z > _max.z ) _max.z = p.z;

		}

		shadowCamera.left = _min.x;
		shadowCamera.right = _max.x;
		shadowCamera.top = _max.y;
		shadowCamera.bottom = _min.y;

		// can't really fit near/far
		//shadowCamera.near = _min.z;
		//shadowCamera.far = _max.z;

		shadowCamera.updateProjectionMatrix();

	}

	// For the moment just ignore objects that have multiple materials with different animation methods
	// Only the first material will be taken into account for deciding which depth material to use for shadow maps

	function getObjectMaterial( object ) {

		return object.material instanceof THREE.MeshFaceMaterial
			? object.material.materials[ 0 ]
			: object.material;

	};

};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.alarming',
  name: 'AlarmNotificationDAO',
  extends: 'foam.dao.ProxyDAO',

  documentation: `Generate Notification for WARN or ERROR Alarms.`,

  javaImports: [
    'foam.dao.DAO',
    'foam.log.LogLevel',
    'foam.nanos.notification.Notification'
  ],

  properties: [
    {
      name: 'group',
      class: 'Reference',
      of: 'foam.nanos.auth.Group',
      value: 'noc'
    }
  ],

  methods: [
    {
      name: 'put_',
      javaCode: `
      Alarm old = (Alarm) getDelegate().find_(x, ((Alarm)obj).getId());
      Alarm alarm = (Alarm) getDelegate().put_(x, obj);
<<<<<<< HEAD
      if ( ! alarm.getClusterable() ||
           ( old != null &&
=======
      if ( ( old != null &&
>>>>>>> b289cdffbd14202c9a76d14bce2cc86df1c4cac1
             old.getIsActive() == alarm.getIsActive() ) ||
           ( ( old == null ||
               old.getSeverity().getOrdinal() < LogLevel.WARN.getOrdinal() ) &&
               alarm.getSeverity().getOrdinal() < LogLevel.WARN.getOrdinal() ) ) {
        return alarm;
      }

      // create body for non-email notifications
      StringBuilder body = new StringBuilder();
      body.append("name: ");
      body.append(alarm.getName());
      body.append("\\nstatus: ");
      body.append(alarm.getIsActive() ? "Active": "Cleared");
      body.append("\\nseverity: ");
      body.append(alarm.getSeverity().getLabel());
      body.append("\\nhost: ");
      body.append(alarm.getHostname());
      body.append("\\nstarted: ");
      body.append(alarm.getCreated().toString());
      body.append("\\ncleared: ");
      if ( ! alarm.getIsActive() ) {
        body.append(alarm.getLastModified().toString());
      }
      body.append("\\ninfo: ");
      body.append(alarm.getNote());

      Notification notification = new Notification.Builder(x)
        .setGroupId(getGroup())
        .setSeverity(alarm.getSeverity())
        .setEmailName("alarm")
        .setEmailArgs(java.util.Map.of(
                         "alarm.name", alarm.getName(),
                         "alarm.status", alarm.getIsActive() ? "Active" : "Cleared",
                         "alarm.severity", alarm.getSeverity().getLabel(),
                         "alarm.host", alarm.getHostname(),
                         "alarm.started", alarm.getCreated().toString(), // TODO format
                         "alarm.cleared", alarm.getIsActive() ? "" : alarm.getLastModified().toString(),
                         "alarm.note", alarm.getNote()
                       ))
        .setBody(body.toString())
        .build();
     ((DAO) x.get("localNotificationDAO")).put(notification);
      return alarm;
      `
    }
  ]
});
<commit_msg>correct bad merge<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.alarming',
  name: 'AlarmNotificationDAO',
  extends: 'foam.dao.ProxyDAO',

  documentation: `Generate Notification for WARN or ERROR Alarms.`,

  javaImports: [
    'foam.dao.DAO',
    'foam.log.LogLevel',
    'foam.nanos.notification.Notification'
  ],

  properties: [
    {
      name: 'group',
      class: 'Reference',
      of: 'foam.nanos.auth.Group',
      value: 'noc'
    }
  ],

  methods: [
    {
      name: 'put_',
      javaCode: `
      Alarm old = (Alarm) getDelegate().find_(x, ((Alarm)obj).getId());
      Alarm alarm = (Alarm) getDelegate().put_(x, obj);
      if ( ! alarm.getClusterable() ||
           ( old != null &&
             old.getIsActive() == alarm.getIsActive() ) ||
           ( ( old == null ||
               old.getSeverity().getOrdinal() < LogLevel.WARN.getOrdinal() ) &&
               alarm.getSeverity().getOrdinal() < LogLevel.WARN.getOrdinal() ) ) {
        return alarm;
      }

      // create body for non-email notifications
      StringBuilder body = new StringBuilder();
      body.append("name: ");
      body.append(alarm.getName());
      body.append("\\nstatus: ");
      body.append(alarm.getIsActive() ? "Active": "Cleared");
      body.append("\\nseverity: ");
      body.append(alarm.getSeverity().getLabel());
      body.append("\\nhost: ");
      body.append(alarm.getHostname());
      body.append("\\nstarted: ");
      body.append(alarm.getCreated().toString());
      body.append("\\ncleared: ");
      if ( ! alarm.getIsActive() ) {
        body.append(alarm.getLastModified().toString());
      }
      body.append("\\ninfo: ");
      body.append(alarm.getNote());

      Notification notification = new Notification.Builder(x)
        .setGroupId(getGroup())
        .setSeverity(alarm.getSeverity())
        .setEmailName("alarm")
        .setEmailArgs(java.util.Map.of(
                         "alarm.name", alarm.getName(),
                         "alarm.status", alarm.getIsActive() ? "Active" : "Cleared",
                         "alarm.severity", alarm.getSeverity().getLabel(),
                         "alarm.host", alarm.getHostname(),
                         "alarm.started", alarm.getCreated().toString(), // TODO format
                         "alarm.cleared", alarm.getIsActive() ? "" : alarm.getLastModified().toString(),
                         "alarm.note", alarm.getNote()
                       ))
        .setBody(body.toString())
        .build();
     ((DAO) x.get("localNotificationDAO")).put(notification);
      return alarm;
      `
    }
  ]
});
<|endoftext|>


<commit_before>/* eslint no-magic-numbers: "off" */
'use strict'

module.exports = {
  rules: {
    'array-bracket-newline': ['error', 'consistent'],
    'array-bracket-spacing': ['error', 'never'],
    'array-element-newline': 'off',
    'block-spacing': ['error', 'always'],
    'brace-style': ['error', 'stroustrup', {allowSingleLine: false}],
    'camelcase': ['error', {properties: 'always'}],
    'capitalized-comments': 'off',
    'comma-dangle': ['error', 'never'],
    'comma-spacing': ['error', {after: true, before: false}],
    'comma-style': ['error', 'last'],
    'computed-property-spacing': ['error', 'never'],
    'consistent-this': ['error', 'self'],
    'eol-last': 'error',
    'func-call-spacing': ['error', 'never'],
    'func-name-matching': 'error',
    'func-names': 'off',
    'func-style': 'off',
    'function-paren-newline': ['error', 'consistent'],
    'id-blacklist': 'off',
    'id-length': [
      'error',
      {
        exceptions: ['_', 'h', 'i', 'm', 'P'],
        max: 35,
        min: 2,
        properties: 'always'
      }
    ],
    'id-match': 'off',
    'indent': ['error', 2, {SwitchCase: 1}],
    'jsx-quotes': ['error', 'prefer-double'],
    'key-spacing': ['error', {afterColon: true, beforeColon: false}],
    'keyword-spacing': 'error',
    'line-comment-position': 'off',
    'linebreak-style': ['error', 'unix'],
    'lines-around-comment': [
      'error',
      {
        afterBlockComment: false,
        afterLineComment: false,
        allowArrayEnd: false,
        allowArrayStart: true,
        allowBlockEnd: false,
        allowBlockStart: true,
        allowObjectEnd: false,
        allowObjectStart: true,
        beforeBlockComment: true,
        beforeLineComment: false
      }
    ],
    'lines-between-class-members': ['error', 'always'],
    'max-depth': ['error', 3],
    'max-len': ['error', {code: 80, ignoreUrls: true, tabWidth: 4}],
    'max-lines': ['error', 300],
    'max-nested-callbacks': ['error', 4],
    'max-params': ['error', 4],
    'max-statements': ['error', 15],
    'max-statements-per-line': ['error', {max: 1}],
    'multiline-comment-style': 'off',
    'multiline-ternary': 'off',
    'new-cap': ['error', {capIsNew: true, newIsCap: true}],
    'new-parens': 'error',
    'newline-per-chained-call': 'error',
    'no-array-constructor': 'error',
    'no-bitwise': 'error',
    'no-continue': 'error',
    'no-inline-comments': 'off',
    'no-lonely-if': 'error',
    'no-mixed-operators': 'error',
    'no-mixed-spaces-and-tabs': 'error',
    'no-multi-assign': 'error',
    'no-multiple-empty-lines': ['error', {max: 1, maxEOF: 1}],
    'no-negated-condition': 'error',
    'no-nested-ternary': 'error',
    'no-new-object': 'error',
    'no-plusplus': ['error', {allowForLoopAfterthoughts: true}],
    'no-restricted-syntax': ['error', 'WithStatement'],
    'no-tabs': 'error',
    'no-ternary': 'off',
    'no-trailing-spaces': 'error',
    'no-underscore-dangle': 'error',
    'no-unneeded-ternary': 'error',
    'no-whitespace-before-property': 'error',
    'nonblock-statement-body-position': 'off',
    'object-curly-newline': 'off',
    'object-curly-spacing': ['error', 'never'],
    'object-property-newline': ['error', {allowAllPropertiesOnSameLine: true}],
    'one-var': ['error', 'never'],
    'one-var-declaration-per-line': 'off',
    'operator-assignment': ['error', 'always'],
    'operator-linebreak': ['error', 'after'],
    'padded-blocks': ['error', 'never'],
    'padding-line-between-statements': 'off',
    'quote-props': ['error', 'consistent-as-needed', {keywords: true}],
    'quotes': ['error', 'single', 'avoid-escape'],
    'require-jsdoc': 'off',
    'semi': ['error', 'never'],
    'semi-spacing': ['error', {after: true, before: false}],
    'semi-style': ['error', 'last'],
    'sort-imports': ['error', {ignoreCase: false}],
    'sort-keys': 'off',
    'sort-vars': ['error', {ignoreCase: false}],
    'space-before-blocks': 'error',
    'space-before-function-paren': [
      'error',
      {
        anonymous: 'never',
        asyncArrow: 'always',
        named: 'never'
      }
    ],
    'space-in-parens': ['error', 'never'],
    'space-infix-ops': ['error', {int32Hint: false}],
    'space-unary-ops': ['error', {nonwords: false, words: true}],
    'spaced-comment': ['error', 'always', {exceptions: ['+', '-', '=']}],
    'switch-colon-spacing': 'error',
    'template-tag-spacing': 'error',
    'unicode-bom': 'error',
    'wrap-regex': 'error'
  }
}
<commit_msg>Allow short variable name "R" used by ramda<commit_after>/* eslint no-magic-numbers: "off" */
'use strict'

module.exports = {
  rules: {
    'array-bracket-newline': ['error', 'consistent'],
    'array-bracket-spacing': ['error', 'never'],
    'array-element-newline': 'off',
    'block-spacing': ['error', 'always'],
    'brace-style': ['error', 'stroustrup', {allowSingleLine: false}],
    'camelcase': ['error', {properties: 'always'}],
    'capitalized-comments': 'off',
    'comma-dangle': ['error', 'never'],
    'comma-spacing': ['error', {after: true, before: false}],
    'comma-style': ['error', 'last'],
    'computed-property-spacing': ['error', 'never'],
    'consistent-this': ['error', 'self'],
    'eol-last': 'error',
    'func-call-spacing': ['error', 'never'],
    'func-name-matching': 'error',
    'func-names': 'off',
    'func-style': 'off',
    'function-paren-newline': ['error', 'consistent'],
    'id-blacklist': 'off',
    'id-length': [
      'error',
      {
        exceptions: ['_', 'h', 'i', 'm', 'P', 'R'],
        max: 35,
        min: 2,
        properties: 'always'
      }
    ],
    'id-match': 'off',
    'indent': ['error', 2, {SwitchCase: 1}],
    'jsx-quotes': ['error', 'prefer-double'],
    'key-spacing': ['error', {afterColon: true, beforeColon: false}],
    'keyword-spacing': 'error',
    'line-comment-position': 'off',
    'linebreak-style': ['error', 'unix'],
    'lines-around-comment': [
      'error',
      {
        afterBlockComment: false,
        afterLineComment: false,
        allowArrayEnd: false,
        allowArrayStart: true,
        allowBlockEnd: false,
        allowBlockStart: true,
        allowObjectEnd: false,
        allowObjectStart: true,
        beforeBlockComment: true,
        beforeLineComment: false
      }
    ],
    'lines-between-class-members': ['error', 'always'],
    'max-depth': ['error', 3],
    'max-len': ['error', {code: 80, ignoreUrls: true, tabWidth: 4}],
    'max-lines': ['error', 300],
    'max-nested-callbacks': ['error', 4],
    'max-params': ['error', 4],
    'max-statements': ['error', 15],
    'max-statements-per-line': ['error', {max: 1}],
    'multiline-comment-style': 'off',
    'multiline-ternary': 'off',
    'new-cap': ['error', {capIsNew: true, newIsCap: true}],
    'new-parens': 'error',
    'newline-per-chained-call': 'error',
    'no-array-constructor': 'error',
    'no-bitwise': 'error',
    'no-continue': 'error',
    'no-inline-comments': 'off',
    'no-lonely-if': 'error',
    'no-mixed-operators': 'error',
    'no-mixed-spaces-and-tabs': 'error',
    'no-multi-assign': 'error',
    'no-multiple-empty-lines': ['error', {max: 1, maxEOF: 1}],
    'no-negated-condition': 'error',
    'no-nested-ternary': 'error',
    'no-new-object': 'error',
    'no-plusplus': ['error', {allowForLoopAfterthoughts: true}],
    'no-restricted-syntax': ['error', 'WithStatement'],
    'no-tabs': 'error',
    'no-ternary': 'off',
    'no-trailing-spaces': 'error',
    'no-underscore-dangle': 'error',
    'no-unneeded-ternary': 'error',
    'no-whitespace-before-property': 'error',
    'nonblock-statement-body-position': 'off',
    'object-curly-newline': 'off',
    'object-curly-spacing': ['error', 'never'],
    'object-property-newline': ['error', {allowAllPropertiesOnSameLine: true}],
    'one-var': ['error', 'never'],
    'one-var-declaration-per-line': 'off',
    'operator-assignment': ['error', 'always'],
    'operator-linebreak': ['error', 'after'],
    'padded-blocks': ['error', 'never'],
    'padding-line-between-statements': 'off',
    'quote-props': ['error', 'consistent-as-needed', {keywords: true}],
    'quotes': ['error', 'single', 'avoid-escape'],
    'require-jsdoc': 'off',
    'semi': ['error', 'never'],
    'semi-spacing': ['error', {after: true, before: false}],
    'semi-style': ['error', 'last'],
    'sort-imports': ['error', {ignoreCase: false}],
    'sort-keys': 'off',
    'sort-vars': ['error', {ignoreCase: false}],
    'space-before-blocks': 'error',
    'space-before-function-paren': [
      'error',
      {
        anonymous: 'never',
        asyncArrow: 'always',
        named: 'never'
      }
    ],
    'space-in-parens': ['error', 'never'],
    'space-infix-ops': ['error', {int32Hint: false}],
    'space-unary-ops': ['error', {nonwords: false, words: true}],
    'spaced-comment': ['error', 'always', {exceptions: ['+', '-', '=']}],
    'switch-colon-spacing': 'error',
    'template-tag-spacing': 'error',
    'unicode-bom': 'error',
    'wrap-regex': 'error'
  }
}
<|endoftext|>


<commit_before>/**
 * @(#)yobi.project.Home.js 2013.04.25
 *
 * Copyright NHN Corporation.
 * Released under the MIT license
 *
 * http://yobi.dev.naver.com/license
 */

(function(ns){

    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        function _init(htOptions){
            var htOpt = htOptions || {};
            _initVar(htOpt);
            _initElement(htOptions);
            _attachEvent();
            _initLabels();

//            _resizeProjectInfo();
        }

        function _initVar(htOptions){
            htVar.sURLProjectLabels = htOptions.sURLProjectLabels;
            htVar.sURLLabels = htOptions.sURLLabels;
            htVar.sURLLabelCategories = htOptions.sURLLabelCategories;
            htVar.nProjectId = htOptions.nProjectId;
            htVar.sRepoURL = htOptions.sRepoURL;
            htVar.sURLProject = htOptions.sURLProject;
        }

        /**
         * initialize element
         */
        function _initElement(htOptions) {
            var welBtnPlus = $('#plus-button-template').tmpl();

            htElement.welRepoURL = $("#repositoryURL");

            // clone url
            htElement.welBtnClone   = $('[data-toggle="cloneURL"]');

            htElement.welInputCloneURL =$('#cloneURL');
            htElement.welBtnCopy   = $('#cloneURLBtn');

            // project label
            htElement.welLabelBoard = htOptions.welLabelBoard;
            htElement.welLabelEditorToggle = htOptions.welLabelEditorToggle;

            htElement.welInputCategory = $('#label-input-template').tmpl();
            htElement.welSubmitCategory = $('#label-submit-template').tmpl();
            htElement.welInputCategory.attr('placeholder', Messages('label.addNewCategory'));
            htElement.welInputCategory.keypress(_onKeyPressNewCategory);
            htElement.welSubmitCategory.click(_onClickNewCategory);

            htElement.welInputLabel = $('#label-input-template').tmpl();
            htElement.welSubmitLabel = $('#label-submit-template').tmpl();
            htElement.welInputLabel.keypress(_onKeyPressNewLabel);
            htElement.welInputLabel.attr('placeholder', Messages('label.new'));
            htElement.welSubmitLabel.click(_submitLabel);

            htElement.welInputLabelBox = $('<p>')
                .append(htElement.welInputLabel)
                .append(htElement.welSubmitLabel);

            htElement.welInputCategoryBox = $('<p>')
                .append(htElement.welInputCategory)
                .append(htElement.welSubmitCategory);

            htElement.welBtnPlusLabel = welBtnPlus.clone();
            htElement.welBtnPlusCategory = welBtnPlus.clone();

            htElement.aLabel = [];
            htElement.htCategory = {};
            htElement.aBtnPlusLabel = [];

            htElement.welNewCategory = $('<li>')
                .append(htElement.welBtnPlusCategory);

            htElement.welLabelBoard.append(htElement.welNewCategory);

            /*
            htElement.welHome = $(".project-home");
            htElement.welHomeLogo = htElement.welHome.find(".logo");
            htElement.welHomeInfo = htElement.welHome.find(".project-info");
            htElement.welHomeMember = htElement.welHome.find(".member-info");
            */
        }

        /**
         * attach event handler
         */
        function _attachEvent(){
            htElement.welRepoURL.click(_onClickRepoURL);
            htElement.welLabelEditorToggle.on('click', function() {
                if ($(this).hasClass('active')) {
                    // Now inactive
                    $(this).removeClass('active');
                    $(this).text(Messages("button.edit"));
                    _hideLabelEditor();
                } else {
                    // Now active
                    $(this).addClass('active');
                    $(this).text(Messages("button.done"));
                    _showLabelEditor();
                }
            });

            new yobi.ui.Typeahead(htElement.welInputCategory, {
                "sActionURL": htVar.sURLLabelCategories,
                "htData": {
                    "project_id": htVar.nProjectId,
                    "limit": 8
                }
            });

            htElement.welBtnPlusCategory.click(_onClickPlusCategory);

            htElement.welBtnCopy.zclip({
                "path": "/assets/javascripts/lib/jquery/ZeroClipboard.swf",
                "copy": htElement.welInputCloneURL.val(),
                "afterCopy": function(){
                    yobi.Common.notify("Url copied", 1000);
                }
            });

            htElement.welInputCloneURL.on('click',function(){
                $(this).select();
            });

            $('.project-page-wrap')
                .on('click', '[data-toggle="description-edit"]', function(){
                    $('[data-toggle="project-description-tab"]').toggleClass('hidden');
                    $('.project-description-edit input').focus();
                }).on('click', '[data-toggle="description-cancel"]', function(){
                    $('[data-toggle="project-description-tab"]').toggleClass('hidden');
                });
            $('#descriptionSaveBtn').on('click',function(){
                var overview = {"overview" : $("#project-description-input").val() };
                $.ajax({
                    "url": htVar.sURLProject,
                    "method": "put",
                    "data": JSON.stringify(overview),
                    "contentType":"application/json"
                }).done(function(data){
                        $('[data-toggle="project-description-tab"]').toggleClass('hidden');
                        $("#project-description").text(data.overview);
                }).fail(function(err){
                        console.log("err>> ", err);
                });
            });
        }

        /*
        function _resizeProjectInfo(){
            htElement.welHomeInfo.width(htElement.welHome.width() - (htElement.welHomeLogo.width() + htElement.welHomeMember.width() + 21));
        }
        */

        function _onClickRepoURL(){
            htElement.welRepoURL.select();
        }

        /**
        * When any key is pressed on input box in any Category line.
        *
        * @param {Object} oEvent
        */
        function _onKeyPressNewLabel(oEvent) {
            if (oEvent.keyCode == 13) {
                _submitLabel();
                return false;
            }
        }

        /**
         * When any key is pressed on input box in New Category line.
         *
         * @param {Object} oEvent
         */
        function _onKeyPressNewCategory(oEvent) {
            if (oEvent.keyCode == 13) {
                _onClickNewCategory();
                return false;
            }
        }

        /**
         * Read data to create a label from input box.
         */
        function _labelFromInput() {
            return {
                "category": htElement.welInputLabel.data('category'),
                "name": htElement.welInputLabel.val()
            };
        }

        /**
        * Submit new tag to add that.
        */
        function _submitLabel() {
            var htLabel = _labelFromInput();

            if (htLabel == null) {
                return;
            }

            htElement.welInputLabel.val("");

            $yobi.sendForm({
                "sURL"   : htVar.sURLProjectLabels,
                "htData" : htLabel,
                "fOnLoad": _appendLabels
            });
        }

        var aRequired = ["Language", "License"];

        function isRequired(sCategory) {
            return aRequired.indexOf(sCategory) < 0;
        }

        /**
        * Get list of tags from the server and show them in #tags div.
        */
        function _initLabels() {
            $yobi.sendForm({
                "sURL"     : htVar.sURLProjectLabels,
                "htOptForm": {"method":"get"},
                "fOnLoad"  : function(data) {
                        _appendLabels(data);

                        for (var i = 0; i < aRequired.length; i++) {
                            var sCategory = aRequired[i];
                            if (!htElement.htCategory.hasOwnProperty(sCategory)) {
                                __addCategory(sCategory);
                            }
                        }

                        _hideLabelEditor();
                    }
            });
        }

        /**
        * Make a tag element by given instance id and name.)
        *
        * @param {String} sInstanceId
        * @param {String} sName
        */
        function _createLabel(sInstanceId, sName) {
            // If someone clicks a delete button, remove the tag which contains
            // the button, and also hide its category in .project-info div if
            // the category becomes to have no tag.
            var fOnLoadAfterDeleteLabel = function() {
                var welCategory = welLabel.parent().parent();
                var sCategory = welCategory.data('category');
                welLabel.remove();
                if (welCategory.children('.label-list').children().length == 0
                    && isRequired(sCategory)
                    && htElement.welInputLabel.data('category') != sCategory) {
                    delete htElement.htCategory[sCategory];
                    welCategory.remove();
                }
            };

            var fOnClickDelete = function() {
                $yobi.sendForm({
                    "sURL"   : htVar.sURLProjectLabels + '/' + sInstanceId,
                    "htData" : {"_method":"DELETE"},
                    "fOnLoad": fOnLoadAfterDeleteLabel
                });
            };

            var welDeleteButton = $('#label-delete-button-template')
                .tmpl()
                .click(fOnClickDelete);

            var welLabel = $('#label-template')
                .tmpl({'name': sName})
                .append(welDeleteButton);

            welLabel.setRemovability = function(bFlag) {
                if (bFlag === true) {
                    welLabel.addClass('label');
                    welDeleteButton.show();
                } else {
                    welLabel.removeClass('label');
                    welDeleteButton.hide();
                }
            }

            htElement.aLabel.push(welLabel);

            return welLabel;
        }

        /**
        * Append the given tags on #tags div to show them.
        *
        * @param {Object} htLabels
        */
        function _appendLabels(htLabels) {
            for(var sInstanceId in htLabels) {
                var waCategory, welCategory;
                var htLabel = htLabels[sInstanceId];

                waCategory = htElement.welLabelBoard
                    .children("[data-category=" + htLabel.category + "]");

                if (waCategory.length > 0) {
                    waCategory
                        .children(".label-list")
                        .append(_createLabel(sInstanceId, htLabel.name));
                } else {
                    __addCategory(htLabel.category)
                        .children(".label-list")
                        .append(_createLabel(sInstanceId, htLabel.name));
                }
            }
        }

        /**
         * Create a category consists with category name, labels belong
         * to this and plus button to add a label.
         *
         * @param {String} sCategory
         * @return {Object} The created category
         */
        function _createCategory(sCategory) {
            var welBtnPlusLabel = htElement.welBtnPlusLabel
                .clone()
                .data('category', sCategory)
                .click(_onClickPlusLabel);

            var welCategory = $('#category-template')
                .tmpl({'category': sCategory})
                .append(welBtnPlusLabel);

            welCategory.welBtnPlusLabel = welBtnPlusLabel;
            htElement.aBtnPlusLabel.push(welBtnPlusLabel);

            return welCategory;
        }

        function __addCategory(sCategory) {
            welCategory = _createCategory(sCategory);
            htElement.htCategory[sCategory] = welCategory;
            htElement.welNewCategory.before(welCategory);

            return welCategory;
        }

        /**
         * Add a category just before `htElement.welNewCategory`.
         */
        function _onClickNewCategory() {
            var sCategory = htElement.welInputCategory.val();
            var welCategory = htElement.htCategory[sCategory];

            if (!welCategory) {
                welCategory = __addCategory(sCategory);
            }

            htElement.welInputCategory.val("");
            welCategory.welBtnPlusLabel.trigger('click');
            if (!htElement.welInputCategory.is(":focus")) {
                htElement.welInputCategory.trigger('focus');
            }
        }

        /**
         * When a plus button in the end of the Label Board is clicked..
         */
        function _onClickPlusCategory() {
            htElement.welInputLabelBox.hide();
            htElement.welInputCategoryBox.show();
            $(this).before(htElement.welInputCategoryBox);
            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.show(); });
            htElement.welBtnPlusCategory.hide();

            if (!htElement.welInputCategory.is(":focus")) {
                htElement.welInputCategory.trigger('focus');
            }
        }

        /**
         * When a plus button in each category is clicked..
         */
        function _onClickPlusLabel() {
            var sCategory, welCategory, nLabel;

            for (sCategory in htElement.htCategory) {
                if ($(this).data('category') == sCategory) {
                    continue;
                }

                welCategory = htElement.htCategory[sCategory];

                nLabel = welCategory.children('.label-list').children().length;

                if (nLabel == 0 && isRequired(sCategory)) {
                    delete htElement.htCategory[sCategory];
                    welCategory.remove();
                }
            }

            htElement.welInputLabel.data('category', $(this).data('category'));

            new yobi.ui.Typeahead(htElement.welInputLabel, {
                "sActionURL": htVar.sURLLabels,
                "htData": {
                    "category":  $(this).data('category'),
                    "project_id": htVar.nProjectId,
                    "limit": 8
                }
            });

            htElement.welInputCategoryBox.hide();
            htElement.welInputLabelBox.show();
            $(this).after(htElement.welInputLabelBox);
            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.show(); });
            $(this).hide();

            if (!htElement.welInputLabel.is(":focus")) {
                htElement.welInputLabel.trigger('focus');
            }
        }

        /**
        * Show all delete buttons for all labels if bFlag is true, and hide if
        * bFlag is false.
        *
        * @param {Boolean} bFlag
        */
        function _setLabelsRemovability(bFlag) {
            jQuery.map(htElement.aLabel,
                    function(label) { label.setRemovability(bFlag); });
        }

        /**
        * Make .project-info div editable.
        *
        * @param {Boolean} bFlag
        */
        function _hideLabelEditor() {
            _setLabelsRemovability(false);

            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.hide(); });
            htElement.welBtnPlusCategory.hide();

            htElement.welInputCategoryBox.hide();
            htElement.welInputLabelBox.hide();

            htElement.welLabelBoard
                .css('height', htVar.nLabelBoardHeight);
            htElement.welLabelBoard.parent()
                .css('height', htVar.labelBoardParentHeight);
        }

        /**
        * Make .project-info div uneditable.
        *
        * @param {Boolean} bFlag
        */
        function _showLabelEditor() {
            _setLabelsRemovability(true);

            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.show(); });
            htElement.welBtnPlusCategory.show();

            htVar.nLabelBoardHeight =
                htElement.welLabelBoard.css('height');
            htVar.nLabelBoardParentHeight =
                htElement.welLabelBoard.parent().css('height');

            htElement.welLabelBoard.css('height', 'auto');
            htElement.welLabelBoard.parent().css('height', 'auto');
        }

        _init(htOptions || {});
    };

})("yobi.project.Home");
<commit_msg>ProjectHome: if remove project description then add default text that same placehoder<commit_after>/**
 * @(#)yobi.project.Home.js 2013.04.25
 *
 * Copyright NHN Corporation.
 * Released under the MIT license
 *
 * http://yobi.dev.naver.com/license
 */

(function(ns){

    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        function _init(htOptions){
            var htOpt = htOptions || {};
            _initVar(htOpt);
            _initElement(htOptions);
            _attachEvent();
            _initLabels();

//            _resizeProjectInfo();
        }

        function _initVar(htOptions){
            htVar.sURLProjectLabels = htOptions.sURLProjectLabels;
            htVar.sURLLabels = htOptions.sURLLabels;
            htVar.sURLLabelCategories = htOptions.sURLLabelCategories;
            htVar.nProjectId = htOptions.nProjectId;
            htVar.sRepoURL = htOptions.sRepoURL;
            htVar.sURLProject = htOptions.sURLProject;
        }

        /**
         * initialize element
         */
        function _initElement(htOptions) {
            var welBtnPlus = $('#plus-button-template').tmpl();

            htElement.welRepoURL = $("#repositoryURL");

            // clone url
            htElement.welBtnClone   = $('[data-toggle="cloneURL"]');

            htElement.welInputCloneURL =$('#cloneURL');
            htElement.welBtnCopy   = $('#cloneURLBtn');

            // project label
            htElement.welLabelBoard = htOptions.welLabelBoard;
            htElement.welLabelEditorToggle = htOptions.welLabelEditorToggle;

            htElement.welInputCategory = $('#label-input-template').tmpl();
            htElement.welSubmitCategory = $('#label-submit-template').tmpl();
            htElement.welInputCategory.attr('placeholder', Messages('label.addNewCategory'));
            htElement.welInputCategory.keypress(_onKeyPressNewCategory);
            htElement.welSubmitCategory.click(_onClickNewCategory);

            htElement.welInputLabel = $('#label-input-template').tmpl();
            htElement.welSubmitLabel = $('#label-submit-template').tmpl();
            htElement.welInputLabel.keypress(_onKeyPressNewLabel);
            htElement.welInputLabel.attr('placeholder', Messages('label.new'));
            htElement.welSubmitLabel.click(_submitLabel);

            htElement.welInputLabelBox = $('<p>')
                .append(htElement.welInputLabel)
                .append(htElement.welSubmitLabel);

            htElement.welInputCategoryBox = $('<p>')
                .append(htElement.welInputCategory)
                .append(htElement.welSubmitCategory);

            htElement.welBtnPlusLabel = welBtnPlus.clone();
            htElement.welBtnPlusCategory = welBtnPlus.clone();

            htElement.aLabel = [];
            htElement.htCategory = {};
            htElement.aBtnPlusLabel = [];

            htElement.welNewCategory = $('<li>')
                .append(htElement.welBtnPlusCategory);

            htElement.welLabelBoard.append(htElement.welNewCategory);

            /*
            htElement.welHome = $(".project-home");
            htElement.welHomeLogo = htElement.welHome.find(".logo");
            htElement.welHomeInfo = htElement.welHome.find(".project-info");
            htElement.welHomeMember = htElement.welHome.find(".member-info");
            */
        }

        /**
         * attach event handler
         */
        function _attachEvent(){
            htElement.welRepoURL.click(_onClickRepoURL);
            htElement.welLabelEditorToggle.on('click', function() {
                if ($(this).hasClass('active')) {
                    // Now inactive
                    $(this).removeClass('active');
                    $(this).text(Messages("button.edit"));
                    _hideLabelEditor();
                } else {
                    // Now active
                    $(this).addClass('active');
                    $(this).text(Messages("button.done"));
                    _showLabelEditor();
                }
            });

            new yobi.ui.Typeahead(htElement.welInputCategory, {
                "sActionURL": htVar.sURLLabelCategories,
                "htData": {
                    "project_id": htVar.nProjectId,
                    "limit": 8
                }
            });

            htElement.welBtnPlusCategory.click(_onClickPlusCategory);

            htElement.welBtnCopy.zclip({
                "path": "/assets/javascripts/lib/jquery/ZeroClipboard.swf",
                "copy": htElement.welInputCloneURL.val(),
                "afterCopy": function(){
                    yobi.Common.notify("Url copied", 1000);
                }
            });

            htElement.welInputCloneURL.on('click',function(){
                $(this).select();
            });

            $('.project-page-wrap')
                .on('click', '[data-toggle="description-edit"]', function(){
                    $('[data-toggle="project-description-tab"]').toggleClass('hidden');
                    $('.project-description-edit input').focus();
                }).on('click', '[data-toggle="description-cancel"]', function(){
                    $('[data-toggle="project-description-tab"]').toggleClass('hidden');
                });
            $('#descriptionSaveBtn').on('click',function(){
                var overview = {"overview" : $("#project-description-input").val() };
                $.ajax({
                    "url": htVar.sURLProject,
                    "method": "put",
                    "data": JSON.stringify(overview),
                    "contentType":"application/json"
                }).done(function(data){
                        var sDescription = (data.overview)
                                            ? data.overview
                                            : $("#project-description-input").attr('placeholder');

                        $('[data-toggle="project-description-tab"]').toggleClass('hidden');
                        $("#project-description").text(sDescription);
                }).fail(function(err){
                        console.log("err>> ", err);
                });
            });
        }

        /*
        function _resizeProjectInfo(){
            htElement.welHomeInfo.width(htElement.welHome.width() - (htElement.welHomeLogo.width() + htElement.welHomeMember.width() + 21));
        }
        */

        function _onClickRepoURL(){
            htElement.welRepoURL.select();
        }

        /**
        * When any key is pressed on input box in any Category line.
        *
        * @param {Object} oEvent
        */
        function _onKeyPressNewLabel(oEvent) {
            if (oEvent.keyCode == 13) {
                _submitLabel();
                return false;
            }
        }

        /**
         * When any key is pressed on input box in New Category line.
         *
         * @param {Object} oEvent
         */
        function _onKeyPressNewCategory(oEvent) {
            if (oEvent.keyCode == 13) {
                _onClickNewCategory();
                return false;
            }
        }

        /**
         * Read data to create a label from input box.
         */
        function _labelFromInput() {
            return {
                "category": htElement.welInputLabel.data('category'),
                "name": htElement.welInputLabel.val()
            };
        }

        /**
        * Submit new tag to add that.
        */
        function _submitLabel() {
            var htLabel = _labelFromInput();

            if (htLabel == null) {
                return;
            }

            htElement.welInputLabel.val("");

            $yobi.sendForm({
                "sURL"   : htVar.sURLProjectLabels,
                "htData" : htLabel,
                "fOnLoad": _appendLabels
            });
        }

        var aRequired = ["Language", "License"];

        function isRequired(sCategory) {
            return aRequired.indexOf(sCategory) < 0;
        }

        /**
        * Get list of tags from the server and show them in #tags div.
        */
        function _initLabels() {
            $yobi.sendForm({
                "sURL"     : htVar.sURLProjectLabels,
                "htOptForm": {"method":"get"},
                "fOnLoad"  : function(data) {
                        _appendLabels(data);

                        for (var i = 0; i < aRequired.length; i++) {
                            var sCategory = aRequired[i];
                            if (!htElement.htCategory.hasOwnProperty(sCategory)) {
                                __addCategory(sCategory);
                            }
                        }

                        _hideLabelEditor();
                    }
            });
        }

        /**
        * Make a tag element by given instance id and name.)
        *
        * @param {String} sInstanceId
        * @param {String} sName
        */
        function _createLabel(sInstanceId, sName) {
            // If someone clicks a delete button, remove the tag which contains
            // the button, and also hide its category in .project-info div if
            // the category becomes to have no tag.
            var fOnLoadAfterDeleteLabel = function() {
                var welCategory = welLabel.parent().parent();
                var sCategory = welCategory.data('category');
                welLabel.remove();
                if (welCategory.children('.label-list').children().length == 0
                    && isRequired(sCategory)
                    && htElement.welInputLabel.data('category') != sCategory) {
                    delete htElement.htCategory[sCategory];
                    welCategory.remove();
                }
            };

            var fOnClickDelete = function() {
                $yobi.sendForm({
                    "sURL"   : htVar.sURLProjectLabels + '/' + sInstanceId,
                    "htData" : {"_method":"DELETE"},
                    "fOnLoad": fOnLoadAfterDeleteLabel
                });
            };

            var welDeleteButton = $('#label-delete-button-template')
                .tmpl()
                .click(fOnClickDelete);

            var welLabel = $('#label-template')
                .tmpl({'name': sName})
                .append(welDeleteButton);

            welLabel.setRemovability = function(bFlag) {
                if (bFlag === true) {
                    welLabel.addClass('label');
                    welDeleteButton.show();
                } else {
                    welLabel.removeClass('label');
                    welDeleteButton.hide();
                }
            }

            htElement.aLabel.push(welLabel);

            return welLabel;
        }

        /**
        * Append the given tags on #tags div to show them.
        *
        * @param {Object} htLabels
        */
        function _appendLabels(htLabels) {
            for(var sInstanceId in htLabels) {
                var waCategory, welCategory;
                var htLabel = htLabels[sInstanceId];

                waCategory = htElement.welLabelBoard
                    .children("[data-category=" + htLabel.category + "]");

                if (waCategory.length > 0) {
                    waCategory
                        .children(".label-list")
                        .append(_createLabel(sInstanceId, htLabel.name));
                } else {
                    __addCategory(htLabel.category)
                        .children(".label-list")
                        .append(_createLabel(sInstanceId, htLabel.name));
                }
            }
        }

        /**
         * Create a category consists with category name, labels belong
         * to this and plus button to add a label.
         *
         * @param {String} sCategory
         * @return {Object} The created category
         */
        function _createCategory(sCategory) {
            var welBtnPlusLabel = htElement.welBtnPlusLabel
                .clone()
                .data('category', sCategory)
                .click(_onClickPlusLabel);

            var welCategory = $('#category-template')
                .tmpl({'category': sCategory})
                .append(welBtnPlusLabel);

            welCategory.welBtnPlusLabel = welBtnPlusLabel;
            htElement.aBtnPlusLabel.push(welBtnPlusLabel);

            return welCategory;
        }

        function __addCategory(sCategory) {
            welCategory = _createCategory(sCategory);
            htElement.htCategory[sCategory] = welCategory;
            htElement.welNewCategory.before(welCategory);

            return welCategory;
        }

        /**
         * Add a category just before `htElement.welNewCategory`.
         */
        function _onClickNewCategory() {
            var sCategory = htElement.welInputCategory.val();
            var welCategory = htElement.htCategory[sCategory];

            if (!welCategory) {
                welCategory = __addCategory(sCategory);
            }

            htElement.welInputCategory.val("");
            welCategory.welBtnPlusLabel.trigger('click');
            if (!htElement.welInputCategory.is(":focus")) {
                htElement.welInputCategory.trigger('focus');
            }
        }

        /**
         * When a plus button in the end of the Label Board is clicked..
         */
        function _onClickPlusCategory() {
            htElement.welInputLabelBox.hide();
            htElement.welInputCategoryBox.show();
            $(this).before(htElement.welInputCategoryBox);
            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.show(); });
            htElement.welBtnPlusCategory.hide();

            if (!htElement.welInputCategory.is(":focus")) {
                htElement.welInputCategory.trigger('focus');
            }
        }

        /**
         * When a plus button in each category is clicked..
         */
        function _onClickPlusLabel() {
            var sCategory, welCategory, nLabel;

            for (sCategory in htElement.htCategory) {
                if ($(this).data('category') == sCategory) {
                    continue;
                }

                welCategory = htElement.htCategory[sCategory];

                nLabel = welCategory.children('.label-list').children().length;

                if (nLabel == 0 && isRequired(sCategory)) {
                    delete htElement.htCategory[sCategory];
                    welCategory.remove();
                }
            }

            htElement.welInputLabel.data('category', $(this).data('category'));

            new yobi.ui.Typeahead(htElement.welInputLabel, {
                "sActionURL": htVar.sURLLabels,
                "htData": {
                    "category":  $(this).data('category'),
                    "project_id": htVar.nProjectId,
                    "limit": 8
                }
            });

            htElement.welInputCategoryBox.hide();
            htElement.welInputLabelBox.show();
            $(this).after(htElement.welInputLabelBox);
            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.show(); });
            $(this).hide();

            if (!htElement.welInputLabel.is(":focus")) {
                htElement.welInputLabel.trigger('focus');
            }
        }

        /**
        * Show all delete buttons for all labels if bFlag is true, and hide if
        * bFlag is false.
        *
        * @param {Boolean} bFlag
        */
        function _setLabelsRemovability(bFlag) {
            jQuery.map(htElement.aLabel,
                    function(label) { label.setRemovability(bFlag); });
        }

        /**
        * Make .project-info div editable.
        *
        * @param {Boolean} bFlag
        */
        function _hideLabelEditor() {
            _setLabelsRemovability(false);

            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.hide(); });
            htElement.welBtnPlusCategory.hide();

            htElement.welInputCategoryBox.hide();
            htElement.welInputLabelBox.hide();

            htElement.welLabelBoard
                .css('height', htVar.nLabelBoardHeight);
            htElement.welLabelBoard.parent()
                .css('height', htVar.labelBoardParentHeight);
        }

        /**
        * Make .project-info div uneditable.
        *
        * @param {Boolean} bFlag
        */
        function _showLabelEditor() {
            _setLabelsRemovability(true);

            jQuery.map(htElement.aBtnPlusLabel, function(btn) { btn.show(); });
            htElement.welBtnPlusCategory.show();

            htVar.nLabelBoardHeight =
                htElement.welLabelBoard.css('height');
            htVar.nLabelBoardParentHeight =
                htElement.welLabelBoard.parent().css('height');

            htElement.welLabelBoard.css('height', 'auto');
            htElement.welLabelBoard.parent().css('height', 'auto');
        }

        _init(htOptions || {});
    };

})("yobi.project.Home");
<|endoftext|>


<commit_before>var EntryCountController = Ember.ObjectController.extend({
  pagina: function() {
    var re = /\#\/(\d+)\//;
    var res = re.exec(window.location.href);
    return res[1];
  },
  counts: function() {
    var promisearray = this.store.find('entry_count', { pagina: this.pagina });
    return promisearray;
  }.property(),
  pending: function() {
    var pendings = [ 'Vacillating...', 'Ululating...', 'Oscillating...', 'Undulating...' ];
    return pendings[Math.floor(Math.random() * pendings.length)];
  }.property(),
  fulfilled: function() {
    console.log('am i fulfilled? ' + this.get('counts').get('isFulfilled'));
    var ecs = this.get('counts').map(function(ec) {
      return {id: ec.get('id'), entryCount: ec.get('entryCount'), hasChanged: ec.get('hasChanged')};
    });

    var re = /\#\/(\d+)\//;
    var res = re.exec(window.location.href);
    var pagina = parseInt(res[1]);
    var count = parseInt(ecs[0].entryCount);
    var pages = [];
    var lp = (count % 11 > 0) ? Math.floor(count / 11) + 1 : Math.floor(count / 11);
    if(pagina > 1) {
      pages.push("
«
");
    }
    for(var i = 1; i <= lp; i++) {
      var ec_html;
      ec_html = "
" + i + "
";
      pages.push(ec_html);
    }
    if(pagina < lp) {
      pages.push("
»
");
    }

    return pages.join('');
  }.property(),
  actions: {
  }
});

module.exports = EntryCountController;
<commit_msg>pagina does not work as a property of EntryCountController<commit_after>var EntryCountController = Ember.ObjectController.extend({
  counts: function() {
    var re = /\#\/(\d+)\//;
    var res = re.exec(window.location.href);
    var promisearray = this.store.find('entry_count', { pagina: res[1] });
    return promisearray;
  }.property(),
  pending: function() {
    var pendings = [ 'Vacillating...', 'Ululating...', 'Oscillating...', 'Undulating...' ];
    return pendings[Math.floor(Math.random() * pendings.length)];
  }.property(),
  fulfilled: function() {
    console.log('am i fulfilled? ' + this.get('counts').get('isFulfilled'));
    var ecs = this.get('counts').map(function(ec) {
      return {id: ec.get('id'), entryCount: ec.get('entryCount'), hasChanged: ec.get('hasChanged')};
    });

    var re = /\#\/(\d+)\//;
    var res = re.exec(window.location.href);
    var pagina = parseInt(res[1]);
    var count = parseInt(ecs[0].entryCount);
    var pages = [];
    var lp = (count % 11 > 0) ? Math.floor(count / 11) + 1 : Math.floor(count / 11);
    if(pagina > 1) {
      pages.push("
«
");
    }
    for(var i = 1; i <= lp; i++) {
      var ec_html;
      ec_html = "
" + i + "
";
      pages.push(ec_html);
    }
    if(pagina < lp) {
      pages.push("
»
");
    }

    return pages.join('');
  }.property(),
  actions: {
  }
});

module.exports = EntryCountController;
<|endoftext|>


<commit_before>app.controller('MailCtrl', ['$rootScope', '$scope', '$state', '$location', '$cookies', 'EmailSvc', 'UserSvc',
 function($rootScope, $scope, $state, $location, $cookies, EmailSvc, UserSvc){

  var cookie = $cookies.get('user');
  if (!cookie) {
    $location.path('/');
  } else {
    $rootScope.rootUser = JSON.parse(cookie);
  }

  if ($location.path() == '/mail') {
    $state.go('mail.inbox', {}, {reload: true});
  }

  $scope.highlight = function(path){
    return $location.path().indexOf(path) !== -1;
  };

  $scope.getUnread = function(){

    EmailSvc.unread($rootScope.rootUser.user_id)
      .success(function(data){
        $scope.unread = data.unread;
      })
      .error(function(data){
      });

  };

  if ($rootScope.rootUser){
    $scope.getUnread();
  }

  $rootScope.logout = function(){
    $cookies.remove('user');
    $rootScope.rootUser = null;
    $state.go('home', {}, {reload: true});
  };

  $scope.dispose = function() {
    swal({
      title: "Are you sure?",
      text: "This account and all it's contents will be permanently deleted",
      type: "warning",
      showCancelButton: true,
      confirmButtonColor: "#DD6B55",
      confirmButtonText: "Yes, dispose it!",
      closeOnConfirm: false
    },
    function(){
      UserSvc.dispose($rootScope.rootUser.user_id, $rootScope.rootUser.access_token)
        .success(function(data){
          swal("Deleted!", "Your account has been disposed.", "success");
          $location.path('/');
        })
        .error(function(){
          swal("Deleted!", "Your account has been disposed.", "success");
          $location.path('/');
        });
    });
  };

}]);<commit_msg>Update mail controller<commit_after>app.controller('MailCtrl', ['$rootScope', '$scope', '$state', '$location', '$cookies', 'EmailSvc', 'UserSvc', 'toastr',
 function($rootScope, $scope, $state, $location, $cookies, EmailSvc, UserSvc, toastr){

  var cookie = $cookies.get('user');
  if (!cookie) {
    $location.path('/');
  } else {
    $rootScope.rootUser = JSON.parse(cookie);
  }

  if ($location.path() == '/mail') {
    $state.go('mail.inbox', {}, {reload: true});
  }

  $scope.highlight = function(path){
    return $location.path().indexOf(path) !== -1;
  };

  $scope.getUnread = function(){
    $state.go('mail.inbox', {}, {reload: true});
  };

  if ($rootScope.rootUser){
    $scope.getUnread();
  }

  $rootScope.logout = function(){
    $cookies.remove('user');
    $rootScope.rootUser = null;
    $state.go('home', {}, {reload: true});
  };

  $scope.dispose = function() {
    swal({
      title: "Are you sure?",
      text: "This account and all it's contents will be permanently deleted",
      type: "warning",
      showCancelButton: true,
      confirmButtonColor: "#DD6B55",
      confirmButtonText: "Yes, dispose it!",
      closeOnConfirm: true
    },
    function(){
      UserSvc.dispose($rootScope.rootUser.user_id, $rootScope.rootUser.access_token)
        .success(function(data){
          toastr.success("Your account has been disposed.");
          $location.path('/');
        })
        .error(function(){
          toastr.success("Your account has been disposed.");
          $location.path('/');
        });
    });
  };

}]);<|endoftext|>


<commit_before>if (typeof(Alchemy) === 'undefined') {
	var Alchemy = {};
}

(function ($) {

	$.extend(Alchemy, {

		getOverlaySpinner : function (options) {
			var defaults = {
				x: '400',
				y: '300'
			};
			var settings = $.extend({}, defaults, options);
			var $spinner_container = $('
').css({width: settings.x, height: settings.y});
			var $spinner = $('');
			$spinner_container.append($spinner);
			$spinner.css({
				position: 'absolute',
				width: 32,
				height: 32,
				left: '50%',
				top: '50%',
				marginLeft: '-16px',
				marginTop: '-16px'
			});
			return $spinner_container;
		},

		AjaxErrorHandler : function($dialog, status, textStatus, errorThrown) {
			var $div = $('
');
			var $errorDiv = $('
');
			$dialog.html($div);
			$div.append($errorDiv);
			if (status === 0) {
				$errorDiv.append('
The server does not respond!
');
				$errorDiv.append('
Please start server and try again.
');
			} else {
				$errorDiv.append('
'+errorThrown+' ('+status+')
');
				$errorDiv.append('
Please check log and try again.
');
			}
		},

		ToolbarButton : function(options) {
			var $btn = $('

'), $lnk;
			if (options.buttonId) $btn.attr({'id': options.buttonId});
			$lnk = $('');
			$lnk.click(options.onClick);
			$lnk.append('');
			$btn.append($lnk);
			$btn.append('
'+options.buttonLabel+'');
			return $btn;
		},

		openConfirmWindow : function (options) {
			var $confirmation = $('

');
			$confirmation.appendTo('body');
			$confirmation.html('
'+options.message+'
');
			Alchemy.ConfirmationWindow = $confirmation.dialog({
				resizable: false,
				minHeight: 100,
				minWidth: 300,
				modal: true,
				title: options.title,
				show: "fade",
				hide: "fade",
				buttons: [
					{
						text: options.cancelLabel,
						click: function() {
							$(this).dialog("close");
						}
					},
					{
						text: options.okLabel,
						click: function() {
							$(this).dialog("close");
							options.okCallback();
						}
					}
				],
				open: function () {
					Alchemy.ButtonObserver('#alchemyConfirmation .button');
				},
				close: function() {
					$('#alchemyConfirmation').remove();
				}
			});
		},

		confirmToDeleteWindow : function (url, title, message, okLabel, cancelLabel) {
			var $confirmation = $('

');
			$confirmation.appendTo('body');
			$confirmation.html('
'+message+'
');
			Alchemy.ConfirmationWindow = $confirmation.dialog({
				resizable: false,
				minHeight: 100,
				minWidth: 300,
				modal: true,
				title: title,
				show: "fade",
				hide: "fade",
				buttons: [
					{
						text: cancelLabel,
						click: function() {
							$(this).dialog("close");
						}
					},
					{
						text: okLabel,
						click: function() {
							$(this).dialog("close");
							$.ajax({
								url: url,
								type: 'DELETE'
							});
						}
					}
				],
				open: function () {
					Alchemy.ButtonObserver('#alchemyConfirmation .button');
				},
				close: function() {
					$('#alchemyConfirmation').remove();
				}
			});
		},

		openWindow : function (action_url, title, size_x, size_y, resizable, modal, overflow) {
			overflow == undefined ? overflow = false: overflow = overflow;
			if (size_x === 'fullscreen') {
				size_x = $(window).width() - 50;
				size_y = $(window).height() - 50;
			}
			var $dialog = $('

');
			$dialog.appendTo('body');
			$dialog.html(Alchemy.getOverlaySpinner({x: size_x === 'auto' ? 400 : size_x, y: size_y === 'auto' ? 300 : size_y}));
			Alchemy.CurrentWindow = $dialog.dialog({
				modal: modal,
				minWidth: size_x === 'auto' ? 400 : size_x,
				minHeight: size_y === 'auto' ? 300 : size_y,
				title: title,
				resizable: resizable,
				show: "fade",
				hide: "fade",
				width: size_x,
				open: function (event, ui) {
					$.ajax({
						url: action_url,
						success: function(data, textStatus, XMLHttpRequest) {
							$dialog.html(data);
							$dialog.css({overflow: overflow ? 'visible' : 'auto'});
							$dialog.dialog('widget').css({overflow: overflow ? 'visible' : 'hidden'});
							if (size_x === 'auto') {
								$dialog.dialog('widget').css({
									left: (($(window).width() / 2) - ($dialog.width() / 2))
								});
							}
							if (size_y === 'auto') {
								$dialog.dialog('widget').css({
									top: ($(window).height() - $dialog.dialog('widget').height()) / 2
								});
							}
							Alchemy.SelectBox('#alchemyOverlay select.alchemy_selectbox');
							Alchemy.Datepicker('#alchemyOverlay input.date, #alchemyOverlay input[type="date"]');
							Alchemy.ButtonObserver('#alchemyOverlay .button');
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							Alchemy.AjaxErrorHandler($dialog, XMLHttpRequest.status, textStatus, errorThrown);
						},
						complete: function(jqXHR, textStatus) {
							Alchemy.enableButton('.button.disabled');
						}
					});
				},
				beforeClose: function() {
					$(".sb.open").triggerAll("close");
				},
				close: function () {
					$dialog.remove();
				}
			});
		},

		closeCurrentWindow : function() {
			if (Alchemy.CurrentWindow) {
				Alchemy.CurrentWindow.dialog('close');
				Alchemy.CurrentWindow = null;
			} else {
				$('#alchemyOverlay').dialog('close');
			}
			return true;
		},

		zoomImage : function(url, title, width, height) {
			var window_height = height;
			var window_width = width;
			var $doc_width = $(window).width();
			var $doc_height = $(window).height();
			if (width > $doc_width) {
				window_width = $doc_width - 50;
			}
			if (height > $doc_height) {
				window_height = $doc_height - 50;
			}
			var $dialog = $('

');
			$dialog.appendTo('body');
			$dialog.html(Alchemy.getOverlaySpinner({x: width, y: height}));
			$dialog.dialog({
				modal: false,
				minWidth: window_width < 320 ? 320 : window_width,
				minHeight: window_height < 240 ? 240 : window_height,
				title: title,
				show: "fade",
				hide: "fade",
				open: function (event, ui) {
					$.ajax({
						url: url,
						success: function(data, textStatus, XMLHttpRequest) {
							$dialog.html(data);
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							Alchemy.AjaxErrorHandler($dialog, XMLHttpRequest.status, textStatus, errorThrown);
						}
					});
				},
				close: function () {
					$dialog.remove();
				}
			});
			return false;
		},

		openTrashWindow : function (page_id, title) {
			var size_x = 380, size_y = 270;
			if (size_x === 'fullscreen') {
				size_x = $(window).width() - 50;
				size_y = $(window).height() - 50;
			}
			var $dialog = $('

');
			$dialog.appendTo('body');
			$dialog.html(Alchemy.getOverlaySpinner({x: size_x, y: size_y}));

			Alchemy.trashWindow = $dialog.dialog({
				modal: false,
				width: 380,
				minHeight: 450,
				maxHeight: $(window).height() - 50,
				title: title,
				resizable: false,
				show: "fade",
				hide: "fade",
				open: function (event, ui) {
					$.ajax({
						url: Alchemy.routes.admin_trash_path(page_id),
						success: function(data, textStatus, XMLHttpRequest) {
							$dialog.html(data);
							// Need this for DragnDrop elements into elements window.
							// Badly this is screwing up maxHeight option
							$dialog.css({overflow: 'visible'}).dialog('widget').css({overflow: 'visible'});
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							Alchemy.AjaxErrorHandler($dialog, XMLHttpRequest.status, textStatus, errorThrown);
						}
					});
				},
				close: function () {
					$dialog.remove();
				}
			});
		},

		refreshTrashWindow: function(page_id) {
			if ($('#alchemyTrashWindow').length > 0) {
				$('#alchemyTrashWindow').html(Alchemy.getOverlaySpinner({x: 380, y: 270}));
				$.get(Alchemy.routes.admin_trash_path(page_id), function(html) {
					$('#alchemyTrashWindow').html(html);
				});
			}
		}

	});
})(jQuery);
<commit_msg>fixing button enabling after window load<commit_after>if (typeof(Alchemy) === 'undefined') {
	var Alchemy = {};
}

(function ($) {

	$.extend(Alchemy, {

		getOverlaySpinner : function (options) {
			var defaults = {
				x: '400',
				y: '300'
			};
			var settings = $.extend({}, defaults, options);
			var $spinner_container = $('
').css({width: settings.x, height: settings.y});
			var $spinner = $('');
			$spinner_container.append($spinner);
			$spinner.css({
				position: 'absolute',
				width: 32,
				height: 32,
				left: '50%',
				top: '50%',
				marginLeft: '-16px',
				marginTop: '-16px'
			});
			return $spinner_container;
		},

		AjaxErrorHandler : function($dialog, status, textStatus, errorThrown) {
			var $div = $('
');
			var $errorDiv = $('
');
			$dialog.html($div);
			$div.append($errorDiv);
			if (status === 0) {
				$errorDiv.append('
The server does not respond!
');
				$errorDiv.append('
Please start server and try again.
');
			} else {
				$errorDiv.append('
'+errorThrown+' ('+status+')
');
				$errorDiv.append('
Please check log and try again.
');
			}
		},

		ToolbarButton : function(options) {
			var $btn = $('

'), $lnk;
			if (options.buttonId) $btn.attr({'id': options.buttonId});
			$lnk = $('');
			$lnk.click(options.onClick);
			$lnk.append('');
			$btn.append($lnk);
			$btn.append('
'+options.buttonLabel+'');
			return $btn;
		},

		openConfirmWindow : function (options) {
			var $confirmation = $('

');
			$confirmation.appendTo('body');
			$confirmation.html('
'+options.message+'
');
			Alchemy.ConfirmationWindow = $confirmation.dialog({
				resizable: false,
				minHeight: 100,
				minWidth: 300,
				modal: true,
				title: options.title,
				show: "fade",
				hide: "fade",
				buttons: [
					{
						text: options.cancelLabel,
						click: function() {
							$(this).dialog("close");
						}
					},
					{
						text: options.okLabel,
						click: function() {
							$(this).dialog("close");
							options.okCallback();
						}
					}
				],
				open: function () {
					Alchemy.ButtonObserver('#alchemyConfirmation .button');
				},
				close: function() {
					$('#alchemyConfirmation').remove();
				}
			});
		},

		confirmToDeleteWindow : function (url, title, message, okLabel, cancelLabel) {
			var $confirmation = $('

');
			$confirmation.appendTo('body');
			$confirmation.html('
'+message+'
');
			Alchemy.ConfirmationWindow = $confirmation.dialog({
				resizable: false,
				minHeight: 100,
				minWidth: 300,
				modal: true,
				title: title,
				show: "fade",
				hide: "fade",
				buttons: [
					{
						text: cancelLabel,
						click: function() {
							$(this).dialog("close");
						}
					},
					{
						text: okLabel,
						click: function() {
							$(this).dialog("close");
							$.ajax({
								url: url,
								type: 'DELETE'
							});
						}
					}
				],
				open: function () {
					Alchemy.ButtonObserver('#alchemyConfirmation .button');
				},
				close: function() {
					$('#alchemyConfirmation').remove();
				}
			});
		},

		openWindow : function (action_url, title, size_x, size_y, resizable, modal, overflow) {
			overflow == undefined ? overflow = false: overflow = overflow;
			if (size_x === 'fullscreen') {
				size_x = $(window).width() - 50;
				size_y = $(window).height() - 50;
			}
			var $dialog = $('

');
			$dialog.appendTo('body');
			$dialog.html(Alchemy.getOverlaySpinner({x: size_x === 'auto' ? 400 : size_x, y: size_y === 'auto' ? 300 : size_y}));
			Alchemy.CurrentWindow = $dialog.dialog({
				modal: modal,
				minWidth: size_x === 'auto' ? 400 : size_x,
				minHeight: size_y === 'auto' ? 300 : size_y,
				title: title,
				resizable: resizable,
				show: "fade",
				hide: "fade",
				width: size_x,
				open: function (event, ui) {
					$.ajax({
						url: action_url,
						success: function(data, textStatus, XMLHttpRequest) {
							$dialog.html(data);
							$dialog.css({overflow: overflow ? 'visible' : 'auto'});
							$dialog.dialog('widget').css({overflow: overflow ? 'visible' : 'hidden'});
							if (size_x === 'auto') {
								$dialog.dialog('widget').css({
									left: (($(window).width() / 2) - ($dialog.width() / 2))
								});
							}
							if (size_y === 'auto') {
								$dialog.dialog('widget').css({
									top: ($(window).height() - $dialog.dialog('widget').height()) / 2
								});
							}
							Alchemy.SelectBox('#alchemyOverlay select.alchemy_selectbox');
							Alchemy.Datepicker('#alchemyOverlay input.date, #alchemyOverlay input[type="date"]');
							Alchemy.ButtonObserver('#alchemyOverlay .button');
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							Alchemy.AjaxErrorHandler($dialog, XMLHttpRequest.status, textStatus, errorThrown);
						},
						complete: function(jqXHR, textStatus) {
							Alchemy.enableButton('.button');
						}
					});
				},
				beforeClose: function() {
					$(".sb.open").triggerAll("close");
				},
				close: function () {
					$dialog.remove();
				}
			});
		},

		closeCurrentWindow : function() {
			if (Alchemy.CurrentWindow) {
				Alchemy.CurrentWindow.dialog('close');
				Alchemy.CurrentWindow = null;
			} else {
				$('#alchemyOverlay').dialog('close');
			}
			return true;
		},

		zoomImage : function(url, title, width, height) {
			var window_height = height;
			var window_width = width;
			var $doc_width = $(window).width();
			var $doc_height = $(window).height();
			if (width > $doc_width) {
				window_width = $doc_width - 50;
			}
			if (height > $doc_height) {
				window_height = $doc_height - 50;
			}
			var $dialog = $('

');
			$dialog.appendTo('body');
			$dialog.html(Alchemy.getOverlaySpinner({x: width, y: height}));
			$dialog.dialog({
				modal: false,
				minWidth: window_width < 320 ? 320 : window_width,
				minHeight: window_height < 240 ? 240 : window_height,
				title: title,
				show: "fade",
				hide: "fade",
				open: function (event, ui) {
					$.ajax({
						url: url,
						success: function(data, textStatus, XMLHttpRequest) {
							$dialog.html(data);
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							Alchemy.AjaxErrorHandler($dialog, XMLHttpRequest.status, textStatus, errorThrown);
						}
					});
				},
				close: function () {
					$dialog.remove();
				}
			});
			return false;
		},

		openTrashWindow : function (page_id, title) {
			var size_x = 380, size_y = 270;
			if (size_x === 'fullscreen') {
				size_x = $(window).width() - 50;
				size_y = $(window).height() - 50;
			}
			var $dialog = $('

');
			$dialog.appendTo('body');
			$dialog.html(Alchemy.getOverlaySpinner({x: size_x, y: size_y}));

			Alchemy.trashWindow = $dialog.dialog({
				modal: false,
				width: 380,
				minHeight: 450,
				maxHeight: $(window).height() - 50,
				title: title,
				resizable: false,
				show: "fade",
				hide: "fade",
				open: function (event, ui) {
					$.ajax({
						url: Alchemy.routes.admin_trash_path(page_id),
						success: function(data, textStatus, XMLHttpRequest) {
							$dialog.html(data);
							// Need this for DragnDrop elements into elements window.
							// Badly this is screwing up maxHeight option
							$dialog.css({overflow: 'visible'}).dialog('widget').css({overflow: 'visible'});
						},
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							Alchemy.AjaxErrorHandler($dialog, XMLHttpRequest.status, textStatus, errorThrown);
						}
					});
				},
				close: function () {
					$dialog.remove();
				}
			});
		},

		refreshTrashWindow: function(page_id) {
			if ($('#alchemyTrashWindow').length > 0) {
				$('#alchemyTrashWindow').html(Alchemy.getOverlaySpinner({x: 380, y: 270}));
				$.get(Alchemy.routes.admin_trash_path(page_id), function(html) {
					$('#alchemyTrashWindow').html(html);
				});
			}
		}

	});
})(jQuery);
<|endoftext|>


<commit_before>Travis.Controllers.Sidebar = SC.Object.extend({
  cookie: 'sidebar_minimized',

  init: function() {
    Travis.Controllers.Workers.create();
    Travis.Controllers.Jobs.create({ queue: 'builds' });
    Travis.Controllers.Jobs.create({ queue: 'rails' });

    $(".slider").click(function() { this.toggle(); }.bind(this));
    if($.cookie(this.cookie) === 'true') { this.minimize(); }
    this.persist();
  },

  toggle: function() {
    this.isMinimized() ? this.maximize() : this.minimize();
    this.persist();
  },

  isMinimized: function() {
    return $('#right').hasClass('minimized');
  },

  minimize: function() {
    $('#right').addClass('minimized');
    $('#main').addClass('maximized');
  },

  maximize: function() {
    $('#right').removeClass('minimized');
    $('#main').removeClass('maximized');
  },

  persist: function() {
    $.cookie(this.cookie, this.isMinimized());
  }
});
<commit_msg>the default queue is now "ruby"<commit_after>Travis.Controllers.Sidebar = SC.Object.extend({
  cookie: 'sidebar_minimized',

  init: function() {
    Travis.Controllers.Workers.create();
    Travis.Controllers.Jobs.create({ queue: 'ruby'  });
    Travis.Controllers.Jobs.create({ queue: 'rails' });

    $(".slider").click(function() { this.toggle(); }.bind(this));
    if($.cookie(this.cookie) === 'true') { this.minimize(); }
    this.persist();
  },

  toggle: function() {
    this.isMinimized() ? this.maximize() : this.minimize();
    this.persist();
  },

  isMinimized: function() {
    return $('#right').hasClass('minimized');
  },

  minimize: function() {
    $('#right').addClass('minimized');
    $('#main').addClass('maximized');
  },

  maximize: function() {
    $('#right').removeClass('minimized');
    $('#main').removeClass('maximized');
  },

  persist: function() {
    $.cookie(this.cookie, this.isMinimized());
  }
});
<|endoftext|>