<commit_before>( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'liveCore', mw.KBasePlugin.extend({

		firstPlay : false,
		/**
		 * API requests interval for updating live stream status (Seconds).
		 * Default is 30 seconds, to match server's cache expiration
		 */
		liveStreamStatusInterval : 10,

		// Default DVR Window (Seconds)
		defaultDVRWindow : 30 * 60,

		onAirStatus: true,

		defaultConfig: {
			//time in ms to wait before displaying the offline alert
			offlineAlertOffest: 1000,
			//disable the islive check (force live to true)
			disableLiveCheck: false,
			//hide live indicators when playing offline from DVR
			hideOfflineIndicators: false
		},

		/**
		 * (only for iOS) indicates we passed the dvr window size and once we will seek backwards we should reAttach timUpdate events
		 */
		shouldReAttachTimeUpdate: false,

		playWhenOnline:false,

		/**
		 * In native HLS playback we don't get duration so we set it to maximum "currentTime" value
		 */
		maxCurrentTime: 0,

		/**
		 * indicates that we've received the first live status update
		 */
		liveStreamStatusUpdate : false,

		setup: function() {
			this.addPlayerBindings();
			this.extendApi();
		},
		/**
		 * Extend JS API to match the KDP
		 */
		extendApi: function() {
			var _this = this;

			this.getPlayer().isOffline = function() {
				return !_this.onAirStatus;
			}
		},

		addPoster: function(){
			this.getPlayer().removePosterFlag = false;
			this.getPlayer().updatePosterHTML();
		},

		removePoster: function(){
			this.getPlayer().removePoster();
			this.getPlayer().removePosterFlag = true;
		},

		addPlayerBindings: function() {
			var _this = this;
			var embedPlayer = this.getPlayer();

			this.bind( 'checkIsLive', function( e, callback ) {
				_this.getLiveStreamStatusFromAPI( callback );
			});

			this.bind( 'playerReady', function() {
				_this.isLiveChanged();
			} );

			this.bind( 'onpause', function() {
				if ( embedPlayer.isLive() && _this.isDVR() && _this.switchDone ) {
					embedPlayer.addPlayerSpinner();
					_this.getLiveStreamStatusFromAPI( function( onAirStatus ) {
						if ( onAirStatus ) {
							if ( _this.shouldHandlePausedMonitor() ) {
								_this.addPausedMonitor();
							}
						}
					} );
				}
			} );

			this.bind( 'firstPlay', function() {
				_this.firstPlay = true;
			} );

			this.bind( 'AdSupport_PreSequenceComplete', function() {
				_this.switchDone = true;
			} );

			this.bind( 'liveStreamStatusUpdate', function( e, onAirObj ) {

				if ( !_this.liveStreamStatusUpdate ) {
					_this.liveStreamStatusUpdate = true;
					if( onAirObj.onAirStatus ){
						_this.addPoster();
						_this.getPlayer().enablePlayControls();
					}else{
						_this.getPlayer().disablePlayControls();
					}
				}

				//check for pending autoPlay
				if ( onAirObj.onAirStatus &&
					embedPlayer.firstPlay &&
					embedPlayer.autoplay &&
					embedPlayer.canAutoPlay() &&
					!embedPlayer.isPlaying() ) {
					embedPlayer.play();
				}

				//if we moved from live to offline  - show message
				if ( _this.onAirStatus && !onAirObj.onAirStatus ) {

					//sometimes offline is only for a second and the message is not needed..
					setTimeout( function() {
						if ( !_this.onAirStatus ) {
							//if we already played once it means stream data was loaded. We can continue playing in "VOD" mode
							if ( !embedPlayer.firstPlay && _this.isDVR() ) {
								embedPlayer.triggerHelper( 'liveEventEnded' );
							} else {
								//remember last state
								_this.playWhenOnline = embedPlayer.isPlaying();

								_this.removePoster();
								embedPlayer.layoutBuilder.displayAlert( {
									title: embedPlayer.getKalturaMsg( 'ks-LIVE-STREAM-OFFLINE-TITLE' ),
									message: embedPlayer.getKalturaMsg( 'ks-LIVE-STREAM-OFFLINE' ),
									keepOverlay: true,
									noButtons : true,
									props: {
										customAlertTitleCssClass: "liveAlertTitle",
										customAlertMessageCssClass: "liveAlertMessage",
										customAlertContainerCssClass: "liveAlertContainer"
									}
								});
								_this.getPlayer().disablePlayControls();
							}

						}
					}, _this.getConfig( 'offlineAlertOffest' ) );

					embedPlayer.triggerHelper( 'liveOffline' );

				}  else if ( !_this.onAirStatus && onAirObj.onAirStatus ) {
					_this.addPoster();
					embedPlayer.layoutBuilder.closeAlert(); //moved from offline to online - hide the offline alert
					if ( !_this.getPlayer().getError() ) {
						_this.getPlayer().enablePlayControls();
					}
					if ( _this.playWhenOnline ) {
						embedPlayer.play();
						_this.playWhenOnline = false;
					}
					embedPlayer.triggerHelper( 'liveOnline' );
				}

				_this.onAirStatus = onAirObj.onAirStatus;

				if ( _this.isDVR() ) {
					if ( !onAirObj.onAirStatus ) {
						if ( _this.shouldHandlePausedMonitor() ) {
							_this.removePausedMonitor();
						}
					}
				}
			} );

			this.bind( 'durationChange', function( e, newDuration) {
				if ( _this.switchDone && embedPlayer.isLive() && _this.isDVR() && embedPlayer.paused ) {
					//refresh playhead position
					embedPlayer.triggerHelper( 'timeupdate', [ embedPlayer.getPlayerElementTime() ] );
					embedPlayer.triggerHelper( 'updatePlayHeadPercent', [ embedPlayer.getPlayerElementTime() / embedPlayer.duration ] );

				}
			});

			this.bind( 'liveEventEnded', function() {
				if ( embedPlayer.isLive() && _this.isDVR() ) {
					//change state to "VOD"
					embedPlayer.setLive( false );
					if ( _this.getConfig('hideOfflineIndicators') ) {
						_this.isLiveChanged();
					} else {
						//once moving back to live, set live state again
						embedPlayer.bindHelper( 'movingBackToLive', function() {
							embedPlayer.setLive( true );
							if ( _this.isNativeHLS() ) {
								embedPlayer.setDuration( _this.dvrWindow );
							}
						} );
					}

					if ( !_this.isNativeHLS() ) {
						embedPlayer.setDuration( embedPlayer.getPlayerElement().duration );
						embedPlayer.bindHelper( 'ended', function() {
							embedPlayer.getPlayerElement().seek( 0 );
						});
					}
				}
			});
		},

		isLiveChanged: function() {
			var _this = this;
			var embedPlayer = this.getPlayer();

			//ui components to hide
			var showComponentsArr = [];
			//ui components to show
			var hideComponentsArr = [];
			_this.maxCurrentTime = 0;
			//live entry
			if ( embedPlayer.isLive() ) {
				if ( !this.getConfig("disableLiveCheck")) {
					//the controls will be enabled upon liveStatus==true notification
					_this.removePoster();
					embedPlayer.disablePlayControls();
				}
				_this.addLiveStreamStatusMonitor();
				//hide source selector until we support live streams switching
				hideComponentsArr.push( 'sourceSelector' );
				embedPlayer.addPlayerSpinner();
				_this.getLiveStreamStatusFromAPI( function( onAirStatus ) {
					if ( !embedPlayer._checkHideSpinner ) {
						embedPlayer.hideSpinner();
					}
				} );
				_this.switchDone = true;
				if ( embedPlayer.sequenceProxy ) {
					_this.switchDone = false;
				}

				hideComponentsArr.push( 'durationLabel' );
				//live + DVR
				if ( _this.isDVR() ) {
					_this.dvrWindow = embedPlayer.evaluate( '{mediaProxy.entry.dvrWindow}' ) * 60;
					if ( !_this.dvrWindow ) {
						_this.dvrWindow = _this.defaultDVRWindow;
					}
					showComponentsArr.push( 'scrubber', 'currentTimeLabel' );
				} else {  //live + no DVR
					showComponentsArr.push( 'liveStatus' );
					hideComponentsArr.push( 'scrubber', 'currentTimeLabel' );
				}

				if ( _this.isNativeHLS() ) {
					_this.bind( 'timeupdate' , function() {
						var curTime = embedPlayer.getPlayerElementTime();

						if ( _this.isDVR() ) {
						  if ( curTime > _this.maxCurrentTime ) {
							_this.maxCurrentTime = curTime;
							embedPlayer.setDuration( _this.maxCurrentTime );

						  }
						}
					});
				}

				if ( _this.shouldHandlePausedMonitor() ) {
					_this.bind( 'playing', function() {
						if ( _this.isDVR() && _this.switchDone ) {
							//	_this.hideLiveStreamStatus();
							_this.removePausedMonitor();
						}
					} );
				}
			}
			//not a live entry: restore ui, hide live ui
			else {
				embedPlayer.removePosterFlag = false;
				hideComponentsArr.push( 'liveStatus' );
				showComponentsArr.push( 'sourceSelector', 'scrubber', 'durationLabel', 'currentTimeLabel' );
				_this.removeLiveStreamStatusMonitor();
				_this.unbind('timeupdate');
			}

			embedPlayer.triggerHelper('onShowInterfaceComponents', [ showComponentsArr ] );
			embedPlayer.triggerHelper('onHideInterfaceComponents', [ hideComponentsArr ] );
		},

		isDVR: function(){
			return ( this.getPlayer().evaluate( '{mediaProxy.entry.dvrStatus}' )  && this.getPlayer().isTimeUpdateSupported() );
		},

		getCurrentTime: function() {
			return this.getPlayer().getPlayerElement().currentTime;
		},

		removeMinDVRMonitor: function() {
			this.log( "removeMinDVRMonitor" );
			this.minDVRMonitor = clearInterval( this.minDVRMonitor );
		},

		/**
		 * API Requests to update on/off air status
		 */
		addLiveStreamStatusMonitor: function() {
			//if player is in error state- no need for islive calls
			if ( this.embedPlayer.getError() ) {
				return;
			}
			this.log( "addLiveStreamStatusMonitor" );
			var _this = this;
			this.liveStreamStatusMonitor = setInterval( function() {
				_this.getLiveStreamStatusFromAPI();
			}, _this.liveStreamStatusInterval * 1000 );
		},

		removeLiveStreamStatusMonitor: function() {
			this.log( "removeLiveStreamStatusMonitor" );
			this.liveStreamStatusMonitor = clearInterval( this.liveStreamStatusMonitor );
		},

		/**
		 * indicates if we should handle paused monitor.
		 */
		shouldHandlePausedMonitor: function() {
			if ( this.isNativeHLS() ) {
				return true;
			}
			return false;
		},

		/**
		 * Updating display time & scrubber while in paused state
		 */
		addPausedMonitor: function() {
			var _this = this;
			var embedPlayer = this.embedPlayer;
			var pauseTime = _this.maxCurrentTime;
			if ( pauseTime == 0 ) {
				pauseTime = embedPlayer.getPlayerElementTime();
			}
			var pauseClockTime = Date.now();
			this.log( "addPausedMonitor :   Monitor rate = " + mw.getConfig( 'EmbedPlayer.MonitorRate' ) );
			this.pausedMonitor = setInterval( function() {
				var timePassed = ( Date.now() - pauseClockTime ) / 1000;
				embedPlayer.setDuration( pauseTime + timePassed );
			}, 1000 );
		},

		removePausedMonitor: function() {
			this.log( "removePausedMonitor" );
			this.pausedMonitor = clearInterval( this.pausedMonitor );
		},

		/**
		 * Get on/off air status based on the API and update locally
		 */
		getLiveStreamStatusFromAPI: function( callback ) {
			var _this = this;
			var embedPlayer = this.getPlayer();

			if ( embedPlayer.getFlashvars( 'streamerType') == 'rtmp' ) {
				if ( callback ) {
					callback( _this.onAirStatus );
				}
				return;
			}

			if (this.getConfig("disableLiveCheck")){
				if ( callback ) {
					callback( true );
				}
				embedPlayer.triggerHelper( 'liveStreamStatusUpdate', { 'onAirStatus' : true } );
				return;
			}

			var service = 'liveStream';
			//type liveChannel
			if ( embedPlayer.kalturaPlayerMetaData && embedPlayer.kalturaPlayerMetaData.type == 8 ) {
				service = 'liveChannel';
			}
			var protocol = 'hls';
			if ( embedPlayer.streamerType != 'http' ) {
				protocol = embedPlayer.streamerType;
			}
			_this.getKalturaClient().doRequest( {
				'service' : service,
				'action' : 'islive',
				'id' : embedPlayer.kentryid,
				'protocol' : protocol,
				'partnerId': embedPlayer.kpartnerid
			}, function( data ) {
				var onAirStatus = false;
				if ( data === true ) {
					onAirStatus = true;
				}
				if ( callback ) {
					callback( onAirStatus );
				}
				embedPlayer.triggerHelper( 'liveStreamStatusUpdate', { 'onAirStatus' : onAirStatus } );
			},mw.getConfig("SkipKSOnIsLiveRequest"),function(){
				mw.log("Error occur while trying to check onAir status");
				embedPlayer.triggerHelper( 'liveStreamStatusUpdate', { 'onAirStatus' : false } );
			} );
		},

		getKalturaClient: function() {
			if( ! this.kClient ) {
				this.kClient = mw.kApiGetPartnerClient( this.embedPlayer.kwidgetid );
			}
			return this.kClient;
		},

		log: function( msg ) {
			mw.log( "LiveStream :: " + msg);
		},

		isNativeHLS: function() {
			if ( mw.isIOS() || mw.isDesktopSafari() || mw.isAndroid() ) {
				return true;
			}
			return false;
		}

	}));

} )( window.mw, window.jQuery );<commit_msg>#FEC-2457 #comment fix live auto play<commit_after>( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'liveCore', mw.KBasePlugin.extend({

		firstPlay : false,
		/**
		 * API requests interval for updating live stream status (Seconds).
		 * Default is 30 seconds, to match server's cache expiration
		 */
		liveStreamStatusInterval : 10,

		// Default DVR Window (Seconds)
		defaultDVRWindow : 30 * 60,

		onAirStatus: true,

		defaultConfig: {
			//time in ms to wait before displaying the offline alert
			offlineAlertOffest: 1000,
			//disable the islive check (force live to true)
			disableLiveCheck: false,
			//hide live indicators when playing offline from DVR
			hideOfflineIndicators: false
		},

		/**
		 * (only for iOS) indicates we passed the dvr window size and once we will seek backwards we should reAttach timUpdate events
		 */
		shouldReAttachTimeUpdate: false,

		playWhenOnline:false,

		/**
		 * In native HLS playback we don't get duration so we set it to maximum "currentTime" value
		 */
		maxCurrentTime: 0,

		/**
		 * indicates that we've received the first live status update
		 */
		liveStreamStatusUpdate : false,

		setup: function() {
			this.addPlayerBindings();
			this.extendApi();
		},
		/**
		 * Extend JS API to match the KDP
		 */
		extendApi: function() {
			var _this = this;

			this.getPlayer().isOffline = function() {
				return !_this.onAirStatus;
			}
		},

		addPoster: function(){
			this.getPlayer().removePosterFlag = false;
			this.getPlayer().updatePosterHTML();
		},

		removePoster: function(){
			this.getPlayer().removePoster();
			this.getPlayer().removePosterFlag = true;
		},

		addPlayerBindings: function() {
			var _this = this;
			var embedPlayer = this.getPlayer();

			this.bind( 'checkIsLive', function( e, callback ) {
				_this.getLiveStreamStatusFromAPI( callback );
			});

			this.bind( 'playerReady', function() {
				_this.isLiveChanged();
			} );

			this.bind( 'onpause', function() {
				if ( embedPlayer.isLive() && _this.isDVR() && _this.switchDone ) {
					embedPlayer.addPlayerSpinner();
					_this.getLiveStreamStatusFromAPI( function( onAirStatus ) {
						if ( onAirStatus ) {
							if ( _this.shouldHandlePausedMonitor() ) {
								_this.addPausedMonitor();
							}
						}
					} );
				}
			} );

			this.bind( 'firstPlay', function() {
				_this.firstPlay = true;
			} );

			this.bind( 'AdSupport_PreSequenceComplete', function() {
				_this.switchDone = true;
			} );

			this.bind( 'liveStreamStatusUpdate', function( e, onAirObj ) {

				if ( !_this.liveStreamStatusUpdate ) {
					_this.liveStreamStatusUpdate = true;
					if( onAirObj.onAirStatus ){
						_this.addPoster();
						_this.getPlayer().enablePlayControls();
					}else{
						_this.getPlayer().disablePlayControls();
					}
				}

				//if we moved from live to offline  - show message
				if ( _this.onAirStatus && !onAirObj.onAirStatus ) {

					//sometimes offline is only for a second and the message is not needed..
					setTimeout( function() {
						if ( !_this.onAirStatus ) {
							//if we already played once it means stream data was loaded. We can continue playing in "VOD" mode
							if ( !embedPlayer.firstPlay && _this.isDVR() ) {
								embedPlayer.triggerHelper( 'liveEventEnded' );
							} else {
								//remember last state
								_this.playWhenOnline = embedPlayer.isPlaying();

								_this.removePoster();
								embedPlayer.layoutBuilder.displayAlert( {
									title: embedPlayer.getKalturaMsg( 'ks-LIVE-STREAM-OFFLINE-TITLE' ),
									message: embedPlayer.getKalturaMsg( 'ks-LIVE-STREAM-OFFLINE' ),
									keepOverlay: true,
									noButtons : true,
									props: {
										customAlertTitleCssClass: "liveAlertTitle",
										customAlertMessageCssClass: "liveAlertMessage",
										customAlertContainerCssClass: "liveAlertContainer"
									}
								});
								_this.getPlayer().disablePlayControls();
							}

						}
					}, _this.getConfig( 'offlineAlertOffest' ) );

					embedPlayer.triggerHelper( 'liveOffline' );

				}  else if ( !_this.onAirStatus && onAirObj.onAirStatus ) {
					_this.addPoster();
					embedPlayer.layoutBuilder.closeAlert(); //moved from offline to online - hide the offline alert
					if ( !_this.getPlayer().getError() ) {
						_this.getPlayer().enablePlayControls();
					}
					if ( _this.playWhenOnline ) {
						embedPlayer.play();
						_this.playWhenOnline = false;
					}
					embedPlayer.triggerHelper( 'liveOnline' );
				}

				//check for pending autoPlay
				if ( onAirObj.onAirStatus &&
					embedPlayer.firstPlay &&
					embedPlayer.autoplay &&
					embedPlayer.canAutoPlay() &&
					!embedPlayer.isPlaying() ) {
					embedPlayer.play();
				}

				_this.onAirStatus = onAirObj.onAirStatus;

				if ( _this.isDVR() ) {
					if ( !onAirObj.onAirStatus ) {
						if ( _this.shouldHandlePausedMonitor() ) {
							_this.removePausedMonitor();
						}
					}
				}
			} );

			this.bind( 'durationChange', function( e, newDuration) {
				if ( _this.switchDone && embedPlayer.isLive() && _this.isDVR() && embedPlayer.paused ) {
					//refresh playhead position
					embedPlayer.triggerHelper( 'timeupdate', [ embedPlayer.getPlayerElementTime() ] );
					embedPlayer.triggerHelper( 'updatePlayHeadPercent', [ embedPlayer.getPlayerElementTime() / embedPlayer.duration ] );

				}
			});

			this.bind( 'liveEventEnded', function() {
				if ( embedPlayer.isLive() && _this.isDVR() ) {
					//change state to "VOD"
					embedPlayer.setLive( false );
					if ( _this.getConfig('hideOfflineIndicators') ) {
						_this.isLiveChanged();
					} else {
						//once moving back to live, set live state again
						embedPlayer.bindHelper( 'movingBackToLive', function() {
							embedPlayer.setLive( true );
							if ( _this.isNativeHLS() ) {
								embedPlayer.setDuration( _this.dvrWindow );
							}
						} );
					}

					if ( !_this.isNativeHLS() ) {
						embedPlayer.setDuration( embedPlayer.getPlayerElement().duration );
						embedPlayer.bindHelper( 'ended', function() {
							embedPlayer.getPlayerElement().seek( 0 );
						});
					}
				}
			});
		},

		isLiveChanged: function() {
			var _this = this;
			var embedPlayer = this.getPlayer();

			//ui components to hide
			var showComponentsArr = [];
			//ui components to show
			var hideComponentsArr = [];
			_this.maxCurrentTime = 0;
			//live entry
			if ( embedPlayer.isLive() ) {
				if ( !this.getConfig("disableLiveCheck")) {
					//the controls will be enabled upon liveStatus==true notification
					_this.removePoster();
					embedPlayer.disablePlayControls();
				}
				_this.addLiveStreamStatusMonitor();
				//hide source selector until we support live streams switching
				hideComponentsArr.push( 'sourceSelector' );
				embedPlayer.addPlayerSpinner();
				_this.getLiveStreamStatusFromAPI( function( onAirStatus ) {
					if ( !embedPlayer._checkHideSpinner ) {
						embedPlayer.hideSpinner();
					}
				} );
				_this.switchDone = true;
				if ( embedPlayer.sequenceProxy ) {
					_this.switchDone = false;
				}

				hideComponentsArr.push( 'durationLabel' );
				//live + DVR
				if ( _this.isDVR() ) {
					_this.dvrWindow = embedPlayer.evaluate( '{mediaProxy.entry.dvrWindow}' ) * 60;
					if ( !_this.dvrWindow ) {
						_this.dvrWindow = _this.defaultDVRWindow;
					}
					showComponentsArr.push( 'scrubber', 'currentTimeLabel' );
				} else {  //live + no DVR
					showComponentsArr.push( 'liveStatus' );
					hideComponentsArr.push( 'scrubber', 'currentTimeLabel' );
				}

				if ( _this.isNativeHLS() ) {
					_this.bind( 'timeupdate' , function() {
						var curTime = embedPlayer.getPlayerElementTime();

						if ( _this.isDVR() ) {
						  if ( curTime > _this.maxCurrentTime ) {
							_this.maxCurrentTime = curTime;
							embedPlayer.setDuration( _this.maxCurrentTime );

						  }
						}
					});
				}

				if ( _this.shouldHandlePausedMonitor() ) {
					_this.bind( 'playing', function() {
						if ( _this.isDVR() && _this.switchDone ) {
							//	_this.hideLiveStreamStatus();
							_this.removePausedMonitor();
						}
					} );
				}
			}
			//not a live entry: restore ui, hide live ui
			else {
				embedPlayer.removePosterFlag = false;
				hideComponentsArr.push( 'liveStatus' );
				showComponentsArr.push( 'sourceSelector', 'scrubber', 'durationLabel', 'currentTimeLabel' );
				_this.removeLiveStreamStatusMonitor();
				_this.unbind('timeupdate');
			}

			embedPlayer.triggerHelper('onShowInterfaceComponents', [ showComponentsArr ] );
			embedPlayer.triggerHelper('onHideInterfaceComponents', [ hideComponentsArr ] );
		},

		isDVR: function(){
			return ( this.getPlayer().evaluate( '{mediaProxy.entry.dvrStatus}' )  && this.getPlayer().isTimeUpdateSupported() );
		},

		getCurrentTime: function() {
			return this.getPlayer().getPlayerElement().currentTime;
		},

		removeMinDVRMonitor: function() {
			this.log( "removeMinDVRMonitor" );
			this.minDVRMonitor = clearInterval( this.minDVRMonitor );
		},

		/**
		 * API Requests to update on/off air status
		 */
		addLiveStreamStatusMonitor: function() {
			//if player is in error state- no need for islive calls
			if ( this.embedPlayer.getError() ) {
				return;
			}
			this.log( "addLiveStreamStatusMonitor" );
			var _this = this;
			this.liveStreamStatusMonitor = setInterval( function() {
				_this.getLiveStreamStatusFromAPI();
			}, _this.liveStreamStatusInterval * 1000 );
		},

		removeLiveStreamStatusMonitor: function() {
			this.log( "removeLiveStreamStatusMonitor" );
			this.liveStreamStatusMonitor = clearInterval( this.liveStreamStatusMonitor );
		},

		/**
		 * indicates if we should handle paused monitor.
		 */
		shouldHandlePausedMonitor: function() {
			if ( this.isNativeHLS() ) {
				return true;
			}
			return false;
		},

		/**
		 * Updating display time & scrubber while in paused state
		 */
		addPausedMonitor: function() {
			var _this = this;
			var embedPlayer = this.embedPlayer;
			var pauseTime = _this.maxCurrentTime;
			if ( pauseTime == 0 ) {
				pauseTime = embedPlayer.getPlayerElementTime();
			}
			var pauseClockTime = Date.now();
			this.log( "addPausedMonitor :   Monitor rate = " + mw.getConfig( 'EmbedPlayer.MonitorRate' ) );
			this.pausedMonitor = setInterval( function() {
				var timePassed = ( Date.now() - pauseClockTime ) / 1000;
				embedPlayer.setDuration( pauseTime + timePassed );
			}, 1000 );
		},

		removePausedMonitor: function() {
			this.log( "removePausedMonitor" );
			this.pausedMonitor = clearInterval( this.pausedMonitor );
		},

		/**
		 * Get on/off air status based on the API and update locally
		 */
		getLiveStreamStatusFromAPI: function( callback ) {
			var _this = this;
			var embedPlayer = this.getPlayer();

			if ( embedPlayer.getFlashvars( 'streamerType') == 'rtmp' ) {
				if ( callback ) {
					callback( _this.onAirStatus );
				}
				return;
			}

			if (this.getConfig("disableLiveCheck")){
				if ( callback ) {
					callback( true );
				}
				embedPlayer.triggerHelper( 'liveStreamStatusUpdate', { 'onAirStatus' : true } );
				return;
			}

			var service = 'liveStream';
			//type liveChannel
			if ( embedPlayer.kalturaPlayerMetaData && embedPlayer.kalturaPlayerMetaData.type == 8 ) {
				service = 'liveChannel';
			}
			var protocol = 'hls';
			if ( embedPlayer.streamerType != 'http' ) {
				protocol = embedPlayer.streamerType;
			}
			_this.getKalturaClient().doRequest( {
				'service' : service,
				'action' : 'islive',
				'id' : embedPlayer.kentryid,
				'protocol' : protocol,
				'partnerId': embedPlayer.kpartnerid
			}, function( data ) {
				var onAirStatus = false;
				if ( data === true ) {
					onAirStatus = true;
				}
				if ( callback ) {
					callback( onAirStatus );
				}
				embedPlayer.triggerHelper( 'liveStreamStatusUpdate', { 'onAirStatus' : onAirStatus } );
			},mw.getConfig("SkipKSOnIsLiveRequest"),function(){
				mw.log("Error occur while trying to check onAir status");
				embedPlayer.triggerHelper( 'liveStreamStatusUpdate', { 'onAirStatus' : false } );
			} );
		},

		getKalturaClient: function() {
			if( ! this.kClient ) {
				this.kClient = mw.kApiGetPartnerClient( this.embedPlayer.kwidgetid );
			}
			return this.kClient;
		},

		log: function( msg ) {
			mw.log( "LiveStream :: " + msg);
		},

		isNativeHLS: function() {
			if ( mw.isIOS() || mw.isDesktopSafari() || mw.isAndroid() ) {
				return true;
			}
			return false;
		}

	}));

} )( window.mw, window.jQuery );<|endoftext|>


<commit_before>// https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
(function () {
    "use strict";

    var parameters = {
        ref: "src",
        sinon: false
    };

    function addScriptTag (src) {
        var script = document.createElement("script");
        script.setAttribute("src", src);
        document.querySelector("head").appendChild(script);
    }

    function include (reference) {
        if ("src" !== reference) {
            reference = "ref/" + reference;
        }
        addScriptTag(reference + "/test.js");
        if (!parameters.sinon) {
            addScriptTag(reference + "/sinon.js");
        }
    }

    window.location.search.split("&").forEach(function (parameter, index) {
        if (0 === index) {
            // search starts with ?
            parameter = parameter.substr(1);
        }
        // Parameter is composed of name[=value]?
        var pair = parameter.split("=");
        if (1 === pair.length) {
            pair.push(true);
        }
        parameters[pair[0]] = pair[1];
    });

    include(parameters.ref);
    if (parameters.sinon) {
        addScriptTag("node_modules/sinon/pkg/sinon.js");
    }

}());
<commit_msg>Adds loader panel<commit_after>// https://en.wikipedia.org/wiki/Immediately-invoked_function_expression
(function () {
    "use strict";

    var parameters = {
        ref: "src",
        sinon: false
    };

    function addElement (parent, type, attributes) {
        var element = document.createElement(type);
        Object.keys(attributes).forEach(function (name) {
            element.setAttribute(name, attributes[name]);
        });
        return parent.appendChild(element);
    }

    function addScriptElement (src) {
        addElement(document.querySelector("head"), "script", {
            src: src
        });
    }

    function include (reference) {
        if ("src" !== reference) {
            reference = "ref/" + reference;
        }
        addScriptElement(reference + "/test.js");
        if (!parameters.sinon) {
            addScriptElement(reference + "/sinon.js");
        }
    }

    window.location.search.split("&").forEach(function (parameter, index) {
        if (0 === index) {
            // search starts with ?
            parameter = parameter.substr(1);
        }
        // Parameter is composed of name[=value]?
        var pair = parameter.split("=");
        if (1 === pair.length) {
            pair.push(true);
        }
        parameters[pair[0]] = pair[1];
    });

    include(parameters.ref);
    if (parameters.sinon) {
        addScriptElement("node_modules/sinon/pkg/sinon.js");
    }

    window.addEventListener("load", function () {
        addElement(document.body, "iframe", {
            src: "loader.html"
        });
    });

}());
<|endoftext|>


<commit_before>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import Snakeskin from '../core';
import { ws } from '../helpers/string';
import { any } from '../helpers/gcc';

Snakeskin.addDirective(
	'return',

	{
		group: 'return',
		placement: 'template'
	},

	function (command) {
		const
			val = command ? this.out(command, {unsafe: true}) : this.getReturnResultDecl(),
			parent = any(this.hasParentFunction());

		if (!parent || parent.block) {
			this.append(`return ${val};`);
			return;
		}

		const def = ws`
			__RETURN__ = true;
			__RETURN_VAL__ = ${val};
		`;

		let str = '';
		if (parent.asyncParent) {
			if (this.getGroup('Async')[parent.asyncParent]) {
				str += def;

				if (this.getGroup('waterfall')[parent.asyncParent]) {
					str += 'return arguments[arguments.length - 1](__RETURN_VAL__);';

				} else {
					str += ws`
						if (typeof arguments[0] === 'function') {
							return arguments[0](__RETURN_VAL__);
						}

						return false;
					`;
				}

			} else {
				str += 'return false;';
			}

		} else {
			if (parent && !this.getGroup('async')[parent.target.name]) {
				str += def;
				this.deferReturn = 1;
			}

			str += 'return false;';
		}

		this.append(str);
	}
);
<commit_msg>Changed return to block<commit_after>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import Snakeskin from '../core';
import { ws } from '../helpers/string';
import { any } from '../helpers/gcc';

Snakeskin.addDirective(
	'return',

	{
		block: true,
		deferInit: true,
		group: ['return', 'microTemplate'],
		placement: 'template'
	},

	function (command) {
		if (command.slice(-1) === '/') {
			this.startInlineDir(null, {command: command.slice(0, -1)});
			return;
		}

		this.startDir(null, {command});

		if (!command) {
			this.wrap(`__RESULT__ = ${this.getResultDecl()};`);
		}
	},

	function () {
		const
			{command} = this.structure.params;

		const
			val = command ? this.out(command, {unsafe: true}) : this.getReturnResultDecl(),
			parent = any(this.hasParentFunction());

		if (!parent || parent.block) {
			this.append(`return ${val};`);
			return;
		}

		const def = ws`
			__RETURN__ = true;
			__RETURN_VAL__ = ${val};
		`;

		let str = '';
		if (parent.asyncParent) {
			if (this.getGroup('Async')[parent.asyncParent]) {
				str += def;

				if (this.getGroup('waterfall')[parent.asyncParent]) {
					str += 'return arguments[arguments.length - 1](__RETURN_VAL__);';

				} else {
					str += ws`
						if (typeof arguments[0] === 'function') {
							return arguments[0](__RETURN_VAL__);
						}

						return false;
					`;
				}

			} else {
				str += 'return false;';
			}

		} else {
			if (parent && !this.getGroup('async')[parent.target.name]) {
				str += def;
				this.deferReturn = 1;
			}

			str += 'return false;';
		}

		this.append(str);
	}
);
<|endoftext|>


<commit_before>function Graph(canvas)
{
	var canvas = canvas;
	var context = canvas.getContext('2d');
	var canvasW = canvas.width;
	var canvasH = canvas.height;
	var canvasR = Math.min(canvasW, canvasH) * 0.5;
	var canvasAspect = canvasW / canvasH;

	var minX;
	var maxX;
	var minY;
	var maxY;

	var unitsPerPixel = {x:0, y:0};
	var dragStartPos = {x:-1, y:-1};
	var dragOffset = {x:0, y:0}
	var g_MousePos = {x:0, y:0}
	var g_MouseActive = false;

	var legendPos = {x:0, y:0};
	var tickDelta = {x:0, y:0};

    var enableLegend = false;
    var enableAxes = false;

	var plotFunctions = [];

	function init()
	{
		canvas.addEventListener('mousemove', onMouseMove, false);
		canvas.addEventListener('mousedown', onMouseDown, false);
		canvas.addEventListener('mouseenter', onMouseEnter, false);
		canvas.addEventListener('mouseleave', onMouseLeave, false);
		canvas.addEventListener('mouseup', onMouseUp, false);
		canvas.addEventListener('wheel', onMouseWheel, false);

		reset();
	}

	function setLimits(_minX, _maxX, _minY, _maxY)
	{
		minX = _minX;
		maxX = _maxX;
		minY = _minY;
		maxY = _maxY;

		unitsPerPixel.x = (maxX-minX);
		unitsPerPixel.y = (maxY-minY);
	}

	function getLimits()
	{
		return {minX:minX, maxX:maxX, minY:minY, maxY:maxY};
	}

	function XC(x)
	{
		return (x - minX) / (maxX - minX) * canvasW ;
	}

	function YC(y)
	{
		return canvasH - (y - minY) / (maxY - minY) * canvasH ;
	}

	function onMouseEnter(evt)
	{
		g_MouseActive = true;
		draw();
	}

	function onMouseLeave(evt)
	{
		g_MouseActive = false;
		draw();
	}

	function onMouseDown(evt)
	{
		var m = getMousePos(evt, canvas);
		g_MousePos = getMousePos(evt, canvas);

		dragStartPos = m;
		dragOffset.x = 0;
		dragOffset.y = 0;
	}

	function onMouseUp(evt)
	{
	}

	function onMouseWheel(evt)
	{
		g_MouseActive = true;
		var m = getMousePos(evt, canvas);
		g_MousePos = getMousePos(evt, canvas);

		var zoomCenter = m;
		zoomCenter.x = minX + (zoomCenter.x) * (maxX-minX);
		zoomCenter.y = maxY - (zoomCenter.y) * (maxY-minY);

		var zoomFactor = 1.0 + Math.sign(evt.deltaY) * 0.1;

		minX = zoomCenter.x - (zoomCenter.x - minX) * zoomFactor;
		maxX = zoomCenter.x + (maxX-zoomCenter.x) * zoomFactor;

		minY = zoomCenter.y - (zoomCenter.y - minY) * zoomFactor;
		maxY = zoomCenter.y + (maxY-zoomCenter.y) * zoomFactor;

//		minX = round(minX);
//		maxX = round(maxX);
//		minY = round(minY);
//		maxY = round(maxY);

		setLimits(minX, maxX, minY, maxY);
		draw();
	}

	function onMouseMove(evt)
	{
		g_MouseActive = true;
		var m = getMousePos(evt, canvas);
		g_MousePos = getMousePos(evt, canvas);

		if (evt.buttons & 1)
		{
			minX -= dragOffset.x;
			maxX -= dragOffset.x;
			minY -= dragOffset.y;
			maxY -= dragOffset.y;

			dragOffset.x = -(m.x - dragStartPos.x) * unitsPerPixel.x;
			dragOffset.y = (m.y - dragStartPos.y) * unitsPerPixel.y;

			dragOffset.x = Math.round(dragOffset.x);
			dragOffset.y = Math.round(dragOffset.y);

			minX += dragOffset.x;
			maxX += dragOffset.x;
			minY += dragOffset.y;
			maxY += dragOffset.y;
		}

		draw();
	}

	function draw()
	{
		clear();

		drawAxes();

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			plotFunction2D(plotFunctions[i][0], plotFunctions[i][1], plotFunctions[i][2], plotFunctions[i][3]);
		}

		drawLegend();

		if (g_MouseActive)
		{
			drawMouseLegent();
		}
	}

	function drawMouseLegent()
	{
		var mouseGraphX = minX + (g_MousePos.x) * (maxX-minX);
		var mouseGraphY = maxY - (g_MousePos.y) * (maxY-minY);

		var x = g_MousePos.x * canvasW;
		var y = g_MousePos.y * canvasH;

		var align = g_MousePos.x>0.5 ? "right" : "left";

		// Shift text so that it's not under mouse cursor
		if (g_MousePos.x<=0.5)
		{
			x += 10;
		}
		else
		{
			x -=5;
		}

		drawText(x, y, mouseGraphX.toFixed(2) + ", " + mouseGraphY.toFixed(2), "#000000", align);
		y += 10;

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			var F = plotFunctions[i][0];
			var steps = plotFunctions[i][1];
			var color = plotFunctions[i][2];
			var label = plotFunctions[i][3];

			drawText(x, y, label + " : " + F(mouseGraphX).toFixed(2), color, align);

			y += 10;
		}

	}

	function drawText(x,y,text,color,align)
	{
		if (typeof(color) === "undefined")
			color = "#000000";

		if (typeof(align) === "undefined")
			align = "center";

		context.save();

		context.font = "10px Arial";
		context.textAlign = align;
		context.fillStyle = color;

		context.fillText(text, x, y);

		context.restore();
	}

	function drawLine(x0,y0,x1,y1,color,width)
	{
		context.save() ;
		context.lineWidth = width;
		context.strokeStyle = color;

		context.beginPath() ;
		context.moveTo(x0,y0) ;
		context.lineTo(x1,y1) ;
		context.stroke() ;

		context.restore();
	}

	function drawGraphLine(x0,y0,x1,y1,color,width)
	{
		drawLine(XC(x0),YC(y0),XC(x1),YC(y1),color,width) ;
	}

	function reset()
	{
		clear();
		plotFunctions = [];
	}

	function clear()
	{
		context.clearRect(0,0,canvasW,canvasH) ;
	}

	function addFunction2D(F, stepsX, color, label)
	{
		plotFunctions.push([F, stepsX, color, label]);
	}

	function plotFunction2D(F, stepsX, color, label)
	{
		context.save() ;

		context.beginPath();

		context.moveTo( XC(minX), YC( F(minX) ) ) ;

		deltaX = (maxX-minX)/stepsX;

		for (var x = minX; x <= maxX; x += deltaX)
		{
			context.lineTo( XC(x), YC( F(x) ) ) ;
		}

		context.lineWidth = 1 ;
		context.strokeStyle = color;
		context.stroke();

		context.restore() ;
	}

	function showAxes(tickDeltaX, tickDeltaY)
    {
  		tickDelta.x = tickDeltaX;
		tickDelta.y = tickDeltaY;
        enableAxes = true;
    }

	function hideAxes()
    {
        enableAxes = false;
    }

	function drawAxes()
	{
        if (!enableAxes)
            return;

		context.save();
		context.lineWidth = 1 ;

		for (var x = Math.floor(minX/tickDelta.x)*tickDelta.x; x <= Math.floor(maxX/tickDelta.x)*tickDelta.x; x += tickDelta.x)
		{
			drawGraphLine(x, minY, x, maxY, "#808080", 1);
		}

		for (var y = Math.floor(minY/tickDelta.y)*tickDelta.y; y <= Math.floor(maxY/tickDelta.y)*tickDelta.y; y += tickDelta.y)
		{
			drawGraphLine(minX, y, maxX, y, "#808080", 1);
		}

		drawGraphLine(minX, 0, maxX, 0, "#000000", 1.5);
		drawGraphLine(0, minY, 0, maxY, "#000000", 1.5);

		context.fillStyle = "blue";
		context.font = "bold 16px Arial";

		var textX = Math.max(0, Math.min(canvasW-20, XC(0)+5));
		var textY = Math.max(0, Math.min(canvasH-5, YC(0)+20));

		context.fillText(minX.toFixed(2), XC(minX)+5, Math.min(canvasH-20, textY));
		context.fillText(maxX.toFixed(2), XC(maxX)-21, textY);
		context.fillText(minY.toFixed(2), textX, YC(minY)-5);
		context.fillText(maxY.toFixed(2), textX, YC(maxY)+16);

		context.restore();
	}

    function showLegend(x, y)
    {
        enableLegend = true;
		legendPos.x = x;
		legendPos.y = y;
    }

    function hideLegend()
    {
        enableLegend = false;
    }

	function drawLegend()
	{
        if (!enableLegend)
            return;

		var maxWidth = 0;

		context.save();

		context.font = "bold 12px Arial";

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			maxWidth = Math.max(maxWidth, context.measureText(plotFunctions[i][3]).width);
		}

		var x = legendPos.x;
		var y = legendPos.y;

		context.beginPath();
		context.rect(x,y,40+maxWidth, 20*plotFunctions.length+10);
		context.fillStyle = 'white';
		context.fill();
		context.lineWidth = 2;
		context.strokeStyle = 'black';
		context.stroke();

		context.fillStyle = "blue";

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			drawLine(x+5, y + i*20+15, x+5+20, y + i*20+15, plotFunctions[i][2], 1.0);

			context.fillText(plotFunctions[i][3], x+5+20+5,y + i*20+15+4);
		}

		context.restore();
	}

	function getCanvas()
	{
		return canvas;
	}

	function getContext()
	{
		return context;
	}

	init();

	this.setLimits = setLimits;
	this.getLimits = getLimits;
	this.addFunction2D = addFunction2D;

	this.showAxes = showAxes;
	this.hideAxes = hideAxes;

	this.showLegend = showLegend;
	this.hideLegend = hideLegend;

	this.draw = draw;
	this.reset = reset;

	this.getContext = getContext;
	this.getCanvas = getCanvas;
}
<commit_msg>Added datasets, disabled mouse for now<commit_after>function Graph(canvas)
{
	var canvas = canvas;
	var context = canvas.getContext('2d');
	var canvasW = canvas.width;
	var canvasH = canvas.height;
	var canvasR = Math.min(canvasW, canvasH) * 0.5;
	var canvasAspect = canvasW / canvasH;

	var minX;
	var maxX;
	var minY;
	var maxY;

	var unitsPerPixel = {x:0, y:0};
	var dragStartPos = {x:-1, y:-1};
	var dragOffset = {x:0, y:0}
	var g_MousePos = {x:0, y:0}
	var g_MouseActive = false;

	var legendPos = {x:0, y:0};
	var tickDelta = {x:0, y:0};

    var enableLegend = false;
    var enableAxes = false;

    var plotFunctions = [];
	var dataSets = [];

	function init()
	{
		canvas.addEventListener('mousemove', onMouseMove, false);
		canvas.addEventListener('mousedown', onMouseDown, false);
		canvas.addEventListener('mouseenter', onMouseEnter, false);
		canvas.addEventListener('mouseleave', onMouseLeave, false);
		canvas.addEventListener('mouseup', onMouseUp, false);
		canvas.addEventListener('wheel', onMouseWheel, false);

		reset();
	}

	function setLimits(_minX, _maxX, _minY, _maxY)
	{
		minX = _minX;
		maxX = _maxX;
		minY = _minY;
		maxY = _maxY;

		unitsPerPixel.x = (maxX-minX);
		unitsPerPixel.y = (maxY-minY);
	}

	function getLimits()
	{
		return {minX:minX, maxX:maxX, minY:minY, maxY:maxY};
	}

	function XC(x)
	{
		return (x - minX) / (maxX - minX) * canvasW ;
	}

	function YC(y)
	{
		return canvasH - (y - minY) / (maxY - minY) * canvasH ;
	}

	function onMouseEnter(evt)
	{
		g_MouseActive = true;
		draw();
	}

	function onMouseLeave(evt)
	{
		g_MouseActive = false;
		draw();
	}

	function onMouseDown(evt)
	{
		var m = getMousePos(evt, canvas);
		g_MousePos = getMousePos(evt, canvas);

		dragStartPos = m;
		dragOffset.x = 0;
		dragOffset.y = 0;
	}

	function onMouseUp(evt)
	{
	}

	function onMouseWheel(evt)
	{
		g_MouseActive = true;
		var m = getMousePos(evt, canvas);
		g_MousePos = getMousePos(evt, canvas);

		var zoomCenter = m;
		zoomCenter.x = minX + (zoomCenter.x) * (maxX-minX);
		zoomCenter.y = maxY - (zoomCenter.y) * (maxY-minY);

		var zoomFactor = 1.0 + Math.sign(evt.deltaY) * 0.1;

		minX = zoomCenter.x - (zoomCenter.x - minX) * zoomFactor;
		maxX = zoomCenter.x + (maxX-zoomCenter.x) * zoomFactor;

		minY = zoomCenter.y - (zoomCenter.y - minY) * zoomFactor;
		maxY = zoomCenter.y + (maxY-zoomCenter.y) * zoomFactor;

//		minX = round(minX);
//		maxX = round(maxX);
//		minY = round(minY);
//		maxY = round(maxY);

		setLimits(minX, maxX, minY, maxY);
		draw();
	}

	function onMouseMove(evt)
	{
		//g_MouseActive = true;
		//var m = getMousePos(evt, canvas);
		//g_MousePos = getMousePos(evt, canvas);

		//if (evt.buttons & 1)
		//{
		//	minX -= dragOffset.x;
		//	maxX -= dragOffset.x;
		//	minY -= dragOffset.y;
		//	maxY -= dragOffset.y;

		//	dragOffset.x = -(m.x - dragStartPos.x) * unitsPerPixel.x;
		//	dragOffset.y = (m.y - dragStartPos.y) * unitsPerPixel.y;

		//	dragOffset.x = Math.round(dragOffset.x);
		//	dragOffset.y = Math.round(dragOffset.y);

		//	minX += dragOffset.x;
		//	maxX += dragOffset.x;
		//	minY += dragOffset.y;
		//	maxY += dragOffset.y;
		//}

		//draw();
	}

	function draw()
	{
		clear();

		drawAxes();

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			plotFunction2D(plotFunctions[i][0], plotFunctions[i][1], plotFunctions[i][2], plotFunctions[i][3]);
		}

		for (var i=0; i!=dataSets.length; ++i)
		{
			plotDataSet2D(dataSets[i][0], dataSets[i][1], dataSets[i][2]);
		}

		drawLegend();

		if (g_MouseActive)
		{
			drawMouseLegent();
		}
	}

	function drawMouseLegent()
	{
		var mouseGraphX = minX + (g_MousePos.x) * (maxX-minX);
		var mouseGraphY = maxY - (g_MousePos.y) * (maxY-minY);

		var x = g_MousePos.x * canvasW;
		var y = g_MousePos.y * canvasH;

		var align = g_MousePos.x>0.5 ? "right" : "left";

		// Shift text so that it's not under mouse cursor
		if (g_MousePos.x<=0.5)
		{
			x += 10;
		}
		else
		{
			x -=5;
		}

		drawText(x, y, mouseGraphX.toFixed(2) + ", " + mouseGraphY.toFixed(2), "#000000", align);
		y += 10;

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			var F = plotFunctions[i][0];
			var steps = plotFunctions[i][1];
			var color = plotFunctions[i][2];
			var label = plotFunctions[i][3];

			drawText(x, y, label + " : " + F(mouseGraphX).toFixed(2), color, align);

			y += 10;
		}

	}

	function drawText(x,y,text,color,align)
	{
		if (typeof(color) === "undefined")
			color = "#000000";

		if (typeof(align) === "undefined")
			align = "center";

		context.save();

		context.font = "10px Arial";
		context.textAlign = align;
		context.fillStyle = color;

		context.fillText(text, x, y);

		context.restore();
	}

	function drawLine(x0,y0,x1,y1,color,width)
	{
		context.save() ;
		context.lineWidth = width;
		context.strokeStyle = color;

		context.beginPath() ;
		context.moveTo(x0,y0) ;
		context.lineTo(x1,y1) ;
		context.stroke() ;

		context.restore();
	}

	function drawGraphLine(x0,y0,x1,y1,color,width)
	{
		drawLine(XC(x0),YC(y0),XC(x1),YC(y1),color,width) ;
	}

	function reset()
	{
		clear();
		plotFunctions = [];
		dataSets = [];
	}

	function clear()
	{
		context.clearRect(0,0,canvasW,canvasH) ;
	}

	function addFunction2D(F, stepsX, color, label)
	{
		plotFunctions.push([F, stepsX, color, label]);
	}

	function addDataset2D(points, color, label)
	{
		dataSets.push([points, color, label]);
	}

	function plotFunction2D(F, stepsX, color, label)
	{
		context.save() ;

		context.beginPath();

		context.moveTo( XC(minX), YC( F(minX) ) ) ;

		deltaX = (maxX-minX)/stepsX;

		for (var x = minX; x <= maxX; x += deltaX)
		{
			context.lineTo( XC(x), YC( F(x) ) ) ;
		}

		context.lineWidth = 1 ;
		context.strokeStyle = color;
		context.stroke();

		context.restore() ;
	}

	function plotDataSet2D(points, color, label)
	{
		context.save() ;

		context.beginPath();

		context.moveTo( XC(points[0].x), YC(points[0].y) ) ;

		for (var i=0; i!=points.length; ++i)
		{
			context.lineTo( XC(points[i].x), YC(points[i].y) ) ;
		}

		context.lineWidth = 1 ;
		context.strokeStyle = color;
		context.stroke();

		context.restore() ;
	}

	function showAxes(tickDeltaX, tickDeltaY)
    {
  		tickDelta.x = tickDeltaX;
		tickDelta.y = tickDeltaY;
        enableAxes = true;
    }

	function hideAxes()
    {
        enableAxes = false;
    }

	function drawAxes()
	{
        if (!enableAxes)
            return;

		context.save();
		context.lineWidth = 1 ;

		for (var x = Math.floor(minX/tickDelta.x)*tickDelta.x; x <= Math.floor(maxX/tickDelta.x)*tickDelta.x; x += tickDelta.x)
		{
			drawGraphLine(x, minY, x, maxY, "#808080", 1);
		}

		for (var y = Math.floor(minY/tickDelta.y)*tickDelta.y; y <= Math.floor(maxY/tickDelta.y)*tickDelta.y; y += tickDelta.y)
		{
			drawGraphLine(minX, y, maxX, y, "#808080", 1);
		}

		drawGraphLine(minX, 0, maxX, 0, "#000000", 1.5);
		drawGraphLine(0, minY, 0, maxY, "#000000", 1.5);

		context.fillStyle = "blue";
		context.font = "bold 16px Arial";

		var textX = Math.max(0, Math.min(canvasW-20, XC(0)+5));
		var textY = Math.max(0, Math.min(canvasH-5, YC(0)+20));

		context.fillText(minX.toFixed(2), XC(minX)+5, Math.min(canvasH-20, textY));
		context.fillText(maxX.toFixed(2), XC(maxX)-21, textY);
		context.fillText(minY.toFixed(2), textX, YC(minY)-5);
		context.fillText(maxY.toFixed(2), textX, YC(maxY)+16);

		context.restore();
	}

    function showLegend(x, y)
    {
        enableLegend = true;
		legendPos.x = x;
		legendPos.y = y;
    }

    function hideLegend()
    {
        enableLegend = false;
    }

	function drawLegend()
	{
        if (!enableLegend)
            return;

		var maxWidth = 0;

		context.save();

		context.font = "bold 12px Arial";

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			maxWidth = Math.max(maxWidth, context.measureText(plotFunctions[i][3]).width);
		}

		for (var i=0; i!=dataSets.length; ++i)
		{
			maxWidth = Math.max(maxWidth, context.measureText(dataSets[i][2]).width);
		}

		var x = legendPos.x;
		var y = legendPos.y;

		context.beginPath();
		context.rect(x,y,40+maxWidth, 20*(plotFunctions.length+dataSets.length)+10);
		context.fillStyle = 'white';
		context.fill();
		context.lineWidth = 2;
		context.strokeStyle = 'black';
		context.stroke();

		context.fillStyle = "blue";

		for (var i=0; i!=plotFunctions.length; ++i)
		{
			drawLine(x+5, y + i*20+15, x+5+20, y + i*20+15, plotFunctions[i][2], 1.0);

			context.fillText(plotFunctions[i][3], x+5+20+5,y + i*20+15+4);
		}

		for (var i=0; i!=dataSets.length; ++i)
		{
			drawLine(x+5, y + i*20+15, x+5+20, y + i*20+15, dataSets[i][1], 1.0);

			context.fillText(dataSets[i][2], x+5+20+5,y + i*20+15+4);
		}

		context.restore();
	}

	function getCanvas()
	{
		return canvas;
	}

	function getContext()
	{
		return context;
	}

	init();

	this.setLimits = setLimits;
	this.getLimits = getLimits;
	this.addFunction2D = addFunction2D;
	this.addDataset2D = addDataset2D;

	this.showAxes = showAxes;
	this.hideAxes = hideAxes;

	this.showLegend = showLegend;
	this.hideLegend = hideLegend;

	this.draw = draw;
	this.reset = reset;

	this.getContext = getContext;
	this.getCanvas = getCanvas;
}
<|endoftext|>


<commit_before>import Link from './Link'
import React, { Component } from 'react'
import { INTERACTIVE_ARTICLE_STYLE, REVIEW_CH_STR } from '../constants/index'
import { date2yyyymmdd } from '../lib/date-transformer'
import { getImageSrc } from '../utils/index'

// lodash
import get from 'lodash/get'
import map from 'lodash/map'

if (process.env.BROWSER) {
  require('./Daily.css')
}

export default class Daily extends Component {
  constructor(props, context) {
    super(props, context)
  }

  render() {
    const { daily } = this.props
    let dailyTop = []
    if ( daily ) { dailyTop = daily.slice(0, 6) }
    return dailyTop ? (

觀 點

          { map(dailyTop, (a, idx) => {
            const pubDate = date2yyyymmdd(a.publishedDate, '.')
            let thumbnail = getImageSrc(a, 'mobile')
            let url = '/a/' + a.slug
            return (

                <Link itemProp="url" to={url} disableReactRouter={get(a, 'style') === INTERACTIVE_ARTICLE_STYLE }>

                    <meta itemProp="contentUrl" content={thumbnail} />

{pubDate}

                  <meta itemProp="datePublished" content={date2yyyymmdd(a.publishedDate, '-')} />
                  <meta itemProp="name" content={a.title} />
                  {a.title}
                </Link>
                <meta itemProp="articleSection" content={REVIEW_CH_STR} />

            )
          })}

    ) : null
  }
}

export { Daily }
<commit_msg>Update components/Daily.js. Remove microData<commit_after>import Link from './Link'
import React, { Component } from 'react'
import { INTERACTIVE_ARTICLE_STYLE } from '../constants/index'
import { date2yyyymmdd } from '../lib/date-transformer'
import { getImageSrc } from '../utils/index'

// lodash
import get from 'lodash/get'
import map from 'lodash/map'

if (process.env.BROWSER) {
  require('./Daily.css')
}

export default class Daily extends Component {
  constructor(props, context) {
    super(props, context)
  }

  render() {
    const { daily } = this.props
    let dailyTop = []
    if ( daily ) { dailyTop = daily.slice(0, 6) }
    return dailyTop ? (

觀 點

          { map(dailyTop, (a, idx) => {
            const pubDate = date2yyyymmdd(a.publishedDate, '.')
            let thumbnail = getImageSrc(a, 'mobile')
            let url = '/a/' + a.slug
            return (

                <Link to={url} disableReactRouter={get(a, 'style') === INTERACTIVE_ARTICLE_STYLE }>

{pubDate}

                  {a.title}
                </Link>

            )
          })}

    ) : null
  }
}

export { Daily }
<|endoftext|>


<commit_before>// send logs to syslog
var Syslog = exports.Syslog = require('node-syslog');

exports.register = function() {
    var options   = 0;
    var ini       = this.config.get('log.syslog.ini');
    var name      = ini.general && (ini.general['name']       || 'haraka');
    var facility  = ini.general && (ini.general['facility']   || 'MAIL');
    var pid       = ini.general && (ini.general['log_pid']    || 1);
    var odelay    = ini.general && (ini.general['log_odelay'] || 1);
    var cons      = ini.general && (ini.general['log_cons']   || 0);
    var ndelay    = ini.general && (ini.general['log_ndelay'] || 0);
    var nowait    = ini.general && (ini.general['log_nowait'] || 0);
    var always_ok = ini.general && (ini.general['always_ok']  || false);

    this.always_ok = always_ok;

    if (pid)
      options |= Syslog.LOG_PID;

    if (odelay)
      options |= Syslog.LOG_ODELAY;

    if (cons)
      options |= Syslog.LOG_CONS;

    if (ndelay)
      options |= Syslog.LOG_NDELAY;

    if (nowait)
      options |= Syslog.LOG_NOWAIT;

    switch(facility.toUpperCase()) {
        case 'MAIL':
            Syslog.init(name, options, Syslog.LOG_MAIL);
            break;
        case 'KERN':
            Syslog.init(name, options, Syslog.LOG_KERN);
            break;
        case 'USER':
            Syslog.init(name, options, Syslog.LOG_USER);
            break;
        case 'DAEMON':
            Syslog.init(name, options, Syslog.LOG_DAEMON);
            break;
        case 'AUTH':
            Syslog.init(name, options, Syslog.LOG_AUTH);
            break;
        case 'SYSLOG':
            Syslog.init(name, options, Syslog.LOG_SYSLOG);
            break;
        case 'LPR':
            Syslog.init(name, options, Syslog.LOG_LPR);
            break;
        case 'NEWS':
            Syslog.init(name, options, Syslog.LOG_NEWS);
            break;
        case 'UUCP':
            Syslog.init(name, options, Syslog.LOG_UUCP);
            break;
        case 'LOCAL0':
            Syslog.init(name, options, Syslog.LOG_LOCAL0);
            break;
        case 'LOCAL1':
            Syslog.init(name, options, Syslog.LOG_LOCAL1);
            break;
        case 'LOCAL2':
            Syslog.init(name, options, Syslog.LOG_LOCAL2);
            break;
        case 'LOCAL3':
            Syslog.init(name, options, Syslog.LOG_LOCAL3);
            break;
        case 'LOCAL4':
            Syslog.init(name, options, Syslog.LOG_LOCAL4);
            break;
        case 'LOCAL5':
            Syslog.init(name, options, Syslog.LOG_LOCAL5);
            break;
        case 'LOCAL6':
            Syslog.init(name, options, Syslog.LOG_LOCAL6);
            break;
        case 'LOCAL7':
            Syslog.init(name, options, Syslog.LOG_LOCAL7);
            break;
        default:
            Syslog.init(name, options, Syslog.LOG_MAIL);
    }

    this.register_hook('log', 'syslog');
};

exports.syslog = function (next, logger, log) {
    var plugin = this;

    switch(log.level.toUpperCase()) {
        case 'INFO':
            Syslog.log(Syslog.LOG_INFO, log.data);
            break;
        case 'NOTICE':
            Syslog.log(Syslog.LOG_NOTICE, log.data);
            break;
        case 'WARN':
            Syslog.log(Syslog.LOG_WARNING, log.data);
            break;
        case 'ERROR':
            Syslog.log(Syslog.LOG_ERR, log.data);
            break;
        case 'CRIT':
            Syslog.log(Syslog.LOG_CRIT, log.data);
            break;
        case 'ALERT':
            Syslog.log(Syslog.LOG_ALERT, log.data);
            break;
        case 'EMERG':
            Syslog.log(Syslog.LOG_EMERG, log.data);
            break;
        case 'DATA':
        case 'PROTOCOL':
        case 'DEBUG':
        default:
            Syslog.log(Syslog.LOG_DEBUG, log.data);
    }

    if (plugin.always_ok) {
        return next(OK);
    } else {
        return next();
    }
};
<commit_msg>a little less code for general.ini.<commit_after>// send logs to syslog
var Syslog = exports.Syslog = require('node-syslog');

exports.register = function() {
    var options   = 0;
    var ini       = this.config.get('log.syslog.ini');
    ini.general   ||= {};
    var name      = ini.general['name']       || 'haraka';
    var facility  = ini.general['facility']   || 'MAIL';
    var pid       = ini.general['log_pid']    || 1;
    var odelay    = ini.general['log_odelay'] || 1;
    var cons      = ini.general['log_cons']   || 0;
    var ndelay    = ini.general['log_ndelay'] || 0;
    var nowait    = ini.general['log_nowait'] || 0;
    var always_ok = ini.general['always_ok']  || false;

    this.always_ok = always_ok;

    if (pid)
      options |= Syslog.LOG_PID;

    if (odelay)
      options |= Syslog.LOG_ODELAY;

    if (cons)
      options |= Syslog.LOG_CONS;

    if (ndelay)
      options |= Syslog.LOG_NDELAY;

    if (nowait)
      options |= Syslog.LOG_NOWAIT;

    switch(facility.toUpperCase()) {
        case 'MAIL':
            Syslog.init(name, options, Syslog.LOG_MAIL);
            break;
        case 'KERN':
            Syslog.init(name, options, Syslog.LOG_KERN);
            break;
        case 'USER':
            Syslog.init(name, options, Syslog.LOG_USER);
            break;
        case 'DAEMON':
            Syslog.init(name, options, Syslog.LOG_DAEMON);
            break;
        case 'AUTH':
            Syslog.init(name, options, Syslog.LOG_AUTH);
            break;
        case 'SYSLOG':
            Syslog.init(name, options, Syslog.LOG_SYSLOG);
            break;
        case 'LPR':
            Syslog.init(name, options, Syslog.LOG_LPR);
            break;
        case 'NEWS':
            Syslog.init(name, options, Syslog.LOG_NEWS);
            break;
        case 'UUCP':
            Syslog.init(name, options, Syslog.LOG_UUCP);
            break;
        case 'LOCAL0':
            Syslog.init(name, options, Syslog.LOG_LOCAL0);
            break;
        case 'LOCAL1':
            Syslog.init(name, options, Syslog.LOG_LOCAL1);
            break;
        case 'LOCAL2':
            Syslog.init(name, options, Syslog.LOG_LOCAL2);
            break;
        case 'LOCAL3':
            Syslog.init(name, options, Syslog.LOG_LOCAL3);
            break;
        case 'LOCAL4':
            Syslog.init(name, options, Syslog.LOG_LOCAL4);
            break;
        case 'LOCAL5':
            Syslog.init(name, options, Syslog.LOG_LOCAL5);
            break;
        case 'LOCAL6':
            Syslog.init(name, options, Syslog.LOG_LOCAL6);
            break;
        case 'LOCAL7':
            Syslog.init(name, options, Syslog.LOG_LOCAL7);
            break;
        default:
            Syslog.init(name, options, Syslog.LOG_MAIL);
    }

    this.register_hook('log', 'syslog');
};

exports.syslog = function (next, logger, log) {
    var plugin = this;

    switch(log.level.toUpperCase()) {
        case 'INFO':
            Syslog.log(Syslog.LOG_INFO, log.data);
            break;
        case 'NOTICE':
            Syslog.log(Syslog.LOG_NOTICE, log.data);
            break;
        case 'WARN':
            Syslog.log(Syslog.LOG_WARNING, log.data);
            break;
        case 'ERROR':
            Syslog.log(Syslog.LOG_ERR, log.data);
            break;
        case 'CRIT':
            Syslog.log(Syslog.LOG_CRIT, log.data);
            break;
        case 'ALERT':
            Syslog.log(Syslog.LOG_ALERT, log.data);
            break;
        case 'EMERG':
            Syslog.log(Syslog.LOG_EMERG, log.data);
            break;
        case 'DATA':
        case 'PROTOCOL':
        case 'DEBUG':
        default:
            Syslog.log(Syslog.LOG_DEBUG, log.data);
    }

    if (plugin.always_ok) {
        return next(OK);
    } else {
        return next();
    }
};
<|endoftext|>


<commit_before>var scheme_prefix;
var fullscreen_workaround;
var animGifHandler;
var newImageHandler;
var resize_observer;
var background_observer;
var size_checker_interval;
var deluminateFullyInitialized = false;

function onExtensionMessage(request) {
  deluminateFullyInitialized = true;
  if (request['manual_css']) {
    addCSSLink();
    return;
  }
  if (request.enabled && request.scheme != 'normal') {
    hc = scheme_prefix + request.scheme + ' ' + request.modifiers;
    if (request.settings.hw_accel === 'enabled' ||
        request.settings.hw_accel !== 'disabled' && window.devicePixelRatio > 1) {
      hc += ' hw_accel';
    }
    document.documentElement.setAttribute('hc', hc);
    if (request.scheme.indexOf("delumine") >= 0) {
      // This results in a more instant, if imperfect, inversion. Injected CSS
      // apparently takes a moment to be processed.
      var oldStyle = document.documentElement.getAttribute('style');
      document.documentElement.setAttribute(
        'style', "filter: hue-rotate(180deg) invert(100%)");
      afterDomLoaded(() => {
        if (oldStyle !== null) {
          document.documentElement.setAttribute('style', oldStyle);
        } else {
          document.documentElement.removeAttribute('style');
        }
      });
    }
    setupFullscreenWorkaround();
  } else {
    document.documentElement.removeAttribute('hc');
    removeFullscreenWorkaround();
  }
  // Enable advanced image recognition on invert modes except "invert all
  // images" mode.
  if (request.enabled
      && request.scheme.indexOf("delumine") >= 0
      && request.scheme.indexOf("delumine-all") < 0) {
    newImageHandler.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  } else {
      newImageHandler.disconnect();
  }
  if (request.enabled && request.settings.detect_animation === 'enabled' &&
      request.scheme == 'delumine-smart') {
    Array.prototype.forEach.call(
      document.querySelectorAll('img[src*=".gif"], img[src*=".GIF"]'),
      detectAnimatedGif);
    animGifHandler.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  } else {
    animGifHandler.disconnect();
  }
}

function addCSSLink() {
  /* Add CSS in a way that still works on chrome URLs. */
  var cssURL = chrome.extension.getURL('deluminate.css');
  var selector = 'link[href="' + cssURL + '"]'
  if (document.querySelector(selector) !== null) {
    return; // Don't re-add if it's already there.
  }
  var link = document.createElement('link');
  link.href = cssURL;
  link.rel = 'stylesheet';
  link.media = 'screen';
  document.documentElement.insertBefore(link, null);
}

function setupFullscreenWorkaround() {
  // Skip adding this in nested iframes
  if (window != window.top) return;
  if (document.getElementById("deluminate_fullscreen_workaround") == null) {
    addFullscreenWorkaround();
  } else {
    resetFullscreenWorkaroundBackground();
    resetFullscreenWorkaroundHeight();
  }
}

function addFullscreenWorkaround() {
  fullscreen_workaround.style.position = 'absolute';
  fullscreen_workaround.style.top = 0;
  fullscreen_workaround.style.left = 0;
  fullscreen_workaround.style.width = '100%';
  fullscreen_workaround.style.height = '100%';
  fullscreen_workaround.style.display = 'block';
  fullscreen_workaround.style['z-index'] = -2147483648;

  resetFullscreenWorkaroundBackground();
  resetFullscreenWorkaroundHeight();
  /* Adding to the root node rather than body so it is not subject to absolute
   * positioning of the body. */
  document.documentElement.appendChild(fullscreen_workaround);
  // Need to periodically reset the size (e.g., for loaded images)
  size_checker_interval = setInterval(resetFullscreenWorkaroundHeight, 1000);
  resize_observer.observe(document.documentElement, {
    childList: true,
    subtree: true,
  });
  background_observer.observe(document.documentElement, {
    childList: true,
    attributes: true
  });
  afterDomLoaded(function() {
    resetFullscreenWorkaroundBackground();
    resetFullscreenWorkaroundHeight();
    background_observer.observe(document.head, {
      childList: true,
      attributes: true,
      subtree: true,
      characterData: true
    });
    background_observer.observe(document.body, {
      attributes: true
    });
  });
}

function removeFullscreenWorkaround() {
  var workaround_div;
  resize_observer.disconnect();
  clearInterval(size_checker_interval);
  background_observer.disconnect();
  workaround_div = document.getElementById("deluminate_fullscreen_workaround");
  if (workaround_div != null) {
    workaround_div.remove();
  }
}

function resetFullscreenWorkaroundHeight() {
  var body_scroll_height;
  try {
    body_scroll_height = document.body.scrollHeight;
  } catch(err) {
    body_scroll_height = 0;
  }
  var page_height = Math.max(body_scroll_height,
                             document.documentElement.clientHeight);
  var body_scroll_width;
  try {
    body_scroll_width = document.body.scrollWidth;
  } catch(err) {
    body_scroll_width = 0;
  }
  var page_width = Math.max(body_scroll_width,
                            document.documentElement.clientWidth);
  fullscreen_workaround.style.height = page_height + 'px';
  fullscreen_workaround.style.width = page_width + 'px';
}

function calculateBackground() {
  if (!deluminateFullyInitialized) {
    return 'black';
  }
  var root_style = window.getComputedStyle(document.documentElement);
  if (!domContentLoaded) {
    // We're still pre-DOM-load, so keep things black.
    if (root_style.filter.indexOf('invert') >= 0) {
      return 'white';
    } else {
      return 'black';
    }
  }
  var body_style = window.getComputedStyle(document.body);
  var no_color = 'rgba(0, 0, 0, 0)';
  var no_image = 'none';
  var new_style_item = document.createElement('div');
  if (root_style.backgroundColor != no_color ||
      root_style.backgroundImage != no_image) {
    new_style_item.style.background = root_style.background;
  } else {
    new_style_item.style.background = body_style.background;
  }
  /* Force an unspecified background color to white so it gets inverted to
   * black properly. */
  if (new_style_item.style.backgroundColor == no_color) {
    new_style_item.style.backgroundColor = 'white';
  } else {
    new_style_item.style.backgroundColor =
      computeEffectiveCanvasColor(new_style_item.style.backgroundColor);
  }
  return new_style_item.style.background;
}

function computeEffectiveCanvasColor(color) {
  var rgbaColorRegex = /rgba\((\d+), (\d+), (\d+), (\d*\.?\d+)\)/;
  var match = rgbaColorRegex.exec(color);
  if (!match) {
    // If this regex doesn't match, it has no alpha component, so it's fine.
    return color;
  }
  // Compute the effective canvas color by simulating the blending (due to an
  // alpha channel) against the default white background. This must be
  // calculated manually.
  var [_, r, g, b, a] = match.map(Number);
  // Calculate the alpha-weighted blend against a white background.
  [r, g, b] = [r, g, b].map(channel => {
    var channelComponent = channel * a;
    var whiteComponent = 255 * (1 - a);
    var result = Math.round(channelComponent + whiteComponent);
    var clampedTo8bit = result <= 0   ? 0
                      : result >= 255 ? 255
                      : result
    return clampedTo8bit;
  });
  return `rgb(${r}, ${g}, ${b})`;
}

function onEvent(evt) {
  if (evt.keyCode == 122 /* F11 */ &&
      evt.shiftKey) {
    chrome.runtime.sendMessage({'toggle_global': true});
    evt.stopPropagation();
    evt.preventDefault();
    return false;
  }
  if (evt.keyCode == 123 /* F12 */ &&
      evt.shiftKey) {
    chrome.runtime.sendMessage({'toggle_site': true});
    evt.stopPropagation();
    evt.preventDefault();
    return false;
  }
  return true;
}

function containsAny(haystack, needleList) {
  for (var i = 0; i < needleList.length; ++i) {
    if (haystack.indexOf(needleList[i]) >= 0) {
      return true;
    }
  }
  return false;
}

function markCssImages(tag) {
  var bgImage = window.getComputedStyle(tag)['background-image'];
  var imageType;
  if (containsAny(bgImage, ['data:image/png', '.png', '.PNG'])) {
    imageType = 'png';
  } else if (containsAny(bgImage, ['.gif', '.GIF'])) {
    imageType = 'gif';
  } else if (containsAny(bgImage,
      ['data:image/jpeg', '.jpg', '.JPG', '.jpeg', '.JPEG'])) {
    imageType = 'jpg';
  }
  if (imageType) {
    tag.setAttribute('deluminate_imageType', imageType);
  } else {
    tag.removeAttribute('deluminate_imageType');
  }
}

function detectAnimatedGif(tag) {
  chrome.runtime.sendMessage(
    { 'detect_gif': true
    , 'src': tag.src
    },
    function(result) {
      if (result.is_animated) {
        tag.setAttribute('deluminate_imageType', 'animated gif');
      }
    });
}

function deepImageProcessing() {
  Array.prototype.forEach.call(
    document.querySelectorAll('body *:not([style*="url"])'),
    markCssImages);
}

var domContentLoaded = false;
function domLoaded() {
  domContentLoaded = true;
}

function afterDomLoaded(cb) {
  if(domContentLoaded) {
    cb();
  } else {
    document.addEventListener('DOMContentLoaded', cb);
  }
}

function log() {
  chrome.runtime.sendMessage({'log':
                             Array.prototype.slice.call(arguments).join(' ')});
}

function resetFullscreenWorkaroundBackground() {
  fullscreen_workaround.style.background = calculateBackground();
  markCssImages(fullscreen_workaround);
}

function init() {
  if (window == window.top) {
    scheme_prefix = '';
  } else {
    scheme_prefix = 'nested_';
  }
  log("Initializing.", scheme_prefix);

  fullscreen_workaround = document.createElement('div');
  fullscreen_workaround.id = scheme_prefix + "deluminate_fullscreen_workaround";

  chrome.runtime.onMessage.addListener(onExtensionMessage);
  chrome.runtime.sendMessage({'init': true, 'url': window.document.baseURI},
      onExtensionMessage);
  document.addEventListener('keydown', onEvent, false);
  document.addEventListener('DOMContentLoaded', domLoaded);
  afterDomLoaded(deepImageProcessing);

  animGifHandler = new MutationObserver(function(mutations, obs) {
    for(var i=0; i<mutations.length; ++i) {
      for(var j=0; j<mutations[i].addedNodes.length; ++j) {
        var newTag = mutations[i].addedNodes[j];
        if (newTag.querySelectorAll) {
          Array.prototype.forEach.call(
            newTag.querySelectorAll('img[src*=".gif"], img[src*=".GIF"]'),
            detectAnimatedGif);
        }
      }
    }
  });

  newImageHandler = new MutationObserver(function(mutations, obs) {
    for(var i=0; i<mutations.length; ++i) {
      for(var j=0; j<mutations[i].addedNodes.length; ++j) {
        var newTag = mutations[i].addedNodes[j];
        if (newTag.querySelectorAll) {
          Array.prototype.forEach.call(
            newTag.querySelectorAll('*:not([style*="url"])'),
            markCssImages);
        }
      }
    }
  });

  resize_observer = new MutationObserver(function(mutations, obs) {
    if (mutations.length > 0) {
      resetFullscreenWorkaroundHeight();
    }
  });

  background_observer = new MutationObserver(function(mutations, obs) {
    if (mutations.length > 0) {
      resetFullscreenWorkaroundBackground();
    }
  });

  window.addEventListener('resize', resetFullscreenWorkaroundHeight);
  setupFullscreenWorkaround();
}

init();
<commit_msg>Make instant inversion only affect filters<commit_after>var scheme_prefix;
var fullscreen_workaround;
var animGifHandler;
var newImageHandler;
var resize_observer;
var background_observer;
var size_checker_interval;
var deluminateFullyInitialized = false;

function onExtensionMessage(request) {
  deluminateFullyInitialized = true;
  if (request['manual_css']) {
    addCSSLink();
    return;
  }
  if (request.enabled && request.scheme != 'normal') {
    hc = scheme_prefix + request.scheme + ' ' + request.modifiers;
    if (request.settings.hw_accel === 'enabled' ||
        request.settings.hw_accel !== 'disabled' && window.devicePixelRatio > 1) {
      hc += ' hw_accel';
    }
    document.documentElement.setAttribute('hc', hc);
    if (request.scheme.indexOf("delumine") >= 0) {
      injectInstantInversion();
    }
    setupFullscreenWorkaround();
  } else {
    document.documentElement.removeAttribute('hc');
    removeFullscreenWorkaround();
  }
  // Enable advanced image recognition on invert modes except "invert all
  // images" mode.
  if (request.enabled
      && request.scheme.indexOf("delumine") >= 0
      && request.scheme.indexOf("delumine-all") < 0) {
    newImageHandler.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  } else {
      newImageHandler.disconnect();
  }
  if (request.enabled && request.settings.detect_animation === 'enabled' &&
      request.scheme == 'delumine-smart') {
    Array.prototype.forEach.call(
      document.querySelectorAll('img[src*=".gif"], img[src*=".GIF"]'),
      detectAnimatedGif);
    animGifHandler.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  } else {
    animGifHandler.disconnect();
  }
}

function injectInstantInversion() {
  // This results in a more instant, if imperfect, inversion. Injected CSS
  // apparently takes a moment to be processed.
  document.documentElement.style.filter = "hue-rotate(180deg) invert(100%)";
  afterDomLoaded(() => {
    // Restore filter control to the injected CSS.
    document.documentElement.style.filter = "";
  });
}

function addCSSLink() {
  /* Add CSS in a way that still works on chrome URLs. */
  var cssURL = chrome.extension.getURL('deluminate.css');
  var selector = 'link[href="' + cssURL + '"]'
  if (document.querySelector(selector) !== null) {
    return; // Don't re-add if it's already there.
  }
  var link = document.createElement('link');
  link.href = cssURL;
  link.rel = 'stylesheet';
  link.media = 'screen';
  document.documentElement.insertBefore(link, null);
}

function setupFullscreenWorkaround() {
  // Skip adding this in nested iframes
  if (window != window.top) return;
  if (document.getElementById("deluminate_fullscreen_workaround") == null) {
    addFullscreenWorkaround();
  } else {
    resetFullscreenWorkaroundBackground();
    resetFullscreenWorkaroundHeight();
  }
}

function addFullscreenWorkaround() {
  fullscreen_workaround.style.position = 'absolute';
  fullscreen_workaround.style.top = 0;
  fullscreen_workaround.style.left = 0;
  fullscreen_workaround.style.width = '100%';
  fullscreen_workaround.style.height = '100%';
  fullscreen_workaround.style.display = 'block';
  fullscreen_workaround.style['z-index'] = -2147483648;

  resetFullscreenWorkaroundBackground();
  resetFullscreenWorkaroundHeight();
  /* Adding to the root node rather than body so it is not subject to absolute
   * positioning of the body. */
  document.documentElement.appendChild(fullscreen_workaround);
  // Need to periodically reset the size (e.g., for loaded images)
  size_checker_interval = setInterval(resetFullscreenWorkaroundHeight, 1000);
  resize_observer.observe(document.documentElement, {
    childList: true,
    subtree: true,
  });
  background_observer.observe(document.documentElement, {
    childList: true,
    attributes: true
  });
  afterDomLoaded(function() {
    resetFullscreenWorkaroundBackground();
    resetFullscreenWorkaroundHeight();
    background_observer.observe(document.head, {
      childList: true,
      attributes: true,
      subtree: true,
      characterData: true
    });
    background_observer.observe(document.body, {
      attributes: true
    });
  });
}

function removeFullscreenWorkaround() {
  var workaround_div;
  resize_observer.disconnect();
  clearInterval(size_checker_interval);
  background_observer.disconnect();
  workaround_div = document.getElementById("deluminate_fullscreen_workaround");
  if (workaround_div != null) {
    workaround_div.remove();
  }
}

function resetFullscreenWorkaroundHeight() {
  var body_scroll_height;
  try {
    body_scroll_height = document.body.scrollHeight;
  } catch(err) {
    body_scroll_height = 0;
  }
  var page_height = Math.max(body_scroll_height,
                             document.documentElement.clientHeight);
  var body_scroll_width;
  try {
    body_scroll_width = document.body.scrollWidth;
  } catch(err) {
    body_scroll_width = 0;
  }
  var page_width = Math.max(body_scroll_width,
                            document.documentElement.clientWidth);
  fullscreen_workaround.style.height = page_height + 'px';
  fullscreen_workaround.style.width = page_width + 'px';
}

function calculateBackground() {
  if (!deluminateFullyInitialized) {
    return 'black';
  }
  var root_style = window.getComputedStyle(document.documentElement);
  if (!domContentLoaded) {
    // We're still pre-DOM-load, so keep things black.
    if (root_style.filter.indexOf('invert') >= 0) {
      return 'white';
    } else {
      return 'black';
    }
  }
  var body_style = window.getComputedStyle(document.body);
  var no_color = 'rgba(0, 0, 0, 0)';
  var no_image = 'none';
  var new_style_item = document.createElement('div');
  if (root_style.backgroundColor != no_color ||
      root_style.backgroundImage != no_image) {
    new_style_item.style.background = root_style.background;
  } else {
    new_style_item.style.background = body_style.background;
  }
  /* Force an unspecified background color to white so it gets inverted to
   * black properly. */
  if (new_style_item.style.backgroundColor == no_color) {
    new_style_item.style.backgroundColor = 'white';
  } else {
    new_style_item.style.backgroundColor =
      computeEffectiveCanvasColor(new_style_item.style.backgroundColor);
  }
  return new_style_item.style.background;
}

function computeEffectiveCanvasColor(color) {
  var rgbaColorRegex = /rgba\((\d+), (\d+), (\d+), (\d*\.?\d+)\)/;
  var match = rgbaColorRegex.exec(color);
  if (!match) {
    // If this regex doesn't match, it has no alpha component, so it's fine.
    return color;
  }
  // Compute the effective canvas color by simulating the blending (due to an
  // alpha channel) against the default white background. This must be
  // calculated manually.
  var [_, r, g, b, a] = match.map(Number);
  // Calculate the alpha-weighted blend against a white background.
  [r, g, b] = [r, g, b].map(channel => {
    var channelComponent = channel * a;
    var whiteComponent = 255 * (1 - a);
    var result = Math.round(channelComponent + whiteComponent);
    var clampedTo8bit = result <= 0   ? 0
                      : result >= 255 ? 255
                      : result
    return clampedTo8bit;
  });
  return `rgb(${r}, ${g}, ${b})`;
}

function onEvent(evt) {
  if (evt.keyCode == 122 /* F11 */ &&
      evt.shiftKey) {
    chrome.runtime.sendMessage({'toggle_global': true});
    evt.stopPropagation();
    evt.preventDefault();
    return false;
  }
  if (evt.keyCode == 123 /* F12 */ &&
      evt.shiftKey) {
    chrome.runtime.sendMessage({'toggle_site': true});
    evt.stopPropagation();
    evt.preventDefault();
    return false;
  }
  return true;
}

function containsAny(haystack, needleList) {
  for (var i = 0; i < needleList.length; ++i) {
    if (haystack.indexOf(needleList[i]) >= 0) {
      return true;
    }
  }
  return false;
}

function markCssImages(tag) {
  var bgImage = window.getComputedStyle(tag)['background-image'];
  var imageType;
  if (containsAny(bgImage, ['data:image/png', '.png', '.PNG'])) {
    imageType = 'png';
  } else if (containsAny(bgImage, ['.gif', '.GIF'])) {
    imageType = 'gif';
  } else if (containsAny(bgImage,
      ['data:image/jpeg', '.jpg', '.JPG', '.jpeg', '.JPEG'])) {
    imageType = 'jpg';
  }
  if (imageType) {
    tag.setAttribute('deluminate_imageType', imageType);
  } else {
    tag.removeAttribute('deluminate_imageType');
  }
}

function detectAnimatedGif(tag) {
  chrome.runtime.sendMessage(
    { 'detect_gif': true
    , 'src': tag.src
    },
    function(result) {
      if (result.is_animated) {
        tag.setAttribute('deluminate_imageType', 'animated gif');
      }
    });
}

function deepImageProcessing() {
  Array.prototype.forEach.call(
    document.querySelectorAll('body *:not([style*="url"])'),
    markCssImages);
}

var domContentLoaded = false;
function domLoaded() {
  domContentLoaded = true;
}

function afterDomLoaded(cb) {
  if(domContentLoaded) {
    cb();
  } else {
    document.addEventListener('DOMContentLoaded', cb);
  }
}

function log() {
  chrome.runtime.sendMessage({'log':
                             Array.prototype.slice.call(arguments).join(' ')});
}

function resetFullscreenWorkaroundBackground() {
  fullscreen_workaround.style.background = calculateBackground();
  markCssImages(fullscreen_workaround);
}

function init() {
  if (window == window.top) {
    scheme_prefix = '';
  } else {
    scheme_prefix = 'nested_';
  }
  log("Initializing.", scheme_prefix);

  fullscreen_workaround = document.createElement('div');
  fullscreen_workaround.id = scheme_prefix + "deluminate_fullscreen_workaround";

  chrome.runtime.onMessage.addListener(onExtensionMessage);
  chrome.runtime.sendMessage({'init': true, 'url': window.document.baseURI},
      onExtensionMessage);
  document.addEventListener('keydown', onEvent, false);
  document.addEventListener('DOMContentLoaded', domLoaded);
  afterDomLoaded(deepImageProcessing);

  animGifHandler = new MutationObserver(function(mutations, obs) {
    for(var i=0; i<mutations.length; ++i) {
      for(var j=0; j<mutations[i].addedNodes.length; ++j) {
        var newTag = mutations[i].addedNodes[j];
        if (newTag.querySelectorAll) {
          Array.prototype.forEach.call(
            newTag.querySelectorAll('img[src*=".gif"], img[src*=".GIF"]'),
            detectAnimatedGif);
        }
      }
    }
  });

  newImageHandler = new MutationObserver(function(mutations, obs) {
    for(var i=0; i<mutations.length; ++i) {
      for(var j=0; j<mutations[i].addedNodes.length; ++j) {
        var newTag = mutations[i].addedNodes[j];
        if (newTag.querySelectorAll) {
          Array.prototype.forEach.call(
            newTag.querySelectorAll('*:not([style*="url"])'),
            markCssImages);
        }
      }
    }
  });

  resize_observer = new MutationObserver(function(mutations, obs) {
    if (mutations.length > 0) {
      resetFullscreenWorkaroundHeight();
    }
  });

  background_observer = new MutationObserver(function(mutations, obs) {
    if (mutations.length > 0) {
      resetFullscreenWorkaroundBackground();
    }
  });

  window.addEventListener('resize', resetFullscreenWorkaroundHeight);
  setupFullscreenWorkaround();
}

init();
<|endoftext|>


<commit_before>'use strict';

var request = require("request");
var defaultUserAgent = require("./user_agent");

// @constructor
// @param {string} apiToken the Dialog API token
// @param {string} botId the Dialog bot Id
function Client(apiToken, botId) {
  this.apiEndpoint = "https://api.dialoganalytics.com/v1/";
  this.apiToken = apiToken;
  this.botId = botId;
  this.userAgent = defaultUserAgent;
};
module.exports = Client;

// @param {Object} payload Properties expected by the track API endpoint
// @param {Function} callback
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/track/
Client.prototype.track = function(payload, callback) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/track",
    json: payload
  };

  return this.post(options, callback);
};

// @param {String} url
// @returns {String}
// @see https://docs.dialoganalytics.com/reference/click-tracking/
Client.prototype.link = function(url) {
  return this.apiEndpoint + "click/" + this.botId + "?url=" + encodeURIComponent(url);
};

// @param {String} conversationId
// @returns
// @see https://docs.dialoganalytics.com/reference/message#list
Client.prototype.listMessages = function(conversationId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/" + conversationId + "/messages"
  };

  this.get(options);
};

// @param {String} conversationId
// @param {String} messageId
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/message#retrieve
Client.prototype.retrieveMessage = function(conversationId, messageId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/" + conversationId + "/messages/" + messageId
  };

  this.get(options);
};

// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/conversation#list
Client.prototype.listConversations = function() {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/"
  };

  this.get(options);
};

// @param {String} conversationId
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/conversation#retrieve
Client.prototype.retrieveConversation = function(conversationId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/" + conversationId
  };

  this.get(options);
};

// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/interlocutor#list
Client.prototype.listInterlocutors = function() {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/interlocutors/"
  };

  this.get(options);
};

// @param {String} interlocutorId
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/interlocutor#retrieve
Client.prototype.retrieveInterlocutor = function(interlocutorId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/interlocutors/" + interlocutorId
  };

  this.get(options);
};

// @param {Object} params
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/interlocutor#create
Client.prototype.createInterlocutor = function(params) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/interlocutors/",
    json: { interlocutor: params }
  };

  this.post(options);
};

// @param {Object} options
// @param {Function} callback
// @returns {Object}
Client.prototype.get = function(options, callback) {
  options.headers = {
    'User-Agent': this.defaultUserAgent,
    'Authorization': 'Api-Key ' + this.apiToken
  };

  var callback = function(error, response, body) {
    // console.log(error)
    // console.log(response)
    console.log(body)
  };

  return request.get(options, callback);
};

// @param {Object} options
// @param {Function} callback
// @returns {Object}
Client.prototype.post = function(options, callback) {
  options.headers = {
    'User-Agent': this.defaultUserAgent,
    'Authorization': 'Api-Key ' + this.apiToken
  };

  var callback = function(error, response, body) {
    // noop
  };

  return request.post(options, callback);
};
<commit_msg>Remove commented out console.log<commit_after>'use strict';

var request = require("request");
var defaultUserAgent = require("./user_agent");

// @constructor
// @param {string} apiToken the Dialog API token
// @param {string} botId the Dialog bot Id
function Client(apiToken, botId) {
  this.apiEndpoint = "https://api.dialoganalytics.com/v1/";
  this.apiToken = apiToken;
  this.botId = botId;
  this.userAgent = defaultUserAgent;
};
module.exports = Client;

// @param {Object} payload Properties expected by the track API endpoint
// @param {Function} callback
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/track/
Client.prototype.track = function(payload, callback) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/track",
    json: payload
  };

  return this.post(options, callback);
};

// @param {String} url
// @returns {String}
// @see https://docs.dialoganalytics.com/reference/click-tracking/
Client.prototype.link = function(url) {
  return this.apiEndpoint + "click/" + this.botId + "?url=" + encodeURIComponent(url);
};

// @param {String} conversationId
// @returns
// @see https://docs.dialoganalytics.com/reference/message#list
Client.prototype.listMessages = function(conversationId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/" + conversationId + "/messages"
  };

  this.get(options);
};

// @param {String} conversationId
// @param {String} messageId
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/message#retrieve
Client.prototype.retrieveMessage = function(conversationId, messageId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/" + conversationId + "/messages/" + messageId
  };

  this.get(options);
};

// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/conversation#list
Client.prototype.listConversations = function() {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/"
  };

  this.get(options);
};

// @param {String} conversationId
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/conversation#retrieve
Client.prototype.retrieveConversation = function(conversationId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/conversations/" + conversationId
  };

  this.get(options);
};

// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/interlocutor#list
Client.prototype.listInterlocutors = function() {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/interlocutors/"
  };

  this.get(options);
};

// @param {String} interlocutorId
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/interlocutor#retrieve
Client.prototype.retrieveInterlocutor = function(interlocutorId) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/interlocutors/" + interlocutorId
  };

  this.get(options);
};

// @param {Object} params
// @returns {Object}
// @see https://docs.dialoganalytics.com/reference/interlocutor#create
Client.prototype.createInterlocutor = function(params) {
  var options = {
    url: this.apiEndpoint + "b/" + this.botId + "/interlocutors/",
    json: { interlocutor: params }
  };

  this.post(options);
};

// @param {Object} options
// @param {Function} callback
// @returns {Object}
Client.prototype.get = function(options, callback) {
  options.headers = {
    'User-Agent': this.defaultUserAgent,
    'Authorization': 'Api-Key ' + this.apiToken
  };

  var callback = function(error, response, body) {
    // noop
  };

  return request.get(options, callback);
};

// @param {Object} options
// @param {Function} callback
// @returns {Object}
Client.prototype.post = function(options, callback) {
  options.headers = {
    'User-Agent': this.defaultUserAgent,
    'Authorization': 'Api-Key ' + this.apiToken
  };

  var callback = function(error, response, body) {
    // noop
  };

  return request.post(options, callback);
};
<|endoftext|>


<commit_before>define(['mac/roman'], function(macintoshRoman) {

  'use strict';

  return function(resource) {

    debugger;

  };

});
<commit_msg>Update open_ATXT.js<commit_after>define(['mac/roman'], function(macintoshRoman) {

  'use strict';

  return function(resource) {

    var text = macintoshRoman(resource.data, 0, resource.data.length);
    debugger;

  };

});
<|endoftext|>