<commit_before>(function($)
{
	function Settings(configurator)
	{
		this.configurator = configurator

		MatrixGroup.patchMethod(configurator, this, 'addBlockType')
		MatrixGroup.patchMethod(configurator, this, 'getBlockTypeSettingsModal')
	}

	Settings.prototype.addBlockType = function(args, output)
	{
		var configurator = this.configurator
		var modal = configurator.blockTypeSettingsModal

		MatrixGroup.patchMethod(modal, {onSubmit: function()
		{
			var id = 'new' + configurator.totalNewBlockTypes
			var blockType = configurator.blockTypes[id]
			var isGroup = modal.$groupInput.is(':checked')

			blockType.$item.toggleClass('matrixgroup', isGroup)

		}}, 'onSubmit')

		return output
	}

	Settings.prototype.getBlockTypeSettingsModal = function(args, output)
	{
		var configurator = this.configurator
		var modal = configurator.blockTypeSettingsModal

		if(!modal.$groupField)
		{
			modal.$groupField = $('
').insertAfter(modal.$handleField)
			modal.$groupInput = $('<input type="checkbox" value="1" id="new-block-type-group" class="checkbox">').appendTo(modal.$groupField)
			modal.$groupLabel = $('' + Craft.t('This is a group block type') + '').appendTo(modal.$groupField)
		}

		return output
	}

	MatrixGroup.onPropertySet(Craft, 'MatrixConfigurator', function()
	{
		MatrixGroup.Settings = Settings
		MatrixGroup.patchClass(Craft.MatrixConfigurator, MatrixGroup.Settings, true)
	})

})(jQuery)
<commit_msg>Group hidden input added, updates on edit<commit_after>(function($)
{
	function Settings(configurator)
	{
		this.configurator = configurator

		MatrixGroup.patchMethod(configurator, this, 'addBlockType')
		MatrixGroup.patchMethod(configurator, this, 'getBlockTypeSettingsModal')
	}

	Settings.prototype.addBlockType = function(args, output)
	{
		var configurator = this.configurator
		var modal = configurator.blockTypeSettingsModal

		MatrixGroup.patchMethod(modal, {onSubmit: function()
		{
			var id = 'new' + configurator.totalNewBlockTypes
			var blockType = configurator.blockTypes[id]
			var isGroup = modal.$groupInput.is(':checked')
			var inputName = 'types[Matrix][blockTypes][' + id + '][group]'

			blockType.$groupHiddenInput = $('<input type="hidden" name="' + inputName + '">').appendTo(blockType.$item)

			blockType.$groupHiddenInput.val(isGroup)
			blockType.$item.toggleClass('matrixgroup', isGroup)

			MatrixGroup.patchMethod(blockType, {applySettings: function()
			{
				var isGroup = modal.$groupInput.is(':checked')

				blockType.$groupHiddenInput.val(isGroup)
				blockType.$item.toggleClass('matrixgroup', isGroup)

			}}, 'applySettings')

		}}, 'onSubmit')

		return output
	}

	Settings.prototype.getBlockTypeSettingsModal = function(args, output)
	{
		var configurator = this.configurator
		var modal = configurator.blockTypeSettingsModal

		if(!modal.$groupField)
		{
			modal.$groupField = $('
').insertAfter(modal.$handleField)
			modal.$groupInput = $('<input type="checkbox" value="1" id="new-block-type-group" class="checkbox">').appendTo(modal.$groupField)
			modal.$groupLabel = $('' + Craft.t('This is a group block type') + '').appendTo(modal.$groupField)
		}

		return output
	}

	MatrixGroup.onPropertySet(Craft, 'MatrixConfigurator', function()
	{
		MatrixGroup.Settings = Settings
		MatrixGroup.patchClass(Craft.MatrixConfigurator, MatrixGroup.Settings, true)
	})

})(jQuery)
<|endoftext|>


<commit_before>/*
 * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
 * See http://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript for formating conventions
 */
( function( mw, $ ){ "use strict";

window['mwePlayerId'];

mw.EmbedPlayerYouTube = {

	//test comment for testing pull request

	// Instance name:
	instanceOf : 'youtube',

	bindPostfix: '.YouTube',
	//current playhead time
	time : 0,
	//current entry duration
	duration : 0,
	// A flag to store if the player has already been embed or not
	playerEmbedFlag: false,
	//Flag holdinng end state
	hasEnded: false,

	//the youtube entry id
	youtubeEntryId : "",

	//the youtube preFix
	//TODO grab from a configuration
	youtubePreFix : "//www.youtube.com/apiplayer?video_id=",
	youtubeProtocol : "http:",

	// List of supported features:
	supports : {
		'playHead' : true,
		'pause' : true,
		'stop' : true,
		'timeDisplay' : true,
		'volumeControl' : true,
		'overlays' : true,
		'fullscreen' : true
	},

	init: function(){
		var _this = this;
		this.registerGlobalCallbacks();
	},
	onPlayerStateChange : function (event)
	{
		//delegate to window function
		window['onPlayerStateChange'](event);
	},

	registerGlobalCallbacks: function(){
		window['onPlayerStateChange'] = function( event ){
			var _this = $('#' + window['mwePlayerId'])[0];
			// clean up
			if( event.data || event.data == 0 || event.data ){
				event = event.data;
			}
			mw.log(event , 4);
			var stateName;
			// move to other method
			switch( event ){
				case -1:
					stateName = "unstarted";
				  break;
				case 0:
				case "0":
					stateName = "ended";
					this.hasEnded = true;
				  break;
				case 1:
					//hide the poster
					$(".playerPoster").hide();
					$('.blackBoxHide').hide();
					stateName = "playing";
					//$(this).hide();
					// update duraiton
					_this.setDuration();
					// trigger the seeked event only if this is seek and not in play
					if(_this.seeking){
						_this.seeking = false;
						$( _this ).trigger( 'seeked' );
						// update the playhead status
						_this.updatePlayheadStatus();
					}
				  break;
				case 2:
					stateName = "paused";
					_this.parent_pause();
				  break;
				case 3:
					stateName = "buffering";
				  break;
				case 4:
					stateName = "unbuffering";
					break;
				case 5:
					stateName = "video cued";
				  break;
			}
			if(typeof(event) === 'number' || event == 0 )
				mw.log("onPlayerStateChange  : "+stateName+"  :  " + event , 1 );
			else
				mw.log("onPlayerStateChange  :: "+stateName+"  ::  "  + event.data , 1 );
		};
		window['onError'] = function( event ){
			var errorMessage;
			switch( event ){
			case 2:
				errorMessage = "The request contains an invalid parameter value.";
				break;
			case 100:
				errorMessage = "The video requested was not found";
				break;
			case 101:
			case 150:
				errorMessage = "The owner of the requested video does not allow it to be played in embedded players";
				break;
			}
			//alert(errorMessage);
		};
		//YOUTUBE IFRAME PLAYER READY (Not the Iframe - the player itself)
		window['onIframePlayerReady'] = function( event ){

			//autoplay
			mw.log(mw.getConfig('autoPlay'),4);
			$('#pid_kaltura_player').after('

');
			window['iframePlayer'] = event.target;

			//TODO grab autoplay from configuration and to a

//			var _this = this;
//			if(true){
//				setTimeout(function(){
//					console.log(_this.mw.EmbedPlayerYouTube);
//					} , 1000);
//			}
		};
		// YOUTUBE FLASH PLAYER READY
		window['onYouTubePlayerReady'] = function( playerIdStr ){
			$('#pid_kaltura_player').after('

');
			mw.log("Flash ready" , 5);
			//playerId = playerIdStr;
			//$( '#' + a ).hide();
			//console.log(this.getPlayerElement());
			//var embedPlayer = $('#' + playerIdStr.replace( 'pid_', '' ) )[0];
			//embedPlayer.addBindings();
			var flashPlayer = $( '#' + playerIdStr )[0];
			flashPlayer.addEventListener("onStateChange", "onPlayerStateChange");
			flashPlayer.addEventListener("onError", "onError");
		};
		// YOUTUBE IFRAME READY
		window['onYouTubeIframeAPIReady'] = function( playerIdStr ){
			//move to the other scope
			var embedPlayer = $('#' + window["pid"].replace( 'pid_', '' ) )[0];
			embedPlayer.addBindings();
			var playerVars;
			if(window['KeyValueParams'])
			{
				playerVars = {
						controls: 0,
						iv_load_policy:3,
						showinfo:'0'
				};
				var kevarsArray = window['KeyValueParams'].split("&");
				for(var i=0;i<kevarsArray.length;i++){
					var kv = kevarsArray[i].split("=");
					playerVars[kv[0]] = kv[1];
				}
			}else{
				playerVars = {
					controls: '0',
					iv_load_policy:3,
					showinfo:'0'
				};
			}

			mw.log(playerVars);

			embedPlayer.playerElement = new YT.Player(pid,
				{
					height: '50%',
					width: '50%',
					videoId: window["youtubeEntryId"],
					playerVars: playerVars,
					events: {
						'onReady': onIframePlayerReady,
						'onError': onError,
						'onStateChange': onPlayerStateChange
					}
			});
		};
	},

	/*
	 * Write the Embed html to the target
	 */
	embedPlayerHTML : function(){
		if( this.playerEmbedFlag ){
			return ;
		}
		window['mwePlayerId'] = this.id;
		//handle fetching the youtubeId
		var metadata = this.evaluate('{mediaProxy.entryMetadata}');
		var entry = this.evaluate('{mediaProxy.entry}');
		//look for referenceId and then for custom data field YoutubeId
		if(entry.referenceId)
			this.youtubeEntryId = entry.referenceId;
		if(metadata.YoutubeId)
			this.youtubeEntryId = metadata.YoutubeId;

		if(this.youtubeEntryId.indexOf('http') > -1 || this.youtubeEntryId.indexOf('youtube') > -1  ){
			//found a full path - parse the entryId from it:
			var arr = this.youtubeEntryId.split("v=");
			var newEntryId = arr[1];
			if (newEntryId.indexOf("#") > -1)
				newEntryId = newEntryId.split("#")[0];
			if (newEntryId.indexOf("&") > -1)
				newEntryId = newEntryId.split("&")[0];
			this.youtubeEntryId = newEntryId;
		}

		if(metadata.KeyValueParams){
			window['KeyValueParams'] = metadata.KeyValueParams;
		}
		window['pid'] = this.pid;

		if(mw.getConfig("forceYoutubeEntry"))
		{
			this.youtubeEntryId=mw.getConfig("forceYoutubeEntry");
		}
		window["youtubeEntryId"] = this.youtubeEntryId;

		this.playerEmbedFlag = true;
		this.youtubeProtocol = location.protocol;
		this.youtubePreFix = this.youtubeProtocol+this.youtubePreFix;

		if( this.supportsFlash() && mw.getConfig("forceIframe") != 1 ){
			// embed chromeless flash
			if(window['KeyValueParams']){
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid +
				"&amp&" + window['KeyValueParams'];
			}else{
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid ;
			}

			$('.persistentNativePlayer').replaceWith(
					'<object type="application/x-shockwave-flash" id="' + this.pid + '"' +
				'AllowScriptAccess="always" ' +
				'data=' + dataUrl + " " +
				'width="100%" height="100%">' +
				'<param name="allowScriptAccess" value="always">' +
				'<param name="wmode" value="opaque">' +
				'<param name="bgcolor" value="#000000">' +
				'</object>');

		} else {
			// embed iframe ( native skin in iOS )
			$('.persistentNativePlayer').replaceWith('

');
			var tag = document.createElement('script');
			tag.src = "//www.youtube.com/iframe_api";
			var firstScriptTag = document.getElementsByTagName('script')[0];
			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
		}
	},
	setDuration: function(){

		//set duration only once
		if (this.duration == 0 && this.getPlayerElement().getDuration()){
			this.duration = this.getPlayerElement().getDuration();
			$(this).trigger('durationchange');
		}
	},
	onPlayerReady : function (event){
	},
	addBindings: function(){

	},
	supportsVolumeControl: function(){
		// if ipad no.
		return true;
	},
	getYouTubeId: function(){
		return this.getSrc().split('?')[1];
	},
	/**
	 * If the browser supports flash
	 * @return {boolean} true or false if flash > 10 is supported.
	 */
	supportsFlash: function(){
		if( mw.getConfig('EmbedPlayer.DisableHTML5FlashFallback' ) ){
			return false;
		}
		var version = this.getFlashVersion().split(',').shift();
		if( version < 10 ){
			return false;
		} else {
			return true;
		}
	},
	/**
	 * Checks for flash version
	 * @return {string} flash version string
	 */
	getFlashVersion: function(){
		// navigator browsers:
		if (navigator.plugins && navigator.plugins.length){
			try {
				if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
					return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
				}
			} catch(e){}
		}
		// IE
		try {
			try {
				if( typeof ActiveXObject != 'undefined' ){
					// avoid fp6 minor version lookup issues
					// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
					var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
					try {
						axo.AllowScriptAccess = 'always';
					} catch(e){
						return '6,0,0';
					}
				}
			} catch(e){}
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
		} catch(e){}
		return '0,0,0';
	 },
	/**
	 * javascript run post player embedding
	 */
	postEmbedActions : function(){
	},

	/**
	 * Bind a Player Function,
	 *
	 * Build a global callback to bind to "this" player instance:
	 *
	 * @param {String}
	 *            flash binding name
	 * @param {String}
	 *            function callback name
	 */
	bindPlayerFunction : function(bindName, methodName){
	},

	/**
	 * play method calls parent_play to update the interface
	 */
	play: function(){
		var _this = this;

		if(this.hasEnded){
				//handle replay
			}
		if( this.parent_play() ){
			if(_this.getPlayerElement())
			{
				_this.getPlayerElement().playVideo();
			}
		}
		this.monitor();
	},

	/**
	 * pause method calls parent_pause to update the interface
	 */
	pause: function(){
		var yt = this.getPlayerElement();
		yt.pauseVideo();
		this.parent_pause();
	},
	/**
	 * playerSwitchSource switches the player source working around a few bugs in browsers
	 *
	 * @param {object}
	 *            source Video Source object to switch to.
	 * @param {function}
	 *            switchCallback Function to call once the source has been switched
	 * @param {function}
	 *            doneCallback Function to call once the clip has completed playback
	 */
	playerSwitchSource: function( source, switchCallback, doneCallback ){

	},

	/**
	 * Issues a seek to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage of total stream length to seek to
	 */
	seek : function( percentage ){
		this.seeking = true;
		$( this ).trigger( 'seeking' );
		var yt = this.getPlayerElement();
		yt.seekTo( yt.getDuration() * percentage );
		this.controlBuilder.onSeek();
		//TODO check if there is a cleaner way to get the playback

	},

	/**
	 * Issues a volume update to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage to update volume to
	 */
	setPlayerElementVolume : function(percentage){
//		if ( this.getPlayerElement() && this.playerElement.sendNotification ){
//			this.playerElement.sendNotification('changeVolume', percentage);
//		}
		var yt = this.getPlayerElement();
		yt.setVolume(percentage*100);
	},

	/**
	 * function called by flash at set interval to update the playhead.
	 */
	onUpdatePlayhead : function( playheadValue ){
		this.time = playheadValue;
	},

	/**
	 * function called by flash when the total media size changes
	 */
	onBytesTotalChange : function(data, id){
		this.bytesTotal = data.newValue;
	},
	/**
	 * Get the embed player time
	 */
	getPlayerElementTime : function(){
		// update currentTime
		return this.getPlayerElement().getCurrentTime();
	},

	/**
	 * Get the embed fla object player Element
	 */
	getPlayerElement : function(){

		//IFRAME
		if( window['iframePlayer'] )
			return  window['iframePlayer']
		//Flash
		return $('#' + this.pid)[0];
	}
};

} )( mediaWiki, jQuery );
<commit_msg>hide the player container so that youtube click through work<commit_after>/*
 * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
 * See http://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript for formating conventions
 */
( function( mw, $ ){ "use strict";

window['mwePlayerId'];

mw.EmbedPlayerYouTube = {

	//test comment for testing pull request

	// Instance name:
	instanceOf : 'youtube',

	bindPostfix: '.YouTube',
	//current playhead time
	time : 0,
	//current entry duration
	duration : 0,
	// A flag to store if the player has already been embed or not
	playerEmbedFlag: false,
	//Flag holdinng end state
	hasEnded: false,

	//the youtube entry id
	youtubeEntryId : "",

	//the youtube preFix
	//TODO grab from a configuration
	youtubePreFix : "//www.youtube.com/apiplayer?video_id=",
	youtubeProtocol : "http:",

	// List of supported features:
	supports : {
		'playHead' : true,
		'pause' : true,
		'stop' : true,
		'timeDisplay' : true,
		'volumeControl' : true,
		'overlays' : true,
		'fullscreen' : true
	},

	init: function(){
		var _this = this;
		this.registerGlobalCallbacks();
	},
	onPlayerStateChange : function (event)
	{
		//delegate to window function
		window['onPlayerStateChange'](event);
	},

	registerGlobalCallbacks: function(){
		window['onPlayerStateChange'] = function( event ){
			var _this = $('#' + window['mwePlayerId'])[0];
			// clean up
			if( event.data || event.data == 0 || event.data ){
				event = event.data;
			}
			mw.log(event , 4);
			var stateName;
			// move to other method
			switch( event ){
				case -1:
					stateName = "unstarted";
				  break;
				case 0:
				case "0":
					stateName = "ended";
					this.hasEnded = true;
				  break;
				case 1:
					// hide the player container so that youtube click through work
					$('.mwEmbedPlayer').hide();
					//hide the poster
					$(".playerPoster").hide();
					$('.blackBoxHide').hide();
					stateName = "playing";
					//$(this).hide();
					// update duraiton
					_this.setDuration();
					// trigger the seeked event only if this is seek and not in play
					if(_this.seeking){
						_this.seeking = false;
						$( _this ).trigger( 'seeked' );
						// update the playhead status
						_this.updatePlayheadStatus();
					}
				  break;
				case 2:
					stateName = "paused";
					_this.parent_pause();
				  break;
				case 3:
					stateName = "buffering";
				  break;
				case 4:
					stateName = "unbuffering";
					break;
				case 5:
					stateName = "video cued";
				  break;
			}
			if(typeof(event) === 'number' || event == 0 )
				mw.log("onPlayerStateChange  : "+stateName+"  :  " + event , 1 );
			else
				mw.log("onPlayerStateChange  :: "+stateName+"  ::  "  + event.data , 1 );
		};
		window['onError'] = function( event ){
			var errorMessage;
			switch( event ){
			case 2:
				errorMessage = "The request contains an invalid parameter value.";
				break;
			case 100:
				errorMessage = "The video requested was not found";
				break;
			case 101:
			case 150:
				errorMessage = "The owner of the requested video does not allow it to be played in embedded players";
				break;
			}
			//alert(errorMessage);
		};
		//YOUTUBE IFRAME PLAYER READY (Not the Iframe - the player itself)
		window['onIframePlayerReady'] = function( event ){
			//autoplay
			mw.log(mw.getConfig('autoPlay'),4);
			$('#pid_kaltura_player').after('

');
			window['iframePlayer'] = event.target;

			//TODO grab autoplay from configuration and to a

//			var _this = this;
//			if(true){
//				setTimeout(function(){
//					console.log(_this.mw.EmbedPlayerYouTube);
//					} , 1000);
//			}
		};
		// YOUTUBE FLASH PLAYER READY
		window['onYouTubePlayerReady'] = function( playerIdStr ){
			$('#pid_kaltura_player').after('

');
			mw.log("Flash ready" , 5);
			//playerId = playerIdStr;
			//$( '#' + a ).hide();
			//console.log(this.getPlayerElement());
			//var embedPlayer = $('#' + playerIdStr.replace( 'pid_', '' ) )[0];
			//embedPlayer.addBindings();
			var flashPlayer = $( '#' + playerIdStr )[0];
			flashPlayer.addEventListener("onStateChange", "onPlayerStateChange");
			flashPlayer.addEventListener("onError", "onError");
		};
		// YOUTUBE IFRAME READY
		window['onYouTubeIframeAPIReady'] = function( playerIdStr ){
			//move to the other scope
			var embedPlayer = $('#' + window["pid"].replace( 'pid_', '' ) )[0];
			embedPlayer.addBindings();
			var playerVars;
			if(window['KeyValueParams'])
			{
				playerVars = {
						controls: 0,
						iv_load_policy:3,
						showinfo:'0'
				};
				var kevarsArray = window['KeyValueParams'].split("&");
				for(var i=0;i<kevarsArray.length;i++){
					var kv = kevarsArray[i].split("=");
					playerVars[kv[0]] = kv[1];
				}
			}else{
				playerVars = {
					controls: '0',
					iv_load_policy:3,
					showinfo:'0'
				};
			}

			mw.log(playerVars);

			embedPlayer.playerElement = new YT.Player(pid,
				{
					height: '50%',
					width: '50%',
					videoId: window["youtubeEntryId"],
					playerVars: playerVars,
					events: {
						'onReady': onIframePlayerReady,
						'onError': onError,
						'onStateChange': onPlayerStateChange
					}
			});
		};
	},

	/*
	 * Write the Embed html to the target
	 */
	embedPlayerHTML : function(){
		if( this.playerEmbedFlag ){
			return ;
		}
		window['mwePlayerId'] = this.id;
		//handle fetching the youtubeId
		var metadata = this.evaluate('{mediaProxy.entryMetadata}');
		var entry = this.evaluate('{mediaProxy.entry}');
		//look for referenceId and then for custom data field YoutubeId
		if(entry.referenceId)
			this.youtubeEntryId = entry.referenceId;
		if(metadata.YoutubeId)
			this.youtubeEntryId = metadata.YoutubeId;

		if(this.youtubeEntryId.indexOf('http') > -1 || this.youtubeEntryId.indexOf('youtube') > -1  ){
			//found a full path - parse the entryId from it:
			var arr = this.youtubeEntryId.split("v=");
			var newEntryId = arr[1];
			if (newEntryId.indexOf("#") > -1)
				newEntryId = newEntryId.split("#")[0];
			if (newEntryId.indexOf("&") > -1)
				newEntryId = newEntryId.split("&")[0];
			this.youtubeEntryId = newEntryId;
		}

		if(metadata.KeyValueParams){
			window['KeyValueParams'] = metadata.KeyValueParams;
		}
		window['pid'] = this.pid;

		if(mw.getConfig("forceYoutubeEntry"))
		{
			this.youtubeEntryId=mw.getConfig("forceYoutubeEntry");
		}
		window["youtubeEntryId"] = this.youtubeEntryId;

		this.playerEmbedFlag = true;
		this.youtubeProtocol = location.protocol;
		this.youtubePreFix = this.youtubeProtocol+this.youtubePreFix;

		if( this.supportsFlash() && mw.getConfig("forceIframe") != 1 ){
			// embed chromeless flash
			if(window['KeyValueParams']){
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid +
				"&amp&" + window['KeyValueParams'];
			}else{
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid ;
			}

			$('.persistentNativePlayer').replaceWith(
					'<object type="application/x-shockwave-flash" id="' + this.pid + '"' +
				'AllowScriptAccess="always" ' +
				'data=' + dataUrl + " " +
				'width="100%" height="100%">' +
				'<param name="allowScriptAccess" value="always">' +
				'<param name="wmode" value="opaque">' +
				'<param name="bgcolor" value="#000000">' +
				'</object>');

		} else {
			// embed iframe ( native skin in iOS )
			$('.persistentNativePlayer').replaceWith('

');
			var tag = document.createElement('script');
			tag.src = "//www.youtube.com/iframe_api";
			var firstScriptTag = document.getElementsByTagName('script')[0];
			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
		}
	},
	setDuration: function(){

		//set duration only once
		if (this.duration == 0 && this.getPlayerElement().getDuration()){
			this.duration = this.getPlayerElement().getDuration();
			$(this).trigger('durationchange');
		}
	},
	onPlayerReady : function (event){
	},
	addBindings: function(){

	},
	supportsVolumeControl: function(){
		// if ipad no.
		return true;
	},
	getYouTubeId: function(){
		return this.getSrc().split('?')[1];
	},
	/**
	 * If the browser supports flash
	 * @return {boolean} true or false if flash > 10 is supported.
	 */
	supportsFlash: function(){
		if( mw.getConfig('EmbedPlayer.DisableHTML5FlashFallback' ) ){
			return false;
		}
		var version = this.getFlashVersion().split(',').shift();
		if( version < 10 ){
			return false;
		} else {
			return true;
		}
	},
	/**
	 * Checks for flash version
	 * @return {string} flash version string
	 */
	getFlashVersion: function(){
		// navigator browsers:
		if (navigator.plugins && navigator.plugins.length){
			try {
				if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
					return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
				}
			} catch(e){}
		}
		// IE
		try {
			try {
				if( typeof ActiveXObject != 'undefined' ){
					// avoid fp6 minor version lookup issues
					// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
					var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
					try {
						axo.AllowScriptAccess = 'always';
					} catch(e){
						return '6,0,0';
					}
				}
			} catch(e){}
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
		} catch(e){}
		return '0,0,0';
	 },
	/**
	 * javascript run post player embedding
	 */
	postEmbedActions : function(){
	},

	/**
	 * Bind a Player Function,
	 *
	 * Build a global callback to bind to "this" player instance:
	 *
	 * @param {String}
	 *            flash binding name
	 * @param {String}
	 *            function callback name
	 */
	bindPlayerFunction : function(bindName, methodName){
	},

	/**
	 * play method calls parent_play to update the interface
	 */
	play: function(){
		var _this = this;

		if(this.hasEnded){
				//handle replay
			}
		if( this.parent_play() ){
			if(_this.getPlayerElement())
			{
				_this.getPlayerElement().playVideo();
			}
		}
		this.monitor();
	},

	/**
	 * pause method calls parent_pause to update the interface
	 */
	pause: function(){
		var yt = this.getPlayerElement();
		yt.pauseVideo();
		this.parent_pause();
	},
	/**
	 * playerSwitchSource switches the player source working around a few bugs in browsers
	 *
	 * @param {object}
	 *            source Video Source object to switch to.
	 * @param {function}
	 *            switchCallback Function to call once the source has been switched
	 * @param {function}
	 *            doneCallback Function to call once the clip has completed playback
	 */
	playerSwitchSource: function( source, switchCallback, doneCallback ){

	},

	/**
	 * Issues a seek to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage of total stream length to seek to
	 */
	seek : function( percentage ){
		this.seeking = true;
		$( this ).trigger( 'seeking' );
		var yt = this.getPlayerElement();
		yt.seekTo( yt.getDuration() * percentage );
		this.controlBuilder.onSeek();
		//TODO check if there is a cleaner way to get the playback

	},

	/**
	 * Issues a volume update to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage to update volume to
	 */
	setPlayerElementVolume : function(percentage){
//		if ( this.getPlayerElement() && this.playerElement.sendNotification ){
//			this.playerElement.sendNotification('changeVolume', percentage);
//		}
		var yt = this.getPlayerElement();
		yt.setVolume(percentage*100);
	},

	/**
	 * function called by flash at set interval to update the playhead.
	 */
	onUpdatePlayhead : function( playheadValue ){
		this.time = playheadValue;
	},

	/**
	 * function called by flash when the total media size changes
	 */
	onBytesTotalChange : function(data, id){
		this.bytesTotal = data.newValue;
	},
	/**
	 * Get the embed player time
	 */
	getPlayerElementTime : function(){
		// update currentTime
		return this.getPlayerElement().getCurrentTime();
	},

	/**
	 * Get the embed fla object player Element
	 */
	getPlayerElement : function(){

		//IFRAME
		if( window['iframePlayer'] )
			return  window['iframePlayer']
		//Flash
		return $('#' + this.pid)[0];
	}
};

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


<commit_before>var protocol = require('./protocol');
var http = require('http');
var once = require('once');
var thunky = require('thunky');
var xtend = require('xtend');
var events = require('events');

var noop = function() {};

module.exports = function(remote) {
	if (!remote) remote = '127.0.0.1';
	if (typeof remote === 'string') {
		var match = remote.match(/^([^:]+)(?::(\d+))?$/);
		remote = {host:match[1], port:match[2] || 10002};
	}

	var client = new events.EventEmitter();
	var subs = {};

	var connect = thunky(function(cb) {
		var req = http.request(xtend(remote, {method:'CONNECT'}));

		connecting = true;
		cb = once(cb);

		req.on('error', cb);
		req.on('connect', function(res, socket, data) {
			var p = protocol(socket, data);

			p.on('close', function() {
				client.emit('close');
			});

			p.on('stdout', function(id, data) {
				client.emit('stdout', id, data);
			});

			p.on('stderr', function(id, data) {
				client.emit('stderr', id, data);
			});

			p.on('spawn', function(id, pid) {
				client.emit('spawn', id, pid);
			});

			p.on('exit', function(id, code) {
				client.emit('exit', id, code);
			});

			cb(null, p, socket);
		});

		req.end();
	});

	var refs = 0;
	var incref = function(cb, fn) {
		if (!cb) cb = noop;
		connect(function(err, p, socket) {
			if (err) return cb(err);
			if (!refs++) socket.ref();
			fn(p, function(err, val) {
				if (!--refs && !client.subscriptions().length) socket.unref();
				cb(err, val);
			});
		});
	};

	client.open = connect;

	client.add = function(id, opts, cb) {
		if (typeof opts === 'function') return client.add(id, null, opts);
		incref(cb, function(p, cb) {
			p.add(id, opts || {}, cb);
		});
	};

	client.update = function(id, opts, cb) {
		incref(cb, function(p, cb) {
			p.update(id, opts, cb);
		});
	};

	client.remove = function(id, cb) {
		incref(cb, function(p, cb) {
			p.remove(id, cb);
		});
	};

	client.get = function(id, cb) {
		incref(cb, function(p, cb) {
			p.get(id, cb);
		});
	};

	client.list = function(cb) {
		incref(cb, function(p, cb) {
			p.list(cb);
		});
	};

	client.start = function(id, cb) {
		incref(cb, function(p, cb) {
			p.start(id, cb);
		});
	};

	client.restart = function(id, cb) {
		incref(cb, function(p, cb) {
			p.restart(id, cb);
		});
	};

	client.stop = function(id, cb) {
		incref(cb, function(p, cb) {
			p.stop(id, cb);
		});
	};

	client.ps = function(cb) {
		incref(cb, function(p, cb) {
			p.ps(function(err, docks) {
				if (err) return cb(err);

				docks.forEach(function(dock) {
					dock.list.forEach(function(proc) {
						if (proc.started) proc.started = new Date(proc.started);
						if (proc.deployed) proc.deployed = new Date(proc.deployed);
					});
				});

				cb(null, docks);
			});
		});
	};

	client.subscriptions = function() {
		return Object.keys(subs);
	};

	client.subscribing = function(id) {
		return !!subs[id];
	};

	client.subscribe = function(id, cb) {
		subs[id] = subs[id] || thunky(function(cb) {
			incref(cb, function(p, cb) {
				p.subscribe(id, cb);
			});
		});

		subs[id](cb);
	};

	client.unsubscribe = function(id, cb) {
		if (!cb) cb = noop;
		if (!subs[id]) return cb();
		delete subs[id];
		incref(cb, function(p, cb) {
			p.unsubscribe(id, cb);
		});
	};

	client.destroy = function(cb) {
		incref(cb, function(p, cb) {
			p.destroy();
			cb();
		});
	};

	return client;
};<commit_msg>added deploy method<commit_after>var protocol = require('./protocol');
var http = require('http');
var once = require('once');
var thunky = require('thunky');
var xtend = require('xtend');
var events = require('events');

var noop = function() {};

module.exports = function(remote) {
	if (!remote) remote = '127.0.0.1';
	if (typeof remote === 'string') {
		var match = remote.match(/^([^:]+)(?::(\d+))?$/);
		remote = {host:match[1], port:match[2] || 10002};
	}

	var client = new events.EventEmitter();
	var subs = {};

	var connect = thunky(function(cb) {
		var req = http.request(xtend(remote, {method:'CONNECT'}));

		connecting = true;
		cb = once(cb);

		req.on('error', cb);
		req.on('connect', function(res, socket, data) {
			var p = protocol(socket, data);

			p.on('close', function() {
				client.emit('close');
			});

			p.on('stdout', function(id, data) {
				client.emit('stdout', id, data);
			});

			p.on('stderr', function(id, data) {
				client.emit('stderr', id, data);
			});

			p.on('spawn', function(id, pid) {
				client.emit('spawn', id, pid);
			});

			p.on('exit', function(id, code) {
				client.emit('exit', id, code);
			});

			cb(null, p, socket);
		});

		req.end();
	});

	var refs = 0;
	var incref = function(cb, fn) {
		if (!cb) cb = noop;
		connect(function(err, p, socket) {
			if (err) return cb(err);
			if (!refs++) socket.ref();
			fn(p, function(err, val) {
				if (!--refs && !client.subscriptions().length) socket.unref();
				cb(err, val);
			});
		});
	};

	client.deploy = function(id, cb) {
		var req = http.request(xtend(remote, {method:'PUT', path:'/'+id}));

		if (cb) {
			req.on('error', cb);
			cb = once(cb);
		} else {
			cb = noop;
		}

		var done = function(err) {
			if (err) req.emit('error', err);
			cb(err);
		};

		var onbuild = function() {
			req.emit('build');
			req.emit('distributing');
			incref(done, function(p, cb) {
				p.distribute(id, null, function(err) {
					if (err) return cb(err);
					req.emit('distribute');
					req.emit('restarting');
					p.restart(id, function(err) {
						if (err) return cb(err);
						req.emit('restart');
						cb();
					});
				});
			});
		};

		var onerror = function(res) {
			var message = '';
			res.setEncoding('utf-8');
			res.on('data', function(data) {
				message += data;
			});
			res.on('end', function() {
				done(new Error(message));
			});
		};

		req.on('response', function(res) {
			if (res.statusCode === 204) return onbuild();
			if (res.statusCode !== 200) return onerror(res);

			if (!req.emit('building', res)) res.resume();

			res.on('end', function() {
				var status = parseInt(res.trailers['x-status'] || 200, 10);
				if (status !== 200) return done(new Error('Build failed'));
				onbuild();
			});
		});

		return req;
	};

	client.open = connect;

	client.add = function(id, opts, cb) {
		if (typeof opts === 'function') return client.add(id, null, opts);
		incref(cb, function(p, cb) {
			p.add(id, opts || {}, cb);
		});
	};

	client.update = function(id, opts, cb) {
		incref(cb, function(p, cb) {
			p.update(id, opts, cb);
		});
	};

	client.remove = function(id, cb) {
		incref(cb, function(p, cb) {
			p.remove(id, cb);
		});
	};

	client.get = function(id, cb) {
		incref(cb, function(p, cb) {
			p.get(id, cb);
		});
	};

	client.list = function(cb) {
		incref(cb, function(p, cb) {
			p.list(cb);
		});
	};

	client.start = function(id, cb) {
		incref(cb, function(p, cb) {
			p.start(id, cb);
		});
	};

	client.restart = function(id, cb) {
		incref(cb, function(p, cb) {
			p.restart(id, cb);
		});
	};

	client.stop = function(id, cb) {
		incref(cb, function(p, cb) {
			p.stop(id, cb);
		});
	};

	client.ps = function(cb) {
		incref(cb, function(p, cb) {
			p.ps(function(err, docks) {
				if (err) return cb(err);

				docks.forEach(function(dock) {
					dock.list.forEach(function(proc) {
						if (proc.started) proc.started = new Date(proc.started);
						if (proc.deployed) proc.deployed = new Date(proc.deployed);
					});
				});

				cb(null, docks);
			});
		});
	};

	client.subscriptions = function() {
		return Object.keys(subs);
	};

	client.subscribing = function(id) {
		return !!subs[id];
	};

	client.subscribe = function(id, cb) {
		subs[id] = subs[id] || thunky(function(cb) {
			incref(cb, function(p, cb) {
				p.subscribe(id, cb);
			});
		});

		subs[id](cb);
	};

	client.unsubscribe = function(id, cb) {
		if (!cb) cb = noop;
		if (!subs[id]) return cb();
		delete subs[id];
		incref(cb, function(p, cb) {
			p.unsubscribe(id, cb);
		});
	};

	client.destroy = function(cb) {
		incref(cb, function(p, cb) {
			p.destroy();
			cb();
		});
	};

	return client;
};<|endoftext|>


<commit_before>import * as amadeus from './amadeus';
import * as google from './google';

const handlers = [
  {
    expr: /Plan my trip to/g,
    handler: async(session, msg) => {
      let city = msg.replace("Plan my trip to", "");
      city = city.substring(0, city.length - 1);
      session.city = city;
      session.geocode = await google.geocode(city);
      return {
        msg: `Cool, let's plan your trip to ${city}!`,
        session
      };
    }
  },
  {
    expr: /hotel/g,
    handler: async(session, msg) => {
      const city = session.city
      const hotel = "El Cheapo hotel"
      if (hotel) {
        return {
          msg: `Found a hotel in` + city,
          hotel
        };
      }else {
        return {
           msg: `Could'nt find a hotl, ask for something else`,
           hotel
        };
      }
    }
  },
  {
    expr: /flight/g,
    handler: async(session, msg) => {
      session.city = "Dallas"
      const fare = await amadeus.findFare({
        origin: 'BOS',
        dest: 'DFW',
        depart: '2015-10-01',
        ret: '2015-10-03'
      });
      if (fare) {
        return {
          msg: `Found a flight.`,
          fare
        };
      } else {
        return {
          msg: `Couldn't find a flight. Ask for a different location.`,
          fare
        };
      }
    }
  }
];

export default async function(session, msg) {
  for (let i = 0; i < handlers.length; i++) {
    if (handlers[i].expr.test(msg)) {
      handlers[i].expr = new RegExp(handlers[i].expr);
      return handlers[i].handler(session, msg);
    }
  }
  return {
    msg: `Cool! You said ${msg}`
  };
}
<commit_msg>added start date<commit_after>import * as amadeus from './amadeus';
import * as google from './google';

const handlers = [
  {
    expr: /Plan my trip to/g,
    handler: async(session, msg) => {
      let city = msg.replace("Plan my trip to", "");
      city = city.substring(0, city.length - 1);
      session.city = city;
      session.geocode = await google.geocode(city);
      return {
        msg: `Cool, let's plan your trip to ${city}!`,
        session
      };
    }
  },
   {
    expr: /\d+\d+\-\d+\d+/g,
    handler: async(session, msg) => {
      var parts = msg.split("-");
      var d = new Date(2015,parts[0]-1,parts[1]);
      session.startdate = d
      return {
        msg: `Alright, type flight to find a flight`
      };
    }
  },
  {
    expr: /hotel/g,
    handler: async(session, msg) => {
      const city = session.city
      const hotel = "El Cheapo hotel"
      if (hotel) {
        return {
          msg: `Found a hotel in` + city,
          hotel
        };
      }else {
        return {
           msg: `Could'nt find a hotl, ask for something else`,
           hotel
        };
      }
    }
  },
  {
    expr: /flight/g,
    handler: async(session, msg) => {
      session.city = "Dallas"
      const fare = await amadeus.findFare({
        origin: 'BOS',
        dest: 'DFW',
        depart: '2015-10-01',
        ret: '2015-10-03'
      });
      if (fare) {
        return {
          msg: `Found a flight.`,
          fare
        };
      } else {
        return {
          msg: `Couldn't find a flight. Ask for a different location.`,
          fare
        };
      }
    }
  }
];

export default async function(session, msg) {
  for (let i = 0; i < handlers.length; i++) {
    if (handlers[i].expr.test(msg)) {
      handlers[i].expr = new RegExp(handlers[i].expr);
      return handlers[i].handler(session, msg);
    }
  }
  return {
    msg: `Cool! You said ${msg}`
  };
}
<|endoftext|>


<commit_before>var describe = require('mocha').describe;
var it = require('mocha').it;
// var beforeEach = require('mocha').beforeEach;
var afterEach = require('mocha').afterEach;
var expect = require('chai').expect;
var mockRequire = require('mock-require');

describe('[UNIT] ForkTsCheckerWebpackPlugin', function() {
  afterEach(function() {
    mockRequire.stopAll();
  });

  it('should not throw if typescript version >= 2.1.0', function() {
    mockRequire('typescript', { version: '2.1.0' });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin();
    }).to.not.throw();
  });

  it('should throw if typescript version < 2.1.0', function() {
    mockRequire('typescript', { version: '2.0.8' });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin();
    }).to.throw();
  });

  it('should not throw if tslint version >= 4.0.0', function() {
    mockRequire('typescript', { version: '2.1.0' });
    mockRequire('tslint', { Linter: { VERSION: '4.0.0' } });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin({ tslint: true });
    }).to.not.throw();
  });

  it('should throw if tslint version < 4.0.0', function() {
    mockRequire('typescript', { version: '2.1.0' });
    mockRequire('tslint', { Linter: { VERSION: '3.15.1' } });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin({ tslint: true });
    }).to.throw();
  });
});
<commit_msg>more unit tests (#205)<commit_after>var describe = require('mocha').describe;
var it = require('mocha').it;
var afterEach = require('mocha').afterEach;
var expect = require('chai').expect;
var mockRequire = require('mock-require');

describe('[UNIT] ForkTsCheckerWebpackPlugin', function() {
  afterEach(function() {
    mockRequire.stopAll();
  });

  it('should throw if typescript not present', function() {
    mockRequire('typescript', undefined);
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin();
    }).to.throw(
      Error,
      'When you use this plugin you must install `typescript`.'
    );
  });

  it('should not throw if typescript version >= 2.1.0', function() {
    mockRequire('typescript', { version: '2.1.0' });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin();
    }).to.not.throw();
  });

  it('should throw if typescript version < 2.1.0', function() {
    mockRequire('typescript', { version: '2.0.8' });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin();
    }).to.throw(
      Error,
      'Cannot use current typescript version of 2.0.8, the minimum required version is 2.1.0'
    );
  });

  it('should throw if tslint not present', function() {
    mockRequire('typescript', { version: '2.1.0' });
    mockRequire('tslint', undefined);
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin({ tslint: true });
    }).to.throw(
      Error,
      'When you use `tslint` option, make sure to install `tslint`.'
    );
  });

  it('should not throw if tslint version >= 4.0.0', function() {
    mockRequire('typescript', { version: '2.1.0' });
    mockRequire('tslint', { Linter: { VERSION: '4.0.0' } });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin({ tslint: true });
    }).to.not.throw();
  });

  it('should throw if tslint version < 4.0.0', function() {
    mockRequire('typescript', { version: '2.1.0' });
    mockRequire('tslint', { Linter: { VERSION: '3.15.1' } });
    var ForkTsCheckerWebpackPlugin = mockRequire.reRequire('../../lib/index');

    expect(function() {
      new ForkTsCheckerWebpackPlugin({ tslint: true });
    }).to.throw(
      Error,
      'Cannot use current tslint version of 3.15.1, the minimum required version is 4.0.0'
    );
  });
});
<|endoftext|>


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

var GeodeticCoord = require('./coords/geodetic.js');
var Ellipsoid = require('./ellipsoid.js');
var MagneticElements = require('./magnetic_elements.js');
var MagneticVector = require('./magnetic_vector.js');

module.exports = Model;

function Model(options){
	this.epoch = options.epoch;
	this.start_date = new Date(options.start_date);
	this.end_date = new Date(options.end_date);
	this.name = options.name || "";
	this.main_field_coeff_g = options.main_field_coeff_g || [0];
	this.main_field_coeff_h = options.main_field_coeff_h || [0];
	this.secular_var_coeff_g = options.secular_var_coeff_g || [0];
	this.secular_var_coeff_h = options.secular_var_coeff_h || [0];
	this.n_max = options.n_max || 0;
	this.n_max_sec_var = options.n_max_sec_var || 0;
	this.num_terms = this.n_max*(this.n_max+1)/2 + this.n_max;
}

Model.prototype.getTimedModel = function(date){
	var year_int = date.getFullYear();
	var year_start = new Date(year_int, 0, 1);
	var fractional_year = (date.valueOf() - year_start.valueOf()) / (1000*3600*24*365);
	var year = year_int + fractional_year;
	var dyear = year - this.epoch;

	if(date < this.start_date || date > this.end_date){
		throw new RangeError("Model is only valid from "+this.start_date.toDateString()+" to "+this.end_date.toDateString());
	}

	var model = new Model({
		epoch: this.epoch,
		n_max: this.n_max,
		n_max_sec_var: this.n_max_sec_var,
		name: this.name
	});
	var a = model.n_max_sec_var;
	var b = a*(a + 1)/2 + a;
	for(var n = 1; n <= this.n_max; n++){
		for(var m = 0; m <= n; m++){
			var i = n * (n + 1)/2 + m;
			var hnm = this.main_field_coeff_h[i];
			var gnm = this.main_field_coeff_g[i];
			var dhnm = this.secular_var_coeff_h[i];
			var dgnm = this.secular_var_coeff_g[i];
			if(i <= b){
				model.main_field_coeff_h[i] = hnm + dyear*dhnm;
				model.main_field_coeff_g[i] = gnm + dyear*dgnm;
				model.secular_var_coeff_h[i] = dhnm;
				model.secular_var_coeff_g[i] = dgnm;
			} else {
				model.main_field_coeff_h[i] = hnm;
				model.main_field_coeff_g[i] = gnm;
			}
		}
	}
	return model;
};

Model.prototype.getSummation = function(legendre, sph_variables, coord_spherical){
	var bx = 0;
	var by = 0;
	var bz = 0;
	var n, m, i, k;
	var relative_radius_power = sph_variables.relative_radius_power;
	var cos_mlambda = sph_variables.cos_mlambda;
	var sin_mlambda = sph_variables.sin_mlambda;
	var g = this.main_field_coeff_g;
	var h = this.main_field_coeff_h;

	for(n = 1; n <= this.n_max; n++){
		for(m = 0; m <= n; m++){
			i = n*(n+1)/2 + m;
			bz -= relative_radius_power[n] *
				(g[i]*cos_mlambda[m] + h[i]*sin_mlambda[m]) *
				(n+1) * legendre.pcup[i];
			by += relative_radius_power[n] *
				(g[i]*sin_mlambda[m] - h[i]*cos_mlambda[m]) *
				(m) * legendre.pcup[i];
			bx -= relative_radius_power[n] *
				(g[i]*cos_mlambda[m] + h[i]*sin_mlambda[m]) *
				legendre.dpcup[i];
		}
	}
	var cos_phi = Math.cos(Math.PI/180 * coord_spherical.phig);
	if(Math.abs(cos_phi) > 1e-10){
		by = by / cos_phi;
	} else {
		//special calculation around poles
		by = 0;
		var schmidt_quasi_norm1 = 1.0, schmidt_quasi_norm2, schmidt_quasi_norm3;
		var pcup_s = [1];
		var sin_phi = Math.sin(Math.PI/180 * coord_spherical.phig);

		for(n = 1; n <= this.n_max; n++){
			i = n*(n+1)/2 + 1;
			schmidt_quasi_norm2 = schmidt_quasi_norm1 * (2*n-1) / n;
			schmidt_quasi_norm3 = schmidt_quasi_norm2 * Math.sqrt(2*n/(n+1));
			schmidt_quasi_norm1 = schmidt_quasi_norm2;
			if(n == 1){
				pcup_s[n] = pcup_s[n-1];
			} else {
				k = ((n-1)*(n-1) - 1) / ((2*n-1)*(2*n-3));
				pcup_s[n] = sin_phi * pcup_s[n-1] - k*pcup_s[n-2];
			}
			by += relative_radius_power[n] *
				(g[i]*sin_mlambda[1] - h[i]*cos_mlambda[1]) *
				pcup_s[n] * schmidt_quasi_norm3;
		}
	}
	return new MagneticVector({
		bx: bx, by: by, bz: bz
	});
};

/*
Model.prototype.getSecVarSummation = function(sph_variables, coord_spherical){
	//TODO
}
*/

Model.prototype.point = function(coords) {
	var coord_geodetic = new GeodeticCoord({
		lat: coords[0],
		lon: coords[1]
	});
	var coord_spherical = coord_geodetic.toSpherical();

	var legendre = coord_spherical.getLegendreFunction(this.n_max);
	var harmonic_variables = coord_spherical.getHarmonicVariables(coord_geodetic.ellipsoid, this.n_max);

	var magnetic_vector_sph = this.getSummation(legendre, harmonic_variables, coord_spherical);
	var magnetic_vector_geo = magnetic_vector_sph.rotate(coord_spherical, coord_geodetic);

	return MagneticElements.fromGeoMagneticVector(magnetic_vector_geo);
};
<commit_msg>Remove unused import of path<commit_after>var GeodeticCoord = require('./coords/geodetic.js');
var Ellipsoid = require('./ellipsoid.js');
var MagneticElements = require('./magnetic_elements.js');
var MagneticVector = require('./magnetic_vector.js');

module.exports = Model;

function Model(options){
	this.epoch = options.epoch;
	this.start_date = new Date(options.start_date);
	this.end_date = new Date(options.end_date);
	this.name = options.name || "";
	this.main_field_coeff_g = options.main_field_coeff_g || [0];
	this.main_field_coeff_h = options.main_field_coeff_h || [0];
	this.secular_var_coeff_g = options.secular_var_coeff_g || [0];
	this.secular_var_coeff_h = options.secular_var_coeff_h || [0];
	this.n_max = options.n_max || 0;
	this.n_max_sec_var = options.n_max_sec_var || 0;
	this.num_terms = this.n_max*(this.n_max+1)/2 + this.n_max;
}

Model.prototype.getTimedModel = function(date){
	var year_int = date.getFullYear();
	var year_start = new Date(year_int, 0, 1);
	var fractional_year = (date.valueOf() - year_start.valueOf()) / (1000*3600*24*365);
	var year = year_int + fractional_year;
	var dyear = year - this.epoch;

	if(date < this.start_date || date > this.end_date){
		throw new RangeError("Model is only valid from "+this.start_date.toDateString()+" to "+this.end_date.toDateString());
	}

	var model = new Model({
		epoch: this.epoch,
		n_max: this.n_max,
		n_max_sec_var: this.n_max_sec_var,
		name: this.name
	});
	var a = model.n_max_sec_var;
	var b = a*(a + 1)/2 + a;
	for(var n = 1; n <= this.n_max; n++){
		for(var m = 0; m <= n; m++){
			var i = n * (n + 1)/2 + m;
			var hnm = this.main_field_coeff_h[i];
			var gnm = this.main_field_coeff_g[i];
			var dhnm = this.secular_var_coeff_h[i];
			var dgnm = this.secular_var_coeff_g[i];
			if(i <= b){
				model.main_field_coeff_h[i] = hnm + dyear*dhnm;
				model.main_field_coeff_g[i] = gnm + dyear*dgnm;
				model.secular_var_coeff_h[i] = dhnm;
				model.secular_var_coeff_g[i] = dgnm;
			} else {
				model.main_field_coeff_h[i] = hnm;
				model.main_field_coeff_g[i] = gnm;
			}
		}
	}
	return model;
};

Model.prototype.getSummation = function(legendre, sph_variables, coord_spherical){
	var bx = 0;
	var by = 0;
	var bz = 0;
	var n, m, i, k;
	var relative_radius_power = sph_variables.relative_radius_power;
	var cos_mlambda = sph_variables.cos_mlambda;
	var sin_mlambda = sph_variables.sin_mlambda;
	var g = this.main_field_coeff_g;
	var h = this.main_field_coeff_h;

	for(n = 1; n <= this.n_max; n++){
		for(m = 0; m <= n; m++){
			i = n*(n+1)/2 + m;
			bz -= relative_radius_power[n] *
				(g[i]*cos_mlambda[m] + h[i]*sin_mlambda[m]) *
				(n+1) * legendre.pcup[i];
			by += relative_radius_power[n] *
				(g[i]*sin_mlambda[m] - h[i]*cos_mlambda[m]) *
				(m) * legendre.pcup[i];
			bx -= relative_radius_power[n] *
				(g[i]*cos_mlambda[m] + h[i]*sin_mlambda[m]) *
				legendre.dpcup[i];
		}
	}
	var cos_phi = Math.cos(Math.PI/180 * coord_spherical.phig);
	if(Math.abs(cos_phi) > 1e-10){
		by = by / cos_phi;
	} else {
		//special calculation around poles
		by = 0;
		var schmidt_quasi_norm1 = 1.0, schmidt_quasi_norm2, schmidt_quasi_norm3;
		var pcup_s = [1];
		var sin_phi = Math.sin(Math.PI/180 * coord_spherical.phig);

		for(n = 1; n <= this.n_max; n++){
			i = n*(n+1)/2 + 1;
			schmidt_quasi_norm2 = schmidt_quasi_norm1 * (2*n-1) / n;
			schmidt_quasi_norm3 = schmidt_quasi_norm2 * Math.sqrt(2*n/(n+1));
			schmidt_quasi_norm1 = schmidt_quasi_norm2;
			if(n == 1){
				pcup_s[n] = pcup_s[n-1];
			} else {
				k = ((n-1)*(n-1) - 1) / ((2*n-1)*(2*n-3));
				pcup_s[n] = sin_phi * pcup_s[n-1] - k*pcup_s[n-2];
			}
			by += relative_radius_power[n] *
				(g[i]*sin_mlambda[1] - h[i]*cos_mlambda[1]) *
				pcup_s[n] * schmidt_quasi_norm3;
		}
	}
	return new MagneticVector({
		bx: bx, by: by, bz: bz
	});
};

/*
Model.prototype.getSecVarSummation = function(sph_variables, coord_spherical){
	//TODO
}
*/

Model.prototype.point = function(coords) {
	var coord_geodetic = new GeodeticCoord({
		lat: coords[0],
		lon: coords[1]
	});
	var coord_spherical = coord_geodetic.toSpherical();

	var legendre = coord_spherical.getLegendreFunction(this.n_max);
	var harmonic_variables = coord_spherical.getHarmonicVariables(coord_geodetic.ellipsoid, this.n_max);

	var magnetic_vector_sph = this.getSummation(legendre, harmonic_variables, coord_spherical);
	var magnetic_vector_geo = magnetic_vector_sph.rotate(coord_spherical, coord_geodetic);

	return MagneticElements.fromGeoMagneticVector(magnetic_vector_geo);
};
<|endoftext|>


<commit_before>var url = typeof window === 'undefined' ? 'http://example.org' : location.href;
var httpinvoke = require('../httpinvoke-node');

describe('"uploading" option', function() {
    this.timeout(10000);
    it('is called at least twice', function(done) {
        var count = 0;
        var abort = httpinvoke(url, {
            uploading: function() {
                count += 1;
                if(count === 2) {
                    done();
                }
            },
            finished: function() {
                if(count < 2) {
                    done(new Error('It was called ' + count + ' times'));
                }
                abort();
            }
        });
    });
    it('has "current" and "total" be non-negative integers', function(done) {
        var fail = function(msg) {
            done(new Error(msg));
            done = null;
        };
        httpinvoke(url, {
            uploading: function(current, total) {
                if(done === null) {
                    return;
                }
                if(typeof current !== 'number') {
                    return fail('"current" was not a number');
                }
                if(current % 1 !== 0) {
                    return fail('"current" was not an integer');
                }
                if(current < 0) {
                    return fail('"current" was not an non-negative');
                }
                if(typeof total !== 'number') {
                    return fail('"total" was not a number');
                }
                if(total % 1 !== 0) {
                    return fail('"total" was not an integer');
                }
                if(total < 0) {
                    return fail('"total" was not an non-negative');
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
    it('has the last "current" be equal to total', function(done) {
        var current, total;
        httpinvoke(url, {
            uploading: function(_current, _total) {
                current = _current;
                total = _total;
            },
            finished: function() {
                if(current !== total) {
                    done(new Error('The last received "current"=' + current + ' is not equal to "total"=' + total));
                } else {
                    done();
                }
            }
        });
    });
    it('has the first "current" be equal to 0', function(done) {
        var abort = httpinvoke(url, {
            uploading: function(current) {
                if(done === null) {
                    return;
                }
                if(current !== 0) {
                    done(new Error('First "current" is not equal to 0: ' + current));
                } else {
                    done();
                }
                done = null;
                abort();
            }
        });
    });
    it('has "current" not greater than "total"', function(done) {
        httpinvoke(url, {
            uploading: function(current, total) {
                if(current > total) {
                    done(new Error('"current" was greater than "total"'));
                    done = null;
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
    it('has "total" always be the same', function(done) {
        var total = null;
        httpinvoke(url, {
            uploading: function(current, _total) {
                if(done === null) {
                    return;
                }
                if(total === null) {
                    total = _total;
                    return;
                }
                if(total !== _total) {
                    done(new Error('Received "total"=' + _total + ' that is different from previously received "total"=' + total));
                    done = null;
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
    it('has "total" be equal to input length', function(done) {
        var input = 'foobar';
        var abort = httpinvoke(url, {
            input: input,
            uploading: function(_, total) {
                if(done === null) {
                    return;
                }
                if(input.length !== total) {
                    done(new Error('"total"=' + total + ' was not equal to input length = ' + input.length));
                } else {
                    done();
                }
                done = null;
                abort();
            }
        });
    });
    it('has "current" be non-decreasing', function(done) {
        var current = null;
        httpinvoke(url, {
            uploading: function(_current) {
                if(done === null) {
                    return;
                }
                if(current === null) {
                    current = _current;
                    return;
                }
                if(_current < current) {
                    done(new Error('Received "current"=' + _current + ' that is lower than previously received "current"=' + current));
                    done = null;
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
});
<commit_msg>uploadingSpec: add "input" to all httpinvoke options<commit_after>var url = typeof window === 'undefined' ? 'http://example.org' : location.href;
var httpinvoke = require('../httpinvoke-node');

describe('"uploading" option', function() {
    this.timeout(10000);
    it('is called at least twice', function(done) {
        var count = 0;
        var abort = httpinvoke(url, {
            input: 'foobar',
            uploading: function() {
                count += 1;
                if(count === 2) {
                    done();
                }
            },
            finished: function() {
                if(count < 2) {
                    done(new Error('It was called ' + count + ' times'));
                }
                abort();
            }
        });
    });
    it('has "current" and "total" be non-negative integers', function(done) {
        var fail = function(msg) {
            done(new Error(msg));
            done = null;
        };
        httpinvoke(url, {
            input: 'foobar',
            uploading: function(current, total) {
                if(done === null) {
                    return;
                }
                if(typeof current !== 'number') {
                    return fail('"current" was not a number');
                }
                if(current % 1 !== 0) {
                    return fail('"current" was not an integer');
                }
                if(current < 0) {
                    return fail('"current" was not an non-negative');
                }
                if(typeof total !== 'number') {
                    return fail('"total" was not a number');
                }
                if(total % 1 !== 0) {
                    return fail('"total" was not an integer');
                }
                if(total < 0) {
                    return fail('"total" was not an non-negative');
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
    it('has the last "current" be equal to total', function(done) {
        var current, total;
        httpinvoke(url, {
            input: 'foobar',
            uploading: function(_current, _total) {
                current = _current;
                total = _total;
            },
            finished: function() {
                if(current !== total) {
                    done(new Error('The last received "current"=' + current + ' is not equal to "total"=' + total));
                } else {
                    done();
                }
            }
        });
    });
    it('has the first "current" be equal to 0', function(done) {
        var abort = httpinvoke(url, {
            input: 'foobar',
            uploading: function(current) {
                if(done === null) {
                    return;
                }
                if(current !== 0) {
                    done(new Error('First "current" is not equal to 0: ' + current));
                } else {
                    done();
                }
                done = null;
                abort();
            }
        });
    });
    it('has "current" not greater than "total"', function(done) {
        httpinvoke(url, {
            input: 'foobar',
            uploading: function(current, total) {
                if(current > total) {
                    done(new Error('"current" was greater than "total"'));
                    done = null;
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
    it('has "total" always be the same', function(done) {
        var total = null;
        httpinvoke(url, {
            input: 'foobar',
            uploading: function(current, _total) {
                if(done === null) {
                    return;
                }
                if(total === null) {
                    total = _total;
                    return;
                }
                if(total !== _total) {
                    done(new Error('Received "total"=' + _total + ' that is different from previously received "total"=' + total));
                    done = null;
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
    it('has "total" be equal to input length', function(done) {
        var input = 'foobar';
        var abort = httpinvoke(url, {
            input: input,
            uploading: function(_, total) {
                if(done === null) {
                    return;
                }
                if(input.length !== total) {
                    done(new Error('"total"=' + total + ' was not equal to input length = ' + input.length));
                } else {
                    done();
                }
                done = null;
                abort();
            }
        });
    });
    it('has "current" be non-decreasing', function(done) {
        var current = null;
        httpinvoke(url, {
            input: 'foobar',
            uploading: function(_current) {
                if(done === null) {
                    return;
                }
                if(current === null) {
                    current = _current;
                    return;
                }
                if(_current < current) {
                    done(new Error('Received "current"=' + _current + ' that is lower than previously received "current"=' + current));
                    done = null;
                }
            },
            finished: function() {
                if(done === null) {
                    return;
                }
                done();
            }
        });
    });
});
<|endoftext|>


<commit_before>import React, { Suspense, lazy } from 'react'
import PropTypes from 'prop-types'
import { get } from 'lodash/object'
import {
  createMuiTheme,
  MuiThemeProvider,
  withStyles,
} from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import CircleIcon from '@material-ui/icons/Lens'
import Typography from '@material-ui/core/Typography'
import theme from 'js/theme/defaultV1'
import MoneyRaised from 'js/components/MoneyRaised/MoneyRaisedContainer'
import Hearts from 'js/components/Dashboard/HeartsContainer'
import HeartsDropdown from 'js/components/Dashboard/HeartsDropdownContainer'
import SettingsButton from 'js/components/Dashboard/SettingsButtonComponent'
import SettingsDropdown from 'js/components/Dashboard/SettingsDropdownComponent'
import { logout } from 'js/authentication/user'
import {
  goTo,
  loginURL,
  searchChromeExtensionPage,
  searchFirefoxExtensionPage,
} from 'js/navigation/navigation'
import logger from 'js/utils/logger'
import DashboardPopover from 'js/components/Dashboard/DashboardPopover'
import { inviteFriendsURL } from 'js/navigation/navigation'
import Link from 'js/components/General/Link'
import {
  CHROME_BROWSER,
  FIREFOX_BROWSER,
  TAB_APP,
  UNSUPPORTED_BROWSER,
} from 'js/constants'
import ErrorBoundary from 'js/components/General/ErrorBoundary'
import TreeIcon from 'mdi-material-ui/PineTree'

const Sparkle = lazy(() => import('react-sparkle'))

const defaultTheme = createMuiTheme(theme)

const styles = theme => ({
  circleIcon: {
    alignSelf: 'center',
    width: 5,
    height: 5,
    marginTop: 2,
    marginLeft: 12,
    marginRight: 12,
  },
  treeText: {
    transition: 'color 300ms ease-in',
    fontWeight: 'normal',
    userSelect: 'none',
    cursor: 'pointer',
  },
  treeIcon: {
    transition: 'color 300ms ease-in',
    cursor: 'pointer',
    paddingBottom: 0,
    color: 'rgba(255, 255, 255, 0.8)',
  },
})

const menuFontSize = 24

class UserMenu extends React.Component {
  async logout() {
    var logoutSuccess = false
    try {
      logoutSuccess = await logout()
    } catch (e) {
      logger.error(e)
    }
    if (logoutSuccess) {
      goTo(loginURL)
    }
  }

  render() {
    const {
      app,
      browser,
      classes,
      user,
      isUserAnonymous,
      onClickCampaignReopen,
      onClickSparklySearchIntroButton,
      showSparklySearchIntroButton,
      showCampaignReopenButton,
    } = this.props
    const numUsersRecruitedForCampaign = get(
      user,
      'recruits.recruitsWithAtLeastOneTab',
      0
    )
    return (
      <MuiThemeProvider
        theme={{
          ...defaultTheme,
          palette: {
            ...defaultTheme.palette,
            background: {
              ...defaultTheme.palette.background,
              paper: 'rgba(0, 0, 0, 0.36)',
            },
            divider: 'rgba(255, 255, 255, 0.20)',
          },
          typography: {
            ...defaultTheme.typography,
            h2: {
              ...defaultTheme.typography.h2,
              color: 'rgba(255, 255, 255, 0.8)',
              fontSize: menuFontSize,
            },
            h3: {
              ...defaultTheme.typography.h3,
              color: '#fff',
            },
            h4: {
              ...defaultTheme.typography.h4,
              color: '#fff',
            },
            h5: {
              ...defaultTheme.typography.h5,
              color: '#fff',
            },
            body2: {
              ...defaultTheme.typography.body2,
              color: '#fff',
            },
          },
          overrides: {
            ...defaultTheme.overrides,
            MuiListItemIcon: {
              ...get(defaultTheme, 'overrides.MuiListItemIcon', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiListItemIcon.root', {}),
                color: '#fff',
              },
            },
            MuiButtonBase: {
              ...get(defaultTheme, 'overrides.MuiButtonBase', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiButtonBase.root', {}),
                color: '#fff',
              },
            },
            MuiIconButton: {
              ...get(defaultTheme, 'overrides.MuiIconButton', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiIconButton.root', {}),
                color: '#fff',
              },
            },
            MuiSvgIcon: {
              ...get(defaultTheme, 'overrides.MuiSvgIcon', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiSvgIcon.root', {}),
                color: '#fff',
                fontSize: menuFontSize,
              },
            },
            MuiTypography: {
              ...get(defaultTheme, 'overrides.MuiTypography', {}),
              h2: {
                ...get(defaultTheme, 'overrides.MuiTypography.h2', {}),
                '&:hover': {
                  color: '#fff',
                },
              },
            },
          },
        }}
      >

          {showSparklySearchIntroButton ? (

              <Link
                to={
                  browser === CHROME_BROWSER
                    ? searchChromeExtensionPage
                    : browser === FIREFOX_BROWSER
                    ? searchFirefoxExtensionPage
                    : searchChromeExtensionPage
                }
                target={'blank'}
                onClick={onClickSparklySearchIntroButton}
              >
                <Button
                  variant={'text'}
                  color={'default'}
                  style={{
                    marginRight: 16,
                    color: 'rgba(255, 255, 255, 0.8)',
                  }}
                >
                  Double your impact
                </Button>
              </Link>
              <ErrorBoundary ignoreErrors brand={TAB_APP}>
                <Suspense fallback={null}>
                  <Sparkle
                    color={'#FFEBA2'}
                    count={12}
                    fadeOutSpeed={34}
                    overflowPx={8}
                    flicker={false}
                  />
                </Suspense>
              </ErrorBoundary>

          ) : null}
          {/* Remove when tree campaign is no longer live */}
          {showCampaignReopenButton ? (
            <>

                <Typography variant={'h2'} className={classes.treeText}>
                  {numUsersRecruitedForCampaign}
                </Typography>
                <TreeIcon className={classes.treeIcon} />

              <CircleIcon
                style={{
                  color: 'rgba(255, 255, 255, 0.8)',
                }}
                classes={{
                  root: classes.circleIcon,
                }}
              />
            </>
          ) : null}
          <MoneyRaised
            app={app}
            dropdown={({ open, onClose, anchorElement }) => (
              <DashboardPopover
                open={open}
                anchorEl={anchorElement}
                onClose={onClose}
                style={{
                  marginTop: 6,
                }}
              >

                  <Typography
                    variant={'body2'}
                    className={classes.dropdownText}
                    gutterBottom
                  >
                    This is how much money our community has raised for charity.
                  </Typography>
                  <Typography
                    variant={'body2'}
                    className={classes.dropdownText}
                    gutterBottom
                  >
                    Recruit your friends to raise more!
                  </Typography>

                    <Link to={inviteFriendsURL}>
                      <Button variant={'contained'} color={'primary'}>
                        Invite Friends
                      </Button>
                    </Link>

              </DashboardPopover>
            )}
          />
          <CircleIcon
            style={{
              color: 'rgba(255, 255, 255, 0.8)',
            }}
            classes={{
              root: classes.circleIcon,
            }}
          />
          <Hearts
            app={app}
            user={user}
            showMaxHeartsFromTabsMessage
            dropdown={({ open, onClose, anchorElement }) => (
              <HeartsDropdown
                app={app}
                user={user}
                open={open}
                onClose={onClose}
                anchorElement={anchorElement}
                style={{
                  marginTop: 6,
                }}
              />
            )}
          />
          <SettingsButton
            dropdown={({ open, onClose, anchorElement }) => (
              <SettingsDropdown
                open={open}
                anchorElement={anchorElement}
                onClose={onClose}
                onLogoutClick={this.logout.bind(this)}
                isUserAnonymous={isUserAnonymous}
              />
            )}
          />

      </MuiThemeProvider>
    )
  }
}

UserMenu.propTypes = {
  app: PropTypes.shape({}).isRequired,
  browser: PropTypes.oneOf([
    CHROME_BROWSER,
    FIREFOX_BROWSER,
    UNSUPPORTED_BROWSER,
  ]).isRequired,
  classes: PropTypes.object.isRequired,
  isUserAnonymous: PropTypes.bool,
  onClickCampaignReopen: PropTypes.func,
  onClickSparklySearchIntroButton: PropTypes.func,
  showSparklySearchIntroButton: PropTypes.bool,
  user: PropTypes.shape({
    recruits: PropTypes.shape({
      recruitsWithAtLeastOneTab: PropTypes.number.isRequired,
    }).isRequired,
  }).isRequired,
}

UserMenu.defaultProps = {
  isUserAnonymous: false,
  onClickCampaignReopen: () => {},
  onClickSparklySearchIntroButton: () => {},
  showSparklySearchIntroButton: false,
}

export default withStyles(styles)(UserMenu)
<commit_msg>Style tweak<commit_after>import React, { Suspense, lazy } from 'react'
import PropTypes from 'prop-types'
import { get } from 'lodash/object'
import {
  createMuiTheme,
  MuiThemeProvider,
  withStyles,
} from '@material-ui/core/styles'
import Button from '@material-ui/core/Button'
import CircleIcon from '@material-ui/icons/Lens'
import Typography from '@material-ui/core/Typography'
import theme from 'js/theme/defaultV1'
import MoneyRaised from 'js/components/MoneyRaised/MoneyRaisedContainer'
import Hearts from 'js/components/Dashboard/HeartsContainer'
import HeartsDropdown from 'js/components/Dashboard/HeartsDropdownContainer'
import SettingsButton from 'js/components/Dashboard/SettingsButtonComponent'
import SettingsDropdown from 'js/components/Dashboard/SettingsDropdownComponent'
import { logout } from 'js/authentication/user'
import {
  goTo,
  loginURL,
  searchChromeExtensionPage,
  searchFirefoxExtensionPage,
} from 'js/navigation/navigation'
import logger from 'js/utils/logger'
import DashboardPopover from 'js/components/Dashboard/DashboardPopover'
import { inviteFriendsURL } from 'js/navigation/navigation'
import Link from 'js/components/General/Link'
import {
  CHROME_BROWSER,
  FIREFOX_BROWSER,
  TAB_APP,
  UNSUPPORTED_BROWSER,
} from 'js/constants'
import ErrorBoundary from 'js/components/General/ErrorBoundary'
import TreeIcon from 'mdi-material-ui/PineTree'

const Sparkle = lazy(() => import('react-sparkle'))

const defaultTheme = createMuiTheme(theme)

const styles = theme => ({
  circleIcon: {
    alignSelf: 'center',
    width: 5,
    height: 5,
    marginTop: 2,
    marginLeft: 12,
    marginRight: 12,
  },
  treeText: {
    transition: 'color 300ms ease-in',
    fontWeight: 'normal',
    userSelect: 'none',
    cursor: 'pointer',
  },
  treeIcon: {
    transition: 'color 300ms ease-in',
    cursor: 'pointer',
    paddingBottom: 0,
    color: 'rgba(255, 255, 255, 0.8)',
  },
})

const menuFontSize = 24

class UserMenu extends React.Component {
  async logout() {
    var logoutSuccess = false
    try {
      logoutSuccess = await logout()
    } catch (e) {
      logger.error(e)
    }
    if (logoutSuccess) {
      goTo(loginURL)
    }
  }

  render() {
    const {
      app,
      browser,
      classes,
      user,
      isUserAnonymous,
      onClickCampaignReopen,
      onClickSparklySearchIntroButton,
      showSparklySearchIntroButton,
      showCampaignReopenButton,
    } = this.props
    const numUsersRecruitedForCampaign = get(
      user,
      'recruits.recruitsWithAtLeastOneTab',
      0
    )
    return (
      <MuiThemeProvider
        theme={{
          ...defaultTheme,
          palette: {
            ...defaultTheme.palette,
            background: {
              ...defaultTheme.palette.background,
              paper: 'rgba(0, 0, 0, 0.36)',
            },
            divider: 'rgba(255, 255, 255, 0.20)',
          },
          typography: {
            ...defaultTheme.typography,
            h2: {
              ...defaultTheme.typography.h2,
              color: 'rgba(255, 255, 255, 0.8)',
              fontSize: menuFontSize,
            },
            h3: {
              ...defaultTheme.typography.h3,
              color: '#fff',
            },
            h4: {
              ...defaultTheme.typography.h4,
              color: '#fff',
            },
            h5: {
              ...defaultTheme.typography.h5,
              color: '#fff',
            },
            body2: {
              ...defaultTheme.typography.body2,
              color: '#fff',
            },
          },
          overrides: {
            ...defaultTheme.overrides,
            MuiListItemIcon: {
              ...get(defaultTheme, 'overrides.MuiListItemIcon', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiListItemIcon.root', {}),
                color: '#fff',
              },
            },
            MuiButtonBase: {
              ...get(defaultTheme, 'overrides.MuiButtonBase', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiButtonBase.root', {}),
                color: '#fff',
              },
            },
            MuiIconButton: {
              ...get(defaultTheme, 'overrides.MuiIconButton', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiIconButton.root', {}),
                color: '#fff',
              },
            },
            MuiSvgIcon: {
              ...get(defaultTheme, 'overrides.MuiSvgIcon', {}),
              root: {
                ...get(defaultTheme, 'overrides.MuiSvgIcon.root', {}),
                color: '#fff',
                fontSize: menuFontSize,
              },
            },
            MuiTypography: {
              ...get(defaultTheme, 'overrides.MuiTypography', {}),
              h2: {
                ...get(defaultTheme, 'overrides.MuiTypography.h2', {}),
                '&:hover': {
                  color: '#fff',
                },
              },
            },
          },
        }}
      >

          {showSparklySearchIntroButton ? (

              <Link
                to={
                  browser === CHROME_BROWSER
                    ? searchChromeExtensionPage
                    : browser === FIREFOX_BROWSER
                    ? searchFirefoxExtensionPage
                    : searchChromeExtensionPage
                }
                target={'blank'}
                onClick={onClickSparklySearchIntroButton}
              >
                <Button
                  variant={'text'}
                  color={'default'}
                  style={{
                    marginRight: 16,
                    color: 'rgba(255, 255, 255, 0.8)',
                  }}
                >
                  Double your impact
                </Button>
              </Link>
              <ErrorBoundary ignoreErrors brand={TAB_APP}>
                <Suspense fallback={null}>
                  <Sparkle
                    color={'#FFEBA2'}
                    count={12}
                    fadeOutSpeed={34}
                    overflowPx={8}
                    flicker={false}
                  />
                </Suspense>
              </ErrorBoundary>

          ) : null}
          {/* Remove when tree campaign is no longer live */}
          {showCampaignReopenButton ? (
            <>

                <Typography variant={'h2'} className={classes.treeText}>
                  {numUsersRecruitedForCampaign}
                </Typography>
                <TreeIcon className={classes.treeIcon} />

              <CircleIcon
                style={{
                  marginLeft: 10,
                  color: 'rgba(255, 255, 255, 0.8)',
                }}
                classes={{
                  root: classes.circleIcon,
                }}
              />
            </>
          ) : null}
          <MoneyRaised
            app={app}
            dropdown={({ open, onClose, anchorElement }) => (
              <DashboardPopover
                open={open}
                anchorEl={anchorElement}
                onClose={onClose}
                style={{
                  marginTop: 6,
                }}
              >

                  <Typography
                    variant={'body2'}
                    className={classes.dropdownText}
                    gutterBottom
                  >
                    This is how much money our community has raised for charity.
                  </Typography>
                  <Typography
                    variant={'body2'}
                    className={classes.dropdownText}
                    gutterBottom
                  >
                    Recruit your friends to raise more!
                  </Typography>

                    <Link to={inviteFriendsURL}>
                      <Button variant={'contained'} color={'primary'}>
                        Invite Friends
                      </Button>
                    </Link>

              </DashboardPopover>
            )}
          />
          <CircleIcon
            style={{
              color: 'rgba(255, 255, 255, 0.8)',
            }}
            classes={{
              root: classes.circleIcon,
            }}
          />
          <Hearts
            app={app}
            user={user}
            showMaxHeartsFromTabsMessage
            dropdown={({ open, onClose, anchorElement }) => (
              <HeartsDropdown
                app={app}
                user={user}
                open={open}
                onClose={onClose}
                anchorElement={anchorElement}
                style={{
                  marginTop: 6,
                }}
              />
            )}
          />
          <SettingsButton
            dropdown={({ open, onClose, anchorElement }) => (
              <SettingsDropdown
                open={open}
                anchorElement={anchorElement}
                onClose={onClose}
                onLogoutClick={this.logout.bind(this)}
                isUserAnonymous={isUserAnonymous}
              />
            )}
          />

      </MuiThemeProvider>
    )
  }
}

UserMenu.propTypes = {
  app: PropTypes.shape({}).isRequired,
  browser: PropTypes.oneOf([
    CHROME_BROWSER,
    FIREFOX_BROWSER,
    UNSUPPORTED_BROWSER,
  ]).isRequired,
  classes: PropTypes.object.isRequired,
  isUserAnonymous: PropTypes.bool,
  onClickCampaignReopen: PropTypes.func,
  onClickSparklySearchIntroButton: PropTypes.func,
  showSparklySearchIntroButton: PropTypes.bool,
  user: PropTypes.shape({
    recruits: PropTypes.shape({
      recruitsWithAtLeastOneTab: PropTypes.number.isRequired,
    }).isRequired,
  }).isRequired,
}

UserMenu.defaultProps = {
  isUserAnonymous: false,
  onClickCampaignReopen: () => {},
  onClickSparklySearchIntroButton: () => {},
  showSparklySearchIntroButton: false,
}

export default withStyles(styles)(UserMenu)
<|endoftext|>


<commit_before>"use strict";
require("should");
var Voctopus = require("../src/voctopus.core").Voctopus;
var VoctopusSchemas = require("../src/voctopus.schemas.js");
var ExtDV = require("../src/voctopus.core").ExtDV;

/**
 * Used to loop through all 3 axes and check each voxel in several tests
 */
function loop3D(size, cbs) {
	var cbx, cby, cbz, x, y, z;
	cbx = typeof(cbs.x) === "function"?cbs.x:function(){};
	cby = typeof(cbs.y) === "function"?cbs.y:function(){};
	cbz = typeof(cbs.z) === "function"?cbs.z:function(){};
	for(x = 0; x < size; x++) {
		cbx([x,y,z]);
		for(y = 0; y < size; y++) {
			cby([x,y,z]);
			for(z = 0; z < size; z++) {
				cbz([x,y,z]);
			}
		}
	}
}

describe("ExtDV", function() {
	it("should implement Uint24 accessors", function() {
		this.timeout(10000);
		var i, n, buf, dv;
		buf = new ArrayBuffer(3);
		dv = new ExtDV(buf);
		n = Math.pow(2, 24);
		// this should give us decent coverage without trying every single number
		for(i = 1; i < n; i += 111) {
			dv.setUint24(0, i);
			dv.getUint24(0).should.equal(i);
		}
	});
});

describe("Voctopus", function() {
	var d, voc;
	beforeEach("set up a clean voctopus instance", function() {
		d = 5;
		voc = new Voctopus(d, VoctopusSchemas.RGBM);
	});
	it("should expose expected interfaces", function() {
		voc.should.have.property("freedOctets");
		voc.should.have.property("nextOctet");
		voc.should.have.property("buffer");
		voc.should.have.property("depth");
		(typeof(voc.octantOffset)).should.equal("function", "method octantOffset not implemented");
		(typeof(voc.getVoxel)).should.equal("function", "method getVoxel not implemented");
		(typeof(voc.setVoxel)).should.equal("function", "method setVoxel not implemented");
		(typeof(voc.getOctant)).should.equal("function", "method getOctant not implemented");
		(typeof(voc.setOctant)).should.equal("function", "method setOctant not implemented");
		(typeof(voc.getProperty)).should.equal("function", "method getProperty not implemented");
		(typeof(voc.setProperty)).should.equal("function", "method setProperty not implemented");
		(typeof(voc.allocateOctet)).should.equal("function", "method allocateOctet not implemented");
		(typeof(voc.expand)).should.equal("function", "method expand not implemented");
	});
	it("should implement octant schemas", function() {
		var prop;
		// default schema: RGBM
		for(prop of voc.schema) {
			prop.should.have.property("label");
			prop.should.have.property("offset");
			prop.should.have.property("length");
		}
		(voc.schema.find((el) => el.label === "pointer") === "undefined").should.be.false();
		voc.octantSize.should.equal(8);
		voc.octetSize.should.equal(64);
		voc.nextOctet.should.equal(72);
		// now check I8M schema
		voc = new Voctopus(5, VoctopusSchemas.I8M);
		for(prop of voc.schema) {
			prop.should.have.property("label");
			prop.should.have.property("offset");
			prop.should.have.property("length");
		}
		(voc.schema.find((el) => el.label === "pointer") === "undefined").should.be.false();
		voc.octantSize.should.equal(4);
		voc.octetSize.should.equal(32);
		voc.nextOctet.should.equal(36);
	});
	it("should correctly calculate the maximum size for a Voctopus", function() {
		var voxSize = voc.octantSize;
		voc = new Voctopus(1);
		voc.maxSize().should.eql(9*voxSize);
		voc = new Voctopus(2);
		voc.maxSize().should.eql(73*voxSize);
		voc = new Voctopus(3);
		voc.maxSize().should.eql(585*voxSize);
		voc = new Voctopus(4);
		voc.maxSize().should.eql(4681*voxSize);
		voc = new Voctopus(5);
		voc.maxSize().should.eql(37449*voxSize);
		voc = new Voctopus(6);
		voc.maxSize().should.eql(299593*voxSize);
		voc = new Voctopus(7);
		voc.maxSize().should.eql(2396745*voxSize);
		voc = new Voctopus(8);
		voc.maxSize().should.eql(19173961*voxSize);
	});
	it("should refuse to create an octree larger than the schema's pointer can handle", function() {
		var schema;
		// make a contrived schema with a tiny pointer
		schema = [{label:"value",length:1,offset:0},{label:"pointer",length:1,offset:1}];
		// try to make a Voctopus bigger than 256 elements (this would be
		(function() {new Voctopus(3, schema)}).should.throwError();
	});
	it("should always return 0 at depth 0 for octantOffset", function() {
		voc.octantOffset([ 0, 0, 0], 0).should.equal(0);
		voc.octantOffset([31, 0, 0], 0).should.equal(0);
		voc.octantOffset([ 0,31, 0], 0).should.equal(0);
		voc.octantOffset([31,31, 0], 0).should.equal(0);
		voc.octantOffset([ 0, 0,31], 0).should.equal(0);
		voc.octantOffset([31, 0,31], 0).should.equal(0);
		voc.octantOffset([ 0,31,31], 0).should.equal(0);
		voc.octantOffset([31,31,31], 0).should.equal(0);
	});
	it("should yield expected octant offsets (range 0-7 * octantSize) for a position vector", function() {
		var i;
		// These should have the same identity at any depth
		for(i = 1; i < d; i++) {
			voc.octantOffset([ 0, 0, 0], i).should.equal(0*voc.octantSize);
			voc.octantOffset([31, 0, 0], i).should.equal(1*voc.octantSize);
			voc.octantOffset([ 0,31, 0], i).should.equal(2*voc.octantSize);
			voc.octantOffset([31,31, 0], i).should.equal(3*voc.octantSize);
			voc.octantOffset([ 0, 0,31], i).should.equal(4*voc.octantSize);
			voc.octantOffset([31, 0,31], i).should.equal(5*voc.octantSize);
			voc.octantOffset([ 0,31,31], i).should.equal(6*voc.octantSize);
			voc.octantOffset([31,31,31], i).should.equal(7*voc.octantSize);
		}
		// for d == 2, coordinates corresponding to octet voc.octantSize at d == 1)
		for(i = 2; i < d; i++) {
			voc.octantOffset([ 0, 0, 0], 2).should.equal(0*voc.octantSize);
			voc.octantOffset([15, 0, 0], 2).should.equal(1*voc.octantSize);
			voc.octantOffset([ 0,15, 0], 2).should.equal(2*voc.octantSize);
			voc.octantOffset([15,15, 0], 2).should.equal(3*voc.octantSize);
			voc.octantOffset([ 0, 0,15], 2).should.equal(4*voc.octantSize);
			voc.octantOffset([15, 0,15], 2).should.equal(5*voc.octantSize);
			voc.octantOffset([ 0,15,15], 2).should.equal(6*voc.octantSize);
			voc.octantOffset([15,15,15], 2).should.equal(7*voc.octantSize);
		}
	});
	it("should generate a buffer of the correct length", function() {
		// should make a buffer of max size if the max size is less than 73*octantSize
		let voc = new Voctopus(1);
		voc.buffer.byteLength.should.equal(9*voc.octantSize);
		// anything larger than this should start out at a quarter of the max size
		for(var i = 2; i < 10; i++) {
			voc = new Voctopus(i);
			voc.buffer.byteLength.should.eql(voc.maxSize()/4, "buffer is one quarter of max length "+voc.maxSize());
		}
		// until we implement nested octrees 9 will be the max size for the RGBMP Voctant
		var fun = () => new Voctopus(i);
		for(i = 10; i < 16; i++) {
			(fun).should.throwError();
		}
	});
	it("should expand the buffer using expand", function() {
		var i, voc, ms;
		//var fun = () => {voc.expand()}
		for(i = 3; i < 8; i++) {
			voc = null;
			voc = new Voctopus(i);
			ms = voc.maxSize();
			voc.buffer.byteLength.should.equal(~~(ms/4));
			voc.expand();
			voc.buffer.byteLength.should.equal(~~(ms/3));
			voc.expand();
			voc.buffer.byteLength.should.equal(~~(ms/2));
			voc.expand();
			voc.buffer.byteLength.should.equal(ms);
			voc.expand().should.be.false();
			//(fun).should.throwError();
		}
	});
	it("should set voxel data at the right position with setVoxel", function() {
		var dv;
		// this should make a tree going down to 0,0
		voc.setVoxel([0,0,0], {r:31,g:63,b:255,material:1});
		dv = voc.view;
		// look at the raw data, since we haven't yet tested getVoxel
		dv.getUint32(4).should.eql(8, "root octant's pointer is pointing at the right offset");
		dv.getUint32(12).should.eql(72, "octant's pointer at depth 1 is pointing at the right offset");
		dv.getUint32(76).should.eql(136, "octant's pointer at depth 2 is pointing at the right offset");
		dv.getUint32(140).should.eql(200, "octant's pointer at depth 3 is pointing at the right offset");
		dv.getUint32(204).should.eql(264, "octant's pointer at depth 4 is pointing at the right offset");
		dv.getUint8(264).should.eql(31, "voxel's r value is correct");
		dv.getUint8(265).should.eql(63, "voxel's g value is correct");
		dv.getUint8(266).should.eql(255, "voxel's b value is correct");
		dv.getUint8(267).should.eql(1, "voxel's material value is correct");
		dv.getUint32(268).should.eql(0, "voxel's pointer value is correct");
	});
	it("should traverse the octree using traverse, optionally initializing octets as it goes", function() {
		voc.traverse([0,0,0]).should.equal(8);
		voc.traverse([0,0,0], true).should.equal(264);
		voc.traverse([0,0,0]).should.equal(264);
	});
	it("should walk the octree using walk, returning an array of pointers", function() {
		voc.walk([0,0,0]).should.eql(new Uint32Array([8,0,0,0,0]));
		voc.walk([0,0,0], true).should.eql(new Uint32Array([8, 72, 136, 200, 264]));
	});
	it("should get voxel data after setting it using getVoxel in RGBM schema", function() {
		this.timeout(10000);
		var size, x, y, z, i, index, vox, time, count = 0;
		voc = new Voctopus(6, VoctopusSchemas.RGBM);
		size = Math.pow(2, voc.depth - 1);
		time = new Date().getTime();
		loop3D(size, {
			y:() => i = 0,
			z:(pos) => {
				index = voc.setVoxel(pos, {r:i,g:i+1,b:i+2,material:i+3});
				i++;
				count++;
			}
		});
		time = new Date().getTime() - time;
		console.log("Time to populate RGBM:",time/1000+"s"," total voxels:",count);
		time = new Date().getTime();
		loop3D(size, {
			y:() => i = 0,
			z:(pos) => {
				vox = voc.getVoxel(pos);
				vox[0].should.equal(i, "octant at x:"+x+" y:"+y+" z:"+z+" has value "+i);
				vox[1].should.equal(i+1, "octant at x:"+x+" y:"+y+" z:"+z+" has value "+i);
				vox[2].should.equal(i+2, "octant at x:"+x+" y:"+y+" z:"+z+" has value "+i);
				vox[3].should.equal(i+3, "octant at x:"+x+" y:"+y+" z:"+z+" has value "+i);
				i++;
			}
		});
		time = new Date().getTime() - time;
		console.log("Time to check:",time/1000+"s");
	});
	it("should get voxel data after setting it using getVoxel in I8M schema", function() {
		this.timeout(10000);
		var size, i, index, vox, time, count = 0;
		voc = new Voctopus(6, VoctopusSchemas.I8M);
		size = Math.pow(2, voc.depth - 1);
		time = new Date().getTime();
		loop3D(size, {
			y:() => i = 0,
			z:(pos) => {
				index = voc.setVoxel(pos, {material:i});
				i++;
				count++;
			}
		});
		time = new Date().getTime() - time;
		console.log("Time to populate I8M:",time/1000+"s"," total voxels:",count);
		time = new Date().getTime();
		loop3D(size, {
			y:() => i = 0,
			z:(pos) => {
				vox = voc.getVoxel(pos);
				vox[0].should.equal(i, "octant at x:"+pos[0]+" y:"+pos[1]+" z:"+pos[2]+" has value "+i);
				i++;
			}
		});
		time = new Date().getTime() - time;
		console.log("Time to check:",time/1000+"s");
	});
	it("should initialize an octet's data to zero using initializeOctet", function() {
		var index, vox;
		// set the voxel first so we're grabbing the right data with getVoxel
		index = voc.setVoxel([0,0,0], {r:31,g:63,b:127,material:12});
		// the tree was empty so the start of the leaf octet should be 264 for a tree of depth 5 (calculated externally)
		voc.initializeOctet(index); // initialize the octet beginning at offset 1, which is the second down from root octant
		vox = voc.getOctant(index);
		vox[1].should.equal(0);
		vox[2].should.equal(0);
		vox[3].should.equal(0);
		vox[4].should.equal(0);
	});
	xit("should prune redundant branches using prune", function() {
		var i = 0;
		loop3D(16, {y:() => i++, z:(pos)=> voc.setVoxel(pos, {r:i,g:i,b:i,material:i})});
	});
});
<commit_msg>Removed obsolete test script.<commit_after><|endoftext|>


<commit_before>// Replace link to section with its title
//

'use strict';

var render = require('nodeca.core/lib/system/render/common');

module.exports = function (N) {

  N.wire.on('internal:common.embed.local', async function embed_section(data) {
    if (data.html) return;

    if (data.type !== 'inline') return;

    var match = N.router.matchAll(data.url).reduce((acc, match) => {
      if (match.meta.methods.get === 'forum.section') return match;
      return acc;
    }, null);

    if (!match) return;

    let section = await N.models.forum.Section
                            .findOne({ section_hid: match.params.hid })
                            .lean(true);
    if (section) {
      data.html = render(N, 'common.blocks.markup.internal_link', {
        href:    data.url,
        content: section.title
      }, {});
    }
  });
};
<commit_msg>Fix section link expansion<commit_after>// Replace link to section with its title
//

'use strict';

var render = require('nodeca.core/lib/system/render/common');

module.exports = function (N) {

  N.wire.on('internal:common.embed.local', async function embed_section(data) {
    if (data.html) return;

    if (data.type !== 'inline') return;

    var match = N.router.matchAll(data.url).reduce((acc, match) => {
      if (match.meta.methods.get === 'forum.section') return match;
      return acc;
    }, null);

    if (!match) return;

    let section = await N.models.forum.Section
                            .findOne({ section_hid: match.params.section_hid })
                            .lean(true);
    if (section) {
      data.html = render(N, 'common.blocks.markup.internal_link', {
        href:    data.url,
        content: section.title
      }, {});
    }
  });
};
<|endoftext|>