<commit_before>/*
This section of the code will do the following:
Audio:
- Record an audio file with a ".wav" extension
- Playback immediate file
- Send audio file to a server that will interpert through PHP where to save it
GPS:
- Log current GPS coordinates
- Button press to send GPS coordinates
*/
var win = Titanium.UI.currentWindow;

//	Creation of a new Directory to store both GPS and audio files. Will check if directory exists.
var newDir = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,'mydir');
if (newDir.exists('mydir')){
Titanium.API.info('Directory already exists');
} else {
newDir.createDirectory();
Titanium.API.info('Path to newdir: ' + newDir.nativePath);
};

//
//	Recording Audio Global Identifiers
//

Titanium.Media.audioSessionMode = Ti.Media.AUDIO_SESSION_MODE_PLAY_AND_RECORD;
var recording = Ti.Media.createAudioRecorder();
var file;
var sound;
var audioName = 'recording';
var newAudiofile = 'recording.mp4'; //recording.wav
var file_recorded = Titanium.Filesystem.getFile(newDir.nativePath, newAudiofile); //audioSample
upload_audio = file_recorded.read();
// default compression is Ti.Media.AUDIO_FORMAT_LINEAR_PCM
// default format is Ti.Media.AUDIO_FILEFORMAT_CAF

// this will give us a wave file with µLaw compression which
// is a generally small size and suitable for telephony recording
// for high end quality, you'll want LINEAR PCM - however, that
// will result in uncompressed audio and will be very large in size

// In addition, for the "createAudioPlayer()" function to read any audio created through Titanium. It seems
// that the audio needs to have ACC - format, and MP4 - fileformat. Otherwise it will NOT read correctly
// and return "Parse Errors" within the player. This has been my experience.

recording.compression = Ti.Media.AUDIO_FORMAT_AAC; //Was Ti.Media.AUDIO_FORMAT_ULAW
recording.format = Ti.Media.AUDIO_FILEFORMAT_MP4; //Was Ti.Media.AUDIO_FILEFORMAT_WAVE

//
//	Geolocation Global Identifiers
//

var uploadGPS = '';
var updatedLocation;
var updatedLatitude;
var latitude;
var longitude;
var coordinates = 'coordinates';
Titanium.Geolocation.purpose = "Recieve User Location";
Titanium.Geolocation.accuracy = Titanium.Geolocation.ACCURACY_BEST;
Titanium.Geolocation.distanceFilter = 10;

//Getting the files - GPS
var gps_recorded = Titanium.Filesystem.getFile(newDir.nativePath, "coordinates.JSON");
//Loading file into a variable
var uploadGPS = gps_recorded.read();
//Outputting Variable into Titanium GUI for debugging
Titanium.API.info(uploadGPS);

//
//	HTTPClient "Payload" Global Identifiers
//

var postData = {
				"media": upload_audio, //These need to be in double quotes to be accepted in the PHP script
				//"name": audioName, //These need to be in double quotes to be accepted in the PHP script
				"coords": uploadGPS //These need to be in double quotes to be accepted in the PHP script
				};

////////////////////////////////////////////////////////////////////

Titanium.Geolocation.addEventListener('location', function(e){
		if (!e.success || e.error)
		{
			updatedLocation.text = 'error:' + JSON.stringify(e.error);
			updatedLatitude.text = '';
			updatedLocationAccuracy.text = '';
			updatedLocationTime.text = '';
			return;
		}
		var longitude = e.coords.longitude;
		var latitude = e.coords.latitude;
		updatedLocation.text = 'long:' + longitude;
		updatedLatitude.text = 'lat: '+ latitude;

		var datatoWrite = {
							"latitude":latitude,
							"longitude":longitude
										};

		//Data to write?
		var newFile = Titanium.Filesystem.getFile(newDir.nativePath,"coordinates.JSON");
		newFile.write(JSON.stringify(datatoWrite));
});

////////////////////////////////////////////////////////////////////

//
//	Button - Start Recording
//

var start = Titanium.UI.createButton({
	title:'Start Recording',
	height:40,
	width:145,
	right:80,
	top:60
});

//

win.add(start);
	start.addEventListener('click', function(){
		if (recording.recording)
		{
			file = recording.stop();
			//Adding line to create a file instead of just replacing the recording.wav file
			newAudiofile = Titanium.Filesystem.getFile(newDir.nativePath, 'recording.mp4');
			//newAudiofile.write(file.toBlob);
			if (newAudiofile.exists()) {
				newAudiofile.deleteFile();
				newAudiofile.write(file.toBlob);
				} else {
					newAudiofile.write(file.toBlob);
				}
			start.title = "Start Recording";
			Ti.Media.stopMicrophoneMonitor();
			}
		else
		{
			if (!Ti.Media.canRecord) {
				Ti.UI.createAlertDialog({
					title:'Error!',
					message:'No audio recording hardware is currently connected.'
					}).show();
					return;
				}
				start.title = "Stop Recording";
				recording.start();
				Ti.Media.startMicrophoneMonitor();
				duration = 0;
			}
});

//
//	Button - Playback Recording
//

var b2 = Titanium.UI.createButton({
	title:'Playback Recording',
	height:40,
	width:180,
	top:120
});

//

win.add(b2);
	b2.addEventListener('click', function()
	{
		if (file == null)
		{
			Titanium.UI.createAlertDialog({
				title:'Error',
				message:'You need to record something first!'
			}).show();
			//return;
		} else {
		if (sound && sound.playing)
		{
			sound.stop();
			sound.release();
			sound = null;
			b2.title = 'Playback Recording';
		}
		else
		{
			Ti.API.info("recording file size: "+file.size);
			sound = Titanium.Media.createSound({sound:file});
			sound.addEventListener('complete', function()
			{
				b2.title = 'Playback Recording';
			});
			sound.play();
			b2.title = 'Stop Playback';
		}
	}
});

//
//	Button - Upload Audio
//

var upload = Titanium.UI.createButton({
	title:'Upload',
	height:40,
	width:145,
	right:80,
	top:180
});

//

win.add(upload);
	upload.addEventListener('click', function(e)
	{
		if (file == null)
		{
			Titanium.UI.createAlertDialog({
				title:'Error',
				message:'You need to record something first!'
			}).show();
			//return;
		} else {
		upload.title = "Recorded: " + file.size;
		var xhr = Titanium.Network.createHTTPClient();

		xhr.onerror = function(e)
		{
			Titanium.UI.createAlertDialog({title:'Error', message:e.error}).show();
			Titanium.API.info('IN ERROR' + e.error);
		};
		xhr.setTimeout(20000);
		xhr.onload = function(e)
		{
			Titanium.UI.createAlertDialog({title:'Success', message:'Your audio has been uploaded to the server'}).show(); //message:'status code' + this.status
			Titanium.API.info('IN ONLOAD ' + this.status + ' readyState ' + this.readyState);
		};
		xhr.onsendstream = function(e)
		{
			Titanium.API.info('ONSENDSTREAM - PROGRESS: ' + e.progress);
		};
		//open the client
		xhr.open('POST', 'http://localhost/uploadingaudiocoordinates.php', false); //http://localhost/gps_audio.php
		xhr.setRequestHeader("Content-Type", "audio/json");
		xhr.send(postData);
		file = null;
		};

	});

//

	updatedLocationLabel = Titanium.UI.createLabel({
	text:'Updated Location',
	font:{fontSize:12, fontWeight:'bold'},
	color:'#111',
	top:280, //Base number
	left:100, //same
	height:15, //same
	width:300 //same
});
win.add(updatedLocationLabel);

	updatedLocation = Titanium.UI.createLabel({
	text:'Updated Location not fired',
	font:{fontSize:11},
	color:'#444',
	top:300, // + 20 difference
	left:100, //same
	height:15, //same
	width:300 //same
});
win.add(updatedLocation);

	updatedLatitude = Titanium.UI.createLabel({
	text:'Updated Latitude not fired',
	font:{fontSize:11},
	color:'#444',
	top:320, // + 40 difference
	left:100, //same
	height:15, //same
	width:300 //same
});
win.add(updatedLatitude);<commit_msg>testing server side.<commit_after>/*
This section of the code will do the following:
Audio:
- Record an audio file with a ".wav" extension
- Playback immediate file
- Send audio file to a server that will interpert through PHP where to save it
GPS:
- Log current GPS coordinates
- Button press to send GPS coordinates
*/
var win = Titanium.UI.currentWindow;

//Creation of a new Directory to store both GPS and audio files. Will check if directory exists.
var newDir = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,'mydir');
if (newDir.exists('mydir')){
Titanium.API.info('Directory already exists');
} else {
newDir.createDirectory();
Titanium.API.info('Path to newdir: ' + newDir.nativePath);
};

//
//	Recording Audio Global Identifiers
//

Titanium.Media.audioSessionMode = Ti.Media.AUDIO_SESSION_MODE_PLAY_AND_RECORD;
var recording = Ti.Media.createAudioRecorder();
var file;
var sound;
var audioName = 'recording';
var newAudiofile = 'recording.mp4'; //recording.wav
var file_recorded = Titanium.Filesystem.getFile(newDir.nativePath, newAudiofile); //audioSample
upload_audio = file_recorded.read();
// default compression is Ti.Media.AUDIO_FORMAT_LINEAR_PCM
// default format is Ti.Media.AUDIO_FILEFORMAT_CAF

// this will give us a wave file with µLaw compression which
// is a generally small size and suitable for telephony recording
// for high end quality, you'll want LINEAR PCM - however, that
// will result in uncompressed audio and will be very large in size

// In addition, for the "createAudioPlayer()" function to read any audio created through Titanium. It seems
// that the audio needs to have ACC - format, and MP4 - fileformat. Otherwise it will NOT read correctly
// and return "Parse Errors" within the player. This has been my experience.

recording.compression = Ti.Media.AUDIO_FORMAT_AAC; //Was Ti.Media.AUDIO_FORMAT_ULAW
recording.format = Ti.Media.AUDIO_FILEFORMAT_MP4; //Was Ti.Media.AUDIO_FILEFORMAT_WAVE

//
//	Geolocation Global Identifiers
//

var uploadGPS = '';
var updatedLocation;
var updatedLatitude;
var latitude;
var longitude;
var coordinates = 'coordinates';
Titanium.Geolocation.purpose = "Recieve User Location";
Titanium.Geolocation.accuracy = Titanium.Geolocation.ACCURACY_BEST;
Titanium.Geolocation.distanceFilter = 10;

//Getting the files - GPS
var gps_recorded = Titanium.Filesystem.getFile(newDir.nativePath, "coordinates.JSON");
//Loading file into a variable
var uploadGPS = gps_recorded.read();
//Outputting Variable into Titanium GUI for debugging
Titanium.API.info(uploadGPS);

//
//	HTTPClient "Payload" Global Identifiers
//

var postData = {
				"media": upload_audio, //These need to be in double quotes to be accepted in the PHP script
				//"name": audioName, //These need to be in double quotes to be accepted in the PHP script
				"coords": uploadGPS //These need to be in double quotes to be accepted in the PHP script
				};

////////////////////////////////////////////////////////////////////

Titanium.Geolocation.addEventListener('location', function(e){
		if (!e.success || e.error)
		{
			updatedLocation.text = 'error:' + JSON.stringify(e.error);
			updatedLatitude.text = '';
			updatedLocationAccuracy.text = '';
			updatedLocationTime.text = '';
			return;
		}
		var longitude = e.coords.longitude;
		var latitude = e.coords.latitude;
		updatedLocation.text = 'long:' + longitude;
		updatedLatitude.text = 'lat: '+ latitude;

		var datatoWrite = {
							"latitude":latitude,
							"longitude":longitude
										};

		//Data to write?
		var newFile = Titanium.Filesystem.getFile(newDir.nativePath,"coordinates.JSON");
		newFile.write(JSON.stringify(datatoWrite));
});

////////////////////////////////////////////////////////////////////

//
//	Button - Start Recording
//

var start = Titanium.UI.createButton({
	title:'Start Recording',
	height:40,
	width:145,
	right:80,
	top:60
});

//

win.add(start);
	start.addEventListener('click', function(){
		if (recording.recording)
		{
			file = recording.stop();
			//Adding line to create a file instead of just replacing the recording.wav file
			newAudiofile = Titanium.Filesystem.getFile(newDir.nativePath, 'recording.mp4');
			//newAudiofile.write(file.toBlob);
			if (newAudiofile.exists()) {
				newAudiofile.deleteFile();
				newAudiofile.write(file.toBlob);
				} else {
					newAudiofile.write(file.toBlob);
				}
			start.title = "Start Recording";
			Ti.Media.stopMicrophoneMonitor();
			}
		else
		{
			if (!Ti.Media.canRecord) {
				Ti.UI.createAlertDialog({
					title:'Error!',
					message:'No audio recording hardware is currently connected.'
					}).show();
					return;
				}
				start.title = "Stop Recording";
				recording.start();
				Ti.Media.startMicrophoneMonitor();
				duration = 0;
			}
});

//
//	Button - Playback Recording
//

var b2 = Titanium.UI.createButton({
	title:'Playback Recording',
	height:40,
	width:180,
	top:120
});

//

win.add(b2);
	b2.addEventListener('click', function()
	{
		if (file == null)
		{
			Titanium.UI.createAlertDialog({
				title:'Error',
				message:'You need to record something first!'
			}).show();
			//return;
		} else {
		if (sound && sound.playing)
		{
			sound.stop();
			sound.release();
			sound = null;
			b2.title = 'Playback Recording';
		}
		else
		{
			Ti.API.info("recording file size: "+file.size);
			sound = Titanium.Media.createSound({sound:file});
			sound.addEventListener('complete', function()
			{
				b2.title = 'Playback Recording';
			});
			sound.play();
			b2.title = 'Stop Playback';
		}
	}
});

//
//	Button - Upload Audio
//

var upload = Titanium.UI.createButton({
	title:'Upload',
	height:40,
	width:145,
	right:80,
	top:180
});

//

win.add(upload);
	upload.addEventListener('click', function(e)
	{
		if (file == null)
		{
			Titanium.UI.createAlertDialog({
				title:'Error',
				message:'You need to record something first!'
			}).show();
			//return;
		} else {
		upload.title = "Recorded: " + file.size;
		var xhr = Titanium.Network.createHTTPClient();

		xhr.onerror = function(e)
		{
			Titanium.UI.createAlertDialog({title:'Error', message:e.error}).show();
			Titanium.API.info('IN ERROR' + e.error);
		};
		xhr.setTimeout(20000);
		xhr.onload = function(e)
		{
			Titanium.UI.createAlertDialog({title:'Success', message:'Your audio has been uploaded to the server'}).show(); //message:'status code' + this.status
			Titanium.API.info('IN ONLOAD ' + this.status + ' readyState ' + this.readyState);
		};
		xhr.onsendstream = function(e)
		{
			Titanium.API.info('ONSENDSTREAM - PROGRESS: ' + e.progress);
		};
		//open the client
		xhr.open('POST', 'http://localhost/uploadingaudiocoordinates.php', false); //http://localhost/gps_audio.php
		xhr.setRequestHeader("Content-Type", "audio/json");
		xhr.send(postData);
		file = null;
		};

	});

//

	updatedLocationLabel = Titanium.UI.createLabel({
	text:'Updated Location',
	font:{fontSize:12, fontWeight:'bold'},
	color:'#111',
	top:280, //Base number
	left:100, //same
	height:15, //same
	width:300 //same
});
win.add(updatedLocationLabel);

	updatedLocation = Titanium.UI.createLabel({
	text:'Updated Location not fired',
	font:{fontSize:11},
	color:'#444',
	top:300, // + 20 difference
	left:100, //same
	height:15, //same
	width:300 //same
});
win.add(updatedLocation);

	updatedLatitude = Titanium.UI.createLabel({
	text:'Updated Latitude not fired',
	font:{fontSize:11},
	color:'#444',
	top:320, // + 40 difference
	left:100, //same
	height:15, //same
	width:300 //same
});
win.add(updatedLatitude);<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule flattenStyle
 * @flow
 */
'use strict';

var ReactNativePropRegistry = require('ReactNativePropRegistry');
var invariant = require('fbjs/lib/invariant');

import type { StyleObj } from 'StyleSheetTypes';

function getStyle(style) {
  if (typeof style === 'number') {
    return ReactNativePropRegistry.getByID(style);
  }
  return style;
}

function flattenStyle(style: ?StyleObj): ?Object {
  if (!style) {
    return undefined;
  }
  invariant(style !== true, 'style may be false but not true');

  if (!Array.isArray(style)) {
    return getStyle(style);
  }

  var result = {};
  for (var i = 0; i < style.length; ++i) {
    var computedStyle = flattenStyle(style[i]);
    if (computedStyle) {
      for (var key in computedStyle) {
        result[key] = computedStyle[key];
      }
    }
  }
  return result;
}

module.exports = flattenStyle;
<commit_msg>Caches array length in flattenStyles methods for loop<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule flattenStyle
 * @flow
 */
'use strict';

var ReactNativePropRegistry = require('ReactNativePropRegistry');
var invariant = require('fbjs/lib/invariant');

import type { StyleObj } from 'StyleSheetTypes';

function getStyle(style) {
  if (typeof style === 'number') {
    return ReactNativePropRegistry.getByID(style);
  }
  return style;
}

function flattenStyle(style: ?StyleObj): ?Object {
  if (!style) {
    return undefined;
  }
  invariant(style !== true, 'style may be false but not true');

  if (!Array.isArray(style)) {
    return getStyle(style);
  }

  var result = {};
  for (var i = 0, styleLength = style.length; i < styleLength; ++i) {
    var computedStyle = flattenStyle(style[i]);
    if (computedStyle) {
      for (var key in computedStyle) {
        result[key] = computedStyle[key];
      }
    }
  }
  return result;
}

module.exports = flattenStyle;
<|endoftext|>


<commit_before>// namespace
var MPLAY = MPLAY || {};

(function() {
	"use_strict";

	/**
	 *
	 * @class PageEnding
	 * @augments MPlay.MPlayPage
	 */
var PageLoading = function(){
  MPLAY.MPlayPage.call(this);

  this._tweenComplete = true;
	this._curText = null;
	this._curTextBar = null;
	this._loadingComplete = false;
	this._loadTween = null;
	this._notifText = null;

  var page = this;
  var tutCounter = 1;
  //var mouseDownListener = null;
    this.mouseDownListener = function(event) {
    event.preventDefault();
    var mouse = {};
    mouse.x = event.clientX;
    mouse.y = event.clientY;
    if(page._tweenComplete)
    {
			page._tweenComplete = false;
    	tutCounter = page._TutorialNext(tutCounter);
    }
  };

  this._tutorialText = ["Click on characters or other objects like your phone to interact with them.",
  "Decisions affect your relationship with other characters.",
  "Look out for situations that involve moral choices and may affect the story."];

};

PageLoading.prototype = Object.create(MPLAY.MPlayPage.prototype);
PageLoading.prototype.constructor = PageLoading;

/**
 * @override
 */

 PageLoading.prototype._onLoad = function(){
   MPLAY.MPlayPage.prototype._onLoad.call(this);

   var background = this.createImage("/static/gnovel/res/loadingPage/loading screen_noBox.png",new THREE.Vector3(0,0,0),1920,1080);
   //background.position.z = this.getBackgroundLayer();
   this.setBackground("/static/gnovel/res/loadingPage/loading screen_noBox.png");

	 var loadSymbol = this.createImage("/static/gnovel/res/loadingPage/loading_symbol.png",new THREE.Vector3(550,320,0),300,150);
	 loadSymbol.name = "loadSymbol";
	 loadSymbol.material.opacity = 0;
	 this._addToScene(loadSymbol);

	 this._loadTween = this.tweenFlash(loadSymbol,{
		 opacity2: 0,
		 easing:TWEEN.Easing.Cubic.Out,
	 	duration:1500,});
	 this.getOwner().addMouseDownListener(this.mouseDownListener);

	 this._TutorialNext(0);
	 this._notifText = this.createImage("/static/gnovel/res/loadingPage/loading_tut_text.png",new THREE.Vector3(0,-100,5),560,50);
	 /*var message = "(Click or press [Space] to advance messages and dialogue.)"
	 var notifText = this.createTextBox(message,{
		 charLine: 60,
		 font: "28px Noteworthy",
		 center: true,
		 fillstyle: '#ffffff',});*/

	//set text on bottom right
	this._notifText.material.opacity = 0;
	this._addToScene(this._notifText);
	//fade in text after X delay
	this.tweenMat(this._notifText,{
		opacity: 1,
		delay:2000,
		duration:400,
		easing: TWEEN.Easing.Cubic.Out,
	});

 };

 PageLoading.prototype._TutorialNext = function(count){
	 var page = this;

	 //show compass animation for 3rd tutorial text
   if(count == 2)
   {
     this._compassAnim();
		 this.LoadingComplete();
		 this.tweenMat(this._notifText,{
			 opacity:0,
			 duration:400,
			 easing:TWEEN.Easing.Cubic.Out,
			 onComplete: function(){
				 page._removeFromScene(page._notifText);
			 }
		 })
   };
	 //display textbox on top of background

	 if(this._tutorialText[count]!=null)
	 {
		 var textbar = this.createImage("/static/gnovel/res/loadingPage/loading_textBox.png", new THREE.Vector3(0,0,this.getBackgroundLayer() + 10),1000,150);

		 var message = this._tutorialText[count];
		 var tutText = this.createTextBox(message,{
			 charLine: 55,
			 font: "35px Noteworthy",
			 center: true,
			 fillstyle: '#ffffff',});

 		 tutText.position.set(20,40,textbar.position.z+5);

		 //remove previous text and fade out
		 if(this._curText)
		 {
			 this.tweenMat(this._curTextBar,{
				 duration:400,
				 easing:TWEEN.Easing.Cubic.Out,
				 opacity: 0,
				 onComplete: function(){
					 page._removeFromScene(this._curTextBar);
				 }
			 });

			 this.tweenMat(this._curText,{
				 duration:400,
				 easing:TWEEN.Easing.Cubic.Out,
				 opacity: 0,
				 onComplete: function(){
					 page._removeFromScene(this._curText);
				 }
			 });

		 }

		 //fade in textbar
		 this._addToScene(textbar);
		 textbar.material.opacity = 0;
		 this.tweenMat(textbar,{
			 duration:600,
			 easing:TWEEN.Easing.Cubic.Out,
			 opacity: 1,
		 });

		 //fade in text
	     this._addToScene(tutText);
			 tutText.material.opacity = 0;
			 this.tweenMat(tutText,{
				 duration:600,
				 easing:TWEEN.Easing.Cubic.Out,
				 opacity: 1,
			 });

			 //set global variable to current text and image
			 this._curText = tutText;
			 this._curTextBar = textbar;
			 //increment count for which text should display
			 count++;

			 //after tweening in text, set tweenComplete
			 this._tweenComplete = true;
		 }
		 else {
		 		if(this._curText)
				{
					//fade out and remoev
					this.tweenMat(this._curTextBar,{
	 				 duration:400,
	 				 easing:TWEEN.Easing.Cubic.Out,
	 				 opacity: 0,
	 				 onComplete: function(){
	 					 page._removeFromScene(this._curTextBar);
	 				 }
	 			 });

	 			 this.tweenMat(this._curText,{
	 				 duration:400,
	 				 easing:TWEEN.Easing.Cubic.Out,
	 				 opacity: 0,
	 				 onComplete: function(){
	 					 page._removeFromScene(this._curText);
	 				 }
	 			 });
				}
		 }
		 return count;
 };

 PageLoading.prototype._compassAnim = function(){

	 var page = this;
   var compassBack = this.createImage("/static/gnovel/res/textures/ui/compass background.png", new THREE.Vector3(-400, 0, this._backgroundLayer + 35), 150, 150);
   var compassFront = this.createImage("/static/gnovel/res/textures/ui/compass main.png", new THREE.Vector3(-400, 0, this._backgroundLayer + 35), 150, 150);
   compassBack.material.opacity = 0;
   compassFront.material.opacity = 0;

   this._addToScene(compassBack);
   this._addToScene(compassFront);
   var delayFX = 500;

   //full COMPASS ANIMATION
   //fade compass in
   this.tweenMat(compassFront, {
     easing: TWEEN.Easing.Cubic.Out,
     duration:1000,
     opacity: 1,
   });
   this.tweenMat(compassBack, {
     easing: TWEEN.Easing.Cubic.Out,
     duration:1000,
     opacity: 1,
     onComplete: function() {

     //ANIMATE spin compass
         var duration = 200;
         var rotDest = .3;
         var rotTween = new TWEEN.Tween(compassFront.rotation)
           .to({
             z: 90*Math.PI/180, //rotates 90 degrees
           }, duration)
           .easing(TWEEN.Easing.Linear.None)
           .repeat(10)
           .onComplete(function() {

             //fade compass out
             page.tweenMat(compassFront, {
               easing: TWEEN.Easing.Cubic.Out,
               duration: 800,
               opacity: 0,
               opacity2: 0,
               delay: delayFX,
             });
             page.tweenMat(compassBack, {
               easing: TWEEN.Easing.Cubic.Out,
               duration: 800,
               opacity: 0,
               opacity2: 0,
               delay: delayFX,
               onComplete: function() {
                 page._removeFromScene(compassBack);
                 page._removeFromScene(compassFront);
               },
             });

           });

         rotTween.start();
 		 },
 	});
 };

/**
*@function call when loading of assets is complete
*/
 PageLoading.prototype.LoadingComplete = function(){

	 this._loadingComplete = true;
	 //stop loading symbol flashing
	 this._removeFromScene(this._getRootObject().getObjectByName("loadSymbol"));

	 //show continue button
	 var continueBut = this.createImage("/static/gnovel/res/loadingPage/loading_continue.png",new THREE.Vector3(0, -300, this.getBackgroundLayer() + 5), 375, 120);
	 continueBut.material.opacity = 0;
	 this.tweenMat(continueBut,{
		 opacity:1,
		 duration:1000,
		 easing:TWEEN.Easing.Cubic.Out,
	 });
	 this._addToScene(continueBut);
 };

 PageLoading.prototype._onUnload = function(){

 };

    window.addEventListener('resize', function(event) {
       var container = document.getElementById("container");

      var aspect_ratio = window.innerWidth / window.innerHeight;

      if (aspect_ratio > 16 / 9) {
        // fill height
        container.height = window.innerHeight;
        container.width = (16 / 9) * container.height;
      } else {
        // fill width
        container.width = window.innerWidth;
        container.height = (9 / 16) * container.width;
      }
    });

MPLAY.PageLoading = PageLoading;
}());
<commit_msg>added condition for LoadingComplete to go to next page once "Continue" button is clicked.<commit_after>// namespace
var MPLAY = MPLAY || {};

(function() {
	"use_strict";

	/**
	 *
	 * @class PageEnding
	 * @augments MPlay.MPlayPage
	 */
var PageLoading = function(){
  MPLAY.MPlayPage.call(this);

  this._tweenComplete = true;
	this._curText = null;
	this._curTextBar = null;
	this._loadingComplete = false;
	this._loadTween = null;
	this._notifText = null;

  var page = this;
  var tutCounter = 1;
  //var mouseDownListener = null;
    this.mouseDownListener = function(event) {
    event.preventDefault();
    var mouse = {};
    mouse.x = event.clientX;
    mouse.y = event.clientY;
		page._owner.calcMousePositionRelativeToCanvas(mouse);

		//update picking ray with camera and mouse pos
		page._owner._raycaster.setFromCamera(mouse, page._owner.getCamera());
		var intersectBut = page._owner._raycaster.intersectObjects([page._continueBut], true);

    if(page._tweenComplete)
    {
			page._tweenComplete = false;
    	tutCounter = page._TutorialNext(tutCounter);
    }

		if(page._loadingComplete && intersectBut.length>0)
		{
			var nextPage = 1;
		 	page.goToPage(nextPage, GNOVEL.TransitionType.FADE);
		}
  };

  this._tutorialText = ["Click on characters or other objects like your phone to interact with them.",
  "Decisions affect your relationship with other characters.",
  "Look out for situations that involve moral choices and may affect the story."];

};

PageLoading.prototype = Object.create(MPLAY.MPlayPage.prototype);
PageLoading.prototype.constructor = PageLoading;

/**
 * @override
 */

 PageLoading.prototype._onLoad = function(){
   MPLAY.MPlayPage.prototype._onLoad.call(this);

   var background = this.createImage("/static/gnovel/res/loadingPage/loading screen_noBox.png",new THREE.Vector3(0,0,0),1920,1080);
   //background.position.z = this.getBackgroundLayer();
   this.setBackground("/static/gnovel/res/loadingPage/loading screen_noBox.png");

	 var loadSymbol = this.createImage("/static/gnovel/res/loadingPage/loading_symbol.png",new THREE.Vector3(550,320,0),300,150);
	 loadSymbol.name = "loadSymbol";
	 loadSymbol.material.opacity = 0;
	 this._addToScene(loadSymbol);

	 this._loadTween = this.tweenFlash(loadSymbol,{
		 opacity2: 0,
		 easing:TWEEN.Easing.Cubic.Out,
	 	duration:1500,});
	 this.getOwner().addMouseDownListener(this.mouseDownListener);

	 this._TutorialNext(0);
	 this._notifText = this.createImage("/static/gnovel/res/loadingPage/loading_tut_text.png",new THREE.Vector3(0,-100,5),560,50);
	 /*var message = "(Click or press [Space] to advance messages and dialogue.)"
	 var notifText = this.createTextBox(message,{
		 charLine: 60,
		 font: "28px Noteworthy",
		 center: true,
		 fillstyle: '#ffffff',});*/

	//set text on bottom right
	this._notifText.material.opacity = 0;
	this._addToScene(this._notifText);
	//fade in text after X delay
	this.tweenMat(this._notifText,{
		opacity: 1,
		delay:2000,
		duration:400,
		easing: TWEEN.Easing.Cubic.Out,
	});

	//continue button after loading
	this._continueBut = this.createImage("/static/gnovel/res/loadingPage/loading_continue.png",new THREE.Vector3(0, -300, this.getBackgroundLayer() + 5), 375, 120);
	this._continueBut.material.opacity = 0;
	this._addToScene(this._continueBut);
 };

 PageLoading.prototype._onStart = function() {
 	MPLAY.MPlayPage.prototype._onStart.call(this);
};

 PageLoading.prototype._TutorialNext = function(count){
	 var page = this;

	 //show compass animation for 3rd tutorial text
   if(count == 2)
   {
     this._compassAnim();
		 this.LoadingComplete();
		 this.tweenMat(this._notifText,{
			 opacity:0,
			 duration:400,
			 easing:TWEEN.Easing.Cubic.Out,
			 onComplete: function(){
				 page._removeFromScene(page._notifText);
			 }
		 })
   };
	 //display textbox on top of background

	 if(this._tutorialText[count]!=null)
	 {
		 var textbar = this.createImage("/static/gnovel/res/loadingPage/loading_textBox.png", new THREE.Vector3(0,0,this.getBackgroundLayer() + 10),1000,150);

		 var message = this._tutorialText[count];
		 var tutText = this.createTextBox(message,{
			 charLine: 55,
			 font: "35px Noteworthy",
			 center: true,
			 fillstyle: '#ffffff',});

 		 tutText.position.set(20,40,textbar.position.z+5);

		 //remove previous text and fade out
		 if(this._curText)
		 {
			 this.tweenMat(this._curTextBar,{
				 duration:400,
				 easing:TWEEN.Easing.Cubic.Out,
				 opacity: 0,
				 onComplete: function(){
					 page._removeFromScene(this._curTextBar);
				 }
			 });

			 this.tweenMat(this._curText,{
				 duration:400,
				 easing:TWEEN.Easing.Cubic.Out,
				 opacity: 0,
				 onComplete: function(){
					 page._removeFromScene(this._curText);
				 }
			 });

		 }

		 //fade in textbar
		 this._addToScene(textbar);
		 textbar.material.opacity = 0;
		 this.tweenMat(textbar,{
			 duration:600,
			 easing:TWEEN.Easing.Cubic.Out,
			 opacity: 1,
		 });

		 //fade in text
	     this._addToScene(tutText);
			 tutText.material.opacity = 0;
			 this.tweenMat(tutText,{
				 duration:600,
				 easing:TWEEN.Easing.Cubic.Out,
				 opacity: 1,
			 });

			 //set global variable to current text and image
			 this._curText = tutText;
			 this._curTextBar = textbar;
			 //increment count for which text should display
			 count++;

			 //after tweening in text, set tweenComplete
			 this._tweenComplete = true;
		 }
		 else {
		 		if(this._curText)
				{
					//fade out and remoev
					this.tweenMat(this._curTextBar,{
	 				 duration:400,
	 				 easing:TWEEN.Easing.Cubic.Out,
	 				 opacity: 0,
	 				 onComplete: function(){
	 					 page._removeFromScene(this._curTextBar);
	 				 }
	 			 });

	 			 this.tweenMat(this._curText,{
	 				 duration:400,
	 				 easing:TWEEN.Easing.Cubic.Out,
	 				 opacity: 0,
	 				 onComplete: function(){
	 					 page._removeFromScene(this._curText);
	 				 }
	 			 });
				}
		 }
		 return count;
 };

 PageLoading.prototype._compassAnim = function(){

	 var page = this;
   var compassBack = this.createImage("/static/gnovel/res/textures/ui/compass background.png", new THREE.Vector3(-400, 0, this._backgroundLayer + 35), 150, 150);
   var compassFront = this.createImage("/static/gnovel/res/textures/ui/compass main.png", new THREE.Vector3(-400, 0, this._backgroundLayer + 35), 150, 150);
   compassBack.material.opacity = 0;
   compassFront.material.opacity = 0;

   this._addToScene(compassBack);
   this._addToScene(compassFront);
   var delayFX = 500;

   //full COMPASS ANIMATION
   //fade compass in
   this.tweenMat(compassFront, {
     easing: TWEEN.Easing.Cubic.Out,
     duration:1000,
     opacity: 1,
   });
   this.tweenMat(compassBack, {
     easing: TWEEN.Easing.Cubic.Out,
     duration:1000,
     opacity: 1,
     onComplete: function() {

     //ANIMATE spin compass
         var duration = 200;
         var rotDest = .3;
         var rotTween = new TWEEN.Tween(compassFront.rotation)
           .to({
             z: 90*Math.PI/180, //rotates 90 degrees
           }, duration)
           .easing(TWEEN.Easing.Linear.None)
           .repeat(10)
           .onComplete(function() {

             //fade compass out
             page.tweenMat(compassFront, {
               easing: TWEEN.Easing.Cubic.Out,
               duration: 800,
               opacity: 0,
               opacity2: 0,
               delay: delayFX,
             });
             page.tweenMat(compassBack, {
               easing: TWEEN.Easing.Cubic.Out,
               duration: 800,
               opacity: 0,
               opacity2: 0,
               delay: delayFX,
               onComplete: function() {
                 page._removeFromScene(compassBack);
                 page._removeFromScene(compassFront);
               },
             });

           });

         rotTween.start();
 		 },
 	});
 };

/**
*@function call when loading of assets is complete
*/
 PageLoading.prototype.LoadingComplete = function(){

	 this._loadingComplete = true;
	 //stop loading symbol flashing
	 this._removeFromScene(this._getRootObject().getObjectByName("loadSymbol"));

	 //show continue button
	 var continueBut = this._continueBut;
	 this.tweenMat(continueBut,{
		 opacity:1,
		 duration:1000,
		 easing:TWEEN.Easing.Cubic.Out,
	 });
 };

 PageLoading.prototype._onUnload = function(){
	 MPLAY.MPlayPage.prototype._onUnload.call(this);
 };

    window.addEventListener('resize', function(event) {
       var container = document.getElementById("container");

      var aspect_ratio = window.innerWidth / window.innerHeight;

      if (aspect_ratio > 16 / 9) {
        // fill height
        container.height = window.innerHeight;
        container.width = (16 / 9) * container.height;
      } else {
        // fill width
        container.width = window.innerWidth;
        container.height = (9 / 16) * container.width;
      }
    });

MPLAY.PageLoading = PageLoading;
}());
<|endoftext|>


<commit_before>import LayersHelper from 'helpers/LayersHelper';
import React, {PropTypes} from 'react';
import text from 'js/languages';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import 'react-datepicker/dist/react-datepicker.css';
import {defaultColorTheme} from '../../config';
import layerActions from '../../actions/LayerActions';
import MapStore from '../../stores/MapStore';

export default class FiresControls extends React.Component {

  static contextTypes = {
    settings: PropTypes.object.isRequired,
    language: PropTypes.string.isRequired,
    map: PropTypes.object.isRequired
  };

  constructor(props) {
    super(props);

    const currentDate = new Date();
    const oneYearAgo = currentDate.setFullYear(currentDate.getFullYear() - 1);
    const max = new Date();

    this.min = moment(oneYearAgo);
    this.max = moment(max);
    this.fireOptions = [
      {label: 'Past 24 hours', value: 0},
      {label: 'Past 48 hours', value: 1},
      {label: 'Past 72 hours', value: 2},
      {label: 'Past Week', value: 3}
    ];
    this.state = {
      ...MapStore.getState()
    };
  }

  componentDidMount() {
    MapStore.listen(this.storeDidUpdate);
  }

  storeDidUpdate = () => {
    this.setState(MapStore.getState());
  };

  componentDidUpdate(prevProps, prevState, prevContext) {
    if (prevProps.startDate !== this.props.startDate || prevProps.endDate !== this.props.endDate) {
      brApp.map.infoWindow.clearFeatures();
      LayersHelper.updateFiresLayerDefinitions(this.props.startDate, this.props.endDate, this.props.layer, 4);
    }
    // Anytime the map changes to a new map, update that here
    const {map} = this.context;
    if (prevContext.map !== map && prevContext.map.loaded) {
      const signal = map.on('update-end', () => {
        signal.remove();
        LayersHelper.updateFiresLayerDefinitions(this.props.startDate, this.props.endDate, this.props.layer);
      });
    }
  }

  handleStartChange = (startDate) => {
    this.props.updateStartDate(startDate);
  }

  handleEndChange = (endDate) => {
    this.props.updateEndDate(endDate);
  }

  renderActiveFireOptions = fireOptions => {
    return fireOptions.map((fireOption, index) => {
      return <option key={`option-${index}`} value={fireOption.value}>{fireOption.label}</option>;
    });
  };

  updateActiveFires = (evt, fireOptions) => {
    brApp.map.infoWindow.clearFeatures();
    LayersHelper.updateFiresLayerDefinitions(this.props.startDate, this.props.endDate, this.props.layer, evt.target.value);
    layerActions.updateCustomRange(false);
    layerActions.updateActiveFireOption(evt.target.value);
    layerActions.updateActiveFireOptionLabel(fireOptions[evt.target.value].label);
  };

  render () {
    const { startDate, endDate } = this.props;
    const {language} = this.context;
    const {customRange, activeFireOption, activeFireOptionLabel} = this.state;
    const { customColorTheme } = this.context.settings;
    return (

              <select
                className={`${customRange ? 'not-allowed' : 'pointer'}`}
                value={activeFireOption}
                onChange={evt => this.updateActiveFires(evt, this.fireOptions)}
                disabled={customRange}
              >
              {this.renderActiveFireOptions(this.fireOptions)}
              </select>
              <div
                style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
                className={`fa-button sml white ${customRange ? 'fa-button-disabled not-allowed' : 'pointer'}`}>{activeFireOptionLabel}

          <div
            style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
            className="fa-button sml white pointer"
            onClick={() => {
                layerActions.updateCustomRange(!customRange);
                layerActions.updateActiveFireOptionLabel.defer(!customRange ? 'Active Fires' : this.fireOptions[this.fireOptions.filter(fireOption => fireOption.value === activeFireOption)[0].value].label);
              }
            }
          >
            Custom Range

          {customRange &&

                  {text[language].TIMELINE_START}
                  <DatePicker
                    customInput={<StartButton customColorTheme={customColorTheme} />}
                    showMonthDropdown
                    showYearDropdown
                    dropdownMode="select"
                    todayButton='Jump to today'
                    minDate={this.min}
                    maxDate={moment(endDate)}
                    selected={moment(startDate)}
                    onChange={this.handleStartChange}
                  />

                  {text[language].TIMELINE_END}
                  <DatePicker
                    customInput={<EndButton customColorTheme={customColorTheme} />}
                    showMonthDropdown
                    showYearDropdown
                    dropdownMode="select"
                    todayButton='Jump to today'
                    minDate={moment(startDate)}
                    maxDate={this.max}
                    selected={moment(endDate)}
                    onChange={this.handleEndChange}
                  />

          }

    );
  }
}

const StartButton = ({ onClick, value, customColorTheme }) => {
  return (
    <button
      style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
      className='fa-button sml white pointer'
      onClick={onClick}
    >
      {value}
    </button>
  );
};

const EndButton = ({ onClick, value, customColorTheme }) => {
  return (
    <button
      style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
      className='fa-button sml white pointer'
      onClick={onClick}
    >
      {value}
    </button>
  );
};
<commit_msg>Revert styling back to original for fires options dropdown; Fix map store state for storing the right value (integer) instead of a string<commit_after>import LayersHelper from 'helpers/LayersHelper';
import React, {PropTypes} from 'react';
import text from 'js/languages';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import 'react-datepicker/dist/react-datepicker.css';
import {defaultColorTheme} from '../../config';
import layerActions from '../../actions/LayerActions';
import MapStore from '../../stores/MapStore';

export default class FiresControls extends React.Component {

  static contextTypes = {
    settings: PropTypes.object.isRequired,
    language: PropTypes.string.isRequired,
    map: PropTypes.object.isRequired
  };

  constructor(props) {
    super(props);

    const currentDate = new Date();
    const oneYearAgo = currentDate.setFullYear(currentDate.getFullYear() - 1);
    const max = new Date();

    this.min = moment(oneYearAgo);
    this.max = moment(max);
    this.fireOptions = [
      {label: 'Past 24 hours', value: 0},
      {label: 'Past 48 hours', value: 1},
      {label: 'Past 72 hours', value: 2},
      {label: 'Past Week', value: 3}
    ];
    this.state = {
      ...MapStore.getState()
    };
  }

  componentDidMount() {
    MapStore.listen(this.storeDidUpdate);
  }

  storeDidUpdate = () => {
    this.setState(MapStore.getState());
  };

  componentDidUpdate(prevProps, prevState, prevContext) {
    if (prevProps.startDate !== this.props.startDate || prevProps.endDate !== this.props.endDate) {
      brApp.map.infoWindow.clearFeatures();
      LayersHelper.updateFiresLayerDefinitions(this.props.startDate, this.props.endDate, this.props.layer, 4);
    }
    // Anytime the map changes to a new map, update that here
    const {map} = this.context;
    if (prevContext.map !== map && prevContext.map.loaded) {
      const signal = map.on('update-end', () => {
        signal.remove();
        LayersHelper.updateFiresLayerDefinitions(this.props.startDate, this.props.endDate, this.props.layer);
      });
    }
  }

  handleStartChange = (startDate) => {
    this.props.updateStartDate(startDate);
  }

  handleEndChange = (endDate) => {
    this.props.updateEndDate(endDate);
  }

  renderActiveFireOptions = fireOptions => {
    return fireOptions.map((fireOption, index) => {
      return <option key={`option-${index}`} value={fireOption.value}>{fireOption.label}</option>;
    });
  };

  updateActiveFires = (evt, fireOptions) => {
    brApp.map.infoWindow.clearFeatures();
    LayersHelper.updateFiresLayerDefinitions(this.props.startDate, this.props.endDate, this.props.layer, evt.target.value);
    layerActions.updateCustomRange(false);
    layerActions.updateActiveFireOption(parseInt(evt.target.value));
    layerActions.updateActiveFireOptionLabel(fireOptions[parseInt(evt.target.value)].label);
  };

  render () {
    const { startDate, endDate } = this.props;
    const {language} = this.context;
    const {customRange, activeFireOption, activeFireOptionLabel} = this.state;
    const { customColorTheme } = this.context.settings;
    return (

              <select
                className='pointer'
                value={activeFireOption}
                onChange={evt => this.updateActiveFires(evt, this.fireOptions)}
              >
              {this.renderActiveFireOptions(this.fireOptions)}
              </select>
              <div
                style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
                className='fa-button sml white pointer'>{activeFireOptionLabel}

          <div
            style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
            className="fa-button sml white pointer"
            onClick={() => {
                layerActions.updateCustomRange(!customRange);
                layerActions.updateActiveFireOptionLabel.defer(!customRange ? 'Active Fires' : this.fireOptions.filter(fireOption => fireOption.value === activeFireOption)[0].label);
              }
            }
          >
            Custom Range

          {customRange &&

                  {text[language].TIMELINE_START}
                  <DatePicker
                    customInput={<StartButton customColorTheme={customColorTheme} />}
                    showMonthDropdown
                    showYearDropdown
                    dropdownMode="select"
                    todayButton='Jump to today'
                    minDate={this.min}
                    maxDate={moment(endDate)}
                    selected={moment(startDate)}
                    onChange={this.handleStartChange}
                  />

                  {text[language].TIMELINE_END}
                  <DatePicker
                    customInput={<EndButton customColorTheme={customColorTheme} />}
                    showMonthDropdown
                    showYearDropdown
                    dropdownMode="select"
                    todayButton='Jump to today'
                    minDate={moment(startDate)}
                    maxDate={this.max}
                    selected={moment(endDate)}
                    onChange={this.handleEndChange}
                  />

          }

    );
  }
}

const StartButton = ({ onClick, value, customColorTheme }) => {
  return (
    <button
      style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
      className='fa-button sml white pointer'
      onClick={onClick}
    >
      {value}
    </button>
  );
};

const EndButton = ({ onClick, value, customColorTheme }) => {
  return (
    <button
      style={{border: `1px solid ${customColorTheme && customColorTheme !== '' ? customColorTheme : defaultColorTheme}`}}
      className='fa-button sml white pointer'
      onClick={onClick}
    >
      {value}
    </button>
  );
};
<|endoftext|>


<commit_before>(function(){
  'use strict';

  angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',
  function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {
    // Do stuff after mouse has been down this many ms on the header cell
    var mousedownTimeout = 500;
    var changeModeTimeout = 500;    // length of time between a touch event and a mouse event being recognised again, and vice versa

    var uiGridHeaderCell = {
      priority: 0,
      scope: {
        col: '=',
        row: '=',
        renderIndex: '='
      },
      require: ['^uiGrid', '^uiGridRenderContainer'],
      replace: true,
      compile: function() {
        return {
          pre: function ($scope, $elm, $attrs) {
            var cellHeader = $compile($scope.col.headerCellTemplate)($scope);
            $elm.append(cellHeader);
          },

          post: function ($scope, $elm, $attrs, controllers) {
            var uiGridCtrl = controllers[0];
            var renderContainerCtrl = controllers[1];

            $scope.i18n = {
              headerCell: i18nService.getSafeText('headerCell'),
              sort: i18nService.getSafeText('sort')
            };
            $scope.isSortPriorityVisible = function() {
              //show sort priority if column is sorted and there is at least one other sorted column
              return angular.isNumber($scope.col.sort.priority) && $scope.grid.columns.some(function(element, index){
                  return angular.isNumber(element.sort.priority) && element !== $scope.col;
                });
            };
            $scope.getSortDirectionAriaLabel = function(){
              var col = $scope.col;
              //Trying to recreate this sort of thing but it was getting messy having it in the template.
              //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}
              var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);
              var label = sortDirectionText;

              if ($scope.isSortPriorityVisible()) {
                label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + (col.sort.priority + 1);
              }
              return label;
            };

            $scope.grid = uiGridCtrl.grid;

            $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];

            var initColClass = $scope.col.getColClass(false);
            $elm.addClass(initColClass);

            // Hide the menu by default
            $scope.menuShown = false;

            // Put asc and desc sort directions in scope
            $scope.asc = uiGridConstants.ASC;
            $scope.desc = uiGridConstants.DESC;

            // Store a reference to menu element
            var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );

            var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );

            // apply any headerCellClass
            var classAdded;
            var previousMouseX;

            // filter watchers
            var filterDeregisters = [];

            /*
             * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
             * Once we have a down event, we need to work out whether we have a click, a drag, or a
             * hold.  A click would sort the grid (if sortable).  A drag would be used by moveable, so
             * we ignore it.  A hold would open the menu.
             *
             * So, on down event, we put in place handlers for move and up events, and a timer.  If the
             * timer expires before we see a move or up, then we have a long press and hence a column menu open.
             * If the up happens before the timer, then we have a click, and we sort if the column is sortable.
             * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
             * will handle it.
             *
             * To deal with touch enabled devices that also have mice, we only create our handlers when
             * we get the down event, and we create the corresponding handlers - if we're touchstart then
             * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
             *
             * We also suppress the click action whilst this is happening - otherwise after the mouseup there
             * will be a click event and that can cause the column menu to close
             *
             */

            $scope.downFn = function( event ){
              event.stopPropagation();

              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
                event = event.originalEvent;
              }

              // Don't show the menu if it's not the left button
              if (event.button && event.button !== 0) {
                return;
              }
              previousMouseX = event.pageX;

              $scope.mousedownStartTime = (new Date()).getTime();
              $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);

              $scope.mousedownTimeout.then(function () {
                if ( $scope.colMenu ) {
                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
                }
              }).catch(angular.noop);

              uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});

              $scope.offAllEvents();
              if ( event.type === 'touchstart'){
                $document.on('touchend', $scope.upFn);
                $document.on('touchmove', $scope.moveFn);
              } else if ( event.type === 'mousedown' ){
                $document.on('mouseup', $scope.upFn);
                $document.on('mousemove', $scope.moveFn);
              }
            };

            $scope.upFn = function( event ){
              event.stopPropagation();
              $timeout.cancel($scope.mousedownTimeout);
              $scope.offAllEvents();
              $scope.onDownEvents(event.type);

              var mousedownEndTime = (new Date()).getTime();
              var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;

              if (mousedownTime > mousedownTimeout) {
                // long click, handled above with mousedown
              }
              else {
                // short click
                if ( $scope.sortable ){
                  $scope.handleClick(event);
                }
              }
            };

            $scope.moveFn = function( event ){
              // Chrome is known to fire some bogus move events.
              var changeValue = event.pageX - previousMouseX;
              if ( changeValue === 0 ){ return; }

              // we're a move, so do nothing and leave for column move (if enabled) to take over
              $timeout.cancel($scope.mousedownTimeout);
              $scope.offAllEvents();
              $scope.onDownEvents(event.type);
            };

            $scope.clickFn = function ( event ){
              event.stopPropagation();
              $contentsElm.off('click', $scope.clickFn);
            };

            $scope.offAllEvents = function(){
              $contentsElm.off('touchstart', $scope.downFn);
              $contentsElm.off('mousedown', $scope.downFn);

              $document.off('touchend', $scope.upFn);
              $document.off('mouseup', $scope.upFn);

              $document.off('touchmove', $scope.moveFn);
              $document.off('mousemove', $scope.moveFn);

              $contentsElm.off('click', $scope.clickFn);
            };

            $scope.onDownEvents = function( type ){
              // If there is a previous event, then wait a while before
              // activating the other mode - i.e. if the last event was a touch event then
              // don't enable mouse events for a wee while (500ms or so)
              // Avoids problems with devices that emulate mouse events when you have touch events

              switch (type){
                case 'touchmove':
                case 'touchend':
                  $contentsElm.on('click', $scope.clickFn);
                  $contentsElm.on('touchstart', $scope.downFn);
                  $timeout(function(){
                    $contentsElm.on('mousedown', $scope.downFn);
                  }, changeModeTimeout);
                  break;
                case 'mousemove':
                case 'mouseup':
                  $contentsElm.on('click', $scope.clickFn);
                  $contentsElm.on('mousedown', $scope.downFn);
                  $timeout(function(){
                    $contentsElm.on('touchstart', $scope.downFn);
                  }, changeModeTimeout);
                  break;
                default:
                  $contentsElm.on('click', $scope.clickFn);
                  $contentsElm.on('touchstart', $scope.downFn);
                  $contentsElm.on('mousedown', $scope.downFn);
              }
            };

            var updateHeaderOptions = function( grid ){
              var contents = $elm;
              if ( classAdded ){
                contents.removeClass( classAdded );
                classAdded = null;
              }

              if (angular.isFunction($scope.col.headerCellClass)) {
                classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
              }
              else {
                classAdded = $scope.col.headerCellClass;
              }
              contents.addClass(classAdded);

              $timeout(function (){
                var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
                $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );
              });

              // Figure out whether this column is sortable or not
              if ($scope.col.enableSorting) {
                $scope.sortable = true;
              }
              else {
                $scope.sortable = false;
              }

              // Figure out whether this column is filterable or not
              var oldFilterable = $scope.filterable;
              if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {
                $scope.filterable = true;
              }
              else {
                $scope.filterable = false;
              }

              if ( oldFilterable !== $scope.filterable){
                if ( typeof($scope.col.updateFilters) !== 'undefined' ){
                  $scope.col.updateFilters($scope.filterable);
                }

                // if column is filterable add a filter watcher
                if ($scope.filterable) {
                  $scope.col.filters.forEach( function(filter, i) {
                    filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
                      if (n !== o) {
                        uiGridCtrl.grid.api.core.raise.filterChanged();
                        uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
                        uiGridCtrl.grid.queueGridRefresh();
                      }
                    }));
                  });
                  $scope.$on('$destroy', function() {
                    filterDeregisters.forEach( function(filterDeregister) {
                      filterDeregister();
                    });
                  });
                } else {
                  filterDeregisters.forEach( function(filterDeregister) {
                    filterDeregister();
                  });
                }

              }

              // figure out whether we support column menus
              if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&
                      $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){
                $scope.colMenu = true;
              } else {
                $scope.colMenu = false;
              }

              /**
              * @ngdoc property
              * @name enableColumnMenu
              * @propertyOf ui.grid.class:GridOptions.columnDef
              * @description if column menus are enabled, controls the column menus for this specific
              * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus
              * using this option. If gridOptions.enableColumnMenus === false then you get no column
              * menus irrespective of the value of this option ).  Defaults to true.
              *
              */
              /**
              * @ngdoc property
              * @name enableColumnMenus
              * @propertyOf ui.grid.class:GridOptions.columnDef
              * @description Override for column menus everywhere - if set to false then you get no
              * column menus.  Defaults to true.
              *
              */

              $scope.offAllEvents();

              if ($scope.sortable || $scope.colMenu) {
                $scope.onDownEvents();

                $scope.$on('$destroy', function () {
                  $scope.offAllEvents();
                });
              }
            };

/*
            $scope.$watch('col', function (n, o) {
              if (n !== o) {
                // See if the column's internal class has changed
                var newColClass = $scope.col.getColClass(false);
                if (newColClass !== initColClass) {
                  $elm.removeClass(initColClass);
                  $elm.addClass(newColClass);
                  initColClass = newColClass;
                }
              }
            });
*/
            updateHeaderOptions();

            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);

            $scope.$on( '$destroy', dataChangeDereg );

            $scope.handleClick = function(event) {
              // If the shift key is being held down, add this column to the sort
              var add = false;
              if (event.shiftKey) {
                add = true;
              }

              // Sort this column then rebuild the grid's rows
              uiGridCtrl.grid.sortColumn($scope.col, add)
                .then(function () {
                  if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
                  uiGridCtrl.grid.refresh();
                }).catch(angular.noop);
            };

            $scope.toggleMenu = function(event) {
              event.stopPropagation();

              // If the menu is already showing...
              if (uiGridCtrl.columnMenuScope.menuShown) {
                // ... and we're the column the menu is on...
                if (uiGridCtrl.columnMenuScope.col === $scope.col) {
                  // ... hide it
                  uiGridCtrl.columnMenuScope.hideMenu();
                }
                // ... and we're NOT the column the menu is on
                else {
                  // ... move the menu to our column
                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
                }
              }
              // If the menu is NOT showing
              else {
                // ... show it on our column
                uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
              }
            };
          }
        };
      }
    };

    return uiGridHeaderCell;
  }]);

})();
<commit_msg>Allow key down to toggle sort<commit_after>(function(){
  'use strict';

  angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',
  function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {
    // Do stuff after mouse has been down this many ms on the header cell
    var mousedownTimeout = 500;
    var changeModeTimeout = 500;    // length of time between a touch event and a mouse event being recognised again, and vice versa

    var uiGridHeaderCell = {
      priority: 0,
      scope: {
        col: '=',
        row: '=',
        renderIndex: '='
      },
      require: ['^uiGrid', '^uiGridRenderContainer'],
      replace: true,
      compile: function() {
        return {
          pre: function ($scope, $elm, $attrs) {
            var cellHeader = $compile($scope.col.headerCellTemplate)($scope);
            $elm.append(cellHeader);
          },

          post: function ($scope, $elm, $attrs, controllers) {
            var uiGridCtrl = controllers[0];
            var renderContainerCtrl = controllers[1];

            $scope.i18n = {
              headerCell: i18nService.getSafeText('headerCell'),
              sort: i18nService.getSafeText('sort')
            };
            $scope.isSortPriorityVisible = function() {
              //show sort priority if column is sorted and there is at least one other sorted column
              return angular.isNumber($scope.col.sort.priority) && $scope.grid.columns.some(function(element, index){
                  return angular.isNumber(element.sort.priority) && element !== $scope.col;
                });
            };
            $scope.getSortDirectionAriaLabel = function(){
              var col = $scope.col;
              //Trying to recreate this sort of thing but it was getting messy having it in the template.
              //Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending':'none')}}. {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}
              var sortDirectionText = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);
              var label = sortDirectionText;

              if ($scope.isSortPriorityVisible()) {
                label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + (col.sort.priority + 1);
              }
              return label;
            };

            $scope.grid = uiGridCtrl.grid;

            $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];

            var initColClass = $scope.col.getColClass(false);
            $elm.addClass(initColClass);

            // Hide the menu by default
            $scope.menuShown = false;

            // Put asc and desc sort directions in scope
            $scope.asc = uiGridConstants.ASC;
            $scope.desc = uiGridConstants.DESC;

            // Store a reference to menu element
            var $colMenu = angular.element( $elm[0].querySelectorAll('.ui-grid-header-cell-menu') );

            var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );

            // apply any headerCellClass
            var classAdded;
            var previousMouseX;

            // filter watchers
            var filterDeregisters = [];

            /*
             * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
             * Once we have a down event, we need to work out whether we have a click, a drag, or a
             * hold.  A click would sort the grid (if sortable).  A drag would be used by moveable, so
             * we ignore it.  A hold would open the menu.
             *
             * So, on down event, we put in place handlers for move and up events, and a timer.  If the
             * timer expires before we see a move or up, then we have a long press and hence a column menu open.
             * If the up happens before the timer, then we have a click, and we sort if the column is sortable.
             * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
             * will handle it.
             *
             * To deal with touch enabled devices that also have mice, we only create our handlers when
             * we get the down event, and we create the corresponding handlers - if we're touchstart then
             * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
             *
             * We also suppress the click action whilst this is happening - otherwise after the mouseup there
             * will be a click event and that can cause the column menu to close
             *
             */

            $scope.downFn = function( event ){
              event.stopPropagation();

              if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
                event = event.originalEvent;
              }

              // Don't show the menu if it's not the left button
              if (event.button && event.button !== 0) {
                return;
              }
              previousMouseX = event.pageX;

              $scope.mousedownStartTime = (new Date()).getTime();
              $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);

              $scope.mousedownTimeout.then(function () {
                if ( $scope.colMenu ) {
                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
                }
              }).catch(angular.noop);

              uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});

              $scope.offAllEvents();
              if ( event.type === 'touchstart'){
                $document.on('touchend', $scope.upFn);
                $document.on('touchmove', $scope.moveFn);
              } else if ( event.type === 'mousedown' ){
                $document.on('mouseup', $scope.upFn);
                $document.on('mousemove', $scope.moveFn);
              }
            };

            $scope.upFn = function( event ){
              event.stopPropagation();
              $timeout.cancel($scope.mousedownTimeout);
              $scope.offAllEvents();
              $scope.onDownEvents(event.type);

              var mousedownEndTime = (new Date()).getTime();
              var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;

              if (mousedownTime > mousedownTimeout) {
                // long click, handled above with mousedown
              }
              else {
                // short click
                if ( $scope.sortable ){
                  $scope.handleClick(event);
                }
              }
            };

            $scope.moveFn = function( event ){
              // Chrome is known to fire some bogus move events.
              var changeValue = event.pageX - previousMouseX;
              if ( changeValue === 0 ){ return; }

              // we're a move, so do nothing and leave for column move (if enabled) to take over
              $timeout.cancel($scope.mousedownTimeout);
              $scope.offAllEvents();
              $scope.onDownEvents(event.type);
            };

            $scope.clickFn = function ( event ){
              event.stopPropagation();
              $contentsElm.off('click', $scope.clickFn);
            };

            $scope.offAllEvents = function(){
              $contentsElm.off('touchstart', $scope.downFn);
              $contentsElm.off('mousedown', $scope.downFn);

              $document.off('touchend', $scope.upFn);
              $document.off('mouseup', $scope.upFn);

              $document.off('touchmove', $scope.moveFn);
              $document.off('mousemove', $scope.moveFn);

              $contentsElm.off('click', $scope.clickFn);
            };

            $scope.onDownEvents = function( type ){
              // If there is a previous event, then wait a while before
              // activating the other mode - i.e. if the last event was a touch event then
              // don't enable mouse events for a wee while (500ms or so)
              // Avoids problems with devices that emulate mouse events when you have touch events

              switch (type){
                case 'touchmove':
                case 'touchend':
                  $contentsElm.on('click', $scope.clickFn);
                  $contentsElm.on('touchstart', $scope.downFn);
                  $timeout(function(){
                    $contentsElm.on('mousedown', $scope.downFn);
                  }, changeModeTimeout);
                  break;
                case 'mousemove':
                case 'mouseup':
                  $contentsElm.on('click', $scope.clickFn);
                  $contentsElm.on('mousedown', $scope.downFn);
                  $timeout(function(){
                    $contentsElm.on('touchstart', $scope.downFn);
                  }, changeModeTimeout);
                  break;
                default:
                  $contentsElm.on('click', $scope.clickFn);
                  $contentsElm.on('touchstart', $scope.downFn);
                  $contentsElm.on('mousedown', $scope.downFn);
              }
            };

            var updateHeaderOptions = function( grid ){
              var contents = $elm;
              if ( classAdded ){
                contents.removeClass( classAdded );
                classAdded = null;
              }

              if (angular.isFunction($scope.col.headerCellClass)) {
                classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
              }
              else {
                classAdded = $scope.col.headerCellClass;
              }
              contents.addClass(classAdded);

              $timeout(function (){
                var rightMostContainer = $scope.grid.renderContainers['right'] ? $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
                $scope.isLastCol = ( $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ] );
              });

              // Figure out whether this column is sortable or not
              if ($scope.col.enableSorting) {
                $scope.sortable = true;
              }
              else {
                $scope.sortable = false;
              }

              // Figure out whether this column is filterable or not
              var oldFilterable = $scope.filterable;
              if (uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering) {
                $scope.filterable = true;
              }
              else {
                $scope.filterable = false;
              }

              if ( oldFilterable !== $scope.filterable){
                if ( typeof($scope.col.updateFilters) !== 'undefined' ){
                  $scope.col.updateFilters($scope.filterable);
                }

                // if column is filterable add a filter watcher
                if ($scope.filterable) {
                  $scope.col.filters.forEach( function(filter, i) {
                    filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
                      if (n !== o) {
                        uiGridCtrl.grid.api.core.raise.filterChanged();
                        uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
                        uiGridCtrl.grid.queueGridRefresh();
                      }
                    }));
                  });
                  $scope.$on('$destroy', function() {
                    filterDeregisters.forEach( function(filterDeregister) {
                      filterDeregister();
                    });
                  });
                } else {
                  filterDeregisters.forEach( function(filterDeregister) {
                    filterDeregister();
                  });
                }

              }

              // figure out whether we support column menus
              if ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&
                      $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false){
                $scope.colMenu = true;
              } else {
                $scope.colMenu = false;
              }

              /**
              * @ngdoc property
              * @name enableColumnMenu
              * @propertyOf ui.grid.class:GridOptions.columnDef
              * @description if column menus are enabled, controls the column menus for this specific
              * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus
              * using this option. If gridOptions.enableColumnMenus === false then you get no column
              * menus irrespective of the value of this option ).  Defaults to true.
              *
              */
              /**
              * @ngdoc property
              * @name enableColumnMenus
              * @propertyOf ui.grid.class:GridOptions.columnDef
              * @description Override for column menus everywhere - if set to false then you get no
              * column menus.  Defaults to true.
              *
              */

              $scope.offAllEvents();

              if ($scope.sortable || $scope.colMenu) {
                $scope.onDownEvents();

                $scope.$on('$destroy', function () {
                  $scope.offAllEvents();
                });
              }
            };

/*
            $scope.$watch('col', function (n, o) {
              if (n !== o) {
                // See if the column's internal class has changed
                var newColClass = $scope.col.getColClass(false);
                if (newColClass !== initColClass) {
                  $elm.removeClass(initColClass);
                  $elm.addClass(newColClass);
                  initColClass = newColClass;
                }
              }
            });
*/
            updateHeaderOptions();

            // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
            var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);

            $scope.$on( '$destroy', dataChangeDereg );

            function applySort(add) {
              // Sort this column then rebuild the grid's rows
              uiGridCtrl.grid.sortColumn($scope.col, add)
                .then(function () {
                  if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
                  uiGridCtrl.grid.refresh();
                }).catch(angular.noop);
            }

            $scope.handleClick = function(event) {
              // If the shift key is being held down, add this column to the sort
              applySort(event.shiftKey);
            };

            $scope.handleKeyDown = function(event) {
              if (event.keyCode === 32 || event.keyCode === 13) {
                applySort(event.shiftKey);
              }
            };

            $scope.toggleMenu = function(event) {
              event.stopPropagation();

              // If the menu is already showing...
              if (uiGridCtrl.columnMenuScope.menuShown) {
                // ... and we're the column the menu is on...
                if (uiGridCtrl.columnMenuScope.col === $scope.col) {
                  // ... hide it
                  uiGridCtrl.columnMenuScope.hideMenu();
                }
                // ... and we're NOT the column the menu is on
                else {
                  // ... move the menu to our column
                  uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
                }
              }
              // If the menu is NOT showing
              else {
                // ... show it on our column
                uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
              }
            };
          }
        };
      }
    };

    return uiGridHeaderCell;
  }]);

})();
<|endoftext|>


<commit_before>/* @flow */
import reaction from 'dacho';

/**
 * @type {Object}
 */
const storyActionTypes: {[type: string]: string} = reaction([
  'FETCH_STORIES'
], 'STORY/');

export default storyActionTypes;
<commit_msg>feat(constants): storyActionTypesにRECEIVE_STORIESを追加<commit_after>/* @flow */
import reaction from 'dacho';

/**
 * @type {Object}
 */
const storyActionTypes: {[type: string]: string} = reaction([
  'FETCH_STORIES',
  'RECEIVE_STORIES'
], 'STORY/');

export default storyActionTypes;
<|endoftext|>


<commit_before>/*global defineSuite*/
defineSuite([
         'Scene/Polygon',
         '../Specs/createContext',
         '../Specs/destroyContext',
         '../Specs/sceneState',
         '../Specs/pick',
         'Core/Cartesian3',
         'Core/Cartographic3',
         'Core/Ellipsoid',
         'Core/Extent',
         'Core/Matrix4',
         'Core/Math',
         'Renderer/BufferUsage'
     ], function(
         Polygon,
         createContext,
         destroyContext,
         sceneState,
         pick,
         Cartesian3,
         Cartographic3,
         Ellipsoid,
         Extent,
         Matrix4,
         CesiumMath,
         BufferUsage) {
    "use strict";
    /*global it,expect,beforeEach,afterEach*/

    var context;
    var polygon;
    var us;

    beforeEach(function() {
        context = createContext();
        polygon = new Polygon();

        var camera = {
            eye : new Cartesian3(1.02, 0.0, 0.0),
            target : Cartesian3.ZERO,
            up : Cartesian3.UNIT_Z
        };
        us = context.getUniformState();
        us.setView(Matrix4.createLookAt(camera.eye, camera.target, camera.up));
        us.setProjection(Matrix4.createPerspectiveFieldOfView(CesiumMath.toRadians(60.0), 1.0, 0.01, 10.0));
    });

    afterEach(function() {
        polygon = polygon && polygon.destroy();
        us = null;

        destroyContext(context);
    });

    it("gets default show", function() {
        expect(polygon.show).toEqual(true);
    });

    it("sets positions", function() {
        var positions = [
                         new Cartesian3(1.0, 2.0, 3.0),
                         new Cartesian3(4.0, 5.0, 6.0),
                         new Cartesian3(7.0, 8.0, 9.0)
                        ];

        expect(polygon.getPositions()).not.toBeDefined();

        polygon.setPositions(positions);
        expect(polygon.getPositions()).toEqualArray(positions);
    });

    it("configures extent", function() {
        var extent = {
                         north : CesiumMath.toRadians(10.0),
                         south : 0.0,
                         east : CesiumMath.toRadians(10.0),
                         west : 0.0
                     };

        polygon.configureExtent(extent);
        expect(polygon.getPositions()).not.toBeDefined();

    });

    it("gets the default color", function() {
        expect(polygon.material.color).toEqualProperties({
            red : 1.0,
            green : 1.0,
            blue : 0.0,
            alpha : 0.5
        });
    });

    it("gets default buffer usage", function() {
        expect(polygon.bufferUsage).toEqual(BufferUsage.STATIC_DRAW);
    });

    it("has a default ellipsoid", function() {
        expect(polygon.ellipsoid).toEqual(Ellipsoid.WGS84);
    });

    it("gets the default granularity", function() {
        expect(polygon.granularity).toEqual(CesiumMath.toRadians(1.0));
    });

    it("renders", function() {
        // This test fails in Chrome if a breakpoint is set inside this function.  Strange.

        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0)))
                             ]);
        polygon.material.color = {
            red : 1.0,
            green : 0.0,
            blue : 0.0,
            alpha : 1.0
        };

        context.clear();
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);

        polygon.update(context, sceneState);
        polygon.render(context, us);
        expect(context.readPixels()).not.toEqualArray([0, 0, 0, 0]);
    });

    it("renders extent", function() {
        // This test fails in Chrome if a breakpoint is set inside this function.  Strange.

        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.configureExtent(new Extent(
            0.0,
            0.0,
            CesiumMath.toRadians(10.0),
            CesiumMath.toRadians(10.0)
        ));
        polygon.material.color = {
            red : 1.0,
            green : 0.0,
            blue : 0.0,
            alpha : 1.0
        };

        context.clear();
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);

        polygon.update(context, sceneState);
        polygon.render(context, us);
        expect(context.readPixels()).not.toEqualArray([0, 0, 0, 0]);
    });

    it("doesn't renders", function() {
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0)))
                             ]);
        polygon.material.color = {
            red : 1.0,
            green : 0.0,
            blue : 0.0,
            alpha : 1.0
        };
        polygon.show = false;

        context.clear();
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);

        polygon.update(context, sceneState);
        polygon.render(context, us);
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);
    });

    it("is picked", function() {
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0)))
                             ]);

        polygon.update(context, sceneState);

        var pickedObject = pick(context, polygon, 0, 0);
        expect(pickedObject).toEqual(polygon);
    });

    it("is not picked", function() {
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0)))
                             ]);
        polygon.show = false;

        polygon.update(context, sceneState);

        var pickedObject = pick(context, polygon, 0, 0);
        expect(pickedObject).not.toBeDefined();
    });
});
<commit_msg>Change missed test to use Extent.<commit_after>/*global defineSuite*/
defineSuite([
         'Scene/Polygon',
         '../Specs/createContext',
         '../Specs/destroyContext',
         '../Specs/sceneState',
         '../Specs/pick',
         'Core/Cartesian3',
         'Core/Cartographic3',
         'Core/Ellipsoid',
         'Core/Extent',
         'Core/Matrix4',
         'Core/Math',
         'Renderer/BufferUsage'
     ], function(
         Polygon,
         createContext,
         destroyContext,
         sceneState,
         pick,
         Cartesian3,
         Cartographic3,
         Ellipsoid,
         Extent,
         Matrix4,
         CesiumMath,
         BufferUsage) {
    "use strict";
    /*global it,expect,beforeEach,afterEach*/

    var context;
    var polygon;
    var us;

    beforeEach(function() {
        context = createContext();
        polygon = new Polygon();

        var camera = {
            eye : new Cartesian3(1.02, 0.0, 0.0),
            target : Cartesian3.ZERO,
            up : Cartesian3.UNIT_Z
        };
        us = context.getUniformState();
        us.setView(Matrix4.createLookAt(camera.eye, camera.target, camera.up));
        us.setProjection(Matrix4.createPerspectiveFieldOfView(CesiumMath.toRadians(60.0), 1.0, 0.01, 10.0));
    });

    afterEach(function() {
        polygon = polygon && polygon.destroy();
        us = null;

        destroyContext(context);
    });

    it("gets default show", function() {
        expect(polygon.show).toEqual(true);
    });

    it("sets positions", function() {
        var positions = [
                         new Cartesian3(1.0, 2.0, 3.0),
                         new Cartesian3(4.0, 5.0, 6.0),
                         new Cartesian3(7.0, 8.0, 9.0)
                        ];

        expect(polygon.getPositions()).not.toBeDefined();

        polygon.setPositions(positions);
        expect(polygon.getPositions()).toEqualArray(positions);
    });

    it("configures extent", function() {
        var extent = new Extent(
            0.0,
            0.0,
            CesiumMath.toRadians(10.0),
            CesiumMath.toRadians(10.0)
        );

        polygon.configureExtent(extent);
        expect(polygon.getPositions()).not.toBeDefined();

    });

    it("gets the default color", function() {
        expect(polygon.material.color).toEqualProperties({
            red : 1.0,
            green : 1.0,
            blue : 0.0,
            alpha : 0.5
        });
    });

    it("gets default buffer usage", function() {
        expect(polygon.bufferUsage).toEqual(BufferUsage.STATIC_DRAW);
    });

    it("has a default ellipsoid", function() {
        expect(polygon.ellipsoid).toEqual(Ellipsoid.WGS84);
    });

    it("gets the default granularity", function() {
        expect(polygon.granularity).toEqual(CesiumMath.toRadians(1.0));
    });

    it("renders", function() {
        // This test fails in Chrome if a breakpoint is set inside this function.  Strange.

        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0)))
                             ]);
        polygon.material.color = {
            red : 1.0,
            green : 0.0,
            blue : 0.0,
            alpha : 1.0
        };

        context.clear();
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);

        polygon.update(context, sceneState);
        polygon.render(context, us);
        expect(context.readPixels()).not.toEqualArray([0, 0, 0, 0]);
    });

    it("renders extent", function() {
        // This test fails in Chrome if a breakpoint is set inside this function.  Strange.

        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.configureExtent(new Extent(
            0.0,
            0.0,
            CesiumMath.toRadians(10.0),
            CesiumMath.toRadians(10.0)
        ));
        polygon.material.color = {
            red : 1.0,
            green : 0.0,
            blue : 0.0,
            alpha : 1.0
        };

        context.clear();
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);

        polygon.update(context, sceneState);
        polygon.render(context, us);
        expect(context.readPixels()).not.toEqualArray([0, 0, 0, 0]);
    });

    it("doesn't renders", function() {
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0)))
                             ]);
        polygon.material.color = {
            red : 1.0,
            green : 0.0,
            blue : 0.0,
            alpha : 1.0
        };
        polygon.show = false;

        context.clear();
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);

        polygon.update(context, sceneState);
        polygon.render(context, us);
        expect(context.readPixels()).toEqualArray([0, 0, 0, 0]);
    });

    it("is picked", function() {
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0)))
                             ]);

        polygon.update(context, sceneState);

        var pickedObject = pick(context, polygon, 0, 0);
        expect(pickedObject).toEqual(polygon);
    });

    it("is not picked", function() {
        var ellipsoid = Ellipsoid.UNIT_SPHERE;
        polygon.ellipsoid = ellipsoid;
        polygon.granularity = CesiumMath.toRadians(20.0);
        polygon.setPositions([
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, -50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(50.0, 50.0, 0.0))),
                              ellipsoid.toCartesian(CesiumMath.cartographic3ToRadians(new Cartographic3(-50.0, 50.0, 0.0)))
                             ]);
        polygon.show = false;

        polygon.update(context, sceneState);

        var pickedObject = pick(context, polygon, 0, 0);
        expect(pickedObject).not.toBeDefined();
    });
});
<|endoftext|>