Sindbad~EG File Manager

Current Path : /home/beeson/public_html/WebMathXpert/
Upload File :
Current File : //home/beeson/public_html/WebMathXpert/SymbolicDoc.php

<?php
// Set HTTP header to prevent caching
header('Content-Type: text/html; chars=UTF-8');
header("Cache-Control: no-cache, must-revalidate");

// Start or resume the session
session_start();
$sessionId = session_id();  // guaranteed not to contain a pipe character
ini_set('display_errors', 1);
error_reporting(E_ALL);
if ($_SERVER['SERVER_NAME'] == 'localhost') {
    $nextpagegraph = "https://localhost:8443/GraphDoc.php"; 
    $serverAddress = 'localhost';  
    $username = $password = null;
} else {
    $nextpagegraph = "https://mathxpert.org/GraphDoc.php"; 
    $serverAddress = 'mathxpert.org';  
    $username = 'beeson'; 
    $password = 'Turing2024';
}
$serverPort = 12349; // Adjust the server port. Ending in 9 for the Engine; in 7 for Polygon
$timeout = 3600; // Connection timeout in seconds. If the server does not respond by then, close the socket.
$startupDelay = 5; // Delay for server startup in seconds if the server is not already running

if (!(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) {
    $redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    header('HTTP/1.1 301 Moved Permanently');
    header('Location: ' . $redirect);
    exit();
}

if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["language"])) 
	$language = $_POST["language"]; 

require("SendMessage.php");
$clientSocket = createClientSocket($serverAddress, $serverPort, $timeout);

// Handle any Ajax requests before emitting any HTML 
if ($_SERVER['REQUEST_METHOD'] === 'POST') { 
    if (isset($_POST['suppliedArgText'])) {
        $inputText = $_POST['suppliedArgText'];
        $needsArgCondition = $_POST['needsArgCondition'];
        // Process the AJAX request
        $param = $needsArgCondition . "+" . $inputText; 
        $response = sendMessage($clientSocket, "checkArg", $param); 
    } else if (isset($_POST['windowWidth']) && isset($_POST['windowHeight'])) {
        $windowWidth = $_POST['windowWidth'];
        $windowHeight = $_POST['windowHeight'];
        $reasonstart = $_POST['reasonstart'];
        $param = $windowWidth . "+" . $windowHeight . "+" . $reasonstart;
        $response = sendMessage($clientSocket, "symbolWindowResized", $param);
    } else {
        $response = "nothing";
    }

    if ($response === false) {
        $errcode = socket_last_error($socket);
        $message = socket_strerror($errcode);
        echo "Socket_read error: $message<br>";
    } else if ($response != "nothing") {
        echo($response);  // for debugging
        exit; // Stop further processing, so the rest of the HTML isn't sent
    }
}

// Normal page loading code continues below

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=0"> 
	 
    <title>MathXpert Symbolic Calculator</title>
    <style>
        /* Set a global font-family rule for all text elements. Only Times New Roman actually works well. */
		  text {
		      font-family: 'Times New Roman';
		  }

		  svg text {
		      font-family: 'Times New Roman';
		  }

		  /* Ensure Arial for text inside elements with the class svg-button */
		  .svg-button text, .svg-button svg text {
		      font-family: 'Arial';
		  }
      
        .hidden {
            visibility: hidden;
            position: absolute;
        }
        #svgContainer {
            position: relative;
				user-select: none; /* Prevent text and element selection */
				flex-grow:1;
				overflow-x: auto;  /* Enables horizontal scrolling */
				overflow-y: auto;  /* Enables vertical scrolling */
        }
        #selectionRectangle {
            position: absolute;
            border: 1px solid red;
            pointer-events: none; /* Ignore this element during mouse events */
        }
		  body {
		      margin: 0;
		      padding: 0;
		      height: 100vh; /* Fills entire viewport */
		      overflow: hidden; /* Prevents body from scrolling */
		      display: flex;
		      flex-direction: column; /* Ensures divs stack vertically */
		      background-color: CornSilk;
		      user-select: none;
		  }
        .button-container {
            display: flex;
            gap: 3px; /* the gap before and after the form containing seven buttons, not the gap between the buttons */
				width: 100%;
				z-index: 10; 
        }
        .button-container button {
            height: 36px; /* Adjust the height as needed */
        }
		  .button-container form {
		      display: flex;
		      gap: 3px; /* This is the gap between the buttons */ 
		  }
		  .button-container form:first-of-type {
		      margin-right: -4px; /* Reduce the 6px gap to 2px between the two forms */
		  }
		  .selectmenuitem{ 
		  pointer-events:all;
		  }
        .selectMenuItemWrapper {
            display: inline-block;
            cursor: pointer;
            position: relative; 
            pointer-events:hover;
        }
        .selectMenuItemWrapper:hover {
            background-color: rgb(200,200,255);
        }
		  .hovering {
		      background-color: rgb(200, 200, 255); /* same color as for hover, but this works on iPhone and iPad */
		  }
        .highlighted {
            background-color: rgb(200,255,200); 
        }
		  .modal {
		      display: none; /* Hidden by default */
		      position: fixed; /* Stay in place */
		      z-index: 1000; /* Sit on top */
		      left: 0;
		      top: 0;
		      width: 100%; /* Full width */
		      height: 100%; /* Full height */
		      background-color: lightblue
		  }
		  .modal-content {
		      background-color: lightblue;
		      margin: 15% auto;
		      padding: 20px;
		      border: 1px solid #888;
		      width: 60%; /* Could be more/less, depending on screen size */
		      text-align: left;
		  }

		  .progress {
		      margin: 10px 0;
		      text-align: center;
		  }

		  .modal-close {
		      float: right;
		      font-size: 24px;
		      font-weight: bold;
		      cursor: pointer;
		  }
		  
        #hintModal,#assumptionsModal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0);
            justify-content: center;
            align-items: center;
        }
        #modalContent {
            background: rgb(200,200,255);
            padding: 20px;
            border-radius: 5px;
            width: 50%;
            height: 30%;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
        }
        #hintModalContent,#assumptionsModalContent {
            background: rgb(200,200,255);
            padding: 20px;
            border-radius: 5px;
            width: 50%;
            height: 30%;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
        }
        #selectionMenu {
            box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
            width: 100px;
            z-index: 1;
        }
 	    .selectHint {
 	        position: absolute;
 	        top: 50px;
 	        left: 150px;
 	        padding: 5px 10px;
 	        background-color: rgba(255, 255, 255, 0.8);
 	        border: 1px solid #ccc;
 	        border-radius: 4px;
 	        font-size: 14px;
 	        color: #333;
 	        opacity:1;
 	        transition: opacity 0.5s ease;
 	    }
 	</style>
   <script>
      let cheerAudio = new Audio('cheer.mp3');

		function playCheerSound() {
		    // Create the popup
		    const popup = document.createElement("div");
		    popup.style.position = "absolute";
		    popup.style.top = "50px";
		    popup.style.left = "50px";
		    popup.style.padding = "20px";
		    popup.style.border = "1px solid black";
		    popup.style.borderRadius = "8px";
		    popup.style.backgroundColor = "rgb(220,220,255)"; // White background for the popup
		    popup.style.color = "black";
		    popup.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.2)";
		    popup.style.zIndex = "1000";
		    popup.style.fontFamily = "Arial, sans-serif";
		    popup.style.minWidth = "300px"; 
		    popup.style.textAlign = "center";

		    // Add the close button (X)
		    const closeButton = document.createElement("span");
		    closeButton.textContent = "×";
		    closeButton.style.position = "absolute";
		    closeButton.style.top = "10px";
		    closeButton.style.right = "10px";
		    closeButton.style.cursor = "pointer";
		    closeButton.style.fontSize = "20px";
		    closeButton.style.color = "black";
			 // Close button click handler
			 closeButton.addEventListener("click", function (e) {
			     e.stopPropagation(); // Prevent triggering other event listeners
			     document.body.removeChild(popup); // Remove the popup
			 });

		    // the first message
		    const message = document.createElement("p");
		    message.id = "cheerMessage"; // Assign an ID for translation
		    message.textContent = "You have earned applause. Click Play to hear it."; 
		    message.style.marginBottom = "20px";
		    message.style.fontSize = "16px";

		    // the Play button
		    const playButton = document.createElement("button");
		    playButton.textContent = "Play"; 
		    playButton.id = "playButton";
		    playButton.style.padding = "10px 20px";
		    playButton.style.backgroundColor = "rgb(0, 0, 128)"; // Blue background for the button
		    playButton.style.color = "white";
		    playButton.style.border = "none";
		    playButton.style.borderRadius = "5px";
		    playButton.style.cursor = "pointer"; 
		    playButton.style.margin = "0 auto";
			 // Play button click handler
			playButton.addEventListener("click", function (event) {  
				console.log("clicked on ",event.target);
				if(event.target !== playButton) 
					return; 
				cheerAudio.play().catch(error => {
				console.error("Error playing sound:", error);
				});
				document.body.removeChild(popup); // Remove the popup after playing
			 }); 
			 
 		    // the second message
 		    const message2 = document.createElement("p");
 		    message2.id = "cheerMessage2"; // Assign an ID for translation
 		    message2.textContent = "You took more than half the steps without assistance.";
 		    message2.style.marginBottom = "20px";
 		    message2.style.fontSize = "16px";
			 

		    // Append elements to the popup
		    popup.appendChild(closeButton);
		    popup.appendChild(message);
		    popup.appendChild(playButton); 
		    popup.appendChild(message2);
		    

		    // Add the popup to the document
		    document.body.appendChild(popup);
		}
    </script>
</head>
<body>
<script>
// Following is for iPhone and iPad, where there is no "hover", 
// so we simulate hovering this way.

document.querySelectorAll('.selectMenuItemWrapper').forEach(item => {
    item.addEventListener('touchstart', () => {
        item.classList.add('hovering'); // Simulate the hover effect
    });
    item.addEventListener('touchend', () => {
        item.classList.remove('hovering');
    });
});
</script>
<script src="DocumentID.js"></script> 
<script src="ToolbarWidth.js"></script>
<script src="TranslateEnterPages.js"></script>
<?php
ob_start();
include 'toolbar.php';
$toolbarContent = ob_get_clean();
?>
<div id="tooltip-container" class="tooltip"></div>
<div id="hiddenToolbar" class="hidden">
    <?php echo $toolbarContent; ?>
</div>
<div style="display:none;">
	<?php include 'ButtonDefinitions.svg'; ?>
</div>
<style>
.svg-button {
    border: none;
    background: none;
    padding: 0 !important; 
    background-color: transparent;  /* This is ignored even with !important */
    cursor: pointer;
    flex: 1 1 32px; 
}
.video-icon {
    background-color: white; /* Adjust to a contrasting color */
    font-size: 1.2em; /* Slightly larger for better visibility */
}
.video-button {
    background-color: rgb(0,0,128); /* dark blue background */
    color: white; /* White text color */
    border: none; /* No border */
    padding: 5px 10px; /* Padding around the button */
    cursor: pointer; /* Pointer cursor on hover */
    border-radius: 4px; /* Rounded corners */
    font-size: 14px; /* Text size */
    display: inline-flex; /* Inline-flex to align icon and text */
    align-items: center; /* Align icon and text vertically */
    gap: 5px; /* Space between the icon and the text */
    text-align: center; /* Center text alignment */
}

.video-button:hover {
    background-color: rgb(0, 0, 180); /* Slightly lighter blue on hover */
}
/* Tooltips  */  
.tooltip {
	position: absolute;  /* so it will serve as origin for svg text it contains */
	background-color: lightblue;
	color: black;
	padding: 5px;  
	margin-top: 3px;
	border-radius: 3px;
	white-space: nowrap;
	z-index: 1000;
	display: none; /* Hide by default */ 
	font-size: 12px; 
	font-family: Arial, sans-serif; 
}

.tooltip::before {
    content: '';
    position: absolute;
    top: -8px; /* Adjust based on the size of the triangle */
    left: 0px; /* Adjust based on desired position */
    border-width: 0 5px 10px 0px; /* Create a triangle pointing up */
    border-style: solid;
    border-color: transparent transparent lightblue transparent; /* Only the bottom part is visible */
}
	.hidden {
				visibility: hidden;
				position: absolute;
				}
</style>

<!-- promptModal is used by any dialog.  The prompt for the dialog should be dynamically inserted.
	  Until needed this div has display: none -->
<div id="promptModal" style="display: none; position: fixed; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5);">
    <div id="modalContent" style="background: white; margin: 15% auto; padding: 20px; width: 50%;">
        <!-- SVG will be inserted here -->
		<button id="submitResponse">Submit</button>
    </div>
</div>
<style>
/* General styles for the select box */
#languageSelector,#typesize {
    font-size: 12px;
    padding: 5px;
    border-radius: 5px;
    background-color: white;
    border: 1px solid #ccc;
    background-repeat: no-repeat;
    background-position: left center;
}


</style>
<!-- arrowhead definition needed for the undo button, it doesn't get included automatically -->
<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
	<defs>
		<marker id="arrowhead" markerWidth="6" markerHeight="6" refX="1" refY="3" orient="auto">
		<polygon points="0 0, 6 3, 0 6" fill="white" />
		</marker>
	</defs>
	<defs>
		<marker id="arrowhead2" markerWidth="4" markerHeight="4" refX="2" refY="2" orient="auto">
			<polygon points="0 0, 4 2, 0 4" fill="white" />
		</marker>
	</defs>
</svg>
	
<div class="button-container" style="display: flex; flex-direction:row; align-items: top;">
	<!-- Wrapper for select elements to stack them vertically -->
	<div style="display: flex; flex-direction: column; margin-right: 0px;">
		<select id="typesize">
			<option value="1" class="selector-item" id="changeTypeSize">Type Size</option>
			<option value="2" class="selector-item" id="normalSize">Normal</option>
			<option value="3" class="selector-item" id="largerSize">Larger</option>
			<option value="4" class="selector-item" id="smallerSize">Smaller</option>
		</select>
		<select id="languageSelector" onchange="setSelectedLanguage(this.value)">
			<option value="english">🇬🇧 English</option>
			<option value="german">🇩🇪 Deutsch</option>
			<option value="french">🇫🇷 Français</option>
			<option value="spanish">🇪🇸 Español</option>
			<option value="italian">🇮🇹 Italiano</option>
			<option value="dutch">🇳🇱 Nederlands</option>
			<option value="chinese">🇨🇳 中文</option>
		</select>
	</div>
	<!-- Other elements remain in the horizontal flow -->
	<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" >
		<button type="button" name="assumptions" id="assumptionsButton" class="svg-button" onclick="showAssumptions()"> 
			<svg width="66" height="36"><use href="#assumptionsButtonRef"></use></svg>
		</button>
		<button type="submit" name="autoStep" value="autostep" id="autoStepButton" class="svg-button"> <svg width="66" height="36"><use href="#autoStepButtonRef"></use></svg></button>
		<button type="submit" name="autoFinish" value="autofinish" id="autoFinishButton" class="svg-button"> <svg width="66" height="36"><use href="#autoFinishButtonRef"></use></svg></button>
		<button type="submit" name="showStep" value="showstep" id="showStepButton" class="svg-button"> <svg width="66" height="36"><use href="#showStepButtonRef"></use></svg></button>
		<button type="submit" name="undo" value="undo" id="undoButton" class="svg-button"> <svg width="66" height="36"><use href="#undoButtonRef"></use></svg></button>
		<button type="submit" name="hint" value="hint" id="hintButton" class="svg-button"> <svg width="66" height="36"><use href="#hintButtonRef"></use></svg></button>
		<button type="submit" name="finished" value="finished" id="finishedButton" class="svg-button"> <svg width="66" height="36"><use href="#finishedButtonRef"></use></svg></button>			
	</form>
	<form method="post" action="<?php echo htmlspecialchars($nextpagegraph); ?>" target="_blank" id="graphForm">
	    <button type="submit" name="graphButton" value="graphButton" id="graphButton" class="svg-button">
	        <svg width="66" height="36"><use href="#graphButtonRef"></use></svg>
	    </button>
	   <!-- Shortcut Button (Link Styled as a Button) -->
	     <a href="https://www.mathxpert.org" id="shortcutButton" class="svg-button" target="_blank">
	         <img src="./images/MathXpertLink.png" width="66" height="36" alt="MathXpert">
	     </a>
	   <input type="hidden" name="widthField2" id="widthField2" value="0">
	   <input type="hidden" name="heightField2" id="heightField2" value="0">
	   <input type="hidden" name="toolbarwidthField" id="toolbarwidthField" value="0">
	   <input type="hidden" name="language" id="language" value='<?php echo($language); ?>' > 
	   <input type="hidden" name="PHPSESSID" id="PHPSESSID" value='<?php echo session_id(); ?>' > 
	</form>
</div>

<script>
	// Function to update width and height inputs and submit form
	function updateDimensionsAndSubmit() {
		// Get width and height of the window in CSS pixels
		var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
		var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; 
		const toolbarwidth = getToolbarWidth();  
		
		// Set values to the hidden inputs
		hiddenToolbar.value = toolbarwidth;
		document.getElementById('widthField2').value = width-toolbarwidth; 
		document.getElementById('heightField2').value = height;  
		document.getElementById('toolbarwidthField').value = toolbarwidth;

		// Submit the form
		document.getElementById('graphForm').submit();
	}

	// Attach the function to the submit event
	document.getElementById('graphForm').addEventListener('submit', function(event) {
		// Prevent the form from submitting immediately
		event.preventDefault();

		// Update dimensions and submit the form
		updateDimensionsAndSubmit();
	 });
    
// Function to set the height of the svgContainer to the scrollHeight of the window, 
// and also the height and width of the element of class "highlight" that contains the selected rectangle
	function setSvgContainerHeight() {
		const svgContainer = document.getElementById('svgContainer');
		   // Get the scroll height of the svgContainer (which is at least the total height of its contents)
		const containerScrollHeight = svgContainer.scrollHeight-5;
		const containerScrollWidth = svgContainer.scrollWidth;
		const highlightSvg = document.querySelector('svg.highlight'); 
		if (highlightSvg) {
			// Set the height using both attribute and style
			highlightSvg.setAttribute("height", containerScrollHeight);
			highlightSvg.style.height = containerScrollHeight + "px"; // Adding 'px' to specify the unit 
			highlightSvg.setAttribute("width", containerScrollWidth);
			highlightSvg.style.width = containerScrollWidth + "px"; // Adding 'px' to specify the unit
		} 
		// console.log("scrolling", svgContainer.style.height, svgContainer.scrollTop, containerScrollHeight);
		// Scroll the container to the bottom to ensure new content is visible 
		svgContainer.scrollTop =  containerScrollHeight; 
		// console.log("scrolling2", svgContainer.style.height, svgContainer.scrollTop, containerScrollHeight);		
	}

	// Set the height on page load
	window.addEventListener('load', setSvgContainerHeight);

	// Update the height if the window is resized
	window.addEventListener('resize', setSvgContainerHeight);
	
</script>
<script src="displayProgress.js"></script>
<script>
       // This function is not actually used, since resizing is handled locally and the Engine
       //  is just notified of the change by an Ajax message.  But if this form is used, the
       //  Engine can handle resizing, which will be needed if in the future line breaks are implemented.
       //  It does, however, inevitably create flicker
        function submitResizeForm(width, height) {
            // Create a form element
            const form = document.createElement('form');
            form.method = 'POST';
            form.action = '<?php echo $_SERVER["PHP_SELF"]; ?>';

            // Create hidden input elements for width and height
            const widthInput = document.createElement('input');
            widthInput.type = 'hidden';
            widthInput.name = 'windowWidth';
            widthInput.value = width;

            const heightInput = document.createElement('input');
            heightInput.type = 'hidden';
            heightInput.name = 'windowHeight';
            heightInput.value = height;

            // Append inputs to the form
            form.appendChild(widthInput);
            form.appendChild(heightInput);

            // Append form to the body
            document.body.appendChild(form);

            // Submit the form
            form.submit();
        }
	   window.addEventListener('resize', function() {
			const width = window.innerWidth;
			const height = window.innerHeight;
			let reasonstart = 0.7 * width;  //  keep this in sync with the original setting			
	        // Select all elements with the class 'reason'
			const reasons = document.querySelectorAll('.reason');
	 	   // Update the .left attribute of each reason element
			reasons.forEach(reason => {
			reason.style.left = reasonstart + 'px';
			});
		   // send Ajax message notifying the Engine
		    var xhr = new XMLHttpRequest();
		    xhr.open("POST", "<?php echo ($_SERVER['PHP_SELF']); ?>", true);
		    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			const data = `windowWidth=${encodeURIComponent(width)}&windowHeight=${encodeURIComponent(height)}&reasonstart=${encodeURIComponent(reasonstart)}`;
			console.log('Data being sent:', data);
			xhr.send(data);
		});
    </script>



<?php
    if ($_SERVER["REQUEST_METHOD"] === "POST") 
    {   if (isset($_POST['autoProblemField']))
		{
			$problemnumber = $_POST["autoProblemField"];
			$topicnumber =  $_POST["autoTopicField"];
			$sender = "autoTest";
			$language = $_POST["language"];
			$width = $_POST["width"];
			$_SESSION['languagenumber'] = $language;
		}
		if (isset($_POST['problemnumberField']))
		{
			$problemnumber = $_POST["problemnumberField"];
			$topicnumber =  $_POST["topicField"];
			$sender = "GetProblem";
			$language = $_POST["language"];
			$width = $_POST["widthField"];
			$height = $_POST["heightField"];
			$_SESSION['languagenumber'] = $language; 
			$windowWidth = $_SESSION['width'] = intval($_POST["widthField"]);  // width of the browser window 
			$toolbarwidth = $_SESSION['toolbarwidth'] = intval($_POST["toolbarwidthField"]); 
		}  
		if (isset($_POST["widthField3"]))  // from EnterLinearEquations.php or other EnterSomething.php files
			{
				$sender = "startSolving";
				$width =  $_SESSION['width'] = intval($_POST["widthField3"]); 
				$toolbarwidth = $_SESSION['toolbarwidth'] = intval($_POST["toolbarwidthField"]); 
				$height = $_SESSION['height'] = intval($_POST["heightField3"]);  
				$language = $_POST["language"];  
				$topic = $_POST["topicField"];
			}
		if (isset($_POST['autoStep']))
		{ 
			$sender = "autoStep";
		}
		if (isset($_POST['showStep']))
		{ 
			$sender = "showStep"; 
		}
		if (isset($_POST['autoFinish']))
		{
			$sender = "autoFinish"; 
		}
		if (isset($_POST['undo']))
		{
			$sender = "undo";
		}
		if (isset($_POST['hint']))
		{
			$sender = "hint";
		} 
		if (isset($_POST['assumptions']))
		{
			$sender = "assumptions";
		}
		if (isset($_POST['finished']))
		{
			$sender = "finished";
		}
		if (isset($_POST['language2']))
		{
			$sender = "setLanguage";
			$language = $_POST['language2']; 
		}
		if (isset($_POST['commandID']))
		{
			$commandID = $_POST['commandID'];
			$_SESSION['commandID'] = $commandID; 
			   // so we can find it when we are ready to exec it
			$sender = "selectMenuChoice";	
		}
		if (isset($_POST['selectedRectangleField']))
		{
			$sender = "selectedRectangleSymbol";
			$param = $_POST['selectedRectangleField'];
		}
		if (isset($_POST['suppliedArgText']))
		{
			$sender = "suppliedArgText";
			$param = $_POST['suppliedArgText'];
		}
		if (isset($_POST['arg']))  // this is the arg text that has parsed and passed check_arg
		{
			$sender = "execOpWithArg";
			$param = $_SESSION['commandID'] . "+" . $_POST['arg']; 
			$_SESSION['show_selectTermHint'] = false;
		}

		$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

		if ($socket === false) 
			{
				echo "Socket creation failed: " . socket_strerror(socket_last_error()) . "<br>";
			} 
		else 
			{   
				socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0)); 
			   //  setting the receive timeout to zero effectively says don't time out, wait as long as it takes for an answer.
				$result = socket_connect($socket, $serverAddress, $serverPort);
				if ($result) 
					{ 	if($sender=="GetProblem")
						{  
							$reasonstart = intval(0.7 * $width);   // x-coordinate where we want the reasons to start, in papyrus coordinates
							$response = sendMessage($clientSocket,"initSymbolDocFromLibrary",
											$topicnumber . "+" . $problemnumber . "+" . $reasonstart . "+" . $width. "+" . "$language");
							if ($response === false)
								{
									$errcode = socket_last_error($socket);
									$message = socket_strerror($errcode);
									echo "Socket_read error: $message<br>";
								}
							else
								{
									// The response consists of some Javascript, followed by  <svg> elements, 
									//  one for the problem, and one for the reason, in this case "the problem"   
									//  but then also svg for the tooltips
									// Find the position of the first occurrence of "</script>"
									$position = stripos($response, '</script>');

									// Check if "</script>" was found
									if ($position !== false) {
										// Include the length of "</script>" to split after it
										$position += strlen('</script>');
    
										// Split the response into two parts
										$scriptPart = substr($response, 0, $position);
										$svgPart = substr($response, $position);
									} else {
										// If "</script>" is not found, keep the response as is--but it will be found
										$svgPart = $response;
										$scriptPart = ''; 
									}
									echo($scriptPart); 
									?>
									<div id="svgContainer">
										<div id="selectTermHint" class="selectHint">
											To take a step yourself, select the expression you want to change.
											<button id="showMeButton" 
												class="video-button" style="margin-left: 10px;"> 
												<span class="video-icon">🎥</span> 
												Show me how
											</button>
										</div>  	
							
										<?php
											echo($svgPart);
										?>
									</div>
								   <?php
								}
							socket_close($socket);  // because server has already closed it
						}
						else if($sender=="autoTest")
						{	$breakwidth = $width;   //  max length of pieces of broken lines
							$reasonstart = intval(0.7 * $width);   // x-coordinate where we want the reasons to start, in papyrus coordinates 2
							$param =  $topicnumber . "+" . $problemnumber . "+" . $reasonstart . "+" . $breakwidth. "+" . "$language";
							$response = sendMessage($clientSocket,"initAndAutoFinish",$param);
							if ($response === false)
								{
								   $errcode = socket_last_error($socket);
								   $message = socket_strerror($errcode);
								   echo "Socket_read error: $message<br>";
								} 
							else 
								{   
									?>
										<div id="svgContainer">
											<?php
												echo($response);
											?>
										</div>
									<?php
								}
							socket_close($socket);  // because server has already closed it
						}		
						else if($sender == "autoStep" or $sender == "undo" or $sender == "autoFinish" or $sender == "selectMenuChoice" or $sender == "execOpWithArg" or 
								$sender == "showStep" or $sender == "finished" or $sender == "hint" or $sender == "setLanguage" or $sender == "selectedRectangleSymbol" or
								$sender == "symbolWindowResized" or $sender == "startSolving"
							   )
						{
							if($sender == "setLanguage")
								{ 
									$param = $language;
									$_SESSION['languagenumber'] = $language;
								}
							else if($sender == "selectMenuChoice")
								{
									$param = $commandID;
								} 
							else if($sender == "startSolving") 
								{  $param = "$width+$height+$topic"; 
								}
							else if(! isset($param))
								$param = "dummy";
							$response = sendMessage($clientSocket,$sender,$param);
							if ($response === false)
								{
									$errcode = socket_last_error($socket);
									$message = socket_strerror($errcode);
									echo "Socket_read error: $message<br>";
								} 
							else 
								{   
									// The response consists of many <svg> elements,  to redraw the whole computation
									// it may also include other things to be echoed, such as "<script>  highlightIndex = 3; </script>"
								?>

									<div id="svgContainer">
									   <div id="selectTermHint" class="selectHint">
											To take a step yourself, select the expression you want to change.
											<button id="showMeButton" 
												class="video-button" style="margin-left: 10px;"> 
												<span class="video-icon">🎥</span> 
												Show me how
											</button>
									 </div>  
								
										<?php
											echo($response); 
										?>
								 	</div>
								<?php
								}
							socket_close($socket);  // because server has already closed it
						} 
					}
				else 
					{
						echo "Failed to connect to the C program: " . socket_strerror(socket_last_error()) . "<br>";
					}
		}
	}
?>
	
<div id="hintModal">
	<div id="hintModalContent">
	   <button onclick="hideHintModal()">Close</button>
	</div>
</div>
<div id="assumptionsModal">
	<div id="assumptionsModalContent">
	   <button onclick="hideAssumptionsModal()">Close</button>
	</div>
</div>
<script src="crashPopup.js"></script>
<script>
	window.addEventListener('beforeunload', function (e) {
	// Send the beacon request to notify the server about session end
	navigator.sendBeacon('<?php echo $_SERVER["PHP_SELF"]; ?>?action=endSession');
	});
</script>
			
<script>
   <?php 
	if($sender == "hint")
	    {  // embed JavaScript to show the hint modal on page load
		    echo 'document.addEventListener("DOMContentLoaded", function() {
		             // Show the hint modal
		             showHintModal();
		         });';
	    }
 	if($sender == "assumptions")
 	    {  // embed JavaScript to show the hint modal on page load
 		    echo 'document.addEventListener("DOMContentLoaded", function() {
 		             // Show the assumptions modal
 		             showAssumptions();
 		         });';
 	    }
	if($sender == "selectedRectangleSymbol" || $sender == "showStep")
		{   
		    echo 'document.addEventListener("DOMContentLoaded", function() {
		             console.log("about to display selection menu");
		             showSelectionMenu(200,100);
		         });';
			
		}
   ?>

   document.getElementById('languageSelector').addEventListener('change', function() {
       var language = this.value;
	   setLanguage(language);
   });
   
		  
  function Graph(){
   //  submit a hidden form, so that PHP can process it and send the graphButton message
   //  the form needs no input fields.  
	
	var myform = document.createElement('form');

	      // Set form attributes
	myform.setAttribute('method', 'post');
	myform.setAttribute('action', <?php echo json_encode($nextpagegraph); ?>);
	myform.style.display = 'none'; 

	      // Append the form to the body
	document.body.appendChild(myform);

	      // Submit the form 
	myform.submit();
}

  
function setSelectedLanguage(){
    // Assume 'languageSelector' is the id of the language select dropdown
    var languageValue = document.getElementById('languageSelector').value;

    var myform = document.createElement('form');

    // Set form attributes
    myform.setAttribute('method', 'post');
    myform.setAttribute('action', <?php echo json_encode($_SERVER['PHP_SELF']); ?>); // Use json_encode to properly handle strings
    myform.style.display = 'none'; 

    // Create a hidden input to carry the language value
    var languageInput = document.createElement('input');
    languageInput.setAttribute('type', 'hidden');
    languageInput.setAttribute('name', 'language2'); 
    languageInput.setAttribute('value', languageValue);
    // Append the hidden input to the form 
    
    myform.appendChild(languageInput);

    // Append the form to the body
    document.body.appendChild(myform);
    
    // Submit the form 
    myform.submit();
}

  
function selectedRect(param)
 // called on pointerup, with param set to be the parameter for the selectedRectangleSymbol message
{
    var myform = document.createElement('form');

    // Set form attributes
    myform.setAttribute('method', 'post');
    myform.setAttribute('action', <?php echo json_encode($_SERVER['PHP_SELF']); ?>); // Use json_encode to properly handle strings
    myform.style.display = 'none'; 

    // Create a hidden input to carry the selected rectangle 
    var selectedRectangleInput = document.createElement('input');
    selectedRectangleInput.setAttribute('type', 'hidden');
    selectedRectangleInput.setAttribute('name', 'selectedRectangleField');
    selectedRectangleInput.setAttribute('value', param);

    // Append the hidden input to the form
    myform.appendChild(selectedRectangleInput);

    // Append the form to the body
    document.body.appendChild(myform);

    // Submit the form 
    myform.submit();
}

function showAssumptions() {
    // Create a popup window
    var assumptionsModal = document.getElementById('assumptionsModal');
    assumptionsModal.style.display = 'flex';
    // Create a div with relative positioning
    var div = document.createElement('div');
    div.style.position = 'relative';

    // Append the div to the modal content
    var modalContent = document.getElementById('assumptionsModalContent');
    modalContent.appendChild(div);
    // Display all SVG elements with class "assumption"
    var assumptions = document.querySelectorAll('.assumption');
    assumptions.forEach(function (assumption) {
        // Clone the assumption
        var clonedAssumption = assumption.cloneNode(true);

        // Set the display property to block (or any other appropriate value)
        clonedAssumption.style.display = 'block';

        // Append the cloned assumption to the div
        div.appendChild(clonedAssumption);
    });
}

// Function to show the hint modal
function showHintModal() {
    // Get the hint modal
    var hintModal = document.getElementById('hintModal');
    hintModal.style.display = 'flex';
    console.log("called showHintModal");
    // Create a div with relative positioning
    var div = document.createElement('div');
    div.style.position = 'relative';

    // Append the div to the modal content
    var modalContent = document.getElementById('hintModalContent');
    modalContent.appendChild(div);

    // Display all SVG elements with class "hint" (There will only be one)
    var hints = document.querySelectorAll('.hint');
    hints.forEach(function (hint) {
        // Clone the hint
        var clonedHint = hint.cloneNode(true); 
        // perhaps it's a very long hint, in which case we need to wrap it  
        let maxwidth = 800;
        if (clonedHint.style.width > maxwidth) 
           {  wrapSVGTextWithTspans(clonedHint,maxwidth );
           }
        // Set the display property to block (or any other appropriate value)
        clonedHint.style.display = 'block';
        // Append the cloned hint to the div
        div.appendChild(clonedHint);
    });
}



  // Function to hide the hint modal
function hideHintModal() {
      var hintModal = document.getElementById('hintModal');
      hintModal.style.display = 'none';
}
  // Function to hide the assumptions modal
function hideAssumptionsModal() {
	var hintModal = document.getElementById('assumptionsModal');
	assumptionsModal.style.display = 'none';
}


let svgContainer = document.getElementById('svgContainer');
let selectionRectangle = document.createElement('div');
selectionRectangle.id = 'selectionRectangle';
selectionRectangle.style.position = 'absolute';
selectionRectangle.style.border = '1px solid blue';
selectionRectangle.style.pointerEvents = 'none'; // Ignore pointer events

let selectedX = selectionRectangle.style.left = 0;
let selectedY = selectionRectangle.style.top = 0;
let selectedWidth = selectionRectangle.style.width;
let selectedHeight = selectionRectangle.style.height;
let windowwidth =   document.body.clientWidth;
let windowheight = window.innerHeight;   //  technically this is the "viewport height"

let startX, startY, isSelecting = false;
let activeGraphBounds = null;
let whichline = 0;
// the following variables are set in pointerdown and used in pointerup
let lineX = 0;
let lineY = 0;
let lineWidth = 0;
let lineHeight = 0;
// let activeline = 0; sent by the Engine now


function currentlinenumber() {
	    const lines = document.querySelectorAll('.line'); // Get all elements with class "line"
	    let maxId = -1; // Start with -1,  so if no lines are found, the result is -1

	    lines.forEach(line => {
	        const id = parseInt(line.getAttribute('id').replace('line', ''), 10);
	        if (id > maxId) {
	            maxId = id;
	        }
	    });
	    return Math.abs(maxId); 
	}

document.addEventListener('pointerdown', function(e) {  // pointerdown, not mousedown, so it will work on iPhone and iPad
	if (e.shiftkey == false && selectionMade)
		selectionMade = false;
	if (!svgContainer.contains(selectionRectangle)) 
	      svgContainer.appendChild(selectionRectangle);
	let lines = document.querySelectorAll('.line');
	let rect = svgContainer.getBoundingClientRect();
	// if there is a selectionMenu already on-screen, and this mousedown is outside it, remove it
	const menuContainer = document.getElementById('selectionMenu');
	if (menuContainer) {
	    let menurect = menuContainer.getBoundingClientRect();
	    // Check if the click is outside of menurect
	    if (e.clientX < menurect.left || e.clientX > menurect.right || 
	        e.clientY < menurect.top || e.clientY > menurect.bottom) {
	        // Click is outside, so remove the menuContainer
	        document.body.removeChild(menuContainer);
			document.querySelectorAll('.selectmenuitem').forEach(item => {
				item.parentNode.removeChild(item); // Remove all the menu items too
			}); 
			// Remove the rectangles of class "selectedRectangle", which 
			// color the background of the selected term(s)
			document.querySelectorAll('.selectedRectangle').forEach(rect => {
			    rect.parentNode.removeChild(rect); // Remove each rectangle from its parent node
			// And we also remove the svg elements that contain the selected rectangles. 
			document.querySelectorAll('.highlight').forEach(svg => {
					    svg.parentNode.removeChild(svg);  
				});
			// This doesn't remove the selectedRectangle from the document in the Engine.  
			// It will be removed anyway at the next step, so even though there is an Ajax
		    // messsage to remove it,  that's not necessary.
			// The selectionRectangle div now appears as a 2px by 2px dot.  
			// The following code removes it
			const selectedRectangle = document.getElementById('selectionRectangle');  
			selectedRectangle.parentNode.removeChild(selectionRectangle);
			});
			
	    }
	}
	let x = e.clientX - rect.left + svgContainer.scrollLeft;
	let y = e.clientY - rect.top + svgContainer.scrollTop;  // Now these coordinates are relative to svgContainer
	//  activeline = currentlinenumber();   // should be active line number, 
	//  Now activeline is defined in Javascript sent by the Engine
	let lineid = "line" + activeline;
	var line = document.getElementById(lineid);
	lineX = parseInt(line.style.left,10);  // these coordinates are relative to svgContainer
	lineY = parseInt(line.style.top,10);
	lineWidth = line.width.baseVal.value;
	lineHeight = line.height.baseVal.value;
	if (x >= lineX && x <= lineX + lineWidth && y >= lineY && y <= lineY + lineHeight) 
			{
				isSelecting = true;
				startX = x;
				startY = y;
				activeGraphBounds = { left: lineX, top: lineY, right: lineX + lineWidth, bottom: lineY + lineHeight };
				updateSelectionRectangle(x, y, 0, 0);
			}
	});

document.addEventListener('pointermove', function(e) {
        e.stopPropagation();
        e.preventDefault();
	    if (!isSelecting || !activeGraphBounds) return;
	     // prevent the browser from getting the pointermoves
		 // but this doesn't seem to work
	    
	    
	    let rect = svgContainer.getBoundingClientRect();
		 let x = e.clientX - rect.left + svgContainer.scrollLeft;
	
	    
	    let y = e.clientY - rect.top + svgContainer.scrollTop;

	    // Constrain the selection within the manually defined bounds
	    x = Math.max(activeGraphBounds.left, Math.min(x, activeGraphBounds.right));
	    y = Math.max(activeGraphBounds.top, Math.min(y, activeGraphBounds.bottom));

	    let width = Math.abs(x - startX);
	    let height = Math.abs(y - startY);
	
	    let newX = startX < x ? startX : x;
	    let newY = startY < y ? startY : y;

	    // Adjust width and height to not exceed the active graph bounds
	    if (newX + width > activeGraphBounds.right)
			 width = activeGraphBounds.right - newX;
	    if (newY + height > activeGraphBounds.bottom) 
			height = activeGraphBounds.bottom - newY;

	    updateSelectionRectangle(newX, newY, width, height);
	});

document.addEventListener('pointerup', function(e) {
	    if (!isSelecting) return;
	    isSelecting = false;
	    activeGraphBounds = null; // Reset the active graph bounds
	    // The final selected rectangle is available here
       // selectedX = parseInt(selectionRectangle.style.left,10);
        selectedX = parseInt(selectionRectangle.style.left,10);
        selectedY = parseInt(selectionRectangle.style.top,10);
        selectedWidth = parseInt(selectionRectangle.style.width,10);
        selectedHeight = parseInt(selectionRectangle.style.height,10);
		if (!(selectedWidth > 0 && selectedHeight > 0))
			return;
		selectionMade = true;
	    // Next create the parameter for the selectedRectangleSymbol method, which is supposed to be
	   // [left,top,width,height,lineleft,linetop,linewidth,lineheight,windowwidth,windowheight].  
	   // but they all have to be scaled down by scaleFactor
		param = "[" + [
			Math.floor(selectedX / scaleFactor), 
			Math.floor(selectedY / scaleFactor), 
			Math.floor(selectedWidth / scaleFactor), 
			Math.floor(selectedHeight / scaleFactor), 
			Math.floor(lineX / scaleFactor), 
			Math.floor(lineY / scaleFactor), 
		    lineWidth / scaleFactor,   // a double
		    lineHeight / scaleFactor,  // a double
			windowwidth,   // this hasn't been scaled
			windowheight   // this hasn't been scaled
		] + "]";
	    console.log(param);
		selectedRect(param);
		
	});

function updateSelectionRectangle(x, y, width, height) { 
	    selectionRectangle.style.left = x + 'px';
	    selectionRectangle.style.top = y + 'px';
	    selectionRectangle.style.width = width + 'px';
	    selectionRectangle.style.height = height + 'px';
	}

	
function showSelectionMenu(x, y) 
// This shows the selection menu with upper left corner at x,y,
// provided there are any elements of class "selectmenuitem".
// If global variable highlightIndex is nonnegative, highlight the item with that index
{  
	// make the popup that displays "Select the term you want to change"  disappear, so it doesn't lie behind the menu
	selectTermHint = document.getElementById('selectTermHint');  
	selectTermHint.style.display = "none";
	 if(typeof highlightIndex == 'undefined') 
		 highlightIndex = -1;   // Maybe it's already been defined in the response to the showStep message
    // Find all selectmenuitem SVG elements
    const menuItems = document.querySelectorAll('.selectmenuitem');
	// Ensure that each item has a viewBox // but they all do so this is superfluous
  	menuItems.forEach((item, index) => {  
	console.log(item);
		if (!item.hasAttribute('viewBox')) { 
				let width = parseInt(item.getAttribute('width'));
			 	let height = parseInt(item.getAttribute('height'));
				item.setAttribute('viewBox', `0 0  ${width} ${height}`);
		      console.log(`Updated: ID ${item.id}, viewBox=${item.getAttribute('viewBox')}`);		
		} 
	});     
	
   // Check if menuItems is empty
    if (menuItems.length === 0) {
        console.log('No menu items found.');
        return; // Exit the function early
    }

    // Create or find the menu container
    let menuContainer = document.getElementById('selectionMenu');
    if (!menuContainer) {
        menuContainer = document.createElement('div');
        menuContainer.id = 'selectionMenu';
        document.body.appendChild(menuContainer);
    }

    // Clear previous menu items
    menuContainer.innerHTML = '';

    // Set position
    menuContainer.style.position = 'absolute';
    menuContainer.style.left = x + 'px';
    menuContainer.style.top = y + 'px';
    menuContainer.style.display = 'block';
    menuContainer.style.backgroundColor = 'white';
    menuContainer.style.border = '1px solid black';
    menuContainer.style.padding = '0px';
	let menuwidth = 20;  // not 20px
	let nitems = 0;


	let accumulatedHeight = 0; // Keep track of the total height of menu items added so far
	const menuItemSpacing = 3; // Spacing between menu items
	
	// calculate maximum width of the menuItems
	menuItems.forEach((item, index) => {
		const itemWidth = parseInt(item.getAttribute('width'));
	    if (itemWidth > menuwidth) {
	        menuwidth = itemWidth;
	    }
    });
	// Append items to the container and add click event listeners
	menuItems.forEach((item, index) => {
	    const wrapper = document.createElement('div');
	    wrapper.className = 'selectMenuItemWrapper';

	    const menuItem = item.cloneNode(true); // Clone the SVG element
	    menuItem.style.display = "block"; // Make SVG visible
	    const itemWidth = parseInt(menuItem.getAttribute('width'));
	    const itemHeight = parseInt(menuItem.getAttribute('height'));

	    // Set wrapper styles
	    wrapper.style.width = `${menuwidth}px`;
	    wrapper.style.height = `${itemHeight}px`;
	    wrapper.style.position = 'absolute';
	    wrapper.style.left = '0px'; // align items to the left
	    wrapper.style.top = `${accumulatedHeight}px`; // Position items vertically
		
        // Highlight only if highlightIndex is non-negative and matches the current index
        if (index === highlightIndex && highlightIndex >= 0) {
            wrapper.classList.add('highlighted');
        }
		

	    // Add the current item's height plus spacing to the total height
	    accumulatedHeight += itemHeight + menuItemSpacing;

	    wrapper.appendChild(menuItem); // Wrap the SVG with the div

	    wrapper.addEventListener('click', function() {
	        const commandID = parseInt(menuItem.getAttribute('id')); // Use menuItem to get the commandID
			console.log(commandID);
	        selectMenuChoice(commandID);
	    });

	    menuContainer.appendChild(wrapper);
	});

	// Adjust the menu container's width to fit all items
	menuContainer.style.width = `${menuwidth}px`;
	// Set the menu container's total height to fit all items including spacing
	accumulatedHeight -= menuItemSpacing;
	menuContainer.style.height = `${accumulatedHeight}px`;	
  
}


function selectMenuChoice(commandID) {
    console.log('Selected command ID:', commandID);
	
    // Create and submit a hidden form to carry commandID as $_POST data
    const form = document.createElement('form');
    form.method = 'POST';
    form.action = '<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>'; // Dynamically set to this script
    form.style.display = 'none';

    // Create a hidden field for commandID
    const hiddenField = document.createElement('input');
    hiddenField.type = 'hidden';
    hiddenField.name = 'commandID';
    hiddenField.value = commandID;

    // Append the hidden field to the form
    form.appendChild(hiddenField);

    // Append the form to the body and submit it
    document.body.appendChild(form);
    form.submit();
}

// Declare c at a higher scope
let conditionC;

document.addEventListener('DOMContentLoaded', function() { 
	 showCrashPopup();  // if a crash has occurred, notify the user.
    const svgPrompt = document.querySelector('.needsargprompt');
    if (svgPrompt) {
        displayPrompt(svgPrompt);
    }
});



function displayPrompt(svgElement) {
    const modal = document.getElementById('promptModal');
    const modalContent = document.getElementById('modalContent');

    // Clear previous content
    modalContent.innerHTML = '';
	
    // Extract condition from svgElement's ID
    const idStr = svgElement.id;
    const match = idStr.match(/\d+$/); // Matches number at the end of the string
    conditionC = match ? parseInt(match[0], 10) : null; // Save the parsed number globally

    // Clone the SVG element, modify its style properties, and append it
    const clonedSvg = svgElement.cloneNode(true);
    clonedSvg.style.display = 'block'; // Ensure it is visible within the modal
    clonedSvg.style.position = 'relative'; // Adjust positioning to be relative within the modal

    modalContent.appendChild(clonedSvg);

    // Create and append the input field
    const inputField = document.createElement('input');
    inputField.id = 'responseInput';
    inputField.type = 'text';
    inputField.placeholder = 'Enter your response here';
    modalContent.appendChild(inputField);

    // Create a container for the buttons
    const buttonContainer = document.createElement('div');
    buttonContainer.style.display = 'flex';
    buttonContainer.style.justifyContent = 'space-evenly';
    buttonContainer.style.marginTop = '10px'; // Space above the buttons

    // Create and append the OK (submit) button
    const okButton = document.createElement('button');
    okButton.textContent = 'OK';
    okButton.addEventListener('click', submitResponse);
    buttonContainer.appendChild(okButton);

	 // Create and append the Cancel button
	const cancelButton = document.createElement('button');
	cancelButton.textContent = 'Cancel';
	cancelButton.addEventListener('click', function() {
		document.getElementById('promptModal').style.display = 'none';  
		// and get rid of the rectangle(s) highlighting the selected term (or terms) 
		document.querySelectorAll('.selectedRectangle').forEach(rect => {
		    rect.parentNode.removeChild(rect); // Remove each rectangle from its parent node
		// And we also remove the svg elements that contain the selected rectangles. 
		document.querySelectorAll('.highlight').forEach(svg => {
				    svg.parentNode.removeChild(svg);  
			});
		// This doesn't remove the selectedRectangle from the document in the Engine.  
		// It will be removed anyway at the next step, so even though there is an Ajax
		// messsage to remove it,  that's not necessary.
		// The selectionRectangle div now appears as a 2px by 2px dot.  
		// The following code removes it
		const selectedRectangle = document.getElementById('selectionRectangle');  
		selectedRectangle.parentNode.removeChild(selectionRectangle);
		});
	});
	buttonContainer.appendChild(cancelButton);

    // Append the button container to the modal content
    modalContent.appendChild(buttonContainer);

    // Create and append the response area
    const responseArea = document.createElement('div');
    responseArea.id = "responseArea";
    modalContent.appendChild(responseArea);

    // Show the modal
    modal.style.display = 'block';

    // Ensure the modal and its contents are accessible
    modal.style.zIndex = '1000'; // Make sure modal is above other content
    modal.style.pointerEvents = 'auto'; // Ensure it can be interacted with

    // Focus on input after showing the modal
    inputField.focus();
}



function submitResponse() {
    const inputText = document.getElementById('responseInput').value;
    console.log('Entered text:', inputText);
	console.log('conditionC = ',conditionC);
    if (inputText.trim().length == 0)
		{ alert("You must enter a formula.")  // This will have to be localized.
		// document.querySelector('.needsargprompt'); is the prompt, as SVG;  Let's just repeat that in the alert.
		  return;
		}
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>", true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	const data = `suppliedArgText=${encodeURIComponent(inputText)}&needsArgCondition=${encodeURIComponent(conditionC)}`;
	console.log('Data being sent:', data);
	xhr.send(data);
	
    // Get the server response
    xhr.onload = function() {
        if (xhr.status == 200) {
            console.log("Response received:", xhr.responseText);
			// Did it parse?  Did it satisfy check_arg?
			let responseText = xhr.responseText;
			if(responseText == "0+0") {
			 // no message: it parsed and passed check_arg
				checkArgMessage = "OK";
				// Create a hidden form to submit the argument
				const form = document.createElement('form');
				form.method = 'POST';
				form.action = '<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>'; // Adjust the action as needed
				form.style.display = 'none';

				// Create a hidden input to carry the argument value
				const hiddenInput = document.createElement('input');
				hiddenInput.type = 'hidden';
				hiddenInput.name = 'arg';
				hiddenInput.value = inputText; 

				// Append the hidden input to the form
				form.appendChild(hiddenInput);
				document.body.appendChild(form);
				form.submit();
				console.log("Form submitted with arg:", inputText);	
				document.getElementById('promptModal').style.display = 'none';  // close the modal
				// There is no real need to close the modal as the whole file is finished when we submit the form,
				// but if I don't close it here, there is a brief flashing view of "0+0", which is thus prevented.	
			}	
		  
            // Update the modal with the response from the server
            const responseArea = document.getElementById('responseArea'); 
			// responseText is an <svg> element, possibly with display:none.
			// We need to put it into responseArea after setting display:block
            responseArea.innerHTML = responseText;
			svgElement = responseArea.querySelector('svg');
		    if(svgElement) {
		       svgElement.style.display = 'block'; // Ensure SVG is visible
				 console.log("SVG element found and made visible");
		    }
            responseArea.style.display = 'block'; // Make sure it's visible
			responseArea.style.position = "relative";
			if(svgElement.classList.contains("feedback")) {
			    // conditionC is intbyparts1, so change it to intbyparts2 now
			    conditionC = conditionC + 1;
			    console.log("New conditionC is ", conditionC);
			}
		
        } else {
            console.log("Error in Ajax request");
        }
    };

    // Optionally, one might clear the input
    // document.getElementById('responseInput').value = '';
	
    // or close the modal by 
   // document.getElementById('promptModal').style.display = 'none';
	
}
</script>  
<script>
	document.addEventListener('DOMContentLoaded', function() {  
		if(languageNumber == undefined) 
			var languageNumber = 0;  // ENGLISH
		// if it is already defined, then languageName has been set in code supplied by the Engine with sendDocument 
		setLanguage(languageName);	 // translate button text etc.  Engine is told what the language is by setSelectedLanguage.  That's done when it changes, not here.
		// set the language selector to the current language
		document.getElementById('languageSelector').value = languageName;   
		console.log("setting language to ",languageName);   
		if(document.getElementById("progress0"))  // steps of factorization or integration by parts
			displayProgress(); 
		if(hide_selectTermHint){ 
			let theHint = document.getElementById("selectTermHint"); 
			// theHint.style.opacity = 0;   // this still allows a flickering "ghost" to appear 
			theHint.style = "display:none";
		} 
		if (typeof showGraphButton !== 'undefined' && showGraphButton === 0) {
			const graphButton = document.getElementById('graphButton');
			// Set display to none to hide the button entirely
			graphButton.style.display = 'none';
		}
	});
</script>
<script>
// script to play ShowMe video
document.addEventListener("DOMContentLoaded", function () {
    // Check for either button
    const button = document.getElementById("showMeButton");
    // If no such button exists, do nothing
    if (!button)  
    		return; 
    // Add the event listener to the button
    button.addEventListener("click", function () { 
            console.log("Trying to play video");
        // Create the popup container 
        const videoPopup = document.createElement("div");
        videoPopup.id = "videoPopup";
        videoPopup.style.position = "fixed";
        videoPopup.style.top = "50%";
        videoPopup.style.left = "50%";
        videoPopup.style.transform = "translate(-50%, -50%)";
        videoPopup.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
        videoPopup.style.padding = "20px";
        videoPopup.style.borderRadius = "8px";
        videoPopup.style.zIndex = "1000";
        videoPopup.style.display = "flex";
        videoPopup.style.flexDirection = "column";
        videoPopup.style.alignItems = "center";
 
        // Create the video element
        const videoElement = document.createElement("video");
        videoElement.src = "ShowMe.mp4";
        videoElement.controls = true;
        videoElement.autoplay = true; 
		  videoElement.onloadeddata = function () {   // inserted 3.12.25
		      if (videoElement.requestFullscreen) {
		          videoElement.requestFullscreen();
		      } else if (videoElement.webkitRequestFullscreen) { // Safari
		          videoElement.webkitRequestFullscreen();
		      } else if (videoElement.mozRequestFullScreen) { // Firefox
		          videoElement.mozRequestFullScreen();
		      } else if (videoElement.msRequestFullscreen) { // Edge/IE
		          videoElement.msRequestFullscreen();
		      }
		  }; 
		  videoElement.addEventListener("fullscreenchange", function () {
		      if (!document.fullscreenElement) {
		          document.body.removeChild(videoPopup);
		      }
		  });
        videoElement.style.width = "100%";
        videoElement.style.maxWidth = "600px";
        videoElement.style.borderRadius = "8px";

        // Create the close button
        const closeButton = document.createElement("button");
        closeButton.textContent = "X";
        closeButton.style.position = "absolute";
        closeButton.style.top = "10px";
        closeButton.style.right = "10px";
        closeButton.style.backgroundColor = "red";
        closeButton.style.color = "white";
        closeButton.style.border = "none";
        closeButton.style.borderRadius = "50%";
        closeButton.style.cursor = "pointer";
        closeButton.style.fontSize = "16px";
        closeButton.style.width = "30px";
        closeButton.style.height = "30px";
        closeButton.addEventListener("click", function () {
            document.body.removeChild(videoPopup);
        });

        // Append elements to the popup
        videoPopup.appendChild(videoElement);
        videoPopup.appendChild(closeButton);

        // Append the popup to the body
        document.body.appendChild(videoPopup);
    });
});
</script>
<script>
// Script to move the reasons to the right of long lines
document.addEventListener('DOMContentLoaded', () => {
    // Iterate over all elements with ids starting with "line"
    const lineElements = Array.from(document.querySelectorAll('[id^="line"]'));

    lineElements.forEach(lineElement => {
        const lineId = lineElement.id; // E.g., "line13"
        const lineNumber = lineId.replace('line', ''); // Extract the number, e.g., "13"
        const reasonId = `reason${lineNumber}`; // Form the corresponding reason id, e.g., "reason13"
        const reasonElement = document.getElementById(reasonId);

        if (reasonElement) {
            const lineWidth = parseFloat(lineElement.getAttribute('width')) || 0; // Get line width as a number
            const currentLeft = parseFloat(reasonElement.style.left) || 0; // Parse existing left position of reason

            // Update left position if necessary
            if (currentLeft <= lineWidth + 16) {
                reasonElement.style.left = `${lineWidth + 16}px`;
            }
        }
    });
});
</script>
<script src="TypeSize.js"></script> 
<script src="wrapSVGtext.js"></script> 
<script src="Tooltips.js"></script>   <!-- has to come last, or tooltips don't work on .selectionmenuitem  --> 
<script>
document.getElementById('svgContainer').addEventListener('pointermove', function(event) {
    const container = this;
    const rect = container.getBoundingClientRect();
    const margin = 20; // How close to the edge before scrolling starts
    const scrollSpeed = 10; // Adjust scrolling speed
    let scrolled = false; // Track if scrolling happens

    // Scroll right if the pointer is near the right edge
    if (event.clientX > rect.right - margin) {
        container.scrollLeft += scrollSpeed;
        scrolled = true;
    }
    // Scroll left if the pointer is near the left edge
    else if (event.clientX < rect.left + margin) {
        container.scrollLeft -= scrollSpeed;
        scrolled = true;
    }

    // If scrolling occurred, adjust the selection rectangle's position
    if (scrolled) {  
        const selectionRectangle = document.getElementById('selectionRectangle');
        if (selectionRectangle) {
            selectionRectangle.style.left = parseInt(selectionRectangle.style.left) + container.scrollLeft + 'px';
        }
    }
});
</script>
</body>
</html>


 

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists