<commit_before>NGApp.config(['$routeProvider', function($routeProvider) {
	$routeProvider
		.when('/support', {
			action: 'support',
			controller: 'SupportCtrl',
			templateUrl: 'assets/view/support.html',
			title: 'Support',
			reloadOnSearch: false
		})
		.when('/chat', {
			action: 'chat',
			controller: 'ChatCtrl',
			templateUrl: 'assets/view/chat.html',
			title: 'Chat'
		})
		.when('/chat/:room', {
			action: 'chat',
			controller: 'ChatCtrl',
			templateUrl: 'assets/view/chat.html',
			title: 'Chat'
		})
		.when('/support/phone', {
			action: 'support',
			controller: 'SupportPhoneCtrl',
			templateUrl: 'assets/view/support-phone.html',
			title: 'Support',
			reloadOnSearch: false
		});
}]);

NGApp.controller('ChatCtrl', function($scope, $rootScope, $routeParams, SocketService, AccountService) {
	$scope.room = $routeParams.room || 'lobby';

	SocketService.listen('chat.' + $scope.room, $scope)
		.on('message', function(d) {
			console.log(d);
		});
	/*
	$scope.send = function() {
		//SocketService.socket.emit('chat.' + $scope.room, 'message');
		SocketService.socket.emit('event.message', {
			url: 'api/'
		});
	};
	*/
});

NGApp.controller('SideTicketsCtrl', function($scope, $rootScope, $location, TicketService, TicketViewService, AccountService) {

	$scope.params = { status: 'open' };

	var getTickets = function() {
		if (!AccountService || !AccountService.user || !AccountService.user.permissions) {
			return;
		}
		TicketService.shortlist( $scope.params, function(tickets) {
			TicketViewService.scope.tickets = tickets.results;
		});
	};

	if (!TicketViewService.scope.tickets) {
		getTickets();
	}

	$scope.loadTicket = function( id_support ){
		TicketViewService.setViewTicket( id_support );
	}

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count || newValue.timestamp != oldValue.timestamp ) {
			getTickets();
		}
	}, true);
});

NGApp.controller( 'SideTicketCtrl', function($scope, $rootScope, $routeParams, $timeout, TicketService, TicketViewService, SocketService, MainNavigationService ) {

	var id_support = null;

	if (typeof TicketViewService.scope.viewTicket == 'string') {
		id_support = TicketViewService.scope.viewTicket;
	} else {
		id_support = TicketViewService.scope.viewTicket.id;
	}

	TicketViewService.sideInfo.setTicket( id_support );

	var loadData = function(){
		if( TicketViewService.sideInfo.load() ){
			$scope.isLoading = true;
		}
	}

	// $scope.$watchCollection( 'ticket', function( newValue, oldValue ) {
	// 	if( newValue && newValue.total && !$rootScope.supportToggled ){
	// 		$timeout( function(){
	// 			$rootScope.supportToggled = true;
	// 		}, 300 );
	// 	}
	// } );

	$scope.isLoading = false;

	$scope.loadMoreMessages = function(){
		loadData()
	}

	$rootScope.$on( 'triggerTicketInfoUpdated', function(e, data) {
		console.log('$scope.ticket',$scope.ticket);
		console.log('data',data);
		if( $scope.ticket.id_support != data.id_support ){
			$scope.ticket = data;
		} else {
			if( !angular.equals( $scope.ticket.messages, data.messages ) ){
				if( !$scope.ticket.messages || ( $scope.ticket.messages && $scope.ticket.messages.length < data.messages.length ) ){
					$scope.ticket.messages = data.messages;
				}

				console.log('!=!=!=!=!=');
			} else {
				console.log('=====');
			}

			if( $scope.ticket.total != data.total ){
				$timeout( function(){
					$scope.ticket.has_more = data.has_more;
					$scope.ticket.loaded = data.loaded;
					$scope.ticket.page = data.page;
					$scope.ticket.total = data.total;
					console.log('update everything else');
				 }, 300 );
			}
		}

		$scope.isLoading = false;
		if( !$rootScope.supportToggled ){
			$timeout( function(){ $rootScope.supportToggled = true; }, 300 );
		}
	} );

	$rootScope.$on( 'loadMoreMessages', function(e, data) {
		$scope.loadMoreMessages();
	} );

	var socketStuff = function(){
		SocketService.listen('ticket.' + id_support, TicketViewService.scope ).on('message', function(d) {
			if( d.guid ){
				for ( var x in TicketViewService.sideInfo.data.messages ) {
					if ( TicketViewService.sideInfo.data.messages[x].guid == d.guid ) {
						if( TicketViewService.sideInfo.data.messages[x].sending ){
							TicketViewService.sideInfo.data.messages[x] = d;
							console.log('updated status');
						}
						console.log('message already added!');
						return;
					}
				}
			}
			TicketViewService.sideInfo.add_message( d );
		});
	}

	$rootScope.$on( 'triggerViewTicket', function(e, ticket) {
		if( ticket.id_support != TicketViewService.sideInfo.id_support ){
			TicketViewService.sideInfo.setTicket( 0 );
			TicketViewService.sideInfo.setTicket( ticket.id_support );
			loadData();
			socketStuff();
		}
	} );

	$scope.send = TicketViewService.send;
	loadData();
	socketStuff();

} );

NGApp.controller('SideSupportCtrl', function($scope, $rootScope, TicketViewService) {
	TicketViewService.scope = $scope;
	$scope.setViewTicket = TicketViewService.setViewTicket;
});

NGApp.controller('SideSupportPexCardCtrl', function( $scope, StaffPayInfoService, PexCardService ) {

	$scope.add_funds = function(){
		if( $scope.ticket && $scope.ticket.pexcard && $scope.ticket.pexcard.id_pexcard ){
			if( $scope.form.$invalid ){
				App.alert( 'Please fill in all required fields' );
				$scope.submitted = true;
				return;
			}
			$scope.pexcard.id_pexcard = $scope.ticket.pexcard.id_pexcard;
			$scope.isAdding = true;
			PexCardService.add_funds( $scope.pexcard, function( data ){
				if( data.error ){
					App.alert( data.error);
					$scope.isAdding = false;
					return;
				} else {
					$scope.isAdding = false;
					$scope.flash.setMessage( 'Funds Added!' );
					$scope.pexcard = {};
					$scope.isLoadingBalance = true;
					setTimeout( function(){ $scope.current_balanced(); }, 3000 );
				}
			} );
		} else {
			App.alert( 'Oops, it seems the driver doesn\'t have a PexCard!' );
		}
	}

	$scope.current_balanced = function(){
		if( $scope.ticket && $scope.ticket.pexcard && $scope.ticket.pexcard.card_serial ){

			$scope.isLoadingBalance = true;

			PexCardService.pex_id( $scope.ticket.pexcard.card_serial,
				function( json ){
					$scope.isLoadingBalance = false;
					if( json.id ){
						$scope.card = json;
					} else {
						$scope.flash.setMessage( json.error, 'error' );
					}
				}
			);
		} else {
			App.alert( 'Oops, it seems the driver doesn\'t have a PexCard!' );
		}
	}

} );

NGApp.controller('SupportPhoneCtrl', function( $scope, $rootScope, StaffService, CallService, MainNavigationService, TwilioService) {

	$scope.call = { staff : '', to : 'customer', _to: CallService.call_to() };
	$scope.sms = { staff : '', to : 'customer', _to: CallService.call_to() };

	$scope.$watch( 'call.staff', function( newValue, oldValue, scope ) {
		$scope.call.phone = newValue.phone;
	}	);

	$scope.$watch( 'sms.staff', function( newValue, oldValue, scope ) {
		$scope.sms.phone = newValue.phone;
		$scope.sms.name = newValue.name;
	}	);

	StaffService.phones( function( response ){
		$scope.staff = response;
	} );

	$scope.formCallSending = false;
	$scope.formSMSSending = false;

	$scope.reset = function(){
		$scope.call.phone = '';
		$scope.sms.phone = '';
		$scope.sms.message = '';
	}

	$scope.sms.send = function(){

		if( $scope.formSMS.$invalid ){
			$scope.formSMSSubmitted = true;
			return;
		}

		$scope.formSMSSending = true;
		CallService.send_sms( $scope.sms, function( json ){
			$scope.formSMSSending = false;
			if( json.success ){
				MainNavigationService.link( '/ticket/' + json.success);
				if( $scope.complete ){
					$scope.complete();
				}
				$scope.reset();
			} else {
				App.alert( json.error );
			}
		} );
	}

	$scope.call.make = function(){
		if( $scope.formCall.$invalid ){
			$scope.formCallSubmitted = true;
			return;
		}
		$scope.formCallSending = true;
		CallService.make_call( $scope.call, function( json ){
			$scope.formCallSending = false;
			if( json.success ){
				App.alert( json.success );
				$scope.reset();
			} else {
				App.alert( json.error );
			}
		} );
	}

	$scope.call.voip = function() {
		TwilioService.call($scope.call.phone);
		App.dialog.close();
	};

	// Reset stuff when calling from modal
	$rootScope.$on('callText', function(e, num) {
		$scope.reset();
		$scope.call.phone = num;
		$scope.sms.phone = num;
	} );

} );

NGApp.controller('SupportCtrl', function($scope, $rootScope, $timeout, TicketService, TicketViewService, CallService) {

	$scope.ticketparams = {
		status: 'open'
	};

	$scope.callparams = {
		status: ['in-progress','ringing'],
		limit: 5,
		today: true
	};

	$scope.closeTicket = function( id_support ){
		TicketService.openClose( id_support, function() { update(); } );
	}

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count || newValue.timestamp != oldValue.timestamp ) {
			update();
		}
	}, true);

	var update = function(){
		TicketService.list($scope.ticketparams, function(d) {
			$scope.lotsoftickets = d.results;
			TicketViewService.scope.tickets = d.results;
		});
	}

	CallService.list($scope.callparams, function(d) {
		$scope.calls = d.results;
	});

	update();
});
<commit_msg>partial #6135<commit_after>NGApp.config(['$routeProvider', function($routeProvider) {
	$routeProvider
		.when('/support', {
			action: 'support',
			controller: 'SupportCtrl',
			templateUrl: 'assets/view/support.html',
			title: 'Support',
			reloadOnSearch: false
		})
		.when('/chat', {
			action: 'chat',
			controller: 'ChatCtrl',
			templateUrl: 'assets/view/chat.html',
			title: 'Chat'
		})
		.when('/chat/:room', {
			action: 'chat',
			controller: 'ChatCtrl',
			templateUrl: 'assets/view/chat.html',
			title: 'Chat'
		})
		.when('/support/phone', {
			action: 'support',
			controller: 'SupportPhoneCtrl',
			templateUrl: 'assets/view/support-phone.html',
			title: 'Support',
			reloadOnSearch: false
		});
}]);

NGApp.controller('ChatCtrl', function($scope, $rootScope, $routeParams, SocketService, AccountService) {
	$scope.room = $routeParams.room || 'lobby';

	SocketService.listen('chat.' + $scope.room, $scope)
		.on('message', function(d) {
			console.log(d);
		});
	/*
	$scope.send = function() {
		//SocketService.socket.emit('chat.' + $scope.room, 'message');
		SocketService.socket.emit('event.message', {
			url: 'api/'
		});
	};
	*/
});

NGApp.controller('SideTicketsCtrl', function($scope, $rootScope, $location, TicketService, TicketViewService, AccountService) {

	$scope.params = { status: 'open' };

	var getTickets = function() {
		if (!AccountService || !AccountService.user || !AccountService.user.permissions) {
			return;
		}
		TicketService.shortlist( $scope.params, function(tickets) {
			TicketViewService.scope.tickets = tickets.results;
		});
	};

	if (!TicketViewService.scope.tickets) {
		getTickets();
	}

	$scope.loadTicket = function( id_support ){
		TicketViewService.setViewTicket( id_support );
	}

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count || newValue.timestamp != oldValue.timestamp ) {
			getTickets();
		}
	}, true);
});

NGApp.controller( 'SideTicketCtrl', function($scope, $rootScope, $routeParams, $timeout, TicketService, TicketViewService, SocketService, MainNavigationService ) {

	var id_support = null;

	if (typeof TicketViewService.scope.viewTicket == 'string') {
		id_support = TicketViewService.scope.viewTicket;
	} else {
		id_support = TicketViewService.scope.viewTicket.id;
	}

	TicketViewService.sideInfo.setTicket( id_support );

	var loadData = function(){
		if( TicketViewService.sideInfo.load() ){
			$scope.isLoading = true;
		}
	}

	// $scope.$watchCollection( 'ticket', function( newValue, oldValue ) {
	// 	if( newValue && newValue.total && !$rootScope.supportToggled ){
	// 		$timeout( function(){
	// 			$rootScope.supportToggled = true;
	// 		}, 300 );
	// 	}
	// } );

	$scope.isLoading = false;

	$scope.loadMoreMessages = function(){
		loadData()
	}

	$rootScope.$on( 'triggerTicketInfoUpdated', function(e, data) {

		$rootScope.$safeApply( function(){
			console.log('$scope.ticket',$scope.ticket);
			console.log('data',data);
			if( $scope.ticket.id_support != data.id_support ){
				$scope.ticket = data;
			} else {
				if( !angular.equals( $scope.ticket.messages, data.messages ) ){
					if( !$scope.ticket.messages || ( $scope.ticket.messages && $scope.ticket.messages.length < data.messages.length ) ){
						$scope.ticket.messages = data.messages;
					}

					console.log('!=!=!=!=!=');
				} else {
					console.log('=====');
				}

				if( $scope.ticket.total != data.total ){
					$timeout( function(){
						$scope.ticket.has_more = data.has_more;
						$scope.ticket.loaded = data.loaded;
						$scope.ticket.page = data.page;
						$scope.ticket.total = data.total;
						console.log('update everything else');
					 }, 300 );
				}
			}
		} );

		$scope.isLoading = false;
		if( !$rootScope.supportToggled ){
			$timeout( function(){ $rootScope.supportToggled = true; }, 300 );
		}
	} );

	$rootScope.$on( 'loadMoreMessages', function(e, data) {
		$scope.loadMoreMessages();
	} );

	var socketStuff = function(){
		SocketService.listen('ticket.' + id_support, TicketViewService.scope ).on('message', function(d) {
			if( d.guid ){
				for ( var x in TicketViewService.sideInfo.data.messages ) {
					if ( TicketViewService.sideInfo.data.messages[x].guid == d.guid ) {
						if( TicketViewService.sideInfo.data.messages[x].sending ){
							TicketViewService.sideInfo.data.messages[x] = d;
							console.log('updated status');
						}
						console.log('message already added!');
						return;
					}
				}
			}
			TicketViewService.sideInfo.add_message( d );
		});
	}

	$rootScope.$on( 'triggerViewTicket', function(e, ticket) {
		if( ticket.id_support != TicketViewService.sideInfo.id_support ){
			TicketViewService.sideInfo.setTicket( 0 );
			TicketViewService.sideInfo.setTicket( ticket.id_support );
			loadData();
			socketStuff();
		}
	} );

	$scope.send = TicketViewService.send;
	loadData();
	socketStuff();

} );

NGApp.controller('SideSupportCtrl', function($scope, $rootScope, TicketViewService) {
	TicketViewService.scope = $scope;
	$scope.setViewTicket = TicketViewService.setViewTicket;
});

NGApp.controller('SideSupportPexCardCtrl', function( $scope, StaffPayInfoService, PexCardService ) {

	$scope.add_funds = function(){
		if( $scope.ticket && $scope.ticket.pexcard && $scope.ticket.pexcard.id_pexcard ){
			if( $scope.form.$invalid ){
				App.alert( 'Please fill in all required fields' );
				$scope.submitted = true;
				return;
			}
			$scope.pexcard.id_pexcard = $scope.ticket.pexcard.id_pexcard;
			$scope.isAdding = true;
			PexCardService.add_funds( $scope.pexcard, function( data ){
				if( data.error ){
					App.alert( data.error);
					$scope.isAdding = false;
					return;
				} else {
					$scope.isAdding = false;
					$scope.flash.setMessage( 'Funds Added!' );
					$scope.pexcard = {};
					$scope.isLoadingBalance = true;
					setTimeout( function(){ $scope.current_balanced(); }, 3000 );
				}
			} );
		} else {
			App.alert( 'Oops, it seems the driver doesn\'t have a PexCard!' );
		}
	}

	$scope.current_balanced = function(){
		if( $scope.ticket && $scope.ticket.pexcard && $scope.ticket.pexcard.card_serial ){

			$scope.isLoadingBalance = true;

			PexCardService.pex_id( $scope.ticket.pexcard.card_serial,
				function( json ){
					$scope.isLoadingBalance = false;
					if( json.id ){
						$scope.card = json;
					} else {
						$scope.flash.setMessage( json.error, 'error' );
					}
				}
			);
		} else {
			App.alert( 'Oops, it seems the driver doesn\'t have a PexCard!' );
		}
	}

} );

NGApp.controller('SupportPhoneCtrl', function( $scope, $rootScope, StaffService, CallService, MainNavigationService, TwilioService) {

	$scope.call = { staff : '', to : 'customer', _to: CallService.call_to() };
	$scope.sms = { staff : '', to : 'customer', _to: CallService.call_to() };

	$scope.$watch( 'call.staff', function( newValue, oldValue, scope ) {
		$scope.call.phone = newValue.phone;
	}	);

	$scope.$watch( 'sms.staff', function( newValue, oldValue, scope ) {
		$scope.sms.phone = newValue.phone;
		$scope.sms.name = newValue.name;
	}	);

	StaffService.phones( function( response ){
		$scope.staff = response;
	} );

	$scope.formCallSending = false;
	$scope.formSMSSending = false;

	$scope.reset = function(){
		$scope.call.phone = '';
		$scope.sms.phone = '';
		$scope.sms.message = '';
	}

	$scope.sms.send = function(){

		if( $scope.formSMS.$invalid ){
			$scope.formSMSSubmitted = true;
			return;
		}

		$scope.formSMSSending = true;
		CallService.send_sms( $scope.sms, function( json ){
			$scope.formSMSSending = false;
			if( json.success ){
				MainNavigationService.link( '/ticket/' + json.success);
				if( $scope.complete ){
					$scope.complete();
				}
				$scope.reset();
			} else {
				App.alert( json.error );
			}
		} );
	}

	$scope.call.make = function(){
		if( $scope.formCall.$invalid ){
			$scope.formCallSubmitted = true;
			return;
		}
		$scope.formCallSending = true;
		CallService.make_call( $scope.call, function( json ){
			$scope.formCallSending = false;
			if( json.success ){
				App.alert( json.success );
				$scope.reset();
			} else {
				App.alert( json.error );
			}
		} );
	}

	$scope.call.voip = function() {
		TwilioService.call($scope.call.phone);
		App.dialog.close();
	};

	// Reset stuff when calling from modal
	$rootScope.$on('callText', function(e, num) {
		$scope.reset();
		$scope.call.phone = num;
		$scope.sms.phone = num;
	} );

} );

NGApp.controller('SupportCtrl', function($scope, $rootScope, $timeout, TicketService, TicketViewService, CallService) {

	$scope.ticketparams = {
		status: 'open'
	};

	$scope.callparams = {
		status: ['in-progress','ringing'],
		limit: 5,
		today: true
	};

	$scope.closeTicket = function( id_support ){
		TicketService.openClose( id_support, function() { update(); } );
	}

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count || newValue.timestamp != oldValue.timestamp ) {
			update();
		}
	}, true);

	var update = function(){
		TicketService.list($scope.ticketparams, function(d) {
			$scope.lotsoftickets = d.results;
			TicketViewService.scope.tickets = d.results;
		});
	}

	CallService.list($scope.callparams, function(d) {
		$scope.calls = d.results;
	});

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


<commit_before>NGApp.config(['$routeProvider', function($routeProvider) {
	$routeProvider
		.when('/support', {
			redirectTo: '/tickets'
		})
		.when('/tickets', {
			action: 'tickets',
			controller: 'TicketsViewCtrl',
			templateUrl: 'assets/view/tickets-view.html'
		})
		.when('/ticket/:id', {
			action: 'ticket',
			controller: 'TicketsTicketCtrl',
			templateUrl: 'assets/view/tickets-ticket.html'
		});
}]);

NGApp.controller('SideTicketsCtrl', function($scope, $rootScope, TicketService, TicketViewService) {
	$scope.params = {
		status: 'open'
	};

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count) {
			console.debug('Updating support tickets...');
			TicketService.list($scope.params, function(tickets) {
				TicketViewService.scope.tickets = tickets;
			});
		}
	});
});

NGApp.controller('SideTicketCtrl', function($scope, $rootScope, TicketService, TicketViewService) {

	var loadTicket = function(id) {
		TicketService.get(id, function(ticket) {
			TicketViewService.scope.ticket = ticket;
			TicketViewService.scroll();
		});
	};

	$rootScope.$on('triggerViewTicket', function(e, ticket) {
		loadTicket(ticket == 'refresh' ? TicketViewService.scope.ticket : ticket);
	});

	$scope.send = TicketViewService.send;

	loadTicket(TicketViewService.scope.viewTicket);

});

NGApp.controller('SideSupportCtrl', function($scope, $rootScope, TicketViewService) {
	TicketViewService.scope = $scope;
	$scope.setViewTicket = TicketViewService.setViewTicket;
});

NGApp.factory('TicketViewService', function($rootScope, $resource, $routeParams, NotificationService, AccountService) {
	var service = {
		isTyping: false
	};
	service.setViewTicket = function(id) {
		service.scope.viewTicket = id;
	};

	$rootScope.$on('triggerViewTicket', function(e, ticket) {
		NotificationService.check();

		service.scope.viewTicket = ticket;
		$rootScope.supportToggled = true;

		if (service.scope.viewTicket) {
			service.socket.emit('event.subscribe', 'ticket.' + service.scope.viewTicket);
		}
	});

//	service.websocket = new WebSocket('wss://' + location.host + ':9000/test?_token=' + $.cookie('token'));

	service.socket = io('https://chat.cockpit.la');

	service.socket.on('connect', function (data) {
		console.debug('Connected to socket.io');
		service.socket.emit('auth', {
			token: $.cookie('token'),
			phpsessid: $.cookie('PHPSESSID'),
			host: location.host
		});

		if (AccountService.user.id_admin == 1) {
			service.socket.emit('event.subscribe', 'ticket.all');
		}
	});

	service.send = function(message) {
		var msg = {
			url: '/api/tickets/' + service.scope.viewTicket + '/message',
			data: {
				body: message
			}
		};

		service.scope.ticket.messages.push({
			body: message,
			name: AccountService.user.firstName,
			timestamp: new Date().getTime()
		});
		service.scope.$apply();
		service.scroll();

		service.socket.emit('event.message', msg);
		service.isTyping = false;
	};

	var typingTimer;

	service.typing = function(val) {
		return;
		if (!service.isTyping) {
			service.isTyping = true;
			service.websocket.send({
				type: 'ticket.typing.start'
			});

		} else {
			if (!val) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}

		if (typingTimer) {
			clearTimeout(typingTimer);
		}
		typingTimer = setTimeout(function() {
			if (service.isTyping) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}, 5000);
	};

	service.socket.on('event.response', function(payload) {
		console.debug('event response: ',payload);
	});

	var notified  = new Array();
	service.socket.on('ticket.message', function(payload) {

		console.debug('Recieved chat message: ', payload);

		service.scope.ticket.messages.push(payload);
		service.scope.$apply();
		service.scroll();

		if (notified.indexOf(payload.id_support_message) > -1) {
			return;
		}

		notified.push(payload.id_support_message);

		if (payload.id_support == service.scope.viewTicket) {
			App.playAudio('support-message-recieved');
		} else {
			App.playAudio('support-message-new');
		}

		NotificationService.notify(payload.name, payload.body, null, function() {
			document.getElementById('support-chat-box').focus();
		});

	});

	service.scroll = function() {
		$('.support-chat-contents-scroll').stop(true,false).animate({
			scrollTop: $('.support-chat-contents-scroll')[0].scrollHeight
		}, 1800);
	};

	return service;
});

NGApp.controller('TicketsViewCtrl', function($scope, $rootScope, TicketService, TicketViewService) {
	$scope.params = {
		status: 'open'
	};

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count) {
			console.debug('Updating support tickets...');
			TicketService.list($scope.params, function(tickets) {
				$scope.tickets = tickets;
			});
		}
	});

	TicketService.list($scope.params, function(tickets) {
		$scope.tickets = tickets;
	});
});

NGApp.controller('TicketsTicketCtrl', function($scope, $rootScope, $routeParams, TicketService) {
	$rootScope.$broadcast('triggerViewTicket', $routeParams.id);

	TicketService.get($routeParams.id, function(ticket) {
		$scope.ticket = ticket;
		$scope.ready = true;
	});
});<commit_msg>prevent double post<commit_after>NGApp.config(['$routeProvider', function($routeProvider) {
	$routeProvider
		.when('/support', {
			redirectTo: '/tickets'
		})
		.when('/tickets', {
			action: 'tickets',
			controller: 'TicketsViewCtrl',
			templateUrl: 'assets/view/tickets-view.html'
		})
		.when('/ticket/:id', {
			action: 'ticket',
			controller: 'TicketsTicketCtrl',
			templateUrl: 'assets/view/tickets-ticket.html'
		});
}]);

NGApp.controller('SideTicketsCtrl', function($scope, $rootScope, TicketService, TicketViewService) {
	$scope.params = {
		status: 'open'
	};

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count) {
			console.debug('Updating support tickets...');
			TicketService.list($scope.params, function(tickets) {
				TicketViewService.scope.tickets = tickets;
			});
		}
	});
});

NGApp.controller('SideTicketCtrl', function($scope, $rootScope, TicketService, TicketViewService) {

	var loadTicket = function(id) {
		TicketService.get(id, function(ticket) {
			TicketViewService.scope.ticket = ticket;
			TicketViewService.scroll();
		});
	};

	$rootScope.$on('triggerViewTicket', function(e, ticket) {
		loadTicket(ticket == 'refresh' ? TicketViewService.scope.ticket : ticket);
	});

	$scope.send = TicketViewService.send;

	loadTicket(TicketViewService.scope.viewTicket);

});

NGApp.controller('SideSupportCtrl', function($scope, $rootScope, TicketViewService) {
	TicketViewService.scope = $scope;
	$scope.setViewTicket = TicketViewService.setViewTicket;
});

NGApp.factory('TicketViewService', function($rootScope, $resource, $routeParams, NotificationService, AccountService) {
	var service = {
		isTyping: false
	};
	service.setViewTicket = function(id) {
		service.scope.viewTicket = id;
	};

	$rootScope.$on('triggerViewTicket', function(e, ticket) {
		NotificationService.check();

		service.scope.viewTicket = ticket;
		$rootScope.supportToggled = true;

		if (service.scope.viewTicket) {
			service.socket.emit('event.subscribe', 'ticket.' + service.scope.viewTicket);
		}
	});

//	service.websocket = new WebSocket('wss://' + location.host + ':9000/test?_token=' + $.cookie('token'));

	service.socket = io('https://chat.cockpit.la');

	service.socket.on('connect', function (data) {
		console.debug('Connected to socket.io');
		service.socket.emit('auth', {
			token: $.cookie('token'),
			phpsessid: $.cookie('PHPSESSID'),
			host: location.host
		});

		if (AccountService.user.id_admin == 1) {
			service.socket.emit('event.subscribe', 'ticket.all');
		}
	});

	service.send = function(message) {
		var msg = {
			url: '/api/tickets/' + service.scope.viewTicket + '/message',
			data: {
				body: message
			}
		};

		service.scope.ticket.messages.push({
			body: message,
			name: AccountService.user.firstName,
			timestamp: new Date().getTime()
		});
		service.scope.$apply();
		service.scroll();

		service.socket.emit('event.message', msg);
		service.isTyping = false;
	};

	var typingTimer;

	service.typing = function(val) {
		return;
		if (!service.isTyping) {
			service.isTyping = true;
			service.websocket.send({
				type: 'ticket.typing.start'
			});

		} else {
			if (!val) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}

		if (typingTimer) {
			clearTimeout(typingTimer);
		}
		typingTimer = setTimeout(function() {
			if (service.isTyping) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}, 5000);
	};

	service.socket.on('event.response', function(payload) {
		console.debug('event response: ',payload);
	});

	var notified  = new Array();
	service.socket.on('ticket.message', function(payload) {

		console.debug('Recieved chat message: ', payload);

		if (notified.indexOf(payload.id_support_message) > -1) {
			return;
		}

		service.scope.ticket.messages.push(payload);
		service.scope.$apply();
		service.scroll();

		notified.push(payload.id_support_message);

		if (payload.id_support == service.scope.viewTicket) {
			App.playAudio('support-message-recieved');
		} else {
			App.playAudio('support-message-new');
		}

		NotificationService.notify(payload.name, payload.body, null, function() {
			document.getElementById('support-chat-box').focus();
		});

	});

	service.scroll = function() {
		$('.support-chat-contents-scroll').stop(true,false).animate({
			scrollTop: $('.support-chat-contents-scroll')[0].scrollHeight
		}, 1800);
	};

	return service;
});

NGApp.controller('TicketsViewCtrl', function($scope, $rootScope, TicketService, TicketViewService) {
	$scope.params = {
		status: 'open'
	};

	$rootScope.$watch('supportMessages', function(newValue, oldValue) {
		if (!newValue) {
			return;
		}
		if (!oldValue || newValue.count != oldValue.count) {
			console.debug('Updating support tickets...');
			TicketService.list($scope.params, function(tickets) {
				$scope.tickets = tickets;
			});
		}
	});

	TicketService.list($scope.params, function(tickets) {
		$scope.tickets = tickets;
	});
});

NGApp.controller('TicketsTicketCtrl', function($scope, $rootScope, $routeParams, TicketService) {
	$rootScope.$broadcast('triggerViewTicket', $routeParams.id);

	TicketService.get($routeParams.id, function(ticket) {
		$scope.ticket = ticket;
		$scope.ready = true;
	});
});<|endoftext|>


<commit_before>import Immutable from 'immutable'
import { createSelector } from 'reselect'
import get from 'lodash/get'
import { LOAD_STREAM_REQUEST } from '../constants/action_types'
import { COMMENTS, POSTS } from '../constants/mapping_types'
import { selectIsLoggedIn } from './authentication'
import { selectIsGridMode } from './gui'
import { selectCategoryCollection } from './categories'
import { selectParamsToken } from './params'
import { selectId as selectProfileId } from './profile'
import { selectIsPostDetail } from './routing'
import { selectJson } from './store'
import { selectUsers } from './user'
import { selectStreamType, selectStreamMappingType, selectStreamPostIdOrToken } from './stream'
import { findModel } from '../helpers/json_helper'

export const selectPropsPostId = (state, props) =>
  get(props, 'postId') || get(props, 'post', Immutable.Map()).get('id')

// Memoized selectors

// Requires `postId`, `post` or `params.token` to be found in props
// If `post` is on the props, grab it's id and do a lookup on `json.posts` for the latest
// TODO: `findModel` gets calculated a lot with json being an argument :(, is this a concern?
export const selectPost = createSelector(
  [selectPropsPostId, selectParamsToken, selectJson], (id, token, json) => {
    if (id || token) {
      const findObj = id ? { id } : { token }
      return findModel(json, { collection: POSTS, findObj }) || Immutable.Map()
    }
    return Immutable.Map()
  },
)

// Properties on the post reducer
export const selectPostAuthorId = createSelector([selectPost], post => post.get('authorId'))
export const selectPostBody = createSelector([selectPost], post => post.get('body'))
export const selectPostCommentsCount = createSelector([selectPost], post => post.get('commentsCount'))
export const selectPostContent = createSelector([selectPost], post => post.get('content'))
export const selectPostContentWarning = createSelector([selectPost], post => post.get('contentWarning'))
export const selectPostCreatedAt = createSelector([selectPost], post => post.get('createdAt'))
export const selectPostHref = createSelector([selectPost], post => post.get('href'))
export const selectPostId = createSelector([selectPost], post => post.get('id'))
export const selectPostIsAdultContent = createSelector([selectPost], post => post.get('isAdultContent'))
export const selectPostMetaAttributes = createSelector([selectPost], post => post.get('metaAttributes', Immutable.Map()))
export const selectPostLoved = createSelector([selectPost], post => post.get('loved'))
export const selectPostLovesCount = createSelector([selectPost], post => post.get('lovesCount'))
export const selectPostRepostContent = createSelector([selectPost], post => post.get('repostContent'))
export const selectPostRepostId = createSelector([selectPost], post => post.get('repostId'))
export const selectPostRepostPath = createSelector([selectPost], post => post.get('repostPath'))
export const selectPostReposted = createSelector([selectPost], post => post.get('reposted'))
export const selectPostRepostsCount = createSelector([selectPost], post => post.get('repostsCount'))
export const selectPostShowComments = createSelector([selectPost], post => post.get('showComments', false))
export const selectPostShowLovers = createSelector([selectPost], post => post.get('showLovers', false))
export const selectPostShowReposters = createSelector([selectPost], post => post.get('showReposters', false))
export const selectPostSummary = createSelector([selectPost], post => post.get('summary'))
export const selectPostToken = createSelector([selectPost], post => post.get('token'))
export const selectPostViewsCount = createSelector([selectPost], post => post.get('viewsCount'))
export const selectPostViewsCountRounded = createSelector([selectPost], post => post.get('viewsCountRounded'))
export const selectPostWatching = createSelector([selectPost], post => post.get('watching'))

// Nested properties on the post reducer
export const selectPostMetaDescription = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('description'),
)

export const selectPostMetaCanonicalUrl = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('canonicalUrl'),
)

export const selectPostMetaImages = createSelector(
  [selectPostMetaAttributes], (metaAttributes) => {
    const images = (metaAttributes.get('images') || Immutable.List()).toArray()
    const openGraphImages = images.map(image => ({ property: 'og:image', content: image }))
    const schemaImages = images.map(image => ({ name: 'image', itemprop: 'image', content: image }))
    return { openGraphImages, schemaImages }
  },
)

export const selectPostMetaRobots = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('robots'),
)

export const selectPostMetaTitle = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('title'),
)

export const selectPostMetaUrl = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('url'),
)

// TODO: Pull other properties out of post.get('links')?
export const selectPostRepostAuthorId = createSelector([selectPost], post =>
  post.getIn(['links', 'repostAuthor', 'id']),
)

// Derived or additive properties
export const selectPostAuthor = createSelector(
  [selectUsers, selectPostAuthorId], (users, authorId) => users.get(authorId),
)

export const selectPostAuthorUsername = createSelector(
  [selectPostAuthor], author => author.get('username'),
)

export const selectPostRepostAuthor = createSelector(
  [selectUsers, selectPostRepostAuthorId], (users, repostAuthorId) => users.get(repostAuthorId),
)

export const selectPostCategories = createSelector(
  [selectPost], post => post.getIn(['links', 'categories'], Immutable.List()),
)

export const selectPostCategory = createSelector(
  [selectCategoryCollection, selectPostCategories], (collection, categories) =>
    collection && collection.get(categories ? categories.first() : null),
)

export const selectPostCategoryName = createSelector(
  [selectPostCategory], category => category && category.get('name', null),
)

export const selectPostCategorySlug = createSelector(
  [selectPostCategory], category => (category ? `/discover/${category.get('slug')}` : null),
)

export const selectPostDetailPath = createSelector(
  [selectPostAuthorUsername, selectPostToken], (username, token) => `/${username}/post/${token}`,
)

export const selectPostIsCommentsRequesting = createSelector(
  [selectStreamType, selectStreamMappingType, selectStreamPostIdOrToken,
    selectPostId, selectPostToken],
  (streamType, streamMappingType, streamPostIdOrToken, postId, postToken) =>
    streamType === LOAD_STREAM_REQUEST && streamMappingType === COMMENTS &&
    (`${streamPostIdOrToken}` === `${postId}` || `${streamPostIdOrToken}` === `${postToken}`),
)

export const selectPostIsEditing = createSelector([selectPost], post =>
  post.get('isEditing', false),
)

export const selectPostIsGridMode = createSelector(
  [selectIsPostDetail, selectIsGridMode], (isPostDetail, isGridMode) =>
    (isPostDetail ? false : isGridMode),
)

export const selectPostIsOwn = createSelector(
  [selectPostAuthorId, selectProfileId], (authorId, profileId) =>
    `${authorId}` === `${profileId}`,
)

export const selectPostIsOwnOriginal = createSelector(
  [selectPostRepostAuthorId, selectProfileId], (repostAuthorId, profileId) =>
    `${repostAuthorId}` === `${profileId}`,
)

export const selectPostIsRepost = createSelector(
  [selectPostRepostContent], repostContent => !!(repostContent && repostContent.size),
)

export const selectPostIsReposting = createSelector([selectPost], post =>
  post.get('isReposting', false),
)

export const selectPostIsWatching = createSelector(
  [selectIsLoggedIn, selectPostWatching], (isLoggedIn, watching) => isLoggedIn && watching,
)

export const selectPostRepostAuthorWithFallback = createSelector(
  [selectPostIsRepost, selectPostRepostAuthor, selectPostAuthor],
  (isRepost, repostAuthor, author) =>
    (isRepost ? (repostAuthor || author) : null),
)

// Editor and drawer states for a given post
export const selectPostShowEditor = createSelector(
  [selectPostIsEditing, selectPostIsReposting, selectPostBody],
  (isEditing, isReposting, postBody) =>
    !!((isEditing || isReposting) && postBody),
)

export const selectPostShowCommentEditor = createSelector(
  [selectPostShowEditor, selectPostShowComments, selectIsPostDetail],
  (showEditor, showComments, isPostDetail) =>
    !showEditor && !isPostDetail && showComments,
)

export const selectPostShowCommentsDrawer = createSelector(
  [selectPostShowCommentEditor, selectPostCommentsCount],
  (showCommentEditor, commentsCount) =>
    showCommentEditor && commentsCount > 0,
)

export const selectPostShowLoversDrawer = createSelector(
  [selectPostShowEditor, selectPostIsGridMode, selectPostShowLovers,
    selectPostLovesCount, selectIsPostDetail],
  (showEditor, isGridMode, showLovers, lovesCount, isPostDetail) =>
    (!showEditor && !isGridMode && showLovers && lovesCount > 0) ||
    (!showEditor && !isGridMode && isPostDetail && lovesCount > 0),
)

export const selectPostShowRepostersDrawer = createSelector(
  [selectPostShowEditor, selectPostIsGridMode, selectPostShowReposters,
    selectPostRepostsCount, selectIsPostDetail],
  (showEditor, isGridMode, showReposters, repostsCount, isPostDetail) =>
    (!showEditor && !isGridMode && showReposters && repostsCount > 0) ||
    (!showEditor && !isGridMode && isPostDetail && repostsCount > 0),
)

<commit_msg>More focused lookup for selecting a post<commit_after>import Immutable from 'immutable'
import { createSelector } from 'reselect'
import get from 'lodash/get'
import { LOAD_STREAM_REQUEST } from '../constants/action_types'
import { COMMENTS, POSTS } from '../constants/mapping_types'
import { selectIsLoggedIn } from './authentication'
import { selectCategoryCollection } from './categories'
import { selectIsGridMode } from './gui'
import { selectParamsToken } from './params'
import { selectId as selectProfileId } from './profile'
import { selectIsPostDetail } from './routing'
import { selectStreamType, selectStreamMappingType, selectStreamPostIdOrToken } from './stream'
import { selectUsers } from './user'

export const selectPropsPostId = (state, props) =>
  get(props, 'postId') || get(props, 'post', Immutable.Map()).get('id')

export const selectPosts = state => state.json.get(POSTS)

// Memoized selectors

// Requires `postId`, `post` or `params.token` to be found in props
export const selectPost = createSelector(
  [selectPropsPostId, selectParamsToken, selectPosts], (id, token, posts) => {
    if (id && posts) {
      return posts.get(id, Immutable.Map())
    } else if (token && posts) {
      return (posts.find(post => post.get('token') === token)) || Immutable.Map()
    }
    return Immutable.Map()
  },
)

// Properties on the post reducer
export const selectPostAuthorId = createSelector([selectPost], post => post.get('authorId'))
export const selectPostBody = createSelector([selectPost], post => post.get('body'))
export const selectPostCommentsCount = createSelector([selectPost], post => post.get('commentsCount'))
export const selectPostContent = createSelector([selectPost], post => post.get('content'))
export const selectPostContentWarning = createSelector([selectPost], post => post.get('contentWarning'))
export const selectPostCreatedAt = createSelector([selectPost], post => post.get('createdAt'))
export const selectPostHref = createSelector([selectPost], post => post.get('href'))
export const selectPostId = createSelector([selectPost], post => post.get('id'))
export const selectPostIsAdultContent = createSelector([selectPost], post => post.get('isAdultContent'))
export const selectPostMetaAttributes = createSelector([selectPost], post => post.get('metaAttributes', Immutable.Map()))
export const selectPostLoved = createSelector([selectPost], post => post.get('loved'))
export const selectPostLovesCount = createSelector([selectPost], post => post.get('lovesCount'))
export const selectPostRepostContent = createSelector([selectPost], post => post.get('repostContent'))
export const selectPostRepostId = createSelector([selectPost], post => post.get('repostId'))
export const selectPostRepostPath = createSelector([selectPost], post => post.get('repostPath'))
export const selectPostReposted = createSelector([selectPost], post => post.get('reposted'))
export const selectPostRepostsCount = createSelector([selectPost], post => post.get('repostsCount'))
export const selectPostShowComments = createSelector([selectPost], post => post.get('showComments', false))
export const selectPostShowLovers = createSelector([selectPost], post => post.get('showLovers', false))
export const selectPostShowReposters = createSelector([selectPost], post => post.get('showReposters', false))
export const selectPostSummary = createSelector([selectPost], post => post.get('summary'))
export const selectPostToken = createSelector([selectPost], post => post.get('token'))
export const selectPostViewsCount = createSelector([selectPost], post => post.get('viewsCount'))
export const selectPostViewsCountRounded = createSelector([selectPost], post => post.get('viewsCountRounded'))
export const selectPostWatching = createSelector([selectPost], post => post.get('watching'))

// Nested properties on the post reducer
export const selectPostMetaDescription = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('description'),
)

export const selectPostMetaCanonicalUrl = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('canonicalUrl'),
)

export const selectPostMetaImages = createSelector(
  [selectPostMetaAttributes], (metaAttributes) => {
    const images = (metaAttributes.get('images') || Immutable.List()).toArray()
    const openGraphImages = images.map(image => ({ property: 'og:image', content: image }))
    const schemaImages = images.map(image => ({ name: 'image', itemprop: 'image', content: image }))
    return { openGraphImages, schemaImages }
  },
)

export const selectPostMetaRobots = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('robots'),
)

export const selectPostMetaTitle = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('title'),
)

export const selectPostMetaUrl = createSelector(
  [selectPostMetaAttributes], metaAttributes => metaAttributes.get('url'),
)

// TODO: Pull other properties out of post.get('links')?
export const selectPostRepostAuthorId = createSelector([selectPost], post =>
  post.getIn(['links', 'repostAuthor', 'id']),
)

// Derived or additive properties
export const selectPostAuthor = createSelector(
  [selectUsers, selectPostAuthorId], (users, authorId) => users.get(authorId),
)

export const selectPostAuthorUsername = createSelector(
  [selectPostAuthor], author => author.get('username'),
)

export const selectPostRepostAuthor = createSelector(
  [selectUsers, selectPostRepostAuthorId], (users, repostAuthorId) => users.get(repostAuthorId),
)

export const selectPostCategories = createSelector(
  [selectPost], post => post.getIn(['links', 'categories'], Immutable.List()),
)

export const selectPostCategory = createSelector(
  [selectCategoryCollection, selectPostCategories], (collection, categories) =>
    collection && collection.get(categories ? categories.first() : null),
)

export const selectPostCategoryName = createSelector(
  [selectPostCategory], category => category && category.get('name', null),
)

export const selectPostCategorySlug = createSelector(
  [selectPostCategory], category => (category ? `/discover/${category.get('slug')}` : null),
)

export const selectPostDetailPath = createSelector(
  [selectPostAuthorUsername, selectPostToken], (username, token) => `/${username}/post/${token}`,
)

export const selectPostIsCommentsRequesting = createSelector(
  [selectStreamType, selectStreamMappingType, selectStreamPostIdOrToken,
    selectPostId, selectPostToken],
  (streamType, streamMappingType, streamPostIdOrToken, postId, postToken) =>
    streamType === LOAD_STREAM_REQUEST && streamMappingType === COMMENTS &&
    (`${streamPostIdOrToken}` === `${postId}` || `${streamPostIdOrToken}` === `${postToken}`),
)

export const selectPostIsEditing = createSelector([selectPost], post =>
  post.get('isEditing', false),
)

export const selectPostIsGridMode = createSelector(
  [selectIsPostDetail, selectIsGridMode], (isPostDetail, isGridMode) =>
    (isPostDetail ? false : isGridMode),
)

export const selectPostIsOwn = createSelector(
  [selectPostAuthorId, selectProfileId], (authorId, profileId) =>
    `${authorId}` === `${profileId}`,
)

export const selectPostIsOwnOriginal = createSelector(
  [selectPostRepostAuthorId, selectProfileId], (repostAuthorId, profileId) =>
    `${repostAuthorId}` === `${profileId}`,
)

export const selectPostIsRepost = createSelector(
  [selectPostRepostContent], repostContent => !!(repostContent && repostContent.size),
)

export const selectPostIsReposting = createSelector([selectPost], post =>
  post.get('isReposting', false),
)

export const selectPostIsWatching = createSelector(
  [selectIsLoggedIn, selectPostWatching], (isLoggedIn, watching) => isLoggedIn && watching,
)

export const selectPostRepostAuthorWithFallback = createSelector(
  [selectPostIsRepost, selectPostRepostAuthor, selectPostAuthor],
  (isRepost, repostAuthor, author) =>
    (isRepost ? (repostAuthor || author) : null),
)

// Editor and drawer states for a given post
export const selectPostShowEditor = createSelector(
  [selectPostIsEditing, selectPostIsReposting, selectPostBody],
  (isEditing, isReposting, postBody) =>
    !!((isEditing || isReposting) && postBody),
)

export const selectPostShowCommentEditor = createSelector(
  [selectPostShowEditor, selectPostShowComments, selectIsPostDetail],
  (showEditor, showComments, isPostDetail) =>
    !showEditor && !isPostDetail && showComments,
)

export const selectPostShowCommentsDrawer = createSelector(
  [selectPostShowCommentEditor, selectPostCommentsCount],
  (showCommentEditor, commentsCount) =>
    showCommentEditor && commentsCount > 0,
)

export const selectPostShowLoversDrawer = createSelector(
  [selectPostShowEditor, selectPostIsGridMode, selectPostShowLovers,
    selectPostLovesCount, selectIsPostDetail],
  (showEditor, isGridMode, showLovers, lovesCount, isPostDetail) =>
    (!showEditor && !isGridMode && showLovers && lovesCount > 0) ||
    (!showEditor && !isGridMode && isPostDetail && lovesCount > 0),
)

export const selectPostShowRepostersDrawer = createSelector(
  [selectPostShowEditor, selectPostIsGridMode, selectPostShowReposters,
    selectPostRepostsCount, selectIsPostDetail],
  (showEditor, isGridMode, showReposters, repostsCount, isPostDetail) =>
    (!showEditor && !isGridMode && showReposters && repostsCount > 0) ||
    (!showEditor && !isGridMode && isPostDetail && repostsCount > 0),
)

<|endoftext|>


<commit_before>/*!
 * logstation JavaScript helper functions
 * Copyright 2015 Jon Drews
 * Distributed under an Apache 2.0 License
 */

// Safe way to get document height
function getDocHeight() {
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

// make a navigation bar entry the active one based on logId
function makeNavBarEntryActive(logId) {
    console.log("making this file the active one: " + logId);
    // takes in stripSpecials(logFile)

    //make all others not active
    $('.link-logfile').not('#link-'+logId).removeClass("active");
    //make the active one active
    $('#link-'+logId).addClass("active")
}

// hide all other log files, and make logFile the active one
function showLogFile(logFile) {
    console.log("making this file shown: " + logFile);
    var logId = stripSpecials(logFile);
    $('.logFile').not('#' + logId).hide();
    $("#"+logId).show();
    // Only set this log to active if there are no other logs
    if (window.totalLogLines.length > 0) {
        makeNavBarEntryActive(logId)
    }
}

// add a new navigation bar entry for logFile
function addNavBarEntry(logFile) {
    console.log("checking nav for " + logFile);
    var logId = stripSpecials(logFile);
    // only add it if it doesn't already exist
    if ($("#link-"+logId).length == 0) {
        console.log("adding nav for " + logFile);
        //
Home

        var truncatedFileNameArr = logFile.split(/[\\/]+/);
        var truncatedFileName = truncatedFileNameArr[truncatedFileNameArr.length - 1];
        $("ul.nav").append('
'+truncatedFileName+'
');
        showLogFile(logFile)
    }

}

// creates an id based on the log file path, that doesn't contain any special characters
function stripSpecials( myid ) {
    return myid.replace(/([~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '-').replace(/^(-)+|(-)+$/g,'')
}

// if the logFile doesn't exist, add it
// used to push in logs from LogStationPage via a JsFunc
function addOrAppendLogMessage(logFile, logMessage) {
    if (window.pauseState == "play") {
        //create logId
        var logId = stripSpecials(logFile);
        incrementTotalLogLines(logId);
        // Get the div corresponding to this log file
        var logDiv = $("#"+logId);
        console.log("working on " + logId + "; logDiv.length = " + logDiv.length);
        if (logDiv.length) {
            // log file already exists, append message
            console.log("appending to " + logId + " the message " + logMessage);
            logDiv.append("
" + logMessage + "

")

        } else {
            // log file doesn't exist yet. add it with this message
            console.log("adding new logFile " + logId);
            $("#logbody").append("

"+logMessage+"

");
            addNavBarEntry(logFile)
        }
        truncateLinesIfNeeded(logId);
        adjustScroll()
    } else {
        console.log("state paused, not appending message")
    }
}

// update the current maxLogLinesPerLog
// called from LogStationPage
function updateMaxLogLinesPerLog(maxLogLinesPerLog) {
    console.log("updating maxLogLinesPerLog to " + maxLogLinesPerLog);
    window.maxLogLinesPerLog = maxLogLinesPerLog
}

// called from LogStationPage for resetting all local vars
function resetAll() {
    console.log("resetting all");
    window.totalLogLines  = {};
    window.scrollFollow = "follow"
}

// called from LogStationPage to default to following (tailing) to logs
function enableScrollFollow() {
    window.scrollFollow = "follow"
}

// called from LogStationPage to default to playing log messages
function enablePlay() {
    window.pauseState = "play"
}

// increment number of lines in all logs, and handle truncating if they get too large
function incrementTotalLogLines(logId) {
    // increment number of total lines
    if (typeof window.totalLogLines == 'undefined') {
        // first time incrementing any logs. make the Object
        window.totalLogLines = {};
        window.totalLogLines[logId] = 1
    } else if (!(logId in window.totalLogLines)) {
        // first time incrementing this log. initialize
        window.totalLogLines[logId] = 1
    } else {
        // we've managed this log before. increment
        window.totalLogLines[logId] = window.totalLogLines[logId] + 1
    }

    if (typeof window.maxLogLinesPerLog == 'undefined') {
        window.maxLogLinesPerLog = 140
    }
}

function logExists(logId) {
    return (logId in window.totalLogLines)
}

// chop some log messages off the head if we've hit maxLogLinesPerLog
function truncateLinesIfNeeded(logId) {
    console.log(logId + " => log line calculations: " + window.totalLogLines[logId] + " / " + (window.maxLogLinesPerLog));
    // if we've gone over maxLogLinesPerLog, truncate!
    if ( window.totalLogLines[logId] > window.maxLogLinesPerLog) {
        console.log( "working on truncating lines for " + logId);
        $( "#"+logId ).children(".logMessage").first().remove();
        //window.totalLogLines = window.totalLogLines + truncatedLines.length
        //$( this ).removeChild(truncatedLine)
    }
}

// if we're following, then scroll to bottom
function adjustScroll() {
    if (window.scrollFollow == "follow") {
        window.scrollTo(0,document.body.scrollHeight);
    }
}

// helper function to control the current scroll follow state
function setScrollFollow(desiredScrollFollow) {
    if (typeof window.scrollFollow == 'undefined') {
        // turn it on by default
        window.scrollFollow = "follow";
        $("#follow-indicator").html("follow on")
    } else if (window.scrollFollow == "userlockout" && desiredScrollFollow == "userlockout") {
        // user wants to turn user lockout off
        window.scrollFollow = "follow";
        $("#follow-indicator").html("follow on")
    } else if (desiredScrollFollow == "userlockout") {
        // user wants to turn user lockout on
        window.scrollFollow = "userlockout";
        $("#follow-indicator").html("follow user disabled")
    } else if (window.scrollFollow != "userlockout") {
        // we're not in a user lockout state
        if (desiredScrollFollow == "follow") {
            // user scrolled to bottom, start following again
            window.scrollFollow = desiredScrollFollow;
            $("#follow-indicator").html("follow on")
        } else if (desiredScrollFollow == "nofollow") {
            // user scrolled up, stop following.
            window.scrollFollow = desiredScrollFollow;
            $("#follow-indicator").html("follow off")
        }
    }

    console.log("scrollFollow: " + window.scrollFollow)
}

// Logic to control the state of the pause button
function updatePause () {
    if ($("#pause-button").text().match(/play/)) { // if we're playing right now
        console.log("pausing");
        $("#pause-button").html("paused");
        window.pauseState = "pause"
    } else if ($("#pause-button").text().match(/pause/)) { // if we're paused right now
        console.log("playing");
        $("#pause-button").html("playing");
        window.pauseState = "play"
    }
}

// If we hit the bottom-- turn on follow scroll. unless the user locked it out
$(window).scroll(function() {
    if($(window).scrollTop() + $(window).height() == getDocHeight()) {
        setScrollFollow("follow")
    } else {
        if (window.scrollFollow == "follow") {
            setScrollFollow("nofollow")
        }
    }
});

// if user clicks follow-indicator, start the scroll follow user lockout
$( "#follow-indicator" ).click(function() {
    setScrollFollow("userlockout")
});

// TODO: Make pause stop the backend from sending any new log messages
// if user clicks pause-button, update scrolling
$( "#pause-button" ).click(function() {
    updatePause()
});

<commit_msg>don't auto switch to new log files<commit_after>/*!
 * logstation JavaScript helper functions
 * Copyright 2015 Jon Drews
 * Distributed under an Apache 2.0 License
 */

// Safe way to get document height
function getDocHeight() {
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

// make a navigation bar entry the active one based on logId
function makeNavBarEntryActive(logId) {
    console.log("making this file the active one: " + logId);
    // takes in stripSpecials(logFile)

    //make all others not active
    $('.link-logfile').not('#link-'+logId).removeClass("active");
    //make the active one active
    $('#link-'+logId).addClass("active")
}

// hide all other log files, and make logFile the active one
function showLogFile(logFile) {
    console.log("making this file shown: " + logFile);
    var logId = stripSpecials(logFile);
    $('.logFile').not('#' + logId).hide();
    $("#"+logId).show();
    // Only set this log to active if there are no other logs
    if (window.totalLogLines.length > 0) {
        makeNavBarEntryActive(logId)
    }
}

// add a new navigation bar entry for logFile
function addNavBarEntry(logFile) {
    console.log("checking nav for " + logFile);
    var logId = stripSpecials(logFile);
    // only add it if it doesn't already exist
    if ($("#link-"+logId).length == 0) {
        console.log("adding nav for " + logFile);
        //
Home

        var truncatedFileNameArr = logFile.split(/[\\/]+/);
        var truncatedFileName = truncatedFileNameArr[truncatedFileNameArr.length - 1];
        $("ul.nav").append('
'+truncatedFileName+'
');
        //showLogFile(logFile)
    }

}

// creates an id based on the log file path, that doesn't contain any special characters
function stripSpecials( myid ) {
    return myid.replace(/([~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '-').replace(/^(-)+|(-)+$/g,'')
}

// if the logFile doesn't exist, add it
// used to push in logs from LogStationPage via a JsFunc
function addOrAppendLogMessage(logFile, logMessage) {
    if (window.pauseState == "play") {
        //create logId
        var logId = stripSpecials(logFile);
        incrementTotalLogLines(logId);
        // Get the div corresponding to this log file
        var logDiv = $("#"+logId);
        console.log("working on " + logId + "; logDiv.length = " + logDiv.length);
        if (logDiv.length) {
            // log file already exists, append message
            console.log("appending to " + logId + " the message " + logMessage);
            logDiv.append("
" + logMessage + "

")

        } else {
            // log file doesn't exist yet. add it with this message
            console.log("adding new logFile " + logId);
            $("#logbody").append("

"+logMessage+"

");
            addNavBarEntry(logFile)
        }
        truncateLinesIfNeeded(logId);
        adjustScroll()
    } else {
        console.log("state paused, not appending message")
    }
}

// update the current maxLogLinesPerLog
// called from LogStationPage
function updateMaxLogLinesPerLog(maxLogLinesPerLog) {
    console.log("updating maxLogLinesPerLog to " + maxLogLinesPerLog);
    window.maxLogLinesPerLog = maxLogLinesPerLog
}

// called from LogStationPage for resetting all local vars
function resetAll() {
    console.log("resetting all");
    window.totalLogLines  = {};
    window.scrollFollow = "follow"
}

// called from LogStationPage to default to following (tailing) to logs
function enableScrollFollow() {
    window.scrollFollow = "follow"
}

// called from LogStationPage to default to playing log messages
function enablePlay() {
    window.pauseState = "play"
}

// increment number of lines in all logs, and handle truncating if they get too large
function incrementTotalLogLines(logId) {
    // increment number of total lines
    if (typeof window.totalLogLines == 'undefined') {
        // first time incrementing any logs. make the Object
        window.totalLogLines = {};
        window.totalLogLines[logId] = 1
    } else if (!(logId in window.totalLogLines)) {
        // first time incrementing this log. initialize
        window.totalLogLines[logId] = 1
    } else {
        // we've managed this log before. increment
        window.totalLogLines[logId] = window.totalLogLines[logId] + 1
    }

    if (typeof window.maxLogLinesPerLog == 'undefined') {
        window.maxLogLinesPerLog = 140
    }
}

function logExists(logId) {
    return (logId in window.totalLogLines)
}

// chop some log messages off the head if we've hit maxLogLinesPerLog
function truncateLinesIfNeeded(logId) {
    console.log(logId + " => log line calculations: " + window.totalLogLines[logId] + " / " + (window.maxLogLinesPerLog));
    // if we've gone over maxLogLinesPerLog, truncate!
    if ( window.totalLogLines[logId] > window.maxLogLinesPerLog) {
        console.log( "working on truncating lines for " + logId);
        $( "#"+logId ).children(".logMessage").first().remove();
        //window.totalLogLines = window.totalLogLines + truncatedLines.length
        //$( this ).removeChild(truncatedLine)
    }
}

// if we're following, then scroll to bottom
function adjustScroll() {
    if (window.scrollFollow == "follow") {
        window.scrollTo(0,document.body.scrollHeight);
    }
}

// helper function to control the current scroll follow state
function setScrollFollow(desiredScrollFollow) {
    if (typeof window.scrollFollow == 'undefined') {
        // turn it on by default
        window.scrollFollow = "follow";
        $("#follow-indicator").html("follow on")
    } else if (window.scrollFollow == "userlockout" && desiredScrollFollow == "userlockout") {
        // user wants to turn user lockout off
        window.scrollFollow = "follow";
        $("#follow-indicator").html("follow on")
    } else if (desiredScrollFollow == "userlockout") {
        // user wants to turn user lockout on
        window.scrollFollow = "userlockout";
        $("#follow-indicator").html("follow user disabled")
    } else if (window.scrollFollow != "userlockout") {
        // we're not in a user lockout state
        if (desiredScrollFollow == "follow") {
            // user scrolled to bottom, start following again
            window.scrollFollow = desiredScrollFollow;
            $("#follow-indicator").html("follow on")
        } else if (desiredScrollFollow == "nofollow") {
            // user scrolled up, stop following.
            window.scrollFollow = desiredScrollFollow;
            $("#follow-indicator").html("follow off")
        }
    }

    console.log("scrollFollow: " + window.scrollFollow)
}

// Logic to control the state of the pause button
function updatePause () {
    if ($("#pause-button").text().match(/play/)) { // if we're playing right now
        console.log("pausing");
        $("#pause-button").html("paused");
        window.pauseState = "pause"
    } else if ($("#pause-button").text().match(/pause/)) { // if we're paused right now
        console.log("playing");
        $("#pause-button").html("playing");
        window.pauseState = "play"
    }
}

// If we hit the bottom-- turn on follow scroll. unless the user locked it out
$(window).scroll(function() {
    if($(window).scrollTop() + $(window).height() == getDocHeight()) {
        setScrollFollow("follow")
    } else {
        if (window.scrollFollow == "follow") {
            setScrollFollow("nofollow")
        }
    }
});

// if user clicks follow-indicator, start the scroll follow user lockout
$( "#follow-indicator" ).click(function() {
    setScrollFollow("userlockout")
});

// TODO: Make pause stop the backend from sending any new log messages
// if user clicks pause-button, update scrolling
$( "#pause-button" ).click(function() {
    updatePause()
});

<|endoftext|>


<commit_before>/*
 * xslt.js
 *
 * Copyright (c) 2005-2007 Johann Burkard (<mailto:jb@eaio.com>)
 * <http://eaio.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

var pickRecentProgID = function (idList){
	// found progID flag
    var bFound = false;
    for(var i=0; i < idList.length && !bFound; i++){
        try{
            var oDoc = new ActiveXObject(idList[i]);
            o2Store = idList[i];
            bFound = true;
        }catch (objException){
            // trap; try next progID
        };
    };
    if (!bFound)
		throw ("Aucun ActiveXObject n'est valide sur votre ordinateur, pensez ï¿½ mettre ï¿½ jour votre navigateur");
    idList = null;
    return o2Store;
}

// Retourne un nouvel objet XmlHttpRequest
var GetXmlHttpRequest_AXO = null;

var GetXmlHttpRequest=function () {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest()
	} else if (window.ActiveXObject) {
		if (!GetXmlHttpRequest_AXO) {
			GetXmlHttpRequest_AXO = pickRecentProgID(["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
		}
		return new ActiveXObject(GetXmlHttpRequest_AXO)
	}
	return false;
}

/**
 * Properties of this library.
 *
 * @type String
 * @final
 */
var xslt_js = {
    /**
     * The version of this library
     *
     * @type String
     * @final
     */
    revision: 'xslt.js $Revision: 1.5 $'
};

/**
 * Constructor for client-side XSLT transformations.
 *
 * @author Johann Burkard
 * @version $Id$
 * @constructor
 */

function loadXML(url) {
    var xmlDoc;
    /* chargement du fichier XML */
    try {
      // navigateur basï¿½ sur Gecko
      if (document.implementation && document.implementation.createDocument) {
        xmlDoc = document.implementation.createDocument('', '', null);
        xmlDoc.load(url);
      } else if (window.ActiveXObject) {
	    // ActiveX pour Internet Explorer
        try {
          xmlDoc = new ActiveXObject('Msxml2.XMLDOM');
        } catch (e) {
          xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
        }
        xmlDoc.async = false;
        xmlDoc.load(url);
      } else if (window.XMLHttpRequest) {
		// ï¿½ l'aide de lobjet XMLHTTPRequest
      	xmlDoc = new XMLHttpRequest();
		xmlDoc.overrideMimeType('text/xml');
		xmlDoc.open('GET', url, false);
		xmlDoc.send(null);
		if (this.xmlDoc.readyState == 4)
        	xmlDoc = xmlDoc.responseXML;
		}
	} catch (e) {
		return e;
	}
	return xmlDoc;
}

function Transformation() {
    var xml;
    var xmlDoc;
    var xslt;
    var xsltDoc;
    var targetElem;

    var callback = function() {};

    /*
     * Sort of like a fix for Opera who doesn't always get readyStates right.
     */
    var transformed = false;

    /*
     * Returns the URL of the XML document.
     *
     * @return the URL of the XML document
     * @type String
     */
    this.getXml = function() {
        return xml;
    }

    /**
     * Returns the XML document.
     *
     * @return the XML document
     */
    this.getXmlDocument = function() {
        return xmlDoc;
    }

    /**
     * Sets the URL of the XML document.
     *
     * @param x the URL of the XML document
     * @return this
     * @type Transformation
     */
    this.setXml = function(x) {
        xml = x;
        return this;
    }

    /**
     * Returns the URL of the XSLT document.
     *
     * @return the URL of the XSLT document
     * @type String
     */
    this.getXslt = function() {
        return xslt;
    }

    /**
     * Returns the XSLT document.
     *
     * @return the XSLT document
     */
    this.getXsltDocument = function() {
        return xsltDoc;
    }

    /**
     * Sets the URL of the XSLT document.
     *
     * @param x the URL of the XML document
     * @return this
     * @type Transformation
     */
    this.setXslt = function(x) {
        xslt = x;
        return this;
    }

    /**
     * Returns the callback function.
     *
     * @return the callback function
     */
    this.getCallback = function() {
        return callback;
    }

    /**
     * Sets the callback function
     *
     * @param c the callback function
     * @return this
     * @type Transformation
     */
    this.setCallback = function(c) {
        callback = c;
        return this;
    }

	/**
     * Returns the target Element.
     *
     * @return the target Element
     */
    this.getTargetElement = function() {
        return targetElem;
    }

	/**
	 * Sets the target element to write the transformed content to and asynchronously
	 * starts the transformation process.
	 *

	 * target can be a Node or the ID of an element. 2DO
	 *

	 * This method may only be called after {@link #setXml} and {@link #setXslt} have
	 * been called.
	 *

	 * Note that the target element must exist once this method is called. Calling
	 * this method before onload was fired will most likely
	 * not work.
	 *
	 * @param target the Node or the ID of an element
	 *           if (typeof document.all[xmlID] != u && document.all[xmlID].readyState == c &&
	 *           typeof document.all[xsltID] != u && document.all[xsltID].readyState == c) {
	 *
	 *
	 */

    this.transform = function(target) {
        targetElem = target;
        var t = this;

        if (!browserSupportsXSLT()) {
           return;
        }

        if (!document.getElementById("centreonMsg_img")) {
             if (typeof _setAlign == 'function') {
                 _setAlign("centreonMsg", "center");
                 _setTextStyle("centreonMsg", "bold");
                 _setImage("centreonMsg", "./img/misc/ajax-loader.gif");
                 _setText("centreonMsg", " Loading...");
                 _setValign("centreonMsg", "bottom");
             }
        }

        var change = function() {
            if (
                xmlRequest.readyState == 4
                && xmlRequest.responseXML
                && xsltRequest.status == 200
                && xsltRequest.readyState == 4
                && xsltRequest.responseText
            ) {
                if (transformed) {
                    return;
                }
                xsltDoc = xsltRequest.responseXML;
                xmlDoc = xmlRequest.responseXML;
                var targetNode = document.getElementById(target);
                if (window.ActiveXObject || document.hasOwnProperty.call(window, "ActiveXObject")) {
                    document.getElementById(target).innerHTML = xmlDoc.transformNode(xsltDoc);
                } else {
                    var resultDoc;
                    var processor = new XSLTProcessor();
                    if (targetNode) {
                        // remove child nodes from DOM
                        while (targetNode.firstChild) {
                            targetNode.removeChild(targetNode.firstChild);
                        }
                        targetNode.innerHTML = '';
                    }
                    processor.importStylesheet(xsltDoc);
                    resultDoc = processor.transformToFragment(xmlDoc, document);
                    targetNode.appendChild(resultDoc);
                    resultDoc = null;
                    processor = null;
                }
                if (callback) {
                    callback(t);
                    callback = null;
                }

                targetNode = null;
                target = null;

                transformed = true;
                if (typeof _clear == 'function') {
                    _clear("centreonMsg");
                }

                xsltRequest.onreadystatechange = null;
                xsltRequest = null;
                xmlRequest.onreadystatechange = null;
                xmlRequest = null;
                xsltDoc = null;
                xmlDoc = null;
            }
        }

        if(xsltRequest != null){
            xsltRequest.onreadystatechange = new Function;
            xsltRequest = null;
            delete xsltRequest;
        }

        if(xmlRequest != null){
            xmlRequest.onreadystatechange = new Function;
            xmlRequest = null;
            delete xmlRequest;
        }

        var xmlRequest;
        var xsltRequest;
        if (window.ActiveXObject || document.hasOwnProperty.call(window, "ActiveXObject")) {
        xmlRequest = new ActiveXObject("Msxml2.XMLHTTP.6.0");
        xsltRequest = new ActiveXObject("Msxml2.XMLHTTP.6.0");
        } else {
            xmlRequest = GetXmlHttpRequest();
            xsltRequest = GetXmlHttpRequest();
        }
        xmlRequest.open("GET", xml, true);
        xmlRequest.onreadystatechange = change;
        xmlRequest.send(null);
        if (xsltRequest.readyState != 4) {
            xsltRequest.open("GET", xslt);
            xsltRequest.onreadystatechange = change;
            xsltRequest.send(null);
        }
    }

	/**
	 * Generates a random ID.
	 *
	 * @return a random ID
	 */
	function randomID() {
	    var out = 'id' + Math.round(Math.random() * 100000);
	    return out;
	}

}

/**
 * Returns whether the browser supports XSLT.
 *
 * @return the browser supports XSLT
 * @type boolean
 */

function browserSupportsXSLT() {
    var support = false;
    if (window.ActiveXObject !== 'undefined') { // IE 6+
        support = true;
    }
    var u = 'undefined';
    if (typeof XMLHttpRequest != u && typeof XSLTProcessor != u) { // Mozilla 0.9.4+, Opera 9+
       var processor = new XSLTProcessor();
       if (typeof processor.transformDocument == 'function') {
           support = typeof XMLSerializer != u;
       } else {
           support = true;
       }
    }
    return support;
}
<commit_msg>fix(chore): non UTF-8 chars breaking sonarQ analysis (#9606)<commit_after>/*
 * xslt.js
 *
 * Copyright (c) 2005-2007 Johann Burkard (<mailto:jb@eaio.com>)
 * <http://eaio.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

var pickRecentProgID = function (idList){
	// found progID flag
    var bFound = false;
    for(var i=0; i < idList.length && !bFound; i++){
        try{
            var oDoc = new ActiveXObject(idList[i]);
            o2Store = idList[i];
            bFound = true;
        }catch (objException){
            // trap; try next progID
        };
    };
    if (!bFound)
		throw ("Aucun ActiveXObject n'est valide sur votre ordinateur, pensez ï¿½ mettre ï¿½ jour votre navigateur");
    idList = null;
    return o2Store;
}

// Retourne un nouvel objet XmlHttpRequest
var GetXmlHttpRequest_AXO = null;

var GetXmlHttpRequest=function () {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest()
	} else if (window.ActiveXObject) {
		if (!GetXmlHttpRequest_AXO) {
			GetXmlHttpRequest_AXO = pickRecentProgID(["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
		}
		return new ActiveXObject(GetXmlHttpRequest_AXO)
	}
	return false;
}

/**
 * Properties of this library.
 *
 * @type String
 * @final
 */
var xslt_js = {
    /**
     * The version of this library
     *
     * @type String
     * @final
     */
    revision: 'xslt.js $Revision: 1.5 $'
};

/**
 * Constructor for client-side XSLT transformations.
 *
 * @author Johann Burkard
 * @version $Id$
 * @constructor
 */

function loadXML(url) {
    var xmlDoc;
    /* chargement du fichier XML */
    try {
      // navigateur basï¿½ sur Gecko
      if (document.implementation && document.implementation.createDocument) {
        xmlDoc = document.implementation.createDocument('', '', null);
        xmlDoc.load(url);
      } else if (window.ActiveXObject) {
	    // ActiveX pour Internet Explorer
        try {
          xmlDoc = new ActiveXObject('Msxml2.XMLDOM');
        } catch (e) {
          xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
        }
        xmlDoc.async = false;
        xmlDoc.load(url);
      } else if (window.XMLHttpRequest) {
      	xmlDoc = new XMLHttpRequest();
		xmlDoc.overrideMimeType('text/xml');
		xmlDoc.open('GET', url, false);
		xmlDoc.send(null);
		if (this.xmlDoc.readyState == 4)
        	xmlDoc = xmlDoc.responseXML;
		}
	} catch (e) {
		return e;
	}
	return xmlDoc;
}

function Transformation() {
    var xml;
    var xmlDoc;
    var xslt;
    var xsltDoc;
    var targetElem;

    var callback = function() {};

    /*
     * Sort of like a fix for Opera who doesn't always get readyStates right.
     */
    var transformed = false;

    /*
     * Returns the URL of the XML document.
     *
     * @return the URL of the XML document
     * @type String
     */
    this.getXml = function() {
        return xml;
    }

    /**
     * Returns the XML document.
     *
     * @return the XML document
     */
    this.getXmlDocument = function() {
        return xmlDoc;
    }

    /**
     * Sets the URL of the XML document.
     *
     * @param x the URL of the XML document
     * @return this
     * @type Transformation
     */
    this.setXml = function(x) {
        xml = x;
        return this;
    }

    /**
     * Returns the URL of the XSLT document.
     *
     * @return the URL of the XSLT document
     * @type String
     */
    this.getXslt = function() {
        return xslt;
    }

    /**
     * Returns the XSLT document.
     *
     * @return the XSLT document
     */
    this.getXsltDocument = function() {
        return xsltDoc;
    }

    /**
     * Sets the URL of the XSLT document.
     *
     * @param x the URL of the XML document
     * @return this
     * @type Transformation
     */
    this.setXslt = function(x) {
        xslt = x;
        return this;
    }

    /**
     * Returns the callback function.
     *
     * @return the callback function
     */
    this.getCallback = function() {
        return callback;
    }

    /**
     * Sets the callback function
     *
     * @param c the callback function
     * @return this
     * @type Transformation
     */
    this.setCallback = function(c) {
        callback = c;
        return this;
    }

	/**
     * Returns the target Element.
     *
     * @return the target Element
     */
    this.getTargetElement = function() {
        return targetElem;
    }

	/**
	 * Sets the target element to write the transformed content to and asynchronously
	 * starts the transformation process.
	 *

	 * target can be a Node or the ID of an element. 2DO
	 *

	 * This method may only be called after {@link #setXml} and {@link #setXslt} have
	 * been called.
	 *

	 * Note that the target element must exist once this method is called. Calling
	 * this method before onload was fired will most likely
	 * not work.
	 *
	 * @param target the Node or the ID of an element
	 *           if (typeof document.all[xmlID] != u && document.all[xmlID].readyState == c &&
	 *           typeof document.all[xsltID] != u && document.all[xsltID].readyState == c) {
	 *
	 *
	 */

    this.transform = function(target) {
        targetElem = target;
        var t = this;

        if (!browserSupportsXSLT()) {
           return;
        }

        if (!document.getElementById("centreonMsg_img")) {
             if (typeof _setAlign == 'function') {
                 _setAlign("centreonMsg", "center");
                 _setTextStyle("centreonMsg", "bold");
                 _setImage("centreonMsg", "./img/misc/ajax-loader.gif");
                 _setText("centreonMsg", " Loading...");
                 _setValign("centreonMsg", "bottom");
             }
        }

        var change = function() {
            if (
                xmlRequest.readyState == 4
                && xmlRequest.responseXML
                && xsltRequest.status == 200
                && xsltRequest.readyState == 4
                && xsltRequest.responseText
            ) {
                if (transformed) {
                    return;
                }
                xsltDoc = xsltRequest.responseXML;
                xmlDoc = xmlRequest.responseXML;
                var targetNode = document.getElementById(target);
                if (window.ActiveXObject || document.hasOwnProperty.call(window, "ActiveXObject")) {
                    document.getElementById(target).innerHTML = xmlDoc.transformNode(xsltDoc);
                } else {
                    var resultDoc;
                    var processor = new XSLTProcessor();
                    if (targetNode) {
                        // remove child nodes from DOM
                        while (targetNode.firstChild) {
                            targetNode.removeChild(targetNode.firstChild);
                        }
                        targetNode.innerHTML = '';
                    }
                    processor.importStylesheet(xsltDoc);
                    resultDoc = processor.transformToFragment(xmlDoc, document);
                    targetNode.appendChild(resultDoc);
                    resultDoc = null;
                    processor = null;
                }
                if (callback) {
                    callback(t);
                    callback = null;
                }

                targetNode = null;
                target = null;

                transformed = true;
                if (typeof _clear == 'function') {
                    _clear("centreonMsg");
                }

                xsltRequest.onreadystatechange = null;
                xsltRequest = null;
                xmlRequest.onreadystatechange = null;
                xmlRequest = null;
                xsltDoc = null;
                xmlDoc = null;
            }
        }

        if(xsltRequest != null){
            xsltRequest.onreadystatechange = new Function;
            xsltRequest = null;
            delete xsltRequest;
        }

        if(xmlRequest != null){
            xmlRequest.onreadystatechange = new Function;
            xmlRequest = null;
            delete xmlRequest;
        }

        var xmlRequest;
        var xsltRequest;
        if (window.ActiveXObject || document.hasOwnProperty.call(window, "ActiveXObject")) {
        xmlRequest = new ActiveXObject("Msxml2.XMLHTTP.6.0");
        xsltRequest = new ActiveXObject("Msxml2.XMLHTTP.6.0");
        } else {
            xmlRequest = GetXmlHttpRequest();
            xsltRequest = GetXmlHttpRequest();
        }
        xmlRequest.open("GET", xml, true);
        xmlRequest.onreadystatechange = change;
        xmlRequest.send(null);
        if (xsltRequest.readyState != 4) {
            xsltRequest.open("GET", xslt);
            xsltRequest.onreadystatechange = change;
            xsltRequest.send(null);
        }
    }

	/**
	 * Generates a random ID.
	 *
	 * @return a random ID
	 */
	function randomID() {
	    var out = 'id' + Math.round(Math.random() * 100000);
	    return out;
	}

}

/**
 * Returns whether the browser supports XSLT.
 *
 * @return the browser supports XSLT
 * @type boolean
 */

function browserSupportsXSLT() {
    var support = false;
    if (window.ActiveXObject !== 'undefined') { // IE 6+
        support = true;
    }
    var u = 'undefined';
    if (typeof XMLHttpRequest != u && typeof XSLTProcessor != u) { // Mozilla 0.9.4+, Opera 9+
       var processor = new XSLTProcessor();
       if (typeof processor.transformDocument == 'function') {
           support = typeof XMLSerializer != u;
       } else {
           support = true;
       }
    }
    return support;
}
<|endoftext|>