<?php
+use \PFF\HtmlBuilder\Tag as Tag;
+
class IPF_HTTP_Response_ServerErrorDebug extends IPF_HTTP_Response
{
- function __construct($e, $mimetype=null)
+ function __construct($request, $exception, $mimetype=null)
{
$this->status_code = 500;
- $this->content = IPF_HTTP_Response_ServerErrorDebug_Pretty($e);
+ $page = new IPF_HTTP_ServerErrorDebugPage($request, $exception);
+ $this->content = $page->html();
}
}
{
$result = array();
- if ($v instanceof IPF_HTTP_Request) {
- return 'IPF_HTTP_Request';
- } elseif ($v instanceof IPF_ORM_Query_Abstract) {
- $result = array(
- get_class($v),
- '{',
- ' sql: ' . $v->getQuery(),
- '}');
- } elseif ($v instanceof IPF_ORM_Record_Abstract) {
- $result[] = get_class($v);
- $result[] = '{';
- foreach ($v->getTable()->getColumnNames() as $column) {
- $result[] = ' ' . $column . ': ' . debug_print_r($v->get($column), $indent+2);
- }
- $result[] = '}';
- } elseif ($v instanceof IPF_ORM_Collection) {
- $result[] = get_class($v);
- $result[] = '{';
- foreach ($v as $key => $value) {
- $result[] = ' ' . $key . ': ' . debug_print_r($value, $indent+2);
- }
- $result[] = '}';
- } elseif ($v instanceof IPF_Template_Context) {
- $result[] = get_class($v);
+ if (is_object($v) && method_exists($v, '__debugInfo')) {
+ $result[] = get_class($v) . ' Object';
$result[] = '{';
- foreach ($v->_vars as $var => $value) {
- $result[] = ' ' . $var . ': ' . debug_print_r($value, $indent+2);
+ foreach ($v->__debugInfo() as $key => $val) {
+ $result[] = ' [' . $key . '] => ' . debug_print_r($val, $indent+2);
}
$result[] = '}';
- } elseif ($v instanceof IPF_Template_ContextVars) {
- $result[] = get_class($v);
- $result[] = '{';
- foreach ($v as $var => $value) {
- $result[] = ' ' . $var . ': ' . debug_print_r($value, $indent+2);
- }
- $result[] = '}';
- } elseif ($v instanceof IPF_ORM_Pager_Layout) {
- $pager = $v->getPager();
- $result = array(
- 'IPF_ORM_Pager_Layout',
- '{',
- ' page: ' . $pager->getPage(),
- ' size: ' . $pager->getMaxPerPage(),
- ' query: ' . debug_print_r($pager->getQuery(), $indent+2),
- '}');
} elseif ($v instanceof stdClass) {
$result[] = 'stdClass';
$result[] = '{';
$result[] = 'Array';
$result[] = '{';
foreach ($v as $k => $v) {
- $result[] = ' ' . $k . ' => ' . debug_print_r($v, $indent+2);
+ $result[] = ' [' . $k . '] => ' . debug_print_r($v, $indent+2);
}
$result[] = '}';
} elseif (is_bool($v)) {
return ltrim(implode("\n", $result));
}
-function IPF_HTTP_Response_ServerErrorDebug_Pretty($e)
+class IPF_HTTP_ServerErrorDebugPage
{
- $o = create_function('$in','return htmlspecialchars($in);');
- $sub = create_function('$f','$loc="";if(isset($f["class"])){
- $loc.=$f["class"].$f["type"];}
- if(isset($f["function"])){$loc.=$f["function"];}
- if(!empty($loc)){$loc=htmlspecialchars($loc);
- $loc="<strong>$loc</strong>";}return $loc;');
- $parms = create_function('$f','$params=array();if(isset($f["function"])){
- try{if(isset($f["class"])){
- $r=new ReflectionMethod($f["class"]."::".$f["function"]);}
- else{$r=new ReflectionFunction($f["function"]);}
- return $r->getParameters();}catch(Exception $e){}}
- return $params;');
- $src2lines = create_function('$file','$src=nl2br(highlight_file($file,TRUE));
- return explode("<br />",$src);');
- $clean = create_function('$line','return trim(strip_tags($line));');
- $desc = get_class($e)." making ".$_SERVER['REQUEST_METHOD']." request to ".
- $_SERVER['REQUEST_URI'];
- $out = '
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html lang="en">
-<head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <meta name="robots" content="NONE,NOARCHIVE" />
- <title>'.$o($desc).'</title>
- <style type="text/css">
- html * { padding:0; margin:0; }
- body * { padding:10px 20px; }
- body * * { padding:0; }
- body { font:small sans-serif; background: #70DBFF; }
- body>div { border-bottom:1px solid #ddd; }
- h1 { font-weight:normal; }
- h2 { margin-bottom:.8em; }
- h2 span { font-size:80%; color:#666; font-weight:normal; }
- h2 a { text-decoration:none; }
- h3 { margin:1em 0 .5em 0; }
- h4 { margin:0.5em 0 .5em 0; font-weight: normal; font-style: italic; }
- table {
- border:1px solid #ccc; border-collapse: collapse; background:white; }
- tbody td, tbody th { vertical-align:top; padding:2px 3px; }
- thead th {
- padding:1px 6px 1px 3px; background:#70FF94; text-align:left;
- font-weight:bold; font-size:11px; border:1px solid #ddd; }
- tbody th { text-align:right; color:#666; padding-right:.5em; }
- table.vars { margin:5px 0 2px 40px; }
- table.vars td, table.req td { font-family:monospace; }
- table td { background: #70FFDB; }
- table td.code { width:95%;}
- table td.code div { overflow:hidden; }
- table.source th { color:#666; }
- table.source td {
- font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
- ul.traceback { list-style-type:none; }
- ul.traceback li.frame { margin-bottom:1em; }
- div.context { margin:5px 0 2px 40px; background-color:#70FFDB; }
- div.context ol {
- padding-left:30px; margin:0 10px; list-style-position: inside; }
- div.context ol li {
- font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
- div.context li.current-line { color:black; background-color:#70FF94; }
- div.commands { margin-left: 40px; }
- div.commands a { color:black; text-decoration:none; }
- p.headers { background: #70FFDB; font-family:monospace; }
- #summary { background: #00B8F5; }
- #summary h2 { font-weight: normal; color: #666; }
- #traceback { background:#eee; }
- #request { background:#f6f6f6; }
- #response { background:#eee; }
- #summary table { border:none; background:#00B8F5; }
- #summary td { background:#00B8F5; }
- .switch { text-decoration: none; }
- .whitemsg { background:white; color:black;}
- </style>
- <script type="text/javascript">
- //<!--
- function getElementsByClassName(oElm, strTagName, strClassName){
- // Written by Jonathan Snook, http://www.snook.ca/jon;
- // Add-ons by Robert Nyman, http://www.robertnyman.com
- var arrElements = (strTagName == "*" && document.all)? document.all :
- oElm.getElementsByTagName(strTagName);
- var arrReturnElements = new Array();
- strClassName = strClassName.replace(/\-/g, "\\-");
- var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
- var oElement;
- for(var i=0; i<arrElements.length; i++){
- oElement = arrElements[i];
- if(oRegExp.test(oElement.className)){
- arrReturnElements.push(oElement);
+ private $request, $exception, $desc;
+
+ public function __construct($request, $exception)
+ {
+ $this->request = $request;
+ $this->exception = $exception;
+ $this->desc = get_class($this->exception)." making ".$_SERVER['REQUEST_METHOD']." request to ".$_SERVER['REQUEST_URI'];
+ }
+
+ function html()
+ {
+ return "<!DOCTYPE html>\n" . Tag::create('html', array('lang' => 'en'),
+ Tag::head(null,
+ Tag::meta(array('charset' => 'utf-8')),
+ Tag::title(null, $this->desc),
+ $this->css(),
+ $this->js()),
+ Tag::body(null,
+ $this->Summary(),
+ $this->SectionStacktrace(),
+ $this->SectionRequest(),
+ $this->SectionResponse()));
+ }
+
+
+ function Summary()
+ {
+ $msg = $this->exception->getMessage();
+ if ($this->exception->getCode())
+ $msg = $this->exception->getCode(). ' : ' . $msg;
+
+ return Tag::div(array('id' => 'summary'),
+ Tag::h1(null, $this->desc),
+ Tag::h2(null, $msg),
+ Tag::table(null,
+ Tag::tr(null,
+ Tag::th(null, 'PHP'),
+ Tag::td(null, $this->exception->getFile().', line '.$this->exception->getLine())),
+ Tag::tr(null,
+ Tag::th(null, 'URI'),
+ Tag::td(null, $_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI']))));
+ }
+
+
+ private function section($id, $title, $content)
+ {
+ return Tag::div(array('id' => $id, 'class' => 'section'))
+ ->append(Tag::h2()
+ ->append($title)
+ ->append(' ')
+ ->append(Tag::a(array('href' => '#', 'class' => 'section-toggle'))
+ ->append(Tag::span(array('class' => 'section-switch'))->append('▶'))))
+ ->append(Tag::div(array('class' => 'section-body'))
+ ->append($content));
+ }
+
+
+ function SectionStacktrace()
+ {
+ return $this->section('traceback', 'Stacktrace',
+ $this->StacktraceFrames());
+ }
+
+ function StacktraceFrames()
+ {
+ $ul = Tag::ul(array('class' => 'traceback'));
+
+ $frames = $this->exception->getTrace();
+ foreach ($frames as $frame) {
+ if (!isset($frame['file'])) {
+ $frame['file'] = 'No File';
+ $frame['line'] = '0';
+ }
+ $name = '';
+ if (isset($frame["class"]))
+ $name .= $frame["class"].$frame["type"];
+ if (isset($frame["function"]))
+ $name .= $frame["function"];
+
+ $li = Tag::li(array('class' => 'frame'),
+ Tag::strong(null, $name),
+ ' ['.$frame['file'].', line '.$frame['line'].']');
+
+ if (isset($frame['args']) && count($frame['args']) > 0) {
+ $li->append($this->StacktraceArgs($frame));
+ }
+
+ if (is_readable($frame['file']) ) {
+ $li->append($this->StacktraceSourceFile($frame['file'], $frame['line']));
+ } else {
+ $li->append(Tag::div(array('class' => 'commands'), 'No src available'));
}
+
+ $ul->append($li);
}
- return (arrReturnElements)
+ return $ul;
}
- function hideAll(elems) {
- for (var e = 0; e < elems.length; e++) {
- elems[e].style.display = \'none\';
- }
+
+ function StacktraceArgs($frame)
+ {
+ $params = array();
+ if (isset($frame["function"])) {
+ if (isset($frame["class"])) {
+ $r = new ReflectionMethod($frame["class"]."::".$frame["function"]);
+ } else {
+ $r = new ReflectionFunction($frame["function"]);
+ }
+ $params = $r->getParameters();
+ }
+
+ $tbody = Tag::tbody();
+ foreach ($frame['args'] as $k => $v) {
+ $name = isset($params[$k]) ? '$'.$params[$k]->name : '?';
+ $tbody->append(Tag::tr(null,
+ Tag::td(null, $k),
+ Tag::td(null, $name),
+ Tag::td(array('class' => 'code'),
+ Tag::div()->raw(highlight_string(debug_print_r($v), true)))));
+ }
+
+ return Tag::div(array('class' => 'section'),
+ Tag::div(array('class' => 'commands'),
+ Tag::a(array('href' => '#', 'class' => 'section-toggle'),
+ Tag::span(array('class' => 'section-switch'), '▶'),
+ ' Args')),
+ Tag::table(array('class' => 'section-body vars'),
+ Tag::thead(null,
+ Tag::tr(null,
+ Tag::th(null, 'Arg'),
+ Tag::th(null, 'Name'),
+ Tag::th(null, 'Value'))),
+ $tbody));
}
- function toggle() {
- for (var i = 0; i < arguments.length; i++) {
- var e = document.getElementById(arguments[i]);
- if (e) {
- e.style.display = e.style.display == \'none\' ? \'block\' : \'none\';
+
+ function StacktraceSourceFile($file, $line)
+ {
+ $start = max($line - 5, 0);
+ $ol = Tag::ol(array('start' => $start));
+
+ $rows = explode('<br />', nl2br(highlight_file($file, true)));
+ $rows = array_slice($rows, $start, 10);
+
+ foreach ($rows as $k => $row) {
+ $li = Tag::li(null, Tag::code()->raw($row));
+ if ($k + $start === $line)
+ $li->addClass('current-line');
+ $ol->append($li);
}
- }
- return false;
+
+ return Tag::div(array('class' => 'section'),
+ Tag::div(array('class' => 'commands'),
+ Tag::a(array('href' => '#', 'class' => 'section-toggle'),
+ Tag::span(array('class' => 'section-switch'), '▶'),
+ ' Src')),
+ Tag::div(array('class' => 'section-body context'),
+ $ol));
}
- function varToggle(link, id, prefix) {
- toggle(prefix + id);
- var s = link.getElementsByTagName(\'span\')[0];
- var uarr = String.fromCharCode(0x25b6);
- var darr = String.fromCharCode(0x25bc);
- s.innerHTML = s.innerHTML == uarr ? darr : uarr;
- return false;
+
+
+ function SectionRequest()
+ {
+ return $this->section('request', 'Request', array(
+ $this->RequestRaw(),
+
+ Tag::h3(null, 'Request <span>(parsed)</span>'),
+ Tag::h4(null, '$_GET'),
+ $this->RequestSuperlobal($_GET),
+
+ Tag::h4(null, '$_POST'),
+ $this->RequestSuperlobal($_POST),
+
+ Tag::h4(null, '$_COOKIE'),
+ $this->RequestSuperlobal($_COOKIE),
+
+ Tag::h4(null, '$_SERVER'),
+ $this->RequestSuperlobal($_SERVER),
+
+ Tag::h4(null, '$_ENV'),
+ $this->RequestSuperlobal($_ENV),
+ ));
}
- function sectionToggle(span, section) {
- toggle(section);
- var span = document.getElementById(span);
- var uarr = String.fromCharCode(0x25b6);
- var darr = String.fromCharCode(0x25bc);
- span.innerHTML = span.innerHTML == uarr ? darr : uarr;
- return false;
+
+
+ function RequestRaw()
+ {
+ return array(
+ Tag::h3(null, 'Request ', Tag::span('(raw)')),
+ $this->RequestRawHeaders(),
+ $this->RequestRawBody(),
+ );
}
-
- window.onload = function() {
- hideAll(getElementsByClassName(document, \'table\', \'vars\'));
- hideAll(getElementsByClassName(document, \'div\', \'context\'));
- hideAll(getElementsByClassName(document, \'ul\', \'traceback\'));
- hideAll(getElementsByClassName(document, \'div\', \'section\'));
+
+ function RequestRawHeaders()
+ {
+ $r = array(
+ Tag::h4('Headers'),
+ );
+ $headers = $this->request->getHeaders();
+ if ($headers) {
+ $h = Tag::p(array('class' => 'headers'));
+ foreach ($headers as $name => $val) {
+ $h->append($name.': '.$val)->append(Tag::br());
+ }
+ $r[] = $h;
+ } else {
+ $r[] = Tag::p(null, 'No headers.');
+ }
+ return $r;
}
- //-->
- </script>
-</head>
-<body>
-
-<div id="summary">
- <h1>'.$o($desc).'</h1>
- <h2>';
- if ($e->getCode()) {
- $out .= $o($e->getCode()). ' : ';
+
+ function RequestRawBody()
+ {
+ $body = $this->request->getBody();
+ if (!$body)
+ return '';
+
+ return array(
+ Tag::h4('Body'),
+ Tag::p(array('class' => 'req', 'style' => 'padding-bottom: 2em'),
+ Tag::code(null, $body)),
+ );
}
- $out .= ' '.$o($e->getMessage()).'</h2>
- <table>
- <tr>
- <th>PHP</th>
- <td>'.$o($e->getFile()).', line '.$o($e->getLine()).'</td>
- </tr>
- <tr>
- <th>URI</th>
- <td>'.$o($_SERVER['REQUEST_METHOD'].' '.
- $_SERVER['REQUEST_URI']).'</td>
- </tr>
- </table>
-</div>
-
-<div id="traceback">
- <h2>Stacktrace
- <a href=\'#\' onclick="return sectionToggle(\'tb_switch\',\'tb_list\')">
- <span id="tb_switch">▶</span></a></h2>
- <ul id="tb_list" class="traceback">';
- $frames = $e->getTrace();
- foreach ($frames as $frame_id=>$frame) {
- if (!isset($frame['file'])) {
- $frame['file'] = 'No File';
- $frame['line'] = '0';
- }
- $out .= '<li class="frame">'.$sub($frame).'
- ['.$o($frame['file']).', line '.$o($frame['line']).']';
- if (isset($frame['args']) && count($frame['args']) > 0) {
- $params = $parms($frame);
- $out .= '
- <div class="commands">
- <a href=\'#\' onclick="return varToggle(this, \''.
- $o($frame_id).'\',\'v\')"><span>▶</span> Args</a>
- </div>
- <table class="vars" id="v'.$o($frame_id).'">
- <thead>
- <tr>
- <th>Arg</th>
- <th>Name</th>
- <th>Value</th>
- </tr>
- </thead>
- <tbody>';
- foreach ($frame['args'] as $k => $v) {
- $name = isset($params[$k]) ? '$'.$params[$k]->name : '?';
- $out .= '
- <tr>
- <td>'.$o($k).'</td>
- <td>'.$o($name).'</td>
- <td class="code">
- <div>'.highlight_string(debug_print_r($v), true).'</div>
- </td>
- </tr>';
- }
- $out .= '</tbody></table>';
- }
- if (is_readable($frame['file']) ) {
- $out .= '
- <div class="commands">
- <a href=\'#\' onclick="return varToggle(this, \''
- .$o($frame_id).'\',\'c\')"><span>▶</span> Src</a>
- </div>
- <div class="context" id="c'.$o($frame_id).'">';
- $lines = $src2lines($frame['file']);
- $start = $frame['line'] < 5 ?
- 0 : $frame['line'] -5; $end = $start + 10;
- $out2 = '';
- foreach ( $lines as $k => $line ) {
- if ( $k > $end ) { break; }
- $line = trim(strip_tags($line));
- if ( $k < $start && isset($frames[$frame_id+1]["function"])
- && preg_match('/function( )*'.preg_quote($frames[$frame_id+1]["function"]).'/',
- $line) ) {
- $start = $k;
- }
- if ( $k >= $start ) {
- if ( $k != $frame['line'] ) {
- $out2 .= '<li><code>'.$clean($line).'</code></li>'."\n"; }
- else {
- $out2 .= '<li class="current-line"><code>'.
- $clean($line).'</code></li>'."\n"; }
- }
- }
- $out .= "<ol start=\"$start\">\n".$out2. "</ol>\n";
- $out .= '</div>';
- } else {
- $out .= '<div class="commands">No src available</div>';
- }
- $out .= '</li>';
- }
- $out .= '
- </ul>
-
-</div>
-
-<div id="request">
- <h2>Request
- <a href=\'#\' onclick="return sectionToggle(\'req_switch\',\'req_list\')">
- <span id="req_switch">▶</span></a></h2>
- <div id="req_list" class="section">';
- if ( function_exists('apache_request_headers') ) {
- $out .= '<h3>Request <span>(raw)</span></h3>';
- $req_headers = apache_request_headers();
- $out .= '<h4>HEADERS</h4>';
- if ( count($req_headers) > 0 ) {
- $out .= '<p class="headers">';
- foreach ($req_headers as $req_h_name => $req_h_val) {
- $out .= $o($req_h_name.': '.$req_h_val);
- $out .= '<br>';
- }
- $out .= '</p>';
- } else {
- $out .= '<p>No headers.</p>';
- }
- $req_body = file_get_contents('php://input');
- if ( strlen( $req_body ) > 0 ) {
- $out .='
- <h4>Body</h4>
- <p class="req" style="padding-bottom: 2em"><code>
- '.$o($req_body).'
- </code></p>';
- }
- }
- $out .= '
- <h3>Request <span>(parsed)</span></h3>';
- $superglobals = array('$_GET','$_POST','$_COOKIE','$_SERVER','$_ENV');
- foreach ( $superglobals as $sglobal ) {
- $sfn = create_function('','return '.$sglobal.';');
- $out .= '<h4>'.$sglobal.'</h4>';
- if ( count($sfn()) > 0 ) {
- $out .= '
- <table class="req">
- <thead>
- <tr>
- <th>Variable</th>
- <th>Value</th>
- </tr>
- </thead>
- <tbody>';
- foreach ( $sfn() as $k => $v ) {
- $out .= '<tr>
- <td>'.$o($k).'</td>
- <td class="code">
- <div>'.$o(print_r($v,TRUE)).'</div>
- </td>
- </tr>';
+
+
+ function RequestSuperlobal($var)
+ {
+ if (count($var)) {
+ $table = Tag::table(array('class' => 'req'));
+
+ $thead = Tag::thead()
+ ->append(Tag::tr()
+ ->append(Tag::th(null, 'Variable'))
+ ->append(Tag::th(null, 'Value')));
+
+ $tbody = Tag::tbody();
+ foreach ($var as $k => $v) {
+ $tbody->append(Tag::tr()
+ ->append(Tag::td()
+ ->append($k))
+ ->append(Tag::td(array('class' => 'code'))
+ ->append(Tag::div()->append(print_r($v, true)))));
}
- $out .= '
- </tbody>
- </table>';
- } else {
- $out .= '
- <p class="whitemsg">No data</p>';
- }
- }
- $out .= '
-
- </div>
-</div>';
- if ( function_exists('headers_list') ) {
- $out .= '
-<div id="response">
-
- <h2>Response
- <a href=\'#\' onclick="return sectionToggle(\'resp_switch\',\'resp_list\')">
- <span id="resp_switch">▶</span></a></h2>
-
- <div id="resp_list" class="section">
-
- <h3>Headers</h3>';
- $resp_headers = headers_list();
- if (count($resp_headers) > 0) {
- $out .= '
- <p class="headers">';
- foreach ( $resp_headers as $resp_h ) {
- $out .= $o($resp_h);
- $out .= '<br>';
+
+ return $table->append($thead)->append($tbody);
+ } else {
+ return Tag::p(array('class' => 'whitemsg'), 'No data');
+ }
+ }
+
+
+ function SectionResponse()
+ {
+ return $this->section('response', 'Response',
+ $this->ResponseHeaders());
+ }
+
+ function ResponseHeaders()
+ {
+ $r = array(
+ Tag::h3('Headers'),
+ );
+ $headers = headers_list();
+ if ($headers) {
+ $h = Tag::p(array('class' => 'headers'));
+ foreach ($headers as $header) {
+ $h->append($header)->append(Tag::br());
}
- $out .= ' </p>';
+ $r[] = $h;
} else {
- $out .= '
- <p>No headers.</p>';
- }
- $out .= '
-</div>';
- }
- $out .= '
-</body>
-</html>
-';
- return $out;
+ $r[] = Tag::p(null, 'No headers.');
+ }
+ return $r;
+ }
+
+
+ function css()
+ {
+ return Tag::style()->raw('html * { padding:0; margin:0; }
+body * { padding:10px 20px; }
+body * * { padding:0; }
+body { font:small sans-serif; background: #70DBFF; }
+body>div { border-bottom:1px solid #ddd; }
+h1 { font-weight:normal; }
+h2 { margin-bottom:.8em; }
+h2 span { font-size:80%; color:#666; font-weight:normal; }
+h2 a { text-decoration:none; }
+h3 { margin:1em 0 .5em 0; }
+h4 { margin:0.5em 0 .5em 0; font-weight: normal; font-style: italic; }
+table { border:1px solid #ccc; border-collapse: collapse; background:white; }
+tbody td, tbody th { vertical-align:top; padding:2px 3px; }
+thead th { padding:1px 6px 1px 3px; background:#70FF94; text-align:left; font-weight:bold; font-size:11px; border:1px solid #ddd; }
+tbody th { text-align:right; color:#666; padding-right:.5em; }
+.vars table { margin:5px 0 2px 40px; }
+.vars table td, table.req td { font-family:monospace; }
+table td { background: #70FFDB; }
+table td.code { width:95%;}
+table td.code div { overflow:hidden; }
+table.source th { color:#666; }
+table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
+ul.traceback { list-style-type:none; }
+ul.traceback li.frame { margin-bottom:1em; }
+div.context { margin:5px 0 2px 40px; background: #fff; border: 1px dashed #666; }
+div.context ol { padding-left:10px; margin:0 10px; list-style-position: inside; }
+div.context ol li { font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
+div.context li.current-line { color:black; background-color:#70FF94; }
+div.commands { margin-left: 40px; }
+div.commands a { color:black; text-decoration:none; }
+p.headers { background: #70FFDB; font-family:monospace; padding: 2px; }
+#summary { background: #00B8F5; }
+#summary h2 { font-weight: normal; color: #666; }
+#traceback { background:#eee; }
+#request { background:#f6f6f6; }
+#response { background:#eee; }
+#summary table { border:none; background:#00B8F5; }
+#summary td { background:#00B8F5; }
+.switch { text-decoration: none; }
+.whitemsg { background:white; color:black;}');
+ }
+
+ function js()
+ {
+ return Tag::script()->raw('
+window.onload = function() {
+ function onClick(e, c) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ if (e.addEventListener)
+ e.addEventListener("click", function(ev) { c.apply(this, args); ev.preventDefault(); }, false);
+ else
+ e.attachEvent("onclick", function(ev) { c.apply(this, args); ev.returnValue = false; });
+ }
+
+ var i, bd, sections = document.querySelectorAll(".section");
+ for (i = 0; i < sections.length; ++i) {
+ bd = sections[i].querySelector(".section-body");
+ bd.style.display = \'none\';
+ onClick(sections[i].querySelector(".section-toggle"), function (sw, bd) {
+ bd.style.display = bd.style.display == \'none\' ? \'block\' : \'none\';
+
+ var uarr = String.fromCharCode(0x25b6);
+ var darr = String.fromCharCode(0x25bc);
+ sw.innerHTML = sw.innerHTML == uarr ? darr : uarr;
+ },
+ sections[i].querySelector(".section-switch"),
+ bd);
+ }
+}');
+ }
}