testappproj/static/shell.js~
changeset 0 0b061d58aea3
equal deleted inserted replaced
-1:000000000000 0:0b061d58aea3
       
     1 // Copyright 2007 Google Inc.
       
     2 //
       
     3 // Licensed under the Apache License, Version 2.0 (the "License");
       
     4 // you may not use this file except in compliance with the License.
       
     5 // You may obtain a copy of the License at
       
     6 //
       
     7 //      http://www.apache.org/licenses/LICENSE-2.0
       
     8 //
       
     9 // Unless required by applicable law or agreed to in writing, software
       
    10 // distributed under the License is distributed on an "AS IS" BASIS,
       
    11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    12 // See the License for the specific language governing permissions and
       
    13 // limitations under the License.
       
    14 
       
    15 /**
       
    16  * @fileoverview
       
    17  * Javascript code for the interactive AJAX shell.
       
    18  *
       
    19  * Part of http://code.google.com/p/google-app-engine-samples/.
       
    20  *
       
    21  * Includes a function (shell.runStatement) that sends the current python
       
    22  * statement in the shell prompt text box to the server, and a callback
       
    23  * (shell.done) that displays the results when the XmlHttpRequest returns.
       
    24  *
       
    25  * Also includes cross-browser code (shell.getXmlHttpRequest) to get an
       
    26  * XmlHttpRequest.
       
    27  */
       
    28 
       
    29 /**
       
    30  * Shell namespace.
       
    31  * @type {Object}
       
    32  */
       
    33 var shell = {}
       
    34 
       
    35 /**
       
    36  * The shell history. history is an array of strings, ordered oldest to
       
    37  * newest. historyCursor is the current history element that the user is on.
       
    38  *
       
    39  * The last history element is the statement that the user is currently
       
    40  * typing. When a statement is run, it's frozen in the history, a new history
       
    41  * element is added to the end of the array for the new statement, and
       
    42  * historyCursor is updated to point to the new element.
       
    43  *
       
    44  * @type {Array}
       
    45  */
       
    46 shell.history = [''];
       
    47 
       
    48 /**
       
    49  * See {shell.history}
       
    50  * @type {number}
       
    51  */
       
    52 shell.historyCursor = 0;
       
    53 
       
    54 /**
       
    55  * A constant for the XmlHttpRequest 'done' state.
       
    56  * @type Number
       
    57  */
       
    58 shell.DONE_STATE = 4;
       
    59 
       
    60 /**
       
    61  * A cross-browser function to get an XmlHttpRequest object.
       
    62  *
       
    63  * @return {XmlHttpRequest?} a new XmlHttpRequest
       
    64  */
       
    65 shell.getXmlHttpRequest = function() {
       
    66   if (window.XMLHttpRequest) {
       
    67     return new XMLHttpRequest();
       
    68   } else if (window.ActiveXObject) {
       
    69     try {
       
    70       return new ActiveXObject('Msxml2.XMLHTTP');
       
    71     } catch(e) {
       
    72       return new ActiveXObject('Microsoft.XMLHTTP');
       
    73     }
       
    74   }
       
    75 
       
    76   return null;
       
    77 };
       
    78 
       
    79 /**
       
    80  * This is the prompt textarea's onkeypress handler. Depending on the key that
       
    81  * was pressed, it will run the statement, navigate the history, or update the
       
    82  * current statement in the history.
       
    83  *
       
    84  * @param {Event} event the keypress event
       
    85  * @return {Boolean} false to tell the browser not to submit the form.
       
    86  */
       
    87 shell.onPromptKeyPress = function(event) {
       
    88   var statement = document.getElementById('statement');
       
    89 
       
    90   if (this.historyCursor == this.history.length - 1) {
       
    91     // we're on the current statement. update it in the history before doing
       
    92     // anything.
       
    93     this.history[this.historyCursor] = statement.value;
       
    94   }
       
    95 
       
    96   // should we pull something from the history?
       
    97   if (event.ctrlKey && event.keyCode == 38 /* up arrow */) {
       
    98     if (this.historyCursor > 0) {
       
    99       statement.value = this.history[--this.historyCursor];
       
   100     }
       
   101     return false;
       
   102   } else if (event.ctrlKey && event.keyCode == 40 /* down arrow */) {
       
   103     if (this.historyCursor < this.history.length - 1) {
       
   104       statement.value = this.history[++this.historyCursor];
       
   105     }
       
   106     return false;
       
   107   } else if (!event.altKey) {
       
   108     // probably changing the statement. update it in the history.
       
   109     this.historyCursor = this.history.length - 1;
       
   110     this.history[this.historyCursor] = statement.value;
       
   111   }
       
   112 
       
   113   // should we submit?
       
   114   if (event.keyCode == 13 /* enter */ && !event.altKey && !event.shiftKey) {
       
   115     return this.runStatement();
       
   116   }
       
   117 };
       
   118 
       
   119 /**
       
   120  * The XmlHttpRequest callback. If the request succeeds, it adds the command
       
   121  * and its resulting output to the shell history div.
       
   122  *
       
   123  * @param {XmlHttpRequest} req the XmlHttpRequest we used to send the current
       
   124  *     statement to the server
       
   125  */
       
   126 shell.done = function(req) {
       
   127   if (req.readyState == this.DONE_STATE) {
       
   128     var statement = document.getElementById('statement')
       
   129     statement.className = 'prompt';
       
   130 
       
   131     // add the command to the shell output
       
   132     var output = document.getElementById('output');
       
   133 
       
   134    output.value += '\n'+'Out[]:' + statement.value;
       
   135    statement.value = '';
       
   136 
       
   137     // add a new history element
       
   138     this.history.push('');
       
   139     this.historyCursor = this.history.length - 1;
       
   140 
       
   141     // add the command's result
       
   142     var result = req.responseText.replace(/^\s*|\s*$/g, '');  // trim whitespace
       
   143     if (result != '')
       
   144       output.value += '\n'+ result ;
       
   145 
       
   146     // scroll to the bottom
       
   147     output.scrollTop = output.scrollHeight;
       
   148     if (output.createTextRange) {
       
   149       var range = output.createTextRange();
       
   150       range.collapse(false);
       
   151       range.select();
       
   152     }
       
   153   }
       
   154 };
       
   155 
       
   156 /**
       
   157  * This is the form's onsubmit handler. It sends the python statement to the
       
   158  * server, and registers shell.done() as the callback to run when it returns.
       
   159  *
       
   160  * @return {Boolean} false to tell the browser not to submit the form.
       
   161  */
       
   162 shell.runStatement = function() {
       
   163   var form = document.getElementById('form');
       
   164 
       
   165   // build a XmlHttpRequest
       
   166   var req = this.getXmlHttpRequest();
       
   167   if (!req) {
       
   168     document.getElementById('ajax-status').innerHTML =
       
   169         "<span class='error'>Your browser doesn't support AJAX. :(</span>";
       
   170     return false;
       
   171   }
       
   172 
       
   173   req.onreadystatechange = function() { shell.done(req); };
       
   174 
       
   175   // build the query parameter string
       
   176   var params = '';
       
   177   for (i = 0; i < form.elements.length; i++) {
       
   178     var elem = form.elements[i];
       
   179     if (elem.type != 'submit' && elem.type != 'button' && elem.id != 'caret') {
       
   180       var value = escape(elem.value).replace(/\+/g, '%2B'); // escape ignores +
       
   181       params += '&' + elem.name + '=' + value;
       
   182     }
       
   183   }
       
   184 
       
   185   // send the request and tell the user.
       
   186   document.getElementById('statement').className = 'prompt processing';
       
   187   req.open(form.method, form.action + '?' + params, true);
       
   188   req.setRequestHeader('Content-type',
       
   189                        'application/x-www-form-urlencoded;charset=UTF-8');
       
   190   req.send(null);
       
   191 
       
   192   return false;
       
   193 };