Skip to content

Commit

Permalink
Created new event model for audio events. WORK IN PROGRESS. LEFT BROKEN!
Browse files Browse the repository at this point in the history
Added a link on the security prompt so users can go to parent site to sign in.
  • Loading branch information
atruskie committed Nov 12, 2013
1 parent c9cb75f commit 90feb19
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 146 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ baw-client

The AngularJS client for the bioacoustic workbench


---
## Install instructions
$ npm -g install grunt-cli karma bower

Expand Down
10 changes: 5 additions & 5 deletions src/app/annotationViewer/_annotation_viewer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ baw-annotation-viewer {
// general

& .boxItem {

text-align: left;
border-style: $border-style;
border-width: $border-width;
border-color: $marqueeBorderColorInactive;
Expand All @@ -111,18 +111,18 @@ baw-annotation-viewer {
overflow: visible;

&:before {
// @if $DEBUG == false {
// visibility: collapse;
// }
@if not $DEBUG {
background-color: red;
}
border-left: $tagAlignmentLine solid 1px;
height: 256px;
position: relative;
top: -257px;
left: -1px;
display: inline-block;
content: "";
width: 100%;
visibility: hidden;

}

&[data-selected="true"] {
Expand Down
9 changes: 7 additions & 2 deletions src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,13 @@ var app = angular.module('baw',
}])


.run(['$rootScope', '$location', '$route', '$http', 'AudioEvent',
function ($rootScope, $location, $route, $http, AudioEvent) {
.run(['$rootScope', '$location', '$route', '$http', 'AudioEvent', 'conf.paths',
function ($rootScope, $location, $route, $http, AudioEvent, paths) {

// embed configuration for easy site-wide binding
$rootScope.paths = paths;

// helper function for printing scope objects
baw.exports.print = $rootScope.print = function () {
var seen = [];
var badKeys = ["$digest", "$$watchers", "$$childHead", "$$childTail", "$$listeners", "$$nextSibling",
Expand Down
11 changes: 9 additions & 2 deletions src/baw.configuration.tpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ angular.module('bawApp.configuration', [])
show: "/audio_recordings/{recordingId}/media.{format}"
},
security: {
ping: "/security/sign_in"
ping: "/security/sign_in",
signIn: "/my_account/sign_in"
}
}
},
site: {
root: "<%= current.siteRoot %>",
// The following intentionally are not prefixed with a '/'
// static files
files: {
error404: 'error/error_404.tpl.html',
home: 'home/home.tpl.html',
Expand All @@ -53,8 +55,13 @@ angular.module('bawApp.configuration', [])
navigation: 'navigation/navigation.tpl.html',
birdWalks: 'birdWalks/birdWalks.tpl.html'
},
ngRoutes :{
// routes used by angular
ngRoutes: {
listen: "/listen/{recordingId}/"
},
// general links for use in <a />'s
links: {

}
}
};
Expand Down
118 changes: 85 additions & 33 deletions src/components/directives/bawAnnotationViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,19 @@ bawds.directive('bawAnnotationViewer', [ 'conf.paths', function (paths) {
};
}

function resizeOrMove(audioEvent, box, scope) {
var boxId = baw.parseInt(box.id);

if (audioEvent.__temporaryId__ === boxId) {
audioEvent.highFrequencyHertz = scope.model.converters.invertHertz(scope.model.converters.pixelsToHertz(box.top || 0));
audioEvent.startTimeSeconds = scope.model.converters.pixelsToSeconds(box.left || 0);


audioEvent.endTimeSeconds = audioEvent.startTimeSeconds + scope.model.converters.pixelsToSeconds(box.width || 0);
audioEvent.lowFrequencyHertz = audioEvent.highFrequencyHertz - scope.model.converters.pixelsToHertz(box.height || 0);
}
else {
console.error("Box ids do not match on resizing or move event", audioEvent.__temporaryId__, boxId);
}
}

function resizeOrMoveWithApply(scope, audioEvent, box) {
scope.$apply(function () {
scope.__lastDrawABoxEditId__ = audioEvent.__temporaryId__;
resizeOrMove(audioEvent, box, scope);

scope.__lastDrawABoxEditId__ = audioEvent.__localId__;
var boxId = baw.parseInt(box.id);
if (audioEvent.__localId__ === boxId) {
audioEvent.highFrequencyHertz = scope.model.converters.invertHertz(scope.model.converters.pixelsToHertz(box.top || 0));
audioEvent.startTimeSeconds = scope.model.converters.pixelsToSeconds(box.left || 0);
audioEvent.endTimeSeconds = audioEvent.startTimeSeconds + scope.model.converters.pixelsToSeconds(box.width || 0);
audioEvent.lowFrequencyHertz = audioEvent.highFrequencyHertz - scope.model.converters.pixelsToHertz(box.height || 0);
}
else {
console.error("Box ids do not match on resizing or move event", audioEvent.__localId__, boxId);
}
});
}

Expand All @@ -108,8 +100,9 @@ bawds.directive('bawAnnotationViewer', [ 'conf.paths', function (paths) {

var audioEvent = new baw.Annotation(baw.parseInt(simpleBox.id), audioRecordingId);

resizeOrMove(audioEvent, simpleBox, scope);
scope.model.audioEvents.push(audioEvent);
touchUpdatedField(audioEvent);
resizeOrMoveWithApply(audioEvent, simpleBox, scope);

return audioEvent;
}
Expand All @@ -135,20 +128,20 @@ bawds.directive('bawAnnotationViewer', [ 'conf.paths', function (paths) {
var listenerFunc = function audioEventToBoxWatcher(value) {

if (value) {
if (scope.__lastDrawABoxEditId__ === value.__temporaryId__) {
if (scope.__lastDrawABoxEditId__ === value.__localId__) {
scope.__lastDrawABoxEditId__ = undefined;
console.log("audioEvent watcher SKIPPED", value.__localId__, value.selected);
return;
}

console.log("audioEvent watcher fired", value.__temporaryId__, value.selected);
console.log("audioEvent watcher fired", value.__localId__, value.selected);

// TODO: SET UP CONVERSIONS HERE
var top = scope.model.converters.invertPixels(scope.model.converters.hertzToPixels(value.highFrequencyHertz)),
left = scope.model.converters.secondsToPixels(value.startTimeSeconds),
width = scope.model.converters.secondsToPixels(value.endTimeSeconds - value.startTimeSeconds),
height = scope.model.converters.hertzToPixels(value.highFrequencyHertz - value.lowFrequencyHertz);

drawaboxInstance.drawabox('setBox', value.__temporaryId__, top, left, height, width, value.selected);
drawaboxInstance.drawabox('setBox', value.__localId__, top, left, height, width, value.selected);
}
};

Expand Down Expand Up @@ -178,10 +171,10 @@ bawds.directive('bawAnnotationViewer', [ 'conf.paths', function (paths) {

// does the annotation exist in the DOM?
// this means the annotation should not be present in the DOM, assert this
var exists = drawaboxInstance.drawabox('exists', value.__temporaryId__);
var exists = drawaboxInstance.drawabox('exists', value.__localId__);
if (exists[0] === false) {
// if not, add the annotation into the DOM
element = drawaboxInstance.drawabox('insert', value.__temporaryId__)[0][0];
element = drawaboxInstance.drawabox('insert', value.__localId__)[0][0];
}
else {
// the element already exists
Expand Down Expand Up @@ -211,6 +204,71 @@ bawds.directive('bawAnnotationViewer', [ 'conf.paths', function (paths) {

}

/**ȻɌɄƉ**/

var UPDATER_DRAWABOX = "DRAWABOX";
var UPDATER_PAGE_LOAD = "DRAWABOX";

/**
* Update the model. Events must be emitted from drawabox.
* @param box
*/
function drawaboxUpdatesModel(box) {

}

function modelUpdatesDrawabox(annotation) {

}

function modelUpdatesServer(action, annotation) {

}

function serverUpdatesModel() {

}

/**
* This method should be called when an Annotation model is updated.
* There are four possible cases:
* 1) Page load (Ȼ R ɄƉ)
* 2) Single Edit change (ȻɌ UD)
* 3) Drawabox change (C Ɍ UD)
* 4) Server async return for (reverse ȻɌ U Ɖ)
* @param changedAnnotation
* @param oldAnnotation
* @param scope
*/
function modelUpdated(changedAnnotation, oldAnnotation, scope) {
if (!changedAnnotation) {
console.debug("AnnotationEditor:modelUpdated: Falsy annotation, skip update.", changedAnnotation.__localId__);
return;
}

// invariants
if (changedAnnotation.lastUpdater === UPDATER_DRAWABOX && changedAnnotation.isDirty !== true) {
throw "AnnotationEditor:modelUpdated: Invalid state! If the last update came from drawabox then the the annotation must be dirty!";
}
if (changedAnnotation.lastUpdater === UPDATER_PAGE_LOAD && changedAnnotation.isDirty !== false) {
throw "AnnotationEditor:modelUpdated: Invalid state! If the last update came from page load then the the annotation must NOT be dirty!";
}
if (changedAnnotation.toBeDeleted && changedAnnotation.isDirty !== true) {
throw "AnnotationEditor:modelUpdated: Invalid state! If the the delete flag is set the annotation must be dirty!";
}

// if the last update was done by the drawabox control, do not propagate it back to drawabox
if (annotation.lastUpdater === DRAWABOX) {
// reset flag
annotation.lastUpdater = null;
}
else {
modelUpdatesDrawabox(changedAnnotation);
}
}


/****/

return {
restrict: 'AE',
Expand Down Expand Up @@ -277,13 +335,7 @@ bawds.directive('bawAnnotationViewer', [ 'conf.paths', function (paths) {

"newBox": function (element, newBox) {
var newAudioEvent = create(newBox, scope.model.audioRecording.id, scope);


scope.$root.$safeApply(scope, function () {
scope.model.audioEvents.push(newAudioEvent);

console.log("newBox", newBox, newAudioEvent);
});
console.log("newBox", newBox, newAudioEvent);
},
"boxSelected": function (element, selectedBox) {
console.log("boxSelected", selectedBox);
Expand Down
101 changes: 54 additions & 47 deletions src/components/models/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,66 @@ var baw = window.baw = window.baw || {};
* @param {*=} audioRecordingId
* @constructor
*/
baw.Annotation = function Annotation(localIdOrResource, audioRecordingId) {
baw.Annotation = (function () {

var localId = typeof(localIdOrResource) === "number" ? localIdOrResource : undefined;
var resource;
if (localIdOrResource instanceof Object && localIdOrResource.constructor.name == "Resource") {
resource = localIdOrResource;
}
// constructor
var module = function Annotation(localIdOrResource, audioRecordingId) {

if (!(this instanceof Annotation)) {
throw new Error("Constructor called as a function");
}
var localId = typeof(localIdOrResource) === "number" ? localIdOrResource : undefined;
var resource;
if (localIdOrResource instanceof Object && localIdOrResource.constructor.name == "Resource") {
resource = localIdOrResource;
}

this.__temporaryId__ = localId || resource.id; //(Number.Unique() * -1);
if (!angular.isNumber(this.__temporaryId__)) {
throw "Is in an annotation is not a number!";
}
if (!(this instanceof Annotation)) {
throw new Error("Constructor called as a function");
}

this.selected = false;
this.audioEventTags = [];
this.__localId__ = localId || resource.id; //(Number.Unique() * -1);
if (!angular.isNumber(this.__localId__)) {
throw "Is in an annotation is not a number!";
}

if (localId) {
var now = new Date();
this.selected = false;
this.audioEventTags = [];

this.audioRecordingId = audioRecordingId;
if (localId) {
var now = new Date();

this.createdAt = now;
this.updatedAt = now;
this.audioRecordingId = audioRecordingId;

this.endTimeSeconds = 0.0;
this.highFrequencyHertz = 0.0;
this.isReference = false;
this.lowFrequencyHertz = 0.0;
this.startTimeSeconds = 0.0;
this.createdAt = now;
this.updatedAt = now;

}
this.endTimeSeconds = 0.0;
this.highFrequencyHertz = 0.0;
this.isReference = false;
this.lowFrequencyHertz = 0.0;
this.startTimeSeconds = 0.0;

// ensure JSON values taken from a resource have nicely formatted values
if (resource) {
angular.extend(this, resource);
}

this.createdAt = new Date(this.createdAt);
this.updatedAt = new Date(this.updatedAt);
// ensure JSON values taken from a resource have nicely formatted values
if (resource) {
angular.extend(this, resource);

this.endTimeSeconds = parseFloat(this.endTimeSeconds);
this.highFrequencyHertz = parseFloat(this.highFrequencyHertz);
this.lowFrequencyHertz = parseFloat(this.lowFrequencyHertz);
this.startTimeSeconds = parseFloat(this.startTimeSeconds);
this.createdAt = new Date(this.createdAt);
this.updatedAt = new Date(this.updatedAt);

this.audioEventTags = {};
angular.forEach(this.audioEventTags, function (value, key) {
this.audioEventTags[key] = new baw.AudioEventTag(value);
}, this);
}
this.endTimeSeconds = parseFloat(this.endTimeSeconds);
this.highFrequencyHertz = parseFloat(this.highFrequencyHertz);
this.lowFrequencyHertz = parseFloat(this.lowFrequencyHertz);
this.startTimeSeconds = parseFloat(this.startTimeSeconds);

this.audioEventTags = {};
angular.forEach(this.audioEventTags, function (value, key) {
this.audioEventTags[key] = new baw.AudioEventTag(value);
}, this);
}
};

// strip out unnecessary values;
this.exportObj = function () {
module.prototype.exportObj = function exportObj() {
return {
// TODO:
taggings: [],
Expand All @@ -77,13 +81,16 @@ baw.Annotation = function Annotation(localIdOrResource, audioRecordingId) {
};
};

this.toJSON = function () {
module.prototype.toJSON = function toJSON() {
return {
id: this.id || this.__temporaryId__
id: this.id || this.__localId__
};
};
};

baw.Annotation.create = function(arg) {
return new baw.Annotation(arg);
};

module.create = function (arg) {
return new baw.Annotation(arg);
};

return module;
})();
Loading

0 comments on commit 90feb19

Please sign in to comment.