Current location: Hot Scripts Forums » General Web Coding » JavaScript » [SOLVED] delay on html element properties?


[SOLVED] delay on html element properties?

Reply
  #1 (permalink)  
Old 05-03-08, 05:40 AM
UnrealEd's Avatar
UnrealEd UnrealEd is offline
Community Liaison
 
Join Date: May 2005
Location: Antwerp, Belgium
Posts: 3,165
Thanks: 4
Thanked 25 Times in 25 Posts
[SOLVED] delay on html element properties?

Yesterday, I wrote a small javascript that kind of emulates a cmd line tool. Basically what it does is grab the key that was pressed on the keyboard, and outputs it to a div (not a textarea). Whenever a user hits the <enter> key on his keyboard, a request is sent to a php page which will than process the entered data (at this very moment, it only returns some unimportant text).

This is all working fine, at least in IE6 (my mom's laptop only has IE6, and my pc is broken), except that I'm facing one small problem: whenever the data exceeds the height of the div, I want the div to scroll down. After some testing I found that I could use the scrollHeight and screenHeight properties of the div.

Now the actual problem: it is all working, except the scrollHeight never contains the correct height. When the user hits the <enter> key, and when php has returned the text, my javascript will add that text to the div.
The lineheight of 1 textline is 12px.
When I check the scrollHeight of the div before I add the text, it says 16 (2px padding + 1 line of text).
When I check it after I added the text, through javascript, to the div, it says 28 (16px + 1 line of text). However: I did add 2 lines of text to the div. For some reason it does not recognize that second line.

Here's an example output before and after pressing the <enter> key:
before:
Code:
>>>
after:
Code:
>>> 
>>> Using this examples root directory: C:\Mark\PP3E-cd\Examples
Everything Ok?
As you can see the srollHeight property of the div should clearly state 40px, instead of 28.

Now when I now hit the <enter> key (so it would send a new request to the php page), the scrollHeight property does contain the correct value of 40px.

Is there any reason why the scrollHeight property isn't updated immediately?

I'm facing a similar problem as well when I try to use a workaround for that problem.
The text that needs to be displayed is returned as XML, and each line is stored in a separate node. I simply count the number of nodes, and then multiply it by 12 to get the actual height of the new text. I thought this should work, but it doesn't: as you can see in the proceed function of my code, it calls the proceedWithRequests function which will send the request to the php page. When it receives the text, it will process it and then it will count the number of lines that are added to the div. It stores them in the global variable newLines.
If I alert the newLines variable inside the proceedWithRequests function, it displays the correct value, but if I alert it after the proceedWithRequests in the proceed function, it always says 0.

Here's the code I'm using this very moment:
The HTML and javascript page:
Javascript Code:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2. "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  6. <title>Untitled Document</title>
  7. <script language="javascript" type="text/javascript">
  8. // <![CDATA[
  9.  
  10. // Stores specific hotKeyEvents. Certain keys need to be assigned to a different function
  11. // rather than the function that simply outputs the data to the cmdLineDiv div.
  12. // For instance the <enter> key also needs to continue the requests, as well as starting
  13. // a new line
  14. var hotKeyEvents = new Array();
  15. hotKeyEvents[10] = proceed;
  16. hotKeyEvents[13] = proceed;
  17. hotKeyEvents[127] = removeInputIfNecessary;
  18. // De page that need to be accessed via AJAX for processing the input of the cmd
  19. // line
  20. var ajaxRequestPage = 'ajax_install_test_div.php';
  21. // Defines the starting characters of a new cmd line (cf. C:\ on a windows cmd line)
  22. var CMDNL = '>>> ';
  23. // Contains the height of 1 line of text in the cmd (in px)
  24. var LINE_HEIGHT = 12;
  25. // Contains the height of the cmd itself (in px)
  26. var CMD_DIV_HEIGHT = 250;
  27. // contains the maximum amount of lines that can be displayed without having to use
  28. // scrollbars
  29. var MAX_CMD_LINES = Math.round(CMD_DIV_HEIGHT / LINE_HEIGHT);
  30. // When set to true, an additional textarea will be outputted at the bottom of the screen
  31. // with some debug information
  32. var debug = false;
  33.  
  34. // Contains a reference to the cmdLineDiv div in the HTML document
  35. var cmdLineDiv = null;
  36. // Contains the first occurence (backwards) that need to be found so that no contents
  37. // gets deleted after that point (sounds crazy, but is actually very logical)
  38. // In cmd on Windows, for instance, you can't delete the "C:\ " character at the beginning
  39. // of each line. The prevent a user from deleting these lines here, I had to make a copy
  40. // of the string that can't be deleted (">>> " in this case, or when a question is asked)
  41. var noEditLine = null;
  42. // Contains the XMLHttpRequest object in case XMLHttpRequest is available, otherwise
  43. // an ActiveXObject
  44. var ajaxRequestObject = null;
  45. // Contains a question that need to be answered. This question was send from the
  46. // ajaxRequestPage
  47. var cmdQuestion = null;
  48. // Contains the answer, filled in by the user, to the question last asked
  49. var cmdAnswer = null;
  50.  
  51. var newLines = 0;
  52.  
  53. /**
  54. * This function is called whenever a key is pressed inside the cmdLineDiv div.
  55. * It will check the key pressed, and then decides what to do with the event. By
  56. * default it will simply display the character in the cmdLineDiv div, unless a
  57. * hotKeyEvent was stored in the hotKeyEvents Array
  58. *
  59. * @param object An event object containing all information about the event
  60. */
  61. function onKeyPressEvent (event) {
  62.     event = event? event : (window.event? window.event : null);
  63.     if (event != null) {
  64.         var charCode = event.charCode? event.charCode : (event.which? event.which : event.keyCode);
  65.         if (debug) alertT (charCode + " = '" + String.fromCharCode(charCode) + "'");
  66.         if (charCode in hotKeyEvents)
  67.             hotKeyEvents[charCode]();
  68.         else if (charCode > 31 && charCode < 127)
  69.             insertChar (charCode);
  70.         else if (charCode > 160 && charCode <255)
  71.             insertHtmlChar (charCode);
  72.     }   
  73. }
  74.  
  75. /**
  76. * Adds HTML text to the cmdLineDiv.
  77. * It will first remove the fake cursor, otherwise an unecessary underscore will
  78. * be placed on the cmdLineDiv div as well
  79. *
  80. * @param string The text that need to be displayed to the user on the cmdLineDiv div
  81. */
  82. function addHtmlText (text) {
  83.     removeCursor ();
  84.     cmdLineDiv.innerHTML += text;
  85. }
  86.  
  87. /**
  88. * This function is called whenever te <enter> key was pressed on your keyboard
  89. * If a question was asked during the previous cmd output, the answer is searched
  90. * for first. Next it will call the proceedWithRequests function to continue sending
  91. * requests to the ajaxRequestPage
  92. */
  93. function proceed () {
  94.     if (debug) alertT ("proceed:");
  95.     if (cmdQuestion != null) {
  96.         removeCursor ();
  97.         cmdAnswer = cmdLineDiv.innerHTML.substring (cmdLineDiv.innerHTML.lastIndexOf (cmdQuestion) + cmdQuestion.length + 1);
  98.         cmdAnswer = (cmdAnswer == "" || cmdAnswer == " ")? null : cmdAnswer;
  99.         if (debug) alertT ("\tcmdAnswer: " + cmdAnswer);
  100.     }
  101.     //alert (cmdLineDiv.scrollHeight + " - " + cmdLineDiv.scrollTop);
  102.     proceedWithRequests ();
  103.     alertT (newLines);
  104.     alertT ("scrollH - scrollT = " + cmdLineDiv.scrollHeight + " - " + cmdLineDiv.scrollTop);
  105.     addHtmlText ("<br />\r\n" + CMDNL);
  106.     noEditLine = CMDNL;
  107.     var toScroll = Math.round (cmdLineDiv.scrollHeight / LINE_HEIGHT);
  108.     alertT ("toScroll no round: " + parseFloat(cmdLineDiv.scrollHeight / LINE_HEIGHT));
  109.     alertT ("scrollH - toScroll - newLines = " + cmdLineDiv.scrollHeight + " - " + toScroll + " - " + newLines);
  110.     if (toScroll > MAX_CMD_LINES)
  111.         cmdLineDiv.scrollTop = (toScroll - MAX_CMD_LINES) * LINE_HEIGHT;
  112.     cmdLineDiv.focus();
  113.     cmdLineDiv.scrollHeight;
  114.     alertT ("scrollH - toScroll - newLines = " + cmdLineDiv.scrollHeight + " - " + toScroll + " - " + newLines);
  115. }
  116.  
  117. /**
  118. * Whenever the user hits the ctrl+backspace key combination on the keyboard
  119. * The text needs to be removed from the cmdLineDiv div. This function is called
  120. * everytime the user hits this combination, or keeps it down
  121. * Since I couldn't simply catch the backspace key-press, I had to use the
  122. * ctrl+backspace key combination
  123. */
  124. function removeInputIfNecessary () {
  125.     removeCursor ();
  126.     var cur = cmdLineDiv.innerText.substring (cmdLineDiv.innerText.length - noEditLine.length)
  127.     if (debug) alertT ("removeInputIfNecessary: " + cur + " vs. " + noEditLine + " = " + (cur == noEditLine? 'no-change' : 'remove'));
  128.     if (cur != noEditLine) {
  129.         cmdLineDiv.innerHTML = cmdLineDiv.innerHTML.substring (0, cmdLineDiv.innerHTML.length-1);
  130.     }
  131. }
  132.  
  133. /**
  134. * Inserts the character referring to the key that was pressed on your keyboard
  135. * into the cmdLineDiv div
  136. *
  137. * @param string The character code that refers to a certain character
  138. */
  139. function insertChar (char) {
  140.     if (debug) alertT ("insertChar: " + String.fromCharCode (char));
  141.     addHtmlText (String.fromCharCode (char));
  142. }
  143.  
  144. /**
  145. * When extended ASCII characters, such as ù, are typed, the HTML equivalent needs
  146. * to be inserted into the cmdLineDiv div.
  147. *
  148. * @param string The character code of a certain extended ASCII character. Eventually
  149. *            the &#-char-; string is inserted into the cmdLineDiv div
  150. */
  151. function insertHtmlChar (char) {
  152.     if (debug) alertT ("insertHtmlChar: " + String.fromCharCode(char));
  153.     addHtmlText ("&#" + parseInt (char) + ";");
  154. }
  155.  
  156. /**
  157. * This function is called to initiate all startup variables and functions
  158. */
  159. function __init__ () {
  160.     if (debug) createDebugOutputField ();
  161.     cmdLineDiv = document.getElementById('cmdLineDiv');
  162.     cmdLineDiv.focus();
  163.     noEditLine = CMDNL;
  164.     createAjaxObject ();
  165.     toggleCursor ();
  166. }
  167.  
  168. /**
  169. * This function makes a cursor flash inside the cmdLineDiv div.
  170. * It uses the setTimeout function that redirects to itself with an interval of
  171. * 0.5 seconds
  172. */
  173. function toggleCursor () {
  174.     if (cmdLineDiv.innerHTML.substring (cmdLineDiv.innerHTML.length-1) == '_')
  175.         cmdLineDiv.innerHTML = cmdLineDiv.innerHTML.substring (0, cmdLineDiv.innerHTML.length-1);
  176.     else
  177.         cmdLineDiv.innerHTML += '_';
  178.     setTimeout (toggleCursor, 500)
  179. }
  180.  
  181. /**
  182. * Removes the cursor from the cmdLineDiv div whenever text needs to be added to the div
  183. */
  184. function removeCursor () {
  185.     if (cmdLineDiv.innerHTML.substring (cmdLineDiv.innerHTML.length-1) == '_')
  186.         cmdLineDiv.innerHTML = cmdLineDiv.innerHTML.substring (0, cmdLineDiv.innerHTML.length-1);
  187. }
  188.  
  189. /**
  190. * Creates the XMLHttpRequest object or an ActiveXObject, depending on the browser
  191. */
  192. function createAjaxObject () {
  193.     if (window.XMLHttpRequest) {
  194.         ajaxRequestObject = new XMLHttpRequest();
  195.         return true;
  196.     } else if (window.ActiveXObject) {
  197.         var aVersions = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"];
  198.         for (var i=0; i<aVersions.length; i++) {
  199.             try {
  200.                 ajaxRequestObject = new ActiveXObject (aVersions[i]);
  201.                 return true;
  202.             } catch (e) {}
  203.         }
  204.     } else {
  205.         alertT("Your browser doesn't support AJAX, please switch to Opera, Netscape, Firefox or IE");
  206.         return false;
  207.     }
  208. }
  209.  
  210. /**
  211. * Keeps on sending requests to the ajaxRequestPage whenever the user hits the <enter>
  212. * key on his keyboard
  213. */
  214. function proceedWithRequests () {
  215.     if (ajaxRequestObject != null) {
  216.         if (debug) alertT ("proceedWithRequests:");
  217.         ajaxRequestObject.open ('POST', ajaxRequestPage);
  218.         ajaxRequestObject.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
  219.         ajaxRequestObject.onreadystatechange = function () {
  220.             if (ajaxRequestObject.readyState == 4 && ajaxRequestObject.status == 200) {
  221.                 var xml = ajaxRequestObject.responseXML;
  222.                 var status = parseInt(xml.getElementsByTagName ('status')[0].firstChild.nodeValue);
  223.                 if (debug) alertT ("\tstatus: " + status);
  224.                 if (status == 0) {
  225.                     var cmdText = new Array();
  226.                     var a = xml.getElementsByTagName ('cmdText')
  227.                     for (var i=0; i<a.length;i++)
  228.                         if (a[i].firstChild.nodeValue != "") cmdText.push (a[i].firstChild.nodeValue);
  229.                     try {
  230.                         cmdQuestion = xml.getElementsByTagName ('cmdQuestion')[0].firstChild.nodeValue;
  231.                     } catch (e) {
  232.                         cmdQuestion = null;
  233.                     }
  234.                     updateCmdLineDiv (cmdText, cmdQuestion);
  235.                     newLines = parseInt(cmdText.length + (cmdQuestion == null? 0 : 1));
  236.                     alertT("newLines in proceedWithRequests: " + newLines);
  237.                 } else {
  238.                     updateCmdLineDiv (new Array ('<span style="color:red">Error(' + status + '): The installation could not be completed</span>'), null);
  239.                     newLines = 1;
  240.                 }
  241.             } else {
  242.                 try {
  243.                     if (debug) alertT ("\tSomething went wrong during the ajax request:\n\tstatus: " + ajaxRequestObject.status + "\n\treadyState: " + ajaxRequestObject.readyState);
  244.                 } catch (e) {}
  245.                 newLines = 0;
  246.             }
  247.         };
  248.         if (cmdAnswer != null)
  249.             ajaxRequestObject.send ("sectionId=3&cmdAnwser=" + cmdAnswer);
  250.         else
  251.             ajaxRequestObject.send ("sectionId=1");
  252.     }
  253.     return 0;
  254. }
  255.  
  256. /**
  257. * Processes the list of text that needs to be added to the cmdLineDiv div
  258. */
  259. function updateCmdLineDiv (cmdText, cmdQuestion) {
  260.     if (debug) alertT ("updateCmdLineDiv: cmdText(length):" + cmdText.length + ";cmdQuestion:" + cmdQuestion);
  261.     for (var i=0; i<cmdText.length; i++) {
  262.         addHtmlText (cmdText[i] + "<br/>\r\n");
  263.     }
  264.     if (cmdQuestion != null) {
  265.         addHtmlText (CMDNL + cmdQuestion + " ");
  266.         noEditLine = cmdQuestion + " ";
  267.     } else {
  268.         addHtmlText (CMDNL);
  269.         noEditLine = CMDNL;
  270.     }
  271. }
  272.  
  273. /**
  274. * Creates the textarea in which the debug-output will be placed
  275. */
  276. function createDebugOutputField () {
  277.     var textarea = document.createElement ('textarea');
  278.     try {
  279.         textarea.className = 'debugField';
  280.         textarea.id = 'debugField';
  281.     } catch (e) {
  282.         textarea.setAttribute ('class', 'debugField');
  283.         textarea.setAttribute ('id', 'debugField');
  284.     }
  285.     document.body.appendChild (textarea);
  286. }
  287.  
  288. /**
  289. * A variant of the built-in alert function, except this one simply outputs the
  290. * text to the debug field
  291. */
  292. function alertT (text) {
  293.     document.getElementById ('debugField').value += text + '\n';
  294. }
  295. // ]]>
  296. </script>
  297. <style type="text/css" media="screen">
  298. /* <![CDATA[ */
  299. textarea.debugField {
  300.     width:90%;
  301.     height:150px;
  302. }
  303.  
  304. div.cmdLine {
  305.     border:2px solid #AAAAAA;
  306.     height:250px;
  307.     width:90%;
  308.     font-family:"Lucida Console";
  309.     font-size:12px;
  310.     color:rgb(192,192,192);
  311.     background-color:#000000;
  312.     overflow:auto;
  313.     padding:2px;
  314. }
  315. /* ]]> */
  316. </style>
  317. </head>
  318.  
  319. <body onload="__init__(); createDebugOutputField()">
  320. <h3>Even wat zever zetten</h3>
  321. <button id="installbtn" type="button">Install!</button><br/>
  322. <br/>
  323. <div class="cmdLine" id="cmdLineDiv" onkeypress="onKeyPressEvent(event)">>>> </div>
  324. </body>
  325. </html>
The PHP page:
PHP Code:

<?php

header
('Content-type: application/xml; charset=iso-8859-1');

$array = array(
        array(
'starting on win32''Using this is python executable: C:\Python24\Python.exe'),
        array(
'Using this examples root directory: C:\Mark\PP3E-cd\Examples'),
        array(
'PATH start:''C:\Windows\system32;...deleted...;C:\Program Files\PHP''PATH updated:',
                
'C:\Windows\system32;...deleted...;C:\Program Files\PHP;C:\Python24'),
        array(
'PYTHONPATH start:''C:\Mark\PP3E-cd\Examples;C:\Mark\PP2E-cd\Examples',
                
'Exists C:\Mark\PP3E-cd\Examples''PYTHONPATH unchanged'),
        array(
'Environment Configured'), 
        array(
'Spawning: C:\Mark\PP3E-cd\Examples\GUI\TextEditor.py',
            
'Spawning: C:\Mark\PP3E-cd\Examples\Calculator\calculator.py',
            
'Spawning: C:\Mark\PP3E-cd\Examples\PyDemos2.pyw',
            
'Spawning: C:\Mark\PP3E-cd\Examples\echoEnvironment.pyw')
        );

$questions = array('What\'s your name?''Everything Ok?''''''Hello?''');

if (isset(
$_POST['sectionId'])) {
    die(
'<xml><status>0</status><cmdText><![CDATA[' implode("]]></cmdText><cmdText><![CDATA["$array[$_POST['sectionId']]) . ']]></cmdText><cmdQuestion><![CDATA[' $questions[$_POST['sectionId']] . ']]></cmdQuestion></xml>');
}
die(
'<xml><status>1</status><cmdText></cmdText><cmdQuestion></cmdQuestion></xml>');
?>
__________________
"Good judgement comes from experience, and experience comes from bad judgement." - Fred Brooks

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiShare on FacebookShare on Stumble UponShare on Twitter
Reply With Quote
  #2 (permalink)  
Old 05-03-08, 06:17 PM
Vicious's Avatar
Vicious Vicious is offline
Community VIP
 
Join Date: Jan 2007
Location: Belgium
Posts: 584
Thanks: 0
Thanked 0 Times in 0 Posts
In proceedWithRequests, there is only 1 place where newLines is being reset to 0, and that's when the readystate is not 4 or the request state is not 200. But then you should have gotten an extra alert to inform you of that. Maybe you need to debug in that area ?

As for your problem with the scrollHeight, I can't think of anything right now. I should see it in action so I can use firebug on it
__________________
Jack Bauer makes Chuck Norris cry
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiShare on FacebookShare on Stumble UponShare on Twitter
Reply With Quote
  #3 (permalink)  
Old 05-04-08, 01:46 AM
job0107's Avatar
job0107 job0107 is offline
Community Liaison
 
Join Date: Dec 2006
Location: Tacoma, Washington USA
Posts: 3,454
Thanks: 0
Thanked 140 Times in 137 Posts
In the proceed() function you have this line:
Javascript Code:
  1. cmdLineDiv.scrollTop = (toScroll - MAX_CMD_LINES) * LINE_HEIGHT;

Change it to:
Javascript Code:
  1. cmdLineDiv.scrollTop = cmdLineDiv.scrollHeight;
__________________
Jerry Broughton
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiShare on FacebookShare on Stumble UponShare on Twitter
Reply With Quote
  #4 (permalink)  
Old 05-04-08, 04:57 AM
UnrealEd's Avatar
UnrealEd UnrealEd is offline
Community Liaison
 
Join Date: May 2005
Location: Antwerp, Belgium
Posts: 3,165
Thanks: 4
Thanked 25 Times in 25 Posts
Quote:
Originally Posted by Vicious View Post
In proceedWithRequests, there is only 1 place where newLines is being reset to 0, and that's when the readystate is not 4 or the request state is not 200. But then you should have gotten an extra alert to inform you of that. Maybe you need to debug in that area ?
I need to remove that section anyway: it will always alert some debug information when the readyState of the request changes; but the readyState changes about 4 times before it is set to 4.
I'll test it as soon as I can, and let you know

Quote:
Originally Posted by Vicious View Post
As for your problem with the scrollHeight, I can't think of anything right now. I should see it in action so I can use firebug on it
I'll try to place it online somewhere, but I'm afraid I'll have to make it work in Firefox first (what works in IE doesn't necessarily works in FF)

Quote:
Originally Posted by job0107 View Post
In the proceed() function you have this line:
Javascript Code:
  1. cmdLineDiv.scrollTop = (toScroll - MAX_CMD_LINES) * LINE_HEIGHT;
Change it to:
Javascript Code:
  1. cmdLineDiv.scrollTop = cmdLineDiv.scrollHeight;
This will have the same net effect on the crolling: scrollHeight doesn't contain the correct value after adding text to the div, so it will only scroll down 1 line.
__________________
"Good judgement comes from experience, and experience comes from bad judgement." - Fred Brooks

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiShare on FacebookShare on Stumble UponShare on Twitter
Reply With Quote
  #5 (permalink)  
Old 05-05-08, 12:22 AM
job0107's Avatar
job0107 job0107 is offline
Community Liaison
 
Join Date: Dec 2006
Location: Tacoma, Washington USA
Posts: 3,454
Thanks: 0
Thanked 140 Times in 137 Posts
Ok UnrealEd,
I believe I have a solution for you.
I took the scroll feature out of the proceed() function and put it in the toggleCursor() function.
This seems to give it enough time to update the scroll position.
I have tested it in both FireFox and IE.

Javascript Code:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2. "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  6. <title>Untitled Document</title>
  7. <script language="javascript" type="text/javascript">
  8. // <![CDATA[
  9.  
  10. // Stores specific hotKeyEvents. Certain keys need to be assigned to a different function
  11. // rather than the function that simply outputs the data to the cmdLineDiv div.
  12. // For instance the <enter> key also needs to continue the requests, as well as starting
  13. // a new line
  14. var hotKeyEvents = new Array();
  15. hotKeyEvents[10] = proceed;
  16. hotKeyEvents[13] = proceed;
  17. //hotKeyEvents[13]= function(cmdLineDiv.scrollTop = scrollHeight;)
  18. hotKeyEvents[127] = removeInputIfNecessary;
  19. // De page that need to be accessed via AJAX for processing the input of the cmd
  20. // line
  21. var ajaxRequestPage = 'ajax_install_test_div.php';
  22. // Defines the starting characters of a new cmd line (cf. C:\ on a windows cmd line)
  23. var CMDNL = '>>> ';
  24. // Contains the height of 1 line of text in the cmd (in px)
  25. var LINE_HEIGHT = 12;
  26. // Contains the height of the cmd itself (in px)
  27. var CMD_DIV_HEIGHT = 250;
  28. // contains the maximum amount of lines that can be displayed without having to use
  29. // scrollbars
  30. var MAX_CMD_LINES = Math.round(CMD_DIV_HEIGHT / LINE_HEIGHT);
  31. // When set to true, an additional textarea will be outputted at the bottom of the screen
  32. // with some debug information
  33. var debug = false;
  34.  
  35. // Contains a reference to the cmdLineDiv div in the HTML document
  36. var cmdLineDiv = null;
  37. // Contains the first occurence (backwards) that need to be found so that no contents
  38. // gets deleted after that point (sounds crazy, but is actually very logical)
  39. // In cmd on Windows, for instance, you can't delete the "C:\ " character at the beginning
  40. // of each line. The prevent a user from deleting these lines here, I had to make a copy
  41. // of the string that can't be deleted (">>> " in this case, or when a question is asked)
  42. var noEditLine = null;
  43. // Contains the XMLHttpRequest object in case XMLHttpRequest is available, otherwise
  44. // an ActiveXObject
  45. var ajaxRequestObject = null;
  46. // Contains a question that need to be answered. This question was send from the
  47. // ajaxRequestPage
  48. var cmdQuestion = null;
  49. // Contains the answer, filled in by the user, to the question last asked
  50. var cmdAnswer = null;
  51.  
  52. var newLines = 0;
  53.  
  54. /**
  55. * This function is called whenever a key is pressed inside the cmdLineDiv div.
  56. * It will check the key pressed, and then decides what to do with the event. By
  57. * default it will simply display the character in the cmdLineDiv div, unless a
  58. * hotKeyEvent was stored in the hotKeyEvents Array
  59. *
  60. * @param object An event object containing all information about the event
  61. */
  62. function onKeyPressEvent (event) {
  63.     event = event? event : (window.event? window.event : null);
  64.     if (event != null) {
  65.         var charCode = event.charCode? event.charCode : (event.which? event.which : event.keyCode);
  66.         if (debug) alertT (charCode + " = '" + String.fromCharCode(charCode) + "'");
  67.         if (charCode in hotKeyEvents)
  68.             hotKeyEvents[charCode]();
  69.         else if (charCode > 31 && charCode < 127)
  70.             insertChar (charCode);
  71.         else if (charCode > 160 && charCode <255)
  72.             insertHtmlChar (charCode);
  73.     }
  74. }
  75.  
  76. /**
  77. * Adds HTML text to the cmdLineDiv.
  78. * It will first remove the fake cursor, otherwise an unecessary underscore will
  79. * be placed on the cmdLineDiv div as well
  80. *
  81. * @param string The text that need to be displayed to the user on the cmdLineDiv div
  82. */
  83. function addHtmlText (text) {
  84.     removeCursor ();
  85.     cmdLineDiv.innerHTML += text;
  86. }
  87.  
  88. /**
  89. * This function is called whenever te <enter> key was pressed on your keyboard
  90. * If a question was asked during the previous cmd output, the answer is searched
  91. * for first. Next it will call the proceedWithRequests function to continue sending
  92. * requests to the ajaxRequestPage
  93. */
  94.  
  95. function proceed () {
  96.      //if (toScroll > CMD_DIV_HEIGHT)
  97.         //cmdLineDiv.scrollTop = scrollHeight;
  98.     if (debug) alertT ("proceed:");
  99.     if (cmdQuestion != null) {
  100.         removeCursor ();
  101.         cmdAnswer = cmdLineDiv.innerHTML.substring (cmdLineDiv.innerHTML.lastIndexOf (cmdQuestion) + cmdQuestion.length + 1);
  102.         cmdAnswer = (cmdAnswer == "" || cmdAnswer == " ")? null : cmdAnswer;
  103.         if (debug) alertT ("\tcmdAnswer: " + cmdAnswer);
  104.     }
  105.     //alert (cmdLineDiv.scrollHeight + " - " + cmdLineDiv.scrollTop);
  106.     proceedWithRequests ();
  107.     alertT (newLines);
  108.     alertT ("scrollH - scrollT = " + cmdLineDiv.scrollHeight + " - " + cmdLineDiv.scrollTop);
  109.     addHtmlText ("<br />\r\n" + CMDNL);
  110.     noEditLine = CMDNL;
  111.     cmdLineDiv.focus();
  112. }
  113. /**
  114. * Whenever the user hits the ctrl+backspace key combination on the keyboard
  115. * The text needs to be removed from the cmdLineDiv div. This function is called
  116. * everytime the user hits this combination, or keeps it down
  117. * Since I couldn't simply catch the backspace key-press, I had to use the
  118. * ctrl+backspace key combination
  119. */
  120. function removeInputIfNecessary () {
  121.     removeCursor ();
  122.     var cur = cmdLineDiv.innerText.substring (cmdLineDiv.innerText.length - noEditLine.length)
  123.     if (debug) alertT ("removeInputIfNecessary: " + cur + " vs. " + noEditLine + " = " + (cur == noEditLine? 'no-change' : 'remove'));
  124.     if (cur != noEditLine) {
  125.         cmdLineDiv.innerHTML = cmdLineDiv.innerHTML.substring (0, cmdLineDiv.innerHTML.length-1);
  126.     }
  127. }
  128.  
  129. /**
  130. * Inserts the character referring to the key that was pressed on your keyboard
  131. * into the cmdLineDiv div
  132. *
  133. * @param string The character code that refers to a certain character
  134. */
  135. function insertChar (char) {
  136.     if (debug) alertT ("insertChar: " + String.fromCharCode (char));
  137.     addHtmlText (String.fromCharCode (char));
  138. }
  139.  
  140. /**
  141. * When extended ASCII characters, such as ù, are typed, the HTML equivalent needs
  142. * to be inserted into the cmdLineDiv div.
  143. *
  144. * @param string The character code of a certain extended ASCII character. Eventually
  145. *            the &#-char-; string is inserted into the cmdLineDiv div
  146. */
  147. function insertHtmlChar (char) {
  148.     if (debug) alertT ("insertHtmlChar: " + String.fromCharCode(char));
  149.     addHtmlText ("&#" + parseInt (char) + ";");
  150. }
  151.  
  152. /**
  153. * This function is called to initiate all startup variables and functions
  154. */
  155. function __init__ () {
  156.     if (debug) createDebugOutputField ();
  157.     cmdLineDiv = document.getElementById('cmdLineDiv');
  158.     cmdLineDiv.focus();
  159.     noEditLine = CMDNL;
  160.     createAjaxObject ();
  161.     toggleCursor ();
  162. }
  163.  
  164. /**
  165. * This function makes a cursor flash inside the cmdLineDiv div.
  166. * It uses the setTimeout function that redirects to itself with an interval of
  167. * 0.5 seconds
  168. */
  169. function toggleCursor () {
  170.     if (cmdLineDiv.innerHTML.substring (cmdLineDiv.innerHTML.length-1) == '_')
  171.         {cmdLineDiv.innerHTML = cmdLineDiv.innerHTML.substring (0, cmdLineDiv.innerHTML.length-1);
  172.         cmdLineDiv.scrollTop = cmdLineDiv.scrollHeight;}
  173.     else
  174.         {cmdLineDiv.innerHTML += '_';
  175.         cmdLineDiv.scrollTop = cmdLineDiv.scrollHeight;}
  176.     setTimeout (toggleCursor, 500)
  177. }
  178.  
  179. /**
  180. * Removes the cursor from the cmdLineDiv div whenever text needs to be added to the div
  181. */
  182. function removeCursor () {
  183.     if (cmdLineDiv.innerHTML.substring (cmdLineDiv.innerHTML.length-1) == '_')
  184.         cmdLineDiv.innerHTML = cmdLineDiv.innerHTML.substring (0, cmdLineDiv.innerHTML.length-1);
  185. }
  186.  
  187. /**
  188. * Creates the XMLHttpRequest object or an ActiveXObject, depending on the browser
  189. */
  190. function createAjaxObject () {
  191.     if (window.XMLHttpRequest) {
  192.         ajaxRequestObject = new XMLHttpRequest();
  193.         return true;
  194.     } else if (window.ActiveXObject) {
  195.         var aVersions = ["MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp.4.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp", "Microsoft.XMLHttp"];
  196.         for (var i=0; i<aVersions.length; i++) {
  197.             try {
  198.                 ajaxRequestObject = new ActiveXObject (aVersions[i]);
  199.                 return true;
  200.             } catch (e) {}
  201.         }
  202.     } else {
  203.         alertT("Your browser doesn't support AJAX, please switch to Opera, Netscape, Firefox or IE");
  204.         return false;
  205.     }
  206. }
  207.  
  208. /**
  209. * Keeps on sending requests to the ajaxRequestPage whenever the user hits the <enter>
  210. * key on his keyboard
  211. */
  212. function proceedWithRequests () {
  213.     if (ajaxRequestObject != null) {
  214.         if (debug) alertT ("proceedWithRequests:");
  215.         ajaxRequestObject.open ('POST', ajaxRequestPage);
  216.         ajaxRequestObject.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
  217.         ajaxRequestObject.onreadystatechange = function () {
  218.             if (ajaxRequestObject.readyState == 4 && ajaxRequestObject.status == 200) {
  219.                 var xml = ajaxRequestObject.responseXML;
  220.                 var status = parseInt(xml.getElementsByTagName ('status')[0].firstChild.nodeValue);
  221.                 if (debug) alertT ("\tstatus: " + status);
  222.                 if (status == 0) {
  223.                     var cmdText = new Array();
  224.                     var a = xml.getElementsByTagName ('cmdText')
  225.                     for (var i=0; i<a.length;i++)
  226.                         if (a[i].firstChild.nodeValue != "") cmdText.push (a[i].firstChild.nodeValue);
  227.                     try {
  228.                         cmdQuestion = xml.getElementsByTagName ('cmdQuestion')[0].firstChild.nodeValue;
  229.                     } catch (e) {
  230.                         cmdQuestion = null;
  231.                     }
  232.                     updateCmdLineDiv (cmdText, cmdQuestion);
  233.                     newLines = parseInt(cmdText.length + (cmdQuestion == null? 0 : 1));
  234.                     alertT("newLines in proceedWithRequests: " + newLines);
  235.                 } else {
  236.                     updateCmdLineDiv (new Array ('<span style="color:red">Error(' + status + '): The installation could not be completed</span>'), null);
  237.                     newLines = 1;
  238.                 }
  239.             } else {
  240.                 try {
  241.                     if (debug) alertT ("\tSomething went wrong during the ajax request:\n\tstatus: " + ajaxRequestObject.status + "\n\treadyState: " + ajaxRequestObject.readyState);
  242.                 } catch (e) {}
  243.                 newLines = 0;
  244.             }
  245.         };
  246.         if (cmdAnswer != null)
  247.             ajaxRequestObject.send ("sectionId=3&cmdAnwser=" + cmdAnswer);
  248.         else
  249.             ajaxRequestObject.send ("sectionId=1");
  250.     }
  251.  
  252.     return 0;
  253. }
  254.  
  255. /**
  256. * Processes the list of text that needs to be added to the cmdLineDiv div
  257. */
  258. function updateCmdLineDiv (cmdText, cmdQuestion) {
  259.     if (debug) alertT ("updateCmdLineDiv: cmdText(length):" + cmdText.length + ";cmdQuestion:" + cmdQuestion);
  260.     for (var i=0; i<cmdText.length; i++) {
  261.         addHtmlText (cmdText[i] + "<br/>\r\n");
  262.     }
  263.     if (cmdQuestion != null) {
  264.         addHtmlText (CMDNL + cmdQuestion + " ");
  265.         noEditLine = cmdQuestion + " ";
  266.     } else {
  267.         addHtmlText (CMDNL);
  268.         noEditLine = CMDNL;
  269.     }
  270. }
  271.  
  272. /**
  273. * Creates the textarea in which the debug-output will be placed
  274. */
  275. function createDebugOutputField () {
  276.     var textarea = document.createElement ('textarea');
  277.     try {
  278.         textarea.className = 'debugField';
  279.         textarea.id = 'debugField';
  280.     } catch (e) {
  281.         textarea.setAttribute ('class', 'debugField');
  282.         textarea.setAttribute ('id', 'debugField');
  283.     }
  284.     document.body.appendChild (textarea);
  285. }
  286.  
  287. /**
  288. * A variant of the built-in alert function, except this one simply outputs the
  289. * text to the debug field
  290. */
  291. function alertT (text) {
  292.     document.getElementById ('debugField').value += text + '\n';
  293. }
  294. // ]]>
  295. </script>
  296. <style type="text/css" media="screen">
  297. /* <![CDATA[ */
  298. textarea.debugField {
  299.     width:90%;
  300.     height:150px;
  301. }
  302.  
  303. div.cmdLine {
  304.     border:2px solid #AAAAAA;
  305.     height:250px;
  306.     width:90%;
  307.     font-family:"Lucida Console";
  308.     font-size:12px;
  309.     color:rgb(192,192,192);
  310.     background-color:#000000;
  311.     overflow:auto;
  312.     padding:2px;
  313. }
  314. /* ]]> */
  315. </style>
  316. </head>
  317.  
  318. <body onload="__init__(); createDebugOutputField()">
  319. <h3>Even wat zever zetten</h3>
  320. <button id="installbtn" type="button">Install!</button><br/>
  321. <br/>
  322. <div class="cmdLine" id="cmdLineDiv" onkeypress="onKeyPressEvent(event)">>>> </div>
  323. </body>
  324. </html>
__________________
Jerry Broughton
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiShare on FacebookShare on Stumble UponShare on Twitter
Reply With Quote
  #6 (permalink)  
Old 05-05-08, 04:23 AM
UnrealEd's Avatar
UnrealEd UnrealEd is offline
Community Liaison
 
Join Date: May 2005
Location: Antwerp, Belgium
Posts: 3,165
Thanks: 4
Thanked 25 Times in 25 Posts
Thanks for the help guys!

I wasn't able to come online yesterday evening, so I couldn't tell you I allready found a solution to the problem. Sorry

The reason why both newLines and cmdLineDiv.scrollHeight had an incorrect value was because of the proceedWithRequests function. When called in the proceed function, it makes a request to the ajaxRequestPage, and immediately returns back to the proceed function, without waiting for the data to be recieved from the ajaxRequestPage. So while continuing the proceed function, the data was still to be retrieved from the outcome of the request, and added to the cmdLineDiv. That's why both newLines (value = 0) and cmdLineDiv.scrollHeight (value = height before adding the data) gave the wrong value.

I moved the scroll-fix part to the onreadystatechange event handling function in the proceedWithRequests function and all is working fine now.

Thanks anyway
__________________
"Good judgement comes from experience, and experience comes from bad judgement." - Fred Brooks

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiShare on FacebookShare on Stumble UponShare on Twitter
Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
html tutoral thefrtman HTML/XHTML/XML 5 04-27-09 11:25 AM
Dumb HTMl Problem [Could be CSS] _net HTML/XHTML/XML 7 05-25-07 05:51 AM
un-hiding a html element... darkcarnival JavaScript 2 04-15-07 08:45 AM
HTML Form 1 -> Perl -> return response to HTML form 2 Oleks Perl 13 10-18-06 05:59 PM
I most definately suggest DevelopingCentral.com For Any Website Design/Development! Salty777 General Advertisements 2 10-01-04 05:27 AM


All times are GMT -5. The time now is 01:22 PM.
vBulletin® Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.