Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(visualize) Visualize smart click #192

Merged
merged 2 commits into from
Mar 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 64 additions & 36 deletions src/app/d3Bindings/eventDistribution/distributionVisualisation.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ angular
"d3",
"roundDate",
"TimeAxis",
function (d3, roundDate, TimeAxis) {
"$url",
"conf.paths",
function (d3, roundDate, TimeAxis, $url, paths) {
return function DistributionVisualisation(target, data, dataFunctions, uniqueId) {
// variables
var self = this,
Expand Down Expand Up @@ -71,7 +73,8 @@ angular
// init
create();

// functions
/* exported functions */

function updateData(data) {
updateDataVariables(data);

Expand All @@ -81,7 +84,7 @@ angular

generateTiles();

filterTiles();
visibleTiles = filterTiles(visibleExtent, self.category);

updateElements();

Expand All @@ -97,11 +100,13 @@ angular

updateScales();

filterTiles();
visibleTiles = filterTiles(visibleExtent, self.category);

updateElements();
}

/* internal functions*/

function create() {
updateDataVariables(data);

Expand All @@ -117,6 +122,7 @@ angular
function updateDataVariables(data) {
// data should be an array of items with extents
self.items = data.items;

self.nyquistFrequency = data.nyquistFrequency;
self.spectrogramWindowSize = data.spectrogramWindowSize;
self.middle = null;
Expand Down Expand Up @@ -176,21 +182,26 @@ angular
}
}

function filterTiles() {
function filterTiles(visibleExtent, category) {
var filterPadding = tileSizeSeconds * 1000;
// item filter
var f = isItemVisible.bind(null, visibleExtent),
g = isInCategory.bind(null, self.category),
// pad the filtering extent with tileSize so that recordings that have
// duration < tileSize aren't filtered out prematurely
var fExtent = [(+visibleExtent[0]) - filterPadding, (+visibleExtent[1]) + filterPadding],
f = isItemVisible.bind(null, fExtent),
g = isInCategory.bind(null, category),
h = and.bind(null, g, f);

// tile filter
var l = isTileVisible.bind(null, visibleExtent);

visibleTiles = self.items
return self.items
.filter(h)
.reduce(function (previous, current) {
var t = current.tiles.filter(l);
return previous.concat(t);
}, []);
}, [])
.sort(sortTiles);
}

function createElements() {
Expand Down Expand Up @@ -218,19 +229,13 @@ angular
.tickPadding(8);
yAxisGroup = main.append("g")
.classed("y axis", true)
.translate([0,0])
.translate([0, 0])
.call(yAxis);

updateElements();
}

function updateElements() {
var gAttrs = {
"z-index": function (d) {
return d.source.recordedDate.getDay();
}
};

var imageAttrs = {
height: tilesHeight,
width: tileSizePixels
Expand All @@ -254,23 +259,13 @@ angular
// add new tiles
var newTileElements = tileElements.enter()
.append("g")
.attr(gAttrs)
.translate(tileGTranslation)
.classed("tile", true)
.on("click", function (datum) {
// HACK: temporary behaviour for demo
// construct url
var ar = datum.source,
id = ar.id,
startOffset = (datum.offset - ar.recordedDate) / 1000,
endOffset = startOffset + 30.0;

var url = "/listen/" + id + "?start=" + startOffset + "&end=" + endOffset;

console.warn("navigating to ", url);
.append("a")
.attr("xlink:href", function (d, i) {
return d.audioNavigationUrl;
});

window.location = url;
});
newTileElements.append("rect")
.attr(imageAttrs);

Expand Down Expand Up @@ -306,6 +301,8 @@ angular
xAxis.update(xScale, [0, tilesHeight], showAxis);
}

/* helper functions */

function updateResolution() {
resolution = tileSizeSeconds / tileSizePixels;
return resolution;
Expand All @@ -327,9 +324,9 @@ angular
return dataFunctions.getCategory(d) === category;
}

function isItemVisible(visibleExtent, d) {
return dataFunctions.getLow(d) < visibleExtent[1] &&
dataFunctions.getHigh(d) >= visibleExtent[0];
function isItemVisible(filterExtent, d) {
return dataFunctions.getLow(d) < filterExtent[1] &&
dataFunctions.getHigh(d) >= filterExtent[0];
}

function and(a, b, d) {
Expand All @@ -354,20 +351,41 @@ angular

// use d3's in built range functionality to generate steps
var steps = [];
while (offset <= niceHigh) {
while (offset < niceHigh) {
var nextOffset = d3.time.second.offset(offset, tileSizeSeconds);
steps.push({
offset: offset,
offsetEnd: nextOffset,
source: current,
key: offset.toISOString() + dataFunctions.getId(current)
key: offset.toISOString() + dataFunctions.getId(current),
audioNavigationUrl: getNavigateToAudioUrl(current, offset)
});
offset = nextOffset;
}

return steps;
}

function getNavigateToAudioUrl(source, tileStart) {

var ar = source,
id = ar.id,
startOffset = (tileStart - ar.recordedDate) / 1000;

// do not allow negative indexing!
if (startOffset < 0) {
startOffset = 0;
}

// intentionally not specifying an end offset - let the listen page decide
return $url.formatUri(paths.site.ngRoutes.listen,
{
recordingId: id,
start: startOffset
});

}

function getTileLeft(d, i) {
return xScale(d.offset);
}
Expand All @@ -389,12 +407,22 @@ angular
i);

if (url) {
return url;
return url;
}

return "";
}

/**
* Order tiles based on their date. This allows elements to be painted in the
* DOM in the right order
* @param tileA
* @param tileB
*/
function sortTiles(tileA, tileB) {
return tileA.offset - tileB.offset;
}

}
}
]
Expand Down
2 changes: 1 addition & 1 deletion src/app/listen/listen.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ angular.module('bawApp.listen', ['decipher.tags', 'ui.bootstrap.typeahead'])
// parse the start and end offsets
$routeParams.start = parseFloat($routeParams.start) || 0.0;
// warn: this converts 0 to chunk duration
$routeParams.end = parseFloat($routeParams.end) || CHUNK_DURATION_SECONDS;
$routeParams.end = parseFloat($routeParams.end) || ($routeParams.start + CHUNK_DURATION_SECONDS);
var chunkDuration = ($routeParams.end - $routeParams.start);
if (chunkDuration < 0) {

Expand Down
3 changes: 2 additions & 1 deletion src/components/services/audioRecording.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ angular
return q
.in("siteId", siteIds)
.project({include: ["id", "siteId", "durationSeconds", "recordedDate"]})
.page.disable();
.page.disable()
.sort({orderBy: "id"});
});

return $http.post(filterUrl, query.toJSON());
Expand Down