Skip to content

Commit

Permalink
More work on annotation page. Got panel drawing -> model working dece…
Browse files Browse the repository at this point in the history
…ntly.

Midway through switching from an array structure to an hash structure for storing audio events - this is because the pprimary operation on the data will be a key-based lookup (rather than just index)
This will enable moving/resizing before selected evebnt fires

modified:   app/assets/javascripts/angular/controllers/listen.js
modified:   app/assets/javascripts/angular/directives/directives.js

modified:   app/assets/stylesheets/_annotation_viewer.css.scss
	-- added transparent background

modified:   app/assets/templates/annotation_viewer.html
modified:   app/assets/templates/listen.html

modified:   lib/assets/javascripts/jquery.drawabox.js
	-- made unique numbers negative

modified:   app/assets/javascripts/app.js
	-- made a version of safe apply that uses the scope it is attached on
  • Loading branch information
atruskie committed Dec 20, 2012
1 parent 27c006a commit c4b1c97
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 43 deletions.
22 changes: 3 additions & 19 deletions app/assets/javascripts/angular/controllers/listen.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,6 @@ function ListenCtrl($scope, $resource, $routeParams, Media, AudioEvent, Tag) {
else {
var recordingId = $scope.recordingId = $routeParams.recordingId;


//
// $scope.recording = AudioRecording.get($routeParams);
//
// // HACK:
// $scope.recordingurl = "/media/" + recordingId + "_0_120_0_11025.mp3";
//
//
// var spectrogramResource = $resource('/media/:recordingId', {recordingId: '@recordingId'}, {
// get: { method: 'GET', params: {recordingId: '@recordingId'}, isArray: false }
// });
// $scope.spectrogram = spectrogramResource.get($routeParams);
//
// // HACK:
// $scope.spectrogram.url = "/media/" + recordingId + "_0_120_0_11025_512_g.png" + "?" + angularCopies.toKeyValue($scope.authTokenParams());

$scope.model = {};

var formatPaths = function () {
Expand Down Expand Up @@ -71,11 +55,12 @@ function ListenCtrl($scope, $resource, $routeParams, Media, AudioEvent, Tag) {


$scope.clearSelected = function() {
$scope.selectedAnnotation = {};
$scope.model.selectedAudioEvents.length = 0;
};

$scope.addAnnotation = function createAnnotation() {
var a = angular.copy(this.selectedAnnotation);
// BUG: ONLY SAVES FIRST ONE
var a = angular.copy(this. $scope.model.selectedAudioEvents[0]);

// prep tags
a.audio_event_tags_attributes = a.audioEventTags.map(function (v) {return {tag_id:v};});
Expand All @@ -89,7 +74,6 @@ function ListenCtrl($scope, $resource, $routeParams, Media, AudioEvent, Tag) {

// now update tag-list
$scope.model.audioEvents.push(response);
$scope.selectedAnnotation = response;

},
function createAnnotationFailure(response, getResponseHeaders) {
Expand Down
48 changes: 32 additions & 16 deletions app/assets/javascripts/angular/directives/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
};

function resizeOrMove(audioEvent, box) {

if (audioEvent.__temporaryId__ === box.id) {
audioEvent.startTimeSeconds = box.left || 0;
audioEvent.highFrequencyHertz = box.top || 0;
Expand All @@ -125,9 +126,14 @@
audioEvent.lowFrequencyHertz = (audioEvent.highFrequencyHertz + box.height) || 0;
}
else {
throw "Box ids do not match on resizing or move event";
console.error("Box ids do not match on resizing or move event", audioEvent.__temporaryId__ , box.id);
}
}
function resizeOrMoveWithApply(scope, audioEvent, box) {
scope.$apply(function() {
resizeOrMove(audioEvent, box);
})
}

function touchUpdatedField(audioEvent) {
audioEvent.updatedAt = new Date();
Expand Down Expand Up @@ -168,60 +174,70 @@
// // transform DOM
// },
link: function (scope, element, attributes, controller) {


var $element = $(element);
// assign a unique id to scope
scope.id = Number.Unique();

scope.$canvas = $element.find(".annotation-viewer img + div").first();

// init drawabox
scope.model.audioEvents = scope.model.audioEvents || [];
// we use hash (POJO) because most of our operations involve lookups
scope.model.audioEvents = scope.model.audioEvents || {};
// store only the ids in this array (again for speed)
scope.model.selectedAudioEvents = scope.model.selectedAudioEvents || [];


scope.$canvas.drawabox({
"newBox": function (element, newBox) {
var newAudioEvent = create(newBox, "a dummy id!");
scope.model.audioEvents.push(newAudioEvent);

console.log("newBox", newBox, newAudioEvent);
scope.$apply(function() {
scope.model.audioEvents[newAudioEvent.__temporaryId__] = newAudioEvent;
console.log("newBox", newBox, newAudioEvent);
});
},
"boxSelected": function (element, selectedBox) {
console.log("boxSelected", selectedBox);

var audioEvent = _.find(scope.model.audioEvents, function(value) { return value.__temporaryId__ === selectedBox.id});
//var audioEvent = _.find(scope.model.audioEvents, function(value) { return value.__temporaryId__ === selectedBox.id});

// support for multiple selections - remove the clear
scope.model.selectedAudioEvents.length = 0;
scope.model.selectedAudioEvents.push(audioEvent);
scope.model.selectedAudioEvents.push(selectedBox.id);
},
"boxResizing": function (element, box) {
console.log("boxResizing");
resizeOrMove(scope.model.selectedAudioEvents[0], box);
resizeOrMoveWithApply(scope, scope.model.audioEvents[box.id], box);

},
"boxResized": function (element, box) {
console.log("boxResized");
resizeOrMove(scope.model.selectedAudioEvents[0], box);
resizeOrMoveWithApply(scope, scope.model.audioEvents[box.id], box);
},
"boxMoving": function (element, box) {
console.log("boxMoving");
resizeOrMove(scope.model.selectedAudioEvents[0], box);
resizeOrMoveWithApply(scope, scope.model.audioEvents[box.id], box);
},
"boxMoved": function (element, box) {
console.log("boxMoved");
resizeOrMove(scope.model.selectedAudioEvents[0], box);
resizeOrMoveWithApply(scope, scope.model.audioEvents[box.id], box);
},
"boxDeleted": function (element, deletedBox) {
console.log("boxDeleted");

// TODO: is this done by reference? does it even work?;
_(scope.model.audioEvents).reject(function (item) {
return item.id === deletedBox.id;
});
_(scope.model.selectedAudioEvents).reject(function (item) {
return item.id === deletedBox.id;
scope.$apply(function(){
// TODO: is this done by reference? does it even work?;
_(scope.model.audioEvents).reject(function (item) {
return item.id === deletedBox.id;
});
_(scope.model.selectedAudioEvents).reject(function (item) {
return item.id === deletedBox.id;
});
});


}
});

Expand Down
12 changes: 12 additions & 0 deletions app/assets/javascripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,18 @@ var bawApp = (function (undefined) {
}
};

$rootScope.$safeApply2 = function (fn) {
var $scope = this || $rootScope;
fn = fn || function () {};

if ($scope.$$phase) {
fn();
}
else {
$scope.$apply(fn);
}
};

$rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
console.warn("route changing has failed... handle me some how");
//change this code to handle the error somehow
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/_annotation_viewer.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ baw-annotation-viewer {
border-width: $border-width;
border-color: nth($master-highlight, 2);
position: absolute;
background-color: rgba(255,255,255,0.05);

&[data-selected="true"] {
border-color: nth($master-complementary, 2);
Expand Down
2 changes: 1 addition & 1 deletion app/assets/templates/annotation_viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div id="scroller">
<div class="annotation-viewer" id="annotation-viewer_{{id}}" >
<img ng-src="{{model.media.imageUrl}}" src="">
<div id="spectrogramAnnotations_{{id}}"></div>
<div id="spectrogramAnnotations_{{id}}" ></div>
</div>
</div>

Expand Down
11 changes: 8 additions & 3 deletions app/assets/templates/listen.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,13 @@ <h3>Annotations</h3>
</thead>
<tbody>
<tr ng-repeat="ae in model.audioEvents">
<td>{{ae.id}}</td>
<td><a ng-href="/recordings/{{ae.audioRecording.uuid}}"
<td colspan="{{ae.id && 1 || 2}}">
{{ae.id}}
<span ng-hide="ae.id">
<em>new annotation</em>
</span>
</td>
<td ng-show="ae.id" ><a ng-href="/recordings/{{ae.audioRecording.uuid}}"
class="short-guid">{{ae.audioRecording.uuid}}</a></td>
<td>{{ae.createdAt}}</td>
<td>{{ae.creatorId}}</td>
Expand All @@ -100,7 +105,7 @@ <h3>Annotations</h3>
<td>{{ae.updatedAt}}</td>
<td>{{ae.updaterId}}</td>
<td><span ng-repeat="t in ae.audioEventTags">{{t.tagId}},</span></td>
<td>{{ae.starttimeSeconds}} - {{ae.endTimeSeconds}}</td>
<td>{{ae.startTimeSeconds}} - {{ae.endTimeSeconds}}</td>
<td>{{ae.lowFrequencyHertz}} - {{ae.highFrequencyHertz}}</td>
</tr>
</tbody>
Expand Down
12 changes: 8 additions & 4 deletions lib/assets/javascripts/jquery.drawabox.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
var closeIconTemplate = '<span class="close-icon"></span>';


var uniqueId = Number.Unique();
var uniqueId = -1 *Number.Unique();
$('.boxItem').attr(SELECTED_ATTRIBUTE, false);
var newId = "boxItem_" + uniqueId;
contextData.currentMouseDragBoxId = newId;
Expand Down Expand Up @@ -196,6 +196,8 @@
return;
}

// box must be selected

//var wasMouseDownSet = dataMouseMove.mousedown;
var currentBoxId = dataMouseMove.currentMouseDragBoxId;

Expand All @@ -216,8 +218,8 @@
var xdiff = Math.abs(currentPos.x - startClickPos.x);
var ydiff = Math.abs(currentPos.y - startClickPos.y);

// this is wrong - it incorrectly gets hypotenuseal distance, not the length of the edges
//var distance = Math.sqrt((xdiff * xdiff) + (ydiff * ydiff));

// minimum dimensions before valid box
var distance = Math.min(xdiff, ydiff);

if (!currentBoxId) {
Expand Down Expand Up @@ -293,7 +295,7 @@

var maxBoxes = parseInt(options.maxBoxes);
if (isNaN(maxBoxes) && maxBoxes < 1) {
throw new Error("Max boxs must be an int greater than zero (or undefined)");
throw new Error("Max boxes must be an int greater than zero (or undefined)");
}
if (maxBoxes < options.initialBoxes.length) {
throw "max boxes must be greater than the initial number of boxes that are to be drawn";
Expand All @@ -315,6 +317,8 @@
}




return this.each(function () {

var $this = $(this);
Expand Down

0 comments on commit c4b1c97

Please sign in to comment.