Sindbad~EG File Manager

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

<?php
// Set HTTP header to prevent caching
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);

$serverAddress = 'localhost'; // Adjust the server address
$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
//$imageBaseDir = "/Users/beeson/Dropbox/MathXpert/images/";

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();
}

$nextpagegraph = "https://localhost:8443/Demos/ProblemLibraryDemo/GraphDoc.php";
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';  /* Without this, the above rule sometimes doesn't apply to SVG text */
        }
        .hidden {
            visibility: hidden;
            position: absolute;
        }
        #svgContainer {
            position: relative;
        }
        #selectionRectangle {
            position: absolute;
            border: 1px solid red;
            pointer-events: none; /* Ignore this element during mouse events */
        }
        body {
            background-color: CornSilk;
        }
        .button-container {
            display: flex;
            gap: 5px; /* Adjust the gap as needed */
            align-items: center; /* Align items vertically in the center */
        }
        .button-container button {
            height: 17px; /* Adjust the height as needed */
        }
        .selectMenuItemWrapper {
            display: inline-block;
            cursor: pointer;
            position: relative;
        }
        .selectMenuItemWrapper:hover {
            background-color: rgb(200,200,255);
        }
        .highlighted {
            background-color: rgb(200,255,200); 
        }
        #hintModal {
            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 {
            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;
        }
    </style>
</head>
<body>
<?php
ob_start();
include 'toolbar.php';
$toolbarContent = ob_get_clean();
?>
<div id="hiddenToolbar" class="hidden">
    <?php echo $toolbarContent; ?>
</div>
</body>
</html>

<style>
	.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>
	
<div class="button-container" style="display: flex; align-items: center;">
    <!-- Wrapper for select elements to stack them vertically -->
    <div style="display: flex; flex-direction: column; margin-right: 0px;">
        <select id="typesize">
            <option value="1">Change Type Size</option>
            <option value="2">Normal</option>
            <option value="3">Larger</option>
            <option value="4">Smaller</option>
        </select>
        <select id="language">
            <option value="-1">Select Language</option> 
   		 	<option value="0">English</option>
   		 	<option value="5">Nederlands</option> <!-- Dutch in Dutch -->
   		 	<option value="1">Français</option> <!-- French in French -->
   		 	<option value="2">Deutsch</option> <!-- German in German -->
    		<option value="7">Italiano</option> <!-- Italian in Italian -->
   		 	<option value="3">Español</option> <!-- Spanish in Spanish -->
			<option value="11">中文</option>  <!-- Chinese in Chinese>-->
		</select>
    </div>
    <!-- Other elements remain in the horizontal flow -->
    <button onclick="showAssumptions()">Assumptions</button>
    <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" style="display: flex; align-items: center;">
        <input type="image" name="autoStep" src="autostep.bmp" Alt="AutoStep" width="60" height="36">
        <input type="image" name="autoFinish" src="autofinish.bmp" alt="AutoFinish" width="65" height="36">
		<input type="image" name="showStep" src="showstep.bmp" Alt="ShowStep" width="65" height="36">
        <input type="image" name="undo" src="undo.bmp" alt="Undo" width="60" height="36">
        <input type="image" name="hint" src="hint.bmp" alt="Hint" width="60" height="36">
        <input type="image" name="finished" src="finished.bmp" alt="Finished?" width="60" height="36">
    </form>
	<form method="post" action="<?php echo htmlspecialchars($nextpagegraph); ?>"  target="_blank" id="graphForm" style="display:flex; align-items:center;">
	    <input type="image" name="graphButton" src="pigraph.bmp" alt="Graph" width="60" height="36">
	    <!-- Correct the input tags and set initial values -->
	    <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">
	</form>

	<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 hiddenToolbar = document.getElementById('hiddenToolbar'); 
			console.log(hiddenToolbar);
			const toolbarRect = hiddenToolbar.getBoundingClientRect(); 
			console.log(toolbarRect);
			const toolbarwidth = toolbarRect.width;  
			
			// 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 input image click event
	    document.querySelector('input[type="image"][name="graphButton"]').addEventListener('click', 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 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;
            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
            }
            svgContainer.style.height = containerScrollHeight + 'px';
            // Scroll the container to the bottom
            svgContainer.scrollTop = svgContainer.scrollHeight;
		
        }

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

        // Update the height if the window is resized
        window.addEventListener('resize', setSvgContainerHeight);
		
      // Scroll the svgContainer to the bottom whenever new content is loaded
        window.addEventListener('load', () => {
            const svgContainer = document.getElementById('svgContainer');
            svgContainer.scrollTop = svgContainer.scrollHeight;
        });
	</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>
</div>


<?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['autoStep_x']))
		{ 
			$sender = "autoStep";
		}
		if (isset($_POST['showStep_x']))
		{ 
			$sender = "showStep";
		}
		if (isset($_POST['autoFinish_x']))
		{
			$sender = "autoFinish";
		}
		if (isset($_POST['undo_x']))
		{
			$sender = "undo";
		}
		if (isset($_POST['hint_x']))
		{
			$sender = "hint";
		}
		if (isset($_POST['finished_x']))
		{
			$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'];
		}

        $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));
            $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 two <svg> elements, one for the problem, and one for the reason, in this case "the problem" 
							?>
							<div id="svgContainer"> 
						    <?php
							list($line0, $reason) = explode("</svg>\n<svg", $response);
							$line0 = $line0 . "</svg>\n";
							$reason =  "<svg" . $reason;
							echo($line0);
							echo($reason);
							?>
						</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"
					   )
				{
					if($sender == "setLanguage")
					{ 
					  $param = $language;
					  $_SESSION['languagenumber'] = $language;
					}
					else if($sender == "selectMenuChoice")
					{
						$param = $commandID;
					}
					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">
				   		 <?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>
<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 == "selectedRectangleSymbol" || $sender == "showStep")
		{   
		    echo 'document.addEventListener("DOMContentLoaded", function() {
		             console.log("about to display selection menu");
		             showSelectionMenu(200,80);
		         });';
			
		}
   ?>
   
   document.getElementById('typesize').addEventListener('change', function() {
       var selectedValue = this.value;
    
       // Immediately invoke the appropriate function based on the selected value
       if(selectedValue === "3") {
           LargerType();
       } else if(selectedValue === "4") {
           SmallerType();
       } else if(selectedValue === "2") {
           NormalType();
       }

       // Use a timeout to reset the select box, allowing the UI to update
	   // This permits the user to choose "Larger" twice in a row.
       setTimeout(() => {
           this.selectedIndex = 0; // Resets to a non-selected state
       }, 100); // Short delay to ensure the UI has time to react
   });
   
   document.getElementById('language').addEventListener('change', function() {
       var language = this.value;
	   setLanguage(language);
   });
   

   
  // Initialize the default scale factor
  var scaleFactor = 1;
  
  function AutoStep(){
   //  submit a hidden form, so that PHP can process it and send the autoStep 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($_SERVER['PHP_SELF']); ?>); // Use json_encode to properly handle strings
	myform.style.display = 'none'; 

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

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

  function Graph(){
   //  submit a hidden form, so that PHP can process it and send the Graph 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 setLanguage(){
    // Assume 'language' is the id of the language select dropdown
    var languageValue = document.getElementById('language').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 mouseup, 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 popupWindow = window.open('', 'Assumptions', 'width=600, height=400');

    // Create a div with relative positioning
    var div = popupWindow.document.createElement('div');
    div.style.position = 'relative';

    // Append the div to the popup window
    popupWindow.document.body.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);
        // 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 SmallerType() {
	   // Check if it's already at the minimum size
      if (scaleFactor > 0.7) {
          // Decrease the scale factor 
		  var oldscaleFactor = scaleFactor;
          scaleFactor -= 0.15;

          // Get the container that holds the SVG elements
          var container = document.getElementById('svgContainer');
        
          // Loop through all SVG child elements of the container
          for (var i = 0; i < container.children.length; i++) {
              var svgElement = container.children[i]; // Get the current SVG element
            
              if (svgElement.tagName.toLowerCase() === 'svg') {
                  // Get the current width and height from the SVG element
                  var currentWidth = parseFloat(svgElement.getAttribute('width'));
                  var currentHeight = parseFloat(svgElement.getAttribute('height'));
                
                  // Calculate the new width and height based on the scale factor
                  var newWidth = currentWidth  * (scaleFactor/oldscaleFactor);
                  var newHeight = currentHeight  * (scaleFactor/oldscaleFactor);
                
                  // Set the new width and height attributes of the SVG element
                  svgElement.setAttribute('width', newWidth.toString());
                  svgElement.setAttribute('height', newHeight.toString());
				  // the element's viewBox is not changed.  
              }
          }
      }
  }
  

  function LargerType() {
    // Check if it's already at the maximum size
    if (scaleFactor  < 1.5 ) {
		var oldscaleFactor = scaleFactor;
      // Increase the scale factor by
      scaleFactor += 0.15;
	   // Get the container that holds the SVG elements
	  var container = document.getElementById('svgContainer');
        
	   // Loop through all SVG child elements of the container
	  for (var i = 0; i < container.children.length; i++) {
	  	 var svgElement = container.children[i]; // Get the current SVG element          
	  	 if (svgElement.tagName.toLowerCase() === 'svg') {
	          // Get the current width and height from the SVG element
	         var currentWidth = parseFloat(svgElement.getAttribute('width'));
	         var currentHeight = parseFloat(svgElement.getAttribute('height'));
                
	                  // Calculate the new width and height based on the scale factor
	         var newWidth = currentWidth   * (scaleFactor/oldscaleFactor);
	         var newHeight = currentHeight  * (scaleFactor/oldscaleFactor);
                
	                  // Set the new width and height attributes of the SVG element
	         svgElement.setAttribute('width', newWidth.toString());
	         svgElement.setAttribute('height', newHeight.toString());
				 // the element's viewBox is not changed. 
	    }
	  }
   }
}
  
  function NormalType() {
		var oldscaleFactor = scaleFactor;
		scaleFactor = 1.0;
	   // Get the container that holds the SVG elements
	  var container = document.getElementById('svgContainer');
        
	   // Loop through all SVG child elements of the container
	  for (var i = 0; i < container.children.length; i++) {
	  	 var svgElement = container.children[i]; // Get the current SVG element          
	  	 if (svgElement.tagName.toLowerCase() === 'svg') {
	          // Get the current width and height from the SVG element
	         var currentWidth = parseFloat(svgElement.getAttribute('width'));
	         var currentHeight = parseFloat(svgElement.getAttribute('height'));
                
	                  // Calculate the new width and height based on the scale factor
	         var newWidth = currentWidth   * (scaleFactor/oldscaleFactor);
	         var newHeight = currentHeight  * (scaleFactor/oldscaleFactor);
                
	                  // Set the new width and height attributes of the SVG element
	         svgElement.setAttribute('width', newWidth.toString());
	         svgElement.setAttribute('height', newHeight.toString());
				 // the element's viewBox is not changed. 
	    }
	  }
  }

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 mousedown and used in mouseup
let lineX = 0;
let lineY = 0;
let lineWidth = 0;
let lineHeight = 0;
let activeline = 0;


function currentlinenumber() {
	    const lines = document.querySelectorAll('.line'); // Get all elements with class "line"
	    let maxId = -1; // Start with -1 so even 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); 
	}

svgContainer.addEventListener('mousedown', function(e) {
	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);
			// Remove the rectangles of class "selectedRectangle", which 
			// color the background of the selected term(s)
			document.querySelectorAll('.selectmenuitem').forEach(item => {
			    item.parentNode.removeChild(item); // Remove all the menu items too
			});
			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;
	let y = e.clientY - rect.top;  // Now these coordinates are relative to svgContainer
	activeline = currentlinenumber();   // should be active line number, but can't get that from here yet
	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('mousemove', function(e) {
        e.stopPropagation();
        e.preventDefault();
	    if (!isSelecting || !activeGraphBounds) return;
	     // prevent the browser from getting the mousemoves
		 // but this doesn't seem to work
	    
	    
	    let rect = svgContainer.getBoundingClientRect();
	    let x = e.clientX - rect.left;
	    let y = e.clientY - rect.top;

	    // 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('mouseup', 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);
        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]. 
		param = "[" + [selectedX, selectedY,selectedWidth,selectedHeight,lineX,lineY,lineWidth,lineHeight,windowwidth,windowheight]+ "]"
	    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
{
	 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');
	
   // 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';
    });
    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>  
</body>
</html>


 

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