Sindbad~EG File Manager

Current Path : /home/beeson/public_html/WebMathXpert/Demos/ProblemLibraryDemo/backups/
Upload File :
Current File : //home/beeson/public_html/WebMathXpert/Demos/ProblemLibraryDemo/backups/GraphDoc-Jul12.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();
}
 
require("SendMessage.php");
$clientSocket = createClientSocket($serverAddress, $serverPort, $timeout);



// Handle  Ajax requests before emitting  HTML 
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{  $response = "nothing";
	if ( isset($_POST['graphTitleMovedParam'])) 
		{
			$param = $_POST['graphTitleMovedParam']; 
		    // Process the AJAX request
			$response = sendMessage($clientSocket,"graphTitleMoved",$param); 
   	   // We do not care what the response is as long as it is not false
		}  
 	else if ($response != "nothing")
    {    // $response is the response to the Ajax request
   		// echo($response);  // this will display an error message for the developer if an incorrect parameter was sent.
   		 exit; // Stop further processing, so the rest of the HTML isn't sent
    }
   
}
?>
<!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 Grapher</title>
    <style>
		body, html {
		    margin: 0;
		    padding: 0;
		    border: none;
		}
        /* Set a global font-family rule for all text elements. Only Times New Roman actually works well. */
        text {
            font-family: 'Times New Roman', 'STIX Two Math', 'Cambria Math', 'Latin Modern Math', 'TeX Gyre Termes Math';
        }
	    svg text {
	          font-family: 'Times New Roman';
	    }
		/* the following container with horizontal flow will hold the Toolbar and the svgContainer, 
		 so the svgContainer will come to the right of the Toolbar */
		.container {
		  display: flex;
		  align-items: flex-start;  /*  begin each column at the top  */
		  /* the first column contains the Toolbar, so this gets the Toolbar at the top.
		  position:relative; */
		  top = 0;
		  left = 0;
		}
		/* Define svgContainer div so it comes to the right of the Toolbar.
			We have to have either absolute or relative positioning here so that the SVG output of the Engine will be 
			interpreted relative to svgContainer.   If we use position:absolute,  then we must also specify left and top. 
			Using postion:relative allows flex layout in .container to place svgContainer to the 
			right of the Toolbar without hardcoding the width of the Toolbar.
		*/
			
		#svgContainer {
			position:relative; 
			z-index: 1;
			text-shadow: none;
		}
			
		#titleRect {
			position: absolute;
			cursor: move;
			border: none;
			background-color: transparent;
			text-shadow: none;
		} 
	
		[id^="draggableTitle"] { /* applies to draggableTitle0,  draggableTitle1, etc. */
			position: absolute;
			cursor: move;
			border: none;
			background-color: transparent;
			text-shadow: none;
			padding: 5px;
			color: black;
			top: 10px;
			left: 10px; /* Initial position */
			z-index: 2; /* Ensure it's above other elements */
		 }
 
		#selectionRectangle {
			position: absolute;
			border: 1px solid red;  
			pointer-events: none; /* Ignore this element during mouse events */
		}
		body {
			background-color:none;
		}
		.toolbar {
		    display: flex;
		    flex: 0 0; 
		    flex-direction: column; /* Make the contents flow vertically */
		    gap: 5px; /* Adjust the gap as needed */
		    align-items: flex-start; 
		    justify-content: flex-start; /* Align items to the top */ 
		     margin-top: 5px; /* Add a gap at the top */
		}
	

		.toolbar button {
			height: 17px; /* Adjust the height as needed */
		}

		/* Style for the modal */
		#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;
		}

		/* Style for the modal content */
		#modalContent {
			background: rgb(200,200,255);
			padding: 20px;
			border-radius: 5px;
			width: 50%;
			height: 50%;
			box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
		}
	 </style>
</head>


<?php

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

<?php

function decode($response,$fillcolor){
    // To save bandwidth we've compressed some SVG commands, now expand them
	// This only saves bandwidth between the Engine and the PHP code, not between the web server and browser,
	// but otherwise the 1 megabyte limit on messages between the Engine and PHP is broken, i.e., the length of 
	// messages needed to draw these graphs is more than 6 digits.   It's easier 
	// just to do this decoding than alter the basic Engine message mechanisms. 
	 
	    $pattern = '/<q (-?\d+) (-?\d+)>/';
	    return preg_replace_callback(
	        $pattern,
	        function ($matches) use ($fillcolor) { // Use "use" to inherit $fillcolor
	            $x = $matches[1] - 0.5;
	            $y = $matches[2] - 0.5;
	            return "<circle cx=\"{$x}\" cy=\"{$y}\" r=\"1\" style=\"fill:{$fillcolor};stroke:none;\" />\n";
	        },
	        $response
	    );
	}

?>


<?php
    if ($_SERVER["REQUEST_METHOD"] === "POST") 
    {   if(isset($_SESSION['width']))  
		 // in case width and height don't get set below, let's make sure they are set.
			$width = $windowWidth = $_SESSION['width'] ;
		if(isset($_SESSION['height']))
			$height =  $_SESSION['height'];
		$fillcolor = "rgb(128,128,255)"; 
		if(isset($_SESSION['toolbarwidth']))
		   {  $toolbarwidth = $_SESSION['toolbarwidth']; 
		      $graphwidth = $width - $toolbarwidth; 
		   }		
		if (isset($_POST['problemnumberField']))
			{
				$problemnumber = $_POST["problemnumberField"];
				$topicnumber =  $_POST["topicField"];
				$sender = "GetProblem";
				$language = $_POST["language"];
				$windowWidth = $_SESSION['width'] = intval($_POST["widthField"]);  // width of the browser window 
				$toolbarwidth = $_SESSION['toolbarwidth'] = intval($_POST["toolbarwidthField"]); 
				$width = $windowWidth; 
				//  echo("width = $width and toolbarwith = $toolbarwidth");
				$height = $_SESSION['height'] = intval($_POST["heightField"]); // height of the browser window
				$_SESSION['languagenumber'] = $language;
				$_SESSION['width'] = $width;
				$_SESSION['height'] = $height;
				$_SESSION['topicnumber'] = $topicnumber;
			}
		if (isset($_POST["widthField2"]))  // 'graphButton_x'  doesn't work!
			{
				$sender = "graphButton";
				$windoWwidth = $_SESSION['width'] = $width = intval($_POST["widthField2"]);
				$height = $_SESSION['height'] = intval($_POST["heightField2"]);  
				$width = $windowWidth - $_SESSION['toolbarwidthField'];			
			}
		if (isset($_POST['language2']))
		{
			$sender = "setLanguage";
			$language = $_POST['language2'];
		}
		if (isset($_POST['action'])) {
		    $sender = $_POST['action'];
		    // Now, $sender should contain something like "parameterplus0"
		}
		if (isset($_POST['horizontalzoomout_x']))
		{
			$sender = "horizontalzoomout";
		}
		if (isset($_POST['horizontalzoomin_x']))
		{
			$sender = "horizontalzoomin";
		}
		if (isset($_POST['verticalzoomout_x']))
		{
			$sender = "verticalzoomout";
		}
		if (isset($_POST['verticalzoomin_x']))
		{
			$sender = "verticalzoomin";
		}  
		if ( isset($_POST['graphMovedParam'])) 
		{
			$param = $_POST['graphMovedParam']; 
			$sender = "graphMoved";
		} 
		if (isset($_POST['selectedRectangleField']) && !empty($_POST['selectedRectangleField'])) 
		{
		    $selectedRectangleParameter = $_POST['selectedRectangleField'];
		    $sender = "draw";
		}
		$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(isset($_SESSION['width']))
				$width =  $_SESSION['width'] ;
			if(isset($_SESSION['height']))
				$height =  $_SESSION['height']; 
			$graphwidth = $width-$toolbarwidth;  
			//  echo("$width  $toolbarwidth  $graphwidth");
			$fillcolor = "rgb(128,128,255)";
			if ($result) 
			{   if($sender=="GetProblem")
				{	$param = $topicnumber . "+" . $problemnumber . "+" . $language . "+" . $graphwidth . "+" . $height;
					$response = sendMessage($clientSocket, "initGraphDocFromLibrary", $param);
					// echo("topic number is $topicnumber");
					// if ($topicnumber == 21 || $topicnumber == 26) { // MC_SET or graph_relation
					if(strstr("<q",$response))
					{
						$response = decode($response,$fillcolor);
					}
				}
				else if ($sender == "graphButton")
				{
					$param =  $graphwidth  . "+" . $height;
					$response = sendMessage($clientSocket,"graphButton", $param);
				}
				else if($sender == "setLanguage")
				{ 
					$param = $language;
					$_SESSION['languagenumber'] = $language;
				}
				else if( str_starts_with($sender, "parameterplus"))
				{   
					$index = $sender[13];   // the character after parameterplus
					$param = $graphwidth . "+" . $height. "+" . $index;
					$response = sendMessage($clientSocket,"incrementParameter", $param);
				}
				else if( str_starts_with($sender, "parameterminus"))
				{
					
					$index = $sender[14];   // the character after parameterminus
					$param = $graphwidth . "+" . $height. "+" . $index;
					$response = sendMessage($clientSocket,"decrementParameter", $param);
				} 
				else if ($sender == "draw")
				{
					$param = $selectedRectangleParameter;
					$response = sendMessage($clientSocket,"selectedRectangleGraph", $param);
				} 
			   else if ($sender == "graphMoved") 
				{
					$response = sendMessage($clientSocket,"graphMoved", $param);
				}
				else
				{
					if(!is_string($sender) || strlen($sender) == 0)
					   $response = false;
					else
					{
						$param =  $graphwidth  . "+" . $height;
						$response = sendMessage($clientSocket,$sender,$param);
				    }
				}
				if ($response === false || $response == null)
				{
					$errcode = socket_last_error($socket);
					$message = socket_strerror($errcode);
					echo "Socket_read error: $message<br>";
				} 
				else if (strpos($response, 'ERROR:') === 0) 
				{	// It's an error message
					$errorMessage = substr($response, strlen('ERROR:'));
					echo "<div class='error'>Error: {$errorMessage}</div>";
				}
				else 
				{
					// The response consists of SVG, to redraw the whole window.   It has to go into svgContainer.
					if(strstr($response,"<q "))
						$response = decode($response,$fillcolor);
			
					?>
						
					  <div class="container" id="wholeWindow"> 
							<?php include 'toolbar.php'; ?>
							<div id="svgContainer">
								<div id="draggableTitle0" style="position: absolute; cursor: move; border: none; background-color: transparent; padding: 5px; left:10px; top:10px"></div>  
								<div id="draggableTitle1" style="position: absolute; cursor: move; border: none; background-color: transparent; padding: 5px; left:10px; top:10px""> </div> 
								<div id="draggableTitle2" style="position: absolute; cursor: move; border: none; background-color: transparent; padding: 5px; left:10px; top:10px"></div>  
								<div id="draggableTitle3" style="position: absolute; cursor: move; border: none; background-color: transparent; padding: 5px; left:10px; top:10px""> </div>  
								<div id="draggableTitle4" style="position: absolute; cursor: move; border: none; background-color: transparent; padding: 5px; left:10px; top:10px"></div>  
								<div id="draggableTitle5" style="position: absolute; cursor: move; border: none; background-color: transparent; padding: 5px; left:10px; top:10px""> </div> 
								<svg id="graphSVG" width="<?php echo $graphwidth; ?>" height="<?php echo $height; ?>" top = "0px ?>"; xmlns="http://www.w3.org/2000/svg"> 
								<?php echo $response; ?>
  							  </svg>
							</div>   <!--  This closes the svgContainer div -->
						  </div>    <!--  This closes the container div -->
					<?php
				}
				socket_close($socket);  // because server has already closed it
			}  // close if($result)
			else 
			{
				echo "Failed to connect to the C program: " . socket_strerror(socket_last_error()) . "<br>";
			}
		}
	}
?>

<script>  

   let mouseScroll =  true ;   // false means mouse is for rectangle selection; true for scrolling the graph  
   //  ultimately the Hand button will toggle mouseScroll  
   let PointSlopeOn = false;  // this will be toggled by the PointSlope button

	// Make the draggableTitle elements draggable (always, this can't be turned on or off)
	dragElement(document.getElementById("draggableTitle0"));
   dragElement(document.getElementById("draggableTitle1"));  
   function dragElement(elmnt) {
		  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
		  if (document.getElementById(elmnt.id)) 
		  {
		    // If present, the header is where you move the element from:
		    document.getElementById(elmnt.id).onmousedown = dragMouseDown;
		  } 
		  else 
		  {
		    // Otherwise, move the DIV from anywhere inside the DIV:
		    elmnt.onpointerdown = dragMouseDown;
		  }

		  function dragMouseDown(e) {
		    e = e || window.event;
		    e.preventDefault();    // Prevents default action (e.g., text selection)
		    e.stopPropagation();   // Prevents event from bubbling up to parent elements
		    // Get the mouse cursor position at startup:
		    pos3 = e.clientX;
		    pos4 = e.clientY;
		    document.onmouseup = closeDragElement;
		    // Call a function whenever the cursor moves:
		    document.onpointermove = elementDrag;
		    isSelecting = false;   // prevent selection rectangle
		    console.log("set isSelecting to false"); 
		  }

		  function elementDrag(e) {
		    e = e || window.event;
		    e.preventDefault();    // Prevents default action (e.g., text selection)
		    e.stopPropagation();   // Prevents event from bubbling up to parent elements
		    // Calculate the new cursor position:
		    pos1 = pos3 - e.clientX;
		    pos2 = pos4 - e.clientY;
		    pos3 = e.clientX;
		    pos4 = e.clientY;
		    // Set the element's new position:
		    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
		    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; 
		    console.log(elmnt.style.left);
		  }

		  function closeDragElement(e) {
		      // Stop moving when mouse button is released:
		      document.onpointerup = null;
		      document.onpointermove = null; 
		      isSelecting = true;   // it was set to false on mousedown

		      // Get the element's ID and extract the index
		      var id = elmnt.id;
		      var index = id.match(/\d+$/)[0];  // Extract the number at the end of the ID

		      // Get the element's current position and size
		      var rect = elmnt.getBoundingClientRect();
		      var x1 = rect.x-60;
		      var y1 = rect.y;
		      var x2 = rect.right-60;
		      var y2 = rect.bottom; 
            console.log(rect,x1,y1,x2,y2);
		      // Form the string in the required format
		      var param = `[${index},${x1},${y1},${x2},${y2}]`; 
		      // Prepare the data string with the required parameter name
		      var data = `graphTitleMovedParam=${encodeURIComponent(param)}`;
		      // 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");
		      console.log('Data being sent:', data);
		      xhr.send(data); 
		  }  
	} 
	    

		// Make graphs scrollable  if mouseScroll
	
		// scrollElement(document.getElementById("scrollable0"));  
		// following line does that for all elements of class "scrollable"  
		   if(mouseScroll)	
				document.querySelectorAll('.scrollable').forEach(function(element) {
		    	scrollElement(element);
			 	});
		

		function scrollElement(elmnt) {
		    var x1 = 0, y1 = 0, x0 = 0, y0 = 0;

		    if (elmnt) {
		        elmnt.onpointerdown = scrollMouseDown;
		    }

		    function scrollMouseDown(e) {
		        e = e || window.event;
		        e.preventDefault();    // Prevents default action (e.g., text selection)
		        e.stopPropagation();   // Prevents event from bubbling up to parent elements
		        // Get the mouse cursor position at startup:
		        x1 = e.clientX;
		        y1 = e.clientY;
		        x0 = x1;
		        y0 = y1;
		        document.onpointerup = closeScrollElement;
		        document.onpointermove = elementScroll; 
				  const transform = `translate(0,0)`;
				  elmnt.setAttribute('transform', transform); 
		        isSelecting = false;   // prevent selection rectangle
		        console.log("set isSelecting to false");
		    }

		    function elementScroll(e) {
		        e = e || window.event;
		        e.preventDefault();    // Prevents default action (e.g., text selection)
		        e.stopPropagation();   // Prevents event from bubbling up to parent elements
		        // Calculate the new cursor position:
		        var dx = e.clientX - x0;
		        var dy = e.clientY - y0;
				  const transform = `translate(${dx}, ${dy})`;
				  elmnt.setAttribute('transform', transform); 
				  // console.log(transform);
		    }

		    function closeScrollElement(e) {
		        // Stop scrolling when mouse button is released:
		        document.onpointerup = null;
		        document.onpointermove = null; 
  
		        // Get the element's ID and extract the index
		        var id = elmnt.id;
		        var index = id.match(/\d+$/)[0];  // Extract the number at the end of the ID 

		        // How much did it scroll?
		        let deltax = e.clientX - x0;
		        let deltay = e.clientY - y0;  
		        if(deltax == 0 && deltay == 0) 
					  return;  // don't bother telling the Engine nothing happened.

		        // Form the parameter in the required format
		        var param = `[${index},${deltax},${deltay}]`; 
		        // Prepare the data string with the required parameter name
		   
		        // submit a hidden form so param will become $_POST['graphMovedParam'] 
				  let form = document.createElement('form');
				              form.method = 'POST';
				              form.action = ''; // Set the action to the desired URL

				              // Create a hidden input to hold the param value
				              let input = document.createElement('input');
				              input.type = 'hidden';
				              input.name = 'graphMovedParam';
				              input.value = param;

				              // Append the input to the form
				              form.appendChild(input);

				              // Append the form to the body
				              document.body.appendChild(form);
                          console.log("submitting", param);
				              // Submit the form
				              form.submit();
		       
		       
		        
		    }
		}
	   
	
	function moveSvgElementToContainer(svgElementId, destinationContainerId) {
	    var svgElement = document.getElementById(svgElementId);
	    var destinationContainer = document.getElementById(destinationContainerId);

	    if (svgElement && destinationContainer) {
	        destinationContainer.style.position = 'absolute';
	        // destinationContainer.style.left = svgElement.style.left;  
	        // This should be done by the calling function
	        // destinationContainer.style.top = svgElement.style.top;
			var svgRect = svgElement.getBoundingClientRect();
	        destinationContainer.style.width = svgRect.width + 'px';
            destinationContainer.style.height = svgRect.height + 'px';

	        // Now move the SVG element to the destination container
	        destinationContainer.appendChild(svgElement);

	        // Since the SVG is now positioned relative to its new container, reset its position
	        svgElement.style.left = '0px';
	        svgElement.style.top = '0px';
	    }  
	   else 
		{    
		  if(svgElement)
			  {
	          console.error('destination container not found');
		     }
			else
			  {
				 console.error('SVG element not found'); 
				 console.error(svgElementId);
			  }
	    }
		
	} 
  
function toggleMouseScroll(){   
	if (mouseScroll)  
		{	mouseScroll = false;  
			document.querySelectorAll('.scrollable').forEach(function(element) {
			element.onmousedown = null; 
			element.onpointerdown = null;
 			});  
 		}
	else 
		{	mouseScroll = true; 
			document.querySelectorAll('.scrollable').forEach(function(element) {
				scrollElement(element);
	 		}); 
		}
	console.log("mouseScroll is", mouseScroll); 
}
 
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 showSingularities() {
	    // Create a popup window
	    var popupWindow = window.open('', 'Singularities', '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 "singularity"
	    var singularities = document.querySelectorAll('.singularity');
	    singularities.forEach(function (t) {
	        var clonedSingularity = t.cloneNode(true);

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

	        // Append the cloned assumption to the div
	        div.appendChild(clonedSingularity);
	    });
	}
	
	function showJumps() {
	    // Create a popup window
	    var popupWindow = window.open('', 'Singularities', '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 "jump"
	    var jumps = document.querySelectorAll('.jump');
	    jumps.forEach(function (t) {
	        var clonedJump = t.cloneNode(true);

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

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

function svgToImageInput(svgElementId, inputElementId) {
	var svgElement = document.getElementById(svgElementId);
    var inputElement = document.getElementById(inputElementId);

	// Serialize SVG to string
	var serializer = new XMLSerializer();
	var svgString = serializer.serializeToString(svgElement);

	// Encode SVG string in Base64
	var svgBase64 = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgString)));

	// Set the encoded SVG as the source for the input image
	inputElement.setAttribute('src', svgBase64);
}


// Ensure this script runs after the DOM is fully loaded
document.addEventListener('DOMContentLoaded', function() { 
    let title0 = document.getElementById('title0');
     
    if (title0) {
        let left = title0.style.left; 
        let top = title0.style.top; 
        // now (left,top) is where we want draggableTitle0 to be 

        let draggableTitle0 = document.getElementById("draggableTitle0");
        if (draggableTitle0) {
            draggableTitle0.style.left = left;
            draggableTitle0.style.top = top;

            moveSvgElementToContainer('title0', 'draggableTitle0'); 
            moveSvgElementToContainer('titleRect0', 'draggableTitle0'); 
            // that changes title0.left and title0.top to 0 
        }
    }

    // Now do the same for title1 through title5 if they exist
    for (let k = 1; k < 6; k++) {
        let id = "title" + k;
        let title = document.getElementById(id);
        if (title === null) 
           {  //  console.log("breaking because title doesn't exist");
              break;  
             // This works with === but not with ==, which I think is a Javascript bug
			  }
        let titleRectId = "titleRect" + k;
        let titleRect = document.getElementById(titleRectId);     
        let draggableTitleId = "draggableTitle" + k;
        let draggableTitle = document.getElementById(draggableTitleId);   
	     let left = title.style.left; 
	     let top = title.style.top; 
        draggableTitle.style.left = left;
        draggableTitle.style.top = top;
  
        if (draggableTitle) {
            moveSvgElementToContainer(id, draggableTitleId);
            moveSvgElementToContainer(titleRectId, draggableTitleId);
        }
    }
});


let selectionMade = false;  // set it to true on mouse_up when a rectangle is selected.
let selectionMode = "centered";  // "corner"  // the alternative is "centered"

document.addEventListener('DOMContentLoaded', function() {
	
	
	document.getElementById('draw').addEventListener('click', function(event) {
	    // Construct the selected rectangle string
		// The form will submit automatically as this button is of type image/input inside the form.  Therefore:
		event.preventDefault(); // Prevent the default form submission
		console.log("Draw button was clicked");
		console.log("Value of selectionMade = ");
		console.log(selectionMade);
	    if (selectionMade) { // Check if a selection has been made
			let windowwidth = <?php echo($_SESSION['width']);?>;
			let windowheight = <?php echo($_SESSION['height']);?>;
			let toolbarwidth = <?php echo($toolbarwidth);?>;
			// console.log(toolbarwidthpx);
			let selectedRectangleValue = "[" + [whichgraph, parseInt(selectedX), parseInt(selectedY), parseInt(selectedWidth), parseInt(selectedHeight),parseInt(toolbarwidth), windowwidth, windowheight].join(',') + "]"; 
			// coordinate parameters are expected by the Engine to be integers either all in pixels or all without units.  Here, all are withouit units, as shown by console.log.  
			// console.log(selectedRectangleValue)
			// return;  // use this to see the console.log output
			document.getElementById('selectedRectangleField').value = selectedRectangleValue;
		   // Now submit it.
		   selectionMade = false;  // we're done with it
		   document.getElementById('myForm').submit();
	   }  // end if
	  }  //  end of the function
    );   //  end of addEventListener 
	
	
    // Step 1: Identify all SVG elements of class "param"
	const svgs = document.querySelectorAll('svg.param');

	// Step 2 & 3: Process each SVG and create corresponding button groups
	svgs.forEach((svg, index) => {
        // Convert SVG to Data URL
        const xml = new XMLSerializer().serializeToString(svg);
        const svg64 = btoa(unescape(encodeURIComponent(xml)));
        const svgDataUrl = 'data:image/svg+xml;base64,' + svg64;
        svg.style.display = "none";   // Hide the original SVG to prevent clutter.
	   // svg.parentNode.removeChild(svg);

        // Create button group container with specified styles
        const buttonGroup = document.createElement('div');
        buttonGroup.className = 'button-group';
        buttonGroup.style.display = 'flex';
        buttonGroup.style.flexDirection = 'row'; 
        buttonGroup.style.alignItems = 'center'; 
        
        // Create the main button with SVG as the image and specified styles
        const inputImage = document.createElement('input');
        inputImage.type = 'image';
        inputImage.src = svgDataUrl;
        inputImage.alt = `Parameter ${index}`;
        inputImage.style.width = '16px';
        inputImage.style.height = '16px';
        // Apply background color and text color here if the button supports text

        // Container for the + and - buttons, aligned vertically
        const buttonsContainer = document.createElement('div');
        buttonsContainer.style.display = 'flex';
        buttonsContainer.style.flexDirection = 'column'; 
        buttonsContainer.style.alignItems = 'center'; 

        // Create the "+" button with specified styles for background and text color
        const inputPlus = document.createElement('button');
        inputPlus.innerHTML = "+";
        inputPlus.style.cssText = 'height: 8px; width: 12px;';

        // Create the "-" button with specified styles for background and text color
        const inputMinus = document.createElement('button');
        inputMinus.innerHTML = "-";
        inputMinus.style.cssText = 'height: 8px; width: 12px;';

        // Event listeners for "+" and "-" buttons to submit the form
        inputPlus.addEventListener('click', function() {
            submitFormWithAction('parameterplus' + index);
        });
        inputMinus.addEventListener('click', function() {
            submitFormWithAction('parameterminus' + index);
        });
		
        // Append + and - buttons to their container
        buttonsContainer.appendChild(inputPlus);
        buttonsContainer.appendChild(inputMinus);

        // Append elements to the button group
        buttonGroup.appendChild(inputImage); // Main button
        buttonGroup.appendChild(buttonsContainer); // Container with + and - buttons

        // Append the button group to the target container
        document.getElementById('toolbar').appendChild(buttonGroup);
    });
});

function submitFormWithAction(actionValue) {
    const form = document.getElementById('myForm');
    const actionInput = document.getElementById('formAction');
    actionInput.value = actionValue;
    form.submit();
}

</script>

<script>
	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
	//  svgContainer.appendChild(selectionRectangle);  
	//  This is now done on mousedown, when selection starts.  If it's done here,
	//  it makes a visible black dot below the graph and creates scroll bars. 
	let selectedX = 0; 
	selectionRectangle.style.left = 0+"px";
	let selectedY = 0;
	selectionRectangle.style.top = 0+"px";
	let selectedWidth = parseInt(selectionRectangle.style.width,10);
	let selectedHeight = parseInt(selectionRectangle.style.height,10);
	let startX = 0;
	let startY = 0;
	let initialX = 0;
	let initialY = 0;
	let isScrolling = false;
	let isSelecting = false;
	let activeGraphBounds = null;
	let whichgraph = 0; 
 
 const svg0 = document.getElementById('graph0');


 function startDrag(e) {
     if (!isScrolling) 
        return;
     e.preventDefault();
     startX = e.clientX || e.touches[0].clientX;
     startY = e.clientY || e.touches[0].clientY;
     initialX = parseFloat(svg0.style.left) || 0;
     initialY = parseFloat(svg0.style.top) || 0;
     console.log("start drag", initialX, initialY);
 }

 function drag(e) {
     if (!isScrolling) return;
     e.preventDefault();
     const deltaX = e.clientX  - startX;
     const deltaY = e.clientY - startY;
     svg0.style.left = `${initialX + deltaX}px`;
     svg0.style.top = `${initialY + deltaY}px`;  
     console.log(svg0.style.left,svg0.style.position);
 }

 function endDrag(e) {
     if (!isScrolling) return;
     e.preventDefault();
     isScrolling = false;
     document.removeEventListener('mousemove', drag);
     document.removeEventListener('mouseup', endDrag); 
     console.log("end drag");
 }

 
	svgContainer.addEventListener('mousedown', function(e) {
		selectionMade = false;
	    if (!svgContainer.contains(selectionRectangle)) 
	          svgContainer.appendChild(selectionRectangle);
	    let graphs = document.querySelectorAll('.graph');
	    let rect = svgContainer.getBoundingClientRect();
	    let x = e.clientX - rect.left;
	    let y = e.clientY - rect.top;
        let k = 0;
	    for (let graph of graphs) {
	        // Use the manually defined bounds instead of getBoundingClientRect()
	        let graphX = parseInt(graph.getAttribute("left"), 10);
	        let graphY = parseInt(graph.getAttribute("top"), 10);
	        let graphWidth = parseInt(graph.getAttribute("mywidth"), 10);
	        let graphHeight = parseInt(graph.getAttribute("myheight"), 10);
			console.log(graphX, graphY, graphWidth, graphHeight);
	        if (x >= graphX && x <= graphX + graphWidth && y >= graphY && y <= graphY + graphHeight && mouseScroll == false)  
	        {
	            isSelecting = true; 
	            console.log("set isSelecting to true because svgContainer got mousedown");
	            startX = x;
	            startY = y;
	            activeGraphBounds = { left: graphX, top: graphY, right: graphX + graphWidth, bottom: graphY + graphHeight };
	            updateSelectionRectangle(x, y, 0, 0);
					whichgraph = k;
	            break;
	        } 
	        k=k+1;
	    } 
		if (mouseScroll) 
			{ isScrolling = true; 
			  startDrag(e);
			}
	});   
	
 
	svgContainer.addEventListener('mousemove', function(e) {
		if (!isSelecting || !activeGraphBounds)  
			return; 
	   e.preventDefault();    // Prevents default action (e.g., text selection)
	   e.stopPropagation();   // Prevents event from bubbling up to parent elements
		let rect = svgContainer.getBoundingClientRect();
		let x = e.clientX - rect.left;
		let y = e.clientY - rect.top;

		// Constrain the selection or the scroll 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);
		if(selectionMode == "centered")
			{ 
				width *= 2;
				height *= 2;
			}

		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;
		if (mouseScroll == false)
			updateSelectionRectangle(newX, newY, width, height); 
		else if (isScrolling)
			{  
				drag(e); 
			}
			
	});

	svgContainer.addEventListener('mouseup', function(e) {
	    if (!isSelecting) return;
	    isSelecting = false;
	    activeGraphBounds = null; // Reset the active graph bounds 
	    if(mouseScroll== false) 
			 {
			    // The final selected rectangle is available here
		        selectedX = selectionRectangle.style.left;
		        selectedY = selectionRectangle.style.top;
		        selectedWidth = selectionRectangle.style.width;
		        selectedHeight = selectionRectangle.style.height;
				  selectionMade = true; 
				  console.log("on mouse up, whichgraph and selected rectangle:");
			     console.log(whichgraph,selectedX,selectedY,selectedWidth,selectedHeight); 
			} 
		else 
		   {  
			  endDrag(e);
		   }
	});

	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';
	}
</script>

			
</body>
</html>


 

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