├── .gitignore
├── .gitmodules
├── .htaccess
├── LICENSE
├── README
├── TODO
├── config.js.php
├── cpp_visualizer.txt
├── embed
├── README
├── css
│ ├── jquery.qtip.css
│ ├── opt-frontend.css
│ ├── pytutor.css
│ └── ui-lightness
│ │ ├── images
│ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png
│ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png
│ │ ├── ui-bg_flat_10_000000_40x100.png
│ │ ├── ui-bg_glass_100_f6f6f6_1x400.png
│ │ ├── ui-bg_glass_100_fdf5ce_1x400.png
│ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png
│ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png
│ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png
│ │ ├── ui-icons_222222_256x240.png
│ │ ├── ui-icons_228ef1_256x240.png
│ │ ├── ui-icons_ef8c08_256x240.png
│ │ ├── ui-icons_ffd27a_256x240.png
│ │ └── ui-icons_ffffff_256x240.png
│ │ └── jquery-ui-1.8.24.custom.css
└── js
│ ├── d3.v2.min.js
│ ├── iframe-embed.js
│ ├── jquery-1.8.2.min.js
│ ├── jquery-ui-1.8.24.custom.min.js
│ ├── jquery.ba-bbq.min.js
│ ├── jquery.jsPlumb-1.3.10-all-min.js
│ ├── jquery.qtip.min.js
│ ├── opt-frontend-common.js
│ ├── opt-frontend.js
│ └── pytutor.js
├── example-code
├── (Default).java
├── .dir-locals.el
├── .gitignore
├── .htaccess
├── Casting.java
├── CmdLineArgs.java
├── Complex.java
├── ControlFlow.java
├── Exception.java
├── ExceptionFlow.java
├── ExecLimit.java
├── Forest.java
├── Knapsack.java
├── LambdaExample.java
├── LinkedList.java
├── PassByValue.java
├── Person.java
├── Postfix.java
├── Recursion.java
├── Reflect.java
├── Rolex.java
├── Sqrt.java
├── StackOverflow.java
├── StackQueue.java
├── StaticInitializer.java
├── StdIn.java
├── Strings.java
├── SymbolTable.java
├── Synthetic.java
├── ToString.java
├── TwoClasses.java
└── Variables.java
├── iframe-embed.html
├── img
├── README
├── jv.svg
├── jv128.png
├── jv256.png
├── jv32.png
└── jv64.png
├── index.html
├── java_safe_ram_maketrace.php
├── jv-config.example.json
├── jv-frontend.js
├── pytutor-customizations.css
└── pytutor-customizations.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | # hide this file
3 | # also things like jv-config.json~ and #jv-config.json#
4 | *jv-config.json*
5 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "CodeMirror"]
2 | path = CodeMirror
3 | url = https://github.com/marijnh/CodeMirror.git
4 | [submodule "OnlinePythonTutor"]
5 | path = OnlinePythonTutor
6 | url = https://github.com/pgbovine/OnlinePythonTutor.git
7 |
--------------------------------------------------------------------------------
/.htaccess:
--------------------------------------------------------------------------------
1 | # hide this file
2 | # also things like jv-config.json~ and #jv-config.json#
3 |
4 | Order Allow,Deny
5 | Deny from all
6 |
7 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | java_visualize: visualization for java
2 | David Pritchard (daveagp@gmail.com), created May 2013
3 |
4 | This is the frontend for a Java visualizer. It is based on "Online Python Tutor",
5 | a Python visualizer by Philip Guo. Try it at these mirrors (as of time of writing):
6 |
7 | http://cscircles.cemc.uwaterloo.ca/java_visualize/ (Java 8)
8 | http://www.cs.princeton.edu/~cos126/java_visualize/ (Java 7)
9 |
10 | The Online Python Tutor repo contains both a frontend and backend.
11 | For Java wre readapt the frontend (so this repo contains OnlinePythonTutor
12 | as a subrepo) and replace the backend (it is in the java_jail repo mentioned
13 | below, since it runs in a sandbox).
14 |
15 | INSTALLATION
16 |
17 | Install these on your server first:
18 | https://github.com/cemc/safeexec
19 | https://github.com/daveagp/java_jail
20 | This requires root access. See the instructions therein for details. It is best to
21 | install these in locations that are not served to users by your web server.
22 |
23 | Next, in some folder accessible to your web server, run
24 |
25 | git clone --recursive https://github.com/daveagp/java_visualize
26 |
27 | It's recursive because it includes two submodules. Because of this,
28 | to update, use the pair of commands
29 | git pull; git submodule update
30 |
31 | At this point, visiting
32 | http://your.website/url/to/java_visualize/
33 | should give you a beautiful (but non-working) frontend, and
34 | http://your.website/url/to/java_visualize/java_safe_ram_maketrace.php
35 | should give you a "Couldn't find jv-config.json" error.
36 |
37 | Next, copy jv-config.example.json to jv-config.json. Now visiting
38 | http://your.website/url/to/java_visualize/java_safe_ram_maketrace.php
39 | should give you a "http mangling" error.
40 |
41 | Finally, edit jv-config.json to indicate where you installed safeexec
42 | and java_jail. (Just those first two entries need to be changed right now.)
43 |
44 | Now, try the visualizer out!
45 |
46 | THE "C++ VISUALIZER"
47 | See cpp_visualizer.txt.
48 |
49 | FAQ
50 | -- click on "Click for FAQ" on the visualizer page
51 |
52 | MORE INFO
53 | -- index.html is a modified version of visualize.html
54 | -- jv-frontend.js is a modified version of opt-frontend.js
55 | -- java_safe_ram_maketrace.php connects the frontend to the backend
56 | -- config.* is used for configuration stuff specific to your server
57 | -- pytutor-customizations.{js,css} overrides some behaviour of OPT
58 | -- example-code is a directory full of example Java files to visualize
59 |
60 | Note that in the entire frontend, only the two .php files are
61 | written in a server-side language. Everything else we use is static,
62 | although OnlinePythonTutor has some server-side files that this Java
63 | version does not use.
64 |
65 | If you use a database, you'll be putting a DB password in jv-config.json.
66 | Please check that
67 | http://your.website/url/to/java_visualize/jv-config.json
68 | is inaccessible; .htaccess tries to do this, but you should confirm it works.
69 |
70 | ====
71 |
72 | The modified files (index.html, jv-frontend.js) retain the MIT license
73 | under which they were published in the OnlinePythonTutor repo.
74 |
75 | The other files are released under
76 | the GNU Affero General Public License, versions 3 or later. See LICENSE
77 | or visit: http://www.gnu.org/licenses/agpl.html
78 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | graphics! either encode primitive operations as text, or send frames
2 |
3 | short hashes for urls
4 |
5 | caches for past visualizations (probably don't cache 10 times to see if randomized/time-dependent)
6 |
7 | figure out suspend/resume (e.g. for exception handling, data structures)
8 |
9 | allow selective visualization of contents of some built-in classes
10 |
11 | (suggested by Jeff Kang)
12 | When the slider has focus, press "j" (for jump), or another key, and follow that with a number.
13 | That would teleport you to the line of code that corresponds to that number.
14 | The difficulty is that multiple Frames-Objects pair images can belong to 1 line of code.
15 | If it's possible, perhaps show a list of all the pairs.
16 | The pairs could be shortened, compacted, and/or summarized to fit on the screen.
17 | Maybe it just lists the step numbers that correspond to that line number.
18 | Then, a person would be allowed to choose the Frames-Objects pair to skip to.
19 | Or, just pick the earliest Frames-Objects pair that will appear from the current step.
20 | That is, "what's the next step that will take me to this line of code?".
21 |
22 |
23 | (suggested by James Vanderhyde)
24 | improve flow when a return statement is followed by an assignment of that value:
25 | the value disappears and then comes back
26 |
27 | (suggested by Brad Vander Zanden)
28 | If a statement modifies the value of a variable/object, it would be helpful to highlight that value/object so that the student can instantly see what has been modified.
29 |
30 | inner classes, local classes, anonymous classes, lambdas, captured final variables, this$ ...
31 | - right now we show things exactly from JDWP, like Eclipse or NetBeans
32 | - no way to recover all lambda arg names given current bytecode
33 | - could desugar 2 frames into one and pass "this" to nicen a bit
34 | - here's a class that throws a JWDP exception in both java 7 and 8
35 |
36 | public class JWDP32 {
37 | public static void main(String[] args) {
38 | // x needs to be final, but not a compile-time constant
39 | final int x = Math.random() < 2 ? 42 : -42;
40 | Object anon = new Object(){int f(){return x;}};
41 | class Local{int g(){return x;}}
42 | Local loc = new Local();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/config.js.php:
--------------------------------------------------------------------------------
1 | < as follows:
13 | {real Java code to visualize} //>< {fake C++ code to show to the student}
14 | For instance, go to http://cscircles.cemc.uwaterloo.ca/java_visualize/
15 | and type in the following:
16 |
17 | public class C { public static void main(String[] args) { //> < cout << x+y << endl;
21 | }} //><}
22 |
23 | So you're basically writing 2 parallel programs, though lines that are
24 | identical in Java and C++ only need to be typed in once (e.g. "int x = 2;").
25 |
26 | At the moment, I've only deployed these fake visualizations with the embedded
27 | iframe version of the Python Tutor/Java Visualizer, which sort of makes sense
28 | because in this interface it's not editable, but also because our use case
29 | was embedding in course notes. The notes are here:
30 | http://bits.usc.edu/cs103-s15/schedule/
31 | E.g., see this lecture's notes:
32 | http://bits.usc.edu/cs103-s15/control/
33 |
34 | USAGE GUIDE
35 |
36 | You can either do this with your own server, or use a pre-existing one.
37 |
38 | Installing the Java Visualizer (see the README) automatically gives you
39 | the ability to do fake C++ visualizations.
40 |
41 | There is a configuration variable called "faking_cpp" in
42 | pytutor-customizations.js that eases the workflow for creating fake C++
43 | visualizations and makes some superficial changes to some labels.
44 |
45 | For instance, you can use this mirror where it's enabled by default:
46 | http://bits.usc.edu/java_visualize/
47 |
48 | You also can override it by setting the http query variable faking_cpp,
49 | so here is another server you can use:
50 | http://cscircles.cemc.uwaterloo.ca/java_visualize/?faking_cpp=true
51 |
52 | Once there, enter your fake visualization. Once you're happy with it,
53 | copy the "Embeddable iframe:" field into whatever html you like.
54 |
55 | The ugly part of the workflow at the moment is editing a previously-created
56 | animation, which at this point requires editing or converting the URL-encoded
57 | version of the code. If you find this a big hassle, feel free to get in
58 | touch, or please send a pull request if you create a easy solution.
59 |
60 | NOTES
61 |
62 | Right now, the backend is agnostic as to whether it's visualizing true
63 | Java or faking C++. It would be better to fix this, e.g. so main returns 0
64 | and not VOID when we're faking C++.
65 |
66 | To see how this is implemented, search for 'fakify' in the java_jail repo.
67 |
68 | There's nothing special about C++ aside from the semantics and code flow
69 | being similar to Java; you could use this to fake-visualize any
70 | other language depending on how much work you're willing to put into writing
71 | 2 parallel versions of the code.
72 |
73 | The Java/C++ embedded visualizer is using a modification of an old version
74 | of the embedded visualizer code. See embed/README for details. It would
75 | be nice to bring it up to date.
76 |
77 | A few educators and students that I have talked to have ideas and partial
78 | implementations of a "real" C++ visualizer, either by piping through gdb,
79 | or by using LLDB's API, or by doing something like valgrind. Please email
80 | me if you have made progress in this direction or if you want to touch
81 | base with others who are interested.
82 |
--------------------------------------------------------------------------------
/embed/README:
--------------------------------------------------------------------------------
1 | Note! This repository is using a crufty old version of the visualizer
2 | for embedding.
3 |
4 | The reason for this is laziness, but specifically because there are
5 | features of the Java Visualizer not yet supported on the main branch and
6 | at pythontutor.com (as of the date of writing), in particular
7 | command-line arguments and standard input.
8 |
9 | As a result, this subdirectory has out-of-date copies from an old
10 | version of the Python Tutor, which were then manually changed to be
11 | Java-friendly.
12 |
13 | For reference, the files in this directry were taken from
14 | https://github.com/cemc/cscircles-wp-content
15 | in the directory pybox/OnlinePythonTutor3-cemc
16 | and then modified.
17 |
18 |
--------------------------------------------------------------------------------
/embed/css/jquery.qtip.css:
--------------------------------------------------------------------------------
1 | /*! qTip2 - Pretty powerful tooltips - v2.0.0 - 2012-09-10
2 | * http://craigsworks.com/projects/qtip2/
3 | * Copyright (c) 2012 Craig Michael Thompson; Licensed MIT, GPL */
4 |
5 | /* Fluid class for determining actual width in IE */
6 | #qtip-rcontainer{
7 | position: absolute;
8 | left: -28000px;
9 | top: -28000px;
10 | display: block;
11 | visibility: hidden;
12 | }
13 |
14 | /* Fluid class for determining actual width in IE */
15 | #qtip-rcontainer .ui-tooltip{
16 | display: block !important;
17 | visibility: hidden !important;
18 | position: static !important;
19 | float: left !important;
20 | }
21 |
22 | /* Core qTip styles */
23 | .ui-tooltip, .qtip{
24 | position: absolute;
25 | left: -28000px;
26 | top: -28000px;
27 | display: none;
28 |
29 | max-width: 280px;
30 | min-width: 50px;
31 |
32 | font-size: 10.5px;
33 | line-height: 12px;
34 | }
35 |
36 | .ui-tooltip-content{
37 | position: relative;
38 | padding: 5px 9px;
39 | overflow: hidden;
40 |
41 | text-align: left;
42 | word-wrap: break-word;
43 | }
44 |
45 | .ui-tooltip-titlebar{
46 | position: relative;
47 | min-height: 14px;
48 | padding: 5px 35px 5px 10px;
49 | overflow: hidden;
50 |
51 | border-width: 0 0 1px;
52 | font-weight: bold;
53 | }
54 |
55 | .ui-tooltip-titlebar + .ui-tooltip-content{ border-top-width: 0 !important; }
56 |
57 | /* Default close button class */
58 | .ui-tooltip-titlebar .ui-state-default{
59 | position: absolute;
60 | right: 4px;
61 | top: 50%;
62 | margin-top: -9px;
63 |
64 | cursor: pointer;
65 | outline: medium none;
66 |
67 | border-width: 1px;
68 | border-style: solid;
69 | }
70 |
71 | * html .ui-tooltip-titlebar .ui-state-default{ top: 16px; } /* IE fix */
72 |
73 | .ui-tooltip-titlebar .ui-icon,
74 | .ui-tooltip-icon .ui-icon{
75 | display: block;
76 | text-indent: -1000em;
77 | direction: ltr;
78 | }
79 |
80 | .ui-tooltip-icon, .ui-tooltip-icon .ui-icon{
81 | -moz-border-radius: 3px;
82 | -webkit-border-radius: 3px;
83 | border-radius: 3px;
84 | text-decoration: none;
85 | }
86 |
87 | .ui-tooltip-icon .ui-icon{
88 | width: 18px;
89 | height: 14px;
90 |
91 | text-align: center;
92 | text-indent: 0;
93 | font: normal bold 10px/13px Tahoma,sans-serif;
94 |
95 | color: inherit;
96 | background: transparent none no-repeat -100em -100em;
97 | }
98 |
99 |
100 | /* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
101 | .ui-tooltip-focus{}
102 |
103 | /* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
104 | .ui-tooltip-hover{}
105 |
106 | /* Default tooltip style */
107 | .ui-tooltip-default{
108 | border-width: 1px;
109 | border-style: solid;
110 | border-color: #F1D031;
111 |
112 | background-color: #FFFFA3;
113 | color: #555;
114 | }
115 |
116 | .ui-tooltip-default .ui-tooltip-titlebar{
117 | background-color: #FFEF93;
118 | }
119 |
120 | .ui-tooltip-default .ui-tooltip-icon{
121 | border-color: #CCC;
122 | background: #F1F1F1;
123 | color: #777;
124 | }
125 |
126 | .ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{
127 | border-color: #AAA;
128 | color: #111;
129 | }
130 |
131 |
132 | /*! Light tooltip style */
133 | .ui-tooltip-light{
134 | background-color: white;
135 | border-color: #E2E2E2;
136 | color: #454545;
137 | }
138 |
139 | .ui-tooltip-light .ui-tooltip-titlebar{
140 | background-color: #f1f1f1;
141 | }
142 |
143 |
144 | /*! Dark tooltip style */
145 | .ui-tooltip-dark{
146 | background-color: #505050;
147 | border-color: #303030;
148 | color: #f3f3f3;
149 | }
150 |
151 | .ui-tooltip-dark .ui-tooltip-titlebar{
152 | background-color: #404040;
153 | }
154 |
155 | .ui-tooltip-dark .ui-tooltip-icon{
156 | border-color: #444;
157 | }
158 |
159 | .ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{
160 | border-color: #303030;
161 | }
162 |
163 |
164 | /*! Cream tooltip style */
165 | .ui-tooltip-cream{
166 | background-color: #FBF7AA;
167 | border-color: #F9E98E;
168 | color: #A27D35;
169 | }
170 |
171 | .ui-tooltip-cream .ui-tooltip-titlebar{
172 | background-color: #F0DE7D;
173 | }
174 |
175 | .ui-tooltip-cream .ui-state-default .ui-tooltip-icon{
176 | background-position: -82px 0;
177 | }
178 |
179 |
180 | /*! Red tooltip style */
181 | .ui-tooltip-red{
182 | background-color: #F78B83;
183 | border-color: #D95252;
184 | color: #912323;
185 | }
186 |
187 | .ui-tooltip-red .ui-tooltip-titlebar{
188 | background-color: #F06D65;
189 | }
190 |
191 | .ui-tooltip-red .ui-state-default .ui-tooltip-icon{
192 | background-position: -102px 0;
193 | }
194 |
195 | .ui-tooltip-red .ui-tooltip-icon{
196 | border-color: #D95252;
197 | }
198 |
199 | .ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{
200 | border-color: #D95252;
201 | }
202 |
203 |
204 | /*! Green tooltip style */
205 | .ui-tooltip-green{
206 | background-color: #CAED9E;
207 | border-color: #90D93F;
208 | color: #3F6219;
209 | }
210 |
211 | .ui-tooltip-green .ui-tooltip-titlebar{
212 | background-color: #B0DE78;
213 | }
214 |
215 | .ui-tooltip-green .ui-state-default .ui-tooltip-icon{
216 | background-position: -42px 0;
217 | }
218 |
219 |
220 | /*! Blue tooltip style */
221 | .ui-tooltip-blue{
222 | background-color: #E5F6FE;
223 | border-color: #ADD9ED;
224 | color: #5E99BD;
225 | }
226 |
227 | .ui-tooltip-blue .ui-tooltip-titlebar{
228 | background-color: #D0E9F5;
229 | }
230 |
231 | .ui-tooltip-blue .ui-state-default .ui-tooltip-icon{
232 | background-position: -2px 0;
233 | }
234 |
235 |
236 | /* Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
237 | .ui-tooltip-shadow{
238 | -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
239 | -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
240 | box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
241 | }
242 |
243 | /* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
244 | .ui-tooltip-rounded,
245 | .ui-tooltip-tipsy,
246 | .ui-tooltip-bootstrap{
247 | -moz-border-radius: 5px;
248 | -webkit-border-radius: 5px;
249 | border-radius: 5px;
250 | }
251 |
252 | /* Youtube tooltip style */
253 | .ui-tooltip-youtube{
254 | -moz-border-radius: 2px;
255 | -webkit-border-radius: 2px;
256 | border-radius: 2px;
257 |
258 | -webkit-box-shadow: 0 0 3px #333;
259 | -moz-box-shadow: 0 0 3px #333;
260 | box-shadow: 0 0 3px #333;
261 |
262 | color: white;
263 | border-width: 0;
264 |
265 | background: #4A4A4A;
266 | background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,black));
267 | background-image: -webkit-linear-gradient(top,#4A4A4A 0,black 100%);
268 | background-image: -moz-linear-gradient(top,#4A4A4A 0,black 100%);
269 | background-image: -ms-linear-gradient(top,#4A4A4A 0,black 100%);
270 | background-image: -o-linear-gradient(top,#4A4A4A 0,black 100%);
271 | }
272 |
273 | .ui-tooltip-youtube .ui-tooltip-titlebar{
274 | background-color: #4A4A4A;
275 | background-color: rgba(0,0,0,0);
276 | }
277 |
278 | .ui-tooltip-youtube .ui-tooltip-content{
279 | padding: .75em;
280 | font: 12px arial,sans-serif;
281 |
282 | filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);
283 | -ms-filter: "progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);";
284 | }
285 |
286 | .ui-tooltip-youtube .ui-tooltip-icon{
287 | border-color: #222;
288 | }
289 |
290 | .ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{
291 | border-color: #303030;
292 | }
293 |
294 |
295 | /* jQuery TOOLS Tooltip style */
296 | .ui-tooltip-jtools{
297 | background: #232323;
298 | background: rgba(0, 0, 0, 0.7);
299 | background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323));
300 | background-image: -moz-linear-gradient(top, #717171, #232323);
301 | background-image: -webkit-linear-gradient(top, #717171, #232323);
302 | background-image: -ms-linear-gradient(top, #717171, #232323);
303 | background-image: -o-linear-gradient(top, #717171, #232323);
304 |
305 | border: 2px solid #ddd;
306 | border: 2px solid rgba(241,241,241,1);
307 |
308 | -moz-border-radius: 2px;
309 | -webkit-border-radius: 2px;
310 | border-radius: 2px;
311 |
312 | -webkit-box-shadow: 0 0 12px #333;
313 | -moz-box-shadow: 0 0 12px #333;
314 | box-shadow: 0 0 12px #333;
315 | }
316 |
317 | /* IE Specific */
318 | .ui-tooltip-jtools .ui-tooltip-titlebar{
319 | background-color: transparent;
320 | filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);
321 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";
322 | }
323 | .ui-tooltip-jtools .ui-tooltip-content{
324 | filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);
325 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";
326 | }
327 |
328 | .ui-tooltip-jtools .ui-tooltip-titlebar,
329 | .ui-tooltip-jtools .ui-tooltip-content{
330 | background: transparent;
331 | color: white;
332 | border: 0 dashed transparent;
333 | }
334 |
335 | .ui-tooltip-jtools .ui-tooltip-icon{
336 | border-color: #555;
337 | }
338 |
339 | .ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{
340 | border-color: #333;
341 | }
342 |
343 |
344 | /* Cluetip style */
345 | .ui-tooltip-cluetip{
346 | -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
347 | -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
348 | box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
349 |
350 | background-color: #D9D9C2;
351 | color: #111;
352 | border: 0 dashed transparent;
353 | }
354 |
355 | .ui-tooltip-cluetip .ui-tooltip-titlebar{
356 | background-color: #87876A;
357 | color: white;
358 | border: 0 dashed transparent;
359 | }
360 |
361 | .ui-tooltip-cluetip .ui-tooltip-icon{
362 | border-color: #808064;
363 | }
364 |
365 | .ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{
366 | border-color: #696952;
367 | color: #696952;
368 | }
369 |
370 |
371 | /* Tipsy style */
372 | .ui-tooltip-tipsy{
373 | background: black;
374 | background: rgba(0, 0, 0, .87);
375 |
376 | color: white;
377 | border: 0 solid transparent;
378 |
379 | font-size: 11px;
380 | font-family: 'Lucida Grande', sans-serif;
381 | font-weight: bold;
382 | line-height: 16px;
383 | text-shadow: 0 1px black;
384 | }
385 |
386 | .ui-tooltip-tipsy .ui-tooltip-titlebar{
387 | padding: 6px 35px 0 10;
388 | background-color: transparent;
389 | }
390 |
391 | .ui-tooltip-tipsy .ui-tooltip-content{
392 | padding: 6px 10;
393 | }
394 |
395 | .ui-tooltip-tipsy .ui-tooltip-icon{
396 | border-color: #222;
397 | text-shadow: none;
398 | }
399 |
400 | .ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{
401 | border-color: #303030;
402 | }
403 |
404 |
405 | /* Tipped style */
406 | .ui-tooltip-tipped{
407 | border: 3px solid #959FA9;
408 |
409 | -moz-border-radius: 3px;
410 | -webkit-border-radius: 3px;
411 | border-radius: 3px;
412 |
413 | background-color: #F9F9F9;
414 | color: #454545;
415 |
416 | font-weight: normal;
417 | font-family: serif;
418 | }
419 |
420 | .ui-tooltip-tipped .ui-tooltip-titlebar{
421 | border-bottom-width: 0;
422 |
423 | color: white;
424 | background: #3A79B8;
425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D));
426 | background-image: -webkit-linear-gradient(top, #3A79B8, #2E629D);
427 | background-image: -moz-linear-gradient(top, #3A79B8, #2E629D);
428 | background-image: -ms-linear-gradient(top, #3A79B8, #2E629D);
429 | background-image: -o-linear-gradient(top, #3A79B8, #2E629D);
430 | filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);
431 | -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";
432 | }
433 |
434 | .ui-tooltip-tipped .ui-tooltip-icon{
435 | border: 2px solid #285589;
436 | background: #285589;
437 | }
438 |
439 | .ui-tooltip-tipped .ui-tooltip-icon .ui-icon{
440 | background-color: #FBFBFB;
441 | color: #555;
442 | }
443 |
444 |
445 | /**
446 | * Twitter Bootstrap style.
447 | *
448 | * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11.
449 | * Does not work with IE 7.
450 | */
451 | .ui-tooltip-bootstrap{
452 | font-size: 13px;
453 | line-height: 18px;
454 |
455 | color: #333333;
456 | background-color: #ffffff;
457 |
458 |
459 | border: 1px solid #ccc;
460 | border: 1px solid rgba(0, 0, 0, 0.2);
461 |
462 | *border-right-width: 2px;
463 | *border-bottom-width: 2px;
464 |
465 | -webkit-border-radius: 5px;
466 | -moz-border-radius: 5px;
467 | border-radius: 5px;
468 |
469 | -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
470 | -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
471 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
472 |
473 | -webkit-background-clip: padding-box;
474 | -moz-background-clip: padding;
475 | background-clip: padding-box;
476 | }
477 |
478 | .ui-tooltip-bootstrap .ui-tooltip-titlebar{
479 | font-size: 18px;
480 | line-height: 22px;
481 |
482 | border-bottom: 1px solid #ccc;
483 | background-color: transparent;
484 | }
485 |
486 | .ui-tooltip-bootstrap .ui-tooltip-titlebar .ui-state-default{
487 | right: 9px; top: 49%;
488 | border-style: none;
489 | }
490 |
491 | .ui-tooltip-bootstrap .ui-tooltip-icon{
492 | background: white;
493 | }
494 |
495 | .ui-tooltip-bootstrap .ui-tooltip-icon .ui-icon{
496 | width: auto;
497 | height: auto;
498 | float: right;
499 | font-size: 20px;
500 | font-weight: bold;
501 | line-height: 18px;
502 | color: #000000;
503 | text-shadow: 0 1px 0 #ffffff;
504 | opacity: 0.2;
505 | filter: alpha(opacity=20);
506 | }
507 |
508 | .ui-tooltip-bootstrap .ui-tooltip-icon .ui-icon:hover{
509 | color: #000000;
510 | text-decoration: none;
511 | cursor: pointer;
512 | opacity: 0.4;
513 | filter: alpha(opacity=40);
514 | }
515 |
516 |
517 | /* IE9 fix - removes all filters */
518 | .ui-tooltip:not(.ie9haxors) div.ui-tooltip-content,
519 | .ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{
520 | filter: none;
521 | -ms-filter: none;
522 | }
523 |
524 |
525 | /* Tips plugin */
526 | .ui-tooltip .ui-tooltip-tip{
527 | margin: 0 auto;
528 | overflow: hidden;
529 | z-index: 10;
530 | }
531 |
532 | .ui-tooltip .ui-tooltip-tip,
533 | .ui-tooltip .ui-tooltip-tip .qtip-vml{
534 | position: absolute;
535 |
536 | line-height: 0.1px !important;
537 | font-size: 0.1px !important;
538 | color: #123456;
539 |
540 | background: transparent;
541 | border: 0 dashed transparent;
542 | }
543 |
544 | .ui-tooltip .ui-tooltip-tip canvas{ top: 0; left: 0; }
545 |
546 | .ui-tooltip .ui-tooltip-tip .qtip-vml{
547 | behavior: url(#default#VML);
548 | display: inline-block;
549 | visibility: visible;
550 | }
551 | /* Modal plugin */
552 | #qtip-overlay{
553 | position: fixed;
554 | left: -10000em;
555 | top: -10000em;
556 | }
557 |
558 | /* Applied to modals with show.modal.blur set to true */
559 | #qtip-overlay.blurs{ cursor: pointer; }
560 |
561 | /* Change opacity of overlay here */
562 | #qtip-overlay div{
563 | position: absolute;
564 | left: 0; top: 0;
565 | width: 100%; height: 100%;
566 |
567 | background-color: black;
568 |
569 | opacity: 0.7;
570 | filter:alpha(opacity=70);
571 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
572 | }
573 |
574 |
--------------------------------------------------------------------------------
/embed/css/opt-frontend.css:
--------------------------------------------------------------------------------
1 | /* CSS accompanying ../visualize.html */
2 |
3 | h1 {
4 | font-weight: normal;
5 | font-size: 20pt;
6 | font-family: georgia, serif;
7 | line-height: 1em; /* enforce single spacing so that Georgia works */
8 |
9 | margin-top: 0px;
10 | margin-bottom: 8px;
11 | }
12 |
13 | h2 {
14 | font-size: 12pt;
15 | font-weight: normal;
16 | font-family: georgia, serif;
17 | line-height: 1.1em; /* enforce single spacing so that Georgia works */
18 |
19 | margin-top: 2px;
20 | margin-bottom: 20px;
21 | }
22 |
23 |
24 | body {
25 | background-color: white;
26 | font-family: verdana, arial, helvetica, sans-serif;
27 | font-size: 10pt;
28 | }
29 |
30 | a,
31 | a:visited,
32 | a:hover {
33 | color: #3D58A2;
34 | }
35 |
36 | span {
37 | padding: 0px;
38 | }
39 |
40 | table#pyOutputPane {
41 | padding: 10px;
42 | }
43 |
44 | #pyInputPane {
45 | margin-top: 20px;
46 | margin-bottom: 20px;
47 |
48 | max-width: 700px;
49 | /* center align */
50 | margin-left: auto;
51 | margin-right: auto;
52 | }
53 |
54 | #codeInputPane {
55 | margin-top: 5px;
56 | font-size: 12pt;
57 | border: 1px solid #ddd;
58 | }
59 |
60 | button.smallBtn {
61 | font-size: 10pt;
62 | padding: 3px;
63 | }
64 |
65 | button.bigBtn {
66 | font-size: 13pt;
67 | padding: 6px;
68 | margin-top: 6px;
69 | }
70 |
71 | #footer {
72 | color: #666666;
73 | font-size: 9pt;
74 | border-top: 1px solid #bbbbbb;
75 | padding-top: 5px;
76 | margin-top: 5px;
77 |
78 | max-width: 700px;
79 | /* center align */
80 | margin-left: auto;
81 | margin-right: auto;
82 | }
83 |
84 |
85 | /* necessary for CodeMirror error line highlighting to work! */
86 | .CodeMirror .errorLine { background: #ffff3f !important; }
87 |
--------------------------------------------------------------------------------
/embed/css/pytutor.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Online Python Tutor
4 | https://github.com/pgbovine/OnlinePythonTutor/
5 |
6 | Copyright (C) 2010-2012 Philip J. Guo (philip@pgbovine.net)
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a
9 | copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included
17 | in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 | */
28 |
29 | /* Most recent color scheme redesign on 2012-08-19 */
30 |
31 | /* To prevent CSS namespace clashes, prefix all rules with:
32 | div.ExecutionVisualizer
33 | */
34 |
35 |
36 | /* reset some styles to nullify effects of existing stylesheets
37 | e.g., http://meyerweb.com/eric/tools/css/reset/
38 | */
39 | div.ExecutionVisualizer {
40 | /* none for now */
41 | }
42 |
43 | div.ExecutionVisualizer table.visualizer {
44 | font-family: verdana, arial, helvetica, sans-serif;
45 | font-size: 10pt;
46 | margin-bottom: 10px;
47 | }
48 |
49 | div.ExecutionVisualizer table.visualizer td.vizLayoutTd {
50 | vertical-align: top;
51 | }
52 |
53 | div.ExecutionVisualizer td#stack_td,
54 | div.ExecutionVisualizer td#heap_td {
55 | vertical-align:top;
56 | font-size: 10pt; /* don't make fonts in the heap so big! */
57 | }
58 |
59 | div.ExecutionVisualizer #dataViz {
60 | margin-left: 25px;
61 | }
62 |
63 | div.ExecutionVisualizer div#codeDisplayDiv {
64 | /* set this as default unless user specifies a custom size */
65 | /*width: 550px;*/
66 | }
67 |
68 | div.ExecutionVisualizer div#pyCodeOutputDiv {
69 | /*max-width: 550px;*/
70 | max-height: 450px;
71 | /*max-height: 620px;*/
72 | overflow: auto;
73 | /*margin-bottom: 4px;*/
74 |
75 | margin-left: auto;
76 | margin-right: auto;
77 | }
78 |
79 | div.ExecutionVisualizer table#pyCodeOutput {
80 | font-family: Andale mono, monospace;
81 | font-size:12pt;
82 | line-height:1.1em;
83 |
84 | border-collapse: separate; /* some crazy CSS voodoo that needs to be
85 | there so that SVG arrows to the left
86 | of the code line up vertically in Chrome */
87 | border-spacing: 0px;
88 | border-top: 1px solid #bbb;
89 | padding-top: 3px;
90 | border-bottom: 1px solid #bbb;
91 | /*margin-top: 6px;*/
92 | margin: 6px auto; /* Center code in its pane */
93 | }
94 |
95 | /* don't wrap lines within code output ... FORCE scrollbars to appear */
96 | div.ExecutionVisualizer table#pyCodeOutput td {
97 | white-space: nowrap;
98 | vertical-align: middle; /* explicitly force, to override external CSS conflicts */
99 | }
100 |
101 | div.ExecutionVisualizer #leftCodeGutterSVG {
102 | width: 18px;
103 | min-width: 18px; /* make sure it doesn't squash too thin */
104 | height: 0px; /* programmatically set this later ... IE needs this to
105 | be 0 or it defaults to something arbitrary and gross */
106 | }
107 |
108 | div.ExecutionVisualizer #prevLegendArrowSVG,
109 | div.ExecutionVisualizer #curLegendArrowSVG {
110 | width: 18px;
111 | height: 10px;
112 | }
113 |
114 | div.ExecutionVisualizer .arrow {
115 | font-size: 16pt;
116 | }
117 |
118 | div.ExecutionVisualizer table#pyCodeOutput .lineNo {
119 | color: #aaa;
120 | padding: 0.2em;
121 | padding-left: 0.3em;
122 | padding-right: 0.5em;
123 | text-align: right;
124 | }
125 |
126 | div.ExecutionVisualizer table#pyCodeOutput .cod {
127 | /*font-weight: bold;*/
128 | margin-left: 3px;
129 | padding-left: 7px;
130 | text-align: left; /* necessary or else doesn't work properly in IE */
131 | }
132 |
133 | div.ExecutionVisualizer div#progOutputs {
134 | margin-top: 8px;
135 | }
136 |
137 | div.ExecutionVisualizer div#legendDiv {
138 | margin-top: 10px;
139 | padding: 0px;
140 | text-align: left;
141 | color: #666;
142 | font-size: 9pt;
143 | }
144 |
145 | div.ExecutionVisualizer div#editCodeLinkDiv {
146 | text-align: center;
147 | /*
148 | margin-top: 12px;
149 | margin-bottom: 4px;
150 | */
151 | margin: 8px auto;
152 | }
153 |
154 | div.ExecutionVisualizer div#annotateLinkDiv {
155 | /*text-align: left;*/
156 | margin-top: 0px;
157 | margin-bottom: 12px;
158 | /*
159 | margin-left: auto;
160 | margin-right: auto;
161 | */
162 | }
163 |
164 | div.ExecutionVisualizer div#stepAnnotationDiv {
165 | margin-bottom: 12px;
166 | }
167 |
168 | div.ExecutionVisualizer textarea#stepAnnotationEditor,
169 | div.ExecutionVisualizer textarea#vizTitleEditor,
170 | div.ExecutionVisualizer textarea#vizDescriptionEditor {
171 | border: 1px solid #999999;
172 | padding: 4px;
173 |
174 | overflow: auto; /* to look pretty on IE */
175 | /* make sure textarea doesn't grow and stretch */
176 | resize: none;
177 | }
178 |
179 |
180 | div.ExecutionVisualizer #errorOutput {
181 | color: #e93f34; /* should match brightRed JavaScript variable */
182 | font-size: 12pt;
183 | padding: 2px;
184 | line-height: 1.5em;
185 | margin-bottom: 4px;
186 | }
187 |
188 | /* VCR control buttons for stepping through execution */
189 |
190 | div.ExecutionVisualizer #vcrControls {
191 | margin: 15px auto;
192 | /*width: 100%;*/
193 | text-align: center;
194 | }
195 |
196 | div.ExecutionVisualizer #vcrControls button {
197 | margin-left: 2px;
198 | margin-right: 2px;
199 | }
200 |
201 | div.ExecutionVisualizer #vcrControls #curInstr {
202 | margin-left: 4px;
203 | margin-right: 4px;
204 | }
205 |
206 | div.ExecutionVisualizer #pyStdout {
207 | border: 1px solid #999999;
208 | font-size: 12pt;
209 | padding: 4px;
210 | font-family: Andale mono, monospace;
211 |
212 | overflow: auto; /* to look pretty on IE */
213 | /* make sure textarea doesn't grow and stretch */
214 | resize: none;
215 |
216 | -moz-box-sizing: border-box;
217 | box-sizing: border-box;
218 |
219 | width: 100%;
220 | }
221 |
222 |
223 | div.ExecutionVisualizer .vizFrame {
224 | margin-bottom: 20px;
225 | padding-left: 8px;
226 | border-left: 2px solid #cccccc;
227 | }
228 |
229 |
230 | /* Rendering of primitive types */
231 |
232 | div.ExecutionVisualizer .nullObj {
233 | // font-size: 8pt;
234 | }
235 |
236 | div.ExecutionVisualizer .stringObj,
237 | div.ExecutionVisualizer .customObj,
238 | div.ExecutionVisualizer .funcObj {
239 | font-family: Andale mono, monospace;
240 | white-space: nowrap;
241 | }
242 |
243 | div.ExecutionVisualizer .retval {
244 | font-size: 9pt;
245 | }
246 |
247 | div.ExecutionVisualizer .stackFrame .retval {
248 | color: #e93f34; /* highlight non-zombie stack frame return values -
249 | should match brightRed JavaScript variable */
250 | }
251 |
252 | /* Rendering of basic compound types */
253 |
254 | div.ExecutionVisualizer table.listTbl,
255 | div.ExecutionVisualizer table.tupleTbl,
256 | div.ExecutionVisualizer table.setTbl {
257 | background-color: #ffffc6;
258 | }
259 |
260 |
261 | div.ExecutionVisualizer table.listTbl {
262 | border: 0px solid black;
263 | border-spacing: 0px;
264 | }
265 |
266 | div.ExecutionVisualizer table.listTbl td.listHeader,
267 | div.ExecutionVisualizer table.tupleTbl td.tupleHeader {
268 | padding-left: 4px;
269 | padding-top: 2px;
270 | padding-bottom: 3px;
271 | font-size: 8pt;
272 | color: #777;
273 | text-align: left;
274 | border-left: 1px solid #555555;
275 | }
276 |
277 | div.ExecutionVisualizer table.tupleTbl {
278 | border-spacing: 0px;
279 | color: black;
280 |
281 | border-bottom: 1px solid #555555; /* must match td.tupleHeader border */
282 | border-top: 1px solid #555555; /* must match td.tupleHeader border */
283 | border-right: 1px solid #555555; /* must match td.tupleHeader border */
284 | }
285 |
286 |
287 | div.ExecutionVisualizer table.listTbl td.listElt {
288 | border-bottom: 1px solid #555555; /* must match td.listHeader border */
289 | border-left: 1px solid #555555; /* must match td.listHeader border */
290 | }
291 |
292 | div.ExecutionVisualizer table.tupleTbl td.tupleElt {
293 | border-left: 1px solid #555555; /* must match td.tupleHeader border */
294 | }
295 |
296 | div.ExecutionVisualizer table.customObjTbl {
297 | background-color: white;
298 | color: black;
299 | border: 1px solid black;
300 | }
301 |
302 | div.ExecutionVisualizer table.customObjTbl td.customObjElt {
303 | padding: 5px;
304 | }
305 |
306 | div.ExecutionVisualizer table.listTbl td.listElt,
307 | div.ExecutionVisualizer table.tupleTbl td.tupleElt {
308 | padding-top: 0px;
309 | padding-bottom: 8px;
310 | padding-left: 10px;
311 | padding-right: 10px;
312 | vertical-align: bottom;
313 | }
314 |
315 | div.ExecutionVisualizer table.setTbl {
316 | border: 1px solid #555555;
317 | border-spacing: 0px;
318 | text-align: center;
319 | }
320 |
321 | div.ExecutionVisualizer table.setTbl td.setElt {
322 | padding: 8px;
323 | }
324 |
325 |
326 | div.ExecutionVisualizer table.dictTbl,
327 | div.ExecutionVisualizer table.instTbl,
328 | div.ExecutionVisualizer table.classTbl {
329 | border-spacing: 1px;
330 | }
331 |
332 | div.ExecutionVisualizer table.dictTbl td.dictKey,
333 | div.ExecutionVisualizer table.instTbl td.instKey,
334 | div.ExecutionVisualizer table.classTbl td.classKey {
335 | background-color: #faebbf;
336 | }
337 |
338 | div.ExecutionVisualizer table.dictTbl td.dictVal,
339 | div.ExecutionVisualizer table.instTbl td.instVal,
340 | div.ExecutionVisualizer table.classTbl td.classVal {
341 | background-color: #ffffc6;
342 | }
343 |
344 |
345 | div.ExecutionVisualizer table.dictTbl td.dictKey,
346 | div.ExecutionVisualizer table.instTbl td.instKey,
347 | div.ExecutionVisualizer table.classTbl td.classKey {
348 | padding-top: 12px /*15px*/;
349 | padding-bottom: 5px;
350 | padding-left: 10px;
351 | padding-right: 4px;
352 |
353 | text-align: right;
354 | }
355 |
356 | div.ExecutionVisualizer table.dictTbl td.dictVal,
357 | div.ExecutionVisualizer table.instTbl td.instVal,
358 | div.ExecutionVisualizer table.classTbl td.classVal {
359 | padding-top: 12px /*15px*/;
360 | padding-bottom: 5px;
361 | padding-right: 10px;
362 | padding-left: 4px;
363 | }
364 |
365 |
366 | div.ExecutionVisualizer table.classTbl td,
367 | div.ExecutionVisualizer table.instTbl td {
368 | border-bottom: 1px #888 solid;
369 | }
370 |
371 | div.ExecutionVisualizer table.classTbl td.classVal,
372 | div.ExecutionVisualizer table.instTbl td.instVal {
373 | border-left: 1px #888 solid;
374 | }
375 |
376 | div.ExecutionVisualizer table.classTbl {
377 | border-collapse: collapse;
378 | border: 1px #888 solid;
379 | }
380 |
381 | /* only add a border to dicts if they're embedded within another object */
382 | div.ExecutionVisualizer td.listElt table.dictTbl,
383 | div.ExecutionVisualizer td.tupleElt table.dictTbl,
384 | div.ExecutionVisualizer td.dictVal table.dictTbl,
385 | div.ExecutionVisualizer td.instVal table.dictTbl,
386 | div.ExecutionVisualizer td.classVal table.dictTbl {
387 | border: 1px #888 solid;
388 | }
389 |
390 | div.ExecutionVisualizer .objectIdLabel {
391 | font-size: 8pt;
392 | color: #444;
393 | margin-bottom: 2px;
394 | }
395 |
396 | div.ExecutionVisualizer .typeLabel {
397 | font-size: 8pt;
398 | color: #555;
399 | margin-bottom: 2px;
400 | }
401 |
402 | div.ExecutionVisualizer div#stack,
403 | div.ExecutionVisualizer div#globals_area {
404 | padding-left: 10px;
405 | padding-right: 30px;
406 |
407 | /* no longer necessary ... */
408 | /*float: left;*/
409 | /* border-right: 1px dashed #bbbbbb; */
410 | }
411 |
412 | div.ExecutionVisualizer div.stackFrame,
413 | div.ExecutionVisualizer div.zombieStackFrame {
414 | background-color: #ffffff;
415 | margin-bottom: 15px;
416 | padding: 2px;
417 | padding-left: 6px;
418 | padding-right: 6px;
419 | padding-bottom: 4px;
420 | font-size: 10pt;
421 | }
422 |
423 | div.ExecutionVisualizer div.zombieStackFrame {
424 | border-left: 1px dotted #aaa;
425 | /*color: #c0c0c0;*/
426 | color: #a0a0a0;
427 | }
428 |
429 | div.ExecutionVisualizer div.highlightedStackFrame {
430 | background-color: #e2ebf6;
431 | /*background-color: #d7e7fb;*/
432 |
433 | /*background-color: #c0daf8;*/
434 | /*background-color: #9eeaff #c5dfea;*/
435 | }
436 |
437 | div.ExecutionVisualizer div.stackFrame,
438 | div.ExecutionVisualizer div.highlightedStackFrame {
439 | border-left: 1px solid #a6b3b6;
440 | }
441 |
442 |
443 | div.ExecutionVisualizer div.stackFrameHeader {
444 | font-family: Andale mono, monospace;
445 | font-size: 10pt;
446 | margin-top: 4px;
447 | margin-bottom: 3px;
448 | white-space: nowrap;
449 | }
450 |
451 | div.ExecutionVisualizer td.stackFrameVar {
452 | text-align: right;
453 | padding-right: 8px;
454 | padding-top: 3px;
455 | padding-bottom: 3px;
456 | }
457 |
458 | div.ExecutionVisualizer td.stackFrameValue {
459 | text-align: left;
460 | border-bottom: 1px solid #aaaaaa;
461 | border-left: 1px solid #aaaaaa;
462 |
463 | vertical-align: middle;
464 |
465 | padding-top: 3px;
466 | padding-left: 3px;
467 | padding-bottom: 3px;
468 | }
469 |
470 | div.ExecutionVisualizer .stackFrameVarTable tr {
471 |
472 | }
473 |
474 | div.ExecutionVisualizer .stackFrameVarTable {
475 | text-align: right;
476 | padding-top: 3px;
477 |
478 | /* right-align the table */
479 | margin-left: auto;
480 | margin-right: 0px;
481 |
482 | /* hack to counteract possible nasty CSS reset styles from parent divs */
483 | border-collapse: separate;
484 | border-spacing: 2px;
485 | }
486 |
487 | div.ExecutionVisualizer div#heap {
488 | float: left;
489 | padding-left: 30px;
490 | }
491 |
492 | div.ExecutionVisualizer td.toplevelHeapObject {
493 | /* needed for d3 to do transitions */
494 | padding-left: 8px;
495 | padding-right: 8px;
496 | padding-top: 4px;
497 | padding-bottom: 4px;
498 | /*
499 | border: 2px dotted white;
500 | border-color: white;
501 | */
502 | }
503 |
504 | div.ExecutionVisualizer table.heapRow {
505 | margin-bottom: 10px;
506 | }
507 |
508 | div.ExecutionVisualizer div.heapObject {
509 | padding-left: 2px; /* leave a TINY amount of room for connector endpoints */
510 | }
511 |
512 | div.ExecutionVisualizer div.heapPrimitive {
513 | padding-left: 4px; /* leave some more room for connector endpoints */
514 | }
515 |
516 | div.ExecutionVisualizer div#stackHeader {
517 | margin-bottom: 15px;
518 | text-align: right;
519 | }
520 |
521 | div.ExecutionVisualizer div#heapHeader {
522 | /*margin-top: 2px;
523 | margin-bottom: 13px;*/
524 | margin-bottom: 15px;
525 | }
526 |
527 | div.ExecutionVisualizer div#stackHeader,
528 | div.ExecutionVisualizer div#heapHeader {
529 | color: #333333;
530 | font-size: 10pt;
531 | }
532 |
533 | div.ExecutionVisualizer #executionSlider {
534 | /* if you set 'width', then it looks ugly when you dynamically resize */
535 | margin-top: 15px;
536 | margin-bottom: 5px;
537 |
538 | margin-left: auto;
539 | margin-right: auto;
540 |
541 | width: 95%;
542 | }
543 |
544 | div.ExecutionVisualizer #executionSliderCaption {
545 | font-size: 8pt;
546 | color: #666666;
547 | margin-top: 15px;
548 | }
549 |
550 | div.ExecutionVisualizer #executionSliderFooter {
551 | margin-top: -7px; /* make it butt up against #executionSlider */
552 | }
553 |
554 |
555 | /* darken slider handle a bit */
556 | div.ExecutionVisualizer .ui-slider .ui-slider-handle {
557 | border: 1px solid #999;
558 | }
559 |
560 |
561 | /* for annotation bubbles */
562 |
563 | /* For styling tricks, see: http://css-tricks.com/textarea-tricks/ */
564 | textarea.bubbleInputText {
565 | border: 1px solid #ccc;
566 | outline: none;
567 | overflow: auto; /* to look pretty on IE */
568 |
569 | /* make sure textarea doesn't grow and stretch the enclosing bubble */
570 | resize: none;
571 | width: 225px;
572 | max-width: 225px;
573 | height: 35px;
574 | max-height: 35px;
575 | }
576 |
577 |
578 | .ui-tooltip-pgbootstrap,
579 | textarea.bubbleInputText {
580 | font-family: verdana, arial, helvetica, sans-serif;
581 | font-size: 9pt;
582 | line-height: 1.3em;
583 | }
584 |
585 |
586 | /* modified version of Twitter bootstrap style by Philip Guo */
587 | .ui-tooltip-pgbootstrap{
588 | color: #333;
589 | background-color: #ffffff;
590 |
591 | max-width: 250px;
592 | min-width: 10px;
593 |
594 | border: 2px solid #4284D3;
595 |
596 | cursor: pointer;
597 |
598 | *border-right-width: 2px;
599 | *border-bottom-width: 2px;
600 |
601 | -webkit-border-radius: 5px;
602 | -moz-border-radius: 5px;
603 | border-radius: 5px;
604 |
605 | /* way too poofy ...
606 | -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
607 | -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
608 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
609 | */
610 |
611 | -webkit-box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.2);
612 | -moz-box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.2);
613 | box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.2);
614 |
615 | -webkit-background-clip: padding-box;
616 | -moz-background-clip: padding;
617 | background-clip: padding-box;
618 | }
619 |
620 | .ui-tooltip-pgbootstrap .ui-tooltip-titlebar{
621 | font-size: 18px;
622 | line-height: 22px;
623 |
624 | border-bottom: 1px solid #ccc;
625 | background-color: transparent;
626 | }
627 |
628 | .ui-tooltip-pgbootstrap .ui-tooltip-content{
629 | padding: 5px /* 5px is minimum or else it might look ugly */ 8px;
630 | }
631 |
632 |
633 | .ui-tooltip-pgbootstrap .ui-tooltip-titlebar .ui-state-default{
634 | right: 9px; top: 49%;
635 | border-style: none;
636 | }
637 |
638 | .ui-tooltip-pgbootstrap .ui-tooltip-icon{
639 | background: white;
640 | }
641 |
642 | .ui-tooltip-pgbootstrap .ui-tooltip-icon .ui-icon{
643 | width: auto;
644 | height: auto;
645 | float: right;
646 | font-size: 20px;
647 | font-weight: bold;
648 | line-height: 18px;
649 | color: #000000;
650 | text-shadow: 0 1px 0 #ffffff;
651 | opacity: 0.2;
652 | filter: alpha(opacity=20);
653 | }
654 |
655 | .ui-tooltip-pgbootstrap .ui-tooltip-icon .ui-icon:hover{
656 | color: #000000;
657 | text-decoration: none;
658 | cursor: pointer;
659 | opacity: 0.4;
660 | filter: alpha(opacity=40);
661 | }
662 |
663 |
664 | /* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
665 | .ui-tooltip-pgbootstrap{
666 | -moz-border-radius: 5px;
667 | -webkit-border-radius: 5px;
668 | border-radius: 5px;
669 | }
670 |
671 |
672 | .ui-tooltip-pgbootstrap-stub{
673 | border: 1px solid #999;
674 |
675 | /*
676 | -webkit-box-shadow: none;
677 | -moz-box-shadow: none;
678 | box-shadow: none;
679 | */
680 | }
681 |
682 | .ui-tooltip-pgbootstrap-stub .ui-tooltip-content{
683 | padding: 6px 9px;
684 | }
685 |
686 |
687 | div.ExecutionVisualizer .annotationText,
688 | div.ExecutionVisualizer .vizDescriptionText {
689 | font-family: verdana, arial, helvetica, sans-serif;
690 | font-size: 11pt;
691 | line-height: 1.5em;
692 | }
693 |
694 | div.ExecutionVisualizer .vizTitleText {
695 | font-family: verdana, arial, helvetica, sans-serif;
696 | font-size: 16pt;
697 | margin-bottom: 12pt;
698 | }
699 |
700 | div.ExecutionVisualizer div#vizHeader {
701 | margin-bottom: 10px;
702 | width: 700px;
703 | max-width: 700px;
704 | }
705 |
706 | /* prev then curr, so curr gets precedence when both apply */
707 | div.ExecutionVisualizer .highlight-prev {
708 | background-color: #F0F0EA;
709 | }
710 |
711 | div.ExecutionVisualizer .highlight-cur {
712 | background-color: #FFFF66;
713 | }
714 |
715 | div.ExecutionVisualizer .highlight-legend {
716 | padding: 2px;
717 | }
718 |
719 | /* resizing sliders from David Pritchard */
720 | .ui-resizable-e {
721 | background-color: #dddddd;
722 | width: 1px;
723 | border: 3px solid white;
724 | }
725 |
726 | .ui-resizable-e:hover {
727 | border-color: #dddddd;
728 | }
729 |
730 |
731 | /* for pyCrazyMode */
732 |
733 | /* prev then curr, so curr gets precedence when both apply */
734 | div.ExecutionVisualizer .pycrazy-highlight-prev {
735 | background-color: #eeeeee; /*#F0F0EA;*/
736 | /*
737 | text-decoration: none;
738 | border-bottom: 1px solid #dddddd;
739 | */
740 | }
741 |
742 | div.ExecutionVisualizer .pycrazy-highlight-cur {
743 | background-color: #FFFF66;
744 | /* aligned slightly higher than border-bottom */
745 | /*
746 | text-decoration: none;
747 | border-bottom: 1px solid #e93f34;
748 | */
749 | }
750 |
751 | div.ExecutionVisualizer .pycrazy-highlight-prev-and-cur {
752 | background-color: #FFFF66;
753 |
754 | text-decoration: none;
755 | border-bottom: 1px solid #999999;
756 | }
757 |
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-icons_228ef1_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-icons_228ef1_256x240.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-icons_ef8c08_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-icons_ef8c08_256x240.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-icons_ffd27a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-icons_ffd27a_256x240.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/images/ui-icons_ffffff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/embed/css/ui-lightness/images/ui-icons_ffffff_256x240.png
--------------------------------------------------------------------------------
/embed/css/ui-lightness/jquery-ui-1.8.24.custom.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery UI CSS Framework 1.8.24
3 | *
4 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
5 | * Dual licensed under the MIT or GPL Version 2 licenses.
6 | * http://jquery.org/license
7 | *
8 | * http://docs.jquery.com/UI/Theming/API
9 | */
10 |
11 | /* Layout helpers
12 | ----------------------------------*/
13 | .ui-helper-hidden { display: none; }
14 | .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
15 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
16 | .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
17 | .ui-helper-clearfix:after { clear: both; }
18 | .ui-helper-clearfix { zoom: 1; }
19 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
20 |
21 |
22 | /* Interaction Cues
23 | ----------------------------------*/
24 | .ui-state-disabled { cursor: default !important; }
25 |
26 |
27 | /* Icons
28 | ----------------------------------*/
29 |
30 | /* states and images */
31 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
32 |
33 |
34 | /* Misc visuals
35 | ----------------------------------*/
36 |
37 | /* Overlays */
38 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
39 |
40 |
41 | /*!
42 | * jQuery UI CSS Framework 1.8.24
43 | *
44 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
45 | * Dual licensed under the MIT or GPL Version 2 licenses.
46 | * http://jquery.org/license
47 | *
48 | * http://docs.jquery.com/UI/Theming/API
49 | *
50 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
51 | */
52 |
53 |
54 | /* Component containers
55 | ----------------------------------*/
56 | .ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
57 | .ui-widget .ui-widget { font-size: 1em; }
58 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
59 | /* pgbovine - switch border from #dddddd to #ccc */
60 | .ui-widget-content { border: 1px solid #ccc; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
61 | .ui-widget-content a { color: #333333; }
62 | .ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
63 | .ui-widget-header a { color: #ffffff; }
64 |
65 | /* Interaction states
66 | ----------------------------------*/
67 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
68 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }
69 |
70 | /* pgbovine - eliminate hover colors */
71 | /*
72 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
73 | .ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }
74 | */
75 |
76 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
77 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
78 | .ui-widget :active { outline: none; }
79 |
80 | /* Interaction Cues
81 | ----------------------------------*/
82 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
83 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
84 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
85 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
86 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
87 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
88 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
89 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
90 |
91 | /* Icons
92 | ----------------------------------*/
93 |
94 | /* states and images */
95 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
96 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
97 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
98 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
99 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
100 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
101 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
102 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
103 |
104 | /* positioning */
105 | .ui-icon-carat-1-n { background-position: 0 0; }
106 | .ui-icon-carat-1-ne { background-position: -16px 0; }
107 | .ui-icon-carat-1-e { background-position: -32px 0; }
108 | .ui-icon-carat-1-se { background-position: -48px 0; }
109 | .ui-icon-carat-1-s { background-position: -64px 0; }
110 | .ui-icon-carat-1-sw { background-position: -80px 0; }
111 | .ui-icon-carat-1-w { background-position: -96px 0; }
112 | .ui-icon-carat-1-nw { background-position: -112px 0; }
113 | .ui-icon-carat-2-n-s { background-position: -128px 0; }
114 | .ui-icon-carat-2-e-w { background-position: -144px 0; }
115 | .ui-icon-triangle-1-n { background-position: 0 -16px; }
116 | .ui-icon-triangle-1-ne { background-position: -16px -16px; }
117 | .ui-icon-triangle-1-e { background-position: -32px -16px; }
118 | .ui-icon-triangle-1-se { background-position: -48px -16px; }
119 | .ui-icon-triangle-1-s { background-position: -64px -16px; }
120 | .ui-icon-triangle-1-sw { background-position: -80px -16px; }
121 | .ui-icon-triangle-1-w { background-position: -96px -16px; }
122 | .ui-icon-triangle-1-nw { background-position: -112px -16px; }
123 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
124 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
125 | .ui-icon-arrow-1-n { background-position: 0 -32px; }
126 | .ui-icon-arrow-1-ne { background-position: -16px -32px; }
127 | .ui-icon-arrow-1-e { background-position: -32px -32px; }
128 | .ui-icon-arrow-1-se { background-position: -48px -32px; }
129 | .ui-icon-arrow-1-s { background-position: -64px -32px; }
130 | .ui-icon-arrow-1-sw { background-position: -80px -32px; }
131 | .ui-icon-arrow-1-w { background-position: -96px -32px; }
132 | .ui-icon-arrow-1-nw { background-position: -112px -32px; }
133 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
134 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
135 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
136 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
137 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
138 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
139 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
140 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
141 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
142 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
143 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
144 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
145 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
146 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
147 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
148 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
149 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
150 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
151 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
152 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
153 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
154 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
155 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
156 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
157 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
158 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
159 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
160 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
161 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
162 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
163 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
164 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
165 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
166 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
167 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
168 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
169 | .ui-icon-arrow-4 { background-position: 0 -80px; }
170 | .ui-icon-arrow-4-diag { background-position: -16px -80px; }
171 | .ui-icon-extlink { background-position: -32px -80px; }
172 | .ui-icon-newwin { background-position: -48px -80px; }
173 | .ui-icon-refresh { background-position: -64px -80px; }
174 | .ui-icon-shuffle { background-position: -80px -80px; }
175 | .ui-icon-transfer-e-w { background-position: -96px -80px; }
176 | .ui-icon-transferthick-e-w { background-position: -112px -80px; }
177 | .ui-icon-folder-collapsed { background-position: 0 -96px; }
178 | .ui-icon-folder-open { background-position: -16px -96px; }
179 | .ui-icon-document { background-position: -32px -96px; }
180 | .ui-icon-document-b { background-position: -48px -96px; }
181 | .ui-icon-note { background-position: -64px -96px; }
182 | .ui-icon-mail-closed { background-position: -80px -96px; }
183 | .ui-icon-mail-open { background-position: -96px -96px; }
184 | .ui-icon-suitcase { background-position: -112px -96px; }
185 | .ui-icon-comment { background-position: -128px -96px; }
186 | .ui-icon-person { background-position: -144px -96px; }
187 | .ui-icon-print { background-position: -160px -96px; }
188 | .ui-icon-trash { background-position: -176px -96px; }
189 | .ui-icon-locked { background-position: -192px -96px; }
190 | .ui-icon-unlocked { background-position: -208px -96px; }
191 | .ui-icon-bookmark { background-position: -224px -96px; }
192 | .ui-icon-tag { background-position: -240px -96px; }
193 | .ui-icon-home { background-position: 0 -112px; }
194 | .ui-icon-flag { background-position: -16px -112px; }
195 | .ui-icon-calendar { background-position: -32px -112px; }
196 | .ui-icon-cart { background-position: -48px -112px; }
197 | .ui-icon-pencil { background-position: -64px -112px; }
198 | .ui-icon-clock { background-position: -80px -112px; }
199 | .ui-icon-disk { background-position: -96px -112px; }
200 | .ui-icon-calculator { background-position: -112px -112px; }
201 | .ui-icon-zoomin { background-position: -128px -112px; }
202 | .ui-icon-zoomout { background-position: -144px -112px; }
203 | .ui-icon-search { background-position: -160px -112px; }
204 | .ui-icon-wrench { background-position: -176px -112px; }
205 | .ui-icon-gear { background-position: -192px -112px; }
206 | .ui-icon-heart { background-position: -208px -112px; }
207 | .ui-icon-star { background-position: -224px -112px; }
208 | .ui-icon-link { background-position: -240px -112px; }
209 | .ui-icon-cancel { background-position: 0 -128px; }
210 | .ui-icon-plus { background-position: -16px -128px; }
211 | .ui-icon-plusthick { background-position: -32px -128px; }
212 | .ui-icon-minus { background-position: -48px -128px; }
213 | .ui-icon-minusthick { background-position: -64px -128px; }
214 | .ui-icon-close { background-position: -80px -128px; }
215 | .ui-icon-closethick { background-position: -96px -128px; }
216 | .ui-icon-key { background-position: -112px -128px; }
217 | .ui-icon-lightbulb { background-position: -128px -128px; }
218 | .ui-icon-scissors { background-position: -144px -128px; }
219 | .ui-icon-clipboard { background-position: -160px -128px; }
220 | .ui-icon-copy { background-position: -176px -128px; }
221 | .ui-icon-contact { background-position: -192px -128px; }
222 | .ui-icon-image { background-position: -208px -128px; }
223 | .ui-icon-video { background-position: -224px -128px; }
224 | .ui-icon-script { background-position: -240px -128px; }
225 | .ui-icon-alert { background-position: 0 -144px; }
226 | .ui-icon-info { background-position: -16px -144px; }
227 | .ui-icon-notice { background-position: -32px -144px; }
228 | .ui-icon-help { background-position: -48px -144px; }
229 | .ui-icon-check { background-position: -64px -144px; }
230 | .ui-icon-bullet { background-position: -80px -144px; }
231 | .ui-icon-radio-off { background-position: -96px -144px; }
232 | .ui-icon-radio-on { background-position: -112px -144px; }
233 | .ui-icon-pin-w { background-position: -128px -144px; }
234 | .ui-icon-pin-s { background-position: -144px -144px; }
235 | .ui-icon-play { background-position: 0 -160px; }
236 | .ui-icon-pause { background-position: -16px -160px; }
237 | .ui-icon-seek-next { background-position: -32px -160px; }
238 | .ui-icon-seek-prev { background-position: -48px -160px; }
239 | .ui-icon-seek-end { background-position: -64px -160px; }
240 | .ui-icon-seek-start { background-position: -80px -160px; }
241 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
242 | .ui-icon-seek-first { background-position: -80px -160px; }
243 | .ui-icon-stop { background-position: -96px -160px; }
244 | .ui-icon-eject { background-position: -112px -160px; }
245 | .ui-icon-volume-off { background-position: -128px -160px; }
246 | .ui-icon-volume-on { background-position: -144px -160px; }
247 | .ui-icon-power { background-position: 0 -176px; }
248 | .ui-icon-signal-diag { background-position: -16px -176px; }
249 | .ui-icon-signal { background-position: -32px -176px; }
250 | .ui-icon-battery-0 { background-position: -48px -176px; }
251 | .ui-icon-battery-1 { background-position: -64px -176px; }
252 | .ui-icon-battery-2 { background-position: -80px -176px; }
253 | .ui-icon-battery-3 { background-position: -96px -176px; }
254 | .ui-icon-circle-plus { background-position: 0 -192px; }
255 | .ui-icon-circle-minus { background-position: -16px -192px; }
256 | .ui-icon-circle-close { background-position: -32px -192px; }
257 | .ui-icon-circle-triangle-e { background-position: -48px -192px; }
258 | .ui-icon-circle-triangle-s { background-position: -64px -192px; }
259 | .ui-icon-circle-triangle-w { background-position: -80px -192px; }
260 | .ui-icon-circle-triangle-n { background-position: -96px -192px; }
261 | .ui-icon-circle-arrow-e { background-position: -112px -192px; }
262 | .ui-icon-circle-arrow-s { background-position: -128px -192px; }
263 | .ui-icon-circle-arrow-w { background-position: -144px -192px; }
264 | .ui-icon-circle-arrow-n { background-position: -160px -192px; }
265 | .ui-icon-circle-zoomin { background-position: -176px -192px; }
266 | .ui-icon-circle-zoomout { background-position: -192px -192px; }
267 | .ui-icon-circle-check { background-position: -208px -192px; }
268 | .ui-icon-circlesmall-plus { background-position: 0 -208px; }
269 | .ui-icon-circlesmall-minus { background-position: -16px -208px; }
270 | .ui-icon-circlesmall-close { background-position: -32px -208px; }
271 | .ui-icon-squaresmall-plus { background-position: -48px -208px; }
272 | .ui-icon-squaresmall-minus { background-position: -64px -208px; }
273 | .ui-icon-squaresmall-close { background-position: -80px -208px; }
274 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
275 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
276 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
277 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
278 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
279 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
280 |
281 |
282 | /* Misc visuals
283 | ----------------------------------*/
284 |
285 | /* Corner radius */
286 | .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
287 | .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
288 | .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
289 | .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
290 |
291 | /* Overlays */
292 | .ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
293 | .ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*!
294 | * jQuery UI Resizable 1.8.24
295 | *
296 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
297 | * Dual licensed under the MIT or GPL Version 2 licenses.
298 | * http://jquery.org/license
299 | *
300 | * http://docs.jquery.com/UI/Resizable#theming
301 | */
302 | .ui-resizable { position: relative;}
303 | .ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
304 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
305 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
306 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
307 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
308 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
309 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
310 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
311 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
312 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
313 | * jQuery UI Slider 1.8.24
314 | *
315 | * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
316 | * Dual licensed under the MIT or GPL Version 2 licenses.
317 | * http://jquery.org/license
318 | *
319 | * http://docs.jquery.com/UI/Slider#theming
320 | */
321 | .ui-slider { position: relative; text-align: left; }
322 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
323 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
324 |
325 | .ui-slider-horizontal { height: .8em; }
326 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
327 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
328 | .ui-slider-horizontal .ui-slider-range-min { left: 0; }
329 | .ui-slider-horizontal .ui-slider-range-max { right: 0; }
330 |
331 | .ui-slider-vertical { width: .8em; height: 100px; }
332 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
333 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
334 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
335 | .ui-slider-vertical .ui-slider-range-max { top: 0; }
336 |
--------------------------------------------------------------------------------
/embed/js/iframe-embed.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Online Python Tutor
4 | https://github.com/pgbovine/OnlinePythonTutor/
5 |
6 | Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net)
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a
9 | copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included
17 | in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 | */
28 |
29 |
30 | // Pre-reqs:
31 | // - pytutor.js
32 | // - jquery.ba-bbq.min.js
33 | // - opt-frontend-common.js
34 | // should all be imported BEFORE this file
35 |
36 |
37 | var myVisualizer = null; // singleton ExecutionVisualizer instance
38 |
39 |
40 | function NOP() {};
41 |
42 |
43 | $(document).ready(function() {
44 | var queryStrOptions = getQueryStringOptions();
45 |
46 | var preseededCode = queryStrOptions.preseededCode;
47 | var pyState = queryStrOptions.pyState;
48 | var verticalStackBool = (queryStrOptions.verticalStack == 'true');
49 | var heapPrimitivesBool = (queryStrOptions.heapPrimitives == 'true');
50 | var drawParentPointerBool = (queryStrOptions.drawParentPointers == 'true');
51 | var textRefsBool = (queryStrOptions.textRefs == 'true');
52 | var showOnlyOutputsBool = (queryStrOptions.showOnlyOutputs == 'true');
53 | var cumModeBool = (queryStrOptions.cumulativeState == 'true');
54 |
55 | var codeDivWidth = undefined;
56 | var codeDivWidth = 350;
57 | var cdw = $.bbq.getState('codeDivWidth');
58 | var cdw = $.bbq.getState('width');
59 | if (cdw) {
60 | codeDivWidth = Number(cdw);
61 | }
62 |
63 | var codeDivHeight = undefined;
64 | var cdh = $.bbq.getState('codeDivHeight');
65 | if (cdh) {
66 | codeDivHeight = Number(cdh);
67 | }
68 |
69 |
70 | var startingInstruction = queryStrOptions.preseededCurInstr;
71 | if (!startingInstruction) {
72 | startingInstruction = 0;
73 | }
74 |
75 | var backend_script = null;
76 | if (pyState == '2') {
77 | backend_script = python2_backend_script;
78 | }
79 | else if (pyState == '3') {
80 | backend_script = python3_backend_script;
81 | }
82 | else if (pyState == '2crazy') {
83 | backend_script = python2crazy_backend_script;
84 | }
85 |
86 |
87 | // David Pritchard's code for resizeContainer option ...
88 | var resizeContainer = ($.bbq.getState('resizeContainer') == 'true');
89 |
90 | if (resizeContainer) {
91 | function findContainer() {
92 | try {
93 | var ifs = window.top.document.getElementsByTagName("iframe");
94 | for(var i = 0, len = ifs.length; i < len; i++) {
95 | var f = ifs[i];
96 | var fDoc = f.contentDocument || f.contentWindow.document;
97 | if(fDoc === document) {
98 | return f;
99 | }
100 | }
101 | } catch (e) {
102 | // ignore SecurityError
103 | }
104 | }
105 |
106 | var container = findContainer();
107 |
108 | function resizeContainerNow() {
109 | $(container).height($("html").height());
110 | };
111 | }
112 |
113 | // set up all options in a JS object
114 | var backendOptionsObj = {cumulative_mode: cumModeBool,
115 | heap_primitives: heapPrimitivesBool,
116 | show_only_outputs: showOnlyOutputsBool,
117 | py_crazy_mode: (pyState == '2crazy'),
118 | origin: 'iframe-embed.js'};
119 |
120 | var frontendOptionsObj = {startingInstruction: startingInstruction,
121 | embeddedMode: true,
122 | verticalStack: verticalStackBool,
123 | disableHeapNesting: true,
124 | drawParentPointers: drawParentPointerBool,
125 | textualMemoryLabels: textRefsBool,
126 | showOnlyOutputs: showOnlyOutputsBool,
127 | executeCodeWithRawInputFunc: executeCodeWithRawInput,
128 | heightChangeCallback: (resizeContainer ? resizeContainerNow : NOP),
129 |
130 | // undocumented experimental modes:
131 | pyCrazyMode: (pyState == '2crazy'),
132 | highlightLines: typeof $.bbq.getState("highlightLines") !== "undefined",
133 | codeDivWidth: codeDivWidth,
134 | codeDivHeight: codeDivHeight,
135 | }
136 |
137 | function executeCode(forceStartingInstr) {
138 | if (forceStartingInstr) {
139 | frontendOptionsObj.startingInstruction = forceStartingInstr;
140 | }
141 | executePythonCode(preseededCode,
142 | backend_script, backendOptionsObj,
143 | frontendOptionsObj,
144 | 'vizDiv',
145 | function() { // success
146 | /* if (serverReply.stdin != "") {
147 | var stdinHTML = '
';
148 | $('#dataViz').append(stdinHTML);
149 | $("#stdinShow").html(serverReply.stdin);
150 | }*/
151 | if ($.bbq.getState('rightStdout')) {
152 | $("#progOutputs").prependTo("#dataViz");
153 | };
154 | if (resizeContainer)
155 | resizeContainerNow();
156 | },
157 | NOP);
158 | }
159 |
160 |
161 | function executeCodeFromScratch() {
162 | // reset these globals
163 | rawInputLst = [];
164 | executeCode();
165 | }
166 |
167 | function executeCodeWithRawInput(rawInputStr, curInstr) {
168 | // set some globals
169 | rawInputLst.push(rawInputStr);
170 | executeCode(curInstr);
171 | }
172 |
173 |
174 | // log a generic AJAX error handler
175 | $(document).ajaxError(function() {
176 | alert("Ugh, Online Python Tutor server error :(");
177 | });
178 |
179 |
180 | // redraw connector arrows on window resize
181 | $(window).resize(function() {
182 | myVisualizer.redrawConnectors();
183 | });
184 |
185 | executeCodeFromScratch(); // finally, execute code and display visualization
186 |
187 |
188 | });
189 |
190 |
--------------------------------------------------------------------------------
/embed/js/jquery.ba-bbq.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
3 | * http://benalman.com/projects/jquery-bbq-plugin/
4 | *
5 | * Copyright (c) 2010 "Cowboy" Ben Alman
6 | * Dual licensed under the MIT and GPL licenses.
7 | * http://benalman.com/about/license/
8 | */
9 | (function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M ').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this);
--------------------------------------------------------------------------------
/embed/js/opt-frontend-common.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Online Python Tutor
4 | https://github.com/pgbovine/OnlinePythonTutor/
5 |
6 | Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net)
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a
9 | copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included
17 | in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 | */
28 |
29 |
30 | // backend scripts to execute (Python 2 and 3 variants, if available)
31 | // make two copies of ../web_exec.py and give them the following names,
32 | // then change the first line (starting with #!) to the proper version
33 | // of the Python interpreter (i.e., Python 2 or Python 3).
34 | // Note that your hosting provider might have stringent rules for what
35 | // kind of scripts are allowed to execute. For instance, my provider
36 | // (Webfaction) seems to let scripts execute only if permissions are
37 | // something like:
38 | // -rwxr-xr-x 1 pgbovine pgbovine 2.5K Jul 5 22:46 web_exec_py2.py*
39 | // (most notably, only the owner of the file should have write
40 | // permissions)
41 | //var python2_backend_script = 'web_exec_py2.py';
42 | //var python3_backend_script = 'web_exec_py3.py';
43 |
44 |
45 |
46 | var rawInputLst = []; // a list of strings inputted by the user in response to raw_input or mouse_input events
47 |
48 |
49 | function getQueryStringOptions() {
50 | // note that any of these can be 'undefined'
51 | var preseededCode = $.bbq.getState('code');
52 | var preseededCurInstr = Number($.bbq.getState('curInstr'));
53 | var pyState = $.bbq.getState('py');
54 | var verticalStack = $.bbq.getState('verticalStack');
55 | var heapPrimitives = $.bbq.getState('heapPrimitives');
56 | var drawParentPointers = $.bbq.getState('drawParentPointers');
57 | var disableHeapNesting = true;
58 | var textRefs = $.bbq.getState('textReferences');
59 | var showOnlyOutputs = $.bbq.getState('showOnlyOutputs');
60 | var cumulativeState = $.bbq.getState('cumulative');
61 | var raw_input = $.bbq.getState('raw_input');
62 |
63 | return {preseededCode: preseededCode,
64 | preseededCurInstr: preseededCurInstr,
65 | pyState: pyState,
66 | verticalStack: verticalStack,
67 | heapPrimitives: heapPrimitives,
68 | drawParentPointers: drawParentPointers,
69 | disableHeapNesting: disableHeapNesting,
70 | textRefs: textRefs,
71 | showOnlyOutputs: showOnlyOutputs,
72 | cumulativeState: cumulativeState,
73 | raw_input: raw_input};
74 | }
75 |
76 |
77 | function executePythonCode(pythonSourceCode,
78 | backendScript, backendOptionsObj,
79 | frontendOptionsObj,
80 | outputDiv,
81 | handleSuccessFunc, handleUncaughtExceptionFunc) {
82 | if (!backendScript) {
83 | alert('Server configuration error: No backend script');
84 | return;
85 | }
86 |
87 | $.get(backendScript,
88 | {data:$.bbq.getState('data')},
89 | /*
90 | raw_input_json: rawInputLst.length > 0 ? JSON.stringify(rawInputLst) : '',
91 | */
92 | function(dataFromBackend) {
93 | var trace = dataFromBackend.trace;
94 |
95 | // don't enter visualize mode if there are killer errors:
96 | if (!trace ||
97 | (trace.length == 0) ||
98 | (trace[trace.length - 1].event == 'uncaught_exception')) {
99 |
100 | handleUncaughtExceptionFunc(trace);
101 |
102 | if (trace.length == 1) {
103 | alert(trace[0].exception_msg);
104 | }
105 | else if (trace[trace.length - 1].exception_msg) {
106 | alert(trace[trace.length - 1].exception_msg);
107 | }
108 | else {
109 | alert("Unknown error. Reload to try again," +
110 | "or report a bug to philip@pgbovine.net\n\n" +
111 | "(Click the 'Generate URL' button to include a " +
112 | "unique URL in your email bug report.)");
113 | }
114 | }
115 | else {
116 | // fail-soft to prevent running off of the end of trace
117 | if (frontendOptionsObj.startingInstruction >= trace.length) {
118 | frontendOptionsObj.startingInstruction = 0;
119 | }
120 | myVisualizer = new ExecutionVisualizer(outputDiv, dataFromBackend, frontendOptionsObj);
121 |
122 | // set keyboard bindings
123 | // VERY IMPORTANT to clear and reset this every time or
124 | // else the handlers might be bound multiple times
125 | $(document).unbind('keydown');
126 | $(document).keydown(function(k) {
127 | if (k.keyCode == 37) { // left arrow
128 | if (myVisualizer.stepBack()) {
129 | k.preventDefault(); // don't horizontally scroll the display
130 | }
131 | }
132 | else if (k.keyCode == 39) { // right arrow
133 | if (myVisualizer.stepForward()) {
134 | k.preventDefault(); // don't horizontally scroll the display
135 | }
136 | }
137 | });
138 |
139 | handleSuccessFunc();
140 | }
141 | },
142 | "json");
143 | }
144 |
--------------------------------------------------------------------------------
/embed/js/opt-frontend.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Online Python Tutor
4 | https://github.com/pgbovine/OnlinePythonTutor/
5 |
6 | Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net)
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a
9 | copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included
17 | in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 | */
28 |
29 |
30 |
31 | // Pre-reqs:
32 | // - pytutor.js
33 | // - jquery.ba-bbq.min.js
34 | // - opt-frontend-common.js
35 | // should all be imported BEFORE this file
36 |
37 | var appMode = 'edit'; // 'edit', 'display', or 'display_no_frills'
38 |
39 | var preseededCurInstr = null; // if you passed in a 'curInstr=' in the URL, then set this var
40 |
41 | var myVisualizer = null; // singleton ExecutionVisualizer instance
42 |
43 |
44 | function enterEditMode() {
45 | $.bbq.pushState({ mode: 'edit' }, 2 /* completely override other hash strings to keep URL clean */);
46 | }
47 |
48 | function enterDisplayNoFrillsMode() {
49 | $.bbq.pushState({ mode: 'display_no_frills' }, 2 /* completely override other hash strings to keep URL clean */);
50 | }
51 |
52 | var pyInputCodeMirror; // CodeMirror object that contains the input text
53 |
54 | function setCodeMirrorVal(dat) {
55 | pyInputCodeMirror.setValue(dat.rtrim() /* kill trailing spaces */);
56 | $('#urlOutput,#embedCodeOutput').val('');
57 |
58 | // also scroll to top to make the UI more usable on smaller monitors
59 | $(document).scrollTop(0);
60 | }
61 |
62 |
63 | $(document).ready(function() {
64 |
65 | $("#embedLinkDiv").hide();
66 |
67 | pyInputCodeMirror = CodeMirror(document.getElementById('codeInputPane'), {
68 | mode:
69 | {name: "python",
70 | version: 3,
71 | singleLineStringErrors: false
72 | },
73 | lineNumbers: true,
74 | indentUnit: 3,
75 | tabSize: 3,
76 | matchBrackets: true,
77 | extraKeys: {
78 | Tab: function(cm) {
79 | var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
80 | cm.replaceSelection(spaces, "end", "+input");
81 | }
82 | }
83 | });
84 |
85 | //pyInputCodeMirror.setSize(null, '240px');
86 |
87 |
88 |
89 | // be friendly to the browser's forward and back buttons
90 | // thanks to http://benalman.com/projects/jquery-bbq-plugin/
91 | $(window).bind("hashchange", function(e) {
92 | appMode = $.bbq.getState('mode'); // assign this to the GLOBAL appMode
93 |
94 | if (appMode === undefined || appMode == 'edit') {
95 | $("#pyInputPane").show();
96 | $("#pyOutputPane").hide();
97 | $("#embedLinkDiv").hide();
98 |
99 | // destroy all annotation bubbles (NB: kludgy)
100 | if (myVisualizer) {
101 | myVisualizer.destroyAllAnnotationBubbles();
102 | }
103 | }
104 | else if (appMode == 'display') {
105 | $("#pyInputPane").hide();
106 | $("#pyOutputPane").show();
107 |
108 | $("#embedLinkDiv").show();
109 |
110 | $('#executeBtn').html("Visualize Execution");
111 | $('#executeBtn').attr('disabled', false);
112 |
113 |
114 | // do this AFTER making #pyOutputPane visible, or else
115 | // jsPlumb connectors won't render properly
116 | myVisualizer.updateOutput();
117 |
118 | // customize edit button click functionality AFTER rendering (NB: awkward!)
119 | $('#pyOutputPane #editCodeLinkDiv').show();
120 | $('#pyOutputPane #editBtn').click(function() {
121 | enterEditMode();
122 | });
123 | }
124 | else if (appMode == 'display_no_frills') {
125 | $("#pyInputPane").hide();
126 | $("#pyOutputPane").show();
127 | $("#embedLinkDiv").show();
128 | }
129 | else {
130 | assert(false);
131 | }
132 |
133 | $('#urlOutput,#embedCodeOutput').val(''); // clear to avoid stale values
134 | });
135 |
136 | function getRawInput() {
137 | if (typeof window.stdinPane === "undefined")
138 | return "";
139 | else return window.stdinPane.value;
140 | }
141 |
142 | function executeCode(forceStartingInstr) {
143 | var backend_script = null;
144 | if ($('#pythonVersionSelector').val() == '2') {
145 | backend_script = python2_backend_script;
146 | }
147 | else if ($('#pythonVersionSelector').val() == '3') {
148 | backend_script = python3_backend_script;
149 | }
150 | // experimental KRAZY MODE!!!
151 | else if ($('#pythonVersionSelector').val() == '2crazy') {
152 | backend_script = python2crazy_backend_script;
153 | }
154 |
155 | $('#executeBtn').html("Please wait ... processing your code");
156 | $('#executeBtn').attr('disabled', true);
157 | $("#pyOutputPane").hide();
158 | $("#embedLinkDiv").hide();
159 |
160 | var backendOptionsObj = {cumulative_mode: ($('#cumulativeModeSelector').val() == 'true'),
161 | heap_primitives: ($('#heapPrimitivesSelector').val() == 'true'),
162 | show_only_outputs: ($('#showOnlyOutputsSelector').val() == 'true'),
163 | py_crazy_mode: ($('#pythonVersionSelector').val() == '2crazy'),
164 | raw_input: getRawInput(),
165 | origin: 'opt-frontend.js'};
166 |
167 |
168 | var startingInstruction = 0;
169 |
170 | // only do this at most ONCE, and then clear out preseededCurInstr
171 | // NOP anyways if preseededCurInstr is 0
172 | if (preseededCurInstr) {
173 | startingInstruction = preseededCurInstr;
174 | preseededCurInstr = null;
175 | }
176 |
177 | // forceStartingInstr overrides everything else
178 | if (forceStartingInstr !== undefined) {
179 | startingInstruction = forceStartingInstr;
180 | }
181 |
182 | var frontendOptionsObj = {startingInstruction: startingInstruction,
183 | // tricky: selector 'true' and 'false' values are strings!
184 | disableHeapNesting: ($('#heapPrimitivesSelector').val() == 'true'),
185 | drawParentPointers: ($('#drawParentPointerSelector').val() == 'true'),
186 | textualMemoryLabels: ($('#textualMemoryLabelsSelector').val() == 'true'),
187 | showOnlyOutputs: ($('#showOnlyOutputsSelector').val() == 'true'),
188 | executeCodeWithRawInputFunc: executeCodeWithRawInput,
189 | updateOutputCallback: function() {$('#urlOutput,#embedCodeOutput').val('');},
190 |
191 | // undocumented experimental modes:
192 | pyCrazyMode: ($('#pythonVersionSelector').val() == '2crazy'),
193 | //allowEditAnnotations: true,
194 |
195 | highlightLines: true,
196 | }
197 |
198 | function handleSuccessFunc() {
199 | // also scroll to top to make the UI more usable on smaller monitors
200 | $(document).scrollTop(0);
201 |
202 | $.bbq.pushState({ mode: 'display' }, 2 /* completely override other hash strings to keep URL clean */);
203 | }
204 |
205 | function handleUncaughtExceptionFunc(trace) {
206 | if (trace.length == 1) {
207 | var errorLineNo = trace[0].line - 1; /* CodeMirror lines are zero-indexed */
208 | if (errorLineNo !== undefined) {
209 | // highlight the faulting line in pyInputCodeMirror
210 | pyInputCodeMirror.focus();
211 | /* CodeMirror 2
212 | pyInputCodeMirror.setCursor(errorLineNo, 0);
213 | pyInputCodeMirror.setLineClass(errorLineNo, null, 'errorLine');
214 |
215 | pyInputCodeMirror.setOption('onChange', function() {
216 | pyInputCodeMirror.setLineClass(errorLineNo, null, null); // reset line back to normal
217 | pyInputCodeMirror.setOption('onChange', null); // cancel
218 | });
219 | */
220 | /* CodeMirror 3 */
221 | var marked = pyInputCodeMirror.addLineClass(errorLineNo, null, 'errorLine');
222 | var hook = function(marked) { return function() {
223 | pyInputCodeMirror.removeLineClass(marked, null, 'errorLine'); // reset line back to normal
224 | pyInputCodeMirror.off('change', hook); // cancel
225 | }} (marked);
226 | pyInputCodeMirror.on('change', hook);
227 |
228 | }
229 |
230 | $('#executeBtn').html("Visualize Execution");
231 | $('#executeBtn').attr('disabled', false);
232 | }
233 | }
234 |
235 | executePythonCode(pyInputCodeMirror.getValue(),
236 | backend_script, backendOptionsObj,
237 | frontendOptionsObj,
238 | 'pyOutputPane',
239 | handleSuccessFunc, handleUncaughtExceptionFunc);
240 | }
241 |
242 | function executeCodeFromScratch() {
243 | // reset these globals
244 | rawInputLst = [];
245 | executeCode();
246 | }
247 |
248 | function executeCodeWithRawInput(rawInputStr, curInstr) {
249 | enterDisplayNoFrillsMode();
250 |
251 | // set some globals
252 | rawInputLst.push(rawInputStr);
253 | executeCode(curInstr);
254 | }
255 |
256 | $("#executeBtn").attr('disabled', false);
257 | $("#executeBtn").click(executeCodeFromScratch);
258 |
259 |
260 | // canned examples
261 |
262 | $("#tutorialExampleLink").click(function() {
263 | $.get("example-code/py_tutorial.txt", setCodeMirrorVal);
264 | return false;
265 | });
266 |
267 | $("#strtokExampleLink").click(function() {
268 | $.get("example-code/strtok.txt", setCodeMirrorVal);
269 | return false;
270 | });
271 |
272 | $("#listCompLink").click(function() {
273 | $.get("example-code/list-comp.txt", setCodeMirrorVal);
274 | return false;
275 | });
276 |
277 | $("#fibonacciExampleLink").click(function() {
278 | $.get("example-code/fib.txt", setCodeMirrorVal);
279 | return false;
280 | });
281 |
282 | $("#memoFibExampleLink").click(function() {
283 | $.get("example-code/memo_fib.txt", setCodeMirrorVal);
284 | return false;
285 | });
286 |
287 | $("#factExampleLink").click(function() {
288 | $.get("example-code/fact.txt", setCodeMirrorVal);
289 | return false;
290 | });
291 |
292 | $("#filterExampleLink").click(function() {
293 | $.get("example-code/filter.txt", setCodeMirrorVal);
294 | return false;
295 | });
296 |
297 | $("#insSortExampleLink").click(function() {
298 | $.get("example-code/ins_sort.txt", setCodeMirrorVal);
299 | return false;
300 | });
301 |
302 | $("#aliasExampleLink").click(function() {
303 | $.get("example-code/aliasing.txt", setCodeMirrorVal);
304 | return false;
305 | });
306 |
307 | $("#happyExampleLink").click(function() {
308 | $.get("example-code/happy.txt", setCodeMirrorVal);
309 | return false;
310 | });
311 |
312 | $("#newtonExampleLink").click(function() {
313 | $.get("example-code/sqrt.txt", setCodeMirrorVal);
314 | return false;
315 | });
316 |
317 | $("#oopSmallExampleLink").click(function() {
318 | $.get("example-code/oop_small.txt", setCodeMirrorVal);
319 | return false;
320 | });
321 |
322 | $("#mapExampleLink").click(function() {
323 | $.get("example-code/map.txt", setCodeMirrorVal);
324 | return false;
325 | });
326 |
327 | $("#rawInputExampleLink").click(function() {
328 | $.get("example-code/raw_input.txt", setCodeMirrorVal);
329 | return false;
330 | });
331 |
332 | $("#oop1ExampleLink").click(function() {
333 | $.get("example-code/oop_1.txt", setCodeMirrorVal);
334 | return false;
335 | });
336 |
337 | $("#oop2ExampleLink").click(function() {
338 | $.get("example-code/oop_2.txt", setCodeMirrorVal);
339 | return false;
340 | });
341 |
342 | $("#inheritanceExampleLink").click(function() {
343 | $.get("example-code/oop_inherit.txt", setCodeMirrorVal);
344 | return false;
345 | });
346 |
347 | $("#sumExampleLink").click(function() {
348 | $.get("example-code/sum.txt", setCodeMirrorVal);
349 | return false;
350 | });
351 |
352 | $("#pwGcdLink").click(function() {
353 | $.get("example-code/wentworth_gcd.txt", setCodeMirrorVal);
354 | return false;
355 | });
356 |
357 | $("#pwSumListLink").click(function() {
358 | $.get("example-code/wentworth_sumList.txt", setCodeMirrorVal);
359 | return false;
360 | });
361 |
362 | $("#towersOfHanoiLink").click(function() {
363 | $.get("example-code/towers_of_hanoi.txt", setCodeMirrorVal);
364 | return false;
365 | });
366 |
367 | $("#pwTryFinallyLink").click(function() {
368 | $.get("example-code/wentworth_try_finally.txt", setCodeMirrorVal);
369 | return false;
370 | });
371 |
372 | $("#sumCubesLink").click(function() {
373 | $.get("example-code/sum-cubes.txt", setCodeMirrorVal);
374 | return false;
375 | });
376 |
377 | $("#decoratorsLink").click(function() {
378 | $.get("example-code/decorators.txt", setCodeMirrorVal);
379 | return false;
380 | });
381 |
382 | $("#genPrimesLink").click(function() {
383 | $.get("example-code/gen_primes.txt", setCodeMirrorVal);
384 | return false;
385 | });
386 |
387 | $("#genExprLink").click(function() {
388 | $.get("example-code/genexpr.txt", setCodeMirrorVal);
389 | return false;
390 | });
391 |
392 |
393 | $('#closure1Link').click(function() {
394 | $.get("example-code/closures/closure1.txt", setCodeMirrorVal);
395 | return false;
396 | });
397 | $('#closure2Link').click(function() {
398 | $.get("example-code/closures/closure2.txt", setCodeMirrorVal);
399 | return false;
400 | });
401 | $('#closure3Link').click(function() {
402 | $.get("example-code/closures/closure3.txt", setCodeMirrorVal);
403 | return false;
404 | });
405 | $('#closure4Link').click(function() {
406 | $.get("example-code/closures/closure4.txt", setCodeMirrorVal);
407 | return false;
408 | });
409 | $('#closure5Link').click(function() {
410 | $.get("example-code/closures/closure5.txt", setCodeMirrorVal);
411 | return false;
412 | });
413 | $('#lambdaParamLink').click(function() {
414 | $.get("example-code/closures/lambda-param.txt", setCodeMirrorVal);
415 | return false;
416 | });
417 | $('#tortureLink').click(function() {
418 | $.get("example-code/closures/student-torture.txt", setCodeMirrorVal);
419 | return false;
420 | });
421 |
422 |
423 |
424 | $('#aliasing1Link').click(function() {
425 | $.get("example-code/aliasing/aliasing1.txt", setCodeMirrorVal);
426 | return false;
427 | });
428 | $('#aliasing2Link').click(function() {
429 | $.get("example-code/aliasing/aliasing2.txt", setCodeMirrorVal);
430 | return false;
431 | });
432 | $('#aliasing3Link').click(function() {
433 | $.get("example-code/aliasing/aliasing3.txt", setCodeMirrorVal);
434 | return false;
435 | });
436 | $('#aliasing4Link').click(function() {
437 | $.get("example-code/aliasing/aliasing4.txt", setCodeMirrorVal);
438 | return false;
439 | });
440 | $('#aliasing5Link').click(function() {
441 | $.get("example-code/aliasing/aliasing5.txt", setCodeMirrorVal);
442 | return false;
443 | });
444 | $('#aliasing6Link').click(function() {
445 | $.get("example-code/aliasing/aliasing6.txt", setCodeMirrorVal);
446 | return false;
447 | });
448 | $('#aliasing7Link').click(function() {
449 | $.get("example-code/aliasing/aliasing7.txt", setCodeMirrorVal);
450 | return false;
451 | });
452 | $('#aliasing8Link').click(function() {
453 | $.get("example-code/aliasing/aliasing8.txt", setCodeMirrorVal);
454 | return false;
455 | });
456 |
457 |
458 | $('#ll1Link').click(function() {
459 | $.get("example-code/linked-lists/ll1.txt", setCodeMirrorVal);
460 | return false;
461 | });
462 | $('#ll2Link').click(function() {
463 | $.get("example-code/linked-lists/ll2.txt", setCodeMirrorVal);
464 | return false;
465 | });
466 | $('#sumListLink').click(function() {
467 | $.get("example-code/sum-list.txt", setCodeMirrorVal);
468 | return false;
469 | });
470 |
471 | $('#varargsLink').click(function() {
472 | $.get("example-code/varargs.txt", setCodeMirrorVal);
473 | return false;
474 | });
475 |
476 | $('#forElseLink').click(function() {
477 | $.get("example-code/for-else.txt", setCodeMirrorVal);
478 | return false;
479 | });
480 |
481 | $('#nonlocalLink').click(function() {
482 | $.get("example-code/nonlocal.txt", setCodeMirrorVal);
483 | return false;
484 | });
485 |
486 |
487 | var queryStrOptions = getQueryStringOptions();
488 |
489 | if (queryStrOptions.preseededCode) {
490 | setCodeMirrorVal(queryStrOptions.preseededCode);
491 | }
492 | else {
493 | // select a canned example on start-up:
494 | // $("#aliasExampleLink").trigger('click');
495 | }
496 |
497 | if (queryStrOptions.raw_input !== undefined) {
498 | window.stdinPane.value = queryStrOptions.raw_input;
499 | }
500 |
501 | // ugh, ugly tristate due to the possibility of each being undefined
502 | if (queryStrOptions.pyState !== undefined) {
503 | $('#pythonVersionSelector').val(queryStrOptions.pyState);
504 | }
505 | if (queryStrOptions.cumulativeState !== undefined) {
506 | $('#cumulativeModeSelector').val(queryStrOptions.cumulativeState);
507 | }
508 | if (queryStrOptions.heapPrimitives !== undefined) {
509 | $('#heapPrimitivesSelector').val(queryStrOptions.heapPrimitives);
510 | }
511 | if (queryStrOptions.drawParentPointers !== undefined) {
512 | $('#drawParentPointerSelector').val(queryStrOptions.drawParentPointers);
513 | }
514 | if (queryStrOptions.textRefs !== undefined) {
515 | $('#textualMemoryLabelsSelector').val(queryStrOptions.textRefs);
516 | }
517 | if (queryStrOptions.showOnlyOutputs !== undefined) {
518 | $('#showOnlyOutputsSelector').val(queryStrOptions.showOnlyOutputs);
519 | }
520 |
521 |
522 | appMode = $.bbq.getState('mode'); // assign this to the GLOBAL appMode
523 | if ((appMode == "display") && queryStrOptions.preseededCode /* jump to display only with pre-seeded code */) {
524 | preseededCurInstr = queryStrOptions.preseededCurInstr; // ugly global
525 | $("#executeBtn").trigger('click');
526 | }
527 | else {
528 | if (appMode === undefined) {
529 | // default mode is 'edit', don't trigger a "hashchange" event
530 | appMode = 'edit';
531 | }
532 | else {
533 | // fail-soft by killing all passed-in hashes and triggering a "hashchange"
534 | // event, which will then go to 'edit' mode
535 | $.bbq.removeState();
536 | }
537 | }
538 |
539 |
540 | // log a generic AJAX error handler
541 | $(document).ajaxError(function() {
542 | alert("Server error (possibly due to memory/resource overload). " +
543 | "Report a bug to philip@pgbovine.net\n\n" +
544 | "(Click the 'Generate URL' button to include a unique URL in your email bug report.)");
545 |
546 | $('#executeBtn').html("Visualize Execution");
547 | $('#executeBtn').attr('disabled', false);
548 | });
549 |
550 |
551 | // redraw connector arrows on window resize
552 | $(window).resize(function() {
553 | if (appMode == 'display') {
554 | myVisualizer.redrawConnectors();
555 | }
556 | });
557 |
558 | $('#genUrlBtn').bind('click', function() {
559 | var myArgs = {code: pyInputCodeMirror.getValue(),
560 | mode: appMode,
561 | //cumulative: $('#cumulativeModeSelector').val(),
562 | //heapPrimitives: $('#heapPrimitivesSelector').val(),
563 | //drawParentPointers: $('#drawParentPointerSelector').val(),
564 | //textReferences: $('#textualMemoryLabelsSelector').val(),
565 | //showOnlyOutputs: $('#showOnlyOutputsSelector').val(),
566 | //py: $('#pythonVersionSelector').val()
567 | raw_input: getRawInput(),
568 | };
569 |
570 | if (appMode == 'display') {
571 | myArgs.curInstr = myVisualizer.curInstr;
572 | }
573 |
574 | var urlStr = $.param.fragment(window.location.href, myArgs, 2 /* clobber all */);
575 | $('#urlOutput').val(urlStr);
576 | });
577 |
578 |
579 | $('#genEmbedBtn').bind('click', function() {
580 | assert(appMode == 'display');
581 | var myArgs = {code: pyInputCodeMirror.getValue(),
582 | cumulative: $('#cumulativeModeSelector').val(),
583 | heapPrimitives: $('#heapPrimitivesSelector').val(),
584 | drawParentPointers: $('#drawParentPointerSelector').val(),
585 | textReferences: $('#textualMemoryLabelsSelector').val(),
586 | showOnlyOutputs: $('#showOnlyOutputsSelector').val(),
587 | py: $('#pythonVersionSelector').val(),
588 | curInstr: myVisualizer.curInstr,
589 | codeDivWidth: myVisualizer.DEFAULT_EMBEDDED_CODE_DIV_WIDTH,
590 | codeDivHeight: myVisualizer.DEFAULT_EMBEDDED_CODE_DIV_HEIGHT,
591 | };
592 |
593 | var embedUrlStr = $.param.fragment(domain + "iframe-embed.html", myArgs, 2 /* clobber all */);
594 | var iframeStr = '';
595 | $('#embedCodeOutput').val(iframeStr);
596 | });
597 | });
598 |
599 |
--------------------------------------------------------------------------------
/example-code/(Default).java:
--------------------------------------------------------------------------------
1 | public class ClassNameHere {
2 | public static void main(String[] args) {
3 |
4 | }
5 | }
--------------------------------------------------------------------------------
/example-code/.dir-locals.el:
--------------------------------------------------------------------------------
1 | (
2 | (java-mode
3 | (indent-tabs-mode . nil)
4 | (c-basic-offset . 3))
5 | )
6 |
--------------------------------------------------------------------------------
/example-code/.gitignore:
--------------------------------------------------------------------------------
1 | Fakey.java
--------------------------------------------------------------------------------
/example-code/.htaccess:
--------------------------------------------------------------------------------
1 | Options +Indexes
--------------------------------------------------------------------------------
/example-code/Casting.java:
--------------------------------------------------------------------------------
1 | public class Casting {
2 | public static void main(String[] args) {
3 | // casting doesn't change the object
4 | Object obj;
5 | {
6 | Stopwatch w = new Stopwatch();
7 | obj = w;
8 | }
9 | System.out.println(obj); // still a Stopwatch
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/example-code/CmdLineArgs.java:
--------------------------------------------------------------------------------
1 | public class CmdLineArgs {
2 | public static void main(String[] args) {
3 | // you can change "args" in the boxes below this window
4 | int a = Integer.parseInt(args[0]);
5 | int b = Integer.parseInt(args[1]);
6 | int sum = a + b;
7 | int prod = a * b;
8 | int quot = a / b;
9 | int rem = a % b;
10 | System.out.println(a + " + " + b + " = " + sum);
11 | System.out.println(a + " * " + b + " = " + prod);
12 | System.out.println(a + " / " + b + " = " + quot);
13 | System.out.println(a + " % " + b + " = " + rem);
14 | }
15 | }
16 | /*viz_options {"args":["1234","99"]}*/
--------------------------------------------------------------------------------
/example-code/Complex.java:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | * From: http://introcs.cs.princeton.edu/java/home/ (Section 9.7)
3 | *
4 | * Compilation: javac Complex.java
5 | * Execution: java Complex
6 | *
7 | * Data type for complex numbers.
8 | *
9 | * The data type is "immutable" so once you create and initialize
10 | * a Complex object, you cannot change it. The "final" keyword
11 | * when declaring re and im enforces this rule, making it a
12 | * compile-time error to change the .re or .im fields after
13 | * they've been initialized.
14 | *
15 | * % java Complex
16 | * a = 5.0 + 6.0i
17 | * b = -3.0 + 4.0i
18 | * Re(a) = 5.0
19 | * Im(a) = 6.0
20 | * b + a = 2.0 + 10.0i
21 | * a - b = 8.0 + 2.0i
22 | * a * b = -39.0 + 2.0i
23 | * b * a = -39.0 + 2.0i
24 | * a / b = 0.36 - 1.52i
25 | * (a / b) * b = 5.0 + 6.0i
26 | * conj(a) = 5.0 - 6.0i
27 | * |a| = 7.810249675906654
28 | * tan(a) = -6.685231390246571E-6 + 1.0000103108981198i
29 | *
30 | *************************************************************************/
31 |
32 | public class Complex {
33 | private final double re; // the real part
34 | private final double im; // the imaginary part
35 |
36 | // create a new object with the given real and imaginary parts
37 | public Complex(double real, double imag) {
38 | re = real;
39 | im = imag;
40 | }
41 |
42 | // return a string representation of the invoking Complex object
43 | public String toString() {
44 | if (im == 0) return re + "";
45 | if (re == 0) return im + "i";
46 | if (im < 0) return re + " - " + (-im) + "i";
47 | return re + " + " + im + "i";
48 | }
49 |
50 | // return abs/modulus/magnitude and angle/phase/argument
51 | public double abs() { return Math.hypot(re, im); } // Math.sqrt(re*re + im*im)
52 | public double phase() { return Math.atan2(im, re); } // between -pi and pi
53 |
54 | // return a new Complex object whose value is (this + b)
55 | public Complex plus(Complex b) {
56 | Complex a = this; // invoking object
57 | double real = a.re + b.re;
58 | double imag = a.im + b.im;
59 | return new Complex(real, imag);
60 | }
61 |
62 | // return a new Complex object whose value is (this - b)
63 | public Complex minus(Complex b) {
64 | Complex a = this;
65 | double real = a.re - b.re;
66 | double imag = a.im - b.im;
67 | return new Complex(real, imag);
68 | }
69 |
70 | // return a new Complex object whose value is (this * b)
71 | public Complex times(Complex b) {
72 | Complex a = this;
73 | double real = a.re * b.re - a.im * b.im;
74 | double imag = a.re * b.im + a.im * b.re;
75 | return new Complex(real, imag);
76 | }
77 |
78 | // scalar multiplication
79 | // return a new object whose value is (this * alpha)
80 | public Complex times(double alpha) {
81 | return new Complex(alpha * re, alpha * im);
82 | }
83 |
84 | // return a new Complex object whose value is the conjugate of this
85 | public Complex conjugate() { return new Complex(re, -im); }
86 |
87 | // return a new Complex object whose value is the reciprocal of this
88 | public Complex reciprocal() {
89 | double scale = re*re + im*im;
90 | return new Complex(re / scale, -im / scale);
91 | }
92 |
93 | // return the real or imaginary part
94 | public double re() { return re; }
95 | public double im() { return im; }
96 |
97 | // return a / b
98 | public Complex divides(Complex b) {
99 | Complex a = this;
100 | return a.times(b.reciprocal());
101 | }
102 |
103 | // return a new Complex object whose value is the complex exponential of this
104 | public Complex exp() {
105 | return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));
106 | }
107 |
108 | // return a new Complex object whose value is the complex sine of this
109 | public Complex sin() {
110 | return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));
111 | }
112 |
113 | // return a new Complex object whose value is the complex cosine of this
114 | public Complex cos() {
115 | return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));
116 | }
117 |
118 | // return a new Complex object whose value is the complex tangent of this
119 | public Complex tan() {
120 | return sin().divides(cos());
121 | }
122 |
123 |
124 |
125 | // a static version of plus
126 | public static Complex plus(Complex a, Complex b) {
127 | double real = a.re + b.re;
128 | double imag = a.im + b.im;
129 | Complex sum = new Complex(real, imag);
130 | return sum;
131 | }
132 |
133 |
134 |
135 | // sample client for testing
136 | public static void main(String[] args) {
137 | Complex a = new Complex(5.0, 6.0);
138 | Complex b = new Complex(-3.0, 4.0);
139 |
140 | System.out.println("a = " + a);
141 | System.out.println("b = " + b);
142 | System.out.println("Re(a) = " + a.re());
143 | System.out.println("Im(a) = " + a.im());
144 | System.out.println("b + a = " + b.plus(a));
145 | System.out.println("a - b = " + a.minus(b));
146 | System.out.println("a * b = " + a.times(b));
147 | System.out.println("b * a = " + b.times(a));
148 | System.out.println("a / b = " + a.divides(b));
149 | System.out.println("(a / b) * b = " + a.divides(b).times(b));
150 | System.out.println("conj(a) = " + a.conjugate());
151 | System.out.println("|a| = " + a.abs());
152 | }
153 |
154 | }
--------------------------------------------------------------------------------
/example-code/ControlFlow.java:
--------------------------------------------------------------------------------
1 | public class ControlFlow {
2 | public static void main(String[] args) {
3 | while (true) {
4 | double roll = 3*Math.random();
5 | if (roll > 2.8)
6 | break;
7 | if ((int)roll == 2)
8 | continue;
9 | else if ((int)roll == 0)
10 | System.out.println("low");
11 | else
12 | System.out.println("hi");
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/example-code/Exception.java:
--------------------------------------------------------------------------------
1 | public class Exception {
2 | public static void main(String[] args) {
3 | // this one will be caught
4 | int x = 0;
5 | try {
6 | x = 1/x;
7 | }
8 | catch (RuntimeException e) {
9 | x = -1;
10 | System.out.println("Caught!");
11 | }
12 | System.out.println(x);
13 |
14 | System.out.println(1/0);
15 | System.out.println("this won't run");
16 | }
17 | }
--------------------------------------------------------------------------------
/example-code/ExceptionFlow.java:
--------------------------------------------------------------------------------
1 | public class ExceptionFlow {
2 | static String trace = "";
3 |
4 | static void f() {
5 | trace += "call-f ";
6 | g();
7 | trace += "return-f ";
8 | }
9 |
10 | static void g() {
11 | trace += "call-g ";
12 | int z = 1/0;
13 | trace += "return-g ";
14 | }
15 |
16 | public static void main(String[] args) {
17 | try {
18 | f();
19 | }
20 | catch (RuntimeException e) {
21 | trace += "caught!";
22 | }
23 | System.out.println(trace);
24 | }
25 | }
--------------------------------------------------------------------------------
/example-code/ExecLimit.java:
--------------------------------------------------------------------------------
1 | public class ExecLimit {
2 | public static void main(String[] args) {
3 | int sum = 0;
4 | for (int i=0; i<300; i++)
5 | sum += i;
6 | }
7 | }
--------------------------------------------------------------------------------
/example-code/Forest.java:
--------------------------------------------------------------------------------
1 | // Princeton COS 126 Written Exam 2, Fall 2010, Question 3
2 | // note: this is a proof-of-concept, but to do this on
3 | // paper you would instead skip as many internal steps of
4 | // root, merge, and merged as possible
5 |
6 | public class Node {
7 | private Node next;
8 | private int index;
9 | private Node root() {
10 | if (next == null) return this;
11 | return next.root();
12 | }
13 | public static void merge(Node a, Node b) {
14 | a.root().next = b.root();
15 | }
16 | public static boolean merged(Node a, Node b) {
17 | return a.root() == b.root();
18 | }
19 | public static void main(String[] args) {
20 | Node[] f = new Node[8];
21 | for (int i=0; i<8; i++) {f[i] = new Node(); f[i].index=i;}
22 | merge(f[0], f[3]);
23 | merge(f[1], f[2]);
24 | merge(f[1], f[4]);
25 | merge(f[5], f[6]);
26 | merge(f[3], f[4]);
27 | merge(f[7], f[5]);
28 |
29 | System.out.println(merged(f[0], f[3]));
30 | System.out.println(merged(f[0], f[7]));
31 | System.out.println(merged(f[1], f[3]));
32 | System.out.println(merged(f[4], f[5]));
33 | }
34 | }
--------------------------------------------------------------------------------
/example-code/Knapsack.java:
--------------------------------------------------------------------------------
1 | public class Knapsack {
2 | public static void main(String[] args) {
3 | int[] itemSizes = {3, 5, 6, 8};
4 | int capacity = 15;
5 | boolean[] canMakeSum = new boolean[capacity+1];
6 | canMakeSum[0] = true;
7 | for (int size : itemSizes) {
8 | for (int i=capacity; i>=size; i--)
9 | canMakeSum[i] |= canMakeSum[i-size];
10 | }
11 | System.out.println(java.util.Arrays.toString(canMakeSum));
12 | }
13 | }
--------------------------------------------------------------------------------
/example-code/LambdaExample.java:
--------------------------------------------------------------------------------
1 | import java.util.function.*;
2 |
3 | public class LambdaExample {
4 | // note: this only works in Java 8
5 |
6 | static Function inc(int x) {
7 | return y -> x+y;
8 | }
9 |
10 | static Function mul(int x) {
11 | return y -> x*y;
12 | }
13 |
14 | public static void main(String[] args) {
15 | // bad style, generic erasure to get array
16 | Function[] fs = {inc(5), inc(10), mul(7), mul(2)};
17 |
18 | for (Function f : fs)
19 | System.out.println(
20 | ((Function)f).apply(100));
21 | }
22 | }
--------------------------------------------------------------------------------
/example-code/LinkedList.java:
--------------------------------------------------------------------------------
1 | // named after barrel of monkeys:
2 | // each one hangs on to the next
3 | public class LinkedList {
4 |
5 | // structure of items in list
6 | class Node {
7 | // each node knows "next" node
8 | Node next;
9 | // and stores a value
10 | String name;
11 | // constructor for nodes
12 | Node(String initialName) {
13 | name = initialName;
14 | }
15 | }
16 |
17 | // beginning of the list, initially empty
18 | private Node first = null;
19 |
20 | // a demo to create a length-3 list
21 | public void threeKongs() {
22 | first = new Node("DK Sr.");
23 | first.next = new Node("DK");
24 | first.next.next = new Node("DK Jr.");
25 | }
26 |
27 | // use a loop to print all
28 | public void printAll() {
29 | // a while loop also can work
30 | for (Node current = first;
31 | current != null;
32 | current = current.next) {
33 | System.out.println(current.name);
34 | }
35 | }
36 |
37 | public static void main(String[] args) {
38 | LinkedList mc = new LinkedList();
39 | mc.threeKongs();
40 | mc.printAll();
41 | }
42 | }
43 | /*viz_options {"disableNesting":true}*/
--------------------------------------------------------------------------------
/example-code/PassByValue.java:
--------------------------------------------------------------------------------
1 | public class PassByValue {
2 |
3 | static void reset(int x) {
4 | x = 0;
5 | }
6 |
7 | static void reset(int[] x) {
8 | for (int i : x)
9 | i = 0;
10 | }
11 |
12 | static void reallyReset(int[] x) {
13 | for (int i=0; i stacky = new Stack<>();
5 | for (char ch : "123+45*6-+-".toCharArray()) {
6 | if (ch == '+')
7 | stacky.push(stacky.pop() + stacky.pop());
8 | else if (ch == '*')
9 | stacky.push(stacky.pop() * stacky.pop());
10 | else if (ch == '-')
11 | stacky.push(-stacky.pop() + stacky.pop());
12 | else
13 | stacky.push(ch-'0');
14 | }
15 | System.out.println(stacky.pop());
16 | }
17 | }
--------------------------------------------------------------------------------
/example-code/Recursion.java:
--------------------------------------------------------------------------------
1 | public class Recursion {
2 | public static void ruler(int n) {
3 | if (n>0) ruler(n-1);
4 | System.out.println(n);
5 | if (n>0) ruler(n-1);
6 | }
7 | public static void main(String[] args) {
8 | ruler(2);
9 | }
10 | }
--------------------------------------------------------------------------------
/example-code/Reflect.java:
--------------------------------------------------------------------------------
1 | import java.lang.reflect.*;
2 |
3 | public class Reflect {
4 | public static void announce() {
5 | System.out.println("Someone called announce().");
6 | }
7 | public static void main(String[] args) {
8 | try {
9 | Method m = Reflect.class.getMethod("announce", null);
10 | m.invoke(null); // null "this" since it's a static method
11 | }
12 | catch (NoSuchMethodException | IllegalAccessException
13 | | InvocationTargetException e) {}
14 | }
15 | }
--------------------------------------------------------------------------------
/example-code/Rolex.java:
--------------------------------------------------------------------------------
1 | public class Rolex {
2 | private final long start;
3 |
4 | public Rolex() {
5 | start = System.currentTimeMillis();
6 | }
7 |
8 | // return time (in seconds) since this object was created
9 | public double elapsedTime() {
10 | long now = System.currentTimeMillis();
11 | return (now - start) / 1000.0;
12 | }
13 |
14 | public static void main(String[] args) {
15 | Rolex watchOne = new Rolex();
16 | // waste time so it is large enough to be measurable
17 | try {Thread.sleep(500);} catch (InterruptedException e) {}
18 |
19 | Rolex watchTwo = new Rolex();
20 | // waste time so it is large enough to be measurable
21 | try {Thread.sleep(500);} catch (InterruptedException e) {}
22 |
23 | // right now, watchOne is older
24 | System.out.println("watchOne " + watchOne.elapsedTime());
25 | System.out.println("watchTwo " + watchTwo.elapsedTime());
26 |
27 | Rolex watchTmp = watchOne;
28 | watchOne = watchTwo;
29 | watchTwo = watchTmp;
30 |
31 | // swapped! now watchTwo is the older one
32 | // e.g. watchTwo.elapsedTime() returns a value
33 | // (slightly) larger than watchOne.elapsedTime()
34 | System.out.println("watchOne " + watchOne.elapsedTime());
35 | System.out.println("watchTwo " + watchTwo.elapsedTime());
36 | }
37 | }
--------------------------------------------------------------------------------
/example-code/Sqrt.java:
--------------------------------------------------------------------------------
1 | public class Sqrt {
2 | public static void main(String[] args) {
3 | double target = 2013;
4 | double x = 1;
5 | double oldx;
6 | do {
7 | oldx = x;
8 | x = (x + target / x) / 2;
9 | }
10 | while (oldx != x);
11 | System.out.println(x);
12 | System.out.println(x*x);
13 | }
14 | }
--------------------------------------------------------------------------------
/example-code/StackOverflow.java:
--------------------------------------------------------------------------------
1 | public class StackOverflow {
2 | private static void burn(int i) {
3 | i = i + 1;
4 | burn(i);
5 | }
6 | public static void main(String[] args) {
7 | burn(0);
8 | }
9 | }
--------------------------------------------------------------------------------
/example-code/StackQueue.java:
--------------------------------------------------------------------------------
1 | public class StackQueue {
2 | public static void main(String[] args) {
3 | Stack stack = new Stack<>();
4 | Queue queue = new Queue<>();
5 |
6 | stack.push("stack-first");
7 | stack.push("stack-last");
8 |
9 | queue.enqueue("queue-first");
10 | queue.enqueue("queue-last");
11 |
12 | for (String s : stack)
13 | System.out.println("stack contains " + s);
14 | for (String s : queue)
15 | System.out.println("queue contains " + s);
16 |
17 | while (!stack.isEmpty())
18 | System.out.println(stack.pop());
19 | while (!queue.isEmpty())
20 | System.out.println(queue.dequeue());
21 | }
22 | }
--------------------------------------------------------------------------------
/example-code/StaticInitializer.java:
--------------------------------------------------------------------------------
1 | public class StaticInitializer {
2 | static {
3 | // static initializer, runs when class is initialized
4 | System.out.println("When will this print?");
5 | }
6 | public static void main(String[] args) {
7 | System.out.println("Now we're in main");
8 | }
9 | }
--------------------------------------------------------------------------------
/example-code/StdIn.java:
--------------------------------------------------------------------------------
1 | public class StdInDemo {
2 | public static void main(String[] args) {
3 | StdOut.println("int: " + StdIn.readInt());
4 | StdOut.println("double: " + StdIn.readDouble());
5 | StdOut.println("String (token): " + StdIn.readString());
6 | StdOut.println("char: " + StdIn.readChar());
7 | StdOut.println("char: " + StdIn.readChar());
8 | StdOut.println("line: " + StdIn.readLine());
9 | StdOut.println("empty?: " + StdIn.isEmpty());
10 | }
11 | }
12 | /*viz_options {"stdin":"13 3.4 mytoken chars rest of line\nanother line"} */
--------------------------------------------------------------------------------
/example-code/Strings.java:
--------------------------------------------------------------------------------
1 | public class Strings {
2 | public static void main(String[] args) {
3 | String a = "Hello, world!";
4 | String b = "Hello, world!!".substring(0, 13);
5 | String c = "Hello, ";
6 | c += "world!";
7 | String d = "Hello, w"+"orld!"; // constant expr, interned
8 | String e = a.substring(0, 13);
9 | System.out.println((a == b) + " " + a.equals(b));
10 | System.out.println((a == c) + " " + a.equals(c));
11 | System.out.println((a == d) + " " + a.equals(d));
12 | System.out.println((a == e) + " " + a.equals(e));
13 | }
14 | }
15 | /*viz_options {"showStringsAsObjects":true}*/
--------------------------------------------------------------------------------
/example-code/SymbolTable.java:
--------------------------------------------------------------------------------
1 | public class SymbolTable {
2 | public static void main(String[] args) {
3 | ST st = new ST<>();
4 | st.put("key1", "value1");
5 | st.put("key2", "value2");
6 | st.put("key3", "value3");
7 | st.put("key1", "different value");
8 | st.delete("key2");
9 | for (String s : st.keys())
10 | StdOut.println(s + " " + st.get(s));
11 | }
12 | }
--------------------------------------------------------------------------------
/example-code/Synthetic.java:
--------------------------------------------------------------------------------
1 | public class Synthetic {
2 |
3 | class Inner {
4 | // contains auto-generated (synthetic)
5 | // field "this$0" of type Synthetic
6 | }
7 |
8 | public static void main(String[] args) {
9 | Synthetic a = new Synthetic();
10 | Synthetic b = new Synthetic();
11 | Inner c = a.new Inner();
12 | Inner d = b.new Inner();
13 | // end of first
14 |
15 | final String[] magic = {"7", "8"};
16 | // anonymous class
17 | Object e = new Object(){
18 | public String toString() {
19 | return magic[1];
20 | }
21 | };
22 | // it has a synthetic variable val$magic
23 | System.out.println(e.toString());
24 |
25 | class Local {
26 | void foo() {System.out.println(magic.length);}
27 | }
28 | Local x = new Local();
29 | x.foo();
30 | }
31 | }
32 | /*viz_options {"showAllFields":true}*/
--------------------------------------------------------------------------------
/example-code/ToString.java:
--------------------------------------------------------------------------------
1 | public class ToString {
2 | int x;
3 |
4 | public String toString() {
5 | return "Instance with x = " + x;
6 | }
7 |
8 | public static void main(String[] args) {
9 | ToString ts = new ToString();
10 | ts.x = 5;
11 | System.out.println(ts);
12 | }
13 | }
--------------------------------------------------------------------------------
/example-code/TwoClasses.java:
--------------------------------------------------------------------------------
1 | public class TwoClasses {
2 | String message = "Can you put two classes in one file?";
3 | void proclaim() {
4 | System.out.println(message);
5 | }
6 | public static void main(String[] args) {
7 | new TwoClasses().proclaim();
8 | new AnotherClass().proclaim();
9 | }
10 | }
11 | class AnotherClass extends TwoClasses{
12 | {message = "Yup";} // instance initializer
13 | }
14 |
--------------------------------------------------------------------------------
/example-code/Variables.java:
--------------------------------------------------------------------------------
1 | public class Variables {
2 | public static void main(String[] args) {
3 | String me = "me";
4 | String you = "you";
5 | String tmp = me;
6 | me = you;
7 | you = tmp;
8 |
9 | int x = 5;
10 | int y = 10;
11 | int t = x;
12 | x = y;
13 | y = t;
14 | }
15 | }
--------------------------------------------------------------------------------
/iframe-embed.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Online Python Tutor - iframe embed page
6 |
7 |
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/img/README:
--------------------------------------------------------------------------------
1 | Icon based on
2 | * Coffee icon: http://thenounproject.com/noun/coffee/#icon-No4115
3 | by Jacob Halton http://thenounproject.com/jacob
4 | and
5 | * Glasses icon: http://thenounproject.com/noun/glasses/#icon-No15009
6 | by Francesco Terzini http://thenounproject.com/fterzini
7 |
--------------------------------------------------------------------------------
/img/jv128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/img/jv128.png
--------------------------------------------------------------------------------
/img/jv256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/img/jv256.png
--------------------------------------------------------------------------------
/img/jv32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/img/jv32.png
--------------------------------------------------------------------------------
/img/jv64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/daveagp/java_visualize/705b1d8c44d6f61a64321e02f71930922ba0369a/img/jv64.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
44 |
45 |
46 | Java Visualizer
47 |
48 |
49 |
50 |
51 |
52 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
87 |
88 |
339 |
340 |
341 |
342 |
343 |
344 |
411 |
412 |
413 |
414 |
415 |
--------------------------------------------------------------------------------
/java_safe_ram_maketrace.php:
--------------------------------------------------------------------------------
1 | config_get("java_jail-abspath"),
54 |
55 | // you may choose to tweak these important performance parameters
56 | "clock" => config_get("safeexec_wallclock_s", 15),
57 | "cpu" => config_get("safeexec_cpu_s", 10),
58 | "mem" => config_get("safeexec_mem_k", 8000000),
59 | // use up to 8000000k ~ 8g of memory (YMMV)
60 | // counting both VMs and all overhead
61 | // see java_jail/cp/traceprinter/MEMORY-NOTES
62 |
63 | // on almost all machines you should not need to edit anything below in this file
64 |
65 | "exec_dir" => "/", // execute in root of chroot
66 | "env_vars" => "''", // no env vars
67 | "nproc" => "200", // max 200 processes
68 | "nfile" => "200", // up to 200 file handles.
69 | // depends on number of files you are including!
70 |
71 | "share_newnet" => "", // don't unshare network: 2 VMs talk over port
72 | );
73 |
74 | // allow arbitrary overrides
75 | foreach (config_get("safeexec_args", array()) as $k=>$v)
76 | $safeexec_args[$k] = $v;
77 |
78 | // allow wholesale replacement
79 | $safeexec_args = config_get("safeexec_args_override", $safeexec_args);
80 |
81 | // the next two definitions assume things are set up like
82 | // https://github.com/daveagp/java_jail
83 | $java_in_jail = config_get("java_in_jail", "/java/bin/java");
84 | $java_args = array(
85 | "Xmx" => "512M", // 128 mb per VM
86 | "cp" => '/cp/:/cp/javax.json-1.0.jar:/java/lib/tools.jar:/cp/visualizer-stdlib'
87 | );
88 |
89 | // allow arbitrary overrides
90 | foreach (config_get("java_args", array()) as $k=>$v)
91 | $java_args[$k] = $v;
92 |
93 | // allow wholesale replacement
94 | $java_args = config_get("java_args_override", $java_args);
95 |
96 | // safeexec uses --exec, sandbox uses nothing
97 | $safeexec_exec_signal = config_get("safeexec_exec_signal", "--exec");
98 |
99 | // now, build the command:
100 | // safeexec --arg1 val1 ... --exec java_in_jail -arg1 val1 ... traceprinter.InMemory
101 | $jv_cmd = $safeexec;
102 | foreach ($safeexec_args as $a=>$v) $jv_cmd .= " --$a $v ";
103 | $jv_cmd .= " $safeexec_exec_signal $java_in_jail";
104 | // -X commands don't use a space
105 | foreach ($java_args as $a=>$v) $jv_cmd .= " " . (substr($a, 0, 1)=='X' ? "-$a$v" : "-$a $v") . " ";
106 | $jv_cmd .= "traceprinter.InMemory";
107 |
108 | // necessary for sandbox at princeton
109 | $newdir = config_get("chdir_before_call", ".");
110 | chdir($newdir);
111 |
112 | // echo $jv_cmd; // for debugging
113 |
114 | // report an error which caused the code not to run
115 | function visError($msg, $row, $col, $code, $se_stdout = null) {
116 | if (!is_int($col))
117 | $col = 0;
118 | if (!is_int($row))
119 | $row = -1;
120 | return '{"trace":[{"line": '.$row.', "event": "uncaught_exception", '
121 | .'"offset": '.$col.', "exception_msg": '.json_encode($msg).'}],'
122 | .'"code":'.json_encode($code) .
123 | ($se_stdout === null ? '' : (',"se_stdout":'.json_encode($se_stdout)))
124 | .'}';
125 | }
126 |
127 | // do logging if enabled
128 | function logit($user_code, $internal_error) {
129 |
130 | if (config_get("db_host", "") != ""
131 | && config_get("db_user", "") != ""
132 | && config_get("db_database", "") != ""
133 | && config_get("db_password", "") != "")
134 |
135 | /*
136 | At the moment, it's pretty crappy and just logs requests to a
137 | table 'jv_history' that should have this structure
138 |
139 | CREATE TABLE IF NOT EXISTS `jv_history` (
140 | `id` int(11) NOT NULL AUTO_INCREMENT,
141 | `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
142 | `user_code` varchar(8000) COLLATE utf8_unicode_ci NOT NULL,
143 | `internal_error` tinyint(1) NOT NULL,
144 | PRIMARY KEY (`id`)
145 | )
146 |
147 | In the future, it could make sense to cache anything that is not randomized.
148 | */
149 | {
150 | $con = mysqli_connect(config_get("db_host"), config_get("db_user"),
151 | config_get("db_password"), config_get("db_database"));
152 | $stmt = $con->prepare("INSERT INTO jv_history (user_code, internal_error) VALUES (?, " . ($internal_error?1:0).")");
153 | $stmt->bind_param("s", $user_code);
154 | $stmt->execute();
155 | $stmt->close();
156 | }
157 | }
158 |
159 |
160 | // the main method
161 | function maketrace() {
162 | if (!array_key_exists('data', $_REQUEST))
163 | return visError("Error: http mangling? Could not find data variable.", 0, 0, "");
164 |
165 | $data = $_REQUEST['data'];
166 |
167 | if (strlen($data) > config_get("max_request_size_bytes", 10000))
168 | return visError("Too much code!");
169 |
170 | $data = json_decode($data, true); // get assoc. arrays, not objects
171 |
172 | $user_code = $data['user_script'];
173 |
174 | $options = $data['options'];
175 | // sanitize options
176 | foreach ($options as $k => $v) {
177 | if ($k == "showStringsAsValues" || $k == "showAllFields") {
178 | $options[$k] = $options[$k] ? true : false;
179 | }
180 | else unset($options[$k]);
181 | }
182 |
183 | $args = $data['args'];
184 | if (!is_array($args))
185 | return visError("args is not an array");
186 | if (count($args)>0 && array_keys($args) !== range(0, count($args) - 1))
187 | return visError("wrong args format");
188 | for ($i=0; $i array("pipe", "r"),
198 | 1 => array("pipe", "w"),// stdout
199 | 2 => array("pipe", "w"),// stderr
200 | );
201 |
202 | $output = array();
203 | $return = -1;
204 |
205 | global $jv_cmd;
206 | // use the command
207 | $process = proc_open($jv_cmd, $descriptorspec, $pipes); //pwd, env not needed
208 |
209 | if (!is_resource($process)) return FALSE;
210 |
211 | global $visualizer_args;
212 | if (count($visualizer_args)==0) $visualizer_args = null; // b/c array() is not associative in php!
213 | $data_to_send = json_encode(array("usercode"=>$user_code,
214 | "options"=>$options,
215 | "args"=>$args,
216 | "stdin"=>$stdin,
217 | "visualizer_args"=>$visualizer_args));
218 |
219 | fwrite($pipes[0], $data_to_send);
220 | fclose($pipes[0]);
221 |
222 | $se_stdout = stream_get_contents($pipes[1]);
223 | $se_stderr = stream_get_contents($pipes[2]);
224 |
225 | fclose($pipes[1]);
226 | fclose($pipes[2]);
227 |
228 | $safeexec_retval = proc_close($process);
229 |
230 | if ($safeexec_retval === 0 && $se_stdout != "") { //executed okay
231 | logit($user_code, false);
232 | return $se_stdout;
233 | }
234 |
235 | // there was an error
236 | logit($user_code, true);
237 |
238 | if ($safeexec_retval === 0)
239 | return visError("Internal error: safeexec returned 0, but an empty string.\nsafeexec stderr:\n" . $se_stderr, 0, 0, $user_code);
240 |
241 | //this will gum up the javascript, but is convenient to see with browser debugging tools
242 | return visError("Safeexec did not succeed:\n" . $se_stderr, 0, 0, $user_code, $se_stdout);
243 | }
244 |
245 | header("Content-type: text/plain; charset=utf-8");
246 | echo maketrace();
247 |
248 | // end of file.
249 |
--------------------------------------------------------------------------------
/jv-config.example.json:
--------------------------------------------------------------------------------
1 | {"remark1" : "edit the 2 paths below to run anything",
2 |
3 | "safeexec-executable-abspath": "/your/path/to/safeexec/safeexec",
4 | "java_jail-abspath": "/your/path/to/java_jail/",
5 |
6 | "remark2" : [
7 | "optinally, edit these to log the submissions",
8 | "see java_safe_ram_maketrace.php for db format",
9 | "WARNING: check that the url with the passwords,",
10 | "http://url-referencing-java_visualize/config.json",
11 | "can NOT be accessed in the browser.",
12 | ".htaccess tries to hide it, but YMMV!!!",
13 |
14 | "also note that .gitignore ignores config.json",
15 | "because of this security information.",
16 | "back it up using an alternative method if desired."
17 | ],
18 |
19 | "db_host": "",
20 | "db_user": "",
21 | "db_database": "",
22 | "db_password": "",
23 |
24 | "remark3" : "optionally, edit these performance parameters",
25 |
26 | "ajax_timeout_millis": 30000,
27 |
28 | "safeexec_wallclock_s": 15,
29 | "safeexec_cpu_s": 10,
30 | "safeexec_mem_k": 8000000,
31 |
32 | "visualizer_args": {
33 | "MAX_STEPS": 512,
34 | "MAX_STACK_SIZE": 16,
35 | "MAX_WALLTIME_SECONDS": 5,
36 | "remark": "time above starts before compiling"
37 | },
38 |
39 | "max_request_size_bytes" : 10000,
40 |
41 | "remark4": "below is the amount of memory for _each_ of the 2 VMs",
42 | "java_args" : {
43 | "Xmx" : "512M"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/jv-frontend.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | This file, jv-frontend.js, is based on
4 | opt-frontend.js from the Online Python Tutor.
5 | Changes made by David Pritchard (daveagp@gmail.com);
6 | see README for more details.
7 |
8 | Summary of changes made:
9 | - uses Java, not Python
10 | - uses CodeMirror latest version
11 | - lazier approach for loading examples
12 |
13 | ==== Header from opt-frontend.js ====
14 |
15 | Online Python Tutor
16 | https://github.com/pgbovine/OnlinePythonTutor/
17 |
18 | Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net)
19 |
20 | Permission is hereby granted, free of charge, to any person obtaining a
21 | copy of this software and associated documentation files (the
22 | "Software"), to deal in the Software without restriction, including
23 | without limitation the rights to use, copy, modify, merge, publish,
24 | distribute, sublicense, and/or sell copies of the Software, and to
25 | permit persons to whom the Software is furnished to do so, subject to
26 | the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included
29 | in all copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
32 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
34 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
35 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
36 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
37 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 |
39 | */
40 |
41 |
42 | // Pre-reqs: pytutor.js and jquery.ba-bbq.min.js should be imported BEFORE this file
43 |
44 |
45 | // backend scripts to execute (Python 2 and 3 variants, if available)
46 | //var python2_backend_script = 'web_exec_py2.py';
47 | //var python3_backend_script = 'web_exec_py3.py';
48 |
49 | // uncomment below if you're running on Google App Engine using the built-in app.yaml
50 | var python2_backend_script = 'exec';
51 | var python3_backend_script = null;
52 |
53 | var java_iframe_url = './iframe-embed.html';
54 | var java_backend_script = './java_safe_ram_maketrace.php';
55 |
56 | var appMode = 'edit'; // 'edit', 'display', or 'display_no_frills'
57 |
58 | var preseededCode = null; // if you passed in a 'code=' in the URL, then set this var
59 | var preseededCurInstr = null; // if you passed in a 'curInstr=' in the URL, then set this var
60 |
61 | var rawInputLst = []; // a list of strings inputted by the user in response to raw_input or mouse_input events
62 |
63 | var myVisualizer = null; // singleton ExecutionVisualizer instance
64 |
65 | // set keyboard bindings
66 | $(document).keydown(function(k) {
67 | //if (!keyStuckDown) {
68 | if (k.keyCode == 37 && myVisualizer != null) { // left arrow
69 | if (myVisualizer.stepBack()) {
70 | k.preventDefault(); // don't horizontally scroll the display
71 | keyStuckDown = true;
72 | }
73 | }
74 | else if (k.keyCode == 39 && myVisualizer != null) { // right arrow
75 | if (myVisualizer.stepForward()) {
76 | k.preventDefault(); // don't horizontally scroll the display
77 | keyStuckDown = true;
78 | }
79 | }
80 | //}
81 | });
82 |
83 | $(document).keyup(function(k) {
84 | keyStuckDown = false;
85 | });
86 |
87 |
88 | var keyStuckDown = false;
89 |
90 | function enterEditMode() {
91 | $.bbq.pushState({ mode: 'edit' }, 2 /* completely override other hash strings to keep URL clean */);
92 | }
93 |
94 | function enterDisplayNoFrillsMode() {
95 | $.bbq.pushState({ mode: 'display_no_frills' }, 2 /* completely override other hash strings to keep URL clean */);
96 | }
97 |
98 | var pyInputCodeMirror; // CodeMirror object that contains the input text
99 |
100 | function setCodeMirrorVal(dat) {
101 | if (dat.indexOf("/*viz_options")>-1) {
102 | var viz_options = dat.substring(dat.indexOf("/*viz_options")+13);
103 | dat = dat.substring(0, dat.indexOf("/*viz_options"));
104 | viz_options = viz_options.replace(/\s*(\*\/)?\s*$/, ""); // remove trailing spaces, */
105 | viz_options = JSON.parse(viz_options);
106 | setOptions(function(key){ return viz_options[key] });
107 | }
108 | else {
109 | setOptions(function(key){ return undefined;});
110 | }
111 | pyInputCodeMirror.setValue(dat.rtrim());
112 | $('#urlOutput,#embedCodeOutput').val('');
113 |
114 | // also scroll to top to make the UI more usable on smaller monitors
115 | $(document).scrollTop(0);
116 | }
117 |
118 | function getUserArgs() {
119 | return $.map($('#argslist .arg input'), function(e){return e.value;});
120 | }
121 |
122 | function getUserStdin() {
123 | return window.stdinarea.value;
124 | }
125 |
126 | $(document).ready(function() {
127 |
128 | $("#embedLinkDiv").hide();
129 |
130 | pyInputCodeMirror = CodeMirror(document.getElementById('codeInputPane'), {
131 | mode: 'text/x-java',
132 | lineNumbers: true,
133 | matchBrackets: true,
134 | tabSize: 3,
135 | indentUnit: 3,
136 | extraKeys: {
137 | Tab: function(cm) {
138 | var lo = cm.getCursor("start").line;
139 | var hi = cm.getCursor("end").line;
140 | for (var i = lo; i <= hi; i++)
141 | cm.indentLine(i, "smart");
142 | cm.setCursor(cm.getCursor("end"));
143 | return true;
144 | },
145 | F5 : function() {return false;}
146 | }
147 | });
148 |
149 | // setCodeMirrorVal(
150 | // "public class ClassNameHere {\n" +
151 | // " public static void main(String[] args) {\n \n }\n}");
152 |
153 | pyInputCodeMirror.setSize(null, 'auto');
154 |
155 |
156 |
157 | // be friendly to the browser's forward and back buttons
158 | // thanks to http://benalman.com/projects/jquery-bbq-plugin/
159 | $(window).bind("hashchange", function(e) {
160 | appMode = $.bbq.getState('mode'); // assign this to the GLOBAL appMode
161 |
162 | if (appMode === undefined || appMode == 'edit') {
163 | $("#pyInputPane").show();
164 | $("#pyOutputPane").hide();
165 | $("#embedLinkDiv").hide();
166 |
167 | // destroy all annotation bubbles (NB: kludgy)
168 | if (myVisualizer) {
169 | myVisualizer.destroyAllAnnotationBubbles();
170 | }
171 | }
172 | else if (appMode == 'display') {
173 | $("#pyInputPane").hide();
174 | $("#pyOutputPane").show();
175 |
176 | $("#embedLinkDiv").show();
177 |
178 | $('#executeBtn').html("Visualize execution");
179 | $('#executeBtn').attr('disabled', false);
180 |
181 |
182 | // do this AFTER making #pyOutputPane visible, or else
183 | // jsPlumb connectors won't render properly
184 | myVisualizer.updateOutput();
185 |
186 | // customize edit button click functionality AFTER rendering (NB: awkward!)
187 | $('#pyOutputPane #editCodeLinkDiv').show();
188 | $('#pyOutputPane #editBtn').click(function() {
189 | $("#iframeURL-div").hide();
190 | enterEditMode();
191 | });
192 | }
193 | else if (appMode == 'display_no_frills') {
194 | $("#pyInputPane").hide();
195 | $("#pyOutputPane").show();
196 | $("#embedLinkDiv").show();
197 | }
198 | else {
199 | assert(false);
200 | }
201 |
202 | $('#urlOutput,#embedCodeOutput').val(''); // clear to avoid stale values
203 | });
204 |
205 |
206 | function executeCode(forceStartingInstr) {
207 | var backend_script = java_backend_script;
208 | /* if ($('#pythonVersionSelector').val() == '2') {
209 | backend_script = python2_backend_script;
210 | }
211 | else if ($('#pythonVersionSelector').val() == '3') {
212 | backend_script = python3_backend_script;
213 | }
214 |
215 | if (!backend_script) {
216 | alert('Error: This server is not configured to run Python ' + $('#pythonVersionSelector').val());
217 | return;
218 | }*/
219 |
220 | $('#executeBtn').html("Please wait ... processing your code");
221 | $('#executeBtn').attr('disabled', true);
222 | $("#pyOutputPane").hide();
223 | $("#embedLinkDiv").hide();
224 |
225 | var java_backend_options = {};
226 | java_backend_options.showStringsAsValues = !$('#showStringsAsObjects').is(':checked');
227 | java_backend_options.showAllFields = $('#showAllFields').is(':checked');
228 |
229 | var package = {
230 | user_script : pyInputCodeMirror.getValue(),
231 | options: java_backend_options,
232 | args: getUserArgs(),
233 | stdin: getUserStdin()
234 | };
235 |
236 | $("#iframeURL-div").show();
237 | // USC Wordpress approach from Spring '15
238 | // $("#iframeURL").html('[visualize]'+encodeURIComponent(JSON.stringify(package))+'[/visualize]');
239 | // but this is simpler assuming you are editing raw html:
240 | var a = document.createElement('a');
241 | // absolutize iframe-embed.html
242 | a.href = java_iframe_url;
243 | $('#iframeURL').val('');
248 |
249 |
250 | $.ajax({url: backend_script,
251 | data: {data : JSON.stringify(package)},
252 | /*,
253 | raw_input_json: rawInputLst.length > 0 ? JSON.stringify(rawInputLst) : '',
254 | options_json: JSON.stringify(options)*/
255 | dataType: "json",
256 | timeout: pytutor_ajax_timeout_millis, //ms
257 | error: ajaxErrorHandler,
258 | success: function(dataFromBackend) {
259 | console.log(["Data from backend:", dataFromBackend]);
260 |
261 | var trace = dataFromBackend.trace;
262 |
263 | // don't enter visualize mode if there are killer errors:
264 | if (!trace ||
265 | (trace.length == 0) ||
266 | (trace[trace.length - 1].event == 'uncaught_exception')) {
267 |
268 | if (trace.length == 1) {
269 | var errorLineNo = trace[0].line - 1; /* CodeMirror lines are zero-indexed */
270 | if (errorLineNo !== undefined) {
271 | // highlight the faulting line in pyInputCodeMirror
272 | pyInputCodeMirror.focus();
273 | pyInputCodeMirror.setCursor(errorLineNo, 0);
274 | var marked = pyInputCodeMirror.addLineClass(errorLineNo, null, 'errorLine');
275 | //console.log(marked);
276 | var hook = function(marked) { return function() {
277 | pyInputCodeMirror.removeLineClass(marked, null, 'errorLine'); // reset line back to normal
278 | pyInputCodeMirror.off('change', hook); // cancel
279 | }} (marked);
280 | pyInputCodeMirror.on('change', hook);
281 | }
282 |
283 | alert(trace[0].exception_msg);
284 | }
285 | else if (trace[trace.length - 1].exception_msg) {
286 | alert(trace[trace.length - 1].exception_msg);
287 | }
288 | else {
289 | alert("Whoa, unknown error! Reload to try again, or report a bug to daveagp@gmail.com\n\n(Click the 'Generate URL' button to include a unique URL in your email bug report.)");
290 | }
291 |
292 | $('#executeBtn').html("Visualize execution");
293 | $('#executeBtn').attr('disabled', false);
294 | }
295 | else {
296 | var startingInstruction = 0;
297 |
298 | // only do this at most ONCE, and then clear out preseededCurInstr
299 | if (preseededCurInstr && preseededCurInstr < trace.length) { // NOP anyways if preseededCurInstr is 0
300 | startingInstruction = preseededCurInstr;
301 | preseededCurInstr = null;
302 | }
303 |
304 | // forceStartingInstr overrides everything else
305 | if (forceStartingInstr !== undefined) {
306 | startingInstruction = forceStartingInstr;
307 | }
308 |
309 | var frontend_options =
310 | {startingInstruction: startingInstruction,
311 | updateOutputCallback:
312 | function() {
313 | $('#urlOutput,#embedCodeOutput').val('');
314 | },
315 | disableHeapNesting: $('#disableNesting').is(':checked'),
316 | drawParentPointers: false,
317 | textualMemoryLabels: false,
318 | showOnlyOutputs: false,
319 | executeCodeWithRawInputFunc: executeCodeWithRawInput,
320 | //allowEditAnnotations: true,
321 | resizeLeftRight: true,
322 | highlightLines: true,
323 | stdin: getUserStdin(),
324 | };
325 |
326 | myVisualizer = new ExecutionVisualizer('pyOutputPane',
327 | dataFromBackend,
328 | frontend_options);
329 |
330 | // also scroll to top to make the UI more usable on smaller monitors
331 | $(document).scrollTop(0);
332 |
333 | $.bbq.pushState({ mode: 'display' }, 2 /* completely override other hash strings to keep URL clean */);
334 |
335 | }
336 | }});
337 | }
338 |
339 | function executeCodeFromScratch() {
340 | // reset these globals
341 | rawInputLst = [];
342 |
343 | executeCode();
344 | }
345 |
346 | function executeCodeWithRawInput(rawInputStr, curInstr) {
347 | enterDisplayNoFrillsMode();
348 |
349 | // set some globals
350 | rawInputLst.push(rawInputStr);
351 |
352 | executeCode(curInstr);
353 | }
354 |
355 | $("#executeBtn").attr('disabled', false);
356 | $("#executeBtn").click(executeCodeFromScratch);
357 |
358 |
359 | // canned examples
360 |
361 | var examplesDir = "./example-code/";
362 |
363 | var exampleCallback = function(url) {
364 | return function() {$.get(url, setCodeMirrorVal); return false;};
365 | }
366 |
367 | String.prototype.endsWith = function(suffix) {
368 | return this.indexOf(suffix, this.length - suffix.length) !== -1;
369 | };
370 |
371 | // populate examples
372 | var done = {};
373 | for (var i=0; i");
375 | $("#examplesHolder").append(topics[i][0]);
376 | $("#examplesHolder").append(" examples");
377 | for (var j=0; j" + filename + "");
381 | newItem.click(exampleCallback(examplesDir + filename + ".java"));
382 | $("#examplesHolder").append(newItem);
383 | done[filename] = true;
384 | }
385 | }
386 |
387 | var populate_misc = function(index_page) {
388 | $("#examplesHolder").append(" misc examples");
389 | var first = true;
390 | $(index_page).find("td > a").each(function() {
391 | var filename = $(this).attr("href");
392 | if (filename.endsWith(".java")) { // an example
393 | filename = filename.substring(0, filename.length-5);
394 | if (done[filename]) return;
395 | var newItem = $("" + filename + " ");
396 | newItem.click(exampleCallback(examplesDir + filename + ".java"));
397 | $("#examplesHolder").append(" | ");
398 | $("#examplesHolder").append(newItem);
399 | }
400 | });
401 | };
402 |
403 | // fetch uncategorized
404 | $.ajax({
405 | url: "./example-code/",
406 | success: populate_misc,
407 | error: function() {console.log("warning: couldn't read examples directory index");}
408 | });
409 |
410 |
411 | // handle hash parameters passed in when loading the page
412 | preseededCode = $.bbq.getState('code');
413 | if (preseededCode) {
414 | setCodeMirrorVal(preseededCode);
415 | }
416 | else {
417 | // select a canned example on start-up:
418 | exampleCallback(examplesDir+"(Default).java")();
419 | }
420 |
421 | var loadExample = $.bbq.getState('sampleFile');
422 | if (loadExample) {
423 | //console.log(loadExample);
424 | if (loadExample.match(/[a-zA-Z]+/))
425 | exampleCallback(examplesDir+loadExample+".java")();
426 | }
427 |
428 | // args, and only args, is parsed specially
429 | setOptions(function(key){
430 | var value = $.bbq.getState(key);
431 | if (key=='args' && value != undefined) value = JSON.parse(value);
432 | return value;
433 | });
434 |
435 | // log a generic AJAX error handler
436 | var ajaxErrorHandler = function(jqXHR, textStatus, errorThrown) {
437 | var errinfo = "textStatus: " + textStatus + "\nerrorThrown: " + errorThrown + "\nServer reply: " + jqXHR.responseText;
438 |
439 | alert("Server error. Report a bug to daveagp@gmail.com (click 'Generate URL' and include it). Debug info (also copied to console):\n" + errinfo);
440 |
441 | console.log(errinfo);
442 |
443 | $('#executeBtn').html("Visualize execution");
444 | $('#executeBtn').attr('disabled', false);
445 | };
446 |
447 | // $(document).ajaxError(ajaxErrorHandler);
448 |
449 |
450 | // redraw connector arrows on window resize
451 | $(window).resize(function() {
452 | if (appMode == 'display') {
453 | myVisualizer.redrawConnectors();
454 | }
455 | });
456 |
457 | $('#genUrlBtn').bind('click', function() {
458 | var myArgs = {code: pyInputCodeMirror.getValue(),
459 | mode: appMode
460 | /*
461 | , cumulative: $('#cumulativeModeSelector').val(),
462 | heapPrimitives: $('#heapPrimitivesSelector').val(),
463 | drawParentPointers: $('#drawParentPointerSelector').val(),
464 | textReferences: $('#textualMemoryLabelsSelector').val(),
465 | showOnlyOutputs: $('#showOnlyOutputsSelector').val(),
466 | py: $('#pythonVersionSelector').val()
467 | */};
468 |
469 | // Set these to a value which coerces to true
470 | if ($('#showStringsAsObjects').is(':checked'))
471 | myArgs.showStringsAsObjects=1;
472 | if ($('#showAllFields').is(':checked'))
473 | myArgs.showAllFields=1;
474 | if ($('#disableNesting').is(':checked'))
475 | myArgs.disableNesting=1;
476 | if ($('#verticalLists').is(':checked'))
477 | myArgs.verticalLists=1;
478 |
479 | if (getUserArgs().length > 0)
480 | myArgs.args = JSON.stringify(getUserArgs());
481 |
482 | if (getUserStdin().length > 0)
483 | myArgs.stdin = getUserStdin();
484 |
485 | if (appMode == 'display') {
486 | myArgs.curInstr = myVisualizer.curInstr;
487 | }
488 |
489 | var urlStr = $.param.fragment(window.location.href, myArgs, 2 /* clobber all */);
490 | $('#urlOutput').val(urlStr);
491 | });
492 |
493 |
494 | $('#genEmbedBtn').bind('click', function() {
495 | assert(appMode == 'display');
496 | var myArgs = {code: pyInputCodeMirror.getValue(),
497 | cumulative: $('#cumulativeModeSelector').val(),
498 | heapPrimitives: $('#heapPrimitivesSelector').val(),
499 | drawParentPointers: $('#drawParentPointerSelector').val(),
500 | textReferences: $('#textualMemoryLabelsSelector').val(),
501 | showOnlyOutputs: $('#showOnlyOutputsSelector').val(),
502 | py: $('#pythonVersionSelector').val(),
503 | curInstr: myVisualizer.curInstr,
504 | };
505 |
506 | var embedUrlStr = $.param.fragment('http://pythontutor.com/iframe-embed.html', myArgs, 2 /* clobber all */);
507 | var iframeStr = '';
508 | $('#embedCodeOutput').val(iframeStr);
509 | });
510 | });
511 |
512 | var setOptions = function(lookup_function) {
513 | var userArgs = lookup_function('args');
514 | if (userArgs) {
515 | if (!userArgs instanceof Array)
516 | userArgs = JSON.parse(userArgs);
517 | for (var i=0; inull');
26 | else if (typ == "number")
27 | d3DomElement.append('' + obj + ' ');
28 | else if (typ == "boolean") {
29 | if (obj)
30 | d3DomElement.append('true ');
31 | else
32 | d3DomElement.append('false ');
33 | }
34 | else if (obj instanceof Array && obj[0] == "VOID") {
35 | d3DomElement.append('void ');
36 | }
37 | else if (obj instanceof Array && obj[0] == "NUMBER-LITERAL") {
38 | // actually transmitted as a string
39 | d3DomElement.append('' + obj[1] + ' ');
40 | }
41 | else if (obj instanceof Array && obj[0] == "CHAR-LITERAL") {
42 | var asc = obj[1].charCodeAt(0);
43 | var ch = obj[1];
44 |
45 | // default
46 | var show = asc.toString(16);
47 | while (show.length < 4) show = "0" + show;
48 | show = "\\u" + show;
49 |
50 | if (ch == "\n") show = "\\n";
51 | else if (ch == "\r") show = "\\r";
52 | else if (ch == "\t") show = "\\t";
53 | else if (ch == "\b") show = "\\b";
54 | else if (ch == "\f") show = "\\f";
55 | else if (ch == "\'") show = "\\\'";
56 | else if (ch == "\"") show = "\\\"";
57 | else if (ch == "\\") show = "\\\\";
58 | else if (asc >= 32) show = ch;
59 |
60 | // stringObj to make monospace
61 | d3DomElement.append('\'' + show + '\' ');
62 | }
63 | else
64 | return [false]; // we didn't handle it
65 | return [true]; // we handled it
66 | });
67 |
68 | add_pytutor_hook(
69 | "isPrimitiveType",
70 | function(args) {
71 | var obj = args.obj;
72 | if ((obj instanceof Array && obj[0] == "VOID")
73 | || (obj instanceof Array && obj[0] == "NUMBER-LITERAL")
74 | || (obj instanceof Array && obj[0] == "CHAR-LITERAL")
75 | || (obj instanceof Array && obj[0] == "ELIDE"))
76 | return [true, true]; // we handled it, it's primitive
77 | return [false]; // didn't handle it
78 | });
79 |
80 | add_pytutor_hook(
81 | "end_updateOutput",
82 | function(args) {
83 | // find the colophon if it exists, and change it to something that makes more sense
84 | $('#codeDisplayDiv div a').each(function(i, elt) {
85 | if (elt.parentElement.innerHTML.indexOf('Code visualized') > -1) {
86 | if (faking_cpp) {
87 | elt.parentElement.parentElement.removeChild(elt.parentElement);
88 | }
89 | else {
90 | elt.setAttribute('href', 'http://cscircles.cemc.uwaterloo.ca/java_visualize/');
91 | elt.innerHTML = 'Java Visualizer';
92 | }
93 | }
94 | });
95 |
96 | if (faking_cpp) {
97 | $("#stackHeader").html('Variables');
98 | $("#heapHeader").html('Memory');
99 | }
100 |
101 | var myViz = args.myViz;
102 | var curEntry = myViz.curTrace[myViz.curInstr];
103 | if (myViz.params.stdin && myViz.params.stdin != "") {
104 | var stdinPosition = curEntry.stdinPosition || 0;
105 | var stdinContent =
106 | ''+
107 | escapeHtml(myViz.params.stdin.substr(0, stdinPosition))+
108 | ' '+
109 | escapeHtml(myViz.params.stdin.substr(stdinPosition));
110 | myViz.domRoot.find('#stdinShow').html(stdinContent);
111 | }
112 | return [false];
113 | });
114 |
115 | add_pytutor_hook(
116 | "end_constructor",
117 | function(args) {
118 | var myViz = args.myViz;
119 | if ((myViz.curTrace.length > 0)
120 | && myViz.curTrace[myViz.curTrace.length-1]
121 | && myViz.curTrace[myViz.curTrace.length-1].stdout) {
122 | myViz.hasStdout = true;
123 | myViz.stdoutLines = myViz.curTrace[myViz.curTrace.length-1].stdout.split("\n").length;
124 | }
125 | // if last frame is a step limit
126 | else if ((myViz.curTrace.length > 1)
127 | && myViz.curTrace[myViz.curTrace.length-2]
128 | && myViz.curTrace[myViz.curTrace.length-2].stdout) {
129 | myViz.hasStdout = true;
130 | myViz.stdoutLines = myViz.curTrace[myViz.curTrace.length-2].stdout.split("\n").length;
131 | }
132 | else {
133 | myViz.stdoutLines = -1;
134 | }
135 | if (myViz.hasStdout)
136 | for (var i=0; i' + typeLabelPrefix + 'empty ' + visibleLabel + '');
183 | return [true]; //handled
184 | }
185 |
186 | d3DomElement.append('' + typeLabelPrefix + visibleLabel + '
');
187 | d3DomElement.append('');
188 | var tbl = d3DomElement.children('table');
189 |
190 | if (obj[0] == 'LIST') {
191 | tbl.append(' ');
192 | var headerTr = tbl.find('tr:first');
193 | var contentTr = tbl.find('tr:last');
194 |
195 | // i: actual index in json object; ind: apparent index
196 | for (var i=1, ind=0; i