Skip to content

Commit

Permalink
added url and table attributes to q behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
stevewirts committed Jan 26, 2015
1 parent 2e6bc45 commit 0e348f9
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 138 deletions.
57 changes: 31 additions & 26 deletions behaviors/fin-hypergrid-behavior-q.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<script>

'use strict';
//QGridBehavior is a datasource based on an external Q data source.
//fin-hypergrid-behavior-q is a datasource based on an external Q data source.
//<br>See [kx.com](http://www.kx.com)
//<br>Two example scripts are provided in the root of this project, bigtable.q and sorttable.q
//<br>bigtable.q simulates an unsortable 100MM row table, and sorttable.q provides a true randomly generated 1MM row table sortable on any column.
Expand Down Expand Up @@ -62,39 +62,31 @@
this.ws = null;
this.reconnect();
},

attributeChanged: function(attrName, oldVal, newVal) {
console.log(attrName, 'old: ' + oldVal, 'new:', newVal);
if (attrName === 'url') {
this.reconnect();
}
if (attrName === 'table') {
//force a refresh of the data
this.setScrollPositionY(0);
}
},
connectTo: function(newUrl) {
this.setAttribute('url', newUrl);
this.reconnect();
},

reconnect: function() {
this.url = this.getAttribute('url') || 'ws://localhost:5000/';
this.url = this.getAttribute('url');
if (!this.url) {
return;
}
this.connect();
this.scrollPositionY = 0;
this.scrolled = false;
},

//this is a good example of overriding the default cellprovider
//<br>in this case config.x is how we specify a column through its index
createCellProvider: function() {
var provider = document.createElement('fin-hypergrid-cell-provider');
var self = this;
provider.getCell = function(config) {
var x = config.x;
var renderer = provider.cellCache[typeRendererMap[self.block.headers[x + 1][1]]];
renderer = renderer || provider.cellCache.simpleCellRenderer;
if (x === 11) {
renderer = provider.cellCache.sliderCellRenderer;
} else if (x === 13) {
renderer = provider.cellCache.sparkbarCellRenderer;
}
renderer.config = config;
return renderer;
};
return provider;
},

//for now we use the hacky override implementation to save data, in the future we'll have a more elaborate protocol with Q to do real validation and setting of data.
//<br>take note of the usage of the scrollPositionY value in translating our in-memory data page
getValue: function(x, y) {
Expand Down Expand Up @@ -137,9 +129,15 @@
if (!this.isConnected()) {
return;
}
var tableName = this.getAttribute('table');
if (!tableName) {
console.log('you must provide a table attribute for the q behavior');
return;
}
this.ws.send(JSON.stringify({
cmd: 'fetch',
cmd: 'fetchTableData',
data: {
table: tableName,
start: this.scrollPositionY,
num: 60
}
Expand Down Expand Up @@ -192,8 +190,9 @@
this.sorted[columnIndex] = (current + 1) % stateCount;
var state = this.sortStates[this.sorted[columnIndex]];
var message = {
cmd: 'sort',
cmd: 'sortTable',
data: {
table: 'trade',
sort: current === (stateCount - 1) ? '' : this.block.headers[columnIndex][0],
asc: state.indexOf('^') > 0,
abs: state.indexOf('|') > 0,
Expand Down Expand Up @@ -222,6 +221,11 @@
var d;
var oldSize;
var self = this;
var tableName = this.getAttribute('table');
if (!tableName) {
console.log('you must provide a table attribute for the q behavior');
return;
}
if ('WebSocket' in window) {
try {
this.ws = new WebSocket(this.url);
Expand All @@ -233,8 +237,9 @@
this.ws.onopen = function() {
console.log('connected');
self.ws.send(JSON.stringify({
cmd: 'fetch',
cmd: 'fetchTableData',
data: {
table: tableName,
start: this.scrollPositionY || 0,
num: 60
}
Expand Down
59 changes: 54 additions & 5 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
.centered {
margin-left: auto;
margin-right: auto;
width: 25%;
width: 50%;
white-space: nowrap;
}
.description {
Expand Down Expand Up @@ -128,14 +128,17 @@ <h3>To setup q for this demo</h3>
<li>start sorttable.q at the command line<pre>~/myqdir>q sortable.q</pre></li>
<li>refresh your browser and reselect this tab</li>
</ol>
<h3>To point this example to your data</h3>
load <a href="http://q/hypergrid-support.q">hypergrid-support.q</a> into your running q process and modify the url, table name, then press reconnect.
</div>
<br>
<div width="100%">
<div class="centered">url:<input id="qurl" style="width:200px" value="ws://localhost:5000"></input><button id="connectq" onClick="connectQ()">reconnect</button></div>
<div class="centered">url:<input id="qurl" style="width:150px" value="ws://localhost:5000"></input>&nbsp;&nbsp;table:<input id="qtable" style="width:80px" value="trade"></input><button id="connectq" onClick="connectQ()">reconnect</button></div>
</div>
<core-splitter direction="up"></core-splitter>
<div flex class="rel">
<fin-hypergrid class="abs">
<fin-hypergrid-behavior-q url="ws://localhost:5000"></fin-hypergrid-behavior-q>
<fin-hypergrid class="abs" id="q-example">
<fin-hypergrid-behavior-q url="ws://localhost:5000" table="trade"></fin-hypergrid-behavior-q>
</fin-hypergrid>
</div>
</div>
Expand Down Expand Up @@ -171,6 +174,46 @@ <h3>fin-hypergrid-behavior-gol</h3> This element is another custom Polymer web c
});
})();

//override the cell provider for the q example
(function() {
document.addEventListener('polymer-ready', function() {

//get ahold of our q grid example
var qGrid = document.querySelector('#q-example');

//get it's table model
var qModel = qGrid.getBehavior();

//get the cell cellProvider for altering cell renderers
var cellProvider = qModel.getCellProvider();

//there are 4 default cell renderer types to choose from at the moment
//<br>simpleCellRenderer, sliderCellRenderer, sparkbarCellRenderer, sparklineCellRenderer
var typeRendererMap = {
J: 'sparklineCellRenderer',
j: 'simpleCellRenderer',
s: 'simpleCellRenderer',
t: 'simpleCellRenderer',
f: 'simpleCellRenderer',
d: 'simpleCellRenderer'
};

cellProvider.getCell = function(config) {
var x = config.x;
var renderer = cellProvider.cellCache[typeRendererMap[qModel.block.headers[x + 1][1]]];
renderer = renderer || cellProvider.cellCache.simpleCellRenderer;
if (x === 11) {
renderer = cellProvider.cellCache.sliderCellRenderer;
} else if (x === 13) {
renderer = cellProvider.cellCache.sparkbarCellRenderer;
}
renderer.config = config;
return renderer;
};
});

})();

//setup random data for the JSON tab example
(function(){
var seed = 1;
Expand Down Expand Up @@ -337,7 +380,13 @@ <h3>fin-hypergrid-behavior-gol</h3> This element is another custom Polymer web c
function connectQ() {
var q = document.querySelector('fin-hypergrid-behavior-q');
var url = document.querySelector('#qurl').value;
q.connectTo(url);
var table = document.querySelector('#qtable').value;
//set it blank first to tickle the change event if its
//the same value
q.setAttribute('table', table);

q.setAttribute('url', '');
q.setAttribute('url', url);
}
function toggleRunning() {
var button = document.querySelector('#play-button');
Expand Down
6 changes: 6 additions & 0 deletions features/fin-hypergrid-feature-column-moving.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@

initializeAnimationSupport: function(grid) {
this.dragger = document.createElement('canvas');
this.dragger.setAttribute('width', '0px');
this.dragger.setAttribute('height', '0px');

document.body.appendChild(this.dragger);
this.draggerCTX = this.dragger.getContext('2d');

this.floatColumn = document.createElement('canvas');
this.floatColumn.setAttribute('width', '0px');
this.floatColumn.setAttribute('height', '0px');

document.body.appendChild(this.floatColumn);
this.floatColumnCTX = this.floatColumn.getContext('2d');

Expand Down
2 changes: 1 addition & 1 deletion fin-hypergrid.html
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@
var lastPageColumnCount = 0;
var columnsWidth = 0;
for (; lastPageColumnCount < numColumns; lastPageColumnCount++) {
var eachWidth = behavior.getRowHeight(numColumns - lastPageColumnCount - 1);
var eachWidth = behavior.getColumnWidth(numColumns - lastPageColumnCount - 1);
columnsWidth = columnsWidth + eachWidth;
if (columnsWidth > scrollableWidth) {
break;
Expand Down
2 changes: 1 addition & 1 deletion fin-hypergrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@
var lastPageColumnCount = 0;
var columnsWidth = 0;
for (; lastPageColumnCount < numColumns; lastPageColumnCount++) {
var eachWidth = behavior.getRowHeight(numColumns - lastPageColumnCount - 1);
var eachWidth = behavior.getColumnWidth(numColumns - lastPageColumnCount - 1);
columnsWidth = columnsWidth + eachWidth;
if (columnsWidth > scrollableWidth) {
break;
Expand Down
2 changes: 1 addition & 1 deletion fin-hypergrid.min.html

Large diffs are not rendered by default.

26 changes: 6 additions & 20 deletions bigtable.q → q/bigtable.q
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@
// a 255 row table, sorting is not supported in this example as it will blow up
// the 32 bit free version of Q

$[.z.K<3.19999;0N! "You need version 3.2 or later for this, please download a more recent version of q";]
\p 5000

features:flip (
(`sorting; 0b);
(`foo; 0b)
);
features:features[0]!features[1];
\l hypergrid-support.q

0N! "generate random row ordering";
numRows:100000000;
Expand Down Expand Up @@ -45,21 +39,13 @@ trade:([]
date4:2000.01.01 + asc n ? 365;
amount5:100 * 10 + n ? 20);


\t rowsIndexes:numRows?`short$til 255;

window:{[start;num]
//lets hack the default window function to use our index
window:{[tableName;start;num]
ii: start + til num;
([]row:ii),'trade[rowsIndexes[ii]]}

.z.ws:{
message: .j.c x;
@[`$message`cmd;message`data];
}

fetch: {
json: .j.j (`data`rows`headers`features)!(value each window[`long$(x`start);`long$(x`num)];numRows;(enlist (`row;"j")),(value each select c,t from meta trade);features);
neg[.z.w] json; //negating a handle makes the sending of data async
}
([]row:ii),'(value tableName)[rowsIndexes[ii]]}

fetchTableRowCount: {
count rowsIndexes}

44 changes: 44 additions & 0 deletions q/hypergrid-support.q
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// load this script into your q script for
// a simple interface to the hypergrid using the q behavior

$[.z.K<3.19999;0N! "You need version 3.2 or later for this, please download a more recent version of q";]
\p 5000

features:flip (
(`sorting; 0b);
(`columnReordering; 0b)
);

features:features[0]!features[1];

window:{[tableName;start;num]
ii: start + til num;
([]row:ii),'(value tableName)[ii]}

.z.ws:{
message: .j.c x;
@[`$message`cmd;message`data];
}

fetchTableRowCount: {
count (value x`table)}

fetchTableData: {
json: .j.j (`data`rows`headers`features)!(value each window[(x`table);`long$(x`start);`long$(x`num)];fetchTableRowCount x;(enlist (`row;"j")),(value each select c,t from meta (value x`table));features);
neg[.z.w] json; //negating a handle makes the sending of data async
}

sf:parse "delete av from `av xasc update av:abs quantity from `myTable"
sortTable: {
$[0~count x`sort;
[];
[sf[1;2;4;`av]:(`$x`sort);
sf[1;2;1;0]:`$(x`table);
$[x`abs;
$[11h~type ((value x`table)`$x`sort);;sf[1;2;4]:(enlist`av)!enlist (abs;`$x`sort)];
()];
sf[1;0]:$[x`asc;xasc;xdesc];
eval sf]
];
fetchTableData[x];
}
39 changes: 39 additions & 0 deletions q/sorttable.q
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// this example script creates a sortable 1MM row table

\p 5000

\l hypergrid-support.q

//turn on sorting
features[`sorting]:1b;

holdingId:`abcde`bcdef`cdefgh`defgh`efghi`fghij`ghijk;
symbol:`msft`amat`csco`intc`yhoo`aapl;
trader:`chico`harpo`groucho`zeppo`moe`larry`curly`shemp`abbott`costello;
sector:`energy`materials`industrials`financials`healthcare`utilities`infotech;
strategy:`statarb`pairs`mergerarb`house`chart`indexarb

n:1000000;
trade:([]
tradeId:til n;
holdingId:n ? holdingId;
symbol:n ? symbol;
sector:n ? sector;
trader:n ? trader;
strategy:n ? strategy;
time:09:30:00.0+n?23000000;
price:50 + .23 * n ? 400;
quantity:(100 * 10 + n ? 20) - 2000;
date:2000.01.01 + asc n ? 365;
price1:50 + .23 * n ? 400;
amount1:n ? 1.0;
price2:50 + .23 * n ? 400;
amount2:(20*til n)_((n*20)?100);
date2:2000.01.01 + asc n ? 365;
price3:50 + .23 * n ? 400;
amount3:(20*til n)_((n*20)?100);
date3:2000.01.01 + asc n ? 365;
price4:50 + .23 * n ? 400;
amount4:100 * 10 + n ? 20;
date4:2000.01.01 + asc n ? 365;
amount5:100 * 10 + n ? 20);
Loading

0 comments on commit 0e348f9

Please sign in to comment.