$(function() { if (!EVALEX_TRUSTED) { initPinBox(); } /** * if we are in console mode, show the console. */ if (CONSOLE_MODE && EVALEX) { openShell(null, $('div.console div.inner').empty(), 0); } $("div.detail").click(function() { $("div.traceback").get(0).scrollIntoView(false); }); $('div.traceback div.frame').each(function() { var target = $('pre', this), consoleNode = null, frameID = this.id.substring(6); target.click(function() { $(this).parent().toggleClass('expanded'); }); /** * Add an interactive console to the frames */ if (EVALEX && target.is('.current')) { $('') .attr('title', 'Open an interactive python shell in this frame') .click(function() { consoleNode = openShell(consoleNode, target, frameID); return false; }) .prependTo(target); } }); /** * toggle traceback types on click. */ $('h2.traceback').click(function() { $(this).next().slideToggle('fast'); $('div.plain').slideToggle('fast'); }).css('cursor', 'pointer'); $('div.plain').hide(); /** * Add extra info (this is here so that only users with JavaScript * enabled see it.) */ $('span.nojavascript') .removeClass('nojavascript') .html('

To switch between the interactive traceback and the plaintext ' + 'one, you can click on the "Traceback" headline. From the text ' + 'traceback you can also create a paste of it. ' + (!EVALEX ? '' : 'For code execution mouse-over the frame you want to debug and ' + 'click on the console icon on the right side.' + '

You can execute arbitrary Python code in the stack frames and ' + 'there are some extra helpers available for introspection:' + '

')); /** * Add the pastebin feature */ $('div.plain form') .submit(function() { var label = $('input[type="submit"]', this); var old_val = label.val(); label.val('submitting...'); $.ajax({ dataType: 'json', url: document.location.pathname, data: {__debugger__: 'yes', tb: TRACEBACK, cmd: 'paste', s: SECRET}, success: function(data) { $('div.plain span.pastemessage') .removeClass('pastemessage') .text('Paste created: ') .append($('#' + data.id + '').attr('href', data.url)); }, error: function() { alert('Error: Could not submit paste. No network connection?'); label.val(old_val); } }); return false; }); // if we have javascript we submit by ajax anyways, so no need for the // not scaling textarea. var plainTraceback = $('div.plain textarea'); plainTraceback.replaceWith($('
').text(plainTraceback.text()));
});

function initPinBox() {
  $('.pin-prompt form').submit(function(evt) {
    evt.preventDefault();
    var pin = this.pin.value;
    var btn = this.btn;
    btn.disabled = true;
    $.ajax({
      dataType: 'json',
      url: document.location.pathname,
      data: {__debugger__: 'yes', cmd: 'pinauth', pin: pin,
             s: SECRET},
      success: function(data) {
        btn.disabled = false;
        if (data.auth) {
          EVALEX_TRUSTED = true;
          $('.pin-prompt').fadeOut();
        } else {
          if (data.exhausted) {
            alert('Error: too many attempts.  Restart server to retry.');
          } else {
            alert('Error: incorrect pin');
          }
        }
        console.log(data);
      },
      error: function() {
        btn.disabled = false;
        alert('Error: Could not verify PIN.  Network error?');
      }
    });
  });
}

function promptForPin() {
  if (!EVALEX_TRUSTED) {
    $.ajax({
      url: document.location.pathname,
      data: {__debugger__: 'yes', cmd: 'printpin', s: SECRET}
    });
    $('.pin-prompt').fadeIn(function() {
      $('.pin-prompt input[name="pin"]').focus();
    });
  }
}


/**
 * Helper function for shell initialization
 */
function openShell(consoleNode, target, frameID) {
  promptForPin();
  if (consoleNode)
    return consoleNode.slideToggle('fast');
  consoleNode = $('
')
    .appendTo(target.parent())
    .hide()
  var historyPos = 0, history = [''];
  var output = $('
[console ready]
') .appendTo(consoleNode); var form = $('
>>>
') .submit(function() { var cmd = command.val(); $.get('', { __debugger__: 'yes', cmd: cmd, frm: frameID, s: SECRET}, function(data) { var tmp = $('
').html(data); $('span.extended', tmp).each(function() { var hidden = $(this).wrap('').hide(); hidden .parent() .append($('  ') .click(function() { hidden.toggle(); $(this).toggleClass('open') return false; })); }); output.append(tmp); command.focus(); consoleNode.scrollTop(consoleNode.get(0).scrollHeight); var old = history.pop(); history.push(cmd); if (typeof old != 'undefined') history.push(old); historyPos = history.length - 1; }); command.val(''); return false; }). appendTo(consoleNode); var command = $('') .appendTo(form) .keydown(function(e) { if (e.key == 'l' && e.ctrlKey) { output.text('--- screen cleared ---'); return false; } else if (e.charCode == 0 && (e.keyCode == 38 || e.keyCode == 40)) { // handle up arrow and down arrow if (e.keyCode == 38 && historyPos > 0) historyPos--; else if (e.keyCode == 40 && historyPos < history.length) historyPos++; command.val(history[historyPos]); return false; } }); return consoleNode.slideDown('fast', function() { command.focus(); }); }