diff --git a/README b/README index 811c97e..f760cce 100644 --- a/README +++ b/README @@ -43,6 +43,9 @@ and java_jail. (Just those first two entries need to be changed right now.) Now, try the visualizer out! +THE "C++ VISUALIZER" +See cpp_visualizer.txt. + FAQ -- click on "Click for FAQ" on the visualizer page diff --git a/cpp_visualizer.txt b/cpp_visualizer.txt new file mode 100644 index 0000000..311b977 --- /dev/null +++ b/cpp_visualizer.txt @@ -0,0 +1,81 @@ +THE "C++ VISUALIZER" + +This visualizer has been used to help teach a course on C++ by using a dirty +hack: we show the student a version of the code that looks like C++, but +a Java version of the code is actually what is being run and visualized. This +suffices for most of what you would do in an intro course, including +control flow, arrays, recursion, OOP and linked lists. + +Since this is faked, it unfortunately doesn't make sense to allow students +to edit the visualized code or for them to visualize their own code. + +The Java visualizer allows you do this by using the symbol //>< as follows: + {real Java code to visualize} //>< {fake C++ code to show to the student} +For instance, go to http://cscircles.cemc.uwaterloo.ca/java_visualize/ +and type in the following: + +public class C { public static void main(String[] args) { //>< cout << x+y << endl; +}} //><} + +So you're basically writing 2 parallel programs, though lines that are +identical in Java and C++ only need to be typed in once (e.g. "int x = 2;"). + +At the moment, I've only deployed these fake visualizations with the embedded +iframe version of the Python Tutor/Java Visualizer, which sort of makes sense +because in this interface it's not editable, but also because our use case +was embedding in course notes. The notes are here: + http://bits.usc.edu/cs103-s15/schedule/ +E.g., see this lecture's notes: + http://bits.usc.edu/cs103-s15/control/ + +USAGE GUIDE + +You can either do this with your own server, or use a pre-existing one. + +Installing the Java Visualizer (see the README) automatically gives you +the ability to do fake C++ visualizations. + +There is a configuration variable called "faking_cpp" in +pytutor-customizations.js that eases the workflow for creating fake C++ +visualizations and makes some superficial changes to some labels. + +For instance, you can use this mirror where it's enabled by default: + http://bits.usc.edu/java_visualize/ + +You also can override it by setting the http query variable faking_cpp, +so here is another server you can use: + http://cscircles.cemc.uwaterloo.ca/java_visualize/?faking_cpp=true + +Once there, enter your fake visualization. Once you're happy with it, +copy the "Embeddable iframe:" field into whatever html you like. + +The ugly part of the workflow at the moment is editing a previously-created +animation, which at this point requires editing or converting the URL-encoded +version of the code. If you find this a big hassle, feel free to get in +touch, or please send a pull request if you create a easy solution. + +NOTES + +Right now, the backend is agnostic as to whether it's visualizing true +Java or faking C++. It would be better to fix this, e.g. so main returns 0 +and not VOID when we're faking C++. + +To see how this is implemented, search for 'fakify' in the java_jail repo. + +There's nothing special about C++ aside from the semantics and code flow +being similar to Java; you could use this to fake-visualize any +other language depending on how much work you're willing to put into writing +2 parallel versions of the code. + +The Java/C++ embedded visualizer is using a modification of an old version +of the embedded visualizer code. See embed/README for details. It would +be nice to bring it up to date. + +A few educators and students that I have talked to have ideas and partial +implementations of a "real" C++ visualizer, either by piping through gdb, +or by using LLDB's API, or by doing something like valgrind. Please email +me if you have made progress in this direction or if you want to touch +base with others who are interested. diff --git a/embed/README b/embed/README new file mode 100644 index 0000000..5acfa6f --- /dev/null +++ b/embed/README @@ -0,0 +1,17 @@ +Note! This repository is using a crufty old version of the visualizer +for embedding. + +The reason for this is laziness, but specifically because there are +features of the Java Visualizer not yet supported on the main branch and +at pythontutor.com (as of the date of writing), in particular +command-line arguments and standard input. + +As a result, this subdirectory has out-of-date copies from an old +version of the Python Tutor, which were then manually changed to be +Java-friendly. + +For reference, the files in this directry were taken from +https://github.com/cemc/cscircles-wp-content +in the directory pybox/OnlinePythonTutor3-cemc +and then modified. + diff --git a/embed/css/jquery.qtip.css b/embed/css/jquery.qtip.css new file mode 100644 index 0000000..fb7fe24 --- /dev/null +++ b/embed/css/jquery.qtip.css @@ -0,0 +1,573 @@ +/*! qTip2 - Pretty powerful tooltips - v2.0.0 - 2012-09-10 +* http://craigsworks.com/projects/qtip2/ +* Copyright (c) 2012 Craig Michael Thompson; Licensed MIT, GPL */ + +/* Fluid class for determining actual width in IE */ +#qtip-rcontainer{ + position: absolute; + left: -28000px; + top: -28000px; + display: block; + visibility: hidden; +} + + /* Fluid class for determining actual width in IE */ + #qtip-rcontainer .ui-tooltip{ + display: block !important; + visibility: hidden !important; + position: static !important; + float: left !important; + } + +/* Core qTip styles */ +.ui-tooltip, .qtip{ + position: absolute; + left: -28000px; + top: -28000px; + display: none; + + max-width: 280px; + min-width: 50px; + + font-size: 10.5px; + line-height: 12px; +} + + .ui-tooltip-content{ + position: relative; + padding: 5px 9px; + overflow: hidden; + + text-align: left; + word-wrap: break-word; + } + + .ui-tooltip-titlebar{ + position: relative; + min-height: 14px; + padding: 5px 35px 5px 10px; + overflow: hidden; + + border-width: 0 0 1px; + font-weight: bold; + } + + .ui-tooltip-titlebar + .ui-tooltip-content{ border-top-width: 0 !important; } + + /* Default close button class */ + .ui-tooltip-titlebar .ui-state-default{ + position: absolute; + right: 4px; + top: 50%; + margin-top: -9px; + + cursor: pointer; + outline: medium none; + + border-width: 1px; + border-style: solid; + } + + * html .ui-tooltip-titlebar .ui-state-default{ top: 16px; } /* IE fix */ + + .ui-tooltip-titlebar .ui-icon, + .ui-tooltip-icon .ui-icon{ + display: block; + text-indent: -1000em; + direction: ltr; + } + + .ui-tooltip-icon, .ui-tooltip-icon .ui-icon{ + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + text-decoration: none; + } + + .ui-tooltip-icon .ui-icon{ + width: 18px; + height: 14px; + + text-align: center; + text-indent: 0; + font: normal bold 10px/13px Tahoma,sans-serif; + + color: inherit; + background: transparent none no-repeat -100em -100em; + } + + +/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */ +.ui-tooltip-focus{} + +/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */ +.ui-tooltip-hover{} + +/* Default tooltip style */ +.ui-tooltip-default{ + border-width: 1px; + border-style: solid; + border-color: #F1D031; + + background-color: #FFFFA3; + color: #555; +} + + .ui-tooltip-default .ui-tooltip-titlebar{ + background-color: #FFEF93; + } + + .ui-tooltip-default .ui-tooltip-icon{ + border-color: #CCC; + background: #F1F1F1; + color: #777; + } + + .ui-tooltip-default .ui-tooltip-titlebar .ui-state-hover{ + border-color: #AAA; + color: #111; + } + + +/*! Light tooltip style */ +.ui-tooltip-light{ + background-color: white; + border-color: #E2E2E2; + color: #454545; +} + + .ui-tooltip-light .ui-tooltip-titlebar{ + background-color: #f1f1f1; + } + + +/*! Dark tooltip style */ +.ui-tooltip-dark{ + background-color: #505050; + border-color: #303030; + color: #f3f3f3; +} + + .ui-tooltip-dark .ui-tooltip-titlebar{ + background-color: #404040; + } + + .ui-tooltip-dark .ui-tooltip-icon{ + border-color: #444; + } + + .ui-tooltip-dark .ui-tooltip-titlebar .ui-state-hover{ + border-color: #303030; + } + + +/*! Cream tooltip style */ +.ui-tooltip-cream{ + background-color: #FBF7AA; + border-color: #F9E98E; + color: #A27D35; +} + + .ui-tooltip-cream .ui-tooltip-titlebar{ + background-color: #F0DE7D; + } + + .ui-tooltip-cream .ui-state-default .ui-tooltip-icon{ + background-position: -82px 0; + } + + +/*! Red tooltip style */ +.ui-tooltip-red{ + background-color: #F78B83; + border-color: #D95252; + color: #912323; +} + + .ui-tooltip-red .ui-tooltip-titlebar{ + background-color: #F06D65; + } + + .ui-tooltip-red .ui-state-default .ui-tooltip-icon{ + background-position: -102px 0; + } + + .ui-tooltip-red .ui-tooltip-icon{ + border-color: #D95252; + } + + .ui-tooltip-red .ui-tooltip-titlebar .ui-state-hover{ + border-color: #D95252; + } + + +/*! Green tooltip style */ +.ui-tooltip-green{ + background-color: #CAED9E; + border-color: #90D93F; + color: #3F6219; +} + + .ui-tooltip-green .ui-tooltip-titlebar{ + background-color: #B0DE78; + } + + .ui-tooltip-green .ui-state-default .ui-tooltip-icon{ + background-position: -42px 0; + } + + +/*! Blue tooltip style */ +.ui-tooltip-blue{ + background-color: #E5F6FE; + border-color: #ADD9ED; + color: #5E99BD; +} + + .ui-tooltip-blue .ui-tooltip-titlebar{ + background-color: #D0E9F5; + } + + .ui-tooltip-blue .ui-state-default .ui-tooltip-icon{ + background-position: -2px 0; + } + + +/* Add shadows to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ +.ui-tooltip-shadow{ + -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); + box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15); +} + +/* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ +.ui-tooltip-rounded, +.ui-tooltip-tipsy, +.ui-tooltip-bootstrap{ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +/* Youtube tooltip style */ +.ui-tooltip-youtube{ + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + + -webkit-box-shadow: 0 0 3px #333; + -moz-box-shadow: 0 0 3px #333; + box-shadow: 0 0 3px #333; + + color: white; + border-width: 0; + + background: #4A4A4A; + background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,black)); + background-image: -webkit-linear-gradient(top,#4A4A4A 0,black 100%); + background-image: -moz-linear-gradient(top,#4A4A4A 0,black 100%); + background-image: -ms-linear-gradient(top,#4A4A4A 0,black 100%); + background-image: -o-linear-gradient(top,#4A4A4A 0,black 100%); +} + + .ui-tooltip-youtube .ui-tooltip-titlebar{ + background-color: #4A4A4A; + background-color: rgba(0,0,0,0); + } + + .ui-tooltip-youtube .ui-tooltip-content{ + padding: .75em; + font: 12px arial,sans-serif; + + filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000); + -ms-filter: "progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);"; + } + + .ui-tooltip-youtube .ui-tooltip-icon{ + border-color: #222; + } + + .ui-tooltip-youtube .ui-tooltip-titlebar .ui-state-hover{ + border-color: #303030; + } + + +/* jQuery TOOLS Tooltip style */ +.ui-tooltip-jtools{ + background: #232323; + background: rgba(0, 0, 0, 0.7); + background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323)); + background-image: -moz-linear-gradient(top, #717171, #232323); + background-image: -webkit-linear-gradient(top, #717171, #232323); + background-image: -ms-linear-gradient(top, #717171, #232323); + background-image: -o-linear-gradient(top, #717171, #232323); + + border: 2px solid #ddd; + border: 2px solid rgba(241,241,241,1); + + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + + -webkit-box-shadow: 0 0 12px #333; + -moz-box-shadow: 0 0 12px #333; + box-shadow: 0 0 12px #333; +} + + /* IE Specific */ + .ui-tooltip-jtools .ui-tooltip-titlebar{ + background-color: transparent; + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"; + } + .ui-tooltip-jtools .ui-tooltip-content{ + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"; + } + + .ui-tooltip-jtools .ui-tooltip-titlebar, + .ui-tooltip-jtools .ui-tooltip-content{ + background: transparent; + color: white; + border: 0 dashed transparent; + } + + .ui-tooltip-jtools .ui-tooltip-icon{ + border-color: #555; + } + + .ui-tooltip-jtools .ui-tooltip-titlebar .ui-state-hover{ + border-color: #333; + } + + +/* Cluetip style */ +.ui-tooltip-cluetip{ + -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + + background-color: #D9D9C2; + color: #111; + border: 0 dashed transparent; +} + + .ui-tooltip-cluetip .ui-tooltip-titlebar{ + background-color: #87876A; + color: white; + border: 0 dashed transparent; + } + + .ui-tooltip-cluetip .ui-tooltip-icon{ + border-color: #808064; + } + + .ui-tooltip-cluetip .ui-tooltip-titlebar .ui-state-hover{ + border-color: #696952; + color: #696952; + } + + +/* Tipsy style */ +.ui-tooltip-tipsy{ + background: black; + background: rgba(0, 0, 0, .87); + + color: white; + border: 0 solid transparent; + + font-size: 11px; + font-family: 'Lucida Grande', sans-serif; + font-weight: bold; + line-height: 16px; + text-shadow: 0 1px black; +} + + .ui-tooltip-tipsy .ui-tooltip-titlebar{ + padding: 6px 35px 0 10; + background-color: transparent; + } + + .ui-tooltip-tipsy .ui-tooltip-content{ + padding: 6px 10; + } + + .ui-tooltip-tipsy .ui-tooltip-icon{ + border-color: #222; + text-shadow: none; + } + + .ui-tooltip-tipsy .ui-tooltip-titlebar .ui-state-hover{ + border-color: #303030; + } + + +/* Tipped style */ +.ui-tooltip-tipped{ + border: 3px solid #959FA9; + + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + + background-color: #F9F9F9; + color: #454545; + + font-weight: normal; + font-family: serif; +} + + .ui-tooltip-tipped .ui-tooltip-titlebar{ + border-bottom-width: 0; + + color: white; + background: #3A79B8; + background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D)); + background-image: -webkit-linear-gradient(top, #3A79B8, #2E629D); + background-image: -moz-linear-gradient(top, #3A79B8, #2E629D); + background-image: -ms-linear-gradient(top, #3A79B8, #2E629D); + background-image: -o-linear-gradient(top, #3A79B8, #2E629D); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"; + } + + .ui-tooltip-tipped .ui-tooltip-icon{ + border: 2px solid #285589; + background: #285589; + } + + .ui-tooltip-tipped .ui-tooltip-icon .ui-icon{ + background-color: #FBFBFB; + color: #555; + } + + +/** + * Twitter Bootstrap style. + * + * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11. + * Does not work with IE 7. + */ +.ui-tooltip-bootstrap{ + font-size: 13px; + line-height: 18px; + + color: #333333; + background-color: #ffffff; + + + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + + *border-right-width: 2px; + *border-bottom-width: 2px; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + + .ui-tooltip-bootstrap .ui-tooltip-titlebar{ + font-size: 18px; + line-height: 22px; + + border-bottom: 1px solid #ccc; + background-color: transparent; + } + + .ui-tooltip-bootstrap .ui-tooltip-titlebar .ui-state-default{ + right: 9px; top: 49%; + border-style: none; + } + + .ui-tooltip-bootstrap .ui-tooltip-icon{ + background: white; + } + + .ui-tooltip-bootstrap .ui-tooltip-icon .ui-icon{ + width: auto; + height: auto; + float: right; + font-size: 20px; + font-weight: bold; + line-height: 18px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); + } + + .ui-tooltip-bootstrap .ui-tooltip-icon .ui-icon:hover{ + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); + } + + +/* IE9 fix - removes all filters */ +.ui-tooltip:not(.ie9haxors) div.ui-tooltip-content, +.ui-tooltip:not(.ie9haxors) div.ui-tooltip-titlebar{ + filter: none; + -ms-filter: none; +} + + +/* Tips plugin */ +.ui-tooltip .ui-tooltip-tip{ + margin: 0 auto; + overflow: hidden; + z-index: 10; +} + + .ui-tooltip .ui-tooltip-tip, + .ui-tooltip .ui-tooltip-tip .qtip-vml{ + position: absolute; + + line-height: 0.1px !important; + font-size: 0.1px !important; + color: #123456; + + background: transparent; + border: 0 dashed transparent; + } + + .ui-tooltip .ui-tooltip-tip canvas{ top: 0; left: 0; } + + .ui-tooltip .ui-tooltip-tip .qtip-vml{ + behavior: url(#default#VML); + display: inline-block; + visibility: visible; + } +/* Modal plugin */ +#qtip-overlay{ + position: fixed; + left: -10000em; + top: -10000em; +} + + /* Applied to modals with show.modal.blur set to true */ + #qtip-overlay.blurs{ cursor: pointer; } + + /* Change opacity of overlay here */ + #qtip-overlay div{ + position: absolute; + left: 0; top: 0; + width: 100%; height: 100%; + + background-color: black; + + opacity: 0.7; + filter:alpha(opacity=70); + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; + } + diff --git a/embed/css/opt-frontend.css b/embed/css/opt-frontend.css new file mode 100644 index 0000000..1fd537d --- /dev/null +++ b/embed/css/opt-frontend.css @@ -0,0 +1,86 @@ +/* CSS accompanying ../visualize.html */ + +h1 { + font-weight: normal; + font-size: 20pt; + font-family: georgia, serif; + line-height: 1em; /* enforce single spacing so that Georgia works */ + + margin-top: 0px; + margin-bottom: 8px; +} + +h2 { + font-size: 12pt; + font-weight: normal; + font-family: georgia, serif; + line-height: 1.1em; /* enforce single spacing so that Georgia works */ + + margin-top: 2px; + margin-bottom: 20px; +} + + +body { + background-color: white; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 10pt; +} + +a, +a:visited, +a:hover { + color: #3D58A2; +} + +span { + padding: 0px; +} + +table#pyOutputPane { + padding: 10px; +} + +#pyInputPane { + margin-top: 20px; + margin-bottom: 20px; + + max-width: 700px; + /* center align */ + margin-left: auto; + margin-right: auto; +} + +#codeInputPane { + margin-top: 5px; + font-size: 12pt; + border: 1px solid #ddd; +} + +button.smallBtn { + font-size: 10pt; + padding: 3px; +} + +button.bigBtn { + font-size: 13pt; + padding: 6px; + margin-top: 6px; +} + +#footer { + color: #666666; + font-size: 9pt; + border-top: 1px solid #bbbbbb; + padding-top: 5px; + margin-top: 5px; + + max-width: 700px; + /* center align */ + margin-left: auto; + margin-right: auto; +} + + +/* necessary for CodeMirror error line highlighting to work! */ +.CodeMirror .errorLine { background: #ffff3f !important; } diff --git a/embed/css/pytutor.css b/embed/css/pytutor.css new file mode 100644 index 0000000..e518db0 --- /dev/null +++ b/embed/css/pytutor.css @@ -0,0 +1,756 @@ +/* + +Online Python Tutor +https://github.com/pgbovine/OnlinePythonTutor/ + +Copyright (C) 2010-2012 Philip J. Guo (philip@pgbovine.net) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +/* Most recent color scheme redesign on 2012-08-19 */ + +/* To prevent CSS namespace clashes, prefix all rules with: + div.ExecutionVisualizer +*/ + + +/* reset some styles to nullify effects of existing stylesheets + e.g., http://meyerweb.com/eric/tools/css/reset/ +*/ +div.ExecutionVisualizer { + /* none for now */ +} + +div.ExecutionVisualizer table.visualizer { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 10pt; + margin-bottom: 10px; +} + +div.ExecutionVisualizer table.visualizer td.vizLayoutTd { + vertical-align: top; +} + +div.ExecutionVisualizer td#stack_td, +div.ExecutionVisualizer td#heap_td { + vertical-align:top; + font-size: 10pt; /* don't make fonts in the heap so big! */ +} + +div.ExecutionVisualizer #dataViz { + margin-left: 25px; +} + +div.ExecutionVisualizer div#codeDisplayDiv { + /* set this as default unless user specifies a custom size */ + /*width: 550px;*/ +} + +div.ExecutionVisualizer div#pyCodeOutputDiv { + /*max-width: 550px;*/ + max-height: 450px; + /*max-height: 620px;*/ + overflow: auto; + /*margin-bottom: 4px;*/ + + margin-left: auto; + margin-right: auto; +} + +div.ExecutionVisualizer table#pyCodeOutput { + font-family: Andale mono, monospace; + font-size:12pt; + line-height:1.1em; + + border-collapse: separate; /* some crazy CSS voodoo that needs to be + there so that SVG arrows to the left + of the code line up vertically in Chrome */ + border-spacing: 0px; + border-top: 1px solid #bbb; + padding-top: 3px; + border-bottom: 1px solid #bbb; + /*margin-top: 6px;*/ + margin: 6px auto; /* Center code in its pane */ +} + +/* don't wrap lines within code output ... FORCE scrollbars to appear */ +div.ExecutionVisualizer table#pyCodeOutput td { + white-space: nowrap; + vertical-align: middle; /* explicitly force, to override external CSS conflicts */ +} + +div.ExecutionVisualizer #leftCodeGutterSVG { + width: 18px; + min-width: 18px; /* make sure it doesn't squash too thin */ + height: 0px; /* programmatically set this later ... IE needs this to + be 0 or it defaults to something arbitrary and gross */ +} + +div.ExecutionVisualizer #prevLegendArrowSVG, +div.ExecutionVisualizer #curLegendArrowSVG { + width: 18px; + height: 10px; +} + +div.ExecutionVisualizer .arrow { + font-size: 16pt; +} + +div.ExecutionVisualizer table#pyCodeOutput .lineNo { + color: #aaa; + padding: 0.2em; + padding-left: 0.3em; + padding-right: 0.5em; + text-align: right; +} + +div.ExecutionVisualizer table#pyCodeOutput .cod { + /*font-weight: bold;*/ + margin-left: 3px; + padding-left: 7px; + text-align: left; /* necessary or else doesn't work properly in IE */ +} + +div.ExecutionVisualizer div#progOutputs { + margin-top: 8px; +} + +div.ExecutionVisualizer div#legendDiv { + margin-top: 10px; + padding: 0px; + text-align: left; + color: #666; + font-size: 9pt; +} + +div.ExecutionVisualizer div#editCodeLinkDiv { + text-align: center; + /* + margin-top: 12px; + margin-bottom: 4px; + */ + margin: 8px auto; +} + +div.ExecutionVisualizer div#annotateLinkDiv { + /*text-align: left;*/ + margin-top: 0px; + margin-bottom: 12px; + /* + margin-left: auto; + margin-right: auto; + */ +} + +div.ExecutionVisualizer div#stepAnnotationDiv { + margin-bottom: 12px; +} + +div.ExecutionVisualizer textarea#stepAnnotationEditor, +div.ExecutionVisualizer textarea#vizTitleEditor, +div.ExecutionVisualizer textarea#vizDescriptionEditor { + border: 1px solid #999999; + padding: 4px; + + overflow: auto; /* to look pretty on IE */ + /* make sure textarea doesn't grow and stretch */ + resize: none; +} + + +div.ExecutionVisualizer #errorOutput { + color: #e93f34; /* should match brightRed JavaScript variable */ + font-size: 12pt; + padding: 2px; + line-height: 1.5em; + margin-bottom: 4px; +} + +/* VCR control buttons for stepping through execution */ + +div.ExecutionVisualizer #vcrControls { + margin: 15px auto; + /*width: 100%;*/ + text-align: center; +} + +div.ExecutionVisualizer #vcrControls button { + margin-left: 2px; + margin-right: 2px; +} + +div.ExecutionVisualizer #vcrControls #curInstr { + margin-left: 4px; + margin-right: 4px; +} + +div.ExecutionVisualizer #pyStdout { + border: 1px solid #999999; + font-size: 12pt; + padding: 4px; + font-family: Andale mono, monospace; + + overflow: auto; /* to look pretty on IE */ + /* make sure textarea doesn't grow and stretch */ + resize: none; + + -moz-box-sizing: border-box; + box-sizing: border-box; + + width: 100%; +} + + +div.ExecutionVisualizer .vizFrame { + margin-bottom: 20px; + padding-left: 8px; + border-left: 2px solid #cccccc; +} + + +/* Rendering of primitive types */ + +div.ExecutionVisualizer .nullObj { +// font-size: 8pt; +} + +div.ExecutionVisualizer .stringObj, +div.ExecutionVisualizer .customObj, +div.ExecutionVisualizer .funcObj { + font-family: Andale mono, monospace; + white-space: nowrap; +} + +div.ExecutionVisualizer .retval { + font-size: 9pt; +} + +div.ExecutionVisualizer .stackFrame .retval { + color: #e93f34; /* highlight non-zombie stack frame return values - + should match brightRed JavaScript variable */ +} + +/* Rendering of basic compound types */ + +div.ExecutionVisualizer table.listTbl, +div.ExecutionVisualizer table.tupleTbl, +div.ExecutionVisualizer table.setTbl { + background-color: #ffffc6; +} + + +div.ExecutionVisualizer table.listTbl { + border: 0px solid black; + border-spacing: 0px; +} + +div.ExecutionVisualizer table.listTbl td.listHeader, +div.ExecutionVisualizer table.tupleTbl td.tupleHeader { + padding-left: 4px; + padding-top: 2px; + padding-bottom: 3px; + font-size: 8pt; + color: #777; + text-align: left; + border-left: 1px solid #555555; +} + +div.ExecutionVisualizer table.tupleTbl { + border-spacing: 0px; + color: black; + + border-bottom: 1px solid #555555; /* must match td.tupleHeader border */ + border-top: 1px solid #555555; /* must match td.tupleHeader border */ + border-right: 1px solid #555555; /* must match td.tupleHeader border */ +} + + +div.ExecutionVisualizer table.listTbl td.listElt { + border-bottom: 1px solid #555555; /* must match td.listHeader border */ + border-left: 1px solid #555555; /* must match td.listHeader border */ +} + +div.ExecutionVisualizer table.tupleTbl td.tupleElt { + border-left: 1px solid #555555; /* must match td.tupleHeader border */ +} + +div.ExecutionVisualizer table.customObjTbl { + background-color: white; + color: black; + border: 1px solid black; +} + +div.ExecutionVisualizer table.customObjTbl td.customObjElt { + padding: 5px; +} + +div.ExecutionVisualizer table.listTbl td.listElt, +div.ExecutionVisualizer table.tupleTbl td.tupleElt { + padding-top: 0px; + padding-bottom: 8px; + padding-left: 10px; + padding-right: 10px; + vertical-align: bottom; +} + +div.ExecutionVisualizer table.setTbl { + border: 1px solid #555555; + border-spacing: 0px; + text-align: center; +} + +div.ExecutionVisualizer table.setTbl td.setElt { + padding: 8px; +} + + +div.ExecutionVisualizer table.dictTbl, +div.ExecutionVisualizer table.instTbl, +div.ExecutionVisualizer table.classTbl { + border-spacing: 1px; +} + +div.ExecutionVisualizer table.dictTbl td.dictKey, +div.ExecutionVisualizer table.instTbl td.instKey, +div.ExecutionVisualizer table.classTbl td.classKey { + background-color: #faebbf; +} + +div.ExecutionVisualizer table.dictTbl td.dictVal, +div.ExecutionVisualizer table.instTbl td.instVal, +div.ExecutionVisualizer table.classTbl td.classVal { + background-color: #ffffc6; +} + + +div.ExecutionVisualizer table.dictTbl td.dictKey, +div.ExecutionVisualizer table.instTbl td.instKey, +div.ExecutionVisualizer table.classTbl td.classKey { + padding-top: 12px /*15px*/; + padding-bottom: 5px; + padding-left: 10px; + padding-right: 4px; + + text-align: right; +} + +div.ExecutionVisualizer table.dictTbl td.dictVal, +div.ExecutionVisualizer table.instTbl td.instVal, +div.ExecutionVisualizer table.classTbl td.classVal { + padding-top: 12px /*15px*/; + padding-bottom: 5px; + padding-right: 10px; + padding-left: 4px; +} + + +div.ExecutionVisualizer table.classTbl td, +div.ExecutionVisualizer table.instTbl td { + border-bottom: 1px #888 solid; +} + +div.ExecutionVisualizer table.classTbl td.classVal, +div.ExecutionVisualizer table.instTbl td.instVal { + border-left: 1px #888 solid; +} + +div.ExecutionVisualizer table.classTbl { + border-collapse: collapse; + border: 1px #888 solid; +} + +/* only add a border to dicts if they're embedded within another object */ +div.ExecutionVisualizer td.listElt table.dictTbl, +div.ExecutionVisualizer td.tupleElt table.dictTbl, +div.ExecutionVisualizer td.dictVal table.dictTbl, +div.ExecutionVisualizer td.instVal table.dictTbl, +div.ExecutionVisualizer td.classVal table.dictTbl { + border: 1px #888 solid; +} + +div.ExecutionVisualizer .objectIdLabel { + font-size: 8pt; + color: #444; + margin-bottom: 2px; +} + +div.ExecutionVisualizer .typeLabel { + font-size: 8pt; + color: #555; + margin-bottom: 2px; +} + +div.ExecutionVisualizer div#stack, +div.ExecutionVisualizer div#globals_area { + padding-left: 10px; + padding-right: 30px; + + /* no longer necessary ... */ + /*float: left;*/ + /* border-right: 1px dashed #bbbbbb; */ +} + +div.ExecutionVisualizer div.stackFrame, +div.ExecutionVisualizer div.zombieStackFrame { + background-color: #ffffff; + margin-bottom: 15px; + padding: 2px; + padding-left: 6px; + padding-right: 6px; + padding-bottom: 4px; + font-size: 10pt; +} + +div.ExecutionVisualizer div.zombieStackFrame { + border-left: 1px dotted #aaa; + /*color: #c0c0c0;*/ + color: #a0a0a0; +} + +div.ExecutionVisualizer div.highlightedStackFrame { + background-color: #e2ebf6; + /*background-color: #d7e7fb;*/ + + /*background-color: #c0daf8;*/ + /*background-color: #9eeaff #c5dfea;*/ +} + +div.ExecutionVisualizer div.stackFrame, +div.ExecutionVisualizer div.highlightedStackFrame { + border-left: 1px solid #a6b3b6; +} + + +div.ExecutionVisualizer div.stackFrameHeader { + font-family: Andale mono, monospace; + font-size: 10pt; + margin-top: 4px; + margin-bottom: 3px; + white-space: nowrap; +} + +div.ExecutionVisualizer td.stackFrameVar { + text-align: right; + padding-right: 8px; + padding-top: 3px; + padding-bottom: 3px; +} + +div.ExecutionVisualizer td.stackFrameValue { + text-align: left; + border-bottom: 1px solid #aaaaaa; + border-left: 1px solid #aaaaaa; + + vertical-align: middle; + + padding-top: 3px; + padding-left: 3px; + padding-bottom: 3px; +} + +div.ExecutionVisualizer .stackFrameVarTable tr { + +} + +div.ExecutionVisualizer .stackFrameVarTable { + text-align: right; + padding-top: 3px; + + /* right-align the table */ + margin-left: auto; + margin-right: 0px; + + /* hack to counteract possible nasty CSS reset styles from parent divs */ + border-collapse: separate; + border-spacing: 2px; +} + +div.ExecutionVisualizer div#heap { + float: left; + padding-left: 30px; +} + +div.ExecutionVisualizer td.toplevelHeapObject { + /* needed for d3 to do transitions */ + padding-left: 8px; + padding-right: 8px; + padding-top: 4px; + padding-bottom: 4px; + /* + border: 2px dotted white; + border-color: white; + */ +} + +div.ExecutionVisualizer table.heapRow { + margin-bottom: 10px; +} + +div.ExecutionVisualizer div.heapObject { + padding-left: 2px; /* leave a TINY amount of room for connector endpoints */ +} + +div.ExecutionVisualizer div.heapPrimitive { + padding-left: 4px; /* leave some more room for connector endpoints */ +} + +div.ExecutionVisualizer div#stackHeader { + margin-bottom: 15px; + text-align: right; +} + +div.ExecutionVisualizer div#heapHeader { + /*margin-top: 2px; + margin-bottom: 13px;*/ + margin-bottom: 15px; +} + +div.ExecutionVisualizer div#stackHeader, +div.ExecutionVisualizer div#heapHeader { + color: #333333; + font-size: 10pt; +} + +div.ExecutionVisualizer #executionSlider { + /* if you set 'width', then it looks ugly when you dynamically resize */ + margin-top: 15px; + margin-bottom: 5px; + + margin-left: auto; + margin-right: auto; + + width: 95%; +} + +div.ExecutionVisualizer #executionSliderCaption { + font-size: 8pt; + color: #666666; + margin-top: 15px; +} + +div.ExecutionVisualizer #executionSliderFooter { + margin-top: -7px; /* make it butt up against #executionSlider */ +} + + +/* darken slider handle a bit */ +div.ExecutionVisualizer .ui-slider .ui-slider-handle { + border: 1px solid #999; +} + + +/* for annotation bubbles */ + +/* For styling tricks, see: http://css-tricks.com/textarea-tricks/ */ +textarea.bubbleInputText { + border: 1px solid #ccc; + outline: none; + overflow: auto; /* to look pretty on IE */ + + /* make sure textarea doesn't grow and stretch the enclosing bubble */ + resize: none; + width: 225px; + max-width: 225px; + height: 35px; + max-height: 35px; +} + + +.ui-tooltip-pgbootstrap, +textarea.bubbleInputText { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 9pt; + line-height: 1.3em; +} + + +/* modified version of Twitter bootstrap style by Philip Guo */ +.ui-tooltip-pgbootstrap{ + color: #333; + background-color: #ffffff; + + max-width: 250px; + min-width: 10px; + + border: 2px solid #4284D3; + + cursor: pointer; + + *border-right-width: 2px; + *border-bottom-width: 2px; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + + /* way too poofy ... + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + */ + + -webkit-box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.2); + box-shadow: 2px 2px 3px 0px rgba(0, 0, 0, 0.2); + + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + + .ui-tooltip-pgbootstrap .ui-tooltip-titlebar{ + font-size: 18px; + line-height: 22px; + + border-bottom: 1px solid #ccc; + background-color: transparent; + } + + .ui-tooltip-pgbootstrap .ui-tooltip-content{ + padding: 5px /* 5px is minimum or else it might look ugly */ 8px; + } + + + .ui-tooltip-pgbootstrap .ui-tooltip-titlebar .ui-state-default{ + right: 9px; top: 49%; + border-style: none; + } + + .ui-tooltip-pgbootstrap .ui-tooltip-icon{ + background: white; + } + + .ui-tooltip-pgbootstrap .ui-tooltip-icon .ui-icon{ + width: auto; + height: auto; + float: right; + font-size: 20px; + font-weight: bold; + line-height: 18px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); + } + + .ui-tooltip-pgbootstrap .ui-tooltip-icon .ui-icon:hover{ + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); + } + + +/* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */ +.ui-tooltip-pgbootstrap{ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + + +.ui-tooltip-pgbootstrap-stub{ + border: 1px solid #999; + + /* + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + */ +} + + .ui-tooltip-pgbootstrap-stub .ui-tooltip-content{ + padding: 6px 9px; + } + + +div.ExecutionVisualizer .annotationText, +div.ExecutionVisualizer .vizDescriptionText { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 11pt; + line-height: 1.5em; +} + +div.ExecutionVisualizer .vizTitleText { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 16pt; + margin-bottom: 12pt; +} + +div.ExecutionVisualizer div#vizHeader { + margin-bottom: 10px; + width: 700px; + max-width: 700px; +} + +/* prev then curr, so curr gets precedence when both apply */ +div.ExecutionVisualizer .highlight-prev { + background-color: #F0F0EA; +} + +div.ExecutionVisualizer .highlight-cur { + background-color: #FFFF66; +} + +div.ExecutionVisualizer .highlight-legend { + padding: 2px; +} + +/* resizing sliders from David Pritchard */ +.ui-resizable-e { + background-color: #dddddd; + width: 1px; + border: 3px solid white; +} + +.ui-resizable-e:hover { + border-color: #dddddd; +} + + +/* for pyCrazyMode */ + +/* prev then curr, so curr gets precedence when both apply */ +div.ExecutionVisualizer .pycrazy-highlight-prev { + background-color: #eeeeee; /*#F0F0EA;*/ + /* + text-decoration: none; + border-bottom: 1px solid #dddddd; + */ +} + +div.ExecutionVisualizer .pycrazy-highlight-cur { + background-color: #FFFF66; + /* aligned slightly higher than border-bottom */ + /* + text-decoration: none; + border-bottom: 1px solid #e93f34; + */ +} + +div.ExecutionVisualizer .pycrazy-highlight-prev-and-cur { + background-color: #FFFF66; + + text-decoration: none; + border-bottom: 1px solid #999999; +} diff --git a/embed/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/embed/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000..954e22d Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png b/embed/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png new file mode 100644 index 0000000..64ece57 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png b/embed/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png new file mode 100644 index 0000000..abdc010 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png b/embed/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png new file mode 100644 index 0000000..9b383f4 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png b/embed/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png new file mode 100644 index 0000000..a23baad Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png b/embed/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000..42ccba2 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png b/embed/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png new file mode 100644 index 0000000..39d5824 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png b/embed/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png new file mode 100644 index 0000000..f127367 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png differ diff --git a/embed/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png b/embed/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png new file mode 100644 index 0000000..359397a Binary files /dev/null and b/embed/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png differ diff --git a/embed/css/ui-lightness/images/ui-icons_222222_256x240.png b/embed/css/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000..b273ff1 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-icons_222222_256x240.png differ diff --git a/embed/css/ui-lightness/images/ui-icons_228ef1_256x240.png b/embed/css/ui-lightness/images/ui-icons_228ef1_256x240.png new file mode 100644 index 0000000..a641a37 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-icons_228ef1_256x240.png differ diff --git a/embed/css/ui-lightness/images/ui-icons_ef8c08_256x240.png b/embed/css/ui-lightness/images/ui-icons_ef8c08_256x240.png new file mode 100644 index 0000000..85e63e9 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-icons_ef8c08_256x240.png differ diff --git a/embed/css/ui-lightness/images/ui-icons_ffd27a_256x240.png b/embed/css/ui-lightness/images/ui-icons_ffd27a_256x240.png new file mode 100644 index 0000000..e117eff Binary files /dev/null and b/embed/css/ui-lightness/images/ui-icons_ffd27a_256x240.png differ diff --git a/embed/css/ui-lightness/images/ui-icons_ffffff_256x240.png b/embed/css/ui-lightness/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000..42f8f99 Binary files /dev/null and b/embed/css/ui-lightness/images/ui-icons_ffffff_256x240.png differ diff --git a/embed/css/ui-lightness/jquery-ui-1.8.24.custom.css b/embed/css/ui-lightness/jquery-ui-1.8.24.custom.css new file mode 100644 index 0000000..f3988bc --- /dev/null +++ b/embed/css/ui-lightness/jquery-ui-1.8.24.custom.css @@ -0,0 +1,335 @@ +/*! + * jQuery UI CSS Framework 1.8.24 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; } +.ui-helper-clearfix:after { clear: both; } +.ui-helper-clearfix { zoom: 1; } +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/*! + * jQuery UI CSS Framework 1.8.24 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * 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 + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } +/* pgbovine - switch border from #dddddd to #ccc */ +.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; } +.ui-widget-content a { color: #333333; } +.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; } +.ui-widget-header a { color: #ffffff; } + +/* Interaction states +----------------------------------*/ +.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; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } + +/* pgbovine - eliminate hover colors */ +/* +.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; } +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; } +*/ + +.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; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.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; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.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; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.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; } +.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; } +.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; } +.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; } + +/* Overlays */ +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); } +.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; }/*! + * jQuery UI Resizable 1.8.24 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; } +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*! + * jQuery UI Slider 1.8.24 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; } diff --git a/embed/js/d3.v2.min.js b/embed/js/d3.v2.min.js new file mode 100644 index 0000000..2a1e131 --- /dev/null +++ b/embed/js/d3.v2.min.js @@ -0,0 +1,4 @@ +(function(){function d(a,b){try{for(var c in b)Object.defineProperty(a.prototype,c,{value:b[c],enumerable:!1})}catch(d){a.prototype=b}}function f(a){var b=-1,c=a.length,d=[];while(++b=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function H(a,b){var c=Math.pow(10,Math.abs(8-b)*3);return{scale:b>8?function(a){return a/c}:function(a){return a*c},symbol:a}}function N(a){return function(b){return b<=0?0:b>=1?1:a(b)}}function O(a){return function(b){return 1-a(1-b)}}function P(a){return function(b){return.5*(b<.5?a(2*b):2-a(2-2*b))}}function Q(a){return a}function R(a){return function(b){return Math.pow(b,a)}}function S(a){return 1-Math.cos(a*Math.PI/2)}function T(a){return Math.pow(2,10*(a-1))}function U(a){return 1-Math.sqrt(1-a*a)}function V(a,b){var c;return arguments.length<2&&(b=.45),arguments.length<1?(a=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/a),function(d){return 1+a*Math.pow(2,10*-d)*Math.sin((d-c)*2*Math.PI/b)}}function W(a){return a||(a=1.70158),function(b){return b*b*((a+1)*b-a)}}function X(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375}function Y(){d3.event.stopPropagation(),d3.event.preventDefault()}function Z(){var a=d3.event,b;while(b=a.sourceEvent)a=b;return a}function $(a){var b=new z,c=0,d=arguments.length;while(++c360?a-=360:a<0&&(a+=360),a<60?d+(e-d)*a/60:a<180?e:a<240?d+(e-d)*(240-a)/60:d}function g(a){return Math.round(f(a)*255)}var d,e;return a%=360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e,bd(g(a+120),g(a),g(a-120))}function bn(a){return i(a,bt),a}function bu(a){return function(){return bo(a,this)}}function bv(a){return function(){return bp(a,this)}}function bw(a,b){function f(){if(b=this.classList)return b.add(a);var b=this.className,d=b.baseVal!=null,e=d?b.baseVal:b;c.lastIndex=0,c.test(e)||(e=v(e+" "+a),d?b.baseVal=e:this.className=e)}function g(){if(b=this.classList)return b.remove(a);var b=this.className,d=b.baseVal!=null,e=d?b.baseVal:b;e=v(e.replace(c," ")),d?b.baseVal=e:this.className=e}function h(){(b.apply(this,arguments)?f:g).call(this)}var c=new RegExp("(^|\\s+)"+d3.requote(a)+"(\\s+|$)","g");if(arguments.length<2){var d=this.node();if(e=d.classList)return e.contains(a);var e=d.className;return c.lastIndex=0,c.test(e.baseVal!=null?e.baseVal:e)}return this.each(typeof b=="function"?h:b?f:g)}function bx(a){return{__data__:a}}function by(a){return function(){return bs(this,a)}}function bz(a){return arguments.length||(a=d3.ascending),function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function bA(a,b){for(var c=0,d=a.length;cb?q():(m.active=b,d.forEach(function(b,c){(c=c.call(a,n,h))&&j.push(c)}),e.start.call(a,n,h),p(f)||d3.timer(p,0,c),1)}function p(c){if(m.active!==b)return q();var d=(c-k)/l,g=f(d),i=j.length;while(i>0)j[--i].call(a,g);if(d>=1)return q(),bK=b,e.end.call(a,n,h),bK=0,1}function q(){return--m.count||delete a.__transition__,1}var j=[],k=a.delay,l=a.duration,m=(a=a.node).__transition__||(a.__transition__={active:0,count:0}),n=a.__data__;++m.count,k<=g?o(g):d3.timer(o,k,c)})},0,c),a}function bG(a,b,c){return c!=""&&bF}function bH(a,b){function d(a,d,e){var f=b.call(this,a,d);return f==null?e!=""&&bF:e!=f&&c(e,f)}function e(a,d,e){return e!=b&&c(e,b)}var c=ba(a);return typeof b=="function"?d:b==null?bG:(b+="",e)}function bR(a){var b=bK,c=bQ,d=bO,e=bP;return bK=this.id,bQ=this.ease(),bA(this,function(b,c,d){bO=b.delay,bP=b.duration,a.call(b=b.node,b.__data__,c,d)}),bK=b,bQ=c,bO=d,bP=e,this}function bV(){var a,b=Date.now(),c=bS;while(c)a=b-c.then,a>=c.delay&&(c.flush=c.callback(a)),c=c.next;var d=bW()-b;d>24?(isFinite(d)&&(clearTimeout(bU),bU=setTimeout(bV,d)),bT=0):(bT=1,bX(bV))}function bW(){var a=null,b=bS,c=Infinity;while(b)b.flush?b=a?a.next=b.next:bS=b.next:(c=Math.min(c,b.then+b.delay),b=(a=b).next);return c}function bY(a){var b=[a.a,a.b],c=[a.c,a.d],d=b$(b),e=bZ(b,c),f=b$(b_(c,b,-e))||0;b[0]*c[1]2?cp:co,i=d?bc:bb;return e=g(a,b,i,c),f=g(b,a,i,d3.interpolate),h}function h(a){return e(a)}var e,f;return h.invert=function(a){return f(a)},h.domain=function(b){return arguments.length?(a=b.map(Number),g()):a},h.range=function(a){return arguments.length?(b=a,g()):b},h.rangeRound=function(a){return h.range(a).interpolate(d3.interpolateRound)},h.clamp=function(a){return arguments.length?(d=a,g()):d},h.interpolate=function(a){return arguments.length?(c=a,g()):c},h.ticks=function(b){return cm(a,b)},h.tickFormat=function(b){return cn(a,b)},h.nice=function(){return cg(a,ck),g()},h.copy=function(){return ci(a,b,c,d)},g()}function cj(a,b){return d3.rebind(a,b,"range","rangeRound","interpolate","clamp")}function ck(a){return a=Math.pow(10,Math.round(Math.log(a)/Math.LN10)-1),{floor:function(b){return Math.floor(b/a)*a},ceil:function(b){return Math.ceil(b/a)*a}}}function cl(a,b){var c=ce(a),d=c[1]-c[0],e=Math.pow(10,Math.floor(Math.log(d/b)/Math.LN10)),f=b/d*e;return f<=.15?e*=10:f<=.35?e*=5:f<=.75&&(e*=2),c[0]=Math.ceil(c[0]/e)*e,c[1]=Math.floor(c[1]/e)*e+e*.5,c[2]=e,c}function cm(a,b){return d3.range.apply(d3,cl(a,b))}function cn(a,b){return d3.format(",."+Math.max(0,-Math.floor(Math.log(cl(a,b)[2])/Math.LN10+.01))+"f")}function co(a,b,c,d){var e=c(a[0],a[1]),f=d(b[0],b[1]);return function(a){return f(e(a))}}function cp(a,b,c,d){var e=[],f=[],g=0,h=Math.min(a.length,b.length)-1;a[h]0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(a,e){arguments.length<2&&(e=cr);if(arguments.length<1)return e;var f=Math.max(.1,a/d.ticks().length),g=b===ct?(h=-1e-12,Math.floor):(h=1e-12,Math.ceil),h;return function(a){return a/c(g(b(a)+h))<=f?e(a):""}},d.copy=function(){return cq(a.copy(),b)},cj(d,a)}function cs(a){return Math.log(a<0?0:a)/Math.LN10}function ct(a){return-Math.log(a>0?0:-a)/Math.LN10}function cu(a,b){function e(b){return a(c(b))}var c=cv(b),d=cv(1/b);return e.invert=function(b){return d(a.invert(b))},e.domain=function(b){return arguments.length?(a.domain(b.map(c)),e):a.domain().map(d)},e.ticks=function(a){return cm(e.domain(),a)},e.tickFormat=function(a){return cn(e.domain(),a)},e.nice=function(){return e.domain(cg(e.domain(),ck))},e.exponent=function(a){if(!arguments.length)return b;var f=e.domain();return c=cv(b=a),d=cv(1/b),e.domain(f)},e.copy=function(){return cu(a.copy(),b)},cj(e,a)}function cv(a){return function(b){return b<0?-Math.pow(-b,a):Math.pow(b,a)}}function cw(a,b){function f(b){return d[((c.get(b)||c.set(b,a.push(b)))-1)%d.length]}function g(b,c){return d3.range(a.length).map(function(a){return b+c*a})}var c,d,e;return f.domain=function(d){if(!arguments.length)return a;a=[],c=new j;var e=-1,g=d.length,h;while(++e1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;j9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function dh(a){return a.length<3?cP(a):a[0]+cV(a,dg(a))}function di(a){var b,c=-1,d=a.length,e,f;while(++c1){var d=ce(a.domain()),e,f=-1,g=b.length,h=(b[1]-b[0])/++c,i,j;while(++f0;)(j=+b[f]-i*h)>=d[0]&&e.push(j);for(--f,i=0;++id&&(c=b,d=e);return c}function d_(a){return a.reduce(ea,0)}function ea(a,b){return a+b[1]}function eb(a,b){return ec(a,Math.ceil(Math.log(b.length)/Math.LN2+1))}function ec(a,b){var c=-1,d=+a[0],e=(a[1]-d)/b,f=[];while(++c<=b)f[c]=e*c+d;return f}function ed(a){return[d3.min(a),d3.max(a)]}function ee(a,b){return d3.rebind(a,b,"sort","children","value"),a.links=ei,a.nodes=function(b){return ej=!0,(a.nodes=a)(b)},a}function ef(a){return a.children}function eg(a){return a.value}function eh(a,b){return b.value-a.value}function ei(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function ek(a,b){return a.value-b.value}function el(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function em(a,b){a._pack_next=b,b._pack_prev=a}function en(a,b){var c=b.x-a.x,d=b.y-a.y,e=a.r+b.r;return e*e-c*c-d*d>.001}function eo(a){function l(a){b=Math.min(a.x-a.r,b),c=Math.max(a.x+a.r,c),d=Math.min(a.y-a.r,d),e=Math.max(a.y+a.r,e)}var b=Infinity,c=-Infinity,d=Infinity,e=-Infinity,f=a.length,g,h,i,j,k;a.forEach(ep),g=a[0],g.x=-g.r,g.y=0,l(g);if(f>1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],et(g,h,i),l(i),el(g,i),g._pack_prev=i,el(i,h),h=g._pack_next;for(var m=3;m0&&(a=d)}return a}function eC(a,b){return a.x-b.x}function eD(a,b){return b.x-a.x}function eE(a,b){return a.depth-b.depth}function eF(a,b){function c(a,d){var e=a.children;if(e&&(i=e.length)){var f,g=null,h=-1,i;while(++h=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function eH(a,b,c){a=a._tree,b=b._tree;var d=c/(b.number-a.number);a.change+=d,b.change-=d,b.shift+=c,b.prelim+=c,b.mod+=c}function eI(a,b,c){return a._tree.ancestor.parent==b.parent?a._tree.ancestor:c}function eJ(a){return{x:a.x,y:a.y,dx:a.dx,dy:a.dy}}function eK(a,b){var c=a.x+b[3],d=a.y+b[0],e=a.dx-b[1]-b[3],f=a.dy-b[0]-b[2];return e<0&&(c+=e/2,e=0),f<0&&(d+=f/2,f=0),{x:c,y:d,dx:e,dy:f}}function eL(a){return a.map(eM).join(",")}function eM(a){return/[",\n]/.test(a)?'"'+a.replace(/\"/g,'""')+'"':a}function eO(a,b){return function(c){return c&&a.hasOwnProperty(c.type)?a[c.type](c):b}}function eP(a){return"m0,"+a+"a"+a+","+a+" 0 1,1 0,"+ -2*a+"a"+a+","+a+" 0 1,1 0,"+2*a+"z"}function eQ(a,b){eR.hasOwnProperty(a.type)&&eR[a.type](a,b)}function eS(a,b){eQ(a.geometry,b)}function eT(a,b){for(var c=a.features,d=0,e=c.length;d0}function fg(a,b,c){return(c[0]-b[0])*(a[1]-b[1])<(c[1]-b[1])*(a[0]-b[0])}function fh(a,b,c,d){var e=a[0],f=b[0],g=c[0],h=d[0],i=a[1],j=b[1],k=c[1],l=d[1],m=e-g,n=f-e,o=h-g,p=i-k,q=j-i,r=l-k,s=(o*p-r*m)/(r*n-o*q);return[e+s*n,i+s*q]}function fj(a,b){var c={list:a.map(function(a,b){return{index:b,x:a[0],y:a[1]}}).sort(function(a,b){return a.yb.y?1:a.xb.x?1:0}),bottomSite:null},d={list:[],leftEnd:null,rightEnd:null,init:function(){d.leftEnd=d.createHalfEdge(null,"l"),d.rightEnd=d.createHalfEdge(null,"l"),d.leftEnd.r=d.rightEnd,d.rightEnd.l=d.leftEnd,d.list.unshift(d.leftEnd,d.rightEnd)},createHalfEdge:function(a,b){return{edge:a,side:b,vertex:null,l:null,r:null}},insert:function(a,b){b.l=a,b.r=a.r,a.r.l=b,a.r=b},leftBound:function(a){var b=d.leftEnd;do b=b.r;while(b!=d.rightEnd&&e.rightOf(b,a));return b=b.l,b},del:function(a){a.l.r=a.r,a.r.l=a.l,a.edge=null},right:function(a){return a.r},left:function(a){return a.l},leftRegion:function(a){return a.edge==null?c.bottomSite:a.edge.region[a.side]},rightRegion:function(a){return a.edge==null?c.bottomSite:a.edge.region[fi[a.side]]}},e={bisect:function(a,b){var c={region:{l:a,r:b},ep:{l:null,r:null}},d=b.x-a.x,e=b.y-a.y,f=d>0?d:-d,g=e>0?e:-e;return c.c=a.x*d+a.y*e+(d*d+e*e)*.5,f>g?(c.a=1,c.b=e/d,c.c/=d):(c.b=1,c.a=d/e,c.c/=e),c},intersect:function(a,b){var c=a.edge,d=b.edge;if(!c||!d||c.region.r==d.region.r)return null;var e=c.a*d.b-c.b*d.a;if(Math.abs(e)<1e-10)return null;var f=(c.c*d.b-d.c*c.b)/e,g=(d.c*c.a-c.c*d.a)/e,h=c.region.r,i=d.region.r,j,k;h.y=k.region.r.x;return l&&j.side==="l"||!l&&j.side==="r"?null:{x:f,y:g}},rightOf:function(a,b){var c=a.edge,d=c.region.r,e=b.x>d.x;if(e&&a.side==="l")return 1;if(!e&&a.side==="r")return 0;if(c.a===1){var f=b.y-d.y,g=b.x-d.x,h=0,i=0;!e&&c.b<0||e&&c.b>=0?i=h=f>=c.b*g:(i=b.x+b.y*c.b>c.c,c.b<0&&(i=!i),i||(h=1));if(!h){var j=d.x-c.region.l.x;i=c.b*(g*g-f*f)m*m+n*n}return a.side==="l"?i:!i},endPoint:function(a,c,d){a.ep[c]=d;if(!a.ep[fi[c]])return;b(a)},distance:function(a,b){var c=a.x-b.x,d=a.y-b.y;return Math.sqrt(c*c+d*d)}},f={list:[],insert:function(a,b,c){a.vertex=b,a.ystar=b.y+c;for(var d=0,e=f.list,g=e.length;dh.ystar||a.ystar==h.ystar&&b.x>h.vertex.x)continue;break}e.splice(d,0,a)},del:function(a){for(var b=0,c=f.list,d=c.length;bo.y&&(p=n,n=o,o=p,t="r"),s=e.bisect(n,o),m=d.createHalfEdge(s,t),d.insert(k,m),e.endPoint(s,fi[t],r),q=e.intersect(k,m),q&&(f.del(k),f.insert(k,q,e.distance(q,n))),q=e.intersect(m,l),q&&f.insert(m,q,e.distance(q,n));else break}for(i=d.right(d.leftEnd);i!=d.rightEnd;i=d.right(i))b(i.edge)}function fk(){return{leaf:!0,nodes:[],point:null}}function fl(a,b,c,d,e,f){if(!a(b,c,d,e,f)){var g=(c+e)*.5,h=(d+f)*.5,i=b.nodes;i[0]&&fl(a,i[0],c,d,g,h),i[1]&&fl(a,i[1],g,d,e,h),i[2]&&fl(a,i[2],c,h,g,f),i[3]&&fl(a,i[3],g,h,e,f)}}function fm(a){return{x:a[0],y:a[1]}}function fo(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function fq(a,b,c,d){var e,f,g=0,h=b.length,i=c.length;while(g=i)return-1;e=b.charCodeAt(g++);if(e==37){f=fw[b.charAt(g++)];if(!f||(d=f(a,c,d))<0)return-1}else if(e!=c.charCodeAt(d++))return-1}return d}function fx(a,b,c){return fz.test(b.substring(c,c+=3))?c:-1}function fy(a,b,c){fA.lastIndex=0;var d=fA.exec(b.substring(c,c+10));return d?c+=d[0].length:-1}function fC(a,b,c){var d=fD.get(b.substring(c,c+=3).toLowerCase());return d==null?-1:(a.m=d,c)}function fE(a,b,c){fF.lastIndex=0;var d=fF.exec(b.substring(c,c+12));return d?(a.m=fG.get(d[0].toLowerCase()),c+=d[0].length):-1}function fI(a,b,c){return fq(a,fv.c.toString(),b,c)}function fJ(a,b,c){return fq(a,fv.x.toString(),b,c)}function fK(a,b,c){return fq(a,fv.X.toString(),b,c)}function fL(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+4));return d?(a.y=+d[0],c+=d[0].length):-1}function fM(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.y=fN()+ +d[0],c+=d[0].length):-1}function fN(){return~~((new Date).getFullYear()/1e3)*1e3}function fO(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.m=d[0]-1,c+=d[0].length):-1}function fP(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.d=+d[0],c+=d[0].length):-1}function fQ(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.H=+d[0],c+=d[0].length):-1}function fR(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.M=+d[0],c+=d[0].length):-1}function fS(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.S=+d[0],c+=d[0].length):-1}function fT(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+3));return d?(a.L=+d[0],c+=d[0].length):-1}function fV(a,b,c){var d=fW.get(b.substring(c,c+=2).toLowerCase());return d==null?-1:(a.p=d,c)}function fX(a){var b=a.getTimezoneOffset(),c=b>0?"-":"+",d=~~(Math.abs(b)/60),e=Math.abs(b)%60;return c+fr(d)+fr(e)}function fZ(a){return a.toISOString()}function f$(a,b,c){function d(b){var c=a(b),d=f(c,1);return b-c1)while(gb?1:a>=b?0:NaN},d3.descending=function(a,b){return ba?1:b>=a?0:NaN},d3.mean=function(a,b){var c=a.length,d,e=0,f=-1,g=0;if(arguments.length===1)while(++f1&&(a=a.map(b)),a=a.filter(r),a.length?d3.quantile(a.sort(d3.ascending),.5):undefined},d3.min=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++cf&&(e=f)}else{while(++cf&&(e=f)}return e},d3.max=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++ce&&(e=f)}else{while(++ce&&(e=f)}return e},d3.extent=function(a,b){var c=-1,d=a.length,e,f,g;if(arguments.length===1){while(++cf&&(e=f),gf&&(e=f),g1);return a+b*c*Math.sqrt(-2*Math.log(e)/e)}}},d3.sum=function(a,b){var c=0,d=a.length,e,f=-1;if(arguments.length===1)while(++f>1;a.call(b,b[f],f)>1;c0&&(e=f);return e},d3.last=function(a,b){var c=0,d=a.length,e=a[0],f;arguments.length===1&&(b=d3.ascending);while(++c=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,k=b[g++],l,m,n=new j,o,p={};while(++h=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});return f&&e.sort(function(a,b){return f(a.key,b.key)}),e}var a={},b=[],c=[],d,e;return a.map=function(a){return f(a,0)},a.entries=function(a){return g(f(a,0),0)},a.key=function(c){return b.push(c),a},a.sortKeys=function(d){return c[b.length-1]=d,a},a.sortValues=function(b){return d=b,a},a.rollup=function(b){return e=b,a},a},d3.keys=function(a){var b=[];for(var c in a)b.push(c);return b},d3.values=function(a){var b=[];for(var c in a)b.push(a[c]);return b},d3.entries=function(a){var b=[];for(var c in a)b.push({key:c,value:a[c]});return b},d3.permute=function(a,b){var c=[],d=-1,e=b.length;while(++db)d.push(g/e);else while((g=a+c*++f)=200&&a<300||a===304?d:null)}},d.send(null)},d3.text=function(a,b,c){function d(a){c(a&&a.responseText)}arguments.length<3&&(c=b,b=null),d3.xhr(a,b,d)},d3.json=function(a,b){d3.text(a,"application/json",function(a){b(a?JSON.parse(a):null)})},d3.html=function(a,b){d3.text(a,"text/html",function(a){if(a!=null){var c=document.createRange();c.selectNode(document.body),a=c.createContextualFragment(a)}b(a)})},d3.xml=function(a,b,c){function d(a){c(a&&a.responseXML)}arguments.length<3&&(c=b,b=null),d3.xhr(a,b,d)};var y={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};d3.ns={prefix:y,qualify:function(a){var b=a.indexOf(":"),c=a;return b>=0&&(c=a.substring(0,b),a=a.substring(b+1)),y.hasOwnProperty(c)?{space:y[c],local:a}:a}},d3.dispatch=function(){var a=new z,b=-1,c=arguments.length;while(++b0&&(d=a.substring(c+1),a=a.substring(0,c)),arguments.length<2?this[a].on(d):this[a].on(d,b)},d3.format=function(a){var b=B.exec(a),c=b[1]||" ",d=b[3]||"",e=b[5],f=+b[6],g=b[7],h=b[8],i=b[9],j=1,k="",l=!1;h&&(h=+h.substring(1)),e&&(c="0",g&&(f-=Math.floor((f-1)/4)));switch(i){case"n":g=!0,i="g";break;case"%":j=100,k="%",i="f";break;case"p":j=100,k="%",i="r";break;case"d":l=!0,h=0;break;case"s":j=-1,i="r"}return i=="r"&&!h&&(i="g"),i=C.get(i)||E,function(a){if(l&&a%1)return"";var b=a<0&&(a=-a)?"−":d;if(j<0){var m=d3.formatPrefix(a,h);a=m.scale(a),k=m.symbol}else a*=j;a=i(a,h);if(e){var n=a.length+b.length;n=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,C=d3.map({g:function(a,b){return a.toPrecision(b)},e:function(a,b){return a.toExponential(b)},f:function(a,b){return a.toFixed(b)},r:function(a,b){return d3.round(a,b=D(a,b)).toFixed(Math.max(0,Math.min(20,b)))}}),G=["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(H);d3.formatPrefix=function(a,b){var c=0;return a&&(a<0&&(a*=-1),b&&(a=d3.round(a,D(a,b))),c=1+Math.floor(1e-12+Math.log(a)/Math.LN10),c=Math.max(-24,Math.min(24,Math.floor((c<=0?c+1:c-1)/3)*3))),G[8+c/3]};var I=R(2),J=R(3),K=function(){return Q},L=d3.map({linear:K,poly:R,quad:function(){return I},cubic:function(){return J},sin:function(){return S},exp:function(){return T},circle:function(){return U},elastic:V,back:W,bounce:function(){return X}}),M=d3.map({"in":Q,out:O,"in-out":P,"out-in":function(a){return P(O(a))}});d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return c=L.get(c)||K,d=M.get(d)||Q,N(d(c.apply(null,Array.prototype.slice.call(arguments,1))))},d3.event=null,d3.interpolate=function(a,b){var c=d3.interpolators.length,d;while(--c>=0&&!(d=d3.interpolators[c](a,b)));return d},d3.interpolateNumber=function(a,b){return b-=a,function(c){return a+b*c}},d3.interpolateRound=function(a,b){return b-=a,function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;_.lastIndex=0;for(d=0;c=_.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=_.lastIndex;f180?k+=360:k-j>180&&(j+=360),d.push({i:c.push(c.pop()+"rotate(",null,")")-2,x:d3.interpolateNumber(j,k)})):k&&c.push(c.pop()+"rotate("+k+")"),l!=m?d.push({i:c.push(c.pop()+"skewX(",null,")")-2,x:d3.interpolateNumber(l,m)}):m&&c.push(c.pop()+"skewX("+m+")"),n[0]!=o[0]||n[1]!=o[1]?(e=c.push(c.pop()+"scale(",null,",",null,")"),d.push({i:e-4,x:d3.interpolateNumber(n[0],o[0])},{i:e-2,x:d3.interpolateNumber(n[1],o[1])})):(o[0]!=1||o[1]!=1)&&c.push(c.pop()+"scale("+o+")"),e=d.length,function(a){var b=-1,f;while(++b180?f-=360:f<-180&&(f+=360),function(a){return bm(c+f*a,d+g*a,e+h*a).toString()}},d3.interpolateArray=function(a,b){var c=[],d=[],e=a.length,f=b.length,g=Math.min(a.length,b.length),h;for(h=0;h1){while(++e=0;)if(f=c[d])e&&e!==f.nextSibling&&e.parentNode.insertBefore(f,e),e=f;return this},bt.sort=function(a){a=bz.apply(this,arguments);for(var b=-1,c=this.length;++b0&&(a=a.substring(0,e)),arguments.length<2?(e=this.node()[d])&&e._:this.each(function(e,f){function i(a){var c=d3.event;d3.event=a;try{b.call(g,g.__data__,f)}finally{d3.event=c}}var g=this,h=g[d];h&&(g.removeEventListener(a,h,h.$),delete g[d]),b&&(g.addEventListener(a,g[d]=i,i.$=c),i._=b)})},bt.each=function(a){return bA(this,function(b,c,d){a.call(b,b.__data__,c,d)})},bt.call=function(a){return a.apply(this,(arguments[0]=this,arguments)),this},bt.empty=function(){return!this.node()},bt.node=function(a){for(var b=0,c=this.length;b=cF?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,0 0,"+ -e+"A"+e+","+e+" 0 1,0 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=cG,b=cH,c=cI,d=cJ;return e.innerRadius=function(b){return arguments.length?(a=p(b),e):a},e.outerRadius=function(a){return arguments.length?(b=p(a),e):b},e.startAngle=function(a){return arguments.length?(c=p(a),e):c},e.endAngle=function(a){return arguments.length?(d=p(a),e):d},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+cE;return[Math.cos(f)*e,Math.sin(f)*e]},e};var cE=-Math.PI/2,cF=2*Math.PI-1e-6;d3.svg.line=function(){return cK(m)};var cN="linear",cO=d3.map({linear:cP,"step-before":cQ,"step-after":cR,basis:cX,"basis-open":cY,"basis-closed":cZ,bundle:c$,cardinal:cU,"cardinal-open":cS,"cardinal-closed":cT,monotone:dh}),da=[0,2/3,1/3,0],db=[0,1/3,2/3,0],dc=[0,1/6,2/3,1/6];d3.svg.line.radial=function(){var a=cK(di);return a.radius=a.x,delete a.x,a.angle=a.y,delete a.y,a},cQ.reverse=cR,cR.reverse=cQ,d3.svg.area=function(){return dj(Object)},d3.svg.area.radial=function(){var a=dj(di);return a.radius=a.x,delete a.x,a.innerRadius=a.x0,delete a.x0,a.outerRadius=a.x1,delete a.x1,a.angle=a.y,delete a.y,a.startAngle=a.y0,delete a.y0,a.endAngle=a.y1,delete a.y1,a},d3.svg.chord=function(){function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1,e.a1-e.a0)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1,f.a1-f.a0)+j(f.r,f.p1,e.r,e.p0))+"Z"}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+cE,k=e.call(a,h,g)+cE;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function i(a,b,c){return"A"+a+","+a+" 0 "+ +(c>Math.PI)+",1 "+b}function j(a,b,c,d){return"Q 0,0 "+d}var a=dk,b=dl,c=dm,d=cI,e=cJ;return f.radius=function(a){return arguments.length?(c=p(a),f):c},f.source=function(b){return arguments.length?(a=p(b),f):a},f.target=function(a){return arguments.length?(b=p(a),f):b},f.startAngle=function(a){return arguments.length?(d=p(a),f):d},f.endAngle=function(a){return arguments.length?(e=p(a),f):e},f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];return i=i.map(c),"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=dk,b=dl,c=dq;return d.source=function(b){return arguments.length?(a=p(b),d):a},d.target=function(a){return arguments.length?(b=p(a),d):b},d.projection=function(a){return arguments.length?(c=a,d):c},d},d3.svg.diagonal +.radial=function(){var a=d3.svg.diagonal(),b=dq,c=a.projection;return a.projection=function(a){return arguments.length?c(dr(b=a)):b},a},d3.svg.mouse=d3.mouse,d3.svg.touches=d3.touches,d3.svg.symbol=function(){function c(c,d){return(dv.get(a.call(this,c,d))||du)(b.call(this,c,d))}var a=dt,b=ds;return c.type=function(b){return arguments.length?(a=p(b),c):a},c.size=function(a){return arguments.length?(b=p(a),c):b},c};var dv=d3.map({circle:du,cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*dx)),c=b*dx;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/dw),c=b*dw/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/dw),c=b*dw/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}});d3.svg.symbolTypes=dv.keys();var dw=Math.sqrt(3),dx=Math.tan(30*Math.PI/180);d3.svg.axis=function(){function k(k){k.each(function(){var k=d3.select(this),l=h==null?a.ticks?a.ticks.apply(a,g):a.domain():h,m=i==null?a.tickFormat?a.tickFormat.apply(a,g):String:i,n=dA(a,l,j),o=k.selectAll(".minor").data(n,String),p=o.enter().insert("line","g").attr("class","tick minor").style("opacity",1e-6),q=d3.transition(o.exit()).style("opacity",1e-6).remove(),r=d3.transition(o).style("opacity",1),s=k.selectAll("g").data(l,String),t=s.enter().insert("g","path").style("opacity",1e-6),u=d3.transition(s.exit()).style("opacity",1e-6).remove(),v=d3.transition(s).style("opacity",1),w,x=cf(a),y=k.selectAll(".domain").data([0]),z=y.enter().append("path").attr("class","domain"),A=d3.transition(y),B=a.copy(),C=this.__chart__||B;this.__chart__=B,t.append("line").attr("class","tick"),t.append("text");var D=t.select("line"),E=v.select("line"),F=s.select("text").text(m),G=t.select("text"),H=v.select("text");switch(b){case"bottom":w=dy,p.attr("y2",d),r.attr("x2",0).attr("y2",d),D.attr("y2",c),G.attr("y",Math.max(c,0)+f),E.attr("x2",0).attr("y2",c),H.attr("x",0).attr("y",Math.max(c,0)+f),F.attr("dy",".71em").attr("text-anchor","middle"),A.attr("d","M"+x[0]+","+e+"V0H"+x[1]+"V"+e);break;case"top":w=dy,p.attr("y2",-d),r.attr("x2",0).attr("y2",-d),D.attr("y2",-c),G.attr("y",-(Math.max(c,0)+f)),E.attr("x2",0).attr("y2",-c),H.attr("x",0).attr("y",-(Math.max(c,0)+f)),F.attr("dy","0em").attr("text-anchor","middle"),A.attr("d","M"+x[0]+","+ -e+"V0H"+x[1]+"V"+ -e);break;case"left":w=dz,p.attr("x2",-d),r.attr("x2",-d).attr("y2",0),D.attr("x2",-c),G.attr("x",-(Math.max(c,0)+f)),E.attr("x2",-c).attr("y2",0),H.attr("x",-(Math.max(c,0)+f)).attr("y",0),F.attr("dy",".32em").attr("text-anchor","end"),A.attr("d","M"+ -e+","+x[0]+"H0V"+x[1]+"H"+ -e);break;case"right":w=dz,p.attr("x2",d),r.attr("x2",d).attr("y2",0),D.attr("x2",c),G.attr("x",Math.max(c,0)+f),E.attr("x2",c).attr("y2",0),H.attr("x",Math.max(c,0)+f).attr("y",0),F.attr("dy",".32em").attr("text-anchor","start"),A.attr("d","M"+e+","+x[0]+"H0V"+x[1]+"H"+e)}if(a.ticks)t.call(w,C),v.call(w,B),u.call(w,B),p.call(w,C),r.call(w,B),q.call(w,B);else{var I=B.rangeBand()/2,J=function(a){return B(a)+I};t.call(w,J),v.call(w,J)}})}var a=d3.scale.linear(),b="bottom",c=6,d=6,e=6,f=3,g=[10],h=null,i,j=0;return k.scale=function(b){return arguments.length?(a=b,k):a},k.orient=function(a){return arguments.length?(b=a,k):b},k.ticks=function(){return arguments.length?(g=arguments,k):g},k.tickValues=function(a){return arguments.length?(h=a,k):h},k.tickFormat=function(a){return arguments.length?(i=a,k):i},k.tickSize=function(a,b,f){if(!arguments.length)return c;var g=arguments.length-1;return c=+a,d=g>1?+b:c,e=g>0?+arguments[g]:c,k},k.tickPadding=function(a){return arguments.length?(f=+a,k):f},k.tickSubdivide=function(a){return arguments.length?(j=+a,k):j},k},d3.svg.brush=function(){function g(a){a.each(function(){var a=d3.select(this),e=a.selectAll(".background").data([0]),f=a.selectAll(".extent").data([0]),l=a.selectAll(".resize").data(d,String),m;a.style("pointer-events","all").on("mousedown.brush",k).on("touchstart.brush",k),e.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),f.enter().append("rect").attr("class","extent").style("cursor","move"),l.enter().append("g").attr("class",function(a){return"resize "+a}).style("cursor",function(a){return dB[a]}).append("rect").attr("x",function(a){return/[ew]$/.test(a)?-3:null}).attr("y",function(a){return/^[ns]/.test(a)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),l.style("display",g.empty()?"none":null),l.exit().remove(),b&&(m=cf(b),e.attr("x",m[0]).attr("width",m[1]-m[0]),i(a)),c&&(m=cf(c),e.attr("y",m[0]).attr("height",m[1]-m[0]),j(a)),h(a)})}function h(a){a.selectAll(".resize").attr("transform",function(a){return"translate("+e[+/e$/.test(a)][0]+","+e[+/^s/.test(a)][1]+")"})}function i(a){a.select(".extent").attr("x",e[0][0]),a.selectAll(".extent,.n>rect,.s>rect").attr("width",e[1][0]-e[0][0])}function j(a){a.select(".extent").attr("y",e[0][1]),a.selectAll(".extent,.e>rect,.w>rect").attr("height",e[1][1]-e[0][1])}function k(){function x(){var a=d3.event.changedTouches;return a?d3.touches(d,a)[0]:d3.mouse(d)}function y(){d3.event.keyCode==32&&(q||(r=null,s[0]-=e[1][0],s[1]-=e[1][1],q=2),Y())}function z(){d3.event.keyCode==32&&q==2&&(s[0]+=e[1][0],s[1]+=e[1][1],q=0,Y())}function A(){var a=x(),d=!1;t&&(a[0]+=t[0],a[1]+=t[1]),q||(d3.event.altKey?(r||(r=[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]),s[0]=e[+(a[0]0?e=c:e=0:c>0&&(b.start({type:"start",alpha:e=c}),d3.timer(a.tick)),a):e},a.start=function(){function p(a,c){var d=t(b),e=-1,f=d.length,g;while(++ee&&(e=h),d.push(h)}for(g=0;g0){f=-1;while(++f=i[0]&&o<=i[1]&&(k=g[d3.bisect(j,o,1,m)-1],k.y+=n,k.push(e[f]))}return g}var a=!0,b=Number,c=ed,d=eb;return e.value=function(a){return arguments.length?(b=a,e):b},e.range=function(a){return arguments.length?(c=p(a),e):c},e.bins=function(a){return arguments.length?(d=typeof a=="number"?function(b){return ec(b,a)}:p(a),e):d},e.frequency=function(b){return arguments.length?(a=!!b,e):a},e},d3.layout.hierarchy=function(){function d(e,g,h){var i=b.call(f,e,g),j=ej?e:{data:e};j.depth=g,h.push(j);if(i&&(l=i.length)){var k=-1,l,m=j.children=[],n=0,o=g+1,p;while(++k0&&(eH(eI(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!eA(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!ez(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}var f=a.call(this,d,e),g=f[0];eF(g,function(a,b){a._tree={ancestor:a,prelim:0,mod:0,change:0,shift:0,number:b?b._tree.number+1:0}}),h(g),i(g,-g._tree.prelim);var k=eB(g,eD),l=eB(g,eC),m=eB(g,eE),n=k.x-b(k,l)/2,o=l.x+b(l,k)/2,p=m.depth||1;return eF(g,function(a){a.x=(a.x-n)/(o-n)*c[0],a.y=a.depth/p*c[1],delete a._tree}),f}var a=d3.layout.hierarchy().sort(null).value(null),b=ey,c=[1,1];return d.separation=function(a){return arguments.length?(b=a,d):b},d.size=function(a){return arguments.length?(c=a,d):c},ee(d,a)},d3.layout.treemap=function(){function i(a,b){var c=-1,d=a.length,e,f;while(++c0)d.push(g=f[o-1]),d.area+=g.area,(k=l(d,n))<=h?(f.pop(),h=k):(d.area-=d.pop().area,m(d,n,c,!1),n=Math.min(c.dx,c.dy),d.length=d.area=0,h=Infinity);d.length&&(m(d,n,c,!0),d.length=d.area=0),b.forEach(j)}}function k(a){var b=a.children;if(b&&b.length){var c=e(a),d=b.slice(),f,g=[];i(d,c.dx*c.dy/a.value),g.area=0;while(f=d.pop())g.push(f),g.area+=f.area,f.z!=null&&(m(g,f.z?c.dx:c.dy,c,!d.length),g.length=g.area=0);b.forEach(k)}}function l(a,b){var c=a.area,d,e=0,f=Infinity,g=-1,i=a.length;while(++ge&&(e=d)}return c*=c,b*=b,c?Math.max(b*e*h/c,c/(b*f*h)):Infinity}function m(a,c,d,e){var f=-1,g=a.length,h=d.x,i=d.y,j=c?b(a.area/c):0,k;if(c==d.dx){if(e||j>d.dy)j=d.dy;while(++fd.dx)j=d.dx;while(++f=a.length)return d;if(i)return i=!1,c;var b=f.lastIndex;if(a.charCodeAt(b)===34){var e=b;while(e++50?b:f<-140?c:g<21?d:a)(e)}var a=d3.geo.albers(),b=d3.geo.albers().origin([-160,60]).parallels([55,65]),c=d3.geo.albers().origin([-160,20]).parallels([8,18]),d=d3.geo.albers().origin([-60,10]).parallels([8,18]);return e.scale=function(f){return arguments.length?(a.scale(f),b.scale(f*.6),c.scale(f),d.scale(f*1.5),e.translate(a.translate())):a.scale()},e.translate=function(f){if(!arguments.length)return a.translate();var g=a.scale()/1e3,h=f[0],i=f[1];return a.translate(f),b.translate([h-400*g,i+170*g]),c.translate([h-190*g,i+200*g]),d.translate([h+580*g,i+430*g]),e},e.scale(a.scale())},d3.geo.bonne=function(){function g(g){var h=g[0]*eN-c,i=g[1]*eN-d;if(e){var j=f+e-i,k=h*Math.cos(i)/j;h=j*Math.sin(k),i=j*Math.cos(k)-f}else h*=Math.cos(i),i*=-1;return[a*h+b[0],a*i+b[1]]}var a=200,b=[480,250],c,d,e,f;return g.invert=function(d){var g=(d[0]-b[0])/a,h=(d[1]-b[1])/a;if(e){var i=f+h,j=Math.sqrt(g*g+i*i);h=f+e-j,g=c+j*Math.atan2(g,i)/Math.cos(h)}else h*=-1,g/=Math.cos(h);return[g/eN,h/eN]},g.parallel=function(a){return arguments.length?(f=1/Math.tan(e=a*eN),g):e/eN},g.origin=function(a){return arguments.length?(c=a[0]*eN,d=a[1]*eN,g):[c/eN,d/eN]},g.scale=function(b){return arguments.length?(a=+b,g):a},g.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],g):b},g.origin([0,0]).parallel(45)},d3.geo.equirectangular=function(){function c(c){var d=c[0]/360,e=-c[1]/360;return[a*d+b[0],a*e+b[1]]}var a=500,b=[480,250];return c.invert=function(c){var d=(c[0]-b[0])/a,e=(c[1]-b[1])/a;return[360*d,-360*e]},c.scale=function(b){return arguments.length?(a=+b,c):a},c.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],c):b},c},d3.geo.mercator=function(){function c(c){var d=c[0]/360,e=-(Math.log(Math.tan(Math.PI/4+c[1]*eN/2))/eN)/360;return[a*d+b[0],a*Math.max(-0.5,Math.min(.5,e))+b[1]]}var a=500,b=[480,250];return c.invert=function(c){var d=(c[0]-b[0])/a,e=(c[1]-b[1])/a;return[360*d,2*Math.atan(Math.exp(-360*e*eN))/eN-90]},c.scale=function(b){return arguments.length?(a=+b,c):a},c.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],c):b},c},d3.geo.path=function(){function e(c,e){typeof a=="function"&&(b=eP(a.apply(this,arguments))),g(c);var f=d.length?d.join(""):null;return d=[],f}function f(a){return c(a).join(",")}function i(a){var b=l(a[0]),c=0,d=a.length;while(++c0){d.push("M");while(++h0){d.push("M");while(++kd&&(d=a),fe&&(e=f)}),[[b,c],[d,e]]};var eR={Feature:eS,FeatureCollection:eT,GeometryCollection:eU,LineString:eV,MultiLineString:eW,MultiPoint:eV,MultiPolygon:eX,Point:eY,Polygon:eZ};d3.geo.circle=function(){function e(){}function f(a){return d.distance(a)=k*k+l*l?d[f].index=-1:(d[m].index=-1,o=d[f].angle,m=f,n=g)):(o=d[f].angle,m=f,n=g);e.push(h);for(f=0,g=0;f<2;++g)d[g].index!==-1&&(e.push(d[g].index),f++);p=e.length;for(;g=0?(c=a.ep.r,d=a.ep.l):(c=a.ep.l,d=a.ep.r),a.a===1?(g=c?c.y:-1e6,e=a.c-a.b*g,h=d?d.y:1e6,f=a.c-a.b*h):(e=c?c.x:-1e6,g=a.c-a.a*e,f=d?d.x:1e6,h=a.c-a.a*f);var i=[e,g],j=[f,h];b[a.region.l.index].push(i,j),b[a.region.r.index].push(i,j)}),b.map(function(b,c){var d=a[c][0],e=a[c][1];return b.forEach(function(a){a.angle=Math.atan2(a[0]-d,a[1]-e)}),b.sort(function(a,b){return a.angle-b.angle}).filter(function(a,c){return!c||a.angle-b[c-1].angle>1e-10})})};var fi={l:"r",r:"l"};d3.geom.delaunay=function(a){var b=a.map(function(){return[]}),c=[];return fj(a,function(c){b[c.region.l.index].push(a[c.region.r.index])}),b.forEach(function(b,d){var e=a[d],f=e[0],g=e[1];b.forEach(function(a){a.angle=Math.atan2(a[0]-f,a[1]-g)}),b.sort(function(a,b){return a.angle-b.angle});for(var h=0,i=b.length-1;h=g,j=b.y>=h,l=(j<<1)+i;a.leaf=!1,a=a.nodes[l]||(a.nodes[l]=fk()),i?c=g:e=g,j?d=h:f=h,k(a,b,c,d,e,f)}var f,g=-1,h=a.length;h&&isNaN(a[0].x)&&(a=a.map(fm));if(arguments.length<5)if(arguments.length===3)e=d=c,c=b;else{b=c=Infinity,d=e=-Infinity;while(++gd&&(d=f.x),f.y>e&&(e=f.y);var i=d-b,j=e-c;i>j?e=c+i:d=b+j}var m=fk();return m.add=function(a){k(m,a,b,c,d,e)},m.visit=function(a){fl(a,m,b,c,d,e)},a.forEach(m.add),m},d3.time={};var fn=Date;fo.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){fp.setUTCDate.apply(this._,arguments)},setDay:function(){fp.setUTCDay.apply(this._,arguments)},setFullYear:function(){fp.setUTCFullYear.apply(this._,arguments)},setHours:function(){fp.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){fp.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){fp.setUTCMinutes.apply(this._,arguments)},setMonth:function(){fp.setUTCMonth.apply(this._,arguments)},setSeconds:function(){fp.setUTCSeconds.apply(this._,arguments)},setTime:function(){fp.setTime.apply(this._,arguments)}};var fp=Date.prototype;d3.time.format=function(a){function c(c){var d=[],e=-1,f=0,g,h;while(++e=12?"PM":"AM"},S:function(a){return fr(a.getSeconds())},U:function(a){return fr(d3.time.sundayOfYear(a))},w:function(a){return a.getDay()},W:function(a){return fr(d3.time.mondayOfYear(a))},x:d3.time.format("%m/%d/%y"),X:d3.time.format("%H:%M:%S"),y:function(a){return fr(a.getFullYear()%100)},Y:function(a){return ft(a.getFullYear()%1e4)},Z:fX,"%":function(a){return"%"}},fw={a:fx,A:fy,b:fC,B:fE,c:fI,d:fP,e:fP,H:fQ,I:fQ,L:fT,m:fO,M:fR,p:fV,S:fS,x:fJ,X:fK,y:fM,Y:fL},fz=/^(?:sun|mon|tue|wed|thu|fri|sat)/i,fA=/^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/i,fB=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],fD=d3.map({jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11}),fF=/^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig,fG=d3.map({january:0,february:1,march:2,april:3,may:4,june:5,july:6,august:7,september:8,october:9,november:10,december:11}),fH=["January","February","March","April","May","June","July","August","September","October","November","December"],fU=/\s*\d+/,fW=d3.map({am:0,pm:1});d3.time.format.utc=function(a){function c(a){try{fn=fo;var c=new fn;return c._=a,b(c)}finally{fn=Date}}var b=d3.time.format(a);return c.parse=function(a){try{fn=fo;var c=b.parse(a);return c&&c._}finally{fn=Date}},c.toString=b.toString,c};var fY=d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");d3.time.format.iso=Date.prototype.toISOString?fZ:fY,fZ.parse=function(a){var b=new Date(a);return isNaN(b)?null:b},fZ.toString=fY.toString,d3.time.second=f$(function(a){return new fn(Math.floor(a/1e3)*1e3)},function(a,b){a.setTime(a.getTime()+Math.floor(b)*1e3)},function(a){return a.getSeconds()}),d3.time.seconds=d3.time.second.range,d3.time.seconds.utc=d3.time.second.utc.range,d3.time.minute=f$(function(a){return new fn(Math.floor(a/6e4)*6e4)},function(a,b){a.setTime(a.getTime()+Math.floor(b)*6e4)},function(a){return a.getMinutes()}),d3.time.minutes=d3.time.minute.range,d3.time.minutes.utc=d3.time.minute.utc.range,d3.time.hour=f$(function(a){var b=a.getTimezoneOffset()/60;return new fn((Math.floor(a/36e5-b)+b)*36e5)},function(a,b){a.setTime(a.getTime()+Math.floor(b)*36e5)},function(a){return a.getHours()}),d3.time.hours=d3.time.hour.range,d3.time.hours.utc=d3.time.hour.utc.range,d3.time.day=f$(function(a){return new fn(a.getFullYear(),a.getMonth(),a.getDate())},function(a,b){a.setDate(a.getDate()+b)},function(a){return a.getDate()-1}),d3.time.days=d3.time.day.range,d3.time.days.utc=d3.time.day.utc.range,d3.time.dayOfYear=function(a){var b=d3.time.year(a);return Math.floor((a-b)/864e5-(a.getTimezoneOffset()-b.getTimezoneOffset())/1440)},fB.forEach(function(a,b){a=a.toLowerCase(),b=7-b;var c=d3.time[a]=f$(function(a){return(a=d3.time.day(a)).setDate(a.getDate()-(a.getDay()+b)%7),a},function(a,b){a.setDate(a.getDate()+Math.floor(b)*7)},function(a){var c=d3.time.year(a).getDay();return Math.floor((d3.time.dayOfYear(a)+(c+b)%7)/7)-(c!==b)});d3.time[a+"s"]=c.range,d3.time[a+"s"].utc=c.utc.range,d3.time[a+"OfYear"]=function(a){var c=d3.time.year(a).getDay();return Math.floor((d3.time.dayOfYear(a)+(c+b)%7)/7)}}),d3.time.week=d3.time.sunday,d3.time.weeks=d3.time.sunday.range,d3.time.weeks.utc=d3.time.sunday.utc.range,d3.time.weekOfYear=d3.time.sundayOfYear,d3.time.month=f$(function(a){return new fn(a.getFullYear(),a.getMonth(),1)},function(a,b){a.setMonth(a.getMonth()+b)},function(a){return a.getMonth()}),d3.time.months=d3.time.month.range,d3.time.months.utc=d3.time.month.utc.range,d3.time.year=f$(function(a){return new fn(a.getFullYear(),0,1)},function(a,b){a.setFullYear(a.getFullYear()+b)},function(a){return a.getFullYear()}),d3.time.years=d3.time.year.range,d3.time.years.utc=d3.time.year.utc.range;var gg=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],gh=[[d3.time.second,1],[d3.time.second,5],[d3.time.second,15],[d3.time.second,30],[d3.time.minute,1],[d3.time.minute,5],[d3.time.minute,15],[d3.time.minute,30],[d3.time.hour,1],[d3.time.hour,3],[d3.time.hour,6],[d3.time.hour,12],[d3.time.day,1],[d3.time.day,2],[d3.time.week,1],[d3.time.month,1],[d3.time.month,3],[d3.time.year,1]],gi=[[d3.time.format("%Y"),function(a){return!0}],[d3.time.format("%B"),function(a){return a.getMonth()}],[d3.time.format("%b %d"),function(a){return a.getDate()!=1}],[d3.time.format("%a %d"),function(a){return a.getDay()&&a.getDate()!=1}],[d3.time.format("%I %p"),function(a){return a.getHours()}],[d3.time.format("%I:%M"),function(a){return a.getMinutes()}],[d3.time.format(":%S"),function(a){return a.getSeconds()}],[d3.time.format(".%L"),function(a){return a.getMilliseconds()}]],gj=d3.scale.linear(),gk=gd(gi);gh.year=function(a,b){return gj.domain(a.map(gf)).ticks(b).map(ge)},d3.time.scale=function(){return ga(d3.scale.linear(),gh,gk)};var gl=gh.map(function(a){return[a[0].utc,a[1]]}),gm=[[d3.time.format.utc("%Y"),function(a){return!0}],[d3.time.format.utc("%B"),function(a){return a.getUTCMonth()}],[d3.time.format.utc("%b %d"),function(a){return a.getUTCDate()!=1}],[d3.time.format.utc("%a %d"),function(a){return a.getUTCDay()&&a.getUTCDate()!=1}],[d3.time.format.utc("%I %p"),function(a){return a.getUTCHours()}],[d3.time.format.utc("%I:%M"),function(a){return a.getUTCMinutes()}],[d3.time.format.utc(":%S"),function(a){return a.getUTCSeconds()}],[d3.time.format.utc(".%L"),function(a){return a.getUTCMilliseconds()}]],gn=gd(gm);gl.year=function(a,b){return gj.domain(a.map(gp)).ticks(b).map(go)},d3.time.scale.utc=function(){return ga(d3.scale.linear(),gl,gn)}})(); \ No newline at end of file diff --git a/embed/js/iframe-embed.js b/embed/js/iframe-embed.js new file mode 100644 index 0000000..f122707 --- /dev/null +++ b/embed/js/iframe-embed.js @@ -0,0 +1,189 @@ +/* + +Online Python Tutor +https://github.com/pgbovine/OnlinePythonTutor/ + +Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + + +// Pre-reqs: +// - pytutor.js +// - jquery.ba-bbq.min.js +// - opt-frontend-common.js +// should all be imported BEFORE this file + + +var myVisualizer = null; // singleton ExecutionVisualizer instance + + +function NOP() {}; + + +$(document).ready(function() { + var queryStrOptions = getQueryStringOptions(); + + var preseededCode = queryStrOptions.preseededCode; + var pyState = queryStrOptions.pyState; + var verticalStackBool = (queryStrOptions.verticalStack == 'true'); + var heapPrimitivesBool = (queryStrOptions.heapPrimitives == 'true'); + var drawParentPointerBool = (queryStrOptions.drawParentPointers == 'true'); + var textRefsBool = (queryStrOptions.textRefs == 'true'); + var showOnlyOutputsBool = (queryStrOptions.showOnlyOutputs == 'true'); + var cumModeBool = (queryStrOptions.cumulativeState == 'true'); + + var codeDivWidth = undefined; + var codeDivWidth = 350; + var cdw = $.bbq.getState('codeDivWidth'); + var cdw = $.bbq.getState('width'); + if (cdw) { + codeDivWidth = Number(cdw); + } + + var codeDivHeight = undefined; + var cdh = $.bbq.getState('codeDivHeight'); + if (cdh) { + codeDivHeight = Number(cdh); + } + + + var startingInstruction = queryStrOptions.preseededCurInstr; + if (!startingInstruction) { + startingInstruction = 0; + } + + var backend_script = null; + if (pyState == '2') { + backend_script = python2_backend_script; + } + else if (pyState == '3') { + backend_script = python3_backend_script; + } + else if (pyState == '2crazy') { + backend_script = python2crazy_backend_script; + } + + + // David Pritchard's code for resizeContainer option ... + var resizeContainer = ($.bbq.getState('resizeContainer') == 'true'); + + if (resizeContainer) { + function findContainer() { + try { + var ifs = window.top.document.getElementsByTagName("iframe"); + for(var i = 0, len = ifs.length; i < len; i++) { + var f = ifs[i]; + var fDoc = f.contentDocument || f.contentWindow.document; + if(fDoc === document) { + return f; + } + } + } catch (e) { + // ignore SecurityError + } + } + + var container = findContainer(); + + function resizeContainerNow() { + $(container).height($("html").height()); + }; + } + + // set up all options in a JS object + var backendOptionsObj = {cumulative_mode: cumModeBool, + heap_primitives: heapPrimitivesBool, + show_only_outputs: showOnlyOutputsBool, + py_crazy_mode: (pyState == '2crazy'), + origin: 'iframe-embed.js'}; + + var frontendOptionsObj = {startingInstruction: startingInstruction, + embeddedMode: true, + verticalStack: verticalStackBool, + disableHeapNesting: true, + drawParentPointers: drawParentPointerBool, + textualMemoryLabels: textRefsBool, + showOnlyOutputs: showOnlyOutputsBool, + executeCodeWithRawInputFunc: executeCodeWithRawInput, + heightChangeCallback: (resizeContainer ? resizeContainerNow : NOP), + + // undocumented experimental modes: + pyCrazyMode: (pyState == '2crazy'), + highlightLines: typeof $.bbq.getState("highlightLines") !== "undefined", + codeDivWidth: codeDivWidth, + codeDivHeight: codeDivHeight, + } + + function executeCode(forceStartingInstr) { + if (forceStartingInstr) { + frontendOptionsObj.startingInstruction = forceStartingInstr; + } + executePythonCode(preseededCode, + backend_script, backendOptionsObj, + frontendOptionsObj, + 'vizDiv', + function() { // success +/* if (serverReply.stdin != "") { + var stdinHTML = '
stdin:
'; + $('#dataViz').append(stdinHTML); + $("#stdinShow").html(serverReply.stdin); + }*/ + if ($.bbq.getState('rightStdout')) { + $("#progOutputs").prependTo("#dataViz"); + }; + if (resizeContainer) + resizeContainerNow(); + }, + NOP); + } + + + function executeCodeFromScratch() { + // reset these globals + rawInputLst = []; + executeCode(); + } + + function executeCodeWithRawInput(rawInputStr, curInstr) { + // set some globals + rawInputLst.push(rawInputStr); + executeCode(curInstr); + } + + + // log a generic AJAX error handler + $(document).ajaxError(function() { + alert("Ugh, Online Python Tutor server error :("); + }); + + + // redraw connector arrows on window resize + $(window).resize(function() { + myVisualizer.redrawConnectors(); + }); + + executeCodeFromScratch(); // finally, execute code and display visualization + + +}); + diff --git a/embed/js/jquery-1.8.2.min.js b/embed/js/jquery-1.8.2.min.js new file mode 100644 index 0000000..f65cf1d --- /dev/null +++ b/embed/js/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/embed/js/jquery-ui-1.8.24.custom.min.js b/embed/js/jquery-ui-1.8.24.custom.min.js new file mode 100644 index 0000000..7d53c3a --- /dev/null +++ b/embed/js/jquery-ui-1.8.24.custom.min.js @@ -0,0 +1,25 @@ +/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.core.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.24",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this._mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.position.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),a.curCSS||(a.curCSS=a.css),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.resizable.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e
');h.css({zIndex:c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){if(c.disabled)return;a(this).removeClass("ui-resizable-autohide"),b._handles.show()},function(){if(c.disabled)return;b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement),this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");return a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b),!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);return l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui()),!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}return a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),ea.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;return p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null),a},_proportionallyResize:function(){var b=this.options;if(!this._proportionallyResizeElements.length)return;var c=this.helper||this.element;for(var d=0;d');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.24"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!i)return;e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/d.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*d.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.slider.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("
").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;ic&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i),j===!1?!1:(this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0,!0))},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);return this._slide(a,this._handleIndex,c),!1},_mouseStop:function(a){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;return this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e,this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};return this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c1){this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);return}if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;return Math.abs(c)*2>=b&&(d+=c>0?b:-b),parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.24"})})(jQuery);; diff --git a/embed/js/jquery.ba-bbq.min.js b/embed/js/jquery.ba-bbq.min.js new file mode 100644 index 0000000..bcbf248 --- /dev/null +++ b/embed/js/jquery.ba-bbq.min.js @@ -0,0 +1,18 @@ +/* + * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010 + * http://benalman.com/projects/jquery-bbq-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(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); \ No newline at end of file diff --git a/embed/js/jquery.jsPlumb-1.3.10-all-min.js b/embed/js/jquery.jsPlumb-1.3.10-all-min.js new file mode 100644 index 0000000..3171abe --- /dev/null +++ b/embed/js/jquery.jsPlumb-1.3.10-all-min.js @@ -0,0 +1 @@ +jsPlumbUtil={isArray:function(b){return Object.prototype.toString.call(b)==="[object Array]"},isString:function(a){return typeof a==="string"},isObject:function(a){return Object.prototype.toString.call(a)==="[object Object]"},convertStyle:function(b,a){if("transparent"===b){return b}var g=b,f=function(h){return h.length==1?"0"+h:h},c=function(h){return f(Number(h).toString(16))},d=/(rgb[a]?\()(.*)(\))/;if(b.match(d)){var e=b.match(d)[2].split(",");g="#"+c(e[0])+c(e[1])+c(e[2]);if(!a&&e.length==4){g=g+c(e[3])}}return g},gradient:function(b,a){b=jsPlumbUtil.isArray(b)?b:[b.x,b.y];a=jsPlumbUtil.isArray(a)?a:[a.x,a.y];return(a[1]-b[1])/(a[0]-b[0])},normal:function(b,a){return -1/jsPlumbUtil.gradient(b,a)},lineLength:function(b,a){b=jsPlumbUtil.isArray(b)?b:[b.x,b.y];a=jsPlumbUtil.isArray(a)?a:[a.x,a.y];return Math.sqrt(Math.pow(a[1]-b[1],2)+Math.pow(a[0]-b[0],2))},segment:function(b,a){b=jsPlumbUtil.isArray(b)?b:[b.x,b.y];a=jsPlumbUtil.isArray(a)?a:[a.x,a.y];if(a[0]>b[0]){return(a[1]>b[1])?2:1}else{return(a[1]>b[1])?3:4}},intersects:function(f,e){var c=f.x,a=f.x+f.w,k=f.y,h=f.y+f.h,d=e.x,b=e.x+e.w,i=e.y,g=e.y+e.h;return((c<=d&&d<=a)&&(k<=i&&i<=h))||((c<=b&&b<=a)&&(k<=i&&i<=h))||((c<=d&&d<=a)&&(k<=g&&g<=h))||((c<=b&&d<=a)&&(k<=g&&g<=h))||((d<=c&&c<=b)&&(i<=k&&k<=g))||((d<=a&&a<=b)&&(i<=k&&k<=g))||((d<=c&&c<=b)&&(i<=h&&h<=g))||((d<=a&&c<=b)&&(i<=h&&h<=g))},segmentMultipliers:[null,[1,-1],[1,1],[-1,1],[-1,-1]],inverseSegmentMultipliers:[null,[-1,-1],[-1,1],[1,1],[1,-1]],pointOnLine:function(a,e,b){var d=jsPlumbUtil.gradient(a,e),i=jsPlumbUtil.segment(a,e),h=b>0?jsPlumbUtil.segmentMultipliers[i]:jsPlumbUtil.inverseSegmentMultipliers[i],c=Math.atan(d),f=Math.abs(b*Math.sin(c))*h[1],g=Math.abs(b*Math.cos(c))*h[0];return{x:a.x+g,y:a.y+f}},perpendicularLineTo:function(c,d,e){var b=jsPlumbUtil.gradient(c,d),f=Math.atan(-1/b),g=e/2*Math.sin(f),a=e/2*Math.cos(f);return[{x:d.x+a,y:d.y+g},{x:d.x-a,y:d.y-g}]},findWithFunction:function(b,d){if(b){for(var c=0;c-1){c.splice(b,1)}return b!=-1},remove:function(b,c){var a=jsPlumbUtil.indexOf(b,c);if(a>-1){b.splice(a,1)}return a!=-1},addWithFunction:function(c,b,a){if(jsPlumbUtil.findWithFunction(c,a)==-1){c.push(b)}},addToList:function(d,b,c){var a=d[b];if(a==null){a=[],d[b]=a}a.push(c);return a},EventGenerator:function(){var c={},b=this;var a=["ready"];this.bind=function(d,e){jsPlumbUtil.addToList(c,d,e);return b};this.fire=function(g,h,d){if(c[g]){for(var f=0;f';var K=L.firstChild;K.style.behavior="url(#default#VML)";b.vml=K?typeof K.adj=="object":true;L.parentNode.removeChild(L)}return b.vml};var i=jsPlumbUtil.findWithFunction,J=jsPlumbUtil.indexOf,D=jsPlumbUtil.removeWithFunction,m=jsPlumbUtil.remove,u=jsPlumbUtil.addWithFunction,l=jsPlumbUtil.addToList,n=jsPlumbUtil.isArray,C=jsPlumbUtil.isString,w=jsPlumbUtil.isObject;if(!window.console){window.console={time:function(){},timeEnd:function(){},group:function(){},groupEnd:function(){},log:function(){}}}var x=null,d=function(K,L){return p.CurrentLibrary.getAttribute(F(K),L)},f=function(L,M,K){p.CurrentLibrary.setAttribute(F(L),M,K)},B=function(L,K){p.CurrentLibrary.addClass(F(L),K)},k=function(L,K){return p.CurrentLibrary.hasClass(F(L),K)},o=function(L,K){p.CurrentLibrary.removeClass(F(L),K)},F=function(K){return p.CurrentLibrary.getElementObject(K)},t=function(K){return p.CurrentLibrary.getOffset(F(K))},a=function(K){return p.CurrentLibrary.getSize(F(K))},q=jsPlumbUtil.log,I=jsPlumbUtil.group,h=jsPlumbUtil.groupEnd,H=jsPlumbUtil.time,v=jsPlumbUtil.timeEnd,r=function(){return""+(new Date()).getTime()},E=function(Z){var U=this,aa=arguments,R=false,O=Z.parameters||{},M=U.idPrefix,W=M+(new Date()).getTime(),V=null,ab=null;U._jsPlumb=Z._jsPlumb;U.getId=function(){return W};U.tooltip=Z.tooltip;U.hoverClass=Z.hoverClass||U._jsPlumb.Defaults.HoverClass||p.Defaults.HoverClass;jsPlumbUtil.EventGenerator.apply(this);this.clone=function(){var ac=new Object();U.constructor.apply(ac,aa);return ac};this.getParameter=function(ac){return O[ac]},this.getParameters=function(){return O},this.setParameter=function(ac,ad){O[ac]=ad},this.setParameters=function(ac){O=ac},this.overlayPlacements=[];var N=Z.beforeDetach;this.isDetachAllowed=function(ac){var ad=U._jsPlumb.checkCondition("beforeDetach",ac);if(N){try{ad=N(ac)}catch(ae){q("jsPlumb: beforeDetach callback failed",ae)}}return ad};var Q=Z.beforeDrop;this.isDropAllowed=function(ah,ae,af,ac,ad){var ag=U._jsPlumb.checkCondition("beforeDrop",{sourceId:ah,targetId:ae,scope:af,connection:ac,dropEndpoint:ad});if(Q){try{ag=Q({sourceId:ah,targetId:ae,scope:af,connection:ac,dropEndpoint:ad})}catch(ai){q("jsPlumb: beforeDrop callback failed",ai)}}return ag};var X=function(){if(V&&ab){var ac={};p.extend(ac,V);p.extend(ac,ab);delete U.hoverPaintStyle;if(ac.gradient&&V.fillStyle){delete ac.gradient}ab=ac}};this.setPaintStyle=function(ac,ad){V=ac;U.paintStyleInUse=V;X();if(!ad){U.repaint()}};this.getPaintStyle=function(){return V};this.setHoverPaintStyle=function(ac,ad){ab=ac;X();if(!ad){U.repaint()}};this.getHoverPaintStyle=function(){return ab};this.setHover=function(ac,ae,ad){if(!U._jsPlumb.currentlyDragging&&!U._jsPlumb.isHoverSuspended()){R=ac;if(U.hoverClass!=null&&U.canvas!=null){if(ac){L.addClass(U.canvas,U.hoverClass)}else{L.removeClass(U.canvas,U.hoverClass)}}if(ab!=null){U.paintStyleInUse=ac?ab:V;ad=ad||r();U.repaint({timestamp:ad,recalc:false})}if(U.getAttachedElements&&!ae){Y(ac,r(),U)}}};this.isHover=function(){return R};var L=p.CurrentLibrary,K=["click","dblclick","mouseenter","mouseout","mousemove","mousedown","mouseup","contextmenu"],T={mouseout:"mouseexit"},P=function(ae,af,ad){var ac=T[ad]||ad;L.bind(ae,ad,function(ag){af.fire(ac,af,ag)})},S=function(ae,ad){var ac=T[ad]||ad;L.unbind(ae,ad)};this.attachListeners=function(ad,ae){for(var ac=0;ac1){for(var ac=0;ac=0?U.overlays[V]:null};this.getOverlays=function(){return U.overlays};this.hideOverlay=function(W){var V=U.getOverlay(W);if(V){V.hide()}};this.hideOverlays=function(){for(var V=0;V0){try{for(var bw=0;bw0?J(bJ,bI)!=-1:true},bA=(!bw&&bD.length>1)?{}:[],bG=function(bJ,bK){if(!bw&&bD.length>1){var bI=bA[bJ];if(bI==null){bI=[];bA[bJ]=bI}bI.push(bK)}else{bA.push(bK)}};for(var bz in aY){if(bx(bD,bz)){for(var by=0;by=4)?[bA[2],bA[3]]:[0,0],offsets:(bA.length==6)?[bA[4],bA[5]]:[0,0],elementId:bx};by=new aa(bz);by.clone=function(){return new aa(bz)}}}}}if(!by.id){by.id="anchor_"+ak()}return by};this.makeAnchors=function(by,bw,bv){var bz=[];for(var bx=0;bx0&&bP>=ap[bI]){console.log("target element "+bI+" is full.");return false}bn.currentlyDragging=false;var bZ=F(bD.getDragObject(arguments)),bO=d(bZ,"dragId"),bX=d(bZ,"originalScope"),bU=bf[bO],bM=bU.endpoints[0],bL=bw.endpoint?p.extend({},bw.endpoint):{};bM.anchor.locked=false;if(bX){bD.setDragScope(bZ,bX)}var bS=proxyComponent.isDropAllowed(bU.sourceId,K(bK),bU.scope,bU,null);if(bU.endpointsToDeleteOnDetach){if(bM===bU.endpointsToDeleteOnDetach[0]){bU.endpointsToDeleteOnDetach[0]=null}else{if(bM===bU.endpointsToDeleteOnDetach[1]){bU.endpointsToDeleteOnDetach[1]=null}}}if(bU.suspendedEndpoint){bU.targetId=bU.suspendedEndpoint.elementId;bU.target=bD.getElementObject(bU.suspendedEndpoint.elementId);bU.endpoints[1]=bU.suspendedEndpoint}if(bS){bM.detach(bU,false,true,false);var bY=aH[bI]||bn.addEndpoint(bK,bw);if(bw.uniqueEndpoint){aH[bI]=bY}bY._makeTargetCreator=true;if(bY.anchor.positionFinder!=null){var bV=bD.getUIPosition(arguments),bR=bD.getOffset(bK),bW=bD.getSize(bK),bQ=bY.anchor.positionFinder(bV,bR,bW,bY.anchor.constructorParams);bY.anchor.x=bQ[0];bY.anchor.y=bQ[1]}var bT=bn.connect({source:bM,target:bY,scope:bX,previousConnection:bU,container:bU.parent,deleteEndpointsOnDetach:bA,doNotFireConnectionEvent:bM.endpointWillMoveAfterConnection});if(bU.endpoints[1]._makeTargetCreator&&bU.endpoints[1].connections.length<2){bn.deleteEndpoint(bU.endpoints[1])}if(bA){bT.endpointsToDeleteOnDetach=[bM,bY]}bT.repaint()}else{if(bU.suspendedEndpoint){if(bM.isReattach){bU.setHover(false);bU.floatingAnchorIndex=null;bU.suspendedEndpoint.addConnection(bU);bn.repaint(bM.elementId)}else{bM.detach(bU,false,true,true,bN)}}}};var bJ=bD.dragEvents.drop;bH.scope=bH.scope||bE;bH[bJ]=am(bH[bJ],bG);bD.initDroppable(bK,bH,true)};by=aI(by);var bC=by.length&&by.constructor!=String?by:[by];for(var bB=0;bB0?bF[0]:null,bA=bF.length>0?0:-1,bE=this,bz=function(bI,bG,bM,bL,bH){var bK=bL[0]+(bI.x*bH[0]),bJ=bL[1]+(bI.y*bH[1]);return Math.sqrt(Math.pow(bG-bK,2)+Math.pow(bM-bJ,2))},bv=bw||function(bQ,bH,bI,bJ,bG){var bL=bI[0]+(bJ[0]/2),bK=bI[1]+(bJ[1]/2);var bN=-1,bP=Infinity;for(var bM=0;bM=by.left)||(bB.left<=by.right&&bB.right>=by.right)||(bB.left<=by.left&&bB.right>=by.right)||(by.left<=bB.left&&by.right>=bB.right)),bG=((bB.top<=by.top&&bB.bottom>=by.top)||(bB.top<=by.bottom&&bB.bottom>=by.bottom)||(bB.top<=by.top&&bB.bottom>=by.bottom)||(by.top<=bB.top&&by.bottom>=bB.bottom));if(!(bA||bG)){var bD=null,bx=false,bv=false,bC=null;if(by.left>bB.left&&by.top>bB.top){bD=["right","top"]}else{if(by.left>bB.left&&bB.top>by.top){bD=["top","left"]}else{if(by.leftbB.top){bD=["left","top"]}}}}return{orientation:T.DIAGONAL,a:bD,theta:bw,theta2:bz}}else{if(bA){return{orientation:T.HORIZONTAL,a:bB.topbv[0]?1:-1},Z=function(bv){return function(bx,bw){var by=true;if(bv){if(bx[0][0]bw[0][1]}}else{if(bx[0][0]>bw[0][0]){by=true}else{by=bx[0][1]>bw[0][1]}}return by===false?-1:1}},O=function(bw,bv){var by=bw[0][0]<0?-Math.PI-bw[0][0]:Math.PI-bw[0][0],bx=bv[0][0]<0?-Math.PI-bv[0][0]:Math.PI-bv[0][0];if(by>bx){return 1}else{return bw[0][1]>bv[0][1]?1:-1}},a0={top:a8,right:Z(true),bottom:Z(true),left:O},ao=function(bv,bw){return bv.sort(bw)},al=function(bw,bv){var by=ae[bw],bz=ah[bw],bx=function(bG,bN,bC,bF,bL,bK,bB){if(bF.length>0){var bJ=ao(bF,a0[bG]),bH=bG==="right"||bG==="top",bA=a2(bG,bN,bC,bJ,bL,bK,bH);var bO=function(bR,bQ){var bP=bo([bQ[0],bQ[1]],bR.canvas);ai[bR.id]=[bP[0],bP[1],bQ[2],bQ[3]];aJ[bR.id]=bB};for(var bD=0;bD0){var bF=bA.getOffset(bG);bw[bD][bI]={id:bI,offset:{left:bF.left-bJ.left,top:bF.top-bJ.top}}}}}};bC(bz)};this.endpointAdded=function(bB){var bF=p.CurrentLibrary,bI=document.body,bz=bn.getId(bB),bH=bF.getDOMElement(bB),bA=bH.parentNode,bD=bA==bI;bv[bz]=bv[bz]?bv[bz]+1:1;while(bA!=bI){var bE=bn.getId(bA);if(by[bE]){var bK=-1,bG=bF.getElementObject(bA),bC=bF.getOffset(bG);if(bw[bE][bz]==null){var bJ=p.CurrentLibrary.getOffset(bB);bw[bE][bz]={id:bz,offset:{left:bJ.left-bC.left,top:bJ.top-bC.top}}}break}bA=bA.parentNode}};this.endpointDeleted=function(bA){if(bv[bA.elementId]){bv[bA.elementId]--;if(bv[bA.elementId]<=0){for(var bz in bw){delete bw[bz][bA.elementId]}}}};this.getElementsForDraggable=function(bz){return bw[bz]};this.reset=function(){by={};bx=[];bw={};bv={}}};bn.dragManager=new aV();var ax=function(bN){var bG=this,bx=true;bG.idPrefix="_jsplumb_c_";bG.defaultLabelLocation=0.5;bG.defaultOverlayKeys=["Overlays","ConnectionOverlays"];this.parent=bN.parent;z.apply(this,arguments);this.isVisible=function(){return bx};this.setVisible=function(bP){bx=bP;bG[bP?"showOverlays":"hideOverlays"]();if(bG.connector&&bG.connector.canvas){bG.connector.canvas.style.display=bP?"block":"none"}};this.source=F(bN.source);this.target=F(bN.target);if(bN.sourceEndpoint){this.source=bN.sourceEndpoint.endpointWillMoveTo||bN.sourceEndpoint.getElement()}if(bN.targetEndpoint){this.target=bN.targetEndpoint.getElement()}bG.previousConnection=bN.previousConnection;var bD=bN.cost;bG.getCost=function(){return bD};bG.setCost=function(bP){bD=bP};var bB=bN.bidirectional===false?false:true;bG.isBidirectional=function(){return bB};this.sourceId=d(this.source,"id");this.targetId=d(this.target,"id");this.getAttachedElements=function(){return bG.endpoints};this.scope=bN.scope;this.endpoints=[];this.endpointStyles=[];var bM=function(bQ,bP){if(bQ){return bn.makeAnchor(bQ,bP,bn)}},bK=function(bP,bV,bQ,bS,bT,bR,bU){if(bP){bG.endpoints[bV]=bP;bP.addConnection(bG)}else{if(!bQ.endpoints){bQ.endpoints=[null,null]}var b1=bQ.endpoints[bV]||bQ.endpoint||bn.Defaults.Endpoints[bV]||p.Defaults.Endpoints[bV]||bn.Defaults.Endpoint||p.Defaults.Endpoint;if(!bQ.endpointStyles){bQ.endpointStyles=[null,null]}if(!bQ.endpointHoverStyles){bQ.endpointHoverStyles=[null,null]}var bZ=bQ.endpointStyles[bV]||bQ.endpointStyle||bn.Defaults.EndpointStyles[bV]||p.Defaults.EndpointStyles[bV]||bn.Defaults.EndpointStyle||p.Defaults.EndpointStyle;if(bZ.fillStyle==null&&bR!=null){bZ.fillStyle=bR.strokeStyle}if(bZ.outlineColor==null&&bR!=null){bZ.outlineColor=bR.outlineColor}if(bZ.outlineWidth==null&&bR!=null){bZ.outlineWidth=bR.outlineWidth}var bY=bQ.endpointHoverStyles[bV]||bQ.endpointHoverStyle||bn.Defaults.EndpointHoverStyles[bV]||p.Defaults.EndpointHoverStyles[bV]||bn.Defaults.EndpointHoverStyle||p.Defaults.EndpointHoverStyle;if(bU!=null){if(bY==null){bY={}}if(bY.fillStyle==null){bY.fillStyle=bU.strokeStyle}}var bX=bQ.anchors?bQ.anchors[bV]:bQ.anchor?bQ.anchor:bM(bn.Defaults.Anchors[bV],bT)||bM(p.Defaults.Anchors[bV],bT)||bM(bn.Defaults.Anchor,bT)||bM(p.Defaults.Anchor,bT),b0=bQ.uuids?bQ.uuids[bV]:null,bW=aF({paintStyle:bZ,hoverPaintStyle:bY,endpoint:b1,connections:[bG],uuid:b0,anchor:bX,source:bS,scope:bQ.scope,container:bQ.container,reattach:bQ.reattach,detachable:bQ.detachable});bG.endpoints[bV]=bW;if(bQ.drawEndpoints===false){bW.setVisible(false,true,true)}return bW}};var bI=bK(bN.sourceEndpoint,0,bN,bG.source,bG.sourceId,bN.paintStyle,bN.hoverPaintStyle);if(bI){V(aT,this.sourceId,bI)}var by=((bG.sourceId==bG.targetId)&&bN.targetEndpoint==null)?bI:bN.targetEndpoint,bH=bK(by,1,bN,bG.target,bG.targetId,bN.paintStyle,bN.hoverPaintStyle);if(bH){V(aT,this.targetId,bH)}if(!this.scope){this.scope=this.endpoints[0].scope}if(bN.deleteEndpointsOnDetach){bG.endpointsToDeleteOnDetach=[bI,bH]}var bw=bn.Defaults.ConnectionsDetachable;if(bN.detachable===false){bw=false}if(bG.endpoints[0].connectionsDetachable===false){bw=false}if(bG.endpoints[1].connectionsDetachable===false){bw=false}if(bD==null){bD=bG.endpoints[0].getConnectionCost()}if(bN.bidirectional==null){bB=bG.endpoints[0].areConnectionsBidirectional()}this.isDetachable=function(){return bw===true};this.setDetachable=function(bP){bw=bP===true};var bO=p.extend({},this.endpoints[0].getParameters());p.extend(bO,this.endpoints[1].getParameters());p.extend(bO,bG.getParameters());bG.setParameters(bO);var bE=bG.setHover;bG.setHover=function(bP){bG.connector.setHover.apply(bG.connector,arguments);bE.apply(bG,arguments)};var bL=function(bP){if(x==null){bG.setHover(bP,false)}};this.setConnector=function(bP,bQ){if(bG.connector!=null){aX(bG.connector.getDisplayElements(),bG.parent)}var bR={_jsPlumb:bG._jsPlumb,parent:bN.parent,cssClass:bN.cssClass,container:bN.container,tooltip:bG.tooltip};if(C(bP)){this.connector=new p.Connectors[X][bP](bR)}else{if(n(bP)){this.connector=new p.Connectors[X][bP[0]](p.extend(bP[1],bR))}}bG.canvas=bG.connector.canvas;G(bG.connector,bG,bL);if(!bQ){bG.repaint()}};bG.setConnector(this.endpoints[0].connector||this.endpoints[1].connector||bN.connector||bn.Defaults.Connector||p.Defaults.Connector,true);this.setPaintStyle(this.endpoints[0].connectorStyle||this.endpoints[1].connectorStyle||bN.paintStyle||bn.Defaults.PaintStyle||p.Defaults.PaintStyle,true);this.setHoverPaintStyle(this.endpoints[0].connectorHoverStyle||this.endpoints[1].connectorHoverStyle||bN.hoverPaintStyle||bn.Defaults.HoverPaintStyle||p.Defaults.HoverPaintStyle,true);this.paintStyleInUse=this.getPaintStyle();this.moveParent=function(bS){var bR=p.CurrentLibrary,bQ=bR.getParent(bG.connector.canvas);if(bG.connector.bgCanvas){bR.removeElement(bG.connector.bgCanvas,bQ);bR.appendElement(bG.connector.bgCanvas,bS)}bR.removeElement(bG.connector.canvas,bQ);bR.appendElement(bG.connector.canvas,bS);for(var bP=0;bP0){bO.connections[0].setHover(b2,false)}else{bO.setHover(b2)}};G(bO.endpoint,bO,b1);this.setPaintStyle(b0.paintStyle||b0.style||bn.Defaults.EndpointStyle||p.Defaults.EndpointStyle,true);this.setHoverPaintStyle(b0.hoverPaintStyle||bn.Defaults.EndpointHoverStyle||p.Defaults.EndpointHoverStyle,true);this.paintStyleInUse=this.getPaintStyle();var bJ=this.getPaintStyle();this.connectorStyle=b0.connectorStyle;this.connectorHoverStyle=b0.connectorHoverStyle;this.connectorOverlays=b0.connectorOverlays;this.connector=b0.connector;this.connectorTooltip=b0.connectorTooltip;this.isSource=b0.isSource||false;this.isTarget=b0.isTarget||false;var bU=b0.maxConnections||bn.Defaults.MaxConnections;this.getAttachedElements=function(){return bO.connections};this.canvas=this.endpoint.canvas;this.connections=b0.connections||[];this.scope=b0.scope||Q;this.timestamp=null;bO.isReattach=b0.reattach||false;bO.connectionsDetachable=bn.Defaults.ConnectionsDetachable;if(b0.connectionsDetachable===false||b0.detachable===false){bO.connectionsDetachable=false}var bI=b0.dragAllowedWhenFull||true;this.computeAnchor=function(b2){return bO.anchor.compute(b2)};this.addConnection=function(b2){bO.connections.push(b2)};this.detach=function(b3,b8,b4,cb,b2){var ca=i(bO.connections,function(cd){return cd.id==b3.id}),b9=false;cb=(cb!==false);if(ca>=0){if(b4||b3._forceDetach||b3.isDetachable()||b3.isDetachAllowed(b3)){var cc=b3.endpoints[0]==bO?b3.endpoints[1]:b3.endpoints[0];if(b4||b3._forceDetach||(bO.isDetachAllowed(b3))){bO.connections.splice(ca,1);if(!b8){cc.detach(b3,true,b4);if(b3.endpointsToDeleteOnDetach){for(var b7=0;b70){bO.detach(bO.connections[0],false,true,b3,b2)}};this.detachFrom=function(b5,b4,b2){var b6=[];for(var b3=0;b3=0){bO.connections.splice(b2,1)}};this.getElement=function(){return bN};this.setElement=function(b5,b2){var b7=K(b5);D(aT[bO.elementId],function(b8){return b8.id==bO.id});bN=F(b5);bF=K(bN);bO.elementId=bF;var b6=aw({source:b7,container:b2}),b4=bz.getParent(bO.canvas);bz.removeElement(bO.canvas,b4);bz.appendElement(bO.canvas,b6);for(var b3=0;b30){var ce=bK(b5.elementWithPrecedence),cg=ce.endpoints[0]==bO?1:0,b7=cg==0?ce.sourceId:ce.targetId,cd=ah[b7],cf=ae[b7];b4.txy=[cd.left,cd.top];b4.twh=cf;b4.tElement=ce.endpoints[cg]}b8=bO.anchor.compute(b4)}var cc=bL.compute(b8,bO.anchor.getOrientation(bO),bO.paintStyleInUse,b6||bO.paintStyleInUse);bL.paint(cc,bO.paintStyleInUse,bO.anchor);bO.timestamp=cb;for(var b9=0;b90?t:m+t:t*m;return jsPlumbUtil.pointOnLine({x:h,y:g},{x:d,y:c},s)}}};this.gradientAtPoint=function(s){return e};this.pointAlongPathFrom=function(s,w,v){var u=r.pointOnPath(s,v),t=s==1?{x:h+((d-h)*10),y:g+((g-c)*10)}:{x:d,y:c};return jsPlumbUtil.pointOnLine(u,t,w)}};jsPlumb.Connectors.Bezier=function(v){var p=this;v=v||{};this.majorAnchor=v.curviness||150;this.minorAnchor=10;var t=null;this.type="Bezier";this._findControlPoint=function(H,w,C,x,A,F,y){var E=F.getOrientation(x),G=y.getOrientation(A),B=E[0]!=G[0]||E[1]==G[1],z=[],I=p.majorAnchor,D=p.minorAnchor;if(!B){if(E[0]==0){z.push(w[0]u){u=C}if(F<0){s+=F;var H=Math.abs(F);u+=H;q[0]+=H;f+=H;o+=H;l[0]+=H}var P=Math.min(e,n),N=Math.min(q[1],l[1]),B=Math.min(P,N),G=Math.max(e,n),E=Math.max(q[1],l[1]),y=Math.max(G,E);if(y>d){d=y}if(B<0){r+=B;var D=Math.abs(B);d+=D;q[1]+=D;e+=D;n+=D;l[1]+=D}if(L&&u0?0:1,w)}return w};this.pointOnPath=function(w,y){var x=c();w=m(x,w,y);return jsBezier.pointOnCurve(x,w)};this.gradientAtPoint=function(w,y){var x=c();w=m(x,w,y);return jsBezier.gradientAtPoint(x,w)};this.pointAlongPathFrom=function(w,z,y){var x=c();w=m(x,w,y);return jsBezier.pointAlongCurveFrom(x,w,z)}};jsPlumb.Connectors.Flowchart=function(v){this.type="Flowchart";v=v||{};var n=this,c=v.stub||v.minStubLength||30,f=jsPlumbUtil.isArray(c)?c[0]:c,k=jsPlumbUtil.isArray(c)?c[1]:c,p=v.gap||0,q=[],i=0,d=[],m=[],r=[],o,l,u=-Infinity,s=-Infinity,w=Infinity,t=Infinity,x=function(z,y,D,C){var B=0;for(var A=0;A0?A/i:(i+A)/i}var y=d.length-1,z=1;for(var B=0;B=A){y=B;z=(A-d[B][0])/m[B];break}}return{segment:q[y],proportion:z,index:y}};this.compute=function(W,ak,z,Q,av,K,U,P,ap,am){q=[];d=[];i=0;m=[];u=s=-Infinity;w=t=Infinity;o=ak[0]au?0:1,ae=[1,0][ac];N=[];aw=[];N[ac]=W[ac]>ak[ac]?-1:1;aw[ac]=W[ac]>ak[ac]?1:-1;N[ae]=0;aw[ae]=0}if(al(f+k),X=Math.abs(H-aq)>(f+k),ah=Z+((L-Z)/2),af=Y+((J-Y)/2),O=((N[0]*aw[0])+(N[1]*aw[1])),ab=O==-1,ad=O==0,C=O==1;aj-=E;ai-=D;r=[aj,ai,al,au,I,H,ar,aq];var ao=[];var S=N[0]==0?"y":"x",M=ab?"opposite":C?"orthogonal":"perpendicular",F=jsPlumbUtil.segment([I,H],[ar,aq]),ag=N[S=="x"?0:1]==-1,R={x:[null,4,3,2,1],y:[null,2,1,4,3]};if(ag){F=R[S][F]}g(Z,Y,I,H,ar,aq);var T=function(az,ay,y,ax){return az+(ay*((1-y)*ax)+Math.max(f,k))},G={oppositex:function(){if(z.elementId==Q.elementId){var y=Y+((1-av.y)*ap.height)+Math.max(f,k);return[[Z,y],[L,y]]}else{if(V&&(F==1||F==2)){return[[ah,H],[ah,aq]]}else{return[[Z,af],[L,af]]}}},orthogonalx:function(){if(F==1||F==2){return[[L,Y]]}else{return[[Z,J]]}},perpendicularx:function(){var y=(aq+H)/2;if((F==1&&aw[1]==1)||(F==2&&aw[1]==-1)){if(Math.abs(ar-I)>Math.max(f,k)){return[[L,Y]]}else{return[[Z,Y],[Z,y],[L,y]]}}else{if((F==3&&aw[1]==-1)||(F==4&&aw[1]==1)){return[[Z,y],[L,y]]}else{if((F==3&&aw[1]==1)||(F==4&&aw[1]==-1)){return[[Z,J]]}else{if((F==1&&aw[1]==-1)||(F==2&&aw[1]==1)){if(Math.abs(ar-I)>Math.max(f,k)){return[[ah,Y],[ah,J]]}else{return[[Z,J]]}}}}}},oppositey:function(){if(z.elementId==Q.elementId){var y=Z+((1-av.x)*ap.width)+Math.max(f,k);return[[y,Y],[y,J]]}else{if(X&&(F==2||F==3)){return[[I,af],[ar,af]]}else{return[[ah,Y],[ah,J]]}}},orthogonaly:function(){if(F==2||F==3){return[[Z,J]]}else{return[[L,Y]]}},perpendiculary:function(){var y=(ar+I)/2;if((F==2&&aw[0]==-1)||(F==3&&aw[0]==1)){if(Math.abs(ar-I)>Math.max(f,k)){return[[Z,J]]}else{return[[Z,af],[L,af]]}}else{if((F==1&&aw[0]==-1)||(F==4&&aw[0]==1)){var y=(ar+I)/2;return[[y,Y],[y,J]]}else{if((F==1&&aw[0]==1)||(F==4&&aw[0]==-1)){return[[L,Y]]}else{if((F==2&&aw[0]==1)||(F==3&&aw[0]==-1)){if(Math.abs(aq-H)>Math.max(f,k)){return[[Z,af],[L,af]]}else{return[[L,Y]]}}}}}}};var an=G[M+S]();if(an){for(var at=0;atr[3]){r[3]=s+(U*2)}if(u>r[2]){r[2]=u+(U*2)}return r};this.pointOnPath=function(y,z){return n.pointAlongPathFrom(y,0,z)};this.gradientAtPoint=function(y,z){return q[e(y,z)["index"]][4]};this.pointAlongPathFrom=function(F,y,E){var G=e(F,E),C=G.segment,z=G.proportion,B=q[G.index][5],A=q[G.index][4];var D={x:A==Infinity?C[2]:C[2]>C[0]?C[0]+((1-z)*B)-y:C[2]+(z*B)+y,y:A==0?C[3]:C[3]>C[1]?C[1]+((1-z)*B)-y:C[3]+(z*B)+y,segmentInfo:G};return D}};jsPlumb.Endpoints.Dot=function(d){this.type="Dot";var c=this;d=d||{};this.radius=d.radius||10;this.defaultOffset=0.5*this.radius;this.defaultInnerRadius=this.radius/3;this.compute=function(i,f,l,h){var g=l.radius||c.radius,e=i[0]-g,k=i[1]-g;return[e,k,g*2,g*2,g]}};jsPlumb.Endpoints.Rectangle=function(d){this.type="Rectangle";var c=this;d=d||{};this.width=d.width||20;this.height=d.height||20;this.compute=function(k,g,m,i){var h=m.width||c.width,f=m.height||c.height,e=k[0]-(h/2),l=k[1]-(f/2);return[e,l,h,f]}};var a=function(e){jsPlumb.DOMElementComponent.apply(this,arguments);var c=this;var d=[];this.getDisplayElements=function(){return d};this.appendDisplayElement=function(f){d.push(f)}};jsPlumb.Endpoints.Image=function(g){this.type="Image";a.apply(this,arguments);var l=this,f=false,e=g.width,d=g.height,i=null,c=g.endpoint;this.img=new Image();l.ready=false;this.img.onload=function(){l.ready=true;e=e||l.img.width;d=d||l.img.height;if(i){i(l)}};c.setImage=function(m,o){var n=m.constructor==String?m:m.src;i=o;l.img.src=m;if(l.canvas!=null){l.canvas.setAttribute("src",m)}};c.setImage(g.src||g.url,g.onload);this.compute=function(o,m,p,n){l.anchorPoint=o;if(l.ready){return[o[0]-e/2,o[1]-d/2,e,d]}else{return[0,0,0,0]}};l.canvas=document.createElement("img"),f=false;l.canvas.style.margin=0;l.canvas.style.padding=0;l.canvas.style.outline=0;l.canvas.style.position="absolute";var h=g.cssClass?" "+g.cssClass:"";l.canvas.className=jsPlumb.endpointClass+h;if(e){l.canvas.setAttribute("width",e)}if(d){l.canvas.setAttribute("height",d)}jsPlumb.appendElement(l.canvas,g.parent);l.attachListeners(l.canvas,l);var k=function(p,o,n){if(!f){l.canvas.setAttribute("src",l.img.src);l.appendDisplayElement(l.canvas);f=true}var m=l.anchorPoint[0]-(e/2),q=l.anchorPoint[1]-(d/2);jsPlumb.sizeCanvas(l.canvas,m,q,e,d)};this.paint=function(o,n,m){if(l.ready){k(o,n,m)}else{window.setTimeout(function(){l.paint(o,n,m)},200)}}};jsPlumb.Endpoints.Blank=function(d){var c=this;this.type="Blank";a.apply(this,arguments);this.compute=function(g,e,h,f){return[g[0],g[1],10,0]};c.canvas=document.createElement("div");c.canvas.style.display="block";c.canvas.style.width="1px";c.canvas.style.height="1px";c.canvas.style.background="transparent";c.canvas.style.position="absolute";c.canvas.className=c._jsPlumb.endpointClass;jsPlumb.appendElement(c.canvas,d.parent);this.paint=function(g,f,e){jsPlumb.sizeCanvas(c.canvas,g[0],g[1],g[2],g[3])}};jsPlumb.Endpoints.Triangle=function(c){this.type="Triangle";c=c||{};c.width=c.width||55;c.height=c.height||55;this.width=c.width;this.height=c.height;this.compute=function(i,f,l,h){var g=l.width||self.width,e=l.height||self.height,d=i[0]-(g/2),k=i[1]-(e/2);return[d,k,g,e]}};var b=function(e){var d=true,c=this;this.isAppendedAtTopLevel=true;this.component=e.component;this.loc=e.location==null?0.5:e.location;this.endpointLoc=e.endpointLocation==null?[0.5,0.5]:e.endpointLocation;this.setVisible=function(f){d=f;c.component.repaint()};this.isVisible=function(){return d};this.hide=function(){c.setVisible(false)};this.show=function(){c.setVisible(true)};this.incrementLocation=function(f){c.loc+=f;c.component.repaint()};this.setLocation=function(f){c.loc=f;c.component.repaint()};this.getLocation=function(){return c.loc}};jsPlumb.Overlays.Arrow=function(g){this.type="Arrow";b.apply(this,arguments);this.isAppendedAtTopLevel=false;g=g||{};var d=this;this.length=g.length||20;this.width=g.width||20;this.id=g.id;var f=(g.direction||1)<0?-1:1,e=g.paintStyle||{lineWidth:1},c=g.foldback||0.623;this.computeMaxSize=function(){return d.width*1.5};this.cleanup=function(){};this.draw=function(k,z,u){var o,v,h,p,n;if(k.pointAlongPathFrom){if(jsPlumbUtil.isString(d.loc)||d.loc>1||d.loc<0){var i=parseInt(d.loc);o=k.pointAlongPathFrom(i,f*d.length/2,true),v=k.pointOnPath(i,true),h=jsPlumbUtil.pointOnLine(o,v,d.length)}else{if(d.loc==1){o=k.pointOnPath(d.loc);v=k.pointAlongPathFrom(d.loc,-1);h=jsPlumbUtil.pointOnLine(o,v,d.length)}else{if(d.loc==0){h=k.pointOnPath(d.loc);v=k.pointAlongPathFrom(d.loc,1);o=jsPlumbUtil.pointOnLine(h,v,d.length)}else{o=k.pointAlongPathFrom(d.loc,f*d.length/2),v=k.pointOnPath(d.loc),h=jsPlumbUtil.pointOnLine(o,v,d.length)}}}p=jsPlumbUtil.perpendicularLineTo(o,h,d.width);n=jsPlumbUtil.pointOnLine(o,h,c*d.length);var y=Math.min(o.x,p[0].x,p[1].x),s=Math.max(o.x,p[0].x,p[1].x),x=Math.min(o.y,p[0].y,p[1].y),r=Math.max(o.y,p[0].y,p[1].y);var q={hxy:o,tail:p,cxy:n},t=e.strokeStyle||z.strokeStyle,w=e.fillStyle||z.strokeStyle,m=e.lineWidth||z.lineWidth;d.paint(k,q,m,t,w,u);return[y,s,x,r]}else{return[0,0,0,0]}}};jsPlumb.Overlays.PlainArrow=function(d){d=d||{};var c=jsPlumb.extend(d,{foldback:1});jsPlumb.Overlays.Arrow.call(this,c);this.type="PlainArrow"};jsPlumb.Overlays.Diamond=function(e){e=e||{};var c=e.length||40,d=jsPlumb.extend(e,{length:c/2,foldback:2});jsPlumb.Overlays.Arrow.call(this,d);this.type="Diamond"};jsPlumb.Overlays.Label=function(i){this.type="Label";jsPlumb.DOMElementComponent.apply(this,arguments);b.apply(this,arguments);this.labelStyle=i.labelStyle||jsPlumb.Defaults.LabelStyle;this.id=i.id;this.cachedDimensions=null;var e=i.label||"",c=this,f=false,k=document.createElement("div"),g=null;k.style.position="absolute";var d=i._jsPlumb.overlayClass+" "+(c.labelStyle.cssClass?c.labelStyle.cssClass:i.cssClass?i.cssClass:"");k.className=d;jsPlumb.appendElement(k,i.component.parent);jsPlumb.getId(k);c.attachListeners(k,c);c.canvas=k;var h=c.setVisible;c.setVisible=function(l){h(l);k.style.display=l?"block":"none"};this.getElement=function(){return k};this.cleanup=function(){if(k!=null){jsPlumb.CurrentLibrary.removeElement(k)}};this.setLabel=function(m){e=m;g=null;c.component.repaint()};this.getLabel=function(){return e};this.paint=function(l,n,m){if(!f){l.appendDisplayElement(k);c.attachListeners(k,l);f=true}k.style.left=(m[0]+n.minx)+"px";k.style.top=(m[1]+n.miny)+"px"};this.getTextDimensions=function(){if(typeof e=="function"){var l=e(c);k.innerHTML=l.replace(/\r\n/g,"
")}else{if(g==null){g=e;k.innerHTML=g.replace(/\r\n/g,"
")}}var n=jsPlumb.CurrentLibrary.getElementObject(k),m=jsPlumb.CurrentLibrary.getSize(n);return{width:m[0],height:m[1]}};this.computeMaxSize=function(l){var m=c.getTextDimensions(l);return m.width?Math.max(m.width,m.height)*1.5:0};this.draw=function(m,n,o){var s=c.getTextDimensions(m);if(s.width!=null){var p={x:0,y:0};if(m.pointOnPath){var q=c.loc,r=false;if(jsPlumbUtil.isString(c.loc)||c.loc<0||c.loc>1){q=parseInt(c.loc);r=true}p=m.pointOnPath(q,r)}else{var l=c.loc.constructor==Array?c.loc:c.endpointLoc;p={x:l[0]*o[2],y:l[1]*o[3]}}minx=p.x-(s.width/2),miny=p.y-(s.height/2);c.paint(m,{minx:minx,miny:miny,td:s,cxy:p},o);return[minx,minx+s.width,miny,miny+s.height]}else{return[0,0,0,0]}};this.reattachListeners=function(l){if(k){c.reattachListenersForElement(k,c,l)}}};jsPlumb.Overlays.GuideLines=function(){var c=this;c.length=50;c.lineWidth=5;this.type="GuideLines";b.apply(this,arguments);jsPlumb.jsPlumbUIComponent.apply(this,arguments);this.draw=function(e,l,k){var i=e.pointAlongPathFrom(c.loc,c.length/2),h=e.pointOnPath(c.loc),g=jsPlumbUtil.pointOnLine(i,h,c.length),f=jsPlumbUtil.perpendicularLineTo(i,g,40),d=jsPlumbUtil.perpendicularLineTo(g,i,20);c.paint(e,[i,g,f,d],c.lineWidth,"red",null,k);return[Math.min(i.x,g.x),Math.min(i.y,g.y),Math.max(i.x,g.x),Math.max(i.y,g.y)]};this.computeMaxSize=function(){return 50};this.cleanup=function(){}}})();(function(){var c=function(e,g,d,f){this.m=(f-g)/(d-e);this.b=-1*((this.m*e)-g);this.rectIntersect=function(q,p,s,o){var n=[];var k=(p-this.b)/this.m;if(k>=q&&k<=(q+s)){n.push([k,(this.m*k)+this.b])}var t=(this.m*(q+s))+this.b;if(t>=p&&t<=(p+o)){n.push([(t-this.b)/this.m,t])}var k=((p+o)-this.b)/this.m;if(k>=q&&k<=(q+s)){n.push([k,(this.m*k)+this.b])}var t=(this.m*q)+this.b;if(t>=p&&t<=(p+o)){n.push([(t-this.b)/this.m,t])}if(n.length==2){var m=(n[0][0]+n[1][0])/2,l=(n[0][1]+n[1][1])/2;n.push([m,l]);var i=m<=q+(s/2)?-1:1,r=l<=p+(o/2)?-1:1;n.push([i,r]);return n}return null}},a=function(e,g,d,f){if(e<=d&&f<=g){return 1}else{if(e<=d&&g<=f){return 2}else{if(d<=e&&f>=g){return 3}}}return 4},b=function(g,f,i,e,h,m,l,d,k){if(d<=k){return[g,f]}if(i==1){if(e[3]<=0&&h[3]>=1){return[g+(e[2]<0.5?-1*m:m),f]}else{if(e[2]>=1&&h[2]<=0){return[g,f+(e[3]<0.5?-1*l:l)]}else{return[g+(-1*m),f+(-1*l)]}}}else{if(i==2){if(e[3]>=1&&h[3]<=0){return[g+(e[2]<0.5?-1*m:m),f]}else{if(e[2]>=1&&h[2]<=0){return[g,f+(e[3]<0.5?-1*l:l)]}else{return[g+(1*m),f+(-1*l)]}}}else{if(i==3){if(e[3]>=1&&h[3]<=0){return[g+(e[2]<0.5?-1*m:m),f]}else{if(e[2]<=0&&h[2]>=1){return[g,f+(e[3]<0.5?-1*l:l)]}else{return[g+(-1*m),f+(-1*l)]}}}else{if(i==4){if(e[3]<=0&&h[3]>=1){return[g+(e[2]<0.5?-1*m:m),f]}else{if(e[2]<=0&&h[2]>=1){return[g,f+(e[3]<0.5?-1*l:l)]}else{return[g+(1*m),f+(-1*l)]}}}}}}};jsPlumb.Connectors.StateMachine=function(l){var u=this,n=null,o,m,g,e,p=[],d=l.curviness||10,k=l.margin||5,q=l.proximityLimit||80,f=l.orientation&&l.orientation=="clockwise",i=l.loopbackRadius||25,h=false,t=l.showLoopback!==false;this.type="StateMachine";l=l||{};this.compute=function(ad,H,W,I,ac,z,v,U){var Q=Math.abs(ad[0]-H[0]),Y=Math.abs(ad[1]-H[1]),S=0.45*Q,ab=0.45*Y;Q*=1.9;Y*=1.9;v=v||1;var O=Math.min(ad[0],H[0])-S,M=Math.min(ad[1],H[1])-ab;if(!t||(W.elementId!=I.elementId)){h=false;o=ad[0]0?0:1,v)}return v};this.pointOnPath=function(x,B){if(h){if(B){var y=Math.PI*2*i;x=x/y}if(x>0&&x<1){x=1-x}var z=(x*2*Math.PI)+(Math.PI/2),w=n[4]+(n[6]*Math.cos(z)),v=n[5]+(n[6]*Math.sin(z));return{x:w,y:v}}else{var A=r();x=s(A,x,B);return jsBezier.pointOnCurve(A,x)}};this.gradientAtPoint=function(v,y){if(h){if(y){var w=Math.PI*2*i;v=v/w}return Math.atan(v*2*Math.PI)}else{var x=r();v=s(x,v,y);return jsBezier.gradientAtPoint(x,v)}};this.pointAlongPathFrom=function(D,v,C){if(h){if(C){var B=Math.PI*2*i;D=D/B}if(D>0&&D<1){D=1-D}var B=2*Math.PI*n[6],w=v/B*2*Math.PI,z=(D*2*Math.PI)-w+(Math.PI/2),y=n[4]+(n[6]*Math.cos(z)),x=n[5]+(n[6]*Math.sin(z));return{x:y,y:x}}else{var A=r();D=s(A,D,C);return jsBezier.pointAlongCurveFrom(A,D,v)}}};jsPlumb.Connectors.canvas.StateMachine=function(f){f=f||{};var d=this,g=f.drawGuideline||true,e=f.avoidSelector;jsPlumb.Connectors.StateMachine.apply(this,arguments);jsPlumb.CanvasConnector.apply(this,arguments);this._paint=function(l){if(l.length==10){d.ctx.beginPath();d.ctx.moveTo(l[4],l[5]);d.ctx.bezierCurveTo(l[8],l[9],l[8],l[9],l[6],l[7]);d.ctx.stroke()}else{d.ctx.save();d.ctx.beginPath();var k=0,i=2*Math.PI,h=l[7];d.ctx.arc(l[4],l[5],l[6],0,i,h);d.ctx.stroke();d.ctx.closePath();d.ctx.restore()}};this.createGradient=function(i,h){return h.createLinearGradient(i[4],i[5],i[6],i[7])}};jsPlumb.Connectors.svg.StateMachine=function(){var d=this;jsPlumb.Connectors.StateMachine.apply(this,arguments);jsPlumb.SvgConnector.apply(this,arguments);this.getPath=function(e){if(e.length==10){return"M "+e[4]+" "+e[5]+" C "+e[8]+" "+e[9]+" "+e[8]+" "+e[9]+" "+e[6]+" "+e[7]}else{return"M"+(e[8]+4)+" "+e[9]+" A "+e[6]+" "+e[6]+" 0 1,0 "+(e[8]-4)+" "+e[9]}}};jsPlumb.Connectors.vml.StateMachine=function(){jsPlumb.Connectors.StateMachine.apply(this,arguments);jsPlumb.VmlConnector.apply(this,arguments);var d=jsPlumb.vml.convertValue;this.getPath=function(k){if(k.length==10){return"m"+d(k[4])+","+d(k[5])+" c"+d(k[8])+","+d(k[9])+","+d(k[8])+","+d(k[9])+","+d(k[6])+","+d(k[7])+" e"}else{var h=d(k[8]-k[6]),g=d(k[9]-(2*k[6])),f=h+d(2*k[6]),e=g+d(2*k[6]),l=h+","+g+","+f+","+e;var i="ar "+l+","+d(k[8])+","+d(k[9])+","+d(k[8])+","+d(k[9])+" e";return i}}}})();(function(){var h={"stroke-linejoin":"joinstyle",joinstyle:"joinstyle",endcap:"endcap",miterlimit:"miterlimit"},c=null;if(document.createStyleSheet&&document.namespaces){var m=[".jsplumb_vml","jsplumb\\:textbox","jsplumb\\:oval","jsplumb\\:rect","jsplumb\\:stroke","jsplumb\\:shape","jsplumb\\:group"],g="behavior:url(#default#VML);position:absolute;";c=document.createStyleSheet();for(var r=0;r0&&C>0&&u=u&&w[2]<=C&&w[3]>=C)){return true}}var A=q.canvas.getContext("2d").getImageData(parseInt(u),parseInt(C),1,1);return A.data[0]!=0||A.data[1]!=0||A.data[2]!=0||A.data[3]!=0}return false};var p=false,o=false,t=null,s=false,r=function(v,u){return v!=null&&i(v,u)};this.mousemove=function(x){var z=n(x),w=f(x),v=document.elementFromPoint(w[0],w[1]),y=r(v,"_jsPlumb_overlay");var u=d==null&&(r(v,"_jsPlumb_endpoint")||r(v,"_jsPlumb_connector"));if(!p&&u&&q._over(x)){p=true;q.fire("mouseenter",q,x);return true}else{if(p&&(!q._over(x)||!u)&&!y){p=false;q.fire("mouseexit",q,x)}}q.fire("mousemove",q,x)};this.click=function(u){if(p&&q._over(u)&&!s){q.fire("click",q,u)}s=false};this.dblclick=function(u){if(p&&q._over(u)&&!s){q.fire("dblclick",q,u)}s=false};this.mousedown=function(u){if(q._over(u)&&!o){o=true;t=m(a(q.canvas));q.fire("mousedown",q,u)}};this.mouseup=function(u){o=false;q.fire("mouseup",q,u)};this.contextmenu=function(u){if(p&&q._over(u)&&!s){q.fire("contextmenu",q,u)}s=false}};var c=function(p){var o=document.createElement("canvas");p._jsPlumb.appendElement(o,p.parent);o.style.position="absolute";if(p["class"]){o.className=p["class"]}p._jsPlumb.getId(o,p.uuid);if(p.tooltip){o.setAttribute("title",p.tooltip)}return o};var l=function(p){k.apply(this,arguments);var o=[];this.getDisplayElements=function(){return o};this.appendDisplayElement=function(q){o.push(q)}};var h=jsPlumb.CanvasConnector=function(r){l.apply(this,arguments);var o=function(v,t){p.ctx.save();jsPlumb.extend(p.ctx,t);if(t.gradient){var u=p.createGradient(v,p.ctx);for(var s=0;s0?c[0].tagName:null},getUIPosition:function(c){if(c.length==1){ret={left:c[0].pageX,top:c[0].pageY}}else{var d=c[1],b=d.offset;ret=b||d.absolutePosition}return ret},hasClass:function(c,b){return c.hasClass(b)},initDraggable:function(c,b,d){b=b||{};b.helper=null;if(d){b.scope=b.scope||jsPlumb.Defaults.Scope}c.draggable(b)},initDroppable:function(c,b){b.scope=b.scope||jsPlumb.Defaults.Scope;c.droppable(b)},isAlreadyDraggable:function(b){b=jsPlumb.CurrentLibrary.getElementObject(b);return b.hasClass("ui-draggable")},isDragSupported:function(c,b){return c.draggable},isDropSupported:function(c,b){return c.droppable},removeClass:function(c,b){c=jsPlumb.CurrentLibrary.getElementObject(c);try{if(c[0].className.constructor==SVGAnimatedString){jsPlumb.util.svg.removeClass(c[0],b)}}catch(d){}c.removeClass(b)},removeElement:function(b,c){jsPlumb.CurrentLibrary.getElementObject(b).remove()},setAttribute:function(c,d,b){c.attr(d,b)},setDraggable:function(c,b){c.draggable("option","disabled",!b)},setDragScope:function(c,b){c.draggable("option","scope",b)},setOffset:function(b,c){jsPlumb.CurrentLibrary.getElementObject(b).offset(c)},trigger:function(d,e,b){var c=jQuery._data(jsPlumb.CurrentLibrary.getElementObject(d)[0],"handle");c(b)},unbind:function(b,c,d){b=jsPlumb.CurrentLibrary.getElementObject(b);b.unbind(c,d)}};a(document).ready(jsPlumb.init)})(jQuery);(function(){"undefined"==typeof Math.sgn&&(Math.sgn=function(l){return 0==l?0:0=64){x[0]=(C[0].x+C[B].x)/2;return 1}var p,u=C[0].y-C[B].y;y=C[B].x-C[0].x;q=C[0].x*C[B].y-C[B].x*C[0].y;s=max_distance_below=0;for(p=1;ps?s=r:r0?1:-1,r=null;n1){l.location=1}if(l.location<0){l.location=0}return i(m,l.location)},nearestPointOnCurve:function(m,l){var n=h(m,l);return{point:k(l,l.length-1,n.location,null,null),location:n.location}},pointOnCurve:c,pointAlongCurveFrom:function(m,l,n){return b(m,l,n).point},perpendicularToCurveAt:function(m,l,n,o){l=b(m,l,o==null?0:o);m=i(m,l.location);o=Math.atan(-1/m);m=n/2*Math.sin(o);n=n/2*Math.cos(o);return[{x:l.point.x+n,y:l.point.y+m},{x:l.point.x-n,y:l.point.y-m}]},locationAlongCurveFrom:function(m,l,n){return b(m,l,n).location}}})(); \ No newline at end of file diff --git a/embed/js/jquery.qtip.min.js b/embed/js/jquery.qtip.min.js new file mode 100644 index 0000000..3971f6d --- /dev/null +++ b/embed/js/jquery.qtip.min.js @@ -0,0 +1,2 @@ +/*! qTip2 v2.0.0 | http://craigsworks.com/projects/qtip2/ | Licensed MIT, GPL */ +(function(a,b,c){(function(a){"use strict",typeof define=="function"&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)})(function(d){function I(a){var b=function(a){return a===g||"object"!=typeof a},c=function(a){return!d.isFunction(a)&&(!a&&!a.attr||a.length<1||"object"==typeof a&&!a.jquery)};if(!a||"object"!=typeof a)return f;b(a.metadata)&&(a.metadata={type:a.metadata});if("content"in a){if(b(a.content)||a.content.jquery)a.content={text:a.content};c(a.content.text||f)&&(a.content.text=f),"title"in a.content&&(b(a.content.title)&&(a.content.title={text:a.content.title}),c(a.content.title.text||f)&&(a.content.title.text=f))}return"position"in a&&b(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&b(a.show)&&(a.show=a.show.jquery?{target:a.show}:{event:a.show}),"hide"in a&&b(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&b(a.style)&&(a.style={classes:a.style}),d.each(u,function(){this.sanitize&&this.sanitize(a)}),a}function J(h,i,q,r){function Q(a){var b=0,c,d=i,e=a.split(".");while(d=d[e[b++]])b",{"class":"ui-state-default ui-tooltip-close "+(i.style.widget?"":x+"-icon"),title:c,"aria-label":c}).prepend(d("",{"class":"ui-icon ui-icon-close",html:"×"})),O.button.appendTo(O.titlebar).attr("role","button").click(function(a){return M.hasClass(z)||s.hide(a),f}),s.redraw()}function V(){var a=J+"-title";O.titlebar&&T(),O.titlebar=d("
",{"class":x+"-titlebar "+(i.style.widget?"ui-widget-header":"")}).append(O.title=d("
",{id:a,"class":x+"-title","aria-atomic":e})).insertBefore(O.content).delegate(".ui-tooltip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus",a.type.substr(-4)==="down")}).delegate(".ui-tooltip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover",a.type==="mouseover")}),i.content.title.button?U():s.rendered&&s.redraw()}function W(a){var b=O.button,c=O.title;if(!s.rendered)return f;a?(c||V(),U()):b.remove()}function X(a,b){var c=O.title;if(!s.rendered||!a)return f;d.isFunction(a)&&(a=a.call(h,P.event,s));if(a===f||!a&&a!=="")return T(f);a.jquery&&a.length>0?c.empty().append(a.css({display:"block"})):c.html(a),s.redraw(),b!==f&&s.rendered&&M[0].offsetWidth>0&&s.reposition(P.event)}function Y(a,b){function g(a){function i(c){c&&(delete h[c.src],clearTimeout(s.timers.img[c.src]),d(c).unbind(N)),d.isEmptyObject(h)&&(s.redraw(),b!==f&&s.reposition(P.event),a())}var g,h={};if((g=e.find("img[src]:not([height]):not([width])")).length===0)return i();g.each(function(a,b){if(h[b.src]!==c)return;var e=0,f=3;(function g(){if(b.height||b.width||e>f)return i(b);e+=1,s.timers.img[b.src]=setTimeout(g,700)})(),d(b).bind("error"+N+" load"+N,function(){i(this)}),h[b.src]=b})}var e=O.content;return!s.rendered||!a?f:(d.isFunction(a)&&(a=a.call(h,P.event,s)||""),a.jquery&&a.length>0?e.empty().append(a.css({display:"block"})):e.html(a),s.rendered<0?M.queue("fx",g):(L=0,g(d.noop)),s)}function Z(){function l(a){if(M.hasClass(z))return f;clearTimeout(s.timers.show),clearTimeout(s.timers.hide);var b=function(){s.toggle(e,a)};i.show.delay>0?s.timers.show=setTimeout(b,i.show.delay):b()}function m(a){if(M.hasClass(z)||K||L)return f;var b=d(a.relatedTarget||a.target),e=b.closest(A)[0]===M[0],h=b[0]===g.show[0];clearTimeout(s.timers.show),clearTimeout(s.timers.hide);if(c.target==="mouse"&&e||i.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(e||h)){try{a.preventDefault(),a.stopImmediatePropagation()}catch(j){}return}i.hide.delay>0?s.timers.hide=setTimeout(function(){s.hide(a)},i.hide.delay):s.hide(a)}function n(a){if(M.hasClass(z))return f;clearTimeout(s.timers.inactive),s.timers.inactive=setTimeout(function(){s.hide(a)},i.hide.inactive)}function o(a){s.rendered&&M[0].offsetWidth>0&&s.reposition(a)}var c=i.position,g={show:i.show.target,hide:i.hide.target,viewport:d(c.viewport),document:d(b),body:d(b.body),window:d(a)},j={show:d.trim(""+i.show.event).split(" "),hide:d.trim(""+i.hide.event).split(" ")},k=d.browser.msie&&parseInt(d.browser.version,10)===6;M.bind("mouseenter"+N+" mouseleave"+N,function(a){var b=a.type==="mouseenter";b&&s.focus(a),M.toggleClass(D,b)}),/mouse(out|leave)/i.test(i.hide.event)&&i.hide.leave==="window"&&g.window.bind("mouseout"+N+" blur"+N,function(a){!/select|option/.test(a.target.nodeName)&&!a.relatedTarget&&s.hide(a)}),i.hide.fixed?(g.hide=g.hide.add(M),M.bind("mouseover"+N,function(){M.hasClass(z)||clearTimeout(s.timers.hide)})):/mouse(over|enter)/i.test(i.show.event)&&g.hide.bind("mouseleave"+N,function(a){clearTimeout(s.timers.show)}),(""+i.hide.event).indexOf("unfocus")>-1&&c.container.closest("html").bind("mousedown"+N,function(a){var b=d(a.target),c=s.rendered&&!M.hasClass(z)&&M[0].offsetWidth>0,e=b.parents(A).filter(M[0]).length>0;b[0]!==h[0]&&b[0]!==M[0]&&!e&&!h.has(b[0]).length&&!b.attr("disabled")&&s.hide(a)}),"number"==typeof i.hide.inactive&&(g.show.bind("qtip-"+q+"-inactive",n),d.each(t.inactiveEvents,function(a,b){g.hide.add(O.tooltip).bind(b+N+"-inactive",n)})),d.each(j.hide,function(a,b){var c=d.inArray(b,j.show),e=d(g.hide);c>-1&&e.add(g.show).length===e.length||b==="unfocus"?(g.show.bind(b+N,function(a){M[0].offsetWidth>0?m(a):l(a)}),delete j.show[c]):g.hide.bind(b+N,m)}),d.each(j.show,function(a,b){g.show.bind(b+N,l)}),"number"==typeof i.hide.distance&&g.show.add(M).bind("mousemove"+N,function(a){var b=P.origin||{},c=i.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&s.hide(a)}),c.target==="mouse"&&(g.show.bind("mousemove"+N,function(a){v={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),c.adjust.mouse&&(i.hide.event&&(M.bind("mouseleave"+N,function(a){(a.relatedTarget||a.target)!==g.show[0]&&s.hide(a)}),O.target.bind("mouseenter"+N+" mouseleave"+N,function(a){P.onTarget=a.type==="mouseenter"})),g.document.bind("mousemove"+N,function(a){s.rendered&&P.onTarget&&!M.hasClass(z)&&M[0].offsetWidth>0&&s.reposition(a||v)}))),(c.adjust.resize||g.viewport.length)&&(d.event.special.resize?g.viewport:g.window).bind("resize"+N,o),(g.viewport.length||k&&M.css("position")==="fixed")&&g.viewport.bind("scroll"+N,o)}function _(){var c=[i.show.target[0],i.hide.target[0],s.rendered&&O.tooltip[0],i.position.container[0],i.position.viewport[0],i.position.container.closest("html")[0],a,b];s.rendered?d([]).pushStack(d.grep(c,function(a){return typeof a=="object"})).unbind(N):i.show.target.unbind(N+"-create")}var s=this,E=b.body,J=x+"-"+q,K=0,L=0,M=d(),N=".qtip-"+q,O,P;s.id=q,s.rendered=f,s.destroyed=f,s.elements=O={target:h},s.timers={img:{}},s.options=i,s.checks={},s.plugins={},s.cache=P={event:{},target:d(),disabled:f,attr:r,onTarget:f,lastClass:""},s.checks.builtin={"^id$":function(a,b,c){var g=c===e?t.nextid:c,h=x+"-"+g;g!==f&&g.length>0&&!d("#"+h).length&&(M[0].id=h,O.content[0].id=h+"-content",O.title[0].id=h+"-title")},"^content.text$":function(a,b,c){Y(c)},"^content.title.text$":function(a,b,c){if(!c)return T();!O.title&&c&&V(),X(c)},"^content.title.button$":function(a,b,c){W(c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(a[b]=new u.Corner(c))},"^position.container$":function(a,b,c){s.rendered&&M.appendTo(c)},"^show.ready$":function(){s.rendered?s.toggle(e):s.render(1)},"^style.classes$":function(a,b,c){M.attr("class",x+" qtip "+c)},"^style.widget|content.title":S,"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){M[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){var a=i.position;M.attr("tracking",a.target==="mouse"&&a.adjust.mouse),_(),Z()}},d.extend(s,{render:function(a){if(s.rendered)return s;var b=i.content.text,c=i.content.title.text,g=i.position;return d.attr(h[0],"aria-describedby",J),M=O.tooltip=d("
",{id:J,"class":x+" qtip "+B+" "+i.style.classes+" "+x+"-pos-"+i.position.my.abbrev(),width:i.style.width||"",height:i.style.height||"",tracking:g.target==="mouse"&&g.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":f,"aria-describedby":J+"-content","aria-hidden":e}).toggleClass(z,P.disabled).data("qtip",s).appendTo(i.position.container).append(O.content=d("
",{"class":x+"-content",id:J+"-content","aria-atomic":e})),s.rendered=-1,L=1,K=1,c&&(V(),d.isFunction(c)||X(c,f)),d.isFunction(b)||Y(b,f),s.rendered=e,S(),d.each(i.events,function(a,b){d.isFunction(b)&&M.bind(a==="toggle"?"tooltipshow tooltiphide":"tooltip"+a,b)}),d.each(u,function(){this.initialize==="render"&&this(s)}),Z(),M.queue("fx",function(b){R("render"),L=0,K=0,s.redraw(),(i.show.ready||a)&&s.toggle(e,P.event,f),b()}),s},get:function(a){var b,c;switch(a.toLowerCase()){case"dimensions":b={height:M.outerHeight(),width:M.outerWidth()};break;case"offset":b=u.offset(M,i.position.container);break;default:c=Q(a.toLowerCase()),b=c[0][c[1]],b=b.precedance?b.string():b}return b},set:function(a,b){function n(a,b){var c,d,e;for(c in l)for(d in l[c])if(e=(new RegExp(d,"i")).exec(a))b.push(e),l[c][d].apply(s,b)}var c=/^position\.(my|at|adjust|target|container)|style|content|show\.ready/i,h=/^content\.(title|attr)|style/i,j=f,k=f,l=s.checks,m;return"string"==typeof a?(m=a,a={},a[m]=b):a=d.extend(e,{},a),d.each(a,function(b,e){var f=Q(b.toLowerCase()),g;g=f[0][f[1]],f[0][f[1]]="object"==typeof e&&e.nodeType?d(e):e,a[b]=[f[0],f[1],e,g],j=c.test(b)||j,k=h.test(b)||k}),I(i),K=L=1,d.each(a,n),K=L=0,s.rendered&&M[0].offsetWidth>0&&(j&&s.reposition(i.position.target==="mouse"?g:P.event),k&&s.redraw()),s},toggle:function(a,c){function t(){a?(d.browser.msie&&M[0].style.removeAttribute("filter"),M.css("overflow",""),"string"==typeof h.autofocus&&d(h.autofocus,M).focus(),h.target.trigger("qtip-"+q+"-inactive")):M.css({display:"",visibility:"",opacity:"",left:"",top:""}),R(a?"visible":"hidden")}if(!s.rendered)return a?s.render(1):s;var g=a?"show":"hide",h=i[g],j=i[a?"hide":"show"],k=i.position,l=i.content,m=M[0].offsetWidth>0,n=a||h.target.length===1,o=!c||h.target.length<2||P.target[0]===c.target,p,r;(typeof a).search("boolean|number")&&(a=!m);if(!M.is(":animated")&&m===a&&o)return s;if(c){if(/over|enter/.test(c.type)&&/out|leave/.test(P.event.type)&&i.show.target.add(c.target).length===i.show.target.length&&M.has(c.relatedTarget).length)return s;P.event=d.extend({},c)}return R(g,[90])?(d.attr(M[0],"aria-hidden",!a),a?(P.origin=d.extend({},v),s.focus(c),d.isFunction(l.text)&&Y(l.text,f),d.isFunction(l.title.text)&&X(l.title.text,f),!G&&k.target==="mouse"&&k.adjust.mouse&&(d(b).bind("mousemove.qtip",function(a){v={pageX:a.pageX,pageY:a.pageY,type:"mousemove"}}),G=e),s.reposition(c,arguments[2]),!h.solo||d(A,h.solo).not(M).qtip("hide",d.Event("tooltipsolo"))):(clearTimeout(s.timers.show),delete P.origin,G&&!d(A+'[tracking="true"]:visible',h.solo).not(M).length&&(d(b).unbind("mousemove.qtip"),G=f),s.blur(c)),h.effect===f||n===f?(M[g](),t.call(M)):d.isFunction(h.effect)?(M.stop(1,1),h.effect.call(M,s),M.queue("fx",function(a){t(),a()})):M.fadeTo(90,a?1:0,t),a&&h.target.trigger("qtip-"+q+"-inactive"),s):s},show:function(a){return s.toggle(e,a)},hide:function(a){return s.toggle(f,a)},focus:function(a){if(!s.rendered)return s;var b=d(A),c=parseInt(M[0].style.zIndex,10),e=t.zindex+b.length,f=d.extend({},a),g;return M.hasClass(C)||R("focus",[e],f)&&(c!==e&&(b.each(function(){this.style.zIndex>c&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+C).qtip("blur",f)),M.addClass(C)[0].style.zIndex=e),s},blur:function(a){return M.removeClass(C),R("blur",[M.css("zIndex")],a),s},reposition:function(c,e){if(!s.rendered||K)return s;K=1;var g=i.position.target,h=i.position,j=h.my,k=h.at,q=h.adjust,r=q.method.split(" "),t=M.outerWidth(),w=M.outerHeight(),x=0,y=0,z=M.css("position")==="fixed",A=h.viewport,B={left:0,top:0},C=h.container,D=M[0].offsetWidth>0,E,F,G;if(d.isArray(g)&&g.length===2)k={x:m,y:l},B={left:g[0],top:g[1]};else if(g==="mouse"&&(c&&c.pageX||P.event.pageX))k={x:m,y:l},c=(c&&(c.type==="resize"||c.type==="scroll")?P.event:c&&c.pageX&&c.type==="mousemove"?c:v&&v.pageX&&(q.mouse||!c||!c.pageX)?{pageX:v.pageX,pageY:v.pageY}:!q.mouse&&P.origin&&P.origin.pageX&&i.show.distance?P.origin:c)||c||P.event||v||{},B={top:c.pageY,left:c.pageX};else{g==="event"&&c&&c.target&&c.type!=="scroll"&&c.type!=="resize"?P.target=d(c.target):g!=="event"&&(P.target=d(g.jquery?g:O.target)),g=P.target,g=d(g).eq(0);if(g.length===0)return s;g[0]===b||g[0]===a?(x=u.iOS?a.innerWidth:g.width(),y=u.iOS?a.innerHeight:g.height(),g[0]===a&&(B={top:(A||g).scrollTop(),left:(A||g).scrollLeft()})):u.imagemap&&g.is("area")?E=u.imagemap(s,g,k,u.viewport?r:f):u.svg&&typeof g[0].xmlbase=="string"?E=u.svg(s,g,k,u.viewport?r:f):(x=g.outerWidth(),y=g.outerHeight(),B=u.offset(g,C)),E&&(x=E.width,y=E.height,F=E.offset,B=E.position);if(u.iOS>3.1&&u.iOS<4.1||u.iOS>=4.3&&u.iOS<4.33||!u.iOS&&z)G=d(a),B.left-=G.scrollLeft(),B.top-=G.scrollTop();B.left+=k.x===o?x:k.x===p?x/2:0,B.top+=k.y===n?y:k.y===p?y/2:0}return B.left+=q.x+(j.x===o?-t:j.x===p?-t/2:0),B.top+=q.y+(j.y===n?-w:j.y===p?-w/2:0),u.viewport?(B.adjusted=u.viewport(s,B,h,x,y,t,w),F&&B.adjusted.left&&(B.left+=F.left),F&&B.adjusted.top&&(B.top+=F.top)):B.adjusted={left:0,top:0},R("move",[B,A.elem||A],c)?(delete B.adjusted,e===f||!D||isNaN(B.left)||isNaN(B.top)||g==="mouse"||!d.isFunction(h.effect)?M.css(B):d.isFunction(h.effect)&&(h.effect.call(M,s,d.extend({},B)),M.queue(function(a){d(this).css({opacity:"",height:""}),d.browser.msie&&this.style.removeAttribute("filter"),a()})),K=0,s):s},redraw:function(){if(s.rendered<1||L)return s;var a=i.style,b=i.position.container,c,d,e,f;return L=1,R("redraw"),a.height&&M.css(k,a.height),a.width?M.css(j,a.width):(M.css(j,"").appendTo(H),d=M.width(),d%2<1&&(d+=1),e=M.css("max-width")||"",f=M.css("min-width")||"",c=(e+f).indexOf("%")>-1?b.width()/100:0,e=(e.indexOf("%")>-1?c:1)*parseInt(e,10)||d,f=(f.indexOf("%")>-1?c:1)*parseInt(f,10)||0,d=e+f?Math.min(Math.max(d,f),e):d,M.css(j,Math.round(d)).appendTo(b)),R("redrawn"),L=0,s},disable:function(a){return"boolean"!=typeof a&&(a=!M.hasClass(z)&&!P.disabled),s.rendered?(M.toggleClass(z,a),d.attr(M[0],"aria-disabled",a)):P.disabled=!!a,s},enable:function(){return s.disable(f)},destroy:function(){var a=h[0],b=d.attr(a,F),c=h.data("qtip");s.destroyed=e,s.rendered&&(M.stop(1,0).remove(),d.each(s.plugins,function(){this.destroy&&this.destroy()})),clearTimeout(s.timers.show),clearTimeout(s.timers.hide),_();if(!c||s===c)d.removeData(a,"qtip"),i.suppress&&b&&(d.attr(a,"title",b),h.removeAttr(F)),h.removeAttr("aria-describedby");return h.unbind(".qtip-"+q),delete w[s.id],h}})}function K(a,c){var h,i,j,k,l,m=d(this),n=d(b.body),o=this===b?n:m,p=m.metadata?m.metadata(c.metadata):g,q=c.metadata.type==="html5"&&p?p[c.metadata.name]:g,r=m.data(c.metadata.name||"qtipopts");try{r=typeof r=="string"?d.parseJSON(r):r}catch(s){}k=d.extend(e,{},t.defaults,c,typeof r=="object"?I(r):g,I(q||p)),i=k.position,k.id=a;if("boolean"==typeof k.content.text){j=m.attr(k.content.attr);if(k.content.attr!==f&&j)k.content.text=j;else return f}i.container.length||(i.container=n),i.target===f&&(i.target=o),k.show.target===f&&(k.show.target=o),k.show.solo===e&&(k.show.solo=i.container.closest("body")),k.hide.target===f&&(k.hide.target=o),k.position.viewport===e&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new u.Corner(i.at),i.my=new u.Corner(i.my);if(d.data(this,"qtip"))if(k.overwrite)m.qtip("destroy");else if(k.overwrite===f)return f;return k.suppress&&(l=d.attr(this,"title"))&&d(this).removeAttr("title").attr(F,l).attr("title",""),h=new J(m,k,a,!!j),d.data(this,"qtip",h),m.bind("remove.qtip-"+a+" removeqtip.qtip-"+a,function(){h.destroy()}),h}function L(a){var b=this,c=a.elements.tooltip,g=a.options.content.ajax,h=t.defaults.content.ajax,i=".qtip-ajax",j=/)<[^<]*)*<\/script>/gi,k=e,l=f,m;a.checks.ajax={"^content.ajax":function(a,d,e){d==="ajax"&&(g=e),d==="once"?b.init():g&&g.url?b.load():c.unbind(i)}},d.extend(b,{init:function(){return g&&g.url&&c.unbind(i)[g.once?"one":"bind"]("tooltipshow"+i,b.load),b},load:function(c){function r(){var b;if(a.destroyed)return;k=f,p&&(l=e,a.show(c.originalEvent)),(b=h.complete||g.complete)&&d.isFunction(b)&&b.apply(g.context||a,arguments)}function s(b,c,e){var f;if(a.destroyed)return;o&&"string"==typeof b&&(b=d("
").append(b.replace(j,"")).find(o)),(f=h.success||g.success)&&d.isFunction(f)?f.call(g.context||a,b,c,e):a.set("content.text",b)}function t(b,c,d){if(a.destroyed||b.status===0)return;a.set("content.text",c+": "+d)}if(l){l=f;return}var i=g.url.lastIndexOf(" "),n=g.url,o,p=!g.loading&&k;if(p)try{c.preventDefault()}catch(q){}else if(c&&c.isDefaultPrevented())return b;m&&m.abort&&m.abort(),i>-1&&(o=n.substr(i),n=n.substr(0,i)),m=d.ajax(d.extend({error:h.error||t,context:a},g,{url:n,success:s,complete:r}))},destroy:function(){m&&m.abort&&m.abort(),a.destroyed=e}}),b.init()}function M(a,b,c){var d=Math.ceil(b/2),e=Math.ceil(c/2),f={bottomright:[[0,0],[b,c],[b,0]],bottomleft:[[0,0],[b,0],[0,c]],topright:[[0,c],[b,0],[b,c]],topleft:[[0,0],[0,c],[b,c]],topcenter:[[0,c],[d,0],[b,c]],bottomcenter:[[0,0],[b,0],[d,c]],rightcenter:[[0,0],[b,e],[0,c]],leftcenter:[[b,0],[b,c],[0,e]]};return f.lefttop=f.bottomright,f.righttop=f.bottomleft,f.leftbottom=f.topright,f.rightbottom=f.topleft,f[a.string()]}function N(a,b){function D(a){var b=v.is(":visible");v.show(),a(),v.toggle(b)}function E(){x.width=r.height,x.height=r.width}function F(){x.width=r.width,x.height=r.height}function G(b,d,g,j){if(!t.tip)return;var k=q.corner.clone(),u=g.adjusted,v=a.options.position.adjust.method.split(" "),x=v[0],y=v[1]||v[0],z={left:f,top:f,x:0,y:0},A,B={},C;q.corner.fixed!==e&&(x===s&&k.precedance===h&&u.left&&k.y!==p?k.precedance=k.precedance===h?i:h:x!==s&&u.left&&(k.x=k.x===p?u.left>0?m:o:k.x===m?o:m),y===s&&k.precedance===i&&u.top&&k.x!==p?k.precedance=k.precedance===i?h:i:y!==s&&u.top&&(k.y=k.y===p?u.top>0?l:n:k.y===l?n:l),k.string()!==w.corner.string()&&(w.top!==u.top||w.left!==u.left)&&q.update(k,f)),A=q.position(k,u),A[k.x]+=I(k,k.x),A[k.y]+=I(k,k.y),A.right!==c&&(A.left=-A.right),A.bottom!==c&&(A.top=-A.bottom),A.user=Math.max(0,r.offset);if(z.left=x===s&&!!u.left)k.x===p?B["margin-left"]=z.x=A["margin-left"]-u.left:(C=A.right!==c?[u.left,-A.left]:[-u.left,A.left],(z.x=Math.max(C[0],C[1]))>C[0]&&(g.left-=u.left,z.left=f),B[A.right!==c?o:m]=z.x);if(z.top=y===s&&!!u.top)k.y===p?B["margin-top"]=z.y=A["margin-top"]-u.top:(C=A.bottom!==c?[u.top,-A.top]:[-u.top,A.top],(z.y=Math.max(C[0],C[1]))>C[0]&&(g.top-=u.top,z.top=f),B[A.bottom!==c?n:l]=z.y);t.tip.css(B).toggle(!(z.x&&z.y||k.x===p&&z.y||k.y===p&&z.x)),g.left-=A.left.charAt?A.user:x!==s||z.top||!z.left&&!z.top?A.left:0,g.top-=A.top.charAt?A.user:y!==s||z.left||!z.left&&!z.top?A.top:0,w.left=u.left,w.top=u.top,w.corner=k.clone()}function H(){var b=r.corner,c=a.options.position,d=c.at,g=c.my.string?c.my.string():c.my;return b===f||g===f&&d===f?f:(b===e?q.corner=new u.Corner(g):b.string||(q.corner=new u.Corner(b),q.corner.fixed=e),w.corner=new u.Corner(q.corner.string()),q.corner.string()!=="centercenter")}function I(a,b,c){b=b?b:a[a.precedance];var d=t.titlebar&&a.y===l,e=d?t.titlebar:v,f="border-"+b+"-width",g=function(a){return parseInt(a.css(f),10)},h;return D(function(){h=(c?g(c):g(t.content)||g(e)||g(v))||0}),h}function J(a){var b=t.titlebar&&a.y===l,c=b?t.titlebar:t.content,e=d.browser.mozilla,f=e?"-moz-":d.browser.webkit?"-webkit-":"",g="border-radius-"+a.y+a.x,h="border-"+a.y+"-"+a.x+"-radius",i=function(a){return parseInt(c.css(a),10)||parseInt(v.css(a),10)},j;return D(function(){j=i(h)||i(f+h)||i(f+g)||i(g)||0}),j}function K(a){function z(a,b,c){var d=a.css(b)||n;return c&&d===a.css(c)?f:j.test(d)?f:d}var b,c,g,h=t.tip.css("cssText",""),i=a||q.corner,j=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,k="border-"+i[i.precedance]+"-color",m="background-color",n="transparent",o=" !important",s=t.titlebar,u=s&&(i.y===l||i.y===p&&h.position().top+x.height/2+r.offset-1,f=c*(e?.5:1),g=Math.pow,h=Math.round,l,m,n,o=Math.sqrt(g(f,2)+g(d,2)),q=[z/f*o,z/d*o];return q[2]=Math.sqrt(g(q[0],2)-g(z,2)),q[3]=Math.sqrt(g(q[1],2)-g(z,2)),l=o+q[2]+q[3]+(e?0:q[0]),m=l/o,n=[h(m*d),h(m*c)],{height:n[b?0:1],width:n[b?1:0]}}function N(a,b,c){return"'}var q=this,r=a.options.style.tip,t=a.elements,v=t.tooltip,w={top:0,left:0},x={width:r.width,height:r.height},y={},z=r.border||0,A=".qtip-tip",B=!!(d("")[0]||{}).getContext,C;q.corner=g,q.mimic=g,q.border=z,q.offset=r.offset,q.size=x,a.checks.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){q.init()||q.destroy(),a.reposition()},"^style.tip.(height|width)$":function(){x={width:r.width,height:r.height},q.create(),q.update(),a.reposition()},"^content.title.text|style.(classes|widget)$":function(){t.tip&&t.tip.length&&q.update()}},d.extend(q,{init:function(){var a=H()&&(B||d.browser.msie);return a&&(q.create(),q.update(),v.unbind(A).bind("tooltipmove"+A,G),B||v.bind("tooltipredraw tooltipredrawn",function(a){a.type==="tooltipredraw"?(C=t.tip.html(),t.tip.html("")):t.tip.html(C)})),a},create:function(){var a=x.width,b=x.height,c;t.tip&&t.tip.remove(),t.tip=d("
",{"class":"ui-tooltip-tip"}).css({width:a,height:b}).prependTo(v),B?d("").appendTo(t.tip)[0].getContext("2d").save():(c=N("shape",'coordorigin="0,0"',"position:absolute;"),t.tip.html(c+c),d("*",t.tip).bind("click mousedown",function(a){a.stopPropagation()}))},update:function(a,b){var c=t.tip,j=c.children(),k=x.width,s=x.height,A=r.mimic,C=Math.round,D,G,H,J,O;a||(a=w.corner||q.corner),A===f?A=a:(A=new u.Corner(A),A.precedance=a.precedance,A.x==="inherit"?A.x=a.x:A.y==="inherit"?A.y=a.y:A.x===A.y&&(A[a.precedance]=a[a.precedance])),D=A.precedance,a.precedance===h?E():F(),t.tip.css({width:k=x.width,height:s=x.height}),K(a),y.border!=="transparent"?(z=I(a,g),r.border===0&&z>0&&(y.fill=y.border),q.border=z=r.border!==e?r.border:z):q.border=z=0,H=M(A,k,s),q.size=O=L(a),c.css(O),a.precedance===i?J=[C(A.x===m?z:A.x===o?O.width-k-z:(O.width-k)/2),C(A.y===l?O.height-s:0)]:J=[C(A.x===m?O.width-k:0),C(A.y===l?z:A.y===n?O.height-s-z:(O.height-s)/2)],B?(j.attr(O),G=j[0].getContext("2d"),G.restore(),G.save(),G.clearRect(0,0,3e3,3e3),G.fillStyle=y.fill,G.strokeStyle=y.border,G.lineWidth=z*2,G.lineJoin="miter",G.miterLimit=100,G.translate(J[0],J[1]),G.beginPath(),G.moveTo(H[0][0],H[0][1]),G.lineTo(H[1][0],H[1][1]),G.lineTo(H[2][0],H[2][1]),G.closePath(),z&&(v.css("background-clip")==="border-box"&&(G.strokeStyle=y.fill,G.stroke()),G.strokeStyle=y.border,G.stroke()),G.fill()):(H="m"+H[0][0]+","+H[0][1]+" l"+H[1][0]+","+H[1][1]+" "+H[2][0]+","+H[2][1]+" xe",J[2]=z&&/^(r|b)/i.test(a.string())?parseFloat(d.browser.version,10)===8?2:1:0,j.css({coordsize:k+z+" "+(s+z),antialias:""+(A.string().indexOf(p)>-1),left:J[0],top:J[1],width:k+z,height:s+z}).each(function(a){var b=d(this);b[b.prop?"prop":"attr"]({coordsize:k+z+" "+(s+z),path:H,fillcolor:y.fill,filled:!!a,stroked:!a}).toggle(!!z||!!a),!a&&b.html()===""&&b.html(N("stroke",'weight="'+z*2+'px" color="'+y.border+'" miterlimit="1000" joinstyle="miter"'))})),b!==f&&q.position(a)},position:function(a){var b=t.tip,c={},e=Math.max(0,r.offset),g,n,o;return r.corner===f||!b?f:(a=a||q.corner,g=a.precedance,n=L(a),o=[a.x,a.y],g===h&&o.reverse(),d.each(o,function(b,d){var f,h,o;d===p?(f=g===i?m:l,c[f]="50%",c["margin-"+f]=-Math.round(n[g===i?j:k]/2)+e):(f=I(a,d),h=I(a,d,t.content),o=J(a),c[d]=b?h:e+(o>f?o:-f))}),c[a[g]]-=n[g===h?j:k],b.css({top:"",bottom:"",left:"",right:"",margin:""}).css(c),c)},destroy:function(){t.tip&&t.tip.remove(),t.tip=!1,v.unbind(A)}}),q.init()}function O(c){function s(){q=d(p,j).not("[disabled]").map(function(){return typeof this.focus=="function"?this:null})}function t(a){q.length<1&&a.length?a.not("body").blur():q.first().focus()}function v(a){var b=d(a.target),c=b.closest(".qtip"),e;e=c.length<1?f:parseInt(c[0].style.zIndex,10)>parseInt(j[0].style.zIndex,10),!e&&d(a.target).closest(A)[0]!==j[0]&&t(b)}var g=this,h=c.options.show.modal,i=c.elements,j=i.tooltip,k="#qtip-overlay",l=".qtipmodal",m=l+c.id,n="is-modal-qtip",o=d(b.body),p=u.modal.focusable.join(","),q={},r;c.checks.modal={"^show.modal.(on|blur)$":function(){g.init(),i.overlay.toggle(j.is(":visible"))},"^content.text$":function(){s()}},d.extend(g,{init:function(){return h.on?(r=g.create(),j.attr(n,e).css("z-index",u.modal.zindex+d(A+"["+n+"]").length).unbind(l).unbind(m).bind("tooltipshow"+l+" tooltiphide"+l,function(a,b,c){var e=a.originalEvent;if(a.target===j[0])if(e&&a.type==="tooltiphide"&&/mouse(leave|enter)/.test(e.type)&&d(e.relatedTarget).closest(r[0]).length)try{a.preventDefault()}catch(f){}else(!e||e&&!e.solo)&&g[a.type.replace("tooltip","")](a,c)}).bind("tooltipfocus"+l,function(a){if(a.isDefaultPrevented()||a.target!==j[0])return;var b=d(A).filter("["+n+"]"),c=u.modal.zindex+b.length,e=parseInt(j[0].style.zIndex,10);r[0].style.zIndex=c-2,b.each(function(){this.style.zIndex>e&&(this.style.zIndex-=1)}),b.end().filter("."+C).qtip("blur",a.originalEvent),j.addClass(C)[0].style.zIndex=c;try{a.preventDefault()}catch(f){}}).bind("tooltiphide"+l,function(a){a.target===j[0]&&d("["+n+"]").filter(":visible").not(j).last().qtip("focus",a)}),h.escape&&d(b).unbind(m).bind("keydown"+m,function(a){a.keyCode===27&&j.hasClass(C)&&c.hide(a)}),h.blur&&i.overlay.unbind(m).bind("click"+m,function(a){j.hasClass(C)&&c.hide(a)}),s(),g):g},create:function(){function c(){r.css({height:d(a).height(),width:d(a).width()})}var b=d(k);return b.length?i.overlay=b.insertAfter(d(A).last()):(r=i.overlay=d("
",{id:k.substr(1),html:"
",mousedown:function(){return f}}).hide().insertAfter(d(A).last()),d(a).unbind(l).bind("resize"+l,c),c(),r)},toggle:function(a,b,c){if(a&&a.isDefaultPrevented())return g;var i=h.effect,k=b?"show":"hide",l=r.is(":visible"),p=d("["+n+"]").filter(":visible").not(j),q;return r||(r=g.create()),r.is(":animated")&&l===b||!b&&p.length?g:(b?(r.css({left:0,top:0}),r.toggleClass("blurs",h.blur),h.stealfocus!==f&&(o.bind("focusin"+m,v),t(d("body :focus")))):o.unbind("focusin"+m),r.stop(e,f),d.isFunction(i)?i.call(r,b):i===f?r[k]():r.fadeTo(parseInt(c,10)||90,b?1:0,function(){b||d(this).hide()}),b||r.queue(function(a){r.css({left:"",top:""}),a()}),g)},show:function(a,b){return g.toggle(a,e,b)},hide:function(a,b){return g.toggle(a,f,b)},destroy:function(){var a=r;return a&&(a=d("["+n+"]").not(j).length<1,a?(i.overlay.remove(),d(b).unbind(l)):i.overlay.unbind(l+c.id),o.undelegate("*","focusin"+m)),j.removeAttr(n).unbind(l)}}),g.init()}function P(a){var b=this,c=a.elements,e=c.tooltip,f=".bgiframe-"+a.id;d.extend(b,{init:function(){c.bgiframe=d(''),c.bgiframe.appendTo(e),e.bind("tooltipmove"+f,b.adjust)},adjust:function(){var b=a.get("dimensions"),d=a.plugins.tip,f=c.tip,g,h;h=parseInt(e.css("border-left-width"),10)||0,h={left:-h,top:-h},d&&f&&(g=d.corner.precedance==="x"?["width","left"]:["height","top"],h[g[1]]-=f[g[0]]()),c.bgiframe.css(h).css(b)},destroy:function(){c.bgiframe.remove(),e.unbind(f)}}),b.init()}var e=!0,f=!1,g=null,h="x",i="y",j="width",k="height",l="top",m="left",n="bottom",o="right",p="center",q="flip",r="flipinvert",s="shift",t,u,v,w={},x="ui-tooltip",y="ui-widget",z="ui-state-disabled",A="div.qtip."+x,B=x+"-default",C=x+"-focus",D=x+"-hover",E="_replacedByqTip",F="oldtitle",G,H;H=d("
",{id:"qtip-rcontainer"}),d(function(){H.appendTo(b.body)}),t=d.fn.qtip=function(a,b,h){var i=(""+a).toLowerCase(),j=g,k=d.makeArray(arguments).slice(1),l=k[k.length-1],m=this[0]?d.data(this[0],"qtip"):g;if(!arguments.length&&m||i==="api")return m;if("string"==typeof a)return this.each(function(){var a=d.data(this,"qtip");if(!a)return e;l&&l.timeStamp&&(a.cache.event=l);if(i!=="option"&&i!=="options"||!b)a[i]&&a[i].apply(a[i],k);else if(d.isPlainObject(b)||h!==c)a.set(b,h);else return j=a.get(b),f}),j!==g?j:this;if("object"==typeof a||!arguments.length)return m=I(d.extend(e,{},a)),t.bind.call(this,m,l)},t.bind=function(a,b){return this.each(function(g){function n(a){function b(){l.render(typeof a=="object"||h.show.ready),i.show.add(i.hide).unbind(k)}if(l.cache.disabled)return f;l.cache.event=d.extend({},a),l.cache.target=a?d(a.target):[c],h.show.delay>0?(clearTimeout(l.timers.show),l.timers.show=setTimeout(b,h.show.delay),j.show!==j.hide&&i.hide.bind(j.hide,function(){clearTimeout(l.timers.show)})):b()}var h,i,j,k,l,m;m=d.isArray(a.id)?a.id[g]:a.id,m=!m||m===f||m.length<1||w[m]?t.nextid++:w[m]=m,k=".qtip-"+m+"-create",l=K.call(this,m,a);if(l===f)return e;h=l.options,d.each(u,function(){this.initialize==="initialize"&&this(l)}),i={show:h.show.target,hide:h.hide.target},j={show:d.trim(""+h.show.event).replace(/ /g,k+" ")+k,hide:d.trim(""+h.hide.event).replace(/ /g,k+" ")+k},/mouse(over|enter)/i.test(j.show)&&!/mouse(out|leave)/i.test(j.hide)&&(j.hide+=" mouseleave"+k),i.show.bind("mousemove"+k,function(a){v={pageX:a.pageX,pageY:a.pageY,type:"mousemove"},l.cache.onTarget=e}),i.show.bind(j.show,n),(h.show.ready||h.prerender)&&n(b)})},u=t.plugins={Corner:function(a){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,p).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase();var b=a.charAt(0);this.precedance=b==="t"||b==="b"?i:h,this.string=function(){return this.precedance===i?this.y+this.x:this.x+this.y},this.abbrev=function(){var a=this.x.substr(0,1),b=this.y.substr(0,1);return a===b?a:this.precedance===i?b+a:a+b},this.invertx=function(a){this.x=this.x===m?o:this.x===o?m:a||this.x},this.inverty=function(a){this.y=this.y===l?n:this.y===n?l:a||this.y},this.clone=function(){return{x:this.x,y:this.y,precedance:this.precedance,string:this.string,abbrev:this.abbrev,clone:this.clone,invertx:this.invertx,inverty:this.inverty}}},offset:function(a,b){function j(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}var c=a.offset(),e=a.closest("body")[0],f=b,g,h,i;if(f){do f.css("position")!=="static"&&(h=f.position(),c.left-=h.left+(parseInt(f.css("borderLeftWidth"),10)||0)+(parseInt(f.css("marginLeft"),10)||0),c.top-=h.top+(parseInt(f.css("borderTopWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0),!g&&(i=f.css("overflow"))!=="hidden"&&i!=="visible"&&(g=f));while((f=d(f[0].offsetParent)).length);g&&g[0]!==e&&j(g,1)}return c},iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||f,fn:{attr:function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?d.attr(c,F):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(F,b))}return d.fn["attr"+E].apply(this,arguments)},clone:function(a){var b=d([]),c="title",e=d.fn["clone"+E].apply(this,arguments);return a||e.filter("["+F+"]").attr("title",function(){return d.attr(this,F)}).removeAttr(F),e}}},d.each(u.fn,function(a,b){if(!b||d.fn[a+E])return e;var c=d.fn[a+E]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+E]=d.cleanData,d.cleanData=function(a){for(var b=0,e;(e=a[b])!==c;b++)try{d(e).triggerHandler("removeqtip")}catch(f){}d["cleanData"+E](a)}),t.version="@VERSION",t.nextid=0,t.inactiveEvents="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),t.zindex=15e3,t.defaults={prerender:f,id:f,overwrite:e,suppress:e,content:{text:e,attr:"title",title:{text:f,button:f}},position:{my:"top left",at:"bottom right",target:f,container:f,viewport:f,adjust:{x:0,y:0,mouse:e,resize:e,method:"flip flip"},effect:function(a,b,c){d(this).animate(b,{duration:200,queue:f})}},show:{target:f,event:"mouseenter",effect:e,delay:90,solo:f,ready:f,autofocus:f},hide:{target:f,event:"mouseleave",effect:e,delay:0,fixed:f,inactive:f,leave:"window",distance:f},style:{classes:"",widget:f,width:f,height:f,def:e},events:{render:g,move:g,show:g,hide:g,toggle:g,visible:g,hidden:g,focus:g,blur:g}},u.svg=function(a,c,e,f){var g=d(b),h=c[0],i={width:0,height:0,position:{top:1e10,left:1e10}},j,k,l,m,n;while(!h.getBBox)h=h.parentNode;if(h.getBBox&&h.parentNode){j=h.getBBox(),k=h.getScreenCTM(),l=h.farthestViewportElement||h;if(!l.createSVGPoint)return i;m=l.createSVGPoint(),m.x=j.x,m.y=j.y,n=m.matrixTransform(k),i.position.left=n.x,i.position.top=n.y,m.x+=j.width,m.y+=j.height,n=m.matrixTransform(k),i.width=n.x-i.position.left,i.height=n.y-i.position.top,i.position.left+=g.scrollLeft(),i.position.top+=g.scrollTop()}return i},u.ajax=function(a){var b=a.plugins.ajax;return"object"==typeof b?b:a.plugins.ajax=new L(a)},u.ajax.initialize="render",u.ajax.sanitize=function(a){var b=a.content,c;b&&"ajax"in b&&(c=b.ajax,typeof c!="object"&&(c=a.content.ajax={url:c}),"boolean"!=typeof c.once&&c.once&&(c.once=!!c.once))},d.extend(e,t.defaults,{content:{ajax:{loading:e,once:e}}}),u.tip=function(a){var b=a.plugins.tip;return"object"==typeof b?b:a.plugins.tip=new N(a)},u.tip.initialize="render",u.tip.sanitize=function(a){var b=a.style,c;b&&"tip"in b&&(c=a.style.tip,typeof c!="object"&&(a.style.tip={corner:c}),/string|boolean/i.test(typeof c.corner)||(c.corner=e),typeof c.width!="number"&&delete c.width,typeof c.height!="number"&&delete c.height,typeof c.border!="number"&&c.border!==e&&delete c.border,typeof c.offset!="number"&&delete c.offset)},d.extend(e,t.defaults,{style:{tip:{corner:e,mimic:f,width:6,height:6,border:e,offset:0}}}),u.modal=function(a){var b=a.plugins.modal;return"object"==typeof b?b:a.plugins.modal=new O(a)},u.modal.initialize="render",u.modal.sanitize=function(a){a.show&&(typeof a.show.modal!="object"?a.show.modal={on:!!a.show.modal}:typeof a.show.modal.on=="undefined"&&(a.show.modal.on=e))},u.modal.zindex=t.zindex-200,u.modal.focusable=["a[href]","area[href]","input","select","textarea","button","iframe","object","embed","[tabindex]","[contenteditable]"],d.extend(e,t.defaults,{show:{modal:{on:f,effect:e,blur:e,stealfocus:e,escape:e}}}),u.viewport=function(c,d,e,f,g,q,t){function L(a,b,c,e,f,g,h,i,j){var k=d[f],l=w[a],m=y[a],n=c===s,o=-E.offset[f]+D.offset[f]+D["scroll"+f],q=l===f?j:l===g?-j:-j/2,t=m===f?i:m===g?-i:-i/2,u=G&&G.size?G.size[h]||0:0,v=G&&G.corner&&G.corner.precedance===a&&!n?u:0,x=o-k+v,z=k+j-D[h]-o+v,A=q-(w.precedance===a||l===w[b]?t:0)-(m===p?i/2:0);return n?(v=G&&G.corner&&G.corner.precedance===b?u:0,A=(l===f?1:-1)*q-v,d[f]+=x>0?x:z>0?-z:0,d[f]=Math.max(-E.offset[f]+D.offset[f]+(v&&G.corner[a]===p?G.offset:0),k-A,Math.min(Math.max(-E.offset[f]+D.offset[f]+D[h],k+A),d[f]))):(e*=c===r?2:0,x>0&&(l!==f||z>0)?(d[f]-=A+e,J["invert"+a](f)):z>0&&(l!==g||x>0)&&(d[f]-=(l===p?-A:A)+e,J["invert"+a](g)),d[f]z&&(d[f]=k,J=w.clone())),d[f]-k}var u=e.target,v=c.elements.tooltip,w=e.my,y=e.at,z=e.adjust,A=z.method.split(" "),B=A[0],C=A[1]||A[0],D=e.viewport,E=e.container,F=c.cache,G=c.plugins.tip,H={left:0,top:0},I,J,K;if(!D.jquery||u[0]===a||u[0]===b.body||z.method==="none")return H;I=v.css("position")==="fixed",D={elem:D,height:D[(D[0]===a?"h":"outerH")+"eight"](),width:D[(D[0]===a?"w":"outerW")+"idth"](),scrollleft:I?0:D.scrollLeft(),scrolltop:I?0:D.scrollTop(),offset:D.offset()||{left:0,top:0}},E={elem:E,scrollLeft:E.scrollLeft(),scrollTop:E.scrollTop(),offset:E.offset()||{left:0,top:0}};if(B!=="shift"||C!=="shift")J=w.clone();return H={left:B!=="none"?L(h,i,B,z.x,m,o,j,f,q):0,top:C!=="none"?L(i,h,C,z.y,l,n,k,g,t):0},J&&F.lastClass!==(K=x+"-pos-"+J.abbrev())&&v.removeClass(c.cache.lastClass).addClass(c.cache.lastClass=K),H},u.imagemap=function(a,b,c,e){function v(a,b,c){var d=0,e=1,f=1,g=0,h=0,i=a.width,j=a.height;while(i>0&&j>0&&e>0&&f>0){i=Math.floor(i/2),j=Math.floor(j/2),c.x===m?e=i:c.x===o?e=a.width-i:e+=Math.floor(i/2),c.y===l?f=j:c.y===n?f=a.height-j:f+=Math.floor(j/2),d=b.length;while(d--){if(b.length<2)break;g=b[d][0]-a.position.left,h=b[d][1]-a.position.top,(c.x===m&&g>=e||c.x===o&&g<=e||c.x===p&&(ga.width-e)||c.y===l&&h>=f||c.y===n&&h<=f||c.y===p&&(ha.height-f))&&b.splice(d,1)}}return{left:b[0][0],top:b[0][1]}}b.jquery||(b=d(b));var f=a.cache.areas={},g=(b[0].shape||b.attr("shape")).toLowerCase(),h=b[0].coords||b.attr("coords"),i=h.split(","),j=[],k=d('img[usemap="#'+b.parent("map").attr("name")+'"]'),q=k.offset(),r={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10}},s=0,t=0,u;q.left+=Math.ceil((k.outerWidth()-k.width())/2),q.top+=Math.ceil((k.outerHeight()-k.height())/2);if(g==="poly"){s=i.length;while(s--)t=[parseInt(i[--s],10),parseInt(i[s+1],10)],t[0]>r.position.right&&(r.position.right=t[0]),t[0]r.position.bottom&&(r.position.bottom=t[1]),t[1] 0 ? JSON.stringify(rawInputLst) : '', +*/ + function(dataFromBackend) { + var trace = dataFromBackend.trace; + + // don't enter visualize mode if there are killer errors: + if (!trace || + (trace.length == 0) || + (trace[trace.length - 1].event == 'uncaught_exception')) { + + handleUncaughtExceptionFunc(trace); + + if (trace.length == 1) { + alert(trace[0].exception_msg); + } + else if (trace[trace.length - 1].exception_msg) { + alert(trace[trace.length - 1].exception_msg); + } + else { + alert("Unknown error. Reload to try again," + + "or report a bug to philip@pgbovine.net\n\n" + + "(Click the 'Generate URL' button to include a " + + "unique URL in your email bug report.)"); + } + } + else { + // fail-soft to prevent running off of the end of trace + if (frontendOptionsObj.startingInstruction >= trace.length) { + frontendOptionsObj.startingInstruction = 0; + } + myVisualizer = new ExecutionVisualizer(outputDiv, dataFromBackend, frontendOptionsObj); + + // set keyboard bindings + // VERY IMPORTANT to clear and reset this every time or + // else the handlers might be bound multiple times + $(document).unbind('keydown'); + $(document).keydown(function(k) { + if (k.keyCode == 37) { // left arrow + if (myVisualizer.stepBack()) { + k.preventDefault(); // don't horizontally scroll the display + } + } + else if (k.keyCode == 39) { // right arrow + if (myVisualizer.stepForward()) { + k.preventDefault(); // don't horizontally scroll the display + } + } + }); + + handleSuccessFunc(); + } + }, + "json"); +} diff --git a/embed/js/opt-frontend.js b/embed/js/opt-frontend.js new file mode 100644 index 0000000..2ad2739 --- /dev/null +++ b/embed/js/opt-frontend.js @@ -0,0 +1,598 @@ +/* + +Online Python Tutor +https://github.com/pgbovine/OnlinePythonTutor/ + +Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + + + +// Pre-reqs: +// - pytutor.js +// - jquery.ba-bbq.min.js +// - opt-frontend-common.js +// should all be imported BEFORE this file + +var appMode = 'edit'; // 'edit', 'display', or 'display_no_frills' + +var preseededCurInstr = null; // if you passed in a 'curInstr=' in the URL, then set this var + +var myVisualizer = null; // singleton ExecutionVisualizer instance + + +function enterEditMode() { + $.bbq.pushState({ mode: 'edit' }, 2 /* completely override other hash strings to keep URL clean */); +} + +function enterDisplayNoFrillsMode() { + $.bbq.pushState({ mode: 'display_no_frills' }, 2 /* completely override other hash strings to keep URL clean */); +} + +var pyInputCodeMirror; // CodeMirror object that contains the input text + +function setCodeMirrorVal(dat) { + pyInputCodeMirror.setValue(dat.rtrim() /* kill trailing spaces */); + $('#urlOutput,#embedCodeOutput').val(''); + + // also scroll to top to make the UI more usable on smaller monitors + $(document).scrollTop(0); +} + + +$(document).ready(function() { + + $("#embedLinkDiv").hide(); + + pyInputCodeMirror = CodeMirror(document.getElementById('codeInputPane'), { + mode: + {name: "python", + version: 3, + singleLineStringErrors: false + }, + lineNumbers: true, + indentUnit: 3, + tabSize: 3, + matchBrackets: true, + extraKeys: { + Tab: function(cm) { + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces, "end", "+input"); + } + } + }); + + //pyInputCodeMirror.setSize(null, '240px'); + + + + // be friendly to the browser's forward and back buttons + // thanks to http://benalman.com/projects/jquery-bbq-plugin/ + $(window).bind("hashchange", function(e) { + appMode = $.bbq.getState('mode'); // assign this to the GLOBAL appMode + + if (appMode === undefined || appMode == 'edit') { + $("#pyInputPane").show(); + $("#pyOutputPane").hide(); + $("#embedLinkDiv").hide(); + + // destroy all annotation bubbles (NB: kludgy) + if (myVisualizer) { + myVisualizer.destroyAllAnnotationBubbles(); + } + } + else if (appMode == 'display') { + $("#pyInputPane").hide(); + $("#pyOutputPane").show(); + + $("#embedLinkDiv").show(); + + $('#executeBtn').html("Visualize Execution"); + $('#executeBtn').attr('disabled', false); + + + // do this AFTER making #pyOutputPane visible, or else + // jsPlumb connectors won't render properly + myVisualizer.updateOutput(); + + // customize edit button click functionality AFTER rendering (NB: awkward!) + $('#pyOutputPane #editCodeLinkDiv').show(); + $('#pyOutputPane #editBtn').click(function() { + enterEditMode(); + }); + } + else if (appMode == 'display_no_frills') { + $("#pyInputPane").hide(); + $("#pyOutputPane").show(); + $("#embedLinkDiv").show(); + } + else { + assert(false); + } + + $('#urlOutput,#embedCodeOutput').val(''); // clear to avoid stale values + }); + + function getRawInput() { + if (typeof window.stdinPane === "undefined") + return ""; + else return window.stdinPane.value; + } + + function executeCode(forceStartingInstr) { + var backend_script = null; + if ($('#pythonVersionSelector').val() == '2') { + backend_script = python2_backend_script; + } + else if ($('#pythonVersionSelector').val() == '3') { + backend_script = python3_backend_script; + } + // experimental KRAZY MODE!!! + else if ($('#pythonVersionSelector').val() == '2crazy') { + backend_script = python2crazy_backend_script; + } + + $('#executeBtn').html("Please wait ... processing your code"); + $('#executeBtn').attr('disabled', true); + $("#pyOutputPane").hide(); + $("#embedLinkDiv").hide(); + + var backendOptionsObj = {cumulative_mode: ($('#cumulativeModeSelector').val() == 'true'), + heap_primitives: ($('#heapPrimitivesSelector').val() == 'true'), + show_only_outputs: ($('#showOnlyOutputsSelector').val() == 'true'), + py_crazy_mode: ($('#pythonVersionSelector').val() == '2crazy'), + raw_input: getRawInput(), + origin: 'opt-frontend.js'}; + + + var startingInstruction = 0; + + // only do this at most ONCE, and then clear out preseededCurInstr + // NOP anyways if preseededCurInstr is 0 + if (preseededCurInstr) { + startingInstruction = preseededCurInstr; + preseededCurInstr = null; + } + + // forceStartingInstr overrides everything else + if (forceStartingInstr !== undefined) { + startingInstruction = forceStartingInstr; + } + + var frontendOptionsObj = {startingInstruction: startingInstruction, + // tricky: selector 'true' and 'false' values are strings! + disableHeapNesting: ($('#heapPrimitivesSelector').val() == 'true'), + drawParentPointers: ($('#drawParentPointerSelector').val() == 'true'), + textualMemoryLabels: ($('#textualMemoryLabelsSelector').val() == 'true'), + showOnlyOutputs: ($('#showOnlyOutputsSelector').val() == 'true'), + executeCodeWithRawInputFunc: executeCodeWithRawInput, + updateOutputCallback: function() {$('#urlOutput,#embedCodeOutput').val('');}, + + // undocumented experimental modes: + pyCrazyMode: ($('#pythonVersionSelector').val() == '2crazy'), + //allowEditAnnotations: true, + + highlightLines: true, + } + + function handleSuccessFunc() { + // also scroll to top to make the UI more usable on smaller monitors + $(document).scrollTop(0); + + $.bbq.pushState({ mode: 'display' }, 2 /* completely override other hash strings to keep URL clean */); + } + + function handleUncaughtExceptionFunc(trace) { + if (trace.length == 1) { + var errorLineNo = trace[0].line - 1; /* CodeMirror lines are zero-indexed */ + if (errorLineNo !== undefined) { + // highlight the faulting line in pyInputCodeMirror + pyInputCodeMirror.focus(); +/* CodeMirror 2 + pyInputCodeMirror.setCursor(errorLineNo, 0); + pyInputCodeMirror.setLineClass(errorLineNo, null, 'errorLine'); + + pyInputCodeMirror.setOption('onChange', function() { + pyInputCodeMirror.setLineClass(errorLineNo, null, null); // reset line back to normal + pyInputCodeMirror.setOption('onChange', null); // cancel + }); +*/ + /* CodeMirror 3 */ + var marked = pyInputCodeMirror.addLineClass(errorLineNo, null, 'errorLine'); + var hook = function(marked) { return function() { + pyInputCodeMirror.removeLineClass(marked, null, 'errorLine'); // reset line back to normal + pyInputCodeMirror.off('change', hook); // cancel + }} (marked); + pyInputCodeMirror.on('change', hook); + + } + + $('#executeBtn').html("Visualize Execution"); + $('#executeBtn').attr('disabled', false); + } + } + + executePythonCode(pyInputCodeMirror.getValue(), + backend_script, backendOptionsObj, + frontendOptionsObj, + 'pyOutputPane', + handleSuccessFunc, handleUncaughtExceptionFunc); + } + + function executeCodeFromScratch() { + // reset these globals + rawInputLst = []; + executeCode(); + } + + function executeCodeWithRawInput(rawInputStr, curInstr) { + enterDisplayNoFrillsMode(); + + // set some globals + rawInputLst.push(rawInputStr); + executeCode(curInstr); + } + + $("#executeBtn").attr('disabled', false); + $("#executeBtn").click(executeCodeFromScratch); + + + // canned examples + + $("#tutorialExampleLink").click(function() { + $.get("example-code/py_tutorial.txt", setCodeMirrorVal); + return false; + }); + + $("#strtokExampleLink").click(function() { + $.get("example-code/strtok.txt", setCodeMirrorVal); + return false; + }); + + $("#listCompLink").click(function() { + $.get("example-code/list-comp.txt", setCodeMirrorVal); + return false; + }); + + $("#fibonacciExampleLink").click(function() { + $.get("example-code/fib.txt", setCodeMirrorVal); + return false; + }); + + $("#memoFibExampleLink").click(function() { + $.get("example-code/memo_fib.txt", setCodeMirrorVal); + return false; + }); + + $("#factExampleLink").click(function() { + $.get("example-code/fact.txt", setCodeMirrorVal); + return false; + }); + + $("#filterExampleLink").click(function() { + $.get("example-code/filter.txt", setCodeMirrorVal); + return false; + }); + + $("#insSortExampleLink").click(function() { + $.get("example-code/ins_sort.txt", setCodeMirrorVal); + return false; + }); + + $("#aliasExampleLink").click(function() { + $.get("example-code/aliasing.txt", setCodeMirrorVal); + return false; + }); + + $("#happyExampleLink").click(function() { + $.get("example-code/happy.txt", setCodeMirrorVal); + return false; + }); + + $("#newtonExampleLink").click(function() { + $.get("example-code/sqrt.txt", setCodeMirrorVal); + return false; + }); + + $("#oopSmallExampleLink").click(function() { + $.get("example-code/oop_small.txt", setCodeMirrorVal); + return false; + }); + + $("#mapExampleLink").click(function() { + $.get("example-code/map.txt", setCodeMirrorVal); + return false; + }); + + $("#rawInputExampleLink").click(function() { + $.get("example-code/raw_input.txt", setCodeMirrorVal); + return false; + }); + + $("#oop1ExampleLink").click(function() { + $.get("example-code/oop_1.txt", setCodeMirrorVal); + return false; + }); + + $("#oop2ExampleLink").click(function() { + $.get("example-code/oop_2.txt", setCodeMirrorVal); + return false; + }); + + $("#inheritanceExampleLink").click(function() { + $.get("example-code/oop_inherit.txt", setCodeMirrorVal); + return false; + }); + + $("#sumExampleLink").click(function() { + $.get("example-code/sum.txt", setCodeMirrorVal); + return false; + }); + + $("#pwGcdLink").click(function() { + $.get("example-code/wentworth_gcd.txt", setCodeMirrorVal); + return false; + }); + + $("#pwSumListLink").click(function() { + $.get("example-code/wentworth_sumList.txt", setCodeMirrorVal); + return false; + }); + + $("#towersOfHanoiLink").click(function() { + $.get("example-code/towers_of_hanoi.txt", setCodeMirrorVal); + return false; + }); + + $("#pwTryFinallyLink").click(function() { + $.get("example-code/wentworth_try_finally.txt", setCodeMirrorVal); + return false; + }); + + $("#sumCubesLink").click(function() { + $.get("example-code/sum-cubes.txt", setCodeMirrorVal); + return false; + }); + + $("#decoratorsLink").click(function() { + $.get("example-code/decorators.txt", setCodeMirrorVal); + return false; + }); + + $("#genPrimesLink").click(function() { + $.get("example-code/gen_primes.txt", setCodeMirrorVal); + return false; + }); + + $("#genExprLink").click(function() { + $.get("example-code/genexpr.txt", setCodeMirrorVal); + return false; + }); + + + $('#closure1Link').click(function() { + $.get("example-code/closures/closure1.txt", setCodeMirrorVal); + return false; + }); + $('#closure2Link').click(function() { + $.get("example-code/closures/closure2.txt", setCodeMirrorVal); + return false; + }); + $('#closure3Link').click(function() { + $.get("example-code/closures/closure3.txt", setCodeMirrorVal); + return false; + }); + $('#closure4Link').click(function() { + $.get("example-code/closures/closure4.txt", setCodeMirrorVal); + return false; + }); + $('#closure5Link').click(function() { + $.get("example-code/closures/closure5.txt", setCodeMirrorVal); + return false; + }); + $('#lambdaParamLink').click(function() { + $.get("example-code/closures/lambda-param.txt", setCodeMirrorVal); + return false; + }); + $('#tortureLink').click(function() { + $.get("example-code/closures/student-torture.txt", setCodeMirrorVal); + return false; + }); + + + + $('#aliasing1Link').click(function() { + $.get("example-code/aliasing/aliasing1.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing2Link').click(function() { + $.get("example-code/aliasing/aliasing2.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing3Link').click(function() { + $.get("example-code/aliasing/aliasing3.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing4Link').click(function() { + $.get("example-code/aliasing/aliasing4.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing5Link').click(function() { + $.get("example-code/aliasing/aliasing5.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing6Link').click(function() { + $.get("example-code/aliasing/aliasing6.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing7Link').click(function() { + $.get("example-code/aliasing/aliasing7.txt", setCodeMirrorVal); + return false; + }); + $('#aliasing8Link').click(function() { + $.get("example-code/aliasing/aliasing8.txt", setCodeMirrorVal); + return false; + }); + + + $('#ll1Link').click(function() { + $.get("example-code/linked-lists/ll1.txt", setCodeMirrorVal); + return false; + }); + $('#ll2Link').click(function() { + $.get("example-code/linked-lists/ll2.txt", setCodeMirrorVal); + return false; + }); + $('#sumListLink').click(function() { + $.get("example-code/sum-list.txt", setCodeMirrorVal); + return false; + }); + + $('#varargsLink').click(function() { + $.get("example-code/varargs.txt", setCodeMirrorVal); + return false; + }); + + $('#forElseLink').click(function() { + $.get("example-code/for-else.txt", setCodeMirrorVal); + return false; + }); + + $('#nonlocalLink').click(function() { + $.get("example-code/nonlocal.txt", setCodeMirrorVal); + return false; + }); + + + var queryStrOptions = getQueryStringOptions(); + + if (queryStrOptions.preseededCode) { + setCodeMirrorVal(queryStrOptions.preseededCode); + } + else { + // select a canned example on start-up: + // $("#aliasExampleLink").trigger('click'); + } + + if (queryStrOptions.raw_input !== undefined) { + window.stdinPane.value = queryStrOptions.raw_input; + } + + // ugh, ugly tristate due to the possibility of each being undefined + if (queryStrOptions.pyState !== undefined) { + $('#pythonVersionSelector').val(queryStrOptions.pyState); + } + if (queryStrOptions.cumulativeState !== undefined) { + $('#cumulativeModeSelector').val(queryStrOptions.cumulativeState); + } + if (queryStrOptions.heapPrimitives !== undefined) { + $('#heapPrimitivesSelector').val(queryStrOptions.heapPrimitives); + } + if (queryStrOptions.drawParentPointers !== undefined) { + $('#drawParentPointerSelector').val(queryStrOptions.drawParentPointers); + } + if (queryStrOptions.textRefs !== undefined) { + $('#textualMemoryLabelsSelector').val(queryStrOptions.textRefs); + } + if (queryStrOptions.showOnlyOutputs !== undefined) { + $('#showOnlyOutputsSelector').val(queryStrOptions.showOnlyOutputs); + } + + + appMode = $.bbq.getState('mode'); // assign this to the GLOBAL appMode + if ((appMode == "display") && queryStrOptions.preseededCode /* jump to display only with pre-seeded code */) { + preseededCurInstr = queryStrOptions.preseededCurInstr; // ugly global + $("#executeBtn").trigger('click'); + } + else { + if (appMode === undefined) { + // default mode is 'edit', don't trigger a "hashchange" event + appMode = 'edit'; + } + else { + // fail-soft by killing all passed-in hashes and triggering a "hashchange" + // event, which will then go to 'edit' mode + $.bbq.removeState(); + } + } + + + // log a generic AJAX error handler + $(document).ajaxError(function() { + alert("Server error (possibly due to memory/resource overload). " + + "Report a bug to philip@pgbovine.net\n\n" + + "(Click the 'Generate URL' button to include a unique URL in your email bug report.)"); + + $('#executeBtn').html("Visualize Execution"); + $('#executeBtn').attr('disabled', false); + }); + + + // redraw connector arrows on window resize + $(window).resize(function() { + if (appMode == 'display') { + myVisualizer.redrawConnectors(); + } + }); + + $('#genUrlBtn').bind('click', function() { + var myArgs = {code: pyInputCodeMirror.getValue(), + mode: appMode, + //cumulative: $('#cumulativeModeSelector').val(), + //heapPrimitives: $('#heapPrimitivesSelector').val(), + //drawParentPointers: $('#drawParentPointerSelector').val(), + //textReferences: $('#textualMemoryLabelsSelector').val(), + //showOnlyOutputs: $('#showOnlyOutputsSelector').val(), + //py: $('#pythonVersionSelector').val() + raw_input: getRawInput(), + }; + + if (appMode == 'display') { + myArgs.curInstr = myVisualizer.curInstr; + } + + var urlStr = $.param.fragment(window.location.href, myArgs, 2 /* clobber all */); + $('#urlOutput').val(urlStr); + }); + + + $('#genEmbedBtn').bind('click', function() { + assert(appMode == 'display'); + var myArgs = {code: pyInputCodeMirror.getValue(), + cumulative: $('#cumulativeModeSelector').val(), + heapPrimitives: $('#heapPrimitivesSelector').val(), + drawParentPointers: $('#drawParentPointerSelector').val(), + textReferences: $('#textualMemoryLabelsSelector').val(), + showOnlyOutputs: $('#showOnlyOutputsSelector').val(), + py: $('#pythonVersionSelector').val(), + curInstr: myVisualizer.curInstr, + codeDivWidth: myVisualizer.DEFAULT_EMBEDDED_CODE_DIV_WIDTH, + codeDivHeight: myVisualizer.DEFAULT_EMBEDDED_CODE_DIV_HEIGHT, + }; + + var embedUrlStr = $.param.fragment(domain + "iframe-embed.html", myArgs, 2 /* clobber all */); + var iframeStr = ''; + $('#embedCodeOutput').val(iframeStr); + }); +}); + diff --git a/embed/js/pytutor.js b/embed/js/pytutor.js new file mode 100644 index 0000000..167906f --- /dev/null +++ b/embed/js/pytutor.js @@ -0,0 +1,3510 @@ +/* + +Online Python Tutor +https://github.com/pgbovine/OnlinePythonTutor/ + +Copyright (C) 2010-2013 Philip J. Guo (philip@pgbovine.net) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + + +/* To import, put this at the top of your HTML page: + + + + + + + + + + + + + + + + +*/ + + +/* Coding gotchas: + +- NEVER use naked $(__) or d3.select(__) statements to select DOM elements. + + ALWAYS use myViz.domRoot or myViz.domRootD3 for jQuery and D3, respectively. + + Otherwise things will break in weird ways when you have more than one visualization + embedded within a webpage, due to multiple matches in the global namespace. + + +- always use generateID to generate unique CSS IDs, or else things will break + when multiple ExecutionVisualizer instances are displayed on a webpage + +*/ + + +var SVG_ARROW_POLYGON = '0,3 12,3 12,0 18,5 12,10 12,7 0,7'; +var SVG_ARROW_HEIGHT = 10; // must match height of SVG_ARROW_POLYGON + +var curVisualizerID = 1; // global to uniquely identify each ExecutionVisualizer instance + +// domRootID is the string ID of the root element where to render this instance +// dat is data returned by the Python Tutor backend consisting of two fields: +// code - string of executed code +// trace - a full execution trace +// +// params is an object containing optional parameters, such as: +// jumpToEnd - if non-null, jump to the very end of execution +// startingInstruction - the (zero-indexed) execution point to display upon rendering +// hideOutput - hide "Program output" display +// codeDivHeight - maximum height of #pyCodeOutputDiv (in integer pixels) +// codeDivWidth - maximum width of #pyCodeOutputDiv (in integer pixels) +// editCodeBaseURL - the base URL to visit when the user clicks 'Edit code' (if null, then 'Edit code' link hidden) +// allowEditAnnotations - allow user to edit per-step annotations (default: false) +// embeddedMode - shortcut for hideOutput=true, allowEditAnnotations=false, +// codeDivWidth=this.DEFAULT_EMBEDDED_CODE_DIV_WIDTH, +// codeDivHeight=this.DEFAULT_EMBEDDED_CODE_DIV_HEIGHT +// disableHeapNesting - if true, then render all heap objects at the top level (i.e., no nested objects) +// drawParentPointers - if true, then draw environment diagram parent pointers for all frames +// WARNING: there are hard-to-debug MEMORY LEAKS associated with activating this option +// textualMemoryLabels - render references using textual memory labels rather than as jsPlumb arrows. +// this is good for slow browsers or when used with disableHeapNesting +// to prevent "arrow overload" +// showOnlyOutputs - show only program outputs and NOT internal data structures +// updateOutputCallback - function to call (with 'this' as parameter) +// whenever this.updateOutput() is called +// (BEFORE rendering the output display) +// heightChangeCallback - function to call (with 'this' as parameter) +// whenever the HEIGHT of #dataViz changes +// verticalStack - if true, then stack code display ON TOP of visualization +// (else place side-by-side) +// executeCodeWithRawInputFunc - function to call when you want to re-execute the given program +// with some new user input (somewhat hacky!) +// highlightLines - highlight current and previously executed lines (default: false) +// arrowLines - draw arrows pointing to current and previously executed lines (default: true) +// compactFuncLabels - render functions with a 'func' prefix and no type label +// pyCrazyMode - run with Py2crazy, which provides expression-level +// granularity instead of line-level granularity (HIGHLY EXPERIMENTAL!) +function ExecutionVisualizer(domRootID, dat, params) { + serverReply = dat; + this.curInputCode = dat.code.rtrim(); // kill trailing spaces + this.curTrace = dat.trace; + + this.DEFAULT_EMBEDDED_CODE_DIV_WIDTH = 350; + this.DEFAULT_EMBEDDED_CODE_DIV_HEIGHT = 400; + + // optional filtering to remove redundancy ... + // ok, we're gonna filter out all trace entries of 'call' events, + // because each one contains IDENTICAL state information as the + // 'step_line' entry immediately following it. this filtering allows the + // visualization to not show as much redundancy. + + //this.curTrace = this.curTrace.filter(function(e) {return e.event != 'call';}); + + // if the final entry is raw_input or mouse_input, then trim it from the trace and + // set a flag to prompt for user input when execution advances to the + // end of the trace + if (this.curTrace.length > 0) { + var lastEntry = this.curTrace[this.curTrace.length - 1]; + if (lastEntry.event == 'raw_input') { + this.promptForUserInput = true; + this.userInputPromptStr = lastEntry.prompt; + this.curTrace.pop() // kill last entry so that it doesn't get displayed + } + else if (lastEntry.event == 'mouse_input') { + this.promptForMouseInput = true; + this.userInputPromptStr = lastEntry.prompt; + this.curTrace.pop() // kill last entry so that it doesn't get displayed + } + } + + this.hasStdout = ((this.curTrace.length > 0) + && this.curTrace[this.curTrace.length-1] + && this.curTrace[this.curTrace.length-1].stdout); + + if (this.hasStdout) { + this.stdoutLines = this.curTrace[this.curTrace.length-1].stdout.split("\n").length; + } + else + this.stdoutLines = -1; + + this.curInstr = 0; + + this.params = params; + if (!this.params) { + this.params = {}; // make it an empty object by default + } + + var arrowLinesDef = (this.params.arrowLines !== undefined); + var highlightLinesDef = (this.params.highlightLines !== undefined); + + if (!arrowLinesDef && !highlightLinesDef) { + // neither is set + this.params.highlightLines = false; + this.params.arrowLines = true; + } + else if (arrowLinesDef && highlightLinesDef) { + // both are set, so just use their set values + } + else if (arrowLinesDef) { + // only arrowLines set + this.params.highlightLines = !(this.params.arrowLines); + } + else { + // only highlightLines set + this.params.arrowLines = !(this.params.highlightLines); + } + + if (this.params.lang == undefined) + this.params.lang = "python"; + + this.compactFuncLabels = this.params.compactFuncLabels; + + // audible! + if (this.params.pyCrazyMode) { + this.params.arrowLines = this.params.highlightLines = false; + } + + // needs to be unique! + this.visualizerID = curVisualizerID; + curVisualizerID++; + + this.leftGutterSvgInitialized = false; + this.arrowOffsetY = undefined; + this.codeRowHeight = undefined; + + // avoid 'undefined' state + this.disableHeapNesting = (this.params.disableHeapNesting == true); + this.drawParentPointers = (this.params.drawParentPointers == true); + this.textualMemoryLabels = (this.params.textualMemoryLabels == true); + this.showOnlyOutputs = (this.params.showOnlyOutputs == true); + + this.executeCodeWithRawInputFunc = this.params.executeCodeWithRawInputFunc; + + // cool, we can create a separate jsPlumb instance for each visualization: + this.jsPlumbInstance = jsPlumb.getInstance({ + Endpoint: ["Dot", {radius:3}], + EndpointStyles: [{fillStyle: connectorBaseColor}, {fillstyle: null} /* make right endpoint invisible */], + Anchors: ["RightMiddle", "LeftMiddle"], + PaintStyle: {lineWidth:1, strokeStyle: connectorBaseColor}, + + // bezier curve style: + //Connector: [ "Bezier", { curviness:15 }], /* too much 'curviness' causes lines to run together */ + //Overlays: [[ "Arrow", { length: 14, width:10, foldback:0.55, location:0.35 }]], + + // state machine curve style: + Connector: [ "StateMachine" ], + Overlays: [[ "Arrow", { length: 10, width:7, foldback:0.55, location:1 }]], + EndpointHoverStyles: [{fillStyle: connectorHighlightColor}, {fillstyle: null} /* make right endpoint invisible */], + HoverPaintStyle: {lineWidth: 1, strokeStyle: connectorHighlightColor}, + }); + + + // true iff trace ended prematurely since maximum instruction limit has + // been reached + var instrLimitReached = false; + + + // the root elements for jQuery and D3 selections, respectively. + // ALWAYS use these and never use naked $(__) or d3.select(__) + this.domRoot = $('#' + domRootID); + this.domRoot.data("vis",this); // bnm store a reference to this as div data for use later. + this.domRootD3 = d3.select('#' + domRootID); + + // stick a new div.ExecutionVisualizer within domRoot and make that + // the new domRoot: + this.domRoot.html('
'); + + this.domRoot = this.domRoot.find('div.ExecutionVisualizer'); + this.domRootD3 = this.domRootD3.select('div.ExecutionVisualizer'); + + + // initialize in renderPyCodeOutput() + this.codeOutputLines = null; + this.breakpoints = null; // set of execution points to set as breakpoints + this.sortedBreakpointsList = null; // sorted and synced with breakpointLines + this.hoverBreakpoints = null; // set of breakpoints because we're HOVERING over a given line + + this.enableTransitions = false; // EXPERIMENTAL - enable transition effects + + + this.hasRendered = false; + + this.render(); // go for it! + +} + + +// create a unique ID, which is often necessary so that jsPlumb doesn't get confused +// due to multiple ExecutionVisualizer instances being displayed simultaneously +ExecutionVisualizer.prototype.generateID = function(original_id) { + // (it's safer to start names with a letter rather than a number) + return 'v' + this.visualizerID + '__' + original_id; +} + + +ExecutionVisualizer.prototype.render = function() { + if (this.hasRendered) { + alert('ERROR: You should only call render() ONCE on an ExecutionVisualizer object.'); + return; + } + + + var myViz = this; // to prevent confusion of 'this' inside of nested functions + + var codeDisplayHTML = + '
\ +
\ + \ +
\ +
\ + \ + \ + Step ? of ?\ + \ + \ +
\ +
\ +
\ +
\ + \ +
\ +
\ +
\ +
'; + + var outputRows = Math.min(10, myViz.stdoutLines); + + var outputsHTML = + '
\ +
\ + Program output:
\ + \ +
'; + + var codeVizHTML = + '
\ +
\ + \ + \ + \ + \ +
\ +
\ +
Variables
\ +
\ +
\ +
\ +
\ +
Memory
\ +
\ +
\ + '; + + var vizHeaderHTML = + '
\ + \ +
\ + \ +
\ +
'; + + if (this.params.verticalStack) { + this.domRoot.html(vizHeaderHTML + '
' + + codeDisplayHTML + '
' + + codeVizHTML + '
'); + } + else { + this.domRoot.html(vizHeaderHTML + '
' + + codeDisplayHTML + '' + + codeVizHTML + '
'); + } + + if (this.showOnlyOutputs) { + myViz.domRoot.find('#dataViz').hide(); + this.domRoot.find('#vizLayoutTdSecond').append(outputsHTML); + + if (this.params.verticalStack) { + this.domRoot.find('#vizLayoutTdSecond').css('padding-top', '25px'); + } + else { + this.domRoot.find('#vizLayoutTdSecond').css('padding-left', '25px'); + } + } + else { + this.domRoot.find('#vizLayoutTdFirst').append(outputsHTML); + } + + if (this.params.arrowLines) { + this.domRoot.find('#legendDiv') + .append(' line that has just executed') + .append('

next line to execute

'); + + myViz.domRootD3.select('svg#prevLegendArrowSVG') + .append('polygon') + .attr('points', SVG_ARROW_POLYGON) + .attr('fill', lightArrowColor); + + myViz.domRootD3.select('svg#curLegendArrowSVG') + .append('polygon') + .attr('points', SVG_ARROW_POLYGON) + .attr('fill', darkArrowColor); + } + else if (this.params.highlightLines) { + myViz.domRoot.find('#legendDiv') + .append('line that has just executed ') + .append('next line to execute') + } + else if (this.params.pyCrazyMode) { + myViz.domRoot.find('#legendDiv') + .append('Py2crazy mode!') + .append(' Stepping through (roughly) each executed expression. Color codes:

') + .append('expression that just executed
') + .append('next expression to execute'); + } + + + if (this.params.editCodeBaseURL) { + var urlStr = $.param.fragment(this.params.editCodeBaseURL, + {code: this.curInputCode}, + 2); + this.domRoot.find('#editBtn').attr('href', urlStr); + } + else { + this.domRoot.find('#editCodeLinkDiv').hide(); // just hide for simplicity! + this.domRoot.find('#editBtn').attr('href', "#"); + this.domRoot.find('#editBtn').click(function(){return false;}); // DISABLE the link! + } + + if (this.params.allowEditAnnotations !== undefined) { + this.allowEditAnnotations = this.params.allowEditAnnotations; + } + else { + this.allowEditAnnotations = false; + } + + if (this.params.pyCrazyMode !== undefined) { + this.pyCrazyMode = this.params.pyCrazyMode; + } + else { + this.pyCrazyMode = false; + } + + this.domRoot.find('#stepAnnotationEditor').hide(); + + if (this.params.embeddedMode) { + this.params.hideOutput = true; // put this before hideOutput handler + + // don't override if they've already been set! + if (this.params.codeDivWidth === undefined) { + this.params.codeDivWidth = this.DEFAULT_EMBEDDED_CODE_DIV_WIDTH; + } + + if (this.params.codeDivHeight === undefined) { + this.params.codeDivHeight = this.DEFAULT_EMBEDDED_CODE_DIV_HEIGHT; + } + + this.allowEditAnnotations = false; + } + + myViz.editAnnotationMode = false; + + if (this.allowEditAnnotations) { + var ab = this.domRoot.find('#annotateBtn'); + + ab.click(function() { + if (myViz.editAnnotationMode) { + myViz.enterViewAnnotationsMode(); + + myViz.domRoot.find("#jmpFirstInstr,#jmpLastInstr,#jmpStepBack,#jmpStepFwd,#executionSlider,#editCodeLinkDiv,#stepAnnotationViewer").show(); + myViz.domRoot.find('#stepAnnotationEditor').hide(); + ab.html('Annotate this step'); + } + else { + myViz.enterEditAnnotationsMode(); + + myViz.domRoot.find("#jmpFirstInstr,#jmpLastInstr,#jmpStepBack,#jmpStepFwd,#executionSlider,#editCodeLinkDiv,#stepAnnotationViewer").hide(); + myViz.domRoot.find('#stepAnnotationEditor').show(); + ab.html('Done annotating'); + } + }); + } + else { + this.domRoot.find('#annotateBtn').hide(); + } + + + // not enough room for these extra buttons ... + if (this.params.codeDivWidth && + this.params.codeDivWidth < 470) { + this.domRoot.find('#jmpFirstInstr').hide(); + this.domRoot.find('#jmpLastInstr').hide(); + } + + // enable left-right draggable pane resizer (originally from David Pritchard) + this.domRoot.find('#codeDisplayDiv').resizable({ + handles: "e", + minWidth: 100, //otherwise looks really goofy + resize: function(event, ui){ // old name: syncStdoutWidth, now not appropriate + $("#codeDisplayDiv").css("height", "auto"); // redetermine height if necessary + if (myViz.params.updateOutputCallback) // report size change + myViz.params.updateOutputCallback(this); + }}); + + if (this.params.codeDivWidth) { + // set width once + this.domRoot.find('#codeDisplayDiv').width( + this.params.codeDivWidth); + // it will propagate to the slider + } + + if (this.params.codeDivHeight) { + this.domRoot.find('#pyCodeOutputDiv') + .css('max-height', this.params.codeDivHeight + 'px'); + } + + var globalsLabel = "Global frame"; + if (myViz.params.lang == 'java') globalsLabel = "Static fields"; + + // create a persistent globals frame + // (note that we need to keep #globals_area separate from #stack for d3 to work its magic) + this.domRoot.find("#globals_area").append('

'+globalsLabel+'
'); + + + if (this.params.hideOutput) { + this.domRoot.find('#progOutputs').hide(); + } + + this.domRoot.find("#jmpFirstInstr").click(function() { + myViz.curInstr = 0; + myViz.updateOutput(); + }); + + this.domRoot.find("#jmpLastInstr").click(function() { + myViz.curInstr = myViz.curTrace.length - 1; + myViz.updateOutput(); + }); + + this.domRoot.find("#jmpStepBack").click(function() { + myViz.stepBack(); + }); + + this.domRoot.find("#jmpStepFwd").click(function() { + myViz.stepForward(); + }); + + // disable controls initially ... + this.domRoot.find("#vcrControls #jmpFirstInstr").attr("disabled", true); + this.domRoot.find("#vcrControls #jmpStepBack").attr("disabled", true); + this.domRoot.find("#vcrControls #jmpStepFwd").attr("disabled", true); + this.domRoot.find("#vcrControls #jmpLastInstr").attr("disabled", true); + + + + // must postprocess curTrace prior to running precomputeCurTraceLayouts() ... + var lastEntry = this.curTrace[this.curTrace.length - 1]; + + this.instrLimitReached = (lastEntry.event == 'instruction_limit_reached'); + + if (this.instrLimitReached) { + this.curTrace.pop() // kill last entry + var warningMsg = lastEntry.exception_msg; + myViz.domRoot.find("#errorOutput").html(htmlspecialchars(warningMsg)); + myViz.domRoot.find("#errorOutput").show(); + } + + // set up slider after postprocessing curTrace + + var sliderDiv = this.domRoot.find('#executionSlider'); + sliderDiv.slider({min: 0, max: this.curTrace.length - 1, step: 1}); + //disable keyboard actions on the slider itself (to prevent double-firing of events) + sliderDiv.find(".ui-slider-handle").unbind('keydown'); + // make skinnier and taller + sliderDiv.find(".ui-slider-handle").css('width', '0.8em'); + sliderDiv.find(".ui-slider-handle").css('height', '1.4em'); + this.domRoot.find(".ui-widget-content").css('font-size', '0.9em'); + + this.domRoot.find('#executionSlider').bind('slide', function(evt, ui) { + // this is SUPER subtle. if this value was changed programmatically, + // then evt.originalEvent will be undefined. however, if this value + // was changed by a user-initiated event, then this code should be + // executed ... + if (evt.originalEvent) { + myViz.curInstr = ui.value; + myViz.updateOutput(); + } + }); + + + if (this.params.startingInstruction) { + assert(0 <= this.params.startingInstruction && + this.params.startingInstruction < this.curTrace.length); + this.curInstr = this.params.startingInstruction; + } + + if (this.params.jumpToEnd) { + this.curInstr = this.curTrace.length - 1; + } + + + this.precomputeCurTraceLayouts(); + + this.renderPyCodeOutput(); + + this.updateOutput(); + + this.hasRendered = true; +} + + +ExecutionVisualizer.prototype.showVizHeaderViewMode = function() { + var titleVal = this.domRoot.find('#vizTitleEditor').val().trim(); + var descVal = this.domRoot.find('#vizDescriptionEditor').val().trim(); + + this.domRoot.find('#vizTitleEditor,#vizDescriptionEditor').hide(); + + if (!titleVal && !descVal) { + this.domRoot.find('#vizHeader').hide(); + } + else { + this.domRoot.find('#vizHeader,#vizTitleViewer,#vizDescriptionViewer').show(); + if (titleVal) { + this.domRoot.find('#vizTitleViewer').html(htmlsanitize(titleVal)); // help prevent HTML/JS injection attacks + } + + if (descVal) { + this.domRoot.find('#vizDescriptionViewer').html(htmlsanitize(descVal)); // help prevent HTML/JS injection attacks + } + } +} + +ExecutionVisualizer.prototype.showVizHeaderEditMode = function() { + this.domRoot.find('#vizHeader').show(); + + this.domRoot.find('#vizTitleViewer,#vizDescriptionViewer').hide(); + this.domRoot.find('#vizTitleEditor,#vizDescriptionEditor').show(); +} + + +ExecutionVisualizer.prototype.destroyAllAnnotationBubbles = function() { + var myViz = this; + + // hopefully destroys all old bubbles and reclaims their memory + if (myViz.allAnnotationBubbles) { + $.each(myViz.allAnnotationBubbles, function(i, e) { + e.destroyQTip(); + }); + } + + // remove this handler as well! + this.domRoot.find('#pyCodeOutputDiv').unbind('scroll'); + + myViz.allAnnotationBubbles = null; +} + +ExecutionVisualizer.prototype.initStepAnnotation = function() { + var curEntry = this.curTrace[this.curInstr]; + if (curEntry.stepAnnotation) { + this.domRoot.find("#stepAnnotationViewer").html(htmlsanitize(curEntry.stepAnnotation)); // help prevent HTML/JS injection attacks + this.domRoot.find("#stepAnnotationEditor").val(curEntry.stepAnnotation); + } + else { + this.domRoot.find("#stepAnnotationViewer").html(''); + this.domRoot.find("#stepAnnotationEditor").val(''); + } +} + +ExecutionVisualizer.prototype.initAllAnnotationBubbles = function() { + var myViz = this; + + // TODO: check for memory leaks + //console.log('initAllAnnotationBubbles'); + + myViz.destroyAllAnnotationBubbles(); + + var codelineIDs = []; + $.each(this.domRoot.find('#pyCodeOutput .cod'), function(i, e) { + codelineIDs.push($(e).attr('id')); + }); + + var heapObjectIDs = []; + $.each(this.domRoot.find('.heapObject'), function(i, e) { + heapObjectIDs.push($(e).attr('id')); + }); + + var variableIDs = []; + $.each(this.domRoot.find('.variableTr'), function(i, e) { + variableIDs.push($(e).attr('id')); + }); + + var frameIDs = []; + $.each(this.domRoot.find('.stackFrame'), function(i, e) { + frameIDs.push($(e).attr('id')); + }); + + myViz.allAnnotationBubbles = []; + + $.each(codelineIDs, function(i,e) {myViz.allAnnotationBubbles.push(new AnnotationBubble(myViz, 'codeline', e));}); + $.each(heapObjectIDs, function(i,e) {myViz.allAnnotationBubbles.push(new AnnotationBubble(myViz, 'object', e));}); + $.each(variableIDs, function(i,e) {myViz.allAnnotationBubbles.push(new AnnotationBubble(myViz, 'variable', e));}); + $.each(frameIDs, function(i,e) {myViz.allAnnotationBubbles.push(new AnnotationBubble(myViz, 'frame', e));}); + + + this.domRoot.find('#pyCodeOutputDiv').scroll(function() { + $.each(myViz.allAnnotationBubbles, function(i, e) { + if (e.type == 'codeline') { + e.redrawCodelineBubble(); + } + }); + }); + + //console.log('initAllAnnotationBubbles', myViz.allAnnotationBubbles.length); +} + + +ExecutionVisualizer.prototype.enterViewAnnotationsMode = function() { + this.editAnnotationMode = false; + var curEntry = this.curTrace[this.curInstr]; + + // TODO: check for memory leaks!!! + var myViz = this; + + if (!myViz.allAnnotationBubbles) { + if (curEntry.bubbleAnnotations) { + // If there is an existing annotations object, then initiate all annotations bubbles + // and display them in 'View' mode + myViz.initAllAnnotationBubbles(); + + $.each(myViz.allAnnotationBubbles, function(i, e) { + var txt = curEntry.bubbleAnnotations[e.domID]; + if (txt) { + e.preseedText(txt); + } + }); + } + } + + + if (myViz.allAnnotationBubbles) { + var curAnnotations = {}; + + $.each(myViz.allAnnotationBubbles, function(i, e) { + e.enterViewMode(); + + if (e.text) { + curAnnotations[e.domID] = e.text; + } + }); + + // Save annotations directly into the current trace entry as an 'annotations' object + // directly mapping domID -> text. + // + // NB: This scheme can break if the functions for generating domIDs are altered. + curEntry.bubbleAnnotations = curAnnotations; + } + + var stepAnnotationEditorVal = myViz.domRoot.find("#stepAnnotationEditor").val().trim(); + if (stepAnnotationEditorVal) { + curEntry.stepAnnotation = stepAnnotationEditorVal; + } + else { + delete curEntry.stepAnnotation; // go as far as to DELETE this field entirely + } + + myViz.initStepAnnotation(); + + myViz.showVizHeaderViewMode(); + + // redraw all connectors and bubbles in new vertical position .. + myViz.redrawConnectors(); + myViz.redrawAllAnnotationBubbles(); +} + +ExecutionVisualizer.prototype.enterEditAnnotationsMode = function() { + this.editAnnotationMode = true; + + // TODO: check for memory leaks!!! + var myViz = this; + + var curEntry = this.curTrace[this.curInstr]; + + if (!myViz.allAnnotationBubbles) { + myViz.initAllAnnotationBubbles(); + } + + $.each(myViz.allAnnotationBubbles, function(i, e) { + e.enterEditMode(); + }); + + + if (curEntry.stepAnnotation) { + myViz.domRoot.find("#stepAnnotationEditor").val(curEntry.stepAnnotation); + } + else { + myViz.domRoot.find("#stepAnnotationEditor").val(''); + } + + + myViz.showVizHeaderEditMode(); + + // redraw all connectors and bubbles in new vertical position .. + myViz.redrawConnectors(); + myViz.redrawAllAnnotationBubbles(); +} + + +ExecutionVisualizer.prototype.redrawAllAnnotationBubbles = function() { + if (this.allAnnotationBubbles) { + $.each(this.allAnnotationBubbles, function(i, e) { + e.redrawBubble(); + }); + } +} + + +// find the previous/next breakpoint to c or return -1 if it doesn't exist +ExecutionVisualizer.prototype.findPrevBreakpoint = function() { + var myViz = this; + var c = myViz.curInstr; + + if (myViz.sortedBreakpointsList.length == 0) { + return -1; + } + else { + for (var i = 1; i < myViz.sortedBreakpointsList.length; i++) { + var prev = myViz.sortedBreakpointsList[i-1]; + var cur = myViz.sortedBreakpointsList[i]; + if (c <= prev) + return -1; + if (cur >= c) + return prev; + } + + // final edge case: + var lastElt = myViz.sortedBreakpointsList[myViz.sortedBreakpointsList.length - 1]; + return (lastElt < c) ? lastElt : -1; + } +} + +ExecutionVisualizer.prototype.findNextBreakpoint = function() { + var myViz = this; + var c = myViz.curInstr; + + if (myViz.sortedBreakpointsList.length == 0) { + return -1; + } + // usability hack: if you're currently on a breakpoint, then + // single-step forward to the next execution point, NOT the next + // breakpoint. it's often useful to see what happens when the line + // at a breakpoint executes. + else if ($.inArray(c, myViz.sortedBreakpointsList) >= 0) { + return c + 1; + } + else { + for (var i = 0; i < myViz.sortedBreakpointsList.length - 1; i++) { + var cur = myViz.sortedBreakpointsList[i]; + var next = myViz.sortedBreakpointsList[i+1]; + if (c < cur) + return cur; + if (cur <= c && c < next) // subtle + return next; + } + + // final edge case: + var lastElt = myViz.sortedBreakpointsList[myViz.sortedBreakpointsList.length - 1]; + return (lastElt > c) ? lastElt : -1; + } +} + + +// returns true if action successfully taken +ExecutionVisualizer.prototype.stepForward = function() { + var myViz = this; + + if (myViz.editAnnotationMode) { + return; + } + + if (myViz.curInstr < myViz.curTrace.length - 1) { + // if there is a next breakpoint, then jump to it ... + if (myViz.sortedBreakpointsList.length > 0) { + var nextBreakpoint = myViz.findNextBreakpoint(); + if (nextBreakpoint != -1) + myViz.curInstr = nextBreakpoint; + else + myViz.curInstr += 1; // prevent "getting stuck" on a solitary breakpoint + } + else { + myViz.curInstr += 1; + } + myViz.updateOutput(true); + return true; + } + + return false; +} + +// returns true if action successfully taken +ExecutionVisualizer.prototype.stepBack = function() { + var myViz = this; + + if (myViz.editAnnotationMode) { + return; + } + + if (myViz.curInstr > 0) { + // if there is a prev breakpoint, then jump to it ... + if (myViz.sortedBreakpointsList.length > 0) { + var prevBreakpoint = myViz.findPrevBreakpoint(); + if (prevBreakpoint != -1) + myViz.curInstr = prevBreakpoint; + else + myViz.curInstr -= 1; // prevent "getting stuck" on a solitary breakpoint + } + else { + myViz.curInstr -= 1; + } + myViz.updateOutput(); + return true; + } + + return false; +} + + +ExecutionVisualizer.prototype.renderPyCodeOutput = function() { + var myViz = this; // to prevent confusion of 'this' inside of nested functions + + + // initialize! + this.breakpoints = d3.map(); + this.sortedBreakpointsList = []; + this.hoverBreakpoints = d3.map(); + + // an array of objects with the following fields: + // 'text' - the text of the line of code + // 'lineNumber' - one-indexed (always the array index + 1) + // 'executionPoints' - an ordered array of zero-indexed execution points where this line was executed + // 'breakpointHere' - has a breakpoint been set here? + this.codeOutputLines = []; + + + function renderSliderBreakpoints() { + myViz.domRoot.find("#executionSliderFooter").empty(); + + // I originally didn't want to delete and re-create this overlay every time, + // but if I don't do so, there are weird flickering artifacts with clearing + // the SVG container; so it's best to just delete and re-create the container each time + var sliderOverlay = myViz.domRootD3.select('#executionSliderFooter') + .append('svg') + .attr('id', 'sliderOverlay') + .attr('width', myViz.domRoot.find('#executionSlider').width()) + .attr('height', 12); + + var xrange = d3.scale.linear() + .domain([0, myViz.curTrace.length - 1]) + .range([0, myViz.domRoot.find('#executionSlider').width()]); + + sliderOverlay.selectAll('rect') + .data(myViz.sortedBreakpointsList) + .enter().append('rect') + .attr('x', function(d, i) { + // make the edge cases look decent + if (d == 0) { + return 0; + } + else { + return xrange(d) - 3; + } + }) + .attr('y', 0) + .attr('width', 2) + .attr('height', 12) + .style('fill', function(d) { + if (myViz.hoverBreakpoints.has(d)) { + return hoverBreakpointColor; + } + else { + return breakpointColor; + } + }); + } + + function _getSortedBreakpointsList() { + var ret = []; + myViz.breakpoints.forEach(function(k, v) { + ret.push(Number(k)); // these should be NUMBERS, not strings + }); + ret.sort(function(x,y){return x-y}); // WTF, javascript sort is lexicographic by default! + return ret; + } + + function addToBreakpoints(executionPoints) { + $.each(executionPoints, function(i, ep) { + myViz.breakpoints.set(ep, 1); + }); + myViz.sortedBreakpointsList = _getSortedBreakpointsList(); + } + + function removeFromBreakpoints(executionPoints) { + $.each(executionPoints, function(i, ep) { + myViz.breakpoints.remove(ep); + }); + myViz.sortedBreakpointsList = _getSortedBreakpointsList(); + } + + + function setHoverBreakpoint(t) { + var exePts = d3.select(t).datum().executionPoints; + + // don't do anything if exePts is empty + // (i.e., this line was never executed) + if (!exePts || exePts.length == 0) { + return; + } + + myViz.hoverBreakpoints = d3.map(); + $.each(exePts, function(i, ep) { + // don't add redundant entries + if (!myViz.breakpoints.has(ep)) { + myViz.hoverBreakpoints.set(ep, 1); + } + }); + + addToBreakpoints(exePts); + renderSliderBreakpoints(); + } + + + function setBreakpoint(t) { + var exePts = d3.select(t).datum().executionPoints; + + // don't do anything if exePts is empty + // (i.e., this line was never executed) + if (!exePts || exePts.length == 0) { + return; + } + + addToBreakpoints(exePts); + + // remove from hoverBreakpoints so that slider display immediately changes color + $.each(exePts, function(i, ep) { + myViz.hoverBreakpoints.remove(ep); + }); + + d3.select(t.parentNode).select('td.lineNo').style('color', breakpointColor); + d3.select(t.parentNode).select('td.lineNo').style('font-weight', 'bold'); + + renderSliderBreakpoints(); + } + + function unsetBreakpoint(t) { + var exePts = d3.select(t).datum().executionPoints; + + // don't do anything if exePts is empty + // (i.e., this line was never executed) + if (!exePts || exePts.length == 0) { + return; + } + + removeFromBreakpoints(exePts); + + var lineNo = d3.select(t).datum().lineNumber; + + renderSliderBreakpoints(); + } + + var lines = this.curInputCode.split('\n'); + + for (var i = 0; i < lines.length; i++) { + var cod = lines[i]; + + var n = {}; + n.text = cod; + n.lineNumber = i + 1; + n.executionPoints = []; + n.breakpointHere = false; + + $.each(this.curTrace, function(j, elt) { + if (elt.line == n.lineNumber) { + n.executionPoints.push(j); + } + }); + + + // if there is a comment containing 'breakpoint' and this line was actually executed, + // then set a breakpoint on this line + var breakpointInComment = false; + var toks = cod.split('#'); + for (var j = 1 /* start at index 1, not 0 */; j < toks.length; j++) { + if (toks[j].indexOf('breakpoint') != -1) { + breakpointInComment = true; + } + } + + if (breakpointInComment && n.executionPoints.length > 0) { + n.breakpointHere = true; + addToBreakpoints(n.executionPoints); + } + + this.codeOutputLines.push(n); + } + + + myViz.domRoot.find('#pyCodeOutputDiv').empty(); + + // maps this.codeOutputLines to both table columns + var codeOutputD3 = this.domRootD3.select('#pyCodeOutputDiv') + .append('table') + .attr('id', 'pyCodeOutput') + .selectAll('tr') + .data(this.codeOutputLines) + .enter().append('tr') + .selectAll('td') + .data(function(d, i){return [d, d] /* map full data item down both columns */;}) + .enter().append('td') + .attr('class', function(d, i) { + if (i == 0) { + return 'lineNo'; + } + else { + return 'cod'; + } + }) + .attr('id', function(d, i) { + if (i == 0) { + return 'lineNo' + d.lineNumber; + } + else { + return myViz.generateID('cod' + d.lineNumber); // make globally unique (within the page) + } + }) + .html(function(d, i) { + if (i == 0) { + return d.lineNumber; + } + else { + return htmlspecialchars(d.text); + } + }); + + // create a left-most gutter td that spans ALL rows ... + // (NB: valign="top" is CRUCIAL for this to work in IE) + if (myViz.params.arrowLines) { + myViz.domRoot.find('#pyCodeOutput tr:first') + .prepend(''); + + // create prevLineArrow and curLineArrow + myViz.domRootD3.select('svg#leftCodeGutterSVG') + .append('polygon') + .attr('id', 'prevLineArrow') + .attr('points', SVG_ARROW_POLYGON) + .attr('fill', lightArrowColor); + + myViz.domRootD3.select('svg#leftCodeGutterSVG') + .append('polygon') + .attr('id', 'curLineArrow') + .attr('points', SVG_ARROW_POLYGON) + .attr('fill', darkArrowColor); + } + + // 2012-09-05: Disable breakpoints for now to simplify UX + /* + if (!this.params.embeddedMode) { + codeOutputD3.style('cursor', function(d, i) {return 'pointer'}) + .on('mouseover', function() { + setHoverBreakpoint(this); + }) + .on('mouseout', function() { + myViz.hoverBreakpoints = d3.map(); + + var breakpointHere = d3.select(this).datum().breakpointHere; + + if (!breakpointHere) { + unsetBreakpoint(this); + } + + renderSliderBreakpoints(); // get rid of hover breakpoint colors + }) + .on('mousedown', function() { + // don't do anything if exePts is empty + // (i.e., this line was never executed) + var exePts = d3.select(this).datum().executionPoints; + if (!exePts || exePts.length == 0) { + return; + } + + // toggle breakpoint + d3.select(this).datum().breakpointHere = !d3.select(this).datum().breakpointHere; + + var breakpointHere = d3.select(this).datum().breakpointHere; + if (breakpointHere) { + setBreakpoint(this); + } + else { + unsetBreakpoint(this); + } + }); + + renderSliderBreakpoints(); // renders breakpoints written in as code comments + } + */ + +} + + +// takes a string inputStr and returns an HTML version with +// the characters from [highlightIndex, highlightIndex+extent) highlighted with +// a span of class highlightCssClass +function htmlWithHighlight(inputStr, highlightInd, extent, highlightCssClass) { + var prefix = ''; + if (highlightInd > 0) { + prefix = inputStr.slice(0, highlightInd); + } + + var highlightedChars = inputStr.slice(highlightInd, highlightInd + extent); + + var suffix = ''; + if (highlightInd + extent < inputStr.length) { + suffix = inputStr.slice(highlightInd + extent, inputStr.length); + } + + // ... then set the current line to lineHTML + var lineHTML = htmlspecialchars(prefix) + + '' + + htmlspecialchars(highlightedChars) + + '' + + htmlspecialchars(suffix); + return lineHTML; +} + + +// This function is called every time the display needs to be updated +// smoothTransition is OPTIONAL! +ExecutionVisualizer.prototype.updateOutput = function(smoothTransition) { + assert(this.curTrace); + + var myViz = this; // to prevent confusion of 'this' inside of nested functions + + // there's no point in re-rendering if this pane isn't even visible in the first place! + if (!myViz.domRoot.is(':visible')) { + return; + } + + + // really nitpicky!!! gets the difference in width between the code display + // and the maximum width of its enclosing div + myViz.codeHorizontalOverflow = myViz.domRoot.find('#pyCodeOutput').width() - myViz.domRoot.find('#pyCodeOutputDiv').width(); + // should always be positive + if (myViz.codeHorizontalOverflow < 0) { + myViz.codeHorizontalOverflow = 0; + } + + + // crucial resets for annotations (TODO: kludgy) + myViz.destroyAllAnnotationBubbles(); + myViz.initStepAnnotation(); + + + var prevDataVizHeight = myViz.domRoot.find('#dataViz').height(); + + + var gutterSVG = myViz.domRoot.find('svg#leftCodeGutterSVG'); + + // one-time initialization of the left gutter + // (we often can't do this earlier since the entire pane + // might be invisible and hence returns a height of zero or NaN + // -- the exact format depends on browser) + if (!myViz.leftGutterSvgInitialized && myViz.params.arrowLines) { + // set the gutter's height to match that of its parent + gutterSVG.height(gutterSVG.parent().height()); + + var firstRowOffsetY = myViz.domRoot.find('table#pyCodeOutput tr:first').offset().top; + + // first take care of edge case when there's only one line ... + myViz.codeRowHeight = myViz.domRoot.find('table#pyCodeOutput td.cod:first').height(); + + // ... then handle the (much more common) multi-line case ... + // this weird contortion is necessary to get the accurate row height on Internet Explorer + // (simpler methods work on all other major browsers, erghhhhhh!!!) + if (this.codeOutputLines && this.codeOutputLines.length > 1) { + var secondRowOffsetY = myViz.domRoot.find('table#pyCodeOutput tr:nth-child(2)').offset().top; + myViz.codeRowHeight = secondRowOffsetY - firstRowOffsetY; + } + + assert(myViz.codeRowHeight > 0); + + var gutterOffsetY = gutterSVG.offset().top; + var teenyAdjustment = gutterOffsetY - firstRowOffsetY; + + // super-picky detail to adjust the vertical alignment of arrows so that they line up + // well with the pointed-to code text ... + // (if you want to manually adjust tableTop, then ~5 is a reasonable number) + myViz.arrowOffsetY = Math.floor((myViz.codeRowHeight / 2) - (SVG_ARROW_HEIGHT / 2)) - teenyAdjustment; + + myViz.leftGutterSvgInitialized = true; + } + + if (myViz.params.arrowLines) { + assert(myViz.arrowOffsetY !== undefined); + assert(myViz.codeRowHeight !== undefined); + assert(0 <= myViz.arrowOffsetY && myViz.arrowOffsetY <= myViz.codeRowHeight); + } + + // call the callback if necessary (BEFORE rendering) + if (this.params.updateOutputCallback) { + this.params.updateOutputCallback(this); + } + + + var curEntry = this.curTrace[this.curInstr]; + var hasError = false; + // bnm Render a question + if (curEntry.question) { + //alert(curEntry.question.text); + + $('#'+curEntry.question.div).modal({position:["25%","50%"]}); + } + + // render VCR controls: + var totalInstrs = this.curTrace.length; + + var isLastInstr = (this.curInstr == (totalInstrs-1)); + + var vcrControls = myViz.domRoot.find("#vcrControls"); + + if (isLastInstr) { + if (this.promptForUserInput || this.promptForMouseInput) { + vcrControls.find("#curInstr").html('' + this.userInputPromptStr + ''); + + // don't do smooth transition since prompt() is modal so it doesn't + // give the animation background thread time to run + smoothTransition = false; + } + else if (this.instrLimitReached) { + vcrControls.find("#curInstr").html("Instruction limit reached"); + } + else { + vcrControls.find("#curInstr").html("Program terminated"); + } + } + else { + vcrControls.find("#curInstr").html("Step " + + String(this.curInstr + 1) + + " of " + String(totalInstrs-1)); + } + + + vcrControls.find("#jmpFirstInstr").attr("disabled", false); + vcrControls.find("#jmpStepBack").attr("disabled", false); + vcrControls.find("#jmpStepFwd").attr("disabled", false); + vcrControls.find("#jmpLastInstr").attr("disabled", false); + + if (this.curInstr == 0) { + vcrControls.find("#jmpFirstInstr").attr("disabled", true); + vcrControls.find("#jmpStepBack").attr("disabled", true); + } + if (isLastInstr) { + vcrControls.find("#jmpLastInstr").attr("disabled", true); + vcrControls.find("#jmpStepFwd").attr("disabled", true); + } + + + // PROGRAMMATICALLY change the value, so evt.originalEvent should be undefined + myViz.domRoot.find('#executionSlider').slider('value', this.curInstr); + + + // render error (if applicable): + if (curEntry.event == 'exception' || + curEntry.event == 'uncaught_exception') { + assert(curEntry.exception_msg); + + if (curEntry.exception_msg == "Unknown error") { + myViz.domRoot.find("#errorOutput").html('Unknown error: Please email a bug report to philip@pgbovine.net'); + } + else { + myViz.domRoot.find("#errorOutput").html(htmlspecialchars(curEntry.exception_msg)); + } + + myViz.domRoot.find("#errorOutput").show(); + + hasError = true; + } + else { + if (!this.instrLimitReached) { // ugly, I know :/ + myViz.domRoot.find("#errorOutput").hide(); + } + } + + + function highlightCodeLine() { + /* if instrLimitReached, then treat like a normal non-terminating line */ + var isTerminated = (!myViz.instrLimitReached && isLastInstr); + + var pcod = myViz.domRoot.find('#pyCodeOutputDiv'); + + var curLineNumber = null; + var prevLineNumber = null; + + // only relevant if in myViz.pyCrazyMode + var prevColumn = undefined; + var prevExprStartCol = undefined; + var prevExprWidth = undefined; + + var curIsReturn = (curEntry.event == 'return'); + var prevIsReturn = false; + + + if (myViz.curInstr > 0) { + prevLineNumber = myViz.curTrace[myViz.curInstr - 1].line; + prevIsReturn = (myViz.curTrace[myViz.curInstr - 1].event == 'return'); + + if (myViz.pyCrazyMode) { + var p = myViz.curTrace[myViz.curInstr - 1]; + prevColumn = p.column; + // if these don't exist, set reasonable defaults + prevExprStartCol = (p.expr_start_col !== undefined) ? p.expr_start_col : p.column; + prevExprWidth = (p.expr_width !== undefined) ? p.expr_width : 1; + } + } + + curLineNumber = curEntry.line; + + if (myViz.pyCrazyMode) { + var curColumn = curEntry.column; + + // if these don't exist, set reasonable defaults + var curExprStartCol = (curEntry.expr_start_col !== undefined) ? curEntry.expr_start_col : curColumn; + var curExprWidth = (curEntry.expr_width !== undefined) ? curEntry.expr_width : 1; + + var curLineInfo = myViz.codeOutputLines[curLineNumber - 1]; + assert(curLineInfo.lineNumber == curLineNumber); + var codeAtLine = curLineInfo.text; + + // shotgun approach: reset ALL lines to their natural (unbolded) state + $.each(myViz.codeOutputLines, function(i, e) { + var d = myViz.generateID('cod' + e.lineNumber); + myViz.domRoot.find('#' + d).html(htmlspecialchars(e.text)); + }); + + + // Three possible cases: + // 1. previous and current trace entries are on the SAME LINE + // 2. previous and current trace entries are on different lines + // 3. there is no previous trace entry + + if (prevLineNumber == curLineNumber) { + var curLineHTML = ''; + + // tricky tricky! + // generate a combined line with both previous and current + // columns highlighted + + for (var i = 0; i < codeAtLine.length; i++) { + var isCur = (curExprStartCol <= i) && (i < curExprStartCol + curExprWidth); + var isPrev = (prevExprStartCol <= i) && (i < prevExprStartCol + prevExprWidth); + + var htmlEscapedChar = htmlspecialchars(codeAtLine[i]); + + if (isCur && isPrev) { + curLineHTML += '' + htmlEscapedChar + ''; + } + else if (isPrev) { + curLineHTML += '' + htmlEscapedChar + ''; + } + else if (isCur) { + curLineHTML += '' + htmlEscapedChar + ''; + } + else { + curLineHTML += htmlEscapedChar; + } + } + + assert(curLineHTML); + myViz.domRoot.find('#' + myViz.generateID('cod' + curLineNumber)).html(curLineHTML); + } + else { + if (prevLineNumber) { + var prevLineInfo = myViz.codeOutputLines[prevLineNumber - 1]; + var prevLineHTML = htmlWithHighlight(prevLineInfo.text, prevExprStartCol, prevExprWidth, 'pycrazy-highlight-prev'); + myViz.domRoot.find('#' + myViz.generateID('cod' + prevLineNumber)).html(prevLineHTML); + } + var curLineHTML = htmlWithHighlight(codeAtLine, curExprStartCol, curExprWidth, 'pycrazy-highlight-cur'); + myViz.domRoot.find('#' + myViz.generateID('cod' + curLineNumber)).html(curLineHTML); + } + } + + // on 'return' events, give a bit more of a vertical nudge to show that + // the arrow is aligned with the 'bottom' of the line ... + var prevVerticalNudge = prevIsReturn ? Math.floor(myViz.codeRowHeight / 2) : 0; + var curVerticalNudge = curIsReturn ? Math.floor(myViz.codeRowHeight / 2) : 0; + + + // edge case for the final instruction :0 + if (isTerminated && !hasError) { + // don't show redundant arrows on the same line when terminated ... + if (prevLineNumber == curLineNumber) { + curLineNumber = null; + } + // otherwise have a smaller vertical nudge (to fit at bottom of display table) + else { + curVerticalNudge = curVerticalNudge - 2; + } + } + + if (myViz.params.arrowLines) { + if (prevLineNumber) { + var pla = myViz.domRootD3.select('#prevLineArrow'); + var translatePrevCmd = 'translate(0, ' + (((prevLineNumber - 1) * myViz.codeRowHeight) + myViz.arrowOffsetY + prevVerticalNudge) + ')'; + + if (smoothTransition) { + pla + .transition() + .duration(200) + .attr('fill', 'white') + .each('end', function() { + pla + .attr('transform', translatePrevCmd) + .attr('fill', lightArrowColor); + + gutterSVG.find('#prevLineArrow').show(); // show at the end to avoid flickering + }); + } + else { + pla.attr('transform', translatePrevCmd) + gutterSVG.find('#prevLineArrow').show(); + } + + } + else { + gutterSVG.find('#prevLineArrow').hide(); + } + + if (curLineNumber) { + var cla = myViz.domRootD3.select('#curLineArrow'); + var translateCurCmd = 'translate(0, ' + (((curLineNumber - 1) * myViz.codeRowHeight) + myViz.arrowOffsetY + curVerticalNudge) + ')'; + + if (smoothTransition) { + cla + .transition() + .delay(200) + .duration(250) + .attr('transform', translateCurCmd); + } + else { + cla.attr('transform', translateCurCmd); + } + + gutterSVG.find('#curLineArrow').show(); + } + else { + gutterSVG.find('#curLineArrow').hide(); + } + } + + myViz.domRootD3.selectAll('#pyCodeOutputDiv td.cod') + .style('border-top', function(d) { + if (hasError && (d.lineNumber == curEntry.line)) { + return '1px solid ' + errorColor; + } + else { + return ''; + } + }) + .style('border-bottom', function(d) { + // COPY AND PASTE ALERT! + if (hasError && (d.lineNumber == curEntry.line)) { + return '1px solid ' + errorColor; + } + else { + return ''; + } + }); + + // returns True iff lineNo is visible in pyCodeOutputDiv + function isOutputLineVisible(lineNo) { + var lineNoTd = myViz.domRoot.find('#lineNo' + lineNo); + var LO = lineNoTd.offset().top; + + var PO = pcod.offset().top; + var ST = pcod.scrollTop(); + var H = pcod.height(); + + // add a few pixels of fudge factor on the bottom end due to bottom scrollbar + return (PO <= LO) && (LO < (PO + H - 30)); + } + + + // smoothly scroll pyCodeOutputDiv so that the given line is at the center + function scrollCodeOutputToLine(lineNo) { + var lineNoTd = myViz.domRoot.find('#lineNo' + lineNo); + var LO = lineNoTd.offset().top; + + var PO = pcod.offset().top; + var ST = pcod.scrollTop(); + var H = pcod.height(); + + pcod.stop(); // first stop all previously-queued animations + pcod.animate({scrollTop: (ST + (LO - PO - (Math.round(H / 2))))}, 300); + } + + if (myViz.params.highlightLines) { + myViz.domRoot.find('#pyCodeOutputDiv td.cod').removeClass('highlight-prev'); + myViz.domRoot.find('#pyCodeOutputDiv td.cod').removeClass('highlight-cur'); + if (curLineNumber) + myViz.domRoot.find('#'+myViz.generateID('cod'+curLineNumber)).addClass('highlight-cur'); + if (prevLineNumber) + myViz.domRoot.find('#'+myViz.generateID('cod'+prevLineNumber)).addClass('highlight-prev'); + } + + + // smoothly scroll code display + if (!isOutputLineVisible(curEntry.line)) { + scrollCodeOutputToLine(curEntry.line); + } + + } // end of highlightCodeLine + + + // render code output: + if (curEntry.line) { + highlightCodeLine(); + } + + // render stdout: + + // if there isn't anything in curEntry.stdout, don't even bother + // displaying the pane + if (myViz.hasStdout) { + this.domRoot.find('#progOutputs').show(); + + // keep original horizontal scroll level: + var oldLeft = myViz.domRoot.find("#pyStdout").scrollLeft(); + myViz.domRoot.find("#pyStdout").val(curEntry.stdout); + + myViz.domRoot.find("#pyStdout").scrollLeft(oldLeft); + // scroll to bottom, though: + myViz.domRoot.find("#pyStdout").scrollTop(myViz.domRoot.find("#pyStdout")[0].scrollHeight); + } + else { + this.domRoot.find('#progOutputs').hide(); + } + + + // inject user-specified HTML/CSS/JS output: + // YIKES -- HUGE CODE INJECTION VULNERABILITIES :O + myViz.domRoot.find("#htmlOutputDiv").empty(); + if (curEntry.html_output) { + if (curEntry.css_output) { + myViz.domRoot.find("#htmlOutputDiv").append(''); + } + myViz.domRoot.find("#htmlOutputDiv").append(curEntry.html_output); + + // inject and run JS *after* injecting HTML and CSS + if (curEntry.js_output) { + // NB: when jQuery injects JS, it executes the code immediately + // and then removes the entire '); + } + } + + + // finally, render all of the data structures + this.renderDataStructures(); + + this.enterViewAnnotationsMode(); // ... and render optional annotations (if any exist) + + + // call the callback if necessary (BEFORE rendering) + if (myViz.domRoot.find('#dataViz').height() != prevDataVizHeight) { + if (this.params.heightChangeCallback) { + this.params.heightChangeCallback(this); + } + } + + if (isLastInstr && this.executeCodeWithRawInputFunc) { + if (this.promptForUserInput) { + // blocking prompt dialog! + // put a default string of '' or else it looks ugly in IE + var userInput = prompt(this.userInputPromptStr, ''); + + // if you hit 'Cancel' in prompt(), it returns null + if (userInput !== null) { + // after executing, jump back to this.curInstr to give the + // illusion of continuity + this.executeCodeWithRawInputFunc(userInput, this.curInstr); + } + } + } + +} // end of updateOutput + + +// Pre-compute the layout of top-level heap objects for ALL execution +// points as soon as a trace is first loaded. The reason why we want to +// do this is so that when the user steps through execution points, the +// heap objects don't "jiggle around" (i.e., preserving positional +// invariance). Also, if we set up the layout objects properly, then we +// can take full advantage of d3 to perform rendering and transitions. + +ExecutionVisualizer.prototype.precomputeCurTraceLayouts = function() { + + // curTraceLayouts is a list of top-level heap layout "objects" with the + // same length as curTrace after it's been fully initialized. Each + // element of curTraceLayouts is computed from the contents of its + // immediate predecessor, thus ensuring that objects don't "jiggle + // around" between consecutive execution points. + // + // Each top-level heap layout "object" is itself a LIST of LISTS of + // object IDs, where each element of the outer list represents a row, + // and each element of the inner list represents columns within a + // particular row. Each row can have a different number of columns. Most + // rows have exactly ONE column (representing ONE object ID), but rows + // containing 1-D linked data structures have multiple columns. Each + // inner list element looks something like ['row1', 3, 2, 1] where the + // first element is a unique row ID tag, which is used as a key for d3 to + // preserve "object constancy" for updates, transitions, etc. The row ID + // is derived from the FIRST object ID inserted into the row. Since all + // object IDs are unique, all row IDs will also be unique. + + /* This is a good, simple example to test whether objects "jiggle" + + x = [1, [2, [3, None]]] + y = [4, [5, [6, None]]] + + x[1][1] = y[1] + + */ + this.curTraceLayouts = []; + this.curTraceLayouts.push([]); // pre-seed with an empty sentinel to simplify the code + + assert(this.curTrace.length > 0); + + var myViz = this; // to prevent confusion of 'this' inside of nested functions + + + $.each(this.curTrace, function(i, curEntry) { + var prevLayout = myViz.curTraceLayouts[myViz.curTraceLayouts.length - 1]; + + // make a DEEP COPY of prevLayout to use as the basis for curLine + var curLayout = $.extend(true /* deep copy */ , [], prevLayout); + + // initialize with all IDs from curLayout + var idsToRemove = d3.map(); + $.each(curLayout, function(i, row) { + for (var j = 1 /* ignore row ID tag */; j < row.length; j++) { + idsToRemove.set(row[j], 1); + } + }); + + var idsAlreadyLaidOut = d3.map(); // to prevent infinite recursion + + + function curLayoutIndexOf(id) { + for (var i = 0; i < curLayout.length; i++) { + var row = curLayout[i]; + var index = row.indexOf(id); + if (index > 0) { // index of 0 is impossible since it's the row ID tag + return {row: row, index: index} + } + } + return null; + } + + + function recurseIntoObject(id, curRow, newRow) { + //console.log('recurseIntoObject', id, + // $.extend(true /* make a deep copy */ , [], curRow), + // $.extend(true /* make a deep copy */ , [], newRow)); + + // heuristic for laying out 1-D linked data structures: check for enclosing elements that are + // structurally identical and then lay them out as siblings in the same "row" + var heapObj = curEntry.heap[id]; + assert(heapObj); + + if (heapObj[0] == 'LIST' || heapObj[0] == 'TUPLE' || heapObj[0] == 'SET') { + $.each(heapObj, function(ind, child) { + if (ind < 1) return; // skip type tag + + if (!isPrimitiveType(child)) { + var childID = getRefID(child); + + // comment this out to make "linked lists" that aren't + // structurally equivalent look good, e.g.,: + // x = (1, 2, (3, 4, 5, 6, (7, 8, 9, None))) + //if (structurallyEquivalent(heapObj, curEntry.heap[childID])) { + // updateCurLayout(childID, curRow, newRow); + //} + if (myViz.disableHeapNesting) { + updateCurLayout(childID, [], []); + } + else { + updateCurLayout(childID, curRow, newRow); + } + } + }); + } + else if (heapObj[0] == 'DICT') { + $.each(heapObj, function(ind, child) { + if (ind < 1) return; // skip type tag + + if (myViz.disableHeapNesting) { + var dictKey = child[0]; + if (!isPrimitiveType(dictKey)) { + var keyChildID = getRefID(dictKey); + updateCurLayout(keyChildID, [], []); + } + } + + var dictVal = child[1]; + if (!isPrimitiveType(dictVal)) { + var childID = getRefID(dictVal); + if (structurallyEquivalent(heapObj, curEntry.heap[childID])) { + updateCurLayout(childID, curRow, newRow); + } + else if (myViz.disableHeapNesting) { + updateCurLayout(childID, [], []); + } + } + }); + } + else if (heapObj[0] == 'INSTANCE' || heapObj[0] == 'CLASS') { + jQuery.each(heapObj, function(ind, child) { + var headerLength = (heapObj[0] == 'INSTANCE') ? 2 : 3; + if (ind < headerLength) return; + + if (myViz.disableHeapNesting) { + var instKey = child[0]; + if (!isPrimitiveType(instKey)) { + var keyChildID = getRefID(instKey); + updateCurLayout(keyChildID, [], []); + } + } + + var instVal = child[1]; + if (!isPrimitiveType(instVal)) { + var childID = getRefID(instVal); + if (structurallyEquivalent(heapObj, curEntry.heap[childID])) { + updateCurLayout(childID, curRow, newRow); + } + else if (myViz.disableHeapNesting) { + updateCurLayout(childID, [], []); + } + } + }); + } + } + + + // a krazy function! + // id - the new object ID to be inserted somewhere in curLayout + // (if it's not already in there) + // curRow - a row within curLayout where new linked list + // elements can be appended onto (might be null) + // newRow - a new row that might be spliced into curRow or appended + // as a new row in curLayout + function updateCurLayout(id, curRow, newRow) { + if (idsAlreadyLaidOut.has(id)) { + return; // PUNT! + } + + var curLayoutLoc = curLayoutIndexOf(id); + + var alreadyLaidOut = idsAlreadyLaidOut.has(id); + idsAlreadyLaidOut.set(id, 1); // unconditionally set now + + // if id is already in curLayout ... + if (curLayoutLoc) { + var foundRow = curLayoutLoc.row; + var foundIndex = curLayoutLoc.index; + + idsToRemove.remove(id); // this id is already accounted for! + + // very subtle ... if id hasn't already been handled in + // this iteration, then splice newRow into foundRow. otherwise + // (later) append newRow onto curLayout as a truly new row + if (!alreadyLaidOut) { + // splice the contents of newRow right BEFORE foundIndex. + // (Think about when you're trying to insert in id=3 into ['row1', 2, 1] + // to represent a linked list 3->2->1. You want to splice the 3 + // entry right before the 2 to form ['row1', 3, 2, 1]) + if (newRow.length > 1) { + var args = [foundIndex, 0]; + for (var i = 1; i < newRow.length; i++) { // ignore row ID tag + args.push(newRow[i]); + idsToRemove.remove(newRow[i]); + } + foundRow.splice.apply(foundRow, args); + + // remove ALL elements from newRow since they've all been accounted for + // (but don't reassign it away to an empty list, since the + // CALLER checks its value. TODO: how to get rid of this gross hack?!?) + newRow.splice(0, newRow.length); + } + } + + // recurse to find more top-level linked entries to append onto foundRow + recurseIntoObject(id, foundRow, []); + } + else { + // push id into newRow ... + if (newRow.length == 0) { + newRow.push('row' + id); // unique row ID (since IDs are unique) + } + newRow.push(id); + + // recurse to find more top-level linked entries ... + recurseIntoObject(id, curRow, newRow); + + + // if newRow hasn't been spliced into an existing row yet during + // a child recursive call ... + if (newRow.length > 0) { + if (curRow && curRow.length > 0) { + // append onto the END of curRow if it exists + for (var i = 1; i < newRow.length; i++) { // ignore row ID tag + curRow.push(newRow[i]); + } + } + else { + // otherwise push to curLayout as a new row + // + // TODO: this might not always look the best, since we might + // sometimes want to splice newRow in the MIDDLE of + // curLayout. Consider this example: + // + // x = [1,2,3] + // y = [4,5,6] + // x = [7,8,9] + // + // when the third line is executed, the arrows for x and y + // will be crossed (ugly!) since the new row for the [7,8,9] + // object is pushed to the end (bottom) of curLayout. The + // proper behavior is to push it to the beginning of + // curLayout where the old row for 'x' used to be. + curLayout.push($.extend(true /* make a deep copy */ , [], newRow)); + } + + // regardless, newRow is now accounted for, so clear it + for (var i = 1; i < newRow.length; i++) { // ignore row ID tag + idsToRemove.remove(newRow[i]); + } + newRow.splice(0, newRow.length); // kill it! + } + + } + } + + + // iterate through all globals and ordered stack frames and call updateCurLayout + $.each(curEntry.ordered_globals, function(i, varname) { + var val = curEntry.globals[varname]; + if (val !== undefined) { // might not be defined at this line, which is OKAY! + if (!isPrimitiveType(val)) { + var id = getRefID(val); + updateCurLayout(id, null, []); + } + } + }); + + $.each(curEntry.stack_to_render, function(i, frame) { + $.each(frame.ordered_varnames, function(xxx, varname) { + var val = frame.encoded_locals[varname]; + + if (!isPrimitiveType(val)) { + var id = getRefID(val); + updateCurLayout(id, null, []); + } + }); + }); + + + // iterate through remaining elements of idsToRemove and REMOVE them from curLayout + idsToRemove.forEach(function(id, xxx) { + id = Number(id); // keys are stored as strings, so convert!!! + $.each(curLayout, function(rownum, row) { + var ind = row.indexOf(id); + if (ind > 0) { // remember that index 0 of the row is the row ID tag + row.splice(ind, 1); + } + }); + }); + + // now remove empty rows (i.e., those with only a row ID tag) from curLayout + curLayout = curLayout.filter(function(row) {return row.length > 1}); + + myViz.curTraceLayouts.push(curLayout); + }); + + this.curTraceLayouts.splice(0, 1); // remove seeded empty sentinel element + assert (this.curTrace.length == this.curTraceLayouts.length); +} + + +var heapPtrSrcRE = /__heap_pointer_src_/; + +// The "3.0" version of renderDataStructures renders variables in +// a stack, values in a separate heap, and draws line connectors +// to represent both stack->heap object references and, more importantly, +// heap->heap references. This version was created in August 2012. +// +// The "2.0" version of renderDataStructures renders variables in +// a stack and values in a separate heap, with data structure aliasing +// explicitly represented via line connectors (thanks to jsPlumb lib). +// This version was created in September 2011. +// +// The ORIGINAL "1.0" version of renderDataStructures +// was created in January 2010 and rendered variables and values +// INLINE within each stack frame without any explicit representation +// of data structure aliasing. That is, aliased objects were rendered +// multiple times, and a unique ID label was used to identify aliases. +ExecutionVisualizer.prototype.renderDataStructures = function() { + + var myViz = this; // to prevent confusion of 'this' inside of nested functions + + var curEntry = this.curTrace[this.curInstr]; + var curToplevelLayout = this.curTraceLayouts[this.curInstr]; + + // for simplicity (but sacrificing some performance), delete all + // connectors and redraw them from scratch. doing so avoids mysterious + // jsPlumb connector alignment issues when the visualizer's enclosing + // div contains, say, a "position: relative;" CSS tag + // (which happens in the IPython Notebook) + var existingConnectionEndpointIDs = d3.map(); + myViz.jsPlumbInstance.select({scope: 'varValuePointer'}).each(function(c) { + // This is VERY crude, but to prevent multiple redundant HEAP->HEAP + // connectors from being drawn with the same source and origin, we need to first + // DELETE ALL existing HEAP->HEAP connections, and then re-render all of + // them in each call to this function. The reason why we can't safely + // hold onto them is because there's no way to guarantee that the + // *__heap_pointer_src_ IDs are consistent across execution points. + // + // thus, only add to existingConnectionEndpointIDs if this is NOT heap->heap + if (!c.sourceId.match(heapPtrSrcRE)) { + existingConnectionEndpointIDs.set(c.sourceId, c.targetId); + } + }); + + var existingParentPointerConnectionEndpointIDs = d3.map(); + myViz.jsPlumbInstance.select({scope: 'frameParentPointer'}).each(function(c) { + existingParentPointerConnectionEndpointIDs.set(c.sourceId, c.targetId); + }); + + + // Heap object rendering phase: + + + // Key: CSS ID of the div element representing the stack frame variable + // (for stack->heap connections) or heap object (for heap->heap connections) + // the format is: '__heap_pointer_src_' + // Value: CSS ID of the div element representing the value rendered in the heap + // (the format is: '__heap_object_') + // + // The reason we need to prepend this.visualizerID is because jsPlumb needs + // GLOBALLY UNIQUE IDs for use as connector endpoints. + + // the only elements in these sets are NEW elements to be rendered in this + // particular call to renderDataStructures. + var connectionEndpointIDs = d3.map(); + var heapConnectionEndpointIDs = d3.map(); // subset of connectionEndpointIDs for heap->heap connections + + // analogous to connectionEndpointIDs, except for environment parent pointers + var parentPointerConnectionEndpointIDs = d3.map(); + + var heap_pointer_src_id = 1; // increment this to be unique for each heap_pointer_src_* + + + var renderedObjectIDs = d3.map(); + + // count everything in curToplevelLayout as already rendered since we will render them + // in d3 .each() statements + $.each(curToplevelLayout, function(xxx, row) { + for (var i = 0; i < row.length; i++) { + renderedObjectIDs.set(row[i], 1); + } + }); + + + + // use d3 to render the heap by mapping curToplevelLayout into + // and '); + var headerTr = tbl.find('tr:first'); + var contentTr = tbl.find('tr:last'); + $.each(obj, function(ind, val) { + if (ind < 1) return; // skip type tag and ID entry + + // add a new column and then pass in that newly-added column + // as d3DomElement to the recursive call to child: + headerTr.append(''); + headerTr.find('td:last').append(ind - 1); + + contentTr.append(''); + renderNestedObject(val, contentTr.find('td:last')); + }); + } + else if (obj[0] == 'SET') { + // create an R x C matrix: + var numElts = obj.length - 1; + + // gives roughly a 3x5 rectangular ratio, square is too, err, + // 'square' and boring + var numRows = Math.round(Math.sqrt(numElts)); + if (numRows > 3) { + numRows -= 1; + } + + var numCols = Math.round(numElts / numRows); + // round up if not a perfect multiple: + if (numElts % numRows) { + numCols += 1; + } + + jQuery.each(obj, function(ind, val) { + if (ind < 1) return; // skip 'SET' tag + + if (((ind - 1) % numCols) == 0) { + tbl.append(''); + } + + var curTr = tbl.find('tr:last'); + curTr.append(''); + renderNestedObject(val, curTr.find('td:last')); + }); + } + else if (obj[0] == 'DICT') { + $.each(obj, function(ind, kvPair) { + if (ind < 1) return; // skip 'DICT' tag + + tbl.append(''); + var newRow = tbl.find('tr:last'); + var keyTd = newRow.find('td:first'); + var valTd = newRow.find('td:last'); + + var key = kvPair[0]; + var val = kvPair[1]; + + renderNestedObject(key, keyTd); + renderNestedObject(val, valTd); + }); + } + } + } + else if (obj[0] == 'INSTANCE' || obj[0] == 'CLASS') { + var isInstance = (obj[0] == 'INSTANCE'); + var headerLength = isInstance ? 2 : 3; + + assert(obj.length >= headerLength); + + if (isInstance) { + d3DomElement.append('
' + typeLabelPrefix + obj[1] + ' instance
'); + } + else { + var superclassStr = ''; + if (obj[2].length > 0) { + superclassStr += ('[extends ' + obj[2].join(', ') + '] '); + } + d3DomElement.append('
' + typeLabelPrefix + obj[1] + ' class ' + superclassStr + '
'); + } + + // right now, let's NOT display class members, since that clutters + // up the display too much. in the future, consider displaying + // class members in a pop-up pane on mouseover or mouseclick + // actually nix what i just said above ... + //if (!isInstance) return; + + if (obj.length > headerLength) { + var lab = isInstance ? 'inst' : 'class'; + d3DomElement.append('
elements + + var heapRows = myViz.domRootD3.select('#heap') + .selectAll('table.heapRow') + .data(curToplevelLayout, function(objLst) { + return objLst[0]; // return first element, which is the row ID tag + }); + + + // insert new heap rows + heapRows.enter().append('table') + //.each(function(objLst, i) {console.log('NEW ROW:', objLst, i);}) + .attr('class', 'heapRow'); + + // delete a heap row + var hrExit = heapRows.exit(); + + if (myViz.enableTransitions) { + hrExit + .style('opacity', '1') + .transition() + .style('opacity', '0') + .duration(500) + .each('end', function() { + hrExit + .each(function(d, idx) { + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + myViz.redrawConnectors(); + }); + } + else { + hrExit + .each(function(d, idx) { + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + } + + + // update an existing heap row + var toplevelHeapObjects = heapRows + //.each(function(objLst, i) { console.log('UPDATE ROW:', objLst, i); }) + .selectAll('td.toplevelHeapObject') + .data(function(d, i) {return d.slice(1, d.length);}, /* map over each row, skipping row ID tag */ + function(objID) {return objID;} /* each object ID is unique for constancy */); + + // insert a new toplevelHeapObject + var tlhEnter = toplevelHeapObjects.enter().append('td') + .attr('class', 'toplevelHeapObject') + .attr('id', function(d, i) {return 'toplevel_heap_object_' + d;}); + + if (myViz.enableTransitions) { + tlhEnter + .style('opacity', '0') + .style('border-color', 'red') + .transition() + .style('opacity', '1') /* fade in */ + .duration(700) + .each('end', function() { + tlhEnter.transition() + .style('border-color', 'white') /* kill border */ + .duration(300) + }); + } + + // remember that the enter selection is added to the update + // selection so that we can process it later ... + + // update a toplevelHeapObject + toplevelHeapObjects + .order() // VERY IMPORTANT to put in the order corresponding to data elements + .each(function(objID, i) { + //console.log('NEW/UPDATE ELT', objID); + + // TODO: add a smoother transition in the future + // Right now, just delete the old element and render a new one in its place + $(this).empty(); + renderCompoundObject(objID, $(this), true); + }); + + // delete a toplevelHeapObject + var tlhExit = toplevelHeapObjects.exit(); + + if (myViz.enableTransitions) { + tlhExit.transition() + .style('opacity', '0') /* fade out */ + .duration(500) + .each('end', function() { + tlhExit + .each(function(d, idx) { + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + myViz.redrawConnectors(); + }); + } + else { + tlhExit + .each(function(d, idx) { + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + } + + + function renderNestedObject(obj, d3DomElement) { + if (isPrimitiveType(obj)) { + renderPrimitiveObject(obj, d3DomElement); + } + else { + renderCompoundObject(getRefID(obj), d3DomElement, false); + } + } + + + function renderPrimitiveObject(obj, d3DomElement) { + var typ = typeof obj; + + if (obj == null) { + if (myViz.params.lang == 'java') + d3DomElement.append('null'); + else + d3DomElement.append('None'); + } + else if (typ == "number") { + d3DomElement.append('' + obj + ''); + } + else if (typ == "boolean") { + if (obj) { + if (myViz.params.lang == 'java') + d3DomElement.append('true'); + else + d3DomElement.append('True'); + } + else { + if (myViz.params.lang == 'java') + d3DomElement.append('false'); + else + d3DomElement.append('False'); + } + } + else if (typ == "string") { + // escape using htmlspecialchars to prevent HTML/script injection + var literalStr = htmlspecialchars(obj); + + // print as a double-quoted string literal + literalStr = literalStr.replace(new RegExp('\"', 'g'), '\\"'); // replace ALL + literalStr = '"' + literalStr + '"'; + + d3DomElement.append('' + literalStr + ''); + } + else if (typ == "number") { + d3DomElement.append('' + obj + ''); + } + else if (obj instanceof Array && obj[0] == "VOID") { + d3DomElement.append('void'); + } + else if (obj instanceof Array && obj[0] == "NUMBER-LITERAL") { + // actually transmitted as a string + d3DomElement.append('' + obj[1] + ''); + } + else { + assert(false); + } + } + + + function renderCompoundObject(objID, d3DomElement, isTopLevel) { + if (!isTopLevel && renderedObjectIDs.has(objID)) { + var srcDivID = myViz.generateID('heap_pointer_src_' + heap_pointer_src_id); + heap_pointer_src_id++; // just make sure each source has a UNIQUE ID + + var dstDivID = myViz.generateID('heap_object_' + objID); + + if (myViz.textualMemoryLabels) { + var labelID = srcDivID + '_text_label'; + d3DomElement.append('
id' + objID + '
'); + + myViz.domRoot.find('div#' + labelID).hover( + function() { + myViz.jsPlumbInstance.connect({source: labelID, target: dstDivID, + scope: 'varValuePointer'}); + }, + function() { + myViz.jsPlumbInstance.select({source: labelID}).detach(); + }); + } + else { + // render jsPlumb arrow source since this heap object has already been rendered + // (or will be rendered soon) + + // add a stub so that we can connect it with a connector later. + // IE needs this div to be NON-EMPTY in order to properly + // render jsPlumb endpoints, so that's why we add an " "! + d3DomElement.append('
 
'); + + assert(!connectionEndpointIDs.has(srcDivID)); + connectionEndpointIDs.set(srcDivID, dstDivID); + //console.log('HEAP->HEAP', srcDivID, dstDivID); + + assert(!heapConnectionEndpointIDs.has(srcDivID)); + heapConnectionEndpointIDs.set(srcDivID, dstDivID); + } + + return; // early return! + } + + + var heapObjID = myViz.generateID('heap_object_' + objID); + + + // wrap ALL compound objects in a heapObject div so that jsPlumb + // connectors can point to it: + d3DomElement.append('
'); + d3DomElement = myViz.domRoot.find('#' + heapObjID); + + renderedObjectIDs.set(objID, 1); + + var obj = curEntry.heap[objID]; + assert($.isArray(obj)); + + // prepend the type label with a memory address label + var typeLabelPrefix = ''; + if (myViz.textualMemoryLabels) { + typeLabelPrefix = 'id' + objID + ':'; + } + + if (obj[0] == 'LIST' || obj[0] == 'TUPLE' || obj[0] == 'SET' || obj[0] == 'DICT') { + var label = obj[0].toLowerCase(); + if (myViz.params.lang == 'java' && label == 'list') + visibleLabel = 'array'; + else + visibleLabel = label; + + assert(obj.length >= 1); + if (obj.length == 1) { + d3DomElement.append('
' + typeLabelPrefix + 'empty ' + visibleLabel + '
'); + } + else { + d3DomElement.append('
' + typeLabelPrefix + visibleLabel + '
'); + d3DomElement.append('
'); + var tbl = d3DomElement.children('table'); + + if (obj[0] == 'LIST' || obj[0] == 'TUPLE') { + tbl.append('
'); + + var tbl = d3DomElement.children('table'); + + $.each(obj, function(ind, kvPair) { + if (ind < headerLength) return; // skip header tags + + tbl.append(''); + + var newRow = tbl.find('tr:last'); + var keyTd = newRow.find('td:first'); + var valTd = newRow.find('td:last'); + + // the keys should always be strings, so render them directly (and without quotes): + // (actually this isn't the case when strings are rendered on the heap) + if (kvPair[0] instanceof Array + && kvPair[0][0] == "NO-LABEL") { + $(keyTd).hide(); + } + else if (typeof kvPair[0] == "string") { + // common case ... + var attrnameStr = htmlspecialchars(kvPair[0]); + keyTd.append('' + attrnameStr + ''); + } + else { + // when strings are rendered as heap objects ... + renderNestedObject(kvPair[0], keyTd); + } + + // values can be arbitrary objects, so recurse: + renderNestedObject(kvPair[1], valTd); + }); + } + } + else if (obj[0] == 'INSTANCE_PPRINT') { + d3DomElement.append('
' + typeLabelPrefix + obj[1] + ' instance
'); + + strRepr = htmlspecialchars(obj[2]); // escape strings! + d3DomElement.append('
' + strRepr + '
'); + } + else if (obj[0] == 'FUNCTION') { + assert(obj.length == 3); + + // pretty-print lambdas and display other weird characters: + var funcName = htmlspecialchars(obj[1]).replace('<lambda>', '\u03bb'); + var parentFrameID = obj[2]; // optional + + if (!myViz.compactFuncLabels) { + d3DomElement.append('
' + typeLabelPrefix + 'function
'); + } + + var funcPrefix = myViz.compactFuncLabels ? 'func' : ''; + + if (parentFrameID) { + d3DomElement.append('
' + funcPrefix + ' ' + funcName + ' [parent=f'+ parentFrameID + ']
'); + } + else { + d3DomElement.append('
' + funcPrefix + ' ' + funcName + '
'); + } + } + else if (obj[0] == 'HEAP_PRIMITIVE') { + assert(obj.length == 3); + + var typeName = obj[1]; + var primitiveVal = obj[2]; + + // add a bit of padding to heap primitives, for aesthetics + d3DomElement.append('
'); + d3DomElement.find('div.heapPrimitive').append('
' + typeLabelPrefix + typeName + '
'); + renderPrimitiveObject(primitiveVal, d3DomElement.find('div.heapPrimitive')); + } + else { + // render custom data type + assert(obj.length == 2); + + var typeName = obj[0]; + var strRepr = obj[1]; + + strRepr = htmlspecialchars(strRepr); // escape strings! + + d3DomElement.append('
' + typeLabelPrefix + typeName + '
'); + d3DomElement.append('
' + strRepr + '
'); + } + } + + + // Render globals and then stack frames using d3: + + + // TODO: this sometimes seems buggy on Safari, so nix it for now: + function highlightAliasedConnectors(d, i) { + // if this row contains a stack pointer, then highlight its arrow and + // ALL aliases that also point to the same heap object + var stackPtrId = $(this).find('div.stack_pointer').attr('id'); + if (stackPtrId) { + var foundTargetId = null; + myViz.jsPlumbInstance.select({source: stackPtrId}).each(function(c) {foundTargetId = c.targetId;}); + + // use foundTargetId to highlight ALL ALIASES + myViz.jsPlumbInstance.select().each(function(c) { + if (c.targetId == foundTargetId) { + c.setHover(true); + $(c.canvas).css("z-index", 2000); // ... and move it to the VERY FRONT + } + else { + c.setHover(false); + } + }); + } + } + + function unhighlightAllConnectors(d, i) { + myViz.jsPlumbInstance.select().each(function(c) { + c.setHover(false); + }); + } + + + + // TODO: coalesce code for rendering globals and stack frames, + // since there's so much copy-and-paste grossness right now + + // render all global variables IN THE ORDER they were created by the program, + // in order to ensure continuity: + + // Derive a list where each element contains varname + // as long as value is NOT undefined. + // (Sometimes entries in curEntry.ordered_globals are undefined, + // so filter those out.) + var realGlobalsLst = []; + $.each(curEntry.ordered_globals, function(i, varname) { + var val = curEntry.globals[varname]; + + // (use '!==' to do an EXACT match against undefined) + if (val !== undefined) { // might not be defined at this line, which is OKAY! + realGlobalsLst.push(varname); + } + }); + + var globalsID = myViz.generateID('globals'); + var globalTblID = myViz.generateID('global_table'); + + var globalVarTable = myViz.domRootD3.select('#' + globalTblID) + .selectAll('tr') + .data(realGlobalsLst, + function(d) {return d;} // use variable name as key + ); + + globalVarTable + .enter() + .append('tr') + .attr('class', 'variableTr') + .attr('id', function(d, i) { + return myViz.generateID(varnameToCssID('global__' + d + '_tr')); // make globally unique (within the page) + }); + + + var globalVarTableCells = globalVarTable + .selectAll('td.stackFrameVar,td.stackFrameValue') + .data(function(d, i){return [d, d];}) /* map varname down both columns */ + + globalVarTableCells.enter() + .append('td') + .attr('class', function(d, i) {return (i == 0) ? 'stackFrameVar' : 'stackFrameValue';}); + + // remember that the enter selection is added to the update + // selection so that we can process it later ... + + // UPDATE + globalVarTableCells + .order() // VERY IMPORTANT to put in the order corresponding to data elements + .each(function(varname, i) { + if (i == 0) { + $(this).html(varname); + } + else { + // always delete and re-render the global var ... + // NB: trying to cache and compare the old value using, + // say -- $(this).attr('data-curvalue', valStringRepr) -- leads to + // a mysterious and killer memory leak that I can't figure out yet + $(this).empty(); + + // make sure varname doesn't contain any weird + // characters that are illegal for CSS ID's ... + var varDivID = myViz.generateID('global__' + varnameToCssID(varname)); + + // need to get rid of the old connector in preparation for rendering a new one: + existingConnectionEndpointIDs.remove(varDivID); + + var val = curEntry.globals[varname]; + if (isPrimitiveType(val)) { + renderPrimitiveObject(val, $(this)); + } + else { + var heapObjID = myViz.generateID('heap_object_' + getRefID(val)); + + if (myViz.textualMemoryLabels) { + var labelID = varDivID + '_text_label'; + $(this).append('
id' + getRefID(val) + '
'); + $(this).find('div#' + labelID).hover( + function() { + myViz.jsPlumbInstance.connect({source: labelID, target: heapObjID, + scope: 'varValuePointer'}); + }, + function() { + myViz.jsPlumbInstance.select({source: labelID}).detach(); + }); + } + else { + // add a stub so that we can connect it with a connector later. + // IE needs this div to be NON-EMPTY in order to properly + // render jsPlumb endpoints, so that's why we add an " "! + $(this).append('
 
'); + + assert(!connectionEndpointIDs.has(varDivID)); + connectionEndpointIDs.set(varDivID, heapObjID); + //console.log('STACK->HEAP', varDivID, heapObjID); + } + } + } + }); + + + + globalVarTableCells.exit() + .each(function(d, idx) { + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + + globalVarTable.exit() + .each(function(d, i) { + // detach all stack_pointer connectors for divs that are being removed + $(this).find('.stack_pointer').each(function(i, sp) { + existingConnectionEndpointIDs.remove($(sp).attr('id')); + }); + + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + + + // for aesthetics, hide globals if there aren't any globals to display + if (curEntry.ordered_globals.length == 0) { + this.domRoot.find('#' + globalsID).hide(); + } + else { + this.domRoot.find('#' + globalsID).show(); + } + + + // holy cow, the d3 code for stack rendering is ABSOLUTELY NUTS! + + var stackDiv = myViz.domRootD3.select('#stack'); + + // VERY IMPORTANT for selectAll selector to be SUPER specific here! + var stackFrameDiv = stackDiv.selectAll('div.stackFrame,div.zombieStackFrame') + .data(curEntry.stack_to_render, function(frame) { + // VERY VERY VERY IMPORTANT for properly handling closures and nested functions + // (see the backend code for more details) + return frame.unique_hash; + }); + + var sfdEnter = stackFrameDiv.enter() + .append('div') + .attr('class', function(d, i) {return d.is_zombie ? 'zombieStackFrame' : 'stackFrame';}) + .attr('id', function(d, i) {return d.is_zombie ? myViz.generateID("zombie_stack" + i) + : myViz.generateID("stack" + i); + }) + // HTML5 custom data attributes + .attr('data-frame_id', function(frame, i) {return frame.frame_id;}) + .attr('data-parent_frame_id', function(frame, i) { + return (frame.parent_frame_id_list.length > 0) ? frame.parent_frame_id_list[0] : null; + }) + .each(function(frame, i) { + if (!myViz.drawParentPointers) { + return; + } + // only run if myViz.drawParentPointers is true ... + + var my_CSS_id = $(this).attr('id'); + + //console.log(my_CSS_id, 'ENTER'); + + // render a parent pointer whose SOURCE node is this frame + // i.e., connect this frame to p, where this.parent_frame_id == p.frame_id + // (if this.parent_frame_id is null, then p is the global frame) + if (frame.parent_frame_id_list.length > 0) { + var parent_frame_id = frame.parent_frame_id_list[0]; + // tricky turkey! + // ok this hack just HAPPENS to work by luck ... usually there will only be ONE frame + // that matches this selector, but sometimes multiple frames match, in which case the + // FINAL frame wins out (since parentPointerConnectionEndpointIDs is a map where each + // key can be mapped to only ONE value). it so happens that the final frame winning + // out looks "desirable" for some of the closure test cases that I've tried. but + // this code is quite brittle :( + myViz.domRoot.find('div#stack [data-frame_id=' + parent_frame_id + ']').each(function(i, e) { + var parent_CSS_id = $(this).attr('id'); + //console.log('connect', my_CSS_id, parent_CSS_id); + parentPointerConnectionEndpointIDs.set(my_CSS_id, parent_CSS_id); + }); + } + else { + // render a parent pointer to the global frame + //console.log('connect', my_CSS_id, globalsID); + // only do this if there are actually some global variables to display ... + if (curEntry.ordered_globals.length > 0) { + parentPointerConnectionEndpointIDs.set(my_CSS_id, globalsID); + } + } + + // tricky turkey: render parent pointers whose TARGET node is this frame. + // i.e., for all frames f such that f.parent_frame_id == my_frame_id, + // connect f to this frame. + // (make sure not to confuse frame IDs with CSS IDs!!!) + var my_frame_id = frame.frame_id; + myViz.domRoot.find('div#stack [data-parent_frame_id=' + my_frame_id + ']').each(function(i, e) { + var child_CSS_id = $(this).attr('id'); + //console.log('connect', child_CSS_id, my_CSS_id); + parentPointerConnectionEndpointIDs.set(child_CSS_id, my_CSS_id); + }); + }); + + sfdEnter + .append('div') + .attr('class', 'stackFrameHeader') + .html(function(frame, i) { + + // pretty-print lambdas and display other weird characters + // (might contain '<' or '>' for weird names like ) + var funcName = htmlspecialchars(frame.func_name).replace('<lambda>', '\u03bb') + .replace('\n', '
'); + + var headerLabel = funcName; + + // only display if you're someone's parent + if (frame.is_parent) { + headerLabel = 'f' + frame.frame_id + ': ' + headerLabel; + } + + // optional (btw, this isn't a CSS id) + if (frame.parent_frame_id_list.length > 0) { + var parentFrameID = frame.parent_frame_id_list[0]; + headerLabel = headerLabel + ' [parent=f' + parentFrameID + ']'; + } + + return headerLabel; + }); + + sfdEnter + .append('table') + .attr('class', 'stackFrameVarTable'); + + + var stackVarTable = stackFrameDiv + .order() // VERY IMPORTANT to put in the order corresponding to data elements + .select('table').selectAll('tr') + .data(function(frame) { + // each list element contains a reference to the entire frame + // object as well as the variable name + // TODO: look into whether we can use d3 parent nodes to avoid + // this hack ... http://bost.ocks.org/mike/nest/ + return frame.ordered_varnames.map(function(varname) {return {varname:varname, frame:frame};}); + }, + function(d) {return d.varname;} // use variable name as key + ); + + stackVarTable + .enter() + .append('tr') + .attr('class', 'variableTr') + .attr('id', function(d, i) { + return myViz.generateID(varnameToCssID(d.frame.unique_hash + '__' + d.varname + '_tr')); // make globally unique (within the page) + }); + + + var stackVarTableCells = stackVarTable + .selectAll('td.stackFrameVar,td.stackFrameValue') + .data(function(d, i) {return [d, d] /* map identical data down both columns */;}); + + stackVarTableCells.enter() + .append('td') + .attr('class', function(d, i) {return (i == 0) ? 'stackFrameVar' : 'stackFrameValue';}); + + stackVarTableCells + .order() // VERY IMPORTANT to put in the order corresponding to data elements + .each(function(d, i) { + var varname = d.varname; + var frame = d.frame; + + if (i == 0) { + if (varname == '__return__') + $(this).html('Return
value
'); + else + $(this).html(varname); + } + else { + // always delete and re-render the stack var ... + // NB: trying to cache and compare the old value using, + // say -- $(this).attr('data-curvalue', valStringRepr) -- leads to + // a mysterious and killer memory leak that I can't figure out yet + $(this).empty(); + + // make sure varname and frame.unique_hash don't contain any weird + // characters that are illegal for CSS ID's ... + var varDivID = myViz.generateID(varnameToCssID(frame.unique_hash + '__' + varname)); + + // need to get rid of the old connector in preparation for rendering a new one: + existingConnectionEndpointIDs.remove(varDivID); + + var val = frame.encoded_locals[varname]; + if (isPrimitiveType(val)) { + renderPrimitiveObject(val, $(this)); + } + else { + var heapObjID = myViz.generateID('heap_object_' + getRefID(val)); + if (myViz.textualMemoryLabels) { + var labelID = varDivID + '_text_label'; + $(this).append('
id' + getRefID(val) + '
'); + $(this).find('div#' + labelID).hover( + function() { + myViz.jsPlumbInstance.connect({source: labelID, target: heapObjID, + scope: 'varValuePointer'}); + }, + function() { + myViz.jsPlumbInstance.select({source: labelID}).detach(); + }); + } + else { + // add a stub so that we can connect it with a connector later. + // IE needs this div to be NON-EMPTY in order to properly + // render jsPlumb endpoints, so that's why we add an " "! + $(this).append('
 
'); + + assert(!connectionEndpointIDs.has(varDivID)); + connectionEndpointIDs.set(varDivID, heapObjID); + //console.log('STACK->HEAP', varDivID, heapObjID); + } + } + } + }); + + + stackVarTableCells.exit() + .each(function(d, idx) { + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + + stackVarTable.exit() + .each(function(d, i) { + $(this).find('.stack_pointer').each(function(i, sp) { + // detach all stack_pointer connectors for divs that are being removed + existingConnectionEndpointIDs.remove($(sp).attr('id')); + }); + + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + + stackFrameDiv.exit() + .each(function(frame, i) { + $(this).find('.stack_pointer').each(function(i, sp) { + // detach all stack_pointer connectors for divs that are being removed + existingConnectionEndpointIDs.remove($(sp).attr('id')); + }); + + var my_CSS_id = $(this).attr('id'); + + //console.log(my_CSS_id, 'EXIT'); + + // Remove all pointers where either the source or destination end is my_CSS_id + existingParentPointerConnectionEndpointIDs.forEach(function(k, v) { + if (k == my_CSS_id || v == my_CSS_id) { + //console.log('remove EPP', k, v); + existingParentPointerConnectionEndpointIDs.remove(k); + } + }); + + $(this).empty(); // crucial for garbage collecting jsPlumb connectors! + }) + .remove(); + + + // NB: ugh, I'm not very happy about this hack, but it seems necessary + // for embedding within sophisticated webpages such as IPython Notebook + + // delete all connectors. do this AS LATE AS POSSIBLE so that + // (presumably) the calls to $(this).empty() earlier in this function + // will properly garbage collect the connectors + // + // WARNING: for environment parent pointers, garbage collection doesn't seem to + // be working as intended :( + // + // I suspect that this is due to the fact that parent pointers are SIBLINGS + // of stackFrame divs and not children, so when stackFrame divs get destroyed, + // their associated parent pointers do NOT.) + myViz.jsPlumbInstance.reset(); + + + // use jsPlumb scopes to keep the different kinds of pointers separated + function renderVarValueConnector(varID, valueID) { + myViz.jsPlumbInstance.connect({source: varID, target: valueID, scope: 'varValuePointer'}); + } + + + var totalParentPointersRendered = 0; + + function renderParentPointerConnector(srcID, dstID) { + // SUPER-DUPER-ugly hack since I can't figure out a cleaner solution for now: + // if either srcID or dstID no longer exists, then SKIP rendering ... + if ((myViz.domRoot.find('#' + srcID).length == 0) || + (myViz.domRoot.find('#' + dstID).length == 0)) { + return; + } + + //console.log('renderParentPointerConnector:', srcID, dstID); + + myViz.jsPlumbInstance.connect({source: srcID, target: dstID, + anchors: ["LeftMiddle", "LeftMiddle"], + + // 'horizontally offset' the parent pointers up so that they don't look as ugly ... + //connector: ["Flowchart", { stub: 9 + (6 * (totalParentPointersRendered + 1)) }], + + // actually let's try a bezier curve ... + connector: [ "Bezier", { curviness: 45 }], + + endpoint: ["Dot", {radius: 4}], + //hoverPaintStyle: {lineWidth: 1, strokeStyle: connectorInactiveColor}, // no hover colors + scope: 'frameParentPointer'}); + totalParentPointersRendered++; + } + + if (!myViz.textualMemoryLabels) { + // re-render existing connectors and then ... + existingConnectionEndpointIDs.forEach(renderVarValueConnector); + // add all the NEW connectors that have arisen in this call to renderDataStructures + connectionEndpointIDs.forEach(renderVarValueConnector); + } + // do the same for environment parent pointers + if (myViz.drawParentPointers) { + existingParentPointerConnectionEndpointIDs.forEach(renderParentPointerConnector); + parentPointerConnectionEndpointIDs.forEach(renderParentPointerConnector); + } + + /* + myViz.jsPlumbInstance.select().each(function(c) { + console.log('CONN:', c.sourceId, c.targetId); + }); + */ + //console.log('---', myViz.jsPlumbInstance.select().length, '---'); + + + function highlight_frame(frameID) { + myViz.jsPlumbInstance.select().each(function(c) { + // this is VERY VERY fragile code, since it assumes that going up + // FOUR layers of parent() calls will get you from the source end + // of the connector to the enclosing stack frame + var stackFrameDiv = c.source.parent().parent().parent().parent(); + + // if this connector starts in the selected stack frame ... + if (stackFrameDiv.attr('id') == frameID) { + // then HIGHLIGHT IT! + c.setPaintStyle({lineWidth:1, strokeStyle: connectorBaseColor}); + c.endpoints[0].setPaintStyle({fillStyle: connectorBaseColor}); + //c.endpoints[1].setVisible(false, true, true); // JUST set right endpoint to be invisible + + $(c.canvas).css("z-index", 1000); // ... and move it to the VERY FRONT + } + // for heap->heap connectors + else if (heapConnectionEndpointIDs.has(c.endpoints[0].elementId)) { + // NOP since it's already the color and style we set by default + } + else { + // else unhighlight it + c.setPaintStyle({lineWidth:1, strokeStyle: connectorInactiveColor}); + c.endpoints[0].setPaintStyle({fillStyle: connectorInactiveColor}); + //c.endpoints[1].setVisible(false, true, true); // JUST set right endpoint to be invisible + + $(c.canvas).css("z-index", 0); + } + }); + + + // clear everything, then just activate this one ... + myViz.domRoot.find(".stackFrame").removeClass("highlightedStackFrame"); + myViz.domRoot.find('#' + frameID).addClass("highlightedStackFrame"); + } + + + // highlight the top-most non-zombie stack frame or, if not available, globals + var frame_already_highlighted = false; + $.each(curEntry.stack_to_render, function(i, e) { + if (e.is_highlighted) { + highlight_frame(myViz.generateID('stack' + i)); + frame_already_highlighted = true; + } + }); + + if (!frame_already_highlighted) { + highlight_frame(myViz.generateID('globals')); + } + +} + + + +ExecutionVisualizer.prototype.redrawConnectors = function() { + this.jsPlumbInstance.repaintEverything(); +} + + +// Utilities + + +/* colors - see pytutor.css for more colors */ + +var highlightedLineColor = '#e4faeb'; +var highlightedLineBorderColor = '#005583'; + +var highlightedLineLighterColor = '#e8fff0'; + +var funcCallLineColor = '#a2eebd'; + +var brightRed = '#e93f34'; + +var connectorBaseColor = '#005583'; +var connectorHighlightColor = brightRed; +var connectorInactiveColor = '#cccccc'; + +var errorColor = brightRed; + +var breakpointColor = brightRed; +var hoverBreakpointColor = connectorBaseColor; + + +// Unicode arrow types: '\u21d2', '\u21f0', '\u2907' +var darkArrowColor = brightRed; +var lightArrowColor = '#c9e6ca'; + + +function assert(cond) { + if (!cond) { + alert("Assertion Failure (see console log for backtrace)"); + throw 'Assertion Failure'; + } +} + +// taken from http://www.toao.net/32-my-htmlspecialchars-function-for-javascript +function htmlspecialchars(str) { + if (typeof(str) == "string") { + str = str.replace(/&/g, "&"); /* must do & first */ + + // ignore these for now ... + //str = str.replace(/"/g, """); + //str = str.replace(/'/g, "'"); + + str = str.replace(//g, ">"); + + // replace spaces: + str = str.replace(/ /g, " "); + + // replace tab as four spaces: + str = str.replace(/\t/g, "    "); + } + return str; +} + + +// same as htmlspecialchars except don't worry about expanding spaces or +// tabs since we want proper word wrapping in divs. +function htmlsanitize(str) { + if (typeof(str) == "string") { + str = str.replace(/&/g, "&"); /* must do & first */ + + str = str.replace(//g, ">"); + } + return str; +} + + +String.prototype.rtrim = function() { + return this.replace(/\s*$/g, ""); +} + + +// make sure varname doesn't contain any weird +// characters that are illegal for CSS ID's ... +// +// I know for a fact that iterator tmp variables named '_[1]' +// are NOT legal names for CSS ID's. +// I also threw in '{', '}', '(', ')', '<', '>' as illegal characters. +// +// also some variable names are like '.0' (for generator expressions), +// and '.' seems to be illegal. +// TODO: what other characters are illegal??? +var lbRE = new RegExp('\\[|{|\\(|<', 'g'); +var rbRE = new RegExp('\\]|}|\\)|>', 'g'); +function varnameToCssID(varname) { + return varname.replace(lbRE, 'LeftB_').replace(rbRE, '_RightB').replace('.', '_DOT_'); +} + + +// compare two JSON-encoded compound objects for structural equivalence: +function structurallyEquivalent(obj1, obj2) { + // punt if either isn't a compound type + if (isPrimitiveType(obj1) || isPrimitiveType(obj2)) { + return false; + } + + // must be the same compound type + if (obj1[0] != obj2[0]) { + return false; + } + + // must have the same number of elements or fields + if (obj1.length != obj2.length) { + return false; + } + + // for a list or tuple, same size (e.g., a cons cell is a list/tuple of size 2) + if (obj1[0] == 'LIST' || obj1[0] == 'TUPLE') { + return true; + } + else { + var startingInd = -1; + + if (obj1[0] == 'DICT') { + startingInd = 2; + } + else if (obj1[0] == 'INSTANCE') { + startingInd = 3; + } + else { + return false; // punt on all other types + } + + var obj1fields = d3.map(); + + // for a dict or object instance, same names of fields (ordering doesn't matter) + for (var i = startingInd; i < obj1.length; i++) { + obj1fields.set(obj1[i][0], 1); // use as a set + } + + for (var i = startingInd; i < obj2.length; i++) { + if (!obj1fields.has(obj2[i][0])) { + return false; + } + } + + return true; + } +} + + +function isPrimitiveType(obj) { + var typ = typeof obj; + return ((obj == null) + || (typ != "object") + || (obj instanceof Array && obj[0] == "VOID") + || (obj instanceof Array && obj[0] == "NUMBER-LITERAL") + ); +} + +function getRefID(obj) { + assert(obj[0] == 'REF'); + return obj[1]; +} + + +// Annotation bubbles + +var qtipShared = { + show: { + ready: true, // show on document.ready instead of on mouseenter + delay: 0, + event: null, + effect: function() {$(this).show();}, // don't do any fancy fading because it screws up with scrolling + }, + hide: { + fixed: true, + event: null, + effect: function() {$(this).hide();}, // don't do any fancy fading because it screws up with scrolling + }, + style: { + classes: 'ui-tooltip-pgbootstrap', // my own customized version of the bootstrap style + }, +}; + + +// a speech bubble annotation to attach to: +// 'codeline' - a line of code +// 'frame' - a stack frame +// 'variable' - a variable within a stack frame +// 'object' - an object on the heap +// (as determined by the 'type' param) +// +// domID is the ID of the element to attach to (without the leading '#' sign) +function AnnotationBubble(parentViz, type, domID) { + this.parentViz = parentViz; + + this.domID = domID; + this.hashID = '#' + domID; + + this.type = type; + + if (type == 'codeline') { + this.my = 'left center'; + this.at = 'right center'; + } + else if (type == 'frame') { + this.my = 'right center'; + this.at = 'left center'; + } + else if (type == 'variable') { + this.my = 'right center'; + this.at = 'left center'; + } + else if (type == 'object') { + this.my = 'bottom left'; + this.at = 'top center'; + } + else { + assert(false); + } + + // possible states: + // 'invisible' + // 'edit' + // 'view' + // 'minimized' + // 'stub' + this.state = 'invisible'; + + this.text = ''; // the actual contents of the annotation bubble + + this.qtipHidden = false; // is there a qtip object present but hidden? (TODO: kinda confusing) +} + +AnnotationBubble.prototype.showStub = function() { + assert(this.state == 'invisible' || this.state == 'edit'); + assert(this.text == ''); + + var myBubble = this; // to avoid name clashes with 'this' in inner scopes + + // destroy then create a new tip: + this.destroyQTip(); + $(this.hashID).qtip($.extend({}, qtipShared, { + content: ' ', + id: this.domID, + position: { + my: this.my, + at: this.at, + adjust: { + x: (myBubble.type == 'codeline' ? -6 : 0), // shift codeline tips over a bit for aesthetics + }, + effect: null, // disable all cutesy animations + }, + style: { + classes: 'ui-tooltip-pgbootstrap ui-tooltip-pgbootstrap-stub' + } + })); + + + $(this.qTipID()) + .unbind('click') // unbind all old handlers + .click(function() { + myBubble.showEditor(); + }); + + this.state = 'stub'; +} + +AnnotationBubble.prototype.showEditor = function() { + assert(this.state == 'stub' || this.state == 'view' || this.state == 'minimized'); + + var myBubble = this; // to avoid name clashes with 'this' in inner scopes + + var ta = ''; + + // destroy then create a new tip: + this.destroyQTip(); + $(this.hashID).qtip($.extend({}, qtipShared, { + content: ta, + id: this.domID, + position: { + my: this.my, + at: this.at, + adjust: { + x: (myBubble.type == 'codeline' ? -6 : 0), // shift codeline tips over a bit for aesthetics + }, + effect: null, // disable all cutesy animations + } + })); + + + $(this.qTipContentID()).find('textarea.bubbleInputText') + // set handler when the textarea loses focus + .blur(function() { + myBubble.text = $(this).val().trim(); // strip all leading and trailing spaces + + if (myBubble.text) { + myBubble.showViewer(); + } + else { + myBubble.showStub(); + } + }) + .focus(); // grab focus so that the user can start typing right away! + + this.state = 'edit'; +} + + +AnnotationBubble.prototype.bindViewerClickHandler = function() { + var myBubble = this; + + $(this.qTipID()) + .unbind('click') // unbind all old handlers + .click(function() { + if (myBubble.parentViz.editAnnotationMode) { + myBubble.showEditor(); + } + else { + myBubble.minimizeViewer(); + } + }); +} + +AnnotationBubble.prototype.showViewer = function() { + assert(this.state == 'edit' || this.state == 'invisible'); + assert(this.text); // must be non-empty! + + var myBubble = this; + // destroy then create a new tip: + this.destroyQTip(); + $(this.hashID).qtip($.extend({}, qtipShared, { + content: htmlsanitize(this.text), // help prevent HTML/JS injection attacks + id: this.domID, + position: { + my: this.my, + at: this.at, + adjust: { + x: (myBubble.type == 'codeline' ? -6 : 0), // shift codeline tips over a bit for aesthetics + }, + effect: null, // disable all cutesy animations + } + })); + + this.bindViewerClickHandler(); + this.state = 'view'; +} + + +AnnotationBubble.prototype.minimizeViewer = function() { + assert(this.state == 'view'); + + var myBubble = this; + + $(this.hashID).qtip('option', 'content.text', ' '); //hack to "minimize" its size + + $(this.qTipID()) + .unbind('click') // unbind all old handlers + .click(function() { + if (myBubble.parentViz.editAnnotationMode) { + myBubble.showEditor(); + } + else { + myBubble.restoreViewer(); + } + }); + + this.state = 'minimized'; +} + +AnnotationBubble.prototype.restoreViewer = function() { + assert(this.state == 'minimized'); + $(this.hashID).qtip('option', 'content.text', htmlsanitize(this.text)); // help prevent HTML/JS injection attacks + this.bindViewerClickHandler(); + this.state = 'view'; +} + +// NB: actually DESTROYS the QTip object +AnnotationBubble.prototype.makeInvisible = function() { + assert(this.state == 'stub' || this.state == 'edit'); + this.destroyQTip(); + this.state = 'invisible'; +} + + +AnnotationBubble.prototype.destroyQTip = function() { + $(this.hashID).qtip('destroy'); +} + +AnnotationBubble.prototype.qTipContentID = function() { + return '#ui-tooltip-' + this.domID + '-content'; +} + +AnnotationBubble.prototype.qTipID = function() { + return '#ui-tooltip-' + this.domID; +} + + +AnnotationBubble.prototype.enterEditMode = function() { + assert(this.parentViz.editAnnotationMode); + if (this.state == 'invisible') { + this.showStub(); + + if (this.type == 'codeline') { + this.redrawCodelineBubble(); + } + } +} + +AnnotationBubble.prototype.enterViewMode = function() { + assert(!this.parentViz.editAnnotationMode); + if (this.state == 'stub') { + this.makeInvisible(); + } + else if (this.state == 'edit') { + this.text = $(this.qTipContentID()).find('textarea.bubbleInputText').val().trim(); // strip all leading and trailing spaces + + if (this.text) { + this.showViewer(); + + if (this.type == 'codeline') { + this.redrawCodelineBubble(); + } + } + else { + this.makeInvisible(); + } + } + else if (this.state == 'invisible') { + // this happens when, say, you first enter View Mode + if (this.text) { + this.showViewer(); + + if (this.type == 'codeline') { + this.redrawCodelineBubble(); + } + } + } +} + +AnnotationBubble.prototype.preseedText = function(txt) { + assert(this.state == 'invisible'); + this.text = txt; +} + +AnnotationBubble.prototype.redrawCodelineBubble = function() { + assert(this.type == 'codeline'); + + if (isOutputLineVisibleForBubbles(this.domID)) { + if (this.qtipHidden) { + $(this.hashID).qtip('show'); + } + else { + $(this.hashID).qtip('reposition'); + } + + this.qtipHidden = false; + } + else { + $(this.hashID).qtip('hide'); + this.qtipHidden = true; + } +} + +AnnotationBubble.prototype.redrawBubble = function() { + $(this.hashID).qtip('reposition'); +} + + +// NB: copy-and-paste from isOutputLineVisible with some minor tweaks +function isOutputLineVisibleForBubbles(lineDivID) { + var pcod = $('#pyCodeOutputDiv'); + + var lineNoTd = $('#' + lineDivID); + var LO = lineNoTd.offset().top; + + var PO = pcod.offset().top; + var ST = pcod.scrollTop(); + var H = pcod.height(); + + // add a few pixels of fudge factor on the bottom end due to bottom scrollbar + return (PO <= LO) && (LO < (PO + H - 25)); +} + + +// popup question dialog code from Brad Miller + +// inputId is the ID of the input element +// divId is the div that containsthe visualizer +// answer is a dotted form of an attribute that lives in the curEntry of the trace +// So if we want to ask for the value of a global variable we would say 'globals.a' +// this allows us do do curTrace[i].globals.a But we do it in the loop below using the +// [] operator. +function traceQCheckMe(inputId, divId, answer) { + var vis = $("#"+divId).data("vis") + var i = vis.curInstr + var curEntry = vis.curTrace[i+1]; + var ans = $('#'+inputId).val() + var attrs = answer.split(".") + var correctAns = curEntry; + for (j in attrs) { + correctAns = correctAns[attrs[j]] + } + feedbackElement = $("#" + divId + "_feedbacktext") + if (ans.length > 0 && ans == correctAns) { + feedbackElement.html('Correct') + } else { + feedbackElement.html(vis.curTrace[i].question.feedback) + } + +} + +function closeModal(divId) { + $.modal.close() + $("#"+divId).data("vis").stepForward(); +} diff --git a/example-code/.gitignore b/example-code/.gitignore new file mode 100644 index 0000000..6ed1f42 --- /dev/null +++ b/example-code/.gitignore @@ -0,0 +1 @@ +Fakey.java \ No newline at end of file diff --git a/iframe-embed.html b/iframe-embed.html new file mode 100644 index 0000000..62eb27f --- /dev/null +++ b/iframe-embed.html @@ -0,0 +1,44 @@ + + + + + Online Python Tutor - iframe embed page + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/index.html b/index.html index ded0c54..94cf717 100644 --- a/index.html +++ b/index.html @@ -74,13 +74,9 @@ - + - - @@ -115,7 +111,12 @@ + + + @@ -342,8 +343,6 @@