Skip to content

Commit

Permalink
latest version
Browse files Browse the repository at this point in the history
  • Loading branch information
amitkaps committed Nov 18, 2017
1 parent 8fd41b1 commit 31723e3
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 348 deletions.
9 changes: 6 additions & 3 deletions index.html
Expand Up @@ -4,7 +4,7 @@
<meta name="description" content="Create Simple Visualisation Charts with Markdown">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link href="https://fonts.googleapis.com/css?family=PT+Sans:400,400i|PT+Serif:700,700i|Roboto+Mono:400,400i,700" rel="stylesheet">
<!-- <link href="https://fonts.googleapis.com/css?family=PT+Sans:400,400i|PT+Serif:700,700i|Roboto+Mono:400,400i,700" rel="stylesheet"> -->
<link rel="stylesheet" href="/static/css/codemirror.css">
<!-- <link rel="stylesheet" href="/static/css/github-markdown.css"> -->
<link rel="stylesheet" href="/static/css/visdown.css">
Expand All @@ -20,7 +20,7 @@

<!-- Markdown Dependencies -->
<script src="/static/lib/marked.js"></script>
<script src="/src/visdown.js"></script>


<body class="yin">
<header>
Expand Down Expand Up @@ -48,6 +48,9 @@
<section id="output" class="markdown-body"></section>
</main>

<script src="js/grammar.js"></script>
<script src="/src/datum.js"></script>
<script src="/src/visdown.js"></script>
<script src="js/editor.js"></script>
<!-- <script src="js/ui.js"></script> -->
</body>

101 changes: 80 additions & 21 deletions js/grammar.js → js/editor.js
@@ -1,20 +1,48 @@

// For CodeMirror Editor Operations

// For Editor Operations
const visdown = window.visdown
const datum = window.datum

/**
* Calculate a 32 bit FNV-1a hash
* Found here: https://gist.github.com/vaiorabbit/5657561
* Ref.: http://isthe.com/chongo/tech/comp/fnv/
*
* @param {string} str the input value
* @param {integer} [seed] optionally pass the hash of the previous chunk
* @returns {string}
*/
function _hashFnv32a(str, seed) {
/*jshint bitwise:false */
var i, l, hval = (seed === undefined) ? 0x811c9dc5 : seed;
for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
}
// Convert to 8 digit hex string
return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
}


// Regex for getting vis code blocks and extracting viscode
const re = /^((```)vis\s([\s\S]+?)(^\2)\s)/gm
const newline = /\n/gm
const visStart = /^```vis\s*\n/gm
const visEnd = /^```\s*\n/gm

function _countNewline(str){
if (str ==="") {return 0 } else {
if (str === "") {return 0 } else {
let newlineMatch = str.match(newline)
if (newlineMatch === null) {return 0}
let len = newlineMatch.length
return len
}
}

function _getVisText(str){
let visText = str.split(visStart)[1].split(visEnd)[0]
return visText
}

// Create Keys to work with CodeMirror Lines
function _keys(str) {
let visCode = str.match(re) || [];
Expand All @@ -23,6 +51,10 @@ function _keys(str) {
let checkString = str
let start = 0
visCode.forEach(function(code, i){
let visText = _getVisText(code);
let spec = datum(visText)
let hash = _hashFnv32a(visText.trim());
console.log(spec, code, hash);
startIndex = checkString.indexOf(code)
codeLength = code.length
endIndex = startIndex + codeLength;
Expand All @@ -31,33 +63,61 @@ function _keys(str) {
codeLine = _countNewline(code)
endLine = startLine + codeLine - 1
checkString = checkString.substring(endIndex);
keys.push({"key": i, "code": code, "newlineCode": codeLine, "start": startLine, "end": endLine})
keys.push({
"key": i, "code": code, "spec": spec, "hash": hash,
"lines": codeLine, "start": startLine, "end": endLine})
start = endLine + 1
})
console.log(keys);
return keys
}

const opts = {
"mode": "vega-lite",
"renderer": "svg",
"actions": {export: false, source: false, editor: false}
};

let widgets = []
function update() {

editor.operation(function(){
for (var i = 0; i < widgets.length; ++i)
editor.removeLineWidget(widgets[i]);
widgets.length = 0;

keys = _keys(editor.getValue());

// ENTER + UPDATE - Add all new widgets and Update Vis if changed
keys.forEach(function(key, i){
console.log(key)
endLine = key.end
let msg = document.createElement("div");
let icon = msg.appendChild(document.createElement("span"));
icon.innerHTML = "!!";
icon.className = "lint-error-icon";
msg.appendChild(document.createTextNode("vis"));
msg.className = "vis";
widgets.push(editor.addLineWidget(endLine, msg));
})
})
let endLine = key.end
let spec = key.spec
let el;
console.log(editor.lineInfo(endLine)[widgets])
// ENTER - Add new widget when none exists
if (editor.lineInfo(endLine).widgets === undefined) {
el = document.createElement("div");
el.style.minHeight = 256 + 'px';
elVis = el.appendChild(document.createElement("div"));
elVis.id = "vis-editor-" + i;
elVis.setAttribute('data-hash', key.hash);
editor.addLineWidget(endLine, el);
vega.embed(elVis, spec, opts)
console.log(el);
} else {
node = editor.lineInfo(endLine).widgets[0].node
console.log(node)
hash = node.getAttribute('data-hash')
console.log(hash, key.hash)
if (hash != key.hash) {
node.setAttribute('data-hash', key.hash);
vega.embed(node, spec, opts);
}
}
})

// EXIT - Remove all widgets that should no longer exist


})

}


Expand Down Expand Up @@ -112,7 +172,6 @@ window.onload = function () {
text = editor.getValue()
elInput = document.getElementById("input");
elCodemirror = editor.getWrapperElement()
console.log(elCodemirror)
elOutput = document.getElementById("output");
elEditor = document.getElementById("editor");
elView = document.getElementById("view")
Expand Down Expand Up @@ -167,6 +226,6 @@ window.onload = function () {
waiting = setTimeout(update, 500);
});

setTimeout(update, 100);
//setTimeout(update, 100);

}
67 changes: 9 additions & 58 deletions pages/data-layer.md
Expand Up @@ -5,19 +5,8 @@
- Continuous: Temporal, Quantitative

```vis
data:
url: "data/notes.csv"
mark: line
encoding:
x:
type: temporal
field: year
y:
type: quantitative
field: money
color:
type: nominal
field: denom
data(data/notes.csv)
line(x=year:T, y=money:Q, color=denom:N)
```

## Transforming the Data
Expand All @@ -34,63 +23,25 @@ encoding:
Lets filter this data for denominations greater than INR 10.

```vis
data:
url: "data/notes.csv"
transform:
- filter: datum.value > 10
mark: line
encoding:
x:
type: temporal
field: year
y:
type: quantitative
field: money
color:
type: nominal
field: denom
data(data/notes.csv)
filter(datum.value > 10)
line(x=year:T, y=money:Q, color=denom:N)
```

### Aggregate

You can aggregate on a particular variable to do basic statistical operations like mean, sum, quantile etc.

```vis
data:
url: data/notes.csv
mark: area
encoding:
x:
field: year
type: temporal
y:
aggregate: sum
field: money
type: quantitative
color:
field: denom
type: nominal
data(data/notes.csv)
area(x=year:T, y=sum(money:Q), color=denom:N)
```

### Bins

Binning is a technique for grouping quantitative, continuous data values of a particular field into smaller number of “bins”

```vis
data:
url: "data/notes.csv"
mark: bar
encoding:
x:
type: quantitative
field: money
bin: true
y:
aggregate: count
type: quantitative
field:
color:
field: denom
type: nominal
data(data/notes.csv)
bar(x=bin(money:Q), y=count:Q, color=denom:N)
```
43 changes: 4 additions & 39 deletions pages/intro.md
Expand Up @@ -7,7 +7,9 @@ Write visualisation using a simple declarative markup like you would write code.
*Make simple static visualisations*

```vis
data(cars.csv) | point(x=kmpl, y=price)
data(cars.csv)
filter(datum.kmpl > 20)
point(x=kmpl:Q, y=price:Q)
```

Visdown is based on the grammar of interactive graphic (vega-lite) which allows you to specify the visualisation including interactions in a declarative fashion.
Expand All @@ -17,45 +19,8 @@ Visdown is based on the grammar of interactive graphic (vega-lite) which allows
Select the circles with the mouse

```vis
data:
url: "data/cars.csv"
mark: circle
selection:
brush:
type: interval
encoding:
x:
type: quantitative
field: kmpl
scale:
domain: [12,25]
y:
type: quantitative
field: price
scale:
domain: [100,900]
color:
condition:
selection: brush
field: type
type: nominal
value: grey
size:
type: quantitative
field: bhp
width: 450
height: 300
data(cars.csv) | point(x=kmpl:Q, y=price:Q, color=bhp:Q)
```

# Concept and Code

Allows you to write **json** specification in simple **yaml** and uses **marked** and **vega-lite** to convert those specific code blocks in to svg.

- yaml -> json (using [yaml.js](https://github.com/jeremyfa/yaml.js))
- json -> vega-lite -> svg (using [vegalite.js](https://vega.github.io/vega-lite/))
- markdown -> html (using [markdown-it.js](https://github.com/markdown-it/markdown-it) and [incremental-dom](https://github.com/google/incremental-dom))

See the code at [http://github.com/amitkaps/visdown](http://github.com/amitkaps/visdown)

---
Handcrafted by [Amit Kapoor](http://amitkaps.com)

0 comments on commit 31723e3

Please sign in to comment.