Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Delegate all data-related code to Data.js, which is now a dependency …

…of Unveil.js.
  • Loading branch information...
commit 1e24bf60df9f85bd291aaa91b1bfc0a7aeb06526 1 parent c3cdfac
Michael Aufreiter authored

Showing 36 changed files with 3,159 additions and 9,068 deletions. Show diff stats Hide diff stats

  1. +2 15 Cakefile
  2. +26 0 LICENSE
  3. +0 154 examples/artist_similarities/barchart_matrix.js
  4. +0 104 examples/artist_similarities/co_occurrences.js
  5. +0 124 examples/artist_similarities/co_occurrences_baccigalupo.js
  6. +0 108 examples/artist_similarities/index.html
  7. +0 66 examples/artist_similarities/table.js
  8. +0 92 examples/artist_similarities/visualization.js
  9. +149 0 examples/bars/index.html
  10. +2 0  examples/multiple_displays/index.html
  11. +0 117 examples/random_bars/index.html
  12. +274 0 fixtures/countries_old.js
  13. +78 7 index.ndg
  14. +1,628 0 lib/data.js
  15. +0 6,240 lib/jquery-1.4.2.js
  16. +0 155 lib/jquery-1.4.2.min.js
  17. +4 0 lib/jquery-1.6.4.js
  18. +931 0 lib/underscore.js
  19. +0 238 src/collection/README.textile
  20. +0 57 src/collection/collection.js
  21. +0 73 src/collection/criterion.js
  22. +0 55 src/collection/item.js
  23. +0 19 src/collection/modifiers.js
  24. +0 59 src/collection/property.js
  25. +0 54 src/collection/transformers/group.js
  26. +0 21 src/collection/value.js
  27. +0 60 src/data_graph/data_graph.js
  28. +0 69 src/data_graph/resource.js
  29. +0 40 src/data_graph/type.js
  30. +0 143 src/node/node.js
  31. +1 1  src/outro.js
  32. +7 7 src/scene/actor.js
  33. +2 2 src/scene/traverser.js
  34. +4 0 src/uv.js
  35. +14 932 unveil.js
  36. +37 56 unveil.min.js
17 Cakefile
@@ -19,19 +19,6 @@ compressionCmd = 'java -jar ./lib/compiler.jar --js unveil.js --js_output_file u
19 19 files = [
20 20 'src/intro.js'
21 21 'src/uv.js'
22   - 'src/sorted_hash/sorted_hash.js'
23   - 'src/sorted_hash/aggregators.js'
24   - 'src/sorted_hash/comparators.js'
25   - 'src/node/node.js'
26   - 'src/collection/value.js'
27   - 'src/collection/item.js'
28   - 'src/collection/property.js'
29   - 'src/collection/collection.js'
30   - 'src/collection/criterion.js'
31   - 'src/collection/transformers/group.js'
32   - 'src/data_graph/data_graph.js'
33   - 'src/data_graph/type.js'
34   - 'src/data_graph/resource.js'
35 22 'src/scene/matrix.js'
36 23 'src/scene/actor.js'
37 24 'src/scene/traverser.js'
@@ -51,12 +38,12 @@ files = [
51 38 # Run a CoffeeScript through the node/coffee interpreter.
52 39 run = (args) ->
53 40 proc = spawn 'bin/coffee', args
54   - proc.stderr.on 'data', (buffer) -> puts buffer.toString()
  41 + proc.stderr.on 'data', (buffer) -> console.log buffer.toString()
55 42 proc.on 'exit', (status) -> process.exit(1) if status != 0
56 43
57 44 # Log a message with a color.
58 45 log = (message, color, explanation) ->
59   - puts "#{color or ''}#{message}#{reset} #{explanation or ''}"
  46 + console.log "#{color or ''}#{message}#{reset} #{explanation or ''}"
60 47
61 48 # Build from source
62 49 build = ->
26 LICENSE
... ... @@ -0,0 +1,26 @@
  1 +//
  2 +// This is free and unencumbered software released into the public domain.
  3 +// It was originally initiated by Michael Aufreiter at Quasipartikel Labs.
  4 +//
  5 +// The software took inspiration from various great open source projects.
  6 +//
  7 +// Among them:
  8 +//
  9 +// - Protovis <http://protovis.org/>
  10 +// - Processing.js <http://processingjs.org/>
  11 +// - Underscore.js <http://documentcloud.github.com/underscore/>
  12 +// - CoffeeScript <http://coffeescript.org/>
  13 +//
  14 +// Anyone is free to copy, modify, publish, use, compile, sell, or
  15 +// distribute this software, either in source code form or as a compiled
  16 +// binary, for any purpose, commercial or non-commercial, and by any
  17 +// means.
  18 +//
  19 +//
  20 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  23 +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  24 +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  25 +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26 +// OTHER DEALINGS IN THE SOFTWARE.
154 examples/artist_similarities/barchart_matrix.js
... ... @@ -1,154 +0,0 @@
1   -function round_float(x,n){
2   - if(!parseInt(n))
3   - var n=0;
4   - if(!parseFloat(x))
5   - return false;
6   - return Math.round(x*Math.pow(10,n))/Math.pow(10,n);
7   -}
8   -
9   -// Table
10   -// =============================================================================
11   -
12   -uv.BarchartMatrix = uv.Visualization.extend({
13   - constructor: function(collection, options) {
14   - uv.Visualization.call(this, collection, options);
15   - this.property = options.params.property;
16   - this.nested_property = options.params.nested_property;
17   - },
18   - render: function() {
19   - var w = 200,
20   - h = 30,
21   - numberFormat = pv.Format.number(),
22   - dateFormat = pv.Format.date("%B %Y"),
23   - property = this.property,
24   - nested_property = this.nested_property;
25   -
26   - if (!this.collection.get('properties', property)) return;
27   - if (!this.collection.get('properties', property).type === 'collection') return;
28   -
29   - /* Color by maximum number of people employed in that job. */
30   - var c = pv.Scale.log(undefined, function(d) { return pv.max(d.values) })
31   - .range("#ccc", "#1f77b4");
32   -
33   - var chart = document.getElementById('canvas');
34   -
35   - // clear the canvas
36   - $(chart).html('');
37   -
38   - // prepare the data
39   - var data = [];
40   -
41   - var items = this.collection.all('items');
42   -
43   - // sort by name
44   - items.sort(function(item1, item2) {
45   - var value1 = item1.value.value('source'),
46   - value2 = item2.value.value('source');
47   - return value1 === value2 ? 0 : (value1 < value2 ? -1 : 1);
48   - });
49   -
50   - items.each(function(index, item) {
51   - var sub_items = item.first(property).all('items');
52   -
53   - var values = [];
54   - var value_names = [];
55   - var correct_matches = [];
56   - var correct_matches_count = 0;
57   - sub_items.each(function(index, i) {
58   - values.push(i.value(nested_property));
59   - value_names.push(i.identify());
60   -
61   - var correct = item.value('checker') === i.value('checker');
62   - if (correct) correct_matches_count++;
63   - correct_matches.push(correct);
64   - });
65   -
66   - var accuracy = correct_matches_count / values.length;
67   - data.push({name: item.identify(), values: values, value_names: value_names, correct_matches: correct_matches, accuracy: accuracy});
68   - });
69   -
70   - var items = this.collection.get('items');
71   - /* Tile the visualization for each job. */
72   - var vis = new pv.Panel()
73   - .data(data)
74   - .width(w)
75   - .height(h + 10)
76   - .top(6)
77   - .left(6)
78   - .right(6)
79   - .bottom(6)
80   - .canvas(function() { return chart.appendChild(document.createElement("span")); })
81   -
82   - /* A panel instance to store scales (x, y) and the mouseover index (i). */
83   - var panel = vis.add(pv.Panel)
84   - .def("i", -1)
85   - .def("x", function(d) { return pv.Scale.linear(d.values, pv.index).range(0, w); })
86   - .def("y", function(d) { return pv.Scale.linear(0, pv.max(d.values)).range(0, h); })
87   - .bottom(10)
88   - .events("all")
89   - .event("mousemove", pv.Behavior.point(Infinity).collapse("y"));
90   -
91   - // closure for the correct_matches
92   - var cached_data;
93   -
94   - /* The area. */
95   - panel.add(pv.Bar)
96   - .data(function(d) { cached_data = d; return d.values; })
97   - .fillStyle(function(d, p) { return cached_data.correct_matches[this.index] ? "#3c99b7" : "#90250c"; })
98   - .left(function() { return parseInt(panel.x()(this.index)); })
99   - .width(8)
100   - .height(function(d) { return panel.y()(d); })
101   - .bottom(0)
102   - .event("point", function() { return panel.i(this.index) })
103   - .event("unpoint", function() { return panel.i(-1) });
104   -
105   - /* The x-axis. */
106   - panel.add(pv.Rule)
107   - .bottom(0);
108   -
109   - /* The mouseover dot. */
110   - panel.add(pv.Dot)
111   - .visible(function() { return panel.i() >= 0; })
112   - .left(function() { return panel.x()(panel.i()); })
113   - .bottom(function(d) { return panel.y()(d.values[panel.i()]); })
114   - .fillStyle("#ff7f0e")
115   - .strokeStyle(null)
116   - .size(10);
117   -
118   - panel.add(pv.Label)
119   - .bottom(-1)
120   - .textBaseline("top")
121   - .left(function() { return panel.i() < 0 ? 0 : null })
122   - .right(function() { return panel.i() < 0 ? null : 0 })
123   - .textAlign(function() { return panel.i() < 0 ? "left" : "right"; })
124   - .textStyle(function() { return panel.i() < 0 ? "#999" : "#000"; })
125   - .text(function(d) { return panel.i() < 0 ? ""
126   - : d.value_names[panel.i()] + ": "+ round_float(d.values[panel.i()], 2); });
127   -
128   - panel.add(pv.Label)
129   - .bottom(-1)
130   - .textBaseline("top")
131   - .textStyle(function() { return panel.i() < 0 ? "#999" : "#000"; })
132   - .textAlign('left')
133   - .text(function(d) { return d.name; });
134   -
135   -
136   - vis.render();
137   -
138   - }
139   -});
140   -
141   -// Specification
142   -//-----------------------------------------------------------------------------
143   -
144   -uv.BarchartMatrix.spec = {
145   - measures: [
146   - {
147   - types: ['number', 'string', 'date'],
148   - unique: true,
149   - cardinality: 1,
150   - optional: true
151   - }
152   - ]
153   -};
154   -
104 examples/artist_similarities/co_occurrences.js
... ... @@ -1,104 +0,0 @@
1   -uv.Collection.transformers.coOccurrences = function(c, params) {
2   - if (!params.property || !params.knn) return c;
3   -
4   - var targetItems = {},
5   - property = c.get('properties', params.property),
6   - values = property.all('values');
7   -
8   - function coOccurrences(v1, v2) {
9   - var items1 = v1.all('items'),
10   - items2 = v2.all('items');
11   - return items1.intersect(items2).length;
12   - };
13   -
14   - function similarity(v1, v2) {
15   - return 0.5* (coOccurrences(v1, v2) / coOccurrences(v1, v1)
16   - + coOccurrences(v2, v1) / coOccurrences(v2, v2));
17   - };
18   -
19   - // get property values
20   - values.each(function(index, value) {
21   - targetItems[value.val] = {
22   - source: value.val,
23   - "similar_items": {}
24   - };
25   -
26   - var similarItems = [];
27   -
28   - values.each(function (index, otherValue) {
29   - var sim = similarity(value, otherValue);
30   - if (sim>0 && value.val !== otherValue.val) {
31   - similarItems.push({
32   - "name": otherValue.val,
33   - "number_of_cooccurrences": coOccurrences(value, otherValue),
34   - "score": sim
35   - });
36   - }
37   - });
38   -
39   - // sort by score
40   - similarItems.sort(function(item1, item2) {
41   - var value1 = item1.score,
42   - value2 = item2.score;
43   - return value1 === value2 ? 0 : (value1 > value2 ? -1 : 1);
44   - });
45   -
46   - similarItems = similarItems.slice(0, params.knn);
47   -
48   - var similarItemsHash = {};
49   - $.each(similarItems, function(index, item) {
50   - similarItemsHash[item.name] = item;
51   - });
52   -
53   - targetItems[value.val].source = value.val;
54   - targetItems[value.val].similar_items = similarItemsHash;
55   - });
56   -
57   - // construct a new collection that models coocurrences
58   - var cspec = {
59   - properties: {
60   - source: {
61   - name: "Source",
62   - type: "string",
63   - unique: true
64   - },
65   - similar_items: {
66   - name: "Similar Items",
67   - type: "collection",
68   - unique: true,
69   - properties: {
70   - "name": {
71   - name: 'Name',
72   - type: 'string',
73   - unique: true
74   - },
75   - "number_of_cooccurrences": {
76   - name: 'Number of Co-occurrences',
77   - type: 'number',
78   - unique: true
79   - },
80   - "score": {
81   - name: 'Similarity Score',
82   - type: 'number',
83   - unique: true
84   - }
85   - }
86   - }
87   - },
88   - items: targetItems
89   - };
90   - return new uv.Collection(cspec);
91   -};
92   -
93   -// Transformer specification
94   -uv.Collection.transformers.coOccurrences.label = "Similarity (COOC)";
95   -uv.Collection.transformers.coOccurrences.params = {
96   - property: {
97   - name: "Property",
98   - type: "property"
99   - },
100   - knn: {
101   - name: "K-nearest Neighbor",
102   - type: "number"
103   - }
104   -};
124 examples/artist_similarities/co_occurrences_baccigalupo.js
... ... @@ -1,124 +0,0 @@
1   -uv.Collection.transformers.coOccurrencesBaccigalupo = function(c, params) {
2   -
3   - // check for valid params
4   - if (!params.property || !params.knn) return c;
5   -
6   - var targetItems = {},
7   - property = c.get('properties', params.property),
8   - values = property.all('values');
9   -
10   - function checkDistance(playlist, v1, v2, d) {
11   - for (var i = 0; i<playlist.values(params.property).length-d; i++) {
12   -
13   - if (playlist.values(params.property).at(i)===v1.val && playlist.values(params.property).at(i+d+1)===v2.val) {
14   - return true;
15   - }
16   - }
17   - return false;
18   - };
19   -
20   - function coOccurencesAtDistance(v1, v2, d) {
21   - var items1 = v1.all('items'),
22   - items2 = v2.all('items'),
23   - playlists = items1.intersect(items2);
24   -
25   - return playlists.select(function(key, p) {
26   - return checkDistance(p, v1, v2, d);
27   - }).length;
28   - };
29   -
30   - function similarity(v1, v2) {
31   - return 1*coOccurencesAtDistance(v1, v2, 0) +
32   - 0.8* coOccurencesAtDistance(v1, v2, 1) +
33   - 0.64* coOccurencesAtDistance(v1, v2, 2);
34   - };
35   -
36   - // get property values
37   - values.each(function(index, value) {
38   - targetItems[value.val] = {
39   - source: value.val,
40   - "similar_items": {}
41   - };
42   -
43   - var similarItems = [];
44   -
45   - values.each(function (index, otherValue) {
46   - var sim = similarity(value, otherValue);
47   -
48   - if (sim>0 && value.val !== otherValue.val) {
49   - similarItems.push({
50   - "name": otherValue.val,
51   - "number_of_cooccurrences": 0,
52   - "score": sim
53   - });
54   - }
55   - });
56   -
57   - // sort by score
58   - similarItems.sort(function(item1, item2) {
59   - var value1 = item1.score,
60   - value2 = item2.score;
61   - return value1 === value2 ? 0 : (value1 > value2 ? -1 : 1);
62   - });
63   -
64   - similarItems = similarItems.slice(0, params.knn);
65   -
66   - var similarItemsHash = {};
67   - $.each(similarItems, function(index, item) {
68   - similarItemsHash[item.name] = item;
69   - });
70   -
71   - targetItems[value.val].source = value.val;
72   - targetItems[value.val].similar_items = similarItemsHash;
73   -
74   - });
75   -
76   - // construct a new collection that models coocurrences
77   - var cspec = {
78   - properties: {
79   - source: {
80   - name: "Source",
81   - type: "string",
82   - unique: true
83   - },
84   - similar_items: {
85   - name: "Similar Items",
86   - type: "collection",
87   - unique: true,
88   - properties: {
89   - "name": {
90   - name: 'Name',
91   - type: 'string',
92   - unique: true
93   - },
94   - "number_of_cooccurrences": {
95   - name: 'Number of Co-occurrences',
96   - type: 'number',
97   - unique: true
98   - },
99   - "score": {
100   - name: 'Similarity Score',
101   - type: 'number',
102   - unique: true
103   - }
104   - }
105   - }
106   - },
107   - items: targetItems
108   - };
109   -
110   - return new uv.Collection(cspec);
111   -};
112   -
113   -// Transformer specification
114   -uv.Collection.transformers.coOccurrencesBaccigalupo.label = "Co-Occurrences Baccigalupo";
115   -uv.Collection.transformers.coOccurrencesBaccigalupo.params = {
116   - property: {
117   - name: "Property",
118   - type: "property"
119   - },
120   - knn: {
121   - name: "K-nearest Neighbor",
122   - type: "number"
123   - }
124   -};
108 examples/artist_similarities/index.html
... ... @@ -1,108 +0,0 @@
1   -<!DOCTYPE html>
2   -<html>
3   -<head>
4   - <title>Unveil.js</title>
5   -
6   - <!-- libraries -->
7   - <script src="../../lib/jquery-1.4.2.js"></script>
8   - <script src="../../lib/protovis-d3.2.js"></script>
9   - <script src="../../lib/underscore.js"></script>
10   -
11   - <script src="../../unveil.js"></script>
12   -
13   - <!-- collection transformers -->
14   - <script src="./co_occurrences.js"></script>
15   - <script src="./co_occurrences_baccigalupo.js"></script>
16   -
17   - <!-- visualization API -->
18   - <script src="./visualization.js"></script>
19   -
20   - <!-- visualizations -->
21   - <script src="./barchart_matrix.js"></script>
22   - <script src="./table.js"></script>
23   -
24   - <!-- fixtures -->
25   - <script src="../../fixtures/playlists.js"></script>
26   -
27   - <script>
28   - $(function() {
29   - // load some data (represented as a Collection)
30   - var c = new uv.Collection(playlists_fixture);
31   -
32   - // construct a visualization based on that data
33   - vis = new uv.Table(c, {
34   - canvas: $('#canvas'),
35   - measures: [],
36   - params: {}
37   - });
38   -
39   - vis.render();
40   -
41   - $('#calculate').click(function() {
42   - $('#hint').show();
43   -
44   - setTimeout(function() {
45   - var artist_similarities = c.transform($('#transformer').val(), {property: 'artists', knn: $('#knn').val()});
46   -
47   - vis = new uv.BarchartMatrix(artist_similarities, {
48   - canvas: $('#canvas'),
49   - measures: [],
50   - params: {property: 'similar_items', nested_property: 'score'}
51   - });
52   - $('#hint').hide();
53   - vis.render();
54   - }, 100);
55   - });
56   -
57   - });
58   - </script>
59   -
60   - <link href="../styles.css" media="screen" rel="stylesheet" type="text/css" />
61   -</head>
62   -<body>
63   - <h1>Unveil.js - Similarity measurement based on Co-occurrences in playlists</h1>
64   - <div id="canvas">
65   -
66   - </div>
67   - <div id="info">
68   - <h3>Method</h3>
69   - <select id="transformer">
70   - <option value="coOccurrences" selected="selected">COOC</option>
71   - <option value="coOccurrencesBaccigalupo">BACCIGALUPO</option>
72   - </select>
73   - <h3>knn (k nearest neighbors)</h3>
74   - <input id="knn" type="text" name="knn" value="15"/><br/><br/>
75   - <input type="button" id="calculate" value="CALCULATE"/>
76   - <p id="hint" style="display: none;">Hardcore processing... This may take a while...</p>
77   - <h3>About</h3>
78   - <!-- A framework for data-driven visualizations based on Collections. -->
79   - <p>
80   - This example demonstrates a data-driven approach on calculating music artist similarities based on co-occurrences in playlists
81   - using the Unveil.js visualization framework. Similarity measurement algorithms have
82   - been implemented as Unveil.js <a href="http://github.com/michael/unveil/tree/master/src/collection/transformers/">Collection Transformers</a>.
83   - </p><p>
84   - Please also have a look at the corresponding <a href="http://quasipartikel.at/">blog post</a>.
85   - </p>
86   -
87   - <h3>Data used</h3>
88   -
89   - <p><a href="../fixtures/playlists.js">Playlists</a> pulled from Last.fm, translated into the Unveil.js Collection format.</p>
90   -
91   - <h3>Code</h3>
92   -
93   - <p>Source Code is available at <a href="http://github.com/michael/unveil">Github</a></p>
94   -
95   - <div class="notice">A <a href="http://quasipartikel.at/">Quasipartikel</a> production</div>
96   - </div>
97   -
98   - <script type="text/javascript">
99   - var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
100   - document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
101   - </script>
102   - <script type="text/javascript">
103   - try {
104   - var pageTracker = _gat._getTracker("UA-10368067-1");
105   - pageTracker._trackPageview();
106   - } catch(err) {}</script>
107   -</body>
108   -</html>
66 examples/artist_similarities/table.js
... ... @@ -1,66 +0,0 @@
1   -// Table
2   -// =============================================================================
3   -
4   -uv.Table = uv.Visualization.extend({
5   - constructor: function(collection, options) {
6   - uv.Visualization.call(this, collection, options);
7   - this.build();
8   - },
9   - build: function() {
10   -
11   - },
12   - render: function() {
13   - this.$canvas.html(this.renderCollection(this.collection));
14   - },
15   - renderItem: function(c, i) {
16   - var that = this;
17   - str = '<tr>';
18   -
19   - c.all("properties").eachKey(function(key, attr) {
20   - if (i.type(key) === 'collection') {
21   - str += '<td>'+that.renderCollection(i.first(key))+'</td>';
22   - } else {
23   - str += '<td>'
24   - i.values(key).each(function(index, v) {
25   - str += v+'<br/>';
26   - });
27   - str += '</td>'
28   - }
29   - });
30   -
31   - str += '</tr>';
32   - return str;
33   - },
34   - renderCollection: function(c) {
35   - var that = this;
36   -
37   - str = '<table><thead><tr>';
38   - c.all("properties").each(function(index, p) {
39   - str += '<th>'+p.name+'</th>';
40   - });
41   -
42   - str += '</tr></thead><tbody>';
43   -
44   - c.all("items").each(function(index, item) {
45   - str += that.renderItem(c, item);
46   - });
47   -
48   - str += '</tbody></table>';
49   - return str;
50   - }
51   -});
52   -
53   -// Specification
54   -//-----------------------------------------------------------------------------
55   -
56   -// Displays 1..n numbers
57   -uv.Table.spec = {
58   - measures: [
59   - {
60   - types: ['number', 'string', 'date'],
61   - unique: true,
62   - cardinality: 1,
63   - optional: true
64   - }
65   - ]
66   -};
92 examples/artist_similarities/visualization.js
... ... @@ -1,92 +0,0 @@
1   -function Class(proto) {
2   - var self = this,
3   - isSubclass = typeof this === 'function',
4   - Class = proto.hasOwnProperty('constructor')
5   - ? proto.constructor
6   - : isSubclass
7   - ? (proto.constructor = function(){ self.apply(this, arguments) })
8   - : (proto.constructor = function(){})
9   - if (proto.hasOwnProperty('extend'))
10   - extend(Class, proto.extend)
11   - Class.prototype = proto
12   - Class.extend = arguments.callee
13   - if (isSubclass) {
14   - Class.prototype.__proto__ = this.prototype
15   - if ('extended' in this)
16   - this.extended(Class)
17   - }
18   - return Class
19   -}
20   -
21   -Class.prototype = Function.prototype
22   -
23   -Class.prototype.include = function(proto){
24   - extend(this.prototype, proto)
25   - if ('included' in proto) proto.included(this)
26   - return this
27   -}
28   -
29   -function extend(a, b) {
30   - for (var key in b)
31   - if (b.hasOwnProperty(key))
32   - a[key] = b[key]
33   -}
34   -
35   -
36   -// Abstract Visualization
37   -// ----------------------------------------------------------------------------
38   -//
39   -// Functionality is shared with all implemented visualizations
40   -
41   -uv.Visualization = new Class({
42   - constructor: function (collection, options) {
43   - this.collection = collection;
44   - this.measures = options.measures;
45   - this.params = options.params;
46   - this.$canvas = options.canvas || $('#canvas');
47   -
48   - // default margin
49   - this.margin = {top: 20, right: 20, bottom: 20, left: 20};
50   - },
51   - // Checks if the constructed instance conforms to the visualization spec
52   - isValid: function() {
53   - var that = this,
54   - idx = 0, // measure index
55   - valid = true;
56   -
57   - // checks for a given measure if it conforms to a given spec
58   - function isComplient(idx, mspec) {
59   - var p = that.property(idx);
60   -
61   - // handle optional measures
62   - if (mspec.optional && !p)
63   - return true;
64   -
65   - return (p && mspec.types.indexOf(p.type) >= 0 && (p.unique === mspec.unique || mspec.unique === undefined));
66   - }
67   -
68   - $.each(this.constructor.spec.measures, function(index, mspec) {
69   - var count;
70   - if (mspec.cardinality === "*") {
71   - count = that.measures.length-idx; // remaining unchecked measures
72   - } else {
73   - count = mspec.cardinality;
74   - }
75   - for (var i=0; i<count; i++) {
76   - if (!isComplient(idx, mspec)) {
77   - valid = false;
78   - }
79   - idx += 1;
80   - }
81   - });
82   -
83   - return idx >= this.measures.length ? valid : false;
84   - },
85   - // returns a property object at given index i
86   - property: function(i) {
87   - return this.collection.get('properties', this.measures[i]);
88   - },
89   - render: function() {
90   - this.$canvas.html('render() is not implemented.');
91   - }
92   -});
149 examples/bars/index.html
... ... @@ -0,0 +1,149 @@
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <title>Unveil.js - Bars</title>
  5 +
  6 + <!-- libraries -->
  7 + <script src="../../lib/protovis-d3.2.js"></script>
  8 + <script src="../../lib/jquery-1.6.4.js"></script>
  9 + <script src="../../lib/underscore.js"></script>
  10 + <script src="../../lib/data.js"></script>
  11 + <script src="../../unveil.js"></script>
  12 +
  13 + <script>
  14 + window.onload = function() {
  15 + var countries_data = {
  16 + "properties": {
  17 + "name": {"name": "Country Name",
  18 + "type": "string", "unique": true },
  19 + "official_language": {"name": "Official Language",
  20 + "type": "string", "unique": true },
  21 + "population": { "name": "Population",
  22 + "type": "number", "unique": true },
  23 + "gdp": { "name": "GDP per capita",
  24 + "type": "number", "unique": true }
  25 + },
  26 + "items": {
  27 + "at": {
  28 + "name": "Austria",
  29 + "official_language": "German",
  30 + "population": 8356700,
  31 + "gdp": 39.761
  32 + },
  33 + "de": {
  34 + "name": "Germany",
  35 + "official_language": "German",
  36 + "population": 82062200,
  37 + "gdp": 46.860
  38 + },
  39 + "usa": {
  40 + "name": "United States of America",
  41 + "official_language": "English",
  42 + "population": 310955497,
  43 + "gdp": 36.081
  44 + }
  45 + }
  46 + };
  47 +
  48 + var countries = new Data.Collection(countries_data);
  49 + var property = "population";
  50 +
  51 + // Create scene
  52 + var scene = new uv.Scene({
  53 + displays: [{
  54 + container: 'canvas',
  55 + width: 300,
  56 + height: 300
  57 + }]
  58 + });
  59 +
  60 + // Scale values to fit on bars
  61 + function y(val) {
  62 + var dMax = countries.properties().get(property).aggregate(Data.Aggregators.MAX);
  63 + oMax = 200;
  64 + return parseInt(val/dMax * oMax);
  65 + }
  66 +
  67 + // Initialize
  68 + countries.items().each(function(c, key, index) {
  69 + scene.add({
  70 + id: "country_"+key,
  71 + type: 'rect',
  72 + x: 50+35*index,
  73 + y: 280,
  74 + width: 30,
  75 + height: -parseInt(y(c.get(property)), 10),
  76 + fillStyle: function() {
  77 + return this.active ? 'orange' : 'blue';
  78 + },
  79 + interactive: true,
  80 + actors: [
  81 + {
  82 + type: 'label',
  83 + x: 15,
  84 + y: 20,
  85 + width: 30,
  86 + height: 20,
  87 + text: function() { return c._id.toUpperCase() },
  88 + textAlign: 'center',
  89 + fillStyle: '#444'
  90 + }
  91 + ]
  92 + });
  93 + });
  94 +
  95 + // Update
  96 + function update() {
  97 + property = $('#property').val();
  98 +
  99 + countries.items().each(function(c, key, index) {
  100 + scene.get("country_"+key).animate({height: -parseInt(y(c.get(property)), 10)}, 1.0);
  101 + });
  102 + }
  103 +
  104 + $('#property').change(update);
  105 +
  106 + scene.start();
  107 + };
  108 + </script>
  109 +
  110 + <link href="../styles.css" media="screen" rel="stylesheet" type="text/css" />
  111 +</head>
  112 +<body>
  113 + <h1>Unveil.js - Bars</h1>
  114 + <div id="canvas">
  115 +
  116 + </div>
  117 + <div id="info">
  118 + <h3>Choose property</h3>
  119 + <select id="property">
  120 + <option value="population">Population</option>
  121 + <option value="gdp">GDP per capita</option>
  122 + </select>
  123 +
  124 + <h3>About</h3>
  125 + <!-- A framework for data-driven visualizations based on Collections. -->
  126 + <p><strong>Unveil.js</strong> provides a simple abstraction layer for visualizations to ease
  127 + the process of creating re-usable charts. To accomplish this, a data-driven methodology is used.
  128 + </p><p>
  129 +
  130 +
  131 +
  132 + <h3>Code</h3>
  133 +
  134 + <p>Source Code is available at <a href="http://github.com/michael/unveil">Github</a></p>
  135 +
  136 + <div class="notice">A <a href="http://quasipartikel.at">Quasipartikel</a> production</div>
  137 + </div>
  138 +
  139 + <script type="text/javascript">
  140 + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
  141 + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
  142 + </script>
  143 + <script type="text/javascript">
  144 + try {
  145 + var pageTracker = _gat._getTracker("UA-10368067-1");
  146 + pageTracker._trackPageview();
  147 + } catch(err) {}</script>
  148 +</body>
  149 +</html>
2  examples/multiple_displays/index.html
@@ -4,6 +4,8 @@
4 4 <title>Unveil.js - Multiple displays</title>
5 5
6 6 <!-- libraries -->
  7 + <script src="../../lib/underscore.js"></script>
  8 + <script src="../../lib/data.js"></script>
7 9 <script src="../../unveil.js"></script>
8 10
9 11 <script>
117 examples/random_bars/index.html
... ... @@ -1,117 +0,0 @@
1   -<!DOCTYPE html>
2   -<html>
3   -<head>
4   - <title>Unveil.js - Random Bars</title>
5   -
6   - <!-- libraries -->
7   - <script src="../../lib/protovis-d3.2.js"></script>
8   - <script src="../../lib/underscore.js"></script>
9   - <script src="../../unveil.js"></script>
10   -
11   - <script>
12   - window.onload = function() {
13   - // Create scene
14   - var scene = new uv.Scene({
15   - displays: [{
16   - container: 'canvas',
17   - width: 800,
18   - height: 300,
19   - zooming: true,
20   - panning: true
21   - }],
22   - actors: [
23   - {
24   - type: 'label',
25   - x: 400,
26   - y: 40,
27   - text: function() { return "FPS: "+parseInt(this.scene.fps, 10); },
28   - },
29   - {
30   - type: 'label',
31   - x: 400,
32   - y: 60,
33   - text: function() { return "Worldpos: ("+this.scene.mouseX+", "+this.scene.mouseY+")"; }
34   - },
35   - {
36   - type: 'label',
37   - x: 400,
38   - y: 100,
39   - text: function() { return "Framerate Requests: "+ this.scene.commands.RequestFramerate.requests; }
40   - }
41   - ]
42   - }),
43   - data = pv.range(20).map(function(d) { return Math.random() + .1; }),
44   - colors = pv.Scale.linear(data).range('lightblue', 'darkblue');
45   -
46   - // Add some actors to the scene
47   - uv.each(data, function(datum, index) {
48   - scene.add({
49   - type: 'rect',
50   - x: 50+35*index,
51   - y: 280,
52   - width: 30,
53   - height: -30+parseInt(-100*datum, 10),
54   - fillStyle: function() {
55   - return this.active ? 'orange' : colors(datum).color;
56   - },
57   - interactive: true,
58   - actors: [
59   - {
60   - type: 'label',
61   - x: 15,
62   - y: -10,
63   - width: 30,
64   - height: 20,
65   - text: function() { return parseInt(this.parent.p('height')*-1) },
66   - textAlign: 'center',
67   - fillStyle: 'white'
68   - }
69   - ]
70   - });
71   - });
72   -
73   - scene.start();
74   -
75   - // move it
76   - setInterval(function() {
77   - var data = pv.range(20).map(function(d) { return Math.random() + .1; });
78   - scene.all('children').each(function(index, child) {
79   - child.animate({height: -30+parseInt(-100*data[index], 10)}, 1.5);
80   - });
81   - }, 1000);
82   -
83   - };
84   - </script>
85   -
86   - <link href="../styles.css" media="screen" rel="stylesheet" type="text/css" />
87   -</head>
88   -<body>
89   - <h1>Unveil.js - Random Bars</h1>
90   - <div id="canvas">
91   -
92   - </div>
93   - <div id="info">
94   - <h3>About</h3>
95   - <!-- A framework for data-driven visualizations based on Collections. -->
96   - <p><strong>Unveil.js</strong> provides a simple abstraction layer for visualizations to ease
97   - the process of creating re-usable charts. To accomplish this, a data-driven methodology is used.
98   - </p><p>
99   -
100   - <h3>Code</h3>
101   -
102   - <p>Source Code is available at <a href="http://github.com/michael/unveil">Github</a></p>
103   -
104   - <div class="notice">A <a href="http://quasipartikel.at">Quasipartikel</a> production</div>
105   - </div>
106   -
107   - <script type="text/javascript">
108   - var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
109   - document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
110   - </script>
111   - <script type="text/javascript">
112   - try {
113   - var pageTracker = _gat._getTracker("UA-10368067-1");
114   - pageTracker._trackPageview();
115   - } catch(err) {}</script>
116   -</body>
117   -</html>
274 fixtures/countries_old.js
... ... @@ -0,0 +1,274 @@
  1 +var countries_fixture = {
  2 + "properties": {
  3 + "name": {
  4 + "type": "string",
  5 + "property_key": "name",
  6 + "unique": true,
  7 + "value_key": "name",
  8 + "name": "Country Name"
  9 + },
  10 + "currency_used": {
  11 + "type": "string",
  12 + "property_key": "currency_used",
  13 + "unique": true,
  14 + "value_key": "name",
  15 + "name": "Currency used"
  16 + },
  17 + "form_of_government": {
  18 + "type": "string",
  19 + "property_key": "form_of_government",
  20 + "unique": false,
  21 + "value_key": "name",
  22 + "name": "Form of governmennt"
  23 + },
  24 + "life_expectancy_male": {
  25 + "type": "number",
  26 + "unique": true,
  27 + "name": "Life expectancy at birth (male)"
  28 + },
  29 + "population_0014": {
  30 + "type": "number",
  31 + "unique": true,
  32 + "name": "Population ages 0-14 (% of total)"
  33 + },
  34 + "life_expectancy_female": {
  35 + "type": "number",
  36 + "unique": true,
  37 + "name": "Life expectancy at birth (female)"
  38 + },
  39 + "official_language": {
  40 + "type": "string",
  41 + "property_key": "official_language",
  42 + "unique": false,
  43 + "value_key": "name",
  44 + "name": "Official language"
  45 + },
  46 + "population": {
  47 + "type": "number",
  48 + "property_key": "/location/statistical_region/population",
  49 + "unique": true,
  50 + "value_key": "number",
  51 + "name": "Population"
  52 + },
  53 + "population_65up": {
  54 + "type": "number",
  55 + "unique": true,
  56 + "name": "Population ages 65 and above (% of total)"
  57 + },
  58 + "area": {
  59 + "type": "number",
  60 + "property_key": "/location/location/area",
  61 + "unique": true,
  62 + "name": "Area"
  63 + },
  64 + "gdp_nominal": {
  65 + "type": "number",
  66 + "property_key": "/location/statistical_region/gdp_nominal",
  67 + "unique": true,
  68 + "value_key": "amount",
  69 + "name": "GDP nominal"
  70 + },
  71 + "date_founded": {
  72 + "type": "date",
  73 + "property_key": "/location/dated_location/date_founded",
  74 + "name": "Date founded",
  75 + "unqiue": true
  76 + },
  77 + "population_1564": {
  78 + "type": "number",
  79 + "unique": true,
  80 + "name": "Population ages 15-65 (% of total)"
  81 + }
  82 + },
  83 + "items": {
  84 + "/en/angola": {
  85 + "name": "Angola",
  86 + "currency_used": "Angolan kwanza",
  87 + "form_of_government": [
  88 + "Republic",
  89 + "Presidential system"
  90 + ],
  91 + "life_expectancy_male": 45.087,
  92 + "population_0014": 45.2844221,
  93 + "life_expectancy_female": 49.086,
  94 + "official_language": [
  95 + "Portuguese Language"
  96 + ],
  97 + "population": 18498000,
  98 + "population_65up": 2.46411,
  99 + "area": 1246700.0,
  100 + "gdp_nominal": 95950000000.0,
  101 + "date_founded": "1975-11-11",
  102 + "population_1564": 52.251468
  103 + },
  104 + "/en/algeria": {
  105 + "name": "Algeria",
  106 + "currency_used": "Algerian dinar",
  107 + "form_of_government": [
  108 + "Presidential system",
  109 + "Semi-presidential system"
  110 + ],
  111 + "life_expectancy_male": 70.991,
  112 + "population_0014": 27.7493177,
  113 + "life_expectancy_female": 73.857,
  114 + "official_language": [
  115 + "Arabic language",
  116 + "Algerian Arabic",
  117 + "French Language"
  118 + ],
  119 + "population": 34895000,
  120 + "population_65up": 4.6111256,
  121 + "area": 2381741.0,
  122 + "gdp_nominal": 171300000000.0,
  123 + "date_founded": "1962",
  124 + "population_1564": 67.6395567
  125 + },
  126 + "/en/afghanistan": {
  127 + "name": "Afghanistan",
  128 + "currency_used": "Afghan afghani",
  129 + "form_of_government": [