better_errors 0.0.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,944 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= exception.class %> at <%= request_path %></title>
5
+ <style>
6
+ /* Basic reset */
7
+ * {
8
+ margin: 0;
9
+ padding: 0;
10
+ }
11
+
12
+ table {
13
+ width: 100%;
14
+ border-collapse: collapse;
15
+ }
16
+
17
+ th, td {
18
+ vertical-align: top;
19
+ text-align: left;
20
+ }
21
+
22
+ textarea {
23
+ resize: none;
24
+ }
25
+
26
+ body {
27
+ font-size: 10pt;
28
+ }
29
+
30
+ body, td, input, textarea {
31
+ font-family: helvetica neue, lucida grande, sans-serif;
32
+ line-height: 1.5;
33
+ color: #333;
34
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
35
+ }
36
+
37
+ html {
38
+ background: #f0f0f5;
39
+ }
40
+
41
+ /* ---------------------------------------------------------------------
42
+ * Basic layout
43
+ * --------------------------------------------------------------------- */
44
+
45
+ /* Small */
46
+ @media screen and (max-width: 1100px) {
47
+ html {
48
+ overflow-y: scroll;
49
+ }
50
+
51
+ body {
52
+ margin: 0 20px;
53
+ }
54
+
55
+ header.exception {
56
+ margin: 0 -20px;
57
+ }
58
+
59
+ nav.sidebar {
60
+ padding: 0;
61
+ margin: 20px 0;
62
+ }
63
+
64
+ ul.frames {
65
+ max-height: 200px;
66
+ overflow: auto;
67
+ }
68
+ }
69
+
70
+ /* Wide */
71
+ @media screen and (min-width: 1100px) {
72
+ header.exception {
73
+ position: fixed;
74
+ top: 0;
75
+ left: 0;
76
+ right: 0;
77
+ }
78
+
79
+ nav.sidebar,
80
+ .frame_info {
81
+ position: fixed;
82
+ top: 95px;
83
+ bottom: 0;
84
+
85
+ box-sizing: border-box;
86
+
87
+ overflow-y: auto;
88
+ overflow-x: hidden;
89
+ }
90
+
91
+ nav.sidebar {
92
+ width: 40%;
93
+ left: 20px;
94
+ top: 115px;
95
+ bottom: 20px;
96
+ }
97
+
98
+ .frame_info {
99
+ right: 0;
100
+ left: 40%;
101
+
102
+ padding: 20px;
103
+ padding-left: 10px;
104
+ margin-left: 30px;
105
+ }
106
+ }
107
+
108
+ nav.sidebar {
109
+ background: #d3d3da;
110
+ border-top: solid 3px #a33;
111
+ border-bottom: solid 3px #a33;
112
+ border-radius: 4px;
113
+ box-shadow: 0 0 6px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
114
+ }
115
+
116
+ /* ---------------------------------------------------------------------
117
+ * Header
118
+ * --------------------------------------------------------------------- */
119
+
120
+ header.exception {
121
+ padding: 18px 20px;
122
+
123
+ height: 59px;
124
+ min-height: 59px;
125
+
126
+ overflow: hidden;
127
+
128
+ background-color: #20202a;
129
+ color: #aaa;
130
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);
131
+ font-weight: 200;
132
+ box-shadow: inset 0 -5px 3px -3px rgba(0, 0, 0, 0.05), inset 0 -1px 0 rgba(0, 0, 0, 0.05);
133
+
134
+ -webkit-text-smoothing: antialiased;
135
+ }
136
+
137
+ /* Heading */
138
+ header.exception h2 {
139
+ font-weight: 200;
140
+ font-size: 11pt;
141
+ }
142
+
143
+ header.exception h2,
144
+ header.exception p {
145
+ line-height: 1.4em;
146
+ height: 1.4em;
147
+ overflow: hidden;
148
+ white-space: pre;
149
+ text-overflow: ellipsis;
150
+ }
151
+
152
+ header.exception h2 strong {
153
+ font-weight: 700;
154
+ color: #d55;
155
+ }
156
+
157
+ header.exception p {
158
+ font-weight: 200;
159
+ font-size: 20pt;
160
+ color: white;
161
+ }
162
+
163
+ header.exception:hover {
164
+ height: auto;
165
+ z-index: 2;
166
+ }
167
+
168
+ header.exception:hover h2,
169
+ header.exception:hover p {
170
+ padding-right: 20px;
171
+ overflow-y: auto;
172
+ word-wrap: break-word;
173
+ height: auto;
174
+ max-height: 7em;
175
+ }
176
+
177
+ @media screen and (max-width: 1100px) {
178
+ header.exception {
179
+ height: auto;
180
+ }
181
+
182
+ header.exception h2,
183
+ header.exception p {
184
+ padding-right: 20px;
185
+ overflow-y: auto;
186
+ word-wrap: break-word;
187
+ height: auto;
188
+ max-height: 7em;
189
+ }
190
+ }
191
+
192
+ <%#
193
+ /* Light theme */
194
+ header.exception {
195
+ text-shadow: 0 1px 0 rgba(250, 250, 250, 0.6);
196
+ background: rgba(200,100,50,0.10);
197
+ color: #977;
198
+ }
199
+ header.exception h2 strong {
200
+ color: #533;
201
+ }
202
+ header.exception p {
203
+ color: #744;
204
+ }
205
+ %>
206
+
207
+ /* ---------------------------------------------------------------------
208
+ * Navigation
209
+ * --------------------------------------------------------------------- */
210
+
211
+ nav.tabs {
212
+ border-bottom: solid 1px #ddd;
213
+
214
+ background-color: #eee;
215
+ text-align: center;
216
+
217
+ padding: 6px;
218
+
219
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
220
+ }
221
+
222
+ nav.tabs a {
223
+ display: inline-block;
224
+
225
+ height: 22px;
226
+ line-height: 22px;
227
+ padding: 0 10px;
228
+
229
+ text-decoration: none;
230
+ font-size: 8pt;
231
+ font-weight: bold;
232
+
233
+ color: #999;
234
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
235
+ }
236
+
237
+ nav.tabs a.selected {
238
+ color: white;
239
+ background: rgba(0, 0, 0, 0.5);
240
+ border-radius: 16px;
241
+ box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.1);
242
+ text-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(0, 0, 0, 0.4);
243
+ }
244
+
245
+ /* ---------------------------------------------------------------------
246
+ * Sidebar
247
+ * --------------------------------------------------------------------- */
248
+
249
+ ul.frames {
250
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
251
+ }
252
+
253
+ /* Each item */
254
+ ul.frames li {
255
+ background-color: #f8f8f8;
256
+ background: -webkit-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
257
+ background: -moz-linear-gradient(top, #f8f8f8 80%, #f0f0f0);
258
+ background: linear-gradient(top, #f8f8f8 80%, #f0f0f0);
259
+ box-shadow: inset 0 -1px 0 #e2e2e2;
260
+ padding: 7px 20px;
261
+
262
+ cursor: pointer;
263
+ overflow: hidden;
264
+ }
265
+
266
+ ul.frames .name,
267
+ ul.frames .location {
268
+ overflow: hidden;
269
+ height: 1.5em;
270
+
271
+ white-space: nowrap;
272
+ word-wrap: none;
273
+ text-overflow: ellipsis;
274
+ }
275
+
276
+ ul.frames .method {
277
+ color: #966;
278
+ }
279
+
280
+ ul.frames .location {
281
+ font-size: 0.85em;
282
+ font-weight: 400;
283
+ color: #999;
284
+ }
285
+
286
+ ul.frames .line {
287
+ font-weight: bold;
288
+ }
289
+
290
+ /* Selected frame */
291
+ ul.frames li.selected {
292
+ background: #38a;
293
+ box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), inset 0 2px 0 rgba(255, 255, 255, 0.01), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
294
+ }
295
+
296
+ ul.frames li.selected .name,
297
+ ul.frames li.selected .method,
298
+ ul.frames li.selected .location {
299
+ color: white;
300
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
301
+ }
302
+
303
+ ul.frames li.selected .location {
304
+ opacity: 0.6;
305
+ }
306
+
307
+ /* Iconography */
308
+ ul.frames li {
309
+ padding-left: 60px;
310
+ position: relative;
311
+ }
312
+
313
+ ul.frames li .icon {
314
+ display: block;
315
+ width: 20px;
316
+ height: 20px;
317
+ line-height: 20px;
318
+ border-radius: 15px;
319
+
320
+ text-align: center;
321
+
322
+ background: white;
323
+ border: solid 2px #ccc;
324
+
325
+ font-size: 9pt;
326
+ font-weight: 200;
327
+ font-style: normal;
328
+
329
+ position: absolute;
330
+ top: 14px;
331
+ left: 20px;
332
+ }
333
+
334
+ ul.frames .icon.application {
335
+ background: #808090;
336
+ border-color: #555;
337
+ }
338
+
339
+ ul.frames .icon.application:before {
340
+ content: 'A';
341
+ color: white;
342
+ text-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
343
+ }
344
+
345
+ /* Responsiveness -- flow to single-line mode */
346
+ @media screen and (max-width: 1100px) {
347
+ ul.frames li {
348
+ padding-top: 6px;
349
+ padding-bottom: 6px;
350
+ padding-left: 36px;
351
+ line-height: 1.3;
352
+ }
353
+
354
+ ul.frames li .icon {
355
+ width: 11px;
356
+ height: 11px;
357
+ line-height: 11px;
358
+
359
+ top: 7px;
360
+ left: 10px;
361
+ font-size: 5pt;
362
+ }
363
+
364
+ ul.frames .name,
365
+ ul.frames .location {
366
+ display: inline-block;
367
+ line-height: 1.3;
368
+ height: 1.3em;
369
+ }
370
+
371
+ ul.frames .name {
372
+ margin-right: 10px;
373
+ }
374
+ }
375
+
376
+ /* ---------------------------------------------------------------------
377
+ * Monospace
378
+ * --------------------------------------------------------------------- */
379
+
380
+ pre, code, .repl input, .repl .prompt span, textarea {
381
+ font-family: menlo, lucida console, monospace;
382
+ font-size: 8pt;
383
+ }
384
+
385
+ /* ---------------------------------------------------------------------
386
+ * Display area
387
+ * --------------------------------------------------------------------- */
388
+
389
+ .trace_info {
390
+ background: #fff;
391
+ padding: 6px;
392
+ border-radius: 3px;
393
+ margin-bottom: 2px;
394
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.03), 1px 1px 0 rgba(0, 0, 0, 0.05), -1px 1px 0 rgba(0, 0, 0, 0.05), 0 0 0 4px rgba(0, 0, 0, 0.04);
395
+ }
396
+
397
+ /* Titlebar */
398
+ .trace_info .title {
399
+ background: #f1f1f1;
400
+
401
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
402
+ overflow: hidden;
403
+ padding: 6px 10px;
404
+
405
+ border: solid 1px #ccc;
406
+ border-bottom: 0;
407
+
408
+ border-top-left-radius: 2px;
409
+ border-top-right-radius: 2px;
410
+ }
411
+
412
+ .trace_info .title .name,
413
+ .trace_info .title .location {
414
+ font-size: 9pt;
415
+ line-height: 26px;
416
+ height: 26px;
417
+ overflow: hidden;
418
+ }
419
+
420
+ .trace_info .title .location {
421
+ float: left;
422
+ font-weight: bold;
423
+ font-size: 10pt;
424
+ }
425
+
426
+ .trace_info .title .name {
427
+ float: right;
428
+ font-weight: 200;
429
+ }
430
+
431
+ .code, .console, .unavailable {
432
+ background: #fff;
433
+ padding: 5px;
434
+
435
+ box-shadow: inset 3px 3px 3px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
436
+ }
437
+
438
+ .code {
439
+ margin-bottom: -1px;
440
+ }
441
+
442
+ .code {
443
+ padding: 10px 0;
444
+ overflow: auto;
445
+ }
446
+
447
+ /* Source unavailable */
448
+ p.unavailable {
449
+ padding: 20px 0 40px 0;
450
+ text-align: center;
451
+ color: #b99;
452
+ font-weight: bold;
453
+ }
454
+
455
+ p.unavailable:before {
456
+ content: '\00d7';
457
+ display: block;
458
+
459
+ color: #daa;
460
+
461
+ text-align: center;
462
+ font-size: 40pt;
463
+ font-weight: normal;
464
+ margin-bottom: -10px;
465
+ }
466
+
467
+ @-webkit-keyframes highlight {
468
+ 0% { background: rgba(220, 30, 30, 0.3); }
469
+ 100% { background: rgba(220, 30, 30, 0.1); }
470
+ }
471
+ @-moz-keyframes highlight {
472
+ 0% { background: rgba(220, 30, 30, 0.3); }
473
+ 100% { background: rgba(220, 30, 30, 0.1); }
474
+ }
475
+ @keyframes highlight {
476
+ 0% { background: rgba(220, 30, 30, 0.3); }
477
+ 100% { background: rgba(220, 30, 30, 0.1); }
478
+ }
479
+
480
+ .code .highlight {
481
+ background: rgba(220, 30, 30, 0.1);
482
+ -webkit-animation: highlight 400ms linear 1;
483
+ -moz-animation: highlight 400ms linear 1;
484
+ animation: highlight 400ms linear 1;
485
+ }
486
+
487
+ /* REPL shell */
488
+ .console {
489
+ padding: 0 1px 10px 1px;
490
+ border-bottom-left-radius: 2px;
491
+ border-bottom-right-radius: 2px;
492
+ }
493
+
494
+ .console pre {
495
+ padding: 10px 10px 0 10px;
496
+ max-height: 200px;
497
+ overflow-x: none;
498
+ overflow-y: auto;
499
+ margin-bottom: -3px;
500
+ word-wrap: break-word;
501
+ white-space: pre-wrap;
502
+ }
503
+
504
+ /* .prompt > span + input */
505
+ .console .prompt {
506
+ display: table;
507
+ width: 100%;
508
+ }
509
+
510
+ .console .prompt span,
511
+ .console .prompt input {
512
+ display: table-cell;
513
+ }
514
+
515
+ .console .prompt span {
516
+ width: 1%;
517
+ padding-right: 5px;
518
+ padding-left: 10px;
519
+ }
520
+
521
+ .console .prompt input {
522
+ width: 99%;
523
+ }
524
+
525
+ /* Input box */
526
+ .console input,
527
+ .console input:focus {
528
+ outline: 0;
529
+ border: 0;
530
+ padding: 0;
531
+ background: transparent;
532
+ margin: 0;
533
+ }
534
+
535
+ /* Hint text */
536
+ .hint {
537
+ margin: 15px 0 20px 0;
538
+ font-size: 8pt;
539
+ color: #8080a0;
540
+ padding-left: 20px;
541
+ }
542
+
543
+ .hint:before {
544
+ content: '\25b2';
545
+ margin-right: 5px;
546
+ opacity: 0.5;
547
+ }
548
+
549
+ /* ---------------------------------------------------------------------
550
+ * Variable infos
551
+ * --------------------------------------------------------------------- */
552
+
553
+ .sub {
554
+ padding: 10px 0;
555
+ margin: 10px 0;
556
+ }
557
+
558
+ .sub:before {
559
+ content: '';
560
+ display: block;
561
+ width: 100%;
562
+ height: 4px;
563
+
564
+ border-radius: 2px;
565
+ background: rgba(0, 150, 200, 0.05);
566
+ box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7), inset 0 0 0 1px rgba(0, 0, 0, 0.04), inset 2px 2px 2px rgba(0, 0, 0, 0.07);
567
+ }
568
+
569
+ .sub h3 {
570
+ color: #39a;
571
+ font-size: 1.1em;
572
+ margin: 10px 0;
573
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
574
+
575
+ -webkit-font-smoothing: antialiased;
576
+ }
577
+
578
+ .sub .inset {
579
+ overflow-y: auto;
580
+ }
581
+
582
+ .sub table {
583
+ table-layout: fixed;
584
+ }
585
+
586
+ .sub table td {
587
+ border-top: dotted 1px #ddd;
588
+ padding: 7px 1px;
589
+ }
590
+
591
+ .sub table td.name {
592
+ width: 150px;
593
+
594
+ font-weight: bold;
595
+ font-size: 0.8em;
596
+ padding-right: 20px;
597
+ }
598
+
599
+ .sub table td pre {
600
+ max-height: 15em;
601
+ overflow-y: auto;
602
+ }
603
+
604
+ .sub table td pre {
605
+ width: 100%;
606
+
607
+ word-wrap: break-word;
608
+ white-space: normal;
609
+ }
610
+
611
+ /* ---------------------------------------------------------------------
612
+ * Scrollbar
613
+ * --------------------------------------------------------------------- */
614
+
615
+ nav.sidebar::-webkit-scrollbar,
616
+ .inset pre::-webkit-scrollbar,
617
+ .console pre::-webkit-scrollbar,
618
+ .code::-webkit-scrollbar {
619
+ width: 10px;
620
+ height: 10px;
621
+ }
622
+
623
+ .inset pre::-webkit-scrollbar-thumb,
624
+ .console pre::-webkit-scrollbar-thumb,
625
+ .code::-webkit-scrollbar-thumb {
626
+ background: #ccc;
627
+ border-radius: 5px;
628
+ }
629
+
630
+ nav.sidebar::-webkit-scrollbar-thumb {
631
+ background: rgba(0, 0, 0, 0.0);
632
+ border-radius: 5px;
633
+ }
634
+
635
+ nav.sidebar:hover::-webkit-scrollbar-thumb {
636
+ background-color: #999;
637
+ background: -webkit-linear-gradient(left, #aaa, #999);
638
+ }
639
+
640
+ .console pre:hover::-webkit-scrollbar-thumb,
641
+ .inset pre:hover::-webkit-scrollbar-thumb,
642
+ .code:hover::-webkit-scrollbar-thumb {
643
+ background: #888;
644
+ }
645
+
646
+
647
+ </style>
648
+ </head>
649
+ <body>
650
+ <div class='top'>
651
+ <header class="exception">
652
+ <h2><strong><%= exception.class %></strong> <span>at <%= request_path %></span></h2>
653
+ <p><%= exception_message %></p>
654
+ </header>
655
+ </div>
656
+
657
+ <section class="backtrace">
658
+ <nav class="sidebar">
659
+ <nav class="tabs">
660
+ <a href="#" id="application_frames">Application Frames</a>
661
+ <a href="#" id="all_frames">All Frames</a>
662
+ </nav>
663
+ <ul class="frames">
664
+ <% backtrace_frames.each_with_index do |frame, index| %>
665
+ <li
666
+ class="<%= frame.context %>"
667
+ style="display: none"
668
+ data-context="<%= frame.context %>"
669
+ data-full-filename="<%= frame.filename %>"
670
+ data-filename="<%= frame.pretty_path %>"
671
+ data-line="<%= frame.line %>"
672
+ data-name="<%= frame.name %>"
673
+ data-index="<%= index %>"
674
+ >
675
+ <span class='stroke'></span>
676
+ <i class="icon <%= frame.context %>"></i>
677
+ <div class="info">
678
+ <div class="name">
679
+ <strong><%= frame.class_name %></strong><span class='method'><%= frame.method_name %></span>
680
+ </div>
681
+ <div class="location">
682
+ <span class="filename"><%= frame.pretty_path %></span>, line <span class="line"><%= frame.line %></span>
683
+ </div>
684
+ </div>
685
+ </li>
686
+ <% end %>
687
+ </ul>
688
+ </nav>
689
+
690
+ <% backtrace_frames.each_with_index do |frame, index| %>
691
+ <div class="frame_info" id="frame_info_<%= index %>" style="display:none;">
692
+ <header class="trace_info">
693
+ <div class="title">
694
+ <h2 class="name"><%= frame.name %></h2>
695
+ <div class="location"><span class="filename"><%= frame.pretty_path %></span></div>
696
+ </div>
697
+
698
+ <%== highlighted_code_block frame %>
699
+
700
+ <% if BetterErrors.binding_of_caller_available? && frame.frame_binding %>
701
+ <div class="repl">
702
+ <div class="console">
703
+ <pre></pre>
704
+ <div class="prompt"><span>&gt;&gt;</span> <input/></div>
705
+ </div>
706
+ </div>
707
+ <% end %>
708
+ </header>
709
+
710
+ <% if BetterErrors.binding_of_caller_available? && frame.frame_binding %>
711
+ <div class="hint">
712
+ This a live shell. Type in here.
713
+ </div>
714
+
715
+ <div class="variable_info"></div>
716
+ <% end %>
717
+
718
+ <% unless BetterErrors.binding_of_caller_available? %>
719
+ <div class="hint">
720
+ <strong>Tip:</strong> add <code>gem "binding_of_caller"</code> to your Gemfile to enable the REPL and local/instance variable inspection.
721
+ </div>
722
+ <% end %>
723
+ </div>
724
+ <% end %>
725
+ <div style="clear:both"></div>
726
+ </section>
727
+ </body>
728
+ <script>
729
+ (function() {
730
+ var OID = <%== object_id.to_s.inspect %>;
731
+
732
+ var previousFrame = null;
733
+ var previousFrameInfo = null;
734
+ var allFrames = document.querySelectorAll("ul.frames li");
735
+ var allFrameInfos = document.querySelectorAll(".frame_info");
736
+
737
+ function apiCall(method, opts, cb) {
738
+ var req = new XMLHttpRequest();
739
+ req.open("POST", "/__better_errors/" + OID + "/" + method, true);
740
+ req.setRequestHeader("Content-Type", "application/json");
741
+ req.send(JSON.stringify(opts));
742
+ req.onreadystatechange = function() {
743
+ if(req.readyState == 4) {
744
+ var res = JSON.parse(req.responseText);
745
+ cb(res);
746
+ }
747
+ };
748
+ }
749
+
750
+ function escapeHTML(html) {
751
+ return html.replace(/&/, "&amp;").replace(/</g, "&lt;");
752
+ }
753
+
754
+ function REPL(index) {
755
+ this.index = index;
756
+
757
+ this.previousCommands = [];
758
+ this.previousCommandOffset = 0;
759
+ }
760
+
761
+ REPL.all = [];
762
+
763
+ REPL.prototype.install = function(containerElement) {
764
+ this.container = containerElement;
765
+
766
+ this.promptElement = this.container.querySelector(".prompt span");
767
+ this.inputElement = this.container.querySelector("input");
768
+ this.outputElement = this.container.querySelector("pre");
769
+
770
+ this.inputElement.onkeydown = this.onKeyDown.bind(this);
771
+
772
+ this.setPrompt(">>");
773
+
774
+ REPL.all[this.index] = this;
775
+ }
776
+
777
+ REPL.prototype.focus = function() {
778
+ this.inputElement.focus();
779
+ };
780
+
781
+ REPL.prototype.setPrompt = function(prompt) {
782
+ this._prompt = prompt;
783
+ this.promptElement.innerHTML = escapeHTML(prompt);
784
+ };
785
+
786
+ REPL.prototype.getInput = function() {
787
+ return this.inputElement.value;
788
+ };
789
+
790
+ REPL.prototype.setInput = function(text) {
791
+ this.inputElement.value = text;
792
+
793
+ if(this.inputElement.setSelectionRange) {
794
+ // set cursor to end of input
795
+ this.inputElement.setSelectionRange(text.length, text.length);
796
+ }
797
+ };
798
+
799
+ REPL.prototype.writeRawOutput = function(output) {
800
+ this.outputElement.innerHTML += output;
801
+ this.outputElement.scrollTop = this.outputElement.scrollHeight;
802
+ };
803
+
804
+ REPL.prototype.writeOutput = function(output) {
805
+ this.writeRawOutput(escapeHTML(output));
806
+ };
807
+
808
+ REPL.prototype.sendInput = function(line) {
809
+ var self = this;
810
+ apiCall("eval", { "index": this.index, source: line }, function(response) {
811
+ if(response.error) {
812
+ self.writeOutput(response.error + "\n");
813
+ }
814
+ self.writeOutput(self._prompt + " ");
815
+ self.writeRawOutput(response.highlighted_input + "\n");
816
+ self.writeOutput(response.result);
817
+ self.setPrompt(response.prompt);
818
+ });
819
+ };
820
+
821
+ REPL.prototype.onEnterKey = function() {
822
+ var text = this.getInput();
823
+ if(text != "" && text !== undefined) {
824
+ this.previousCommandOffset = this.previousCommands.push(text);
825
+ }
826
+ this.setInput("");
827
+ this.sendInput(text);
828
+ };
829
+
830
+ REPL.prototype.onNavigateHistory = function(direction) {
831
+ this.previousCommandOffset += direction;
832
+
833
+ if(this.previousCommandOffset < 0) {
834
+ this.previousCommandOffset = -1;
835
+ this.setInput("");
836
+ return;
837
+ }
838
+
839
+ if(this.previousCommandOffset >= this.previousCommands.length) {
840
+ this.previousCommandOffset = this.previousCommands.length;
841
+ this.setInput("");
842
+ return;
843
+ }
844
+
845
+ this.setInput(this.previousCommands[this.previousCommandOffset]);
846
+ };
847
+
848
+ REPL.prototype.onKeyDown = function(ev) {
849
+ if(ev.keyCode == 13) {
850
+ this.onEnterKey();
851
+ } else if(ev.keyCode == 38) {
852
+ // the user pressed the up arrow.
853
+ this.onNavigateHistory(-1);
854
+ return false;
855
+ } else if(ev.keyCode == 40) {
856
+ // the user pressed the down arrow.
857
+ this.onNavigateHistory(1);
858
+ return false;
859
+ }
860
+ };
861
+
862
+ function populateVariableInfo(index) {
863
+ var el = allFrameInfos[index];
864
+ var varInfo = el.querySelector(".variable_info");
865
+ if(varInfo && varInfo.innerHTML == "") {
866
+ apiCall("variables", { "index": index }, function(response) {
867
+ if(response.error) {
868
+ varInfo.innerHTML = "<span class='error'>" + escapeHTML(response.error) + "</span>";
869
+ } else {
870
+ varInfo.innerHTML = response.html;
871
+ }
872
+ });
873
+ }
874
+ }
875
+
876
+ function selectFrameInfo(index) {
877
+ populateVariableInfo(index);
878
+
879
+ if(previousFrameInfo) {
880
+ previousFrameInfo.style.display = "none";
881
+ }
882
+ previousFrameInfo = allFrameInfos[index];
883
+ previousFrameInfo.style.display = "block";
884
+
885
+ if(REPL.all[index]) {
886
+ REPL.all[index].focus();
887
+ }
888
+ }
889
+
890
+ for(var i = 0; i < allFrames.length; i++) {
891
+ (function(i, el) {
892
+ var el = allFrames[i];
893
+ el.onclick = function() {
894
+ if(previousFrame) {
895
+ previousFrame.className = "";
896
+ }
897
+ el.className = "selected";
898
+ previousFrame = el;
899
+
900
+ selectFrameInfo(el.attributes["data-index"].value);
901
+ };
902
+ var repl = allFrameInfos[i].querySelector(".repl .console");
903
+ if(repl) {
904
+ new REPL(i).install(repl);
905
+ }
906
+ })(i);
907
+ }
908
+
909
+ // Click the first application frame
910
+ (
911
+ document.querySelector(".frames li.application") ||
912
+ document.querySelector(".frames li")
913
+ ).click();
914
+
915
+ var applicationFramesButton = document.getElementById("application_frames");
916
+ var allFramesButton = document.getElementById("all_frames");
917
+
918
+ applicationFramesButton.onclick = function() {
919
+ allFramesButton.className = "";
920
+ applicationFramesButton.className = "selected";
921
+ for(var i = 0; i < allFrames.length; i++) {
922
+ if(allFrames[i].attributes["data-context"].value == "application") {
923
+ allFrames[i].style.display = "block";
924
+ } else {
925
+ allFrames[i].style.display = "none";
926
+ }
927
+ }
928
+ return false;
929
+ };
930
+
931
+ allFramesButton.onclick = function() {
932
+ applicationFramesButton.className = "";
933
+ allFramesButton.className = "selected";
934
+ for(var i = 0; i < allFrames.length; i++) {
935
+ allFrames[i].style.display = "block";
936
+ }
937
+ return false;
938
+ };
939
+
940
+ applicationFramesButton.click();
941
+ })();
942
+ </script>
943
+ </html>
944
+ <!-- generated by Better Errors in <%= Time.now.to_f - @start_time %> seconds -->