提交 98ae4208 编写于 作者: M ma4413

Merge github.com:parkjs814/AlgorithmVisualizer into shell-sort

......@@ -4,10 +4,10 @@ Copyright (c) 2016 Jason Park
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
in the Software without restriction, including without limiting 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:
furnished to do so, subjected to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
......
# Algorithm Visualizer
[![Join the chat at https://gitter.im/parkjs814/AlgorithmVisualizer](https://badges.gitter.im/parkjs814/AlgorithmVisualizer.svg)](https://gitter.im/parkjs814/AlgorithmVisualizer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![OpenCollective](https://opencollective.com/algorithmvisualizer/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/algorithmvisualizer/sponsors/badge.svg)](#sponsors)
http://parkjs814.github.io/AlgorithmVisualizer
![Algorithm Visualizer](http://i.giphy.com/3o6EhJFgsyShX6MHeM.gif)
Check out [**Wiki**](https://github.com/parkjs814/AlgorithmVisualizer/wiki) to add more algorithms!
### Contributing
If you run _Algorithm Visualizer_ locally and files are not loaded because Cross-Origin Requests are blocked, use [http-server](https://github.com/indexzero/http-server) or [SimpleHTTPServer](https://docs.python.org/2/library/simplehttpserver.html) to resolve the issue. [(Issue #2)](https://github.com/parkjs814/AlgorithmVisualizer/issues/2)
If in need of any help check out or [**Wiki**](https://github.com/parkjs814/AlgorithmVisualizer/wiki) or join our [Gitter](https://gitter.im/parkjs814/AlgorithmVisualizer?utm_source=share-link&utm_medium=link&utm_campaign=share-link) chatroom!
### Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/algorithmvisualizer#backer)]
<a href="https://opencollective.com/algorithmvisualizer/backer/0/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/1/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/2/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/3/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/4/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/5/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/6/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/7/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/8/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/9/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/10/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/11/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/12/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/13/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/14/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/15/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/16/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/17/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/18/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/19/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/20/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/21/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/22/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/23/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/24/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/25/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/26/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/27/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/28/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/backer/29/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/backer/29/avatar.svg"></a>
### Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/algorithmvisualizer#sponsor)]
### Run it locally
If you run _Algorithm Visualizer_ locally and files are not loaded because Cross-Origin Requests are blocked, use [http-server](https://github.com/indexzero/http-server) to resolve the issue. [(Issue #2)](https://github.com/parkjs814/AlgorithmVisualizer/issues/2)
<a href="https://opencollective.com/algorithmvisualizer/sponsor/0/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/1/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/2/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/3/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/4/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/5/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/6/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/7/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/8/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/9/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/10/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/11/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/12/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/13/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/14/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/15/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/16/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/17/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/18/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/19/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/20/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/21/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/22/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/23/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/24/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/25/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/26/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/27/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/28/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/algorithmvisualizer/sponsor/29/website" target="_blank"><img src="https://opencollective.com/algorithmvisualizer/sponsor/29/avatar.svg"></a>
......@@ -8,23 +8,11 @@ body {
background: rgb(60, 63, 65);
font-family: 'Roboto', sans-serif;
color: rgb(187, 187, 187);
-webkit-font-smoothing: subpixel-antialiased;
}
*::-webkit-scrollbar {
width: 15px;
}
*::-webkit-scrollbar-track {
background-color: #3C3F41;
}
*::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
}
*::-webkit-scrollbar-button {
background-color: #7c2929;
}
*::-webkit-scrollbar-corner {
background-color: #3C3F41;
display: none;
}
a {
......@@ -32,13 +20,16 @@ a {
}
* {
color: inherit;
}
*:not(input) {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
color: inherit;
}
button {
......@@ -55,21 +46,13 @@ button {
}
button:hover {
background: rgba(0, 0, 0, .15);
background: rgba(0, 0, 0, .15) !important;
}
button.active {
background: rgb(44, 44, 44);
}
button.category {
background: rgba(0, 0, 0, .10);
}
button.indent {
padding-left: 28px;
}
.divider {
position: absolute !important;
z-index: 3;
......@@ -102,10 +85,16 @@ nav h3 {
height: 100%;
}
button input {
outline: none;
background: none;
border: none;
width: 20px;
text-align: right;
}
.sidemenu {
top: 30px;
bottom: 0;
left: 0;
right: 85%;
visibility: hidden;
overflow: scroll;
......@@ -116,7 +105,7 @@ nav h3 {
visibility: visible;
}
.sidemenu #header {
.sidemenu #footer {
border-top: 2px solid rgb(44, 44, 44);
}
......@@ -127,6 +116,19 @@ nav h3 {
text-align: left;
}
button.category {
background: rgba(0, 0, 0, .10);
}
button.indent {
padding-left: 28px;
display: none;
}
button.collapse {
display: block;
}
.workspace {
position: absolute;
top: 30px;
......@@ -136,51 +138,43 @@ nav h3 {
}
nav,
section {
position: absolute;
border: 1px solid rgb(44, 44, 44);
box-sizing: border-box;
}
section,
.viewer_container,
.editor_container {
position: absolute;
}
.viewer_container {
top: 0;
bottom: 0;
left: 0;
right: 0;
}
nav,
section {
border: 1px solid rgb(44, 44, 44);
box-sizing: border-box;
}
.viewer_container {
right: 50%;
}
.editor_container {
top: 0;
bottom: 0;
left: 50%;
right: 0;
}
.module_container {
top: 0;
bottom: 50%;
left: 0;
right: 0;
overflow: hidden;
border: none;
}
.tab_container {
top: 50%;
bottom: 30px;
left: 0;
right: 0;
top: 30px;
}
.tab {
position: absolute;
width: 100%;
height: 100%;
overflow: scroll;
visibility: hidden;
}
......@@ -193,47 +187,73 @@ section {
visibility: visible;
}
.module_wrapper {
overflow: scroll;
}
.module_wrapper .name {
position: fixed;
z-index: 5;
padding: 4px;
font-size: 14px;
background: rgb(44, 44, 44);
}
.module_wrapper .wrapper {
padding: 24px 16px;
box-sizing: border-box;
}
#tab_desc > .wrapper a {
text-decoration: underline;
}
.tab_bar {
bottom: 0;
left: 0;
right: 0;
height: 30px;
}
.files_bar {
left: 0;
right: 0;
height: 30px;
}
.explanation_container {
top: 30px;
left: 0;
right: 0;
height: 30px;
background: rgb(44, 44, 44);
padding: 0 8px;
line-height: 30px;
padding: 7px;
font-size: 12px;
overflow-y: auto;
}
#explanation:before {
font-family: FontAwesome;
content: '\f05a\00a0\00a0';
}
#explanation {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.explanation_container:hover {
z-index: 5;
height: auto;
bottom: auto;
box-shadow: 0 8px 8px -8px rgba(0, 0, 0, .8);
}
.explanation_container:hover #explanation {
white-space: normal;
}
.data_container {
top: 60px;
bottom: 60%;
left: 0;
right: 0;
}
.code_container {
left: 0;
top: 40%;
right: 0;
bottom: 0;
}
pre {
......@@ -269,6 +289,11 @@ pre {
background: rgba(120, 0, 0, .8);
}
.toast.info {
border-color: rgb(0, 150, 0);
background: rgba(0, 120, 0, .8);
}
.github-fork-ribbon {
position: fixed;
}
......@@ -303,6 +328,6 @@ pre {
background: #00f;
}
.mtbl-cell.notifying {
.mtbl-cell.notified {
background: #f00;
}
......@@ -2,11 +2,11 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="description" content="Tool for visualizing algorithms." />
<meta property="og:title" content="Algorithm Visualizer" />
<meta property="og:description" content="Tool for visualizing algorithms." />
<meta property="og:image" content="img/image.png" />
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
<meta name="description" content="Tool for visualizing algorithms."/>
<meta property="og:title" content="Algorithm Visualizer"/>
<meta property="og:description" content="Tool for visualizing algorithms."/>
<meta property="og:image" content="img/image.png"/>
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon"/>
<title>Algorithm Visualizer</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
<link rel="stylesheet" href="css/font-awesome.min.css">
......@@ -30,73 +30,59 @@
<button id="btn_prev"><i class="fa fa-chevron-left" aria-hidden="true"></i> Prev</button>
<button id="btn_pause"><i class="fa fa-pause" aria-hidden="true"></i> Pause</button>
<button id="btn_next">Next <i class="fa fa-chevron-right" aria-hidden="true"></i></button>
<button id="btn_interval">Interval: <input type="text" value="0.5"> sec</button>
</div>
</nav>
<section class="sidemenu active">
<div id="list">
</div>
<div id="header">
<div id="footer">
<button id="scratch-paper"><i class="fa fa-code"></i> Scratch Paper</button>
<a href="https://github.com/parkjs814/AlgorithmVisualizer/wiki">
<button><i class="fa fa-book"></i> Documentation</button>
</a>
<button class="category"><i class="fa fa-github"></i> Powered by ...</button>
<a href="https://github.com/jquery/jquery">
<button class="indent">jquery/jquery</button>
</a>
<a href="https://github.com/ajaxorg/ace">
<button class="indent">ajaxorg/ace</button>
</a>
<a href="https://github.com/jacomyal/sigma.js">
<button class="indent">jacomyal/sigma.js</button>
</a>
<a href="https://github.com/FortAwesome/Font-Awesome">
<button class="indent">FortAwesome/Font-Awesome</button>
</a>
<a href="https://github.com/simonwhitaker/github-fork-ribbon-css">
<button class="indent">simonwhitaker/github-fork-ribbon-css</button>
</a>
<button class="category" id="powered-by"><i class="fa fa-github"></i> Powered by ...</button>
<div id="powered-by-list">
<a href="https://github.com/jquery/jquery">
<button class="indent">jquery/jquery</button>
</a>
<a href="https://github.com/ajaxorg/ace">
<button class="indent">ajaxorg/ace</button>
</a>
<a href="https://github.com/jacomyal/sigma.js">
<button class="indent">jacomyal/sigma.js</button>
</a>
<a href="https://github.com/FortAwesome/Font-Awesome">
<button class="indent">FortAwesome/Font-Awesome</button>
</a>
<a href="https://github.com/simonwhitaker/github-fork-ribbon-css">
<button class="indent">simonwhitaker/github-fork-ribbon-css</button>
</a>
</div>
</div>
<a class="github-fork-ribbon left-bottom" href="http://github.com/parkjs814/AlgorithmVisualizer"
title="Fork me on GitHub">Fork me on GitHub</a>
</section>
<div class="workspace">
<div class="viewer_container">
<section class="module_container"></section>
<section class="tab_bar">
<button class="active" id="btn_desc">Description</button>
<button id="btn_trace">Trace</button>
</section>
<section class="tab_container">
<div class="tab active" id="tab_desc">
<div class="wrapper">
<h2 id="desc_title"></h2>
<p id="desc_def"></p>
<hr/>
<h3>Application</h3>
<ul id="desc_app"></ul>
<hr/>
<h3>Complexity</h3>
<p>
<strong>Time</strong> <span id="desc_time"></span><br/>
<strong>Space</strong> <span id="desc_space"></span>
</p>
<hr/>
<h3>Reference</h3>
<ul id="desc_ref"></ul>
</div>
</div>
<div class="tab" id="tab_trace">
<div class="wrapper">
</div>
<div class="tab module_container" id="tab_module">
</div>
</section>
<section class="tab_bar">
<button class="active" id="btn_desc">Description</button>
<button id="btn_trace">Trace</button>
</section>
</div>
<div class="editor_container">
<section class="files_bar">
</section>
<section class="explanation_container">
<i class="fa fa-info-circle" aria-hidden="true"></i> <span id="explanation"></span>
<span id="explanation"></span>
</section>
<section class="data_container">
<pre id="data"></pre>
......@@ -112,13 +98,16 @@
<script src="js/sigma/sigma.min.js"></script>
<script src="js/sigma/plugins/sigma.plugins.dragNodes.min.js"></script>
<script src="js/ace/ace.js"></script>
<script src="js/ace/ext-language_tools.js"></script>
<script src="js/module/tracer_manager.js"></script>
<script src="js/module/tracer.js"></script>
<script src="js/module/log_tracer.js"></script>
<script src="js/module/array2d.js"></script>
<script src="js/module/array1d.js"></script>
<script src="js/module/directed_graph.js"></script>
<script src="js/module/undirected_graph.js"></script>
<script src="js/module/weighted_directed_graph.js"></script>
<script src="js/module/weighted_undirected_graph.js"></script>
<script src="js/module/array2d.js"></script>
<script src="js/module/array1d.js"></script>
<script src="js/script.js"></script>
<script>
(function (i, s, o, g, r, a, m) {
......
function Array1DTracer(module) {
return Array2DTracer.call(this, module || Array1DTracer);
function Array1DTracer() {
return Array2DTracer.apply(this, arguments);
}
Array1DTracer.prototype = $.extend(true, Object.create(Array2DTracer.prototype), {
constructor: Array1DTracer,
_setData: function (D) {
return Array2DTracer.prototype._setData.call(this, [D]);
_notify: function (idx, v) {
Array2DTracer.prototype._notify.call(this, 0, idx, v);
return this;
},
_notify: function (idx1, idx2) {
if (idx2 === undefined) {
Array2DTracer.prototype._notify.call(this, 0, idx1);
} else {
Array2DTracer.prototype._notify.call(this, 0, idx1, 0, idx2);
}
_denotify: function (idx) {
Array2DTracer.prototype._denotify.call(this, 0, idx);
return this;
},
_select: function (s, e) {
if (e === undefined) {
......@@ -20,16 +18,7 @@ Array1DTracer.prototype = $.extend(true, Object.create(Array2DTracer.prototype),
} else {
Array2DTracer.prototype._selectRow.call(this, 0, s, e);
}
},
_selectSet: function (indexes) {
var coords = [];
indexes.forEach(function (index) {
coords.push({
x: 0,
y: index
});
});
Array2DTracer.prototype._selectSet.call(this, coords);
return this;
},
_deselect: function (s, e) {
if (e === undefined) {
......@@ -37,16 +26,10 @@ Array1DTracer.prototype = $.extend(true, Object.create(Array2DTracer.prototype),
} else {
Array2DTracer.prototype._deselectRow.call(this, 0, s, e);
}
return this;
},
_deselectSet: function (indexes) {
var coords = [];
indexes.forEach(function (index) {
coords.push({
x: 0,
y: index
});
});
Array2DTracer.prototype._deselectSet.call(this, coords);
setData: function (D) {
return Array2DTracer.prototype.setData.call(this, [D]);
}
});
......
var $table = null;
function Array2DTracer(module) {
if (Tracer.call(this, module || Array2DTracer)) {
function Array2DTracer() {
if (Tracer.apply(this, arguments)) {
Array2DTracer.prototype.init.call(this);
return true;
}
......@@ -11,98 +9,49 @@ function Array2DTracer(module) {
Array2DTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
constructor: Array2DTracer,
init: function () {
$table = $('<div class="mtbl-table">');
$module_container.append($table);
},
resize: function () {
Tracer.prototype.resize.call(this);
this.refresh();
},
clear: function () {
Tracer.prototype.clear.call(this);
this.clearColor();
this.$table = this.capsule.$table = $('<div class="mtbl-table">');
this.$container.append(this.$table);
},
_setData: function (D) {
this.D = D;
this.viewX = this.viewY = 0;
this.paddingH = 6;
this.paddingV = 3;
this.fontSize = 16;
if (Tracer.prototype._setData.call(this, arguments)) {
$('.mtbl-row').each(function (i) {
$(this).children().each(function (j) {
$(this).text(D[i][j]);
});
});
return true;
}
$table.empty();
for (var i = 0; i < D.length; i++) {
var $row = $('<div class="mtbl-row">');
$table.append($row);
for (var j = 0; j < D[i].length; j++) {
var $cell = $('<div class="mtbl-cell">')
.css(this.getCellCss())
.text(D[i][j]);
$row.append($cell);
}
}
this.resize();
return false;
_notify: function (x, y, v) {
tm.pushStep(this.capsule, {
type: 'notify',
x: x,
y: y,
v: v
});
return this;
},
_notify: function (x1, y1, x2, y2) {
var second = x2 !== undefined && y2 !== undefined;
this.pushStep({
type: 'notifying',
x: x1,
y: y1,
value: this.D[x1][y1]
}, !second);
if (second) this.pushStep({
type: 'notifying',
x: x2,
y: y2,
value: this.D[x2][y2]
}, true);
this.pushStep({
type: 'notified',
x: x1,
y: y1
}, false);
if (second) this.pushStep({
type: 'notified',
x: x2,
y: y2
}, false);
_denotify: function (x, y) {
tm.pushStep(this.capsule, {
type: 'denotify',
x: x,
y: y
});
return this;
},
_select: function (sx, sy, ex, ey) {
this.pushSelectingStep('select', null, arguments);
return this;
},
_selectRow: function (x, sy, ey) {
this.pushSelectingStep('select', 'row', arguments);
return this;
},
_selectCol: function (y, sx, ex) {
this.pushSelectingStep('select', 'col', arguments);
},
_selectSet: function (coords) {
this.pushSelectingStep('select', 'set', arguments);
return this;
},
_deselect: function (sx, sy, ex, ey) {
this.pushSelectingStep('deselect', null, arguments);
return this;
},
_deselectRow: function (x, sy, ey) {
this.pushSelectingStep('deselect', 'row', arguments);
return this;
},
_deselectCol: function (y, sx, ex) {
this.pushSelectingStep('deselect', 'col', arguments);
},
_deselectSet: function (coords) {
this.pushSelectingStep('deselect', 'set', arguments);
return this;
},
pushSelectingStep: function () {
var args = Array.prototype.slice.call(arguments);
......@@ -125,11 +74,6 @@ Array2DTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
ex: args[2]
};
break;
case 'set':
coord = {
coords: args[0]
};
break;
default:
if (args[2] === undefined && args[3] === undefined) {
coord = {
......@@ -149,40 +93,74 @@ Array2DTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
type: type
};
$.extend(step, coord);
this.pushStep(step, type == 'select');
tm.pushStep(this.capsule, step);
},
processStep: function (step, options) {
var tracer = this;
switch (step.type) {
case 'notifying':
var $row = $table.find('.mtbl-row').eq(step.x);
$row.find('.mtbl-cell').eq(step.y).text(step.value);
case 'notified':
case 'notify':
if (step.v) {
var $row = this.$table.find('.mtbl-row').eq(step.x);
$row.find('.mtbl-cell').eq(step.y).text(refineNumber(step.v));
}
case 'denotify':
case 'select':
case 'deselect':
var colorClass = step.type == 'select' || step.type == 'deselect' ? this.colorClass.selected : this.colorClass.notifying;
var addClass = step.type == 'select' || step.type == 'notifying';
if (step.coords) {
step.coords.forEach(function (coord) {
var x = coord.x;
var y = coord.y;
tracer.paintColor(x, y, x, y, colorClass, addClass);
});
} else {
var sx = step.sx;
var sy = step.sy;
var ex = step.ex;
var ey = step.ey;
if (sx === undefined) sx = step.x;
if (sy === undefined) sy = step.y;
if (ex === undefined) ex = step.x;
if (ey === undefined) ey = step.y;
this.paintColor(sx, sy, ex, ey, colorClass, addClass);
}
var colorClass = step.type == 'select' || step.type == 'deselect' ? this.colorClass.selected : this.colorClass.notified;
var addClass = step.type == 'select' || step.type == 'notify';
var sx = step.sx;
var sy = step.sy;
var ex = step.ex;
var ey = step.ey;
if (sx === undefined) sx = step.x;
if (sy === undefined) sy = step.y;
if (ex === undefined) ex = step.x;
if (ey === undefined) ey = step.y;
this.paintColor(sx, sy, ex, ey, colorClass, addClass);
break;
default:
Tracer.prototype.processStep.call(this, step, options);
}
},
setData: function (D) {
this.viewX = this.viewY = 0;
this.paddingH = 6;
this.paddingV = 3;
this.fontSize = 16;
if (Tracer.prototype.setData.apply(this, arguments)) {
this.$table.find('.mtbl-row').each(function (i) {
$(this).children().each(function (j) {
$(this).text(refineNumber(D[i][j]));
});
});
return true;
}
this.$table.empty();
for (var i = 0; i < D.length; i++) {
var $row = $('<div class="mtbl-row">');
this.$table.append($row);
for (var j = 0; j < D[i].length; j++) {
var $cell = $('<div class="mtbl-cell">')
.css(this.getCellCss())
.text(refineNumber(D[i][j]));
$row.append($cell);
}
}
this.resize();
return false;
},
resize: function () {
Tracer.prototype.resize.call(this);
this.refresh();
},
clear: function () {
Tracer.prototype.clear.call(this);
this.clearColor();
},
getCellCss: function () {
return {
padding: this.paddingV.toFixed(1) + 'px ' + this.paddingH.toFixed(1) + 'px',
......@@ -192,26 +170,11 @@ Array2DTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
refresh: function () {
Tracer.prototype.refresh.call(this);
var $parent = $table.parent();
var top = $parent.height() / 2 - $table.height() / 2 + this.viewY;
var left = $parent.width() / 2 - $table.width() / 2 + this.viewX;
$table.css('margin-top', top);
$table.css('margin-left', left);
},
prevStep: function () {
this.clear();
$('#tab_trace .wrapper').empty();
var finalIndex = this.traceIndex - 1;
if (finalIndex < 0) {
this.traceIndex = -1;
return;
}
for (var i = 0; i < finalIndex; i++) {
this.step(i, {
virtual: true
});
}
this.step(finalIndex);
var $parent = this.$table.parent();
var top = $parent.height() / 2 - this.$table.height() / 2 + this.viewY;
var left = $parent.width() / 2 - this.$table.width() / 2 + this.viewX;
this.$table.css('margin-top', top);
this.$table.css('margin-left', left);
},
mousedown: function (e) {
Tracer.prototype.mousedown.call(this, e);
......@@ -250,12 +213,12 @@ Array2DTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
this.paddingV *= ratio;
this.paddingH *= ratio;
this.fontSize *= ratio;
$('.mtbl-cell').css(this.getCellCss());
this.$table.find('.mtbl-cell').css(this.getCellCss());
this.refresh();
},
paintColor: function (sx, sy, ex, ey, colorClass, addClass) {
for (var i = sx; i <= ex; i++) {
var $row = $table.find('.mtbl-row').eq(i);
var $row = this.$table.find('.mtbl-row').eq(i);
for (var j = sy; j <= ey; j++) {
var $cell = $row.find('.mtbl-cell').eq(j);
if (addClass) $cell.addClass(colorClass);
......@@ -264,11 +227,11 @@ Array2DTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
}
},
clearColor: function () {
$table.find('.mtbl-cell').removeClass(Object.keys(this.colorClass).join(' '));
this.$table.find('.mtbl-cell').removeClass(Object.keys(this.colorClass).join(' '));
},
colorClass: {
selected: 'selected',
notifying: 'notifying'
notified: 'notified'
}
});
......
var s = null, graph = null, sigmaCanvas = null;
function DirectedGraphTracer(module) {
if (Tracer.call(this, module || DirectedGraphTracer)) {
function DirectedGraphTracer() {
if (Tracer.apply(this, arguments)) {
DirectedGraphTracer.prototype.init.call(this);
return true;
}
......@@ -13,14 +11,9 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
init: function () {
var tracer = this;
if (sigmaCanvas == null) {
sigmaCanvas = $.extend(true, {}, sigma.canvas);
} else {
sigma.canvas = $.extend(true, {}, sigmaCanvas);
}
s = new sigma({
this.s = this.capsule.s = new sigma({
renderer: {
container: $module_container[0],
container: this.$container[0],
type: 'canvas'
},
settings: {
......@@ -36,33 +29,62 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
minNodeSize: .5,
maxNodeSize: 12,
labelSize: 'proportional',
labelSizeRatio: 1.3
labelSizeRatio: 1.3,
funcLabelsDef: function (node, context, settings) {
tracer.drawLabel(node, context, settings);
},
funcHoversDef: function (node, context, settings, next) {
tracer.drawOnHover(node, context, settings, next);
},
funcEdgesArrow: function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawArrow(edge, source, target, color, context, settings);
}
}
});
graph = s.graph;
sigma.canvas.labels.def = function (node, context, settings) {
tracer.drawLabel(node, context, settings);
};
sigma.canvas.hovers.def = function (node, context, settings, next) {
tracer.drawOnHover(node, context, settings, next);
};
sigma.canvas.edges.arrow = function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawArrow(edge, source, target, color, context, settings);
};
sigma.plugins.dragNodes(s, s.renderers[0]);
sigma.plugins.dragNodes(this.s, this.s.renderers[0]);
this.graph = this.capsule.graph = this.s.graph;
},
resize: function () {
Tracer.prototype.resize.call(this);
this.refresh();
_setTreeData: function (G, root) {
tm.pushStep(this.capsule, {type: 'setTreeData', arguments: arguments});
return this;
},
clear: function () {
Tracer.prototype.clear.call(this);
this.clearGraphColor();
_visit: function (target, source) {
tm.pushStep(this.capsule, {type: 'visit', target: target, source: source});
return this;
},
_setTreeData: function (G, root) {
_leave: function (target, source) {
tm.pushStep(this.capsule, {type: 'leave', target: target, source: source});
return this;
},
processStep: function (step, options) {
switch (step.type) {
case 'setTreeData':
this.setTreeData.apply(this, step.arguments);
break;
case 'visit':
case 'leave':
var visit = step.type == 'visit';
var targetNode = this.graph.nodes(this.n(step.target));
var color = visit ? this.color.visited : this.color.left;
targetNode.color = color;
if (step.source !== undefined) {
var edgeId = this.e(step.source, step.target);
var edge = this.graph.edges(edgeId);
edge.color = color;
this.graph.dropEdge(edgeId).addEdge(edge);
}
if (this.logTracer) {
var source = step.source;
if (source === undefined) source = '';
this.logTracer.print(visit ? source + ' -> ' + step.target : source + ' <- ' + step.target);
}
break;
default:
Tracer.prototype.processStep.call(this, step, options);
}
},
setTreeData: function (G, root) {
var tracer = this;
root = root || 0;
......@@ -79,10 +101,10 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
};
getDepth(root, 1);
if (this._setData(G, root)) return true;
if (this.setData.apply(this, arguments)) return true;
var place = function (node, x, y) {
var temp = graph.nodes(tracer.n(node));
var temp = tracer.graph.nodes(tracer.n(node));
temp.x = x;
temp.y = y;
};
......@@ -104,10 +126,10 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
this.refresh();
},
_setData: function (G) {
if (Tracer.prototype._setData.call(this, arguments)) return true;
setData: function (G) {
if (Tracer.prototype.setData.apply(this, arguments)) return true;
graph.clear();
this.graph.clear();
var nodes = [];
var edges = [];
var unitAngle = 2 * Math.PI / G.length;
......@@ -135,11 +157,11 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
}
}
graph.read({
this.graph.read({
nodes: nodes,
edges: edges
});
s.camera.goTo({
this.s.camera.goTo({
x: 0,
y: 0,
angle: 0,
......@@ -149,50 +171,21 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
return false;
},
_visit: function (target, source) {
this.pushStep({type: 'visit', target: target, source: source}, true);
},
_leave: function (target, source) {
this.pushStep({type: 'leave', target: target, source: source}, true);
},
processStep: function (step, options) {
switch (step.type) {
case 'visit':
case 'leave':
var visit = step.type == 'visit';
var targetNode = graph.nodes(this.n(step.target));
var color = visit ? this.color.visited : this.color.left;
targetNode.color = color;
if (step.source !== undefined) {
var edgeId = this.e(step.source, step.target);
var edge = graph.edges(edgeId);
edge.color = color;
graph.dropEdge(edgeId).addEdge(edge);
}
var source = step.source;
if (source === undefined) source = '';
this.printTrace(visit ? source + ' -> ' + step.target : source + ' <- ' + step.target);
break;
}
resize: function () {
Tracer.prototype.resize.call(this);
this.s.renderers[0].resize();
this.refresh();
},
refresh: function () {
Tracer.prototype.refresh.call(this);
s.refresh();
this.s.refresh();
},
prevStep: function () {
this.clear();
$('#tab_trace .wrapper').empty();
var finalIndex = this.traceIndex - 1;
if (finalIndex < 0) {
this.traceIndex = -1;
this.refresh();
return;
}
for (var i = 0; i < finalIndex; i++) {
this.step(i, {virtual: true});
}
this.step(finalIndex);
clear: function () {
Tracer.prototype.clear.call(this);
this.clearGraphColor();
},
color: {
visited: '#f00',
......@@ -202,10 +195,10 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
clearGraphColor: function () {
var tracer = this;
graph.nodes().forEach(function (node) {
this.graph.nodes().forEach(function (node) {
node.color = tracer.color.default;
});
graph.edges().forEach(function (edge) {
this.graph.edges().forEach(function (edge) {
edge.color = tracer.color.default;
});
},
......@@ -308,17 +301,17 @@ DirectedGraphTracer.prototype = $.extend(true, Object.create(Tracer.prototype),
context.setLineDash([5, 5]);
var nodeIdx = node.id.substring(1);
graph.edges().forEach(function (edge) {
this.graph.edges().forEach(function (edge) {
var ends = edge.id.substring(1).split("_");
if (ends[0] == nodeIdx) {
var color = '#0ff';
var source = node;
var target = graph.nodes('n' + ends[1]);
var target = tracer.graph.nodes('n' + ends[1]);
tracer.drawArrow(edge, source, target, color, context, settings);
if (next) next(edge, source, target, color, context, settings);
} else if (ends[1] == nodeIdx) {
var color = '#ff0';
var source = graph.nodes('n' + ends[0]);
var source = tracer.graph.nodes('n' + ends[0]);
var target = node;
tracer.drawArrow(edge, source, target, color, context, settings);
if (next) next(edge, source, target, color, context, settings);
......@@ -342,4 +335,29 @@ var DirectedGraph = {
}
return G;
}
};
sigma.canvas.labels.def = function (node, context, settings) {
var func = settings('funcLabelsDef');
if (func) {
func(node, context, settings);
}
};
sigma.canvas.hovers.def = function (node, context, settings) {
var func = settings('funcHoversDef');
if (func) {
func(node, context, settings);
}
};
sigma.canvas.edges.def = function (edge, source, target, context, settings) {
var func = settings('funcEdgesDef');
if (func) {
func(edge, source, target, context, settings);
}
};
sigma.canvas.edges.arrow = function (edge, source, target, context, settings) {
var func = settings('funcEdgesArrow');
if (func) {
func(edge, source, target, context, settings);
}
};
\ No newline at end of file
function LogTracer() {
if (Tracer.apply(this, arguments)) {
LogTracer.prototype.init.call(this);
return true;
}
return false;
}
LogTracer.prototype = $.extend(true, Object.create(Tracer.prototype), {
constructor: LogTracer,
init: function () {
this.$wrapper = this.capsule.$wrapper = $('<div class="wrapper">');
this.$container.append(this.$wrapper);
},
_print: function (msg) {
tm.pushStep(this.capsule, {type: 'print', msg: msg});
return this;
},
processStep: function (step, options) {
switch (step.type) {
case 'print':
this.print(step.msg);
break;
}
},
refresh: function () {
this.scrollToEnd(Math.min(50, this.interval));
},
clear: function () {
Tracer.prototype.clear.call(this);
this.$wrapper.empty();
},
print: function (message) {
this.$wrapper.append($('<span>').append(message + '<br/>'));
},
scrollToEnd: function (duration) {
this.$container.animate({scrollTop: this.$container[0].scrollHeight}, duration);
}
});
\ No newline at end of file
var timer = null;
var lastModule = null, lastData = null;
var stepLimit = 1e6;
var Tracer = function (module) {
this.module = module || Tracer;
this.traces = [];
this.pause = false;
this.traceOptions = null;
this.traceIndex = -1;
this.stepCnt = 0;
var moduleChanged = lastModule != module;
if (moduleChanged) $module_container.empty();
return moduleChanged;
};
function Tracer(name) {
this.module = this.constructor;
this.capsule = tm.allocate(this);
$.extend(this, this.capsule);
this.setName(name);
return this.new;
}
Tracer.prototype = {
resize: function () {
constructor: Tracer,
_setData: function () {
var args = Array.prototype.slice.call(arguments);
tm.pushStep(this.capsule, {type: 'setData', args: toJSON(args)});
return this;
},
clear: function () {
},
reset: function () {
this.traces = [];
this.stepCnt = 0;
if (timer) clearTimeout(timer);
$('#tab_trace .wrapper').empty();
this.clear();
},
_setData: function (arguments) {
var data = JSON.stringify(arguments);
if (lastModule == this.module && lastData == data) return true;
lastData = data;
return false;
_clear: function () {
tm.pushStep(this.capsule, {type: 'clear'});
return this;
},
_wait: function () {
tm.newStep();
return this;
},
processStep: function (step, options) {
switch (step.type) {
case 'setData':
this.setData.apply(this, fromJSON(step.args));
break;
case 'clear':
this.clear();
break;
}
},
pushStep: function (step, delay) {
if (this.stepCnt++ > stepLimit) throw "Tracer's stack overflow";
var len = this.traces.length;
var last = [];
if (len == 0) {
this.traces.push(last);
setName: function (name) {
var $name;
if (this.new) {
$name = $('<span class="name">');
this.$container.append($name);
} else {
last = this.traces[len - 1];
$name = this.$container.find('span.name');
}
last.push(step);
if (delay) this.traces.push([]);
},
_sleep: function (duration) {
this.pushStep({type: 'sleep', duration: duration}, true);
},
_print: function (msg, delay) {
this.pushStep({type: 'print', msg: msg}, delay);
},
_pace: function (interval) {
this.pushStep({type: 'pace', interval: interval}, false);
},
_clear: function () {
this.pushStep({type: 'clear'}, true);
$name.text(name || this.defaultName);
},
visualize: function (options) {
options = options || {};
options.interval = options.interval || 500;
$('#btn_trace').click();
this.traceOptions = options;
this.traceIndex = -1;
this.resumeStep();
},
isPause: function () {
return this.pause;
},
pauseStep: function () {
if (this.traceIndex < 0) return;
this.pause = true;
if (timer) clearTimeout(timer);
$('#btn_pause').addClass('active');
},
resumeStep: function () {
this.pause = false;
this.step(this.traceIndex + 1);
$('#btn_pause').removeClass('active');
setData: function () {
var data = toJSON(arguments);
if (!this.new && this.lastData == data) return true;
this.new = this.capsule.new = false;
this.lastData = this.capsule.lastData = data;
return false;
},
step: function (i, options) {
var tracer = this;
if (isNaN(i) || i >= this.traces.length || i < 0) return;
options = options || {};
this.traceIndex = i;
var trace = this.traces[i];
var sleepDuration = 0;
trace.forEach(function (step) {
switch (step.type) {
case 'sleep':
sleepDuration = step.duration;
break;
case 'print':
tracer.printTrace(step.msg);
break;
case 'pace':
tracer.traceOptions.interval = step.interval;
break;
case 'clear':
tracer.clear();
tracer.printTrace('clear traces');
break;
default:
tracer.module.prototype.processStep.call(tracer, step, options);
}
});
if (!options.virtual) {
this.refresh();
this.scrollToEnd(Math.min(50, this.traceOptions.interval));
}
if (this.pause) return;
timer = setTimeout(function () {
tracer.step(i + 1, options);
}, sleepDuration || this.traceOptions.interval);
resize: function () {
},
refresh: function () {
},
prevStep: function () {
this.step(this.traceIndex - 1);
clear: function () {
},
nextStep: function () {
this.step(this.traceIndex + 1);
attach: function (tracer) {
if (tracer.module == LogTracer) {
this.logTracer = tracer;
}
return this;
},
mousedown: function (e) {
},
......@@ -132,11 +67,5 @@ Tracer.prototype = {
mouseup: function (e) {
},
mousewheel: function (e) {
},
printTrace: function (message) {
$('#tab_trace .wrapper').append($('<span>').append(message + '<br/>'));
},
scrollToEnd: function (duration) {
$('#tab_trace').animate({scrollTop: $('#tab_trace')[0].scrollHeight}, duration);
}
};
\ No newline at end of file
const stepLimit = 1e6;
var TracerManager = function () {
this.timer = null;
this.pause = false;
this.capsules = [];
this.interval = 500;
};
TracerManager.prototype = {
add: function (tracer) {
var $container = $('<section class="module_wrapper">');
$module_container.append($container);
var capsule = {
module: tracer.module,
tracer: tracer,
allocated: true,
defaultName: null,
$container: $container,
new: true
};
this.capsules.push(capsule);
return capsule;
},
allocate: function (newTracer) {
var selectedCapsule = null;
var count = 0;
$.each(this.capsules, function (i, capsule) {
if (capsule.module == newTracer.module) {
count++;
if (!capsule.allocated) {
capsule.tracer = newTracer;
capsule.allocated = true;
capsule.new = false;
selectedCapsule = capsule;
return false;
}
}
});
if (selectedCapsule == null) {
count++;
selectedCapsule = this.add(newTracer);
}
selectedCapsule.defaultName = newTracer.constructor.name + ' ' + count;
return selectedCapsule;
},
deallocateAll: function () {
this.reset();
$.each(this.capsules, function (i, capsule) {
capsule.allocated = false;
});
},
removeUnallocated: function () {
var changed = false;
this.capsules = $.grep(this.capsules, function (capsule) {
var removed = !capsule.allocated;
if (capsule.new || removed) changed = true;
if (removed) {
capsule.$container.remove();
}
return !removed;
});
if (changed) this.place();
},
place: function () {
var capsules = this.capsules;
$.each(capsules, function (i, capsule) {
var width = 100;
var height = (100 / capsules.length);
var top = height * i;
capsule.$container.css({
top: top + '%',
width: width + '%',
height: height + '%'
});
capsule.tracer.resize();
});
},
resize: function () {
this.command('resize');
},
isPause: function () {
return this.pause;
},
setInterval: function (interval) {
$('#btn_interval input').val(interval);
},
reset: function () {
this.traces = [];
this.traceIndex = -1;
this.stepCnt = 0;
if (this.timer) clearTimeout(this.timer);
this.command('clear');
},
pushStep: function (capsule, step) {
if (this.stepCnt++ > stepLimit) throw "Tracer's stack overflow";
var len = this.traces.length;
var last = [];
if (len == 0) {
this.traces.push(last);
} else {
last = this.traces[len - 1];
}
last.push($.extend(step, {capsule: capsule}));
},
newStep: function () {
this.traces.push([]);
},
pauseStep: function () {
if (this.traceIndex < 0) return;
this.pause = true;
if (this.timer) clearTimeout(this.timer);
$('#btn_pause').addClass('active');
},
resumeStep: function () {
this.pause = false;
this.step(this.traceIndex + 1);
$('#btn_pause').removeClass('active');
},
step: function (i, options) {
var tracer = this;
if (isNaN(i) || i >= this.traces.length || i < 0) return;
options = options || {};
this.traceIndex = i;
var trace = this.traces[i];
trace.forEach(function (step) {
step.capsule.tracer.processStep(step, options);
});
if (!options.virtual) {
this.command('refresh');
}
if (this.pause) return;
this.timer = setTimeout(function () {
tracer.step(i + 1, options);
}, this.interval);
},
prevStep: function () {
this.command('clear');
var finalIndex = this.traceIndex - 1;
if (finalIndex < 0) {
this.traceIndex = -1;
this.command('refresh');
return;
}
for (var i = 0; i < finalIndex; i++) {
this.step(i, {virtual: true});
}
this.step(finalIndex);
},
nextStep: function () {
this.step(this.traceIndex + 1);
},
visualize: function () {
this.traceIndex = -1;
this.resumeStep();
},
command: function () {
var args = Array.prototype.slice.call(arguments);
var functionName = args.shift();
$.each(this.capsules, function (i, capsule) {
if (capsule.allocated) {
capsule.tracer.module.prototype[functionName].apply(capsule.tracer, args);
}
});
},
findOwner: function (container) {
var selectedCapsule = null;
$.each(this.capsules, function (i, capsule) {
if (capsule.$container[0] == container) {
selectedCapsule = capsule;
return false;
}
});
return selectedCapsule.tracer;
}
};
\ No newline at end of file
function UndirectedGraphTracer(module) {
if (DirectedGraphTracer.call(this, module || UndirectedGraphTracer)) {
function UndirectedGraphTracer() {
if (DirectedGraphTracer.apply(this, arguments)) {
UndirectedGraphTracer.prototype.init.call(this);
return true;
}
......@@ -11,18 +11,18 @@ UndirectedGraphTracer.prototype = $.extend(true, Object.create(DirectedGraphTrac
init: function () {
var tracer = this;
s.settings({
defaultEdgeType: 'def'
this.s.settings({
defaultEdgeType: 'def',
funcEdgesDef: function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawEdge(edge, source, target, color, context, settings);
}
});
sigma.canvas.edges.def = function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawEdge(edge, source, target, color, context, settings);
};
},
_setData: function (G) {
if (Tracer.prototype._setData.call(this, arguments)) return true;
setData: function (G) {
if (Tracer.prototype.setData.apply(this, arguments)) return true;
graph.clear();
this.graph.clear();
var nodes = [];
var edges = [];
var unitAngle = 2 * Math.PI / G.length;
......@@ -52,11 +52,11 @@ UndirectedGraphTracer.prototype = $.extend(true, Object.create(DirectedGraphTrac
}
}
graph.read({
this.graph.read({
nodes: nodes,
edges: edges
});
s.camera.goTo({
this.s.camera.goTo({
x: 0,
y: 0,
angle: 0,
......@@ -79,17 +79,17 @@ UndirectedGraphTracer.prototype = $.extend(true, Object.create(DirectedGraphTrac
context.setLineDash([5, 5]);
var nodeIdx = node.id.substring(1);
graph.edges().forEach(function (edge) {
this.graph.edges().forEach(function (edge) {
var ends = edge.id.substring(1).split("_");
if (ends[0] == nodeIdx) {
var color = '#0ff';
var source = node;
var target = graph.nodes('n' + ends[1]);
var target = tracer.graph.nodes('n' + ends[1]);
tracer.drawEdge(edge, source, target, color, context, settings);
if (next) next(edge, source, target, color, context, settings);
} else if (ends[1] == nodeIdx) {
var color = '#0ff';
var source = graph.nodes('n' + ends[0]);
var source = tracer.graph.nodes('n' + ends[0]);
var target = node;
tracer.drawEdge(edge, source, target, color, context, settings);
if (next) next(edge, source, target, color, context, settings);
......
function WeightedDirectedGraphTracer(module) {
if (DirectedGraphTracer.call(this, module || WeightedDirectedGraphTracer)) {
function WeightedDirectedGraphTracer() {
if (DirectedGraphTracer.apply(this, arguments)) {
WeightedDirectedGraphTracer.prototype.init.call(this);
return true;
}
......@@ -11,33 +11,69 @@ WeightedDirectedGraphTracer.prototype = $.extend(true, Object.create(DirectedGra
init: function () {
var tracer = this;
s.settings({
this.s.settings({
edgeLabelSize: 'proportional',
defaultEdgeLabelSize: 20,
edgeLabelSizePowRatio: 0.8
edgeLabelSizePowRatio: 0.8,
funcLabelsDef: function (node, context, settings) {
tracer.drawNodeWeight(node, context, settings);
tracer.drawLabel(node, context, settings);
},
funcHoversDef: function (node, context, settings) {
tracer.drawOnHover(node, context, settings, tracer.drawEdgeWeight);
},
funcEdgesArrow: function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawArrow(edge, source, target, color, context, settings);
tracer.drawEdgeWeight(edge, source, target, color, context, settings);
}
});
sigma.canvas.edges.arrow = function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawArrow(edge, source, target, color, context, settings);
tracer.drawEdgeWeight(edge, source, target, color, context, settings);
};
sigma.canvas.hovers.def = function (node, context, settings) {
tracer.drawOnHover(node, context, settings, tracer.drawEdgeWeight);
};
sigma.canvas.labels.def = function (node, context, settings) {
tracer.drawNodeWeight(node, context, settings);
tracer.drawLabel(node, context, settings);
}
},
clear: function () {
DirectedGraphTracer.prototype.clear.call(this);
this.clearWeights();
_weight: function (target, weight) {
tm.pushStep(this.capsule, {type: 'weight', target: target, weight: weight});
return this;
},
_visit: function (target, source, weight) {
tm.pushStep(this.capsule, {type: 'visit', target: target, source: source, weight: weight});
return this;
},
_leave: function (target, source, weight) {
tm.pushStep(this.capsule, {type: 'leave', target: target, source: source, weight: weight});
return this;
},
_setData: function (G) {
if (Tracer.prototype._setData.call(this, arguments)) return true;
processStep: function (step, options) {
switch (step.type) {
case 'weight':
var targetNode = this.graph.nodes(this.n(step.target));
if (step.weight !== undefined) targetNode.weight = refineNumber(step.weight);
break;
case 'visit':
case 'leave':
var visit = step.type == 'visit';
var targetNode = this.graph.nodes(this.n(step.target));
var color = visit ? this.color.visited : this.color.left;
targetNode.color = color;
if (step.weight !== undefined) targetNode.weight = refineNumber(step.weight);
if (step.source !== undefined) {
var edgeId = this.e(step.source, step.target);
var edge = this.graph.edges(edgeId);
edge.color = color;
this.graph.dropEdge(edgeId).addEdge(edge);
}
if (this.logTracer) {
var source = step.source;
if (source === undefined) source = '';
this.logTracer.print(visit ? source + ' -> ' + step.target : source + ' <- ' + step.target);
}
break;
default:
DirectedGraphTracer.prototype.processStep.call(this, step, options);
}
},
setData: function (G) {
if (Tracer.prototype.setData.apply(this, arguments)) return true;
graph.clear();
this.graph.clear();
var nodes = [];
var edges = [];
var unitAngle = 2 * Math.PI / G.length;
......@@ -61,17 +97,17 @@ WeightedDirectedGraphTracer.prototype = $.extend(true, Object.create(DirectedGra
target: this.n(j),
color: this.color.default,
size: 1,
weight: G[i][j]
weight: refineNumber(G[i][j])
});
}
}
}
graph.read({
this.graph.read({
nodes: nodes,
edges: edges
});
s.camera.goTo({
this.s.camera.goTo({
x: 0,
y: 0,
angle: 0,
......@@ -81,44 +117,13 @@ WeightedDirectedGraphTracer.prototype = $.extend(true, Object.create(DirectedGra
return false;
},
_weight: function (target, weight, delay) {
this.pushStep({type: 'weight', target: target, weight: weight}, delay);
},
_visit: function (target, source, weight) {
this.pushStep({type: 'visit', target: target, source: source, weight: weight}, true);
},
_leave: function (target, source, weight) {
this.pushStep({type: 'leave', target: target, source: source, weight: weight}, true);
},
processStep: function (step, options) {
switch (step.type) {
case 'weight':
var targetNode = graph.nodes(this.n(step.target));
if (step.weight !== undefined) targetNode.weight = step.weight;
break;
case 'visit':
case 'leave':
var visit = step.type == 'visit';
var targetNode = graph.nodes(this.n(step.target));
var color = visit ? this.color.visited : this.color.left;
targetNode.color = color;
if (step.weight !== undefined) targetNode.weight = step.weight;
if (step.source !== undefined) {
var edgeId = this.e(step.source, step.target);
var edge = graph.edges(edgeId);
edge.color = color;
graph.dropEdge(edgeId).addEdge(edge);
}
var source = step.source;
if (source === undefined) source = '';
this.printTrace(visit ? source + ' -> ' + step.target : source + ' <- ' + step.target);
break;
default:
DirectedGraphTracer.prototype.processStep.call(this, step, options);
}
clear: function () {
DirectedGraphTracer.prototype.clear.call(this);
this.clearWeights();
},
clearWeights: function () {
graph.nodes().forEach(function (node) {
this.graph.nodes().forEach(function (node) {
node.weight = 0;
});
},
......
function WeightedUndirectedGraphTracer(module) {
if (WeightedDirectedGraphTracer.call(this, module || WeightedUndirectedGraphTracer)) {
function WeightedUndirectedGraphTracer() {
if (WeightedDirectedGraphTracer.apply(this, arguments)) {
WeightedUndirectedGraphTracer.prototype.init.call(this);
return true;
}
......@@ -11,19 +11,19 @@ WeightedUndirectedGraphTracer.prototype = $.extend(true, Object.create(WeightedD
init: function () {
var tracer = this;
s.settings({
defaultEdgeType: 'def'
this.s.settings({
defaultEdgeType: 'def',
funcEdgesDef: function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawEdge(edge, source, target, color, context, settings);
tracer.drawEdgeWeight(edge, source, target, color, context, settings);
}
});
sigma.canvas.edges.def = function (edge, source, target, context, settings) {
var color = tracer.getColor(edge, source, target, settings);
tracer.drawEdge(edge, source, target, color, context, settings);
tracer.drawEdgeWeight(edge, source, target, color, context, settings);
};
},
_setData: function (G) {
if (Tracer.prototype._setData.call(this, arguments)) return true;
setData: function (G) {
if (Tracer.prototype.setData.apply(this, arguments)) return true;
graph.clear();
this.graph.clear();
var nodes = [];
var edges = [];
var unitAngle = 2 * Math.PI / G.length;
......@@ -55,11 +55,11 @@ WeightedUndirectedGraphTracer.prototype = $.extend(true, Object.create(WeightedD
}
}
graph.read({
this.graph.read({
nodes: nodes,
edges: edges
});
s.camera.goTo({
this.s.camera.goTo({
x: 0,
y: 0,
angle: 0,
......@@ -79,8 +79,6 @@ WeightedUndirectedGraphTracer.prototype = $.extend(true, Object.create(WeightedD
source = target;
target = temp;
}
console.log(source);
console.log(target);
WeightedDirectedGraphTracer.prototype.drawEdgeWeight.call(this, edge, source, target, color, context, settings);
}
});
......
......@@ -8,10 +8,22 @@ $(document).on('click', 'a', function (e) {
}
});
var tm = new TracerManager();
$('#btn_interval input').on('change', function () {
tm.interval = Number.parseFloat($(this).val() * 1000);
showInfoToast('Tracing interval has been set to ' + tm.interval / 1000 + ' second(s).');
});
var $module_container = $('.module_container');
var _tracer = new Tracer();
ace.require("ace/ext/language_tools");
var initEditor = function (id) {
var editor = ace.edit(id);
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
});
editor.setTheme("ace/theme/tomorrow_night_eighties");
editor.session.setMode("ace/mode/javascript");
editor.$blockScrolling = Infinity;
......@@ -19,31 +31,43 @@ var initEditor = function (id) {
};
var dataEditor = initEditor('data');
var codeEditor = initEditor('code');
var lastDir = null;
var lastFile = null;
dataEditor.on('change', function () {
var data = dataEditor.getValue();
if (lastDir) cachedFile[lastDir].data = data;
if (lastFile) cachedFile[lastFile].data = data;
try {
tm.deallocateAll();
eval(data);
lastModule = tracer && tracer.module;
_tracer = tracer;
} catch (err) {
} finally {
tm.visualize();
tm.removeUnallocated();
}
_tracer.reset();
});
codeEditor.on('change', function () {
var code = codeEditor.getValue();
if (lastDir) cachedFile[lastDir].code = code;
if (lastFile) cachedFile[lastFile].code = code;
});
var cachedFile = {};
var loading = false;
var isScratchPaper = function (category, algorithm) {
return category == null && algorithm == 'scratch_paper';
};
var getAlgorithmDir = function (category, algorithm) {
if (isScratchPaper(category, algorithm)) return './algorithm/scratch_paper/';
return './algorithm/' + category + '/' + algorithm + '/';
};
var getFileDir = function (category, algorithm, file) {
if (isScratchPaper(category, algorithm)) return './algorithm/scratch_paper/';
return './algorithm/' + category + '/' + algorithm + '/' + file + '/';
};
var loadFile = function (category, algorithm, file, explanation) {
if (checkLoading()) return;
lastData = null;
$('#explanation').html(explanation);
var dir = lastDir = './algorithm/' + category + '/' + algorithm + '/' + file + '/';
var dir = lastFile = getFileDir(category, algorithm, file);
if (cachedFile[dir] && cachedFile[dir].data !== undefined && cachedFile[dir].code !== undefined) {
dataEditor.setValue(cachedFile[dir].data, -1);
codeEditor.setValue(cachedFile[dir].code, -1);
......@@ -75,64 +99,85 @@ var checkLoading = function () {
}
return false;
};
var loadAlgorithm = function (category, algorithm) {
if (checkLoading()) return;
$('#list > button').removeClass('active');
$('[data-category="' + category + '"][data-algorithm="' + algorithm + '"]').addClass('active');
var showDescription = function (data) {
var $container = $('#tab_desc > .wrapper');
$container.empty();
for (var key in data) {
if (key) $container.append($('<h3>').html(key));
var value = data[key];
if (typeof value === "string") {
$container.append($('<p>').html(value));
} else if (Array.isArray(value)) {
var $ul = $('<ul>');
$container.append($ul);
value.forEach(function (li) {
$ul.append($('<li>').html(li));
});
} else if (typeof value === "object") {
var $ul = $('<ul>');
$container.append($ul);
for (var prop in value) {
$ul.append($('<li>').append($('<strong>').html(prop)).append(' ' + value[prop]));
}
}
}
};
var showAlgorithm = function (category, algorithm) {
var $menu;
var category_name;
var algorithm_name;
if (isScratchPaper(category, algorithm)) {
$menu = $('#scratch-paper');
category_name = '';
algorithm_name = 'Scratch Paper';
} else {
$menu = $('[data-category="' + category + '"][data-algorithm="' + algorithm + '"]');
category_name = list[category].name;
algorithm_name = list[category].list[algorithm];
}
$('.sidemenu button').removeClass('active');
$menu.addClass('active');
$('#btn_desc').click();
$('#category').html(list[category].name);
$('#algorithm, #desc_title').html(list[category].list[algorithm]);
$('#category').html(category_name);
$('#algorithm').html(algorithm_name);
$('#tab_desc > .wrapper').empty();
$('.files_bar').empty();
$('#explanation').html('');
lastDir = null;
lastFile = null;
dataEditor.setValue('');
codeEditor.setValue('');
};
var showFiles = function (category, algorithm, files) {
$('.files_bar').empty();
var init = false;
for (var file in files) {
(function (file, explanation) {
var $file = $('<button>').append(file).click(function () {
loadFile(category, algorithm, file, explanation);
$('.files_bar > button').removeClass('active');
$(this).addClass('active');
});
$('.files_bar').append($file);
if (!init) {
init = true;
$file.click();
}
})(file, files[file]);
}
};
var loadAlgorithm = function (category, algorithm) {
if (checkLoading()) return;
showAlgorithm(category, algorithm);
var dir = getAlgorithmDir(category, algorithm);
var dir = './algorithm/' + category + '/' + algorithm + '/';
$.getJSON(dir + 'desc.json', function (data) {
var files = data.files;
delete data.files;
var $container = $('#tab_desc > .wrapper');
$container.empty();
for (var key in data) {
if (key) $container.append($('<h3>').html(key));
var value = data[key];
if (typeof value === "string") {
$container.append($('<p>').html(value));
} else if (Array.isArray(value)) {
var $ul = $('<ul>');
$container.append($ul);
value.forEach(function (li) {
$ul.append($('<li>').html(li));
});
} else if (typeof value === "object") {
var $ul = $('<ul>');
$container.append($ul);
for (var prop in value) {
$ul.append($('<li>').append($('<strong>').html(prop)).append(' ' + value[prop]));
}
}
}
$('.files_bar').empty();
var init = false;
for (var file in files) {
(function (file, explanation) {
var $file = $('<button>').append(file).click(function () {
loadFile(category, algorithm, file, explanation);
$('.files_bar > button').removeClass('active');
$(this).addClass('active');
});
$('.files_bar').append($file);
if (!init) {
init = true;
$file.click();
}
})(file, files[file]);
}
showDescription(data);
showFiles(category, algorithm, files);
});
};
var list = {};
......@@ -142,6 +187,9 @@ $.getJSON('./algorithm/category.json', function (data) {
for (var category in list) {
(function (category) {
var $category = $('<button class="category">').append(list[category].name);
$category.click(function () {
$('[data-category="' + category + '"]').toggleClass('collapse');
});
$('#list').append($category);
var subList = list[category].list;
for (var algorithm in subList) {
......@@ -163,6 +211,12 @@ $.getJSON('./algorithm/category.json', function (data) {
})(category);
}
});
$('#powered-by').click(function () {
$('#powered-by-list button').toggleClass('collapse');
});
$('#scratch-paper').click(function () {
loadAlgorithm(null, 'scratch_paper');
});
var sidemenu_percent;
$('#navigation').click(function () {
......@@ -178,7 +232,7 @@ $('#navigation').click(function () {
$sidemenu.css('right', 0);
$workspace.css('left', 0);
}
_tracer.resize();
tm.resize();
});
var showErrorToast = function (err) {
......@@ -191,33 +245,44 @@ var showErrorToast = function (err) {
}, 3000);
};
var showInfoToast = function (info) {
var $toast = $('<div class="toast info">').append(info);
$('.toast_container').append($toast);
setTimeout(function () {
$toast.fadeOut(function () {
$toast.remove();
});
}, 3000);
};
$('#btn_run').click(function () {
$('#btn_trace').click();
try {
tm.deallocateAll();
eval(dataEditor.getValue());
lastModule = tracer && tracer.module;
_tracer = tracer;
_tracer.reset();
eval(codeEditor.getValue());
_tracer.visualize();
tm.visualize();
} catch (err) {
console.error(err);
showErrorToast(err);
} finally {
tm.removeUnallocated();
}
});
$('#btn_pause').click(function () {
if (_tracer.isPause()) {
_tracer.resumeStep();
if (tm.isPause()) {
tm.resumeStep();
} else {
_tracer.pauseStep();
tm.pauseStep();
}
});
$('#btn_prev').click(function () {
_tracer.pauseStep();
_tracer.prevStep();
tm.pauseStep();
tm.prevStep();
});
$('#btn_next').click(function () {
_tracer.pauseStep();
_tracer.nextStep();
tm.pauseStep();
tm.nextStep();
});
$('#btn_desc').click(function () {
......@@ -228,17 +293,18 @@ $('#btn_desc').click(function () {
});
$('#btn_trace').click(function () {
$('.tab_container > .tab').removeClass('active');
$('#tab_trace').addClass('active');
$('#tab_module').addClass('active');
$('.tab_bar > button').removeClass('active');
$(this).addClass('active');
});
$(window).resize(_tracer.resize);
$(window).resize(function () {
tm.resize();
});
var dividers = [
['v', $('.sidemenu'), $('.workspace')],
['v', $('.viewer_container'), $('.editor_container')],
['h', $('.module_container'), $('.tab_container')],
['h', $('.data_container'), $('.code_container')]
];
for (var i = 0; i < dividers.length; i++) {
......@@ -251,6 +317,7 @@ for (var i = 0; i < dividers.length; i++) {
var thickness = 5;
var $divider = $('<div class="divider">');
var dragging = false;
if (vertical) {
$divider.addClass('vertical');
var _left = -thickness / 2;
......@@ -260,7 +327,7 @@ for (var i = 0; i < dividers.length; i++) {
left: _left,
width: thickness
});
var x, dragging = false;
var x;
$divider.mousedown(function (e) {
x = e.pageX;
dragging = true;
......@@ -273,7 +340,7 @@ for (var i = 0; i < dividers.length; i++) {
$first.css('right', (100 - percent) + '%');
$second.css('left', percent + '%');
x = e.pageX;
_tracer.resize();
tm.resize();
}
});
$(document).mouseup(function (e) {
......@@ -288,7 +355,7 @@ for (var i = 0; i < dividers.length; i++) {
left: 0,
right: 0
});
var y, dragging = false;
var y;
$divider.mousedown(function (e) {
y = e.pageY;
dragging = true;
......@@ -301,7 +368,7 @@ for (var i = 0; i < dividers.length; i++) {
$first.css('bottom', (100 - percent) + '%');
$second.css('top', percent + '%');
y = e.pageY;
_tracer.resize();
tm.resize();
}
});
$(document).mouseup(function (e) {
......@@ -313,15 +380,71 @@ for (var i = 0; i < dividers.length; i++) {
})(divider);
}
$module_container.mousedown(function (e) {
_tracer.mousedown(e);
$module_container.on('mousedown', '.module_wrapper', function (e) {
tm.findOwner(this).mousedown(e);
});
$module_container.mousemove(function (e) {
_tracer.mousemove(e);
$module_container.on('mousemove', '.module_wrapper', function (e) {
tm.findOwner(this).mousemove(e);
});
$(document).mouseup(function (e) {
_tracer.mouseup(e);
tm.command('mouseup', e);
});
$module_container.bind('DOMMouseScroll mousewheel', function (e) {
_tracer.mousewheel(e);
});
\ No newline at end of file
$module_container.on('DOMMouseScroll mousewheel', '.module_wrapper', function (e) {
tm.findOwner(this).mousewheel(e);
});
// Share scratch paper
var getParameterByName = function (name) {
var url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
};
var shareScratchPaper = function () {
var gist = {
'description': 'temp',
'public': true,
'files': {
'code.js': {'content': dataEditor.getValue()},
'data.js': {'content': codeEditor.getValue()}
}
};
$.post('https://api.github.com/gists', JSON.stringify(gist), function (res) {
var data = JSON.parse(res);
console.log(location.protocol + '//' + location.host + location.pathname + '?scratch-paper=' + data.id);
});
};
var loadScratchPaper = function (gistID) {
$.get('https://api.github.com/gists/' + gistID, function (res) {
var data = JSON.parse(res);
console.log(data);
});
};
if (/[?&]scratch-paper=/.test(location.search)) {
var gistID = getParameterByName('scratch-paper');
console.log(gistID);
loadScratchPaper(gistID);
}
var toJSON = function (obj) {
return JSON.stringify(obj, function (key, value) {
return value === Infinity ? "Infinity" : value;
});
};
var fromJSON = function (obj) {
return JSON.parse(obj, function (key, value) {
return value === "Infinity" ? Infinity : value;
});
};
var refineNumber = function (number) {
return number === Infinity ? '' : number;
};
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册