Skip to content

Commit

Permalink
Worked on annotation selection, tag resolving, and better layout for …
Browse files Browse the repository at this point in the history
…tag resolving.

also diabled right click annotation editing

modified:   app/assets/javascripts/angular/controllers/annotation_viewer.js
modified:   app/assets/javascripts/angular/controllers/listen.js
modified:   app/assets/javascripts/angular/directives/directives.js
modified:   app/assets/javascripts/angular/services/services.js
modified:   app/assets/stylesheets/partials/_annotation_viewer.css.scss
modified:   app/assets/templates/annotation_viewer.html
modified:   lib/assets/javascripts/jquery.drawabox.js
  • Loading branch information
atruskie committed Feb 3, 2013
1 parent e8e456b commit c67af6d
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ function Annotation(localId, audioRecordingId) {
var now = new Date();

this.__temporaryId__ = localId || Number.Unique();
this._selected = false;

this.audioRecordingId = audioRecordingId;

this.createdAt = now;
Expand Down
3 changes: 2 additions & 1 deletion app/assets/javascripts/angular/controllers/listen.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ function ListenCtrl($scope, $resource, $routeParams, Media, AudioEvent, Tag) {
});


$scope.tags = Tag.query();
// download all the tags and store them in Tag service cache
Tag.query({}, {}, function(){}, undefined);

$scope.model.limits = {
timeMin: 0.0,
Expand Down
135 changes: 92 additions & 43 deletions app/assets/javascripts/angular/directives/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
var PRECISION = 6;

return {
conversions : conversions,
conversions: conversions,
pixelsToSeconds: function pixelsToSeconds(pixels) {
var seconds = pixels / conversions.pixelsPerSecond;
return seconds;
Expand Down Expand Up @@ -263,12 +263,12 @@
console.log("audioEvent watcher fired");

// TODO: SET UP CONVERSIONS HERE
var top = scope.model.converters.hertzToPixels(value.highFrequencyHertz),
left = scope.model.converters.secondsToPixels(value.startTimeSeconds),
width = scope.model.converters.secondsToPixels(value.endTimeSeconds - value.startTimeSeconds),
var top = 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, undefined);
drawaboxInstance.drawabox('setBox', value.__temporaryId__, top, left, height, width, value._selected);
}
};

Expand Down Expand Up @@ -308,8 +308,12 @@
function updateConverters() {
scope.model.converters = updateUnitConversions(scope, scope.$image.width(), scope.$image.height());
}
scope.$watch(function() {return scope.model.media.imageUrl}, updateConverters);

scope.$watch(function () {
return scope.model.media.imageUrl
}, updateConverters);
scope.$image[0].addEventListener('load', updateConverters, false);
updateConverters();

// init drawabox
scope.model.audioEvents = scope.model.audioEvents || [];
Expand Down Expand Up @@ -342,7 +346,7 @@
//scope.model.selectedAudioEvents.length = 0;
//scope.model.selectedAudioEvents.push(scope.model.audioEvents[element[0].annotationViewerIndex]);

angular.forEach(scope.model.audioEvents, function (value, key){
angular.forEach(scope.model.audioEvents, function (value, key) {
value._selected = false;
});

Expand Down Expand Up @@ -399,7 +403,7 @@
link: function (scope, elements, attributes, controller) {
var element = elements[0];
if (element.nodeName !== "AUDIO") {
throw "Cannot put ngAudio element on an element that is not a <audio />";
throw 'Cannot put ngAudio element on an element that is not a <audio />';
}

var events = {'abort': undefined, 'canplay': undefined, 'canplaythrough': undefined,
Expand Down Expand Up @@ -437,43 +441,88 @@
/**
* A cross record element checker
*/
bawds.directive('bawChecked', function() {


return {
restict: 'A',
bawds.directive('bawChecked', function () {

// a cache of elements for each radio group
var library = {};


return {
restict: 'A',
require: 'ngModel',
link: function radioInputType(scope, element, attr, ctrl) {
// make the name unique, if not defined
if (angularCopies.isUndefined(attr.name)) {
element.attr('name', Number.Unique());
}

function updateModel() {
// if value is defined, then when checked, set to value
// otherwise just use true/false
var value = angularCopies.isUndefined(attr.value) && element[0].checked || (element[0].checked && attr.value || null) ;
if ( value != ctrl.$viewValue) {
scope.$apply(function() {
ctrl.$setViewValue(value);
});
link: function radioInputType(scope, element, attr, ctrl) {
// make the name unique, if not defined
if (angularCopies.isUndefined(attr.name)) {
element.attr('name', Number.Unique());
}

// add element to cache group
library[attr.name] = [];

function fixLast(negativeModelValue) {
if (library[attr.name].length > 0) {
var oldScope = library[attr.name].pop();

oldScope[0].$safeApply2(function () {
// for the other elements, ensure consistent state
oldScope[1].$setViewValue(negativeModelValue);
});
}

library[attr.name].push([scope, ctrl]);
}


// reverse binding (from element to model)

function updateModel() {
// if value is defined, then when checked, set to value
// otherwise just use true/false
var negativeModelValue;
var newModelValue;
var checked = element[0].checked;
if (angularCopies.isUndefined(attr.value)) {
newModelValue = checked;
negativeModelValue = !checked;
}
else {
newModelValue = checked ? attr.value : null;
negativeModelValue = checked ? null : attr.value;
}


if (newModelValue != ctrl.$viewValue) {
fixLast(negativeModelValue);

scope.$apply(function () {
// for the current element change it
ctrl.$setViewValue(newModelValue);
});
}
}


element.bind('click', updateModel);

element.bind('change', updateModel);

ctrl.$render = function() {
var value = angularCopies.isUndefined(attr.value) ? true : attr.value;

element[0].checked = (value == ctrl.$viewValue);
};

attr.$observe('value', ctrl.$render);
}
}


}


element.bind('click', updateModel);
// element.bind('change', updateModel);

// forward binding (from model to element)
ctrl.$render = function () {
var value = angularCopies.isUndefined(attr.value) ? true : attr.value;

element[0].checked = (value == ctrl.$viewValue);

if (element[0].checked === true) {
fixLast(false);
}
};

attr.$observe('value', ctrl.$render);
}
}
});


})();

52 changes: 49 additions & 3 deletions app/assets/javascripts/angular/services/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

bawss.factory('AudioRecording', [ '$resource', function ($resource) {
return resourcePut($resource, '/audio_recordings/:recordingId', {recordingId: '@recordingId'});
}]);;
}]);

bawss.factory('AudioEvent', [ '$resource', function ($resource) {
var actions = {
Expand All @@ -45,8 +45,54 @@
return resource;
}]);

bawss.factory('Tag', [ '$resource', function ($resource) {
return $resource('/tags/:tagId', {tagId: '@tagId'}, {});

function wrap(resource, method, injection) {
var wrappedMethod = resource[method];

resource[method] = function (params, data, success, error) {
if (arguments.length != 4) {
throw "we are doing some funky stuff on this resource method... expecting exactly 4 arguments [params, data, success, error]";
}

var newSuccess = function (value, headers) {
injection(value, headers);
success(value, headers);
};

return wrappedMethod.call(wrappedMethod, params, data, newSuccess, error);
};
}

/**
* A Service for dealing with textual Tags
*
* This service memoises requests for tags
*/
bawss.factory('Tag', [ '$resource', '$q', function ($resource, $q) {
var resource = $resource('/tags/:tagId', {tagId: '@tagId'}, {});

var tags = {};

function memoize(result) {
if (angular.isArray(result)) {
angular.forEach(result, function(value) {
tags[value.id] = value;
})
}
else {
tags[result.id] = result;
}
}

wrap(resource, "get", memoize);
wrap(resource, "query", memoize);

resource.resolve = function resolveTag(id) {
var tag = tags[id];
return tag;
};

return resource;
}]);

bawss.factory('Media', [ '$resource', function ($resource) {
Expand Down
6 changes: 3 additions & 3 deletions app/assets/stylesheets/partials/_annotation_viewer.css.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import "base";
@import "../_dynamic.css.scss.erb";
@import 'base';
@import '../_dynamic.css.scss.erb';



Expand Down Expand Up @@ -107,7 +107,7 @@ baw-annotation-viewer {
}

& .close-icon {
position: relative;
position: absolute;
left: 3px;
top: 6px;
color: black;
Expand Down
17 changes: 9 additions & 8 deletions app/assets/templates/annotation_viewer.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<div ng-controller="AnnotationViewerCtrl">
<div class="tag-preview">
<ul>
<li ng-repeat="annotation in model.audioEvents" ng-style="{left: (positionLabel(annotation)) + 'px' }" >


<div id="scroller">
<div class="tag-preview">
<ul>
<li ng-repeat="annotation in model.audioEvents" ng-style="{left: (positionLabel(annotation)) + 'px' }" >
<span ng-repeat="tag in annotation.audioEventTags">
{{getTag(tag.tagId)}}{{!$last && ',' || ''}}
</span>
</li>
</ul>
</div>

<div id="scroller">
</li>
</ul>
</div>
<div class="annotation-viewer" id="annotation-viewer_{{id}}" >
<img ng-src="{{model.media.imageUrl}}" src="">
<div id="spectrogramAnnotations_{{id}}" ></div>
Expand Down
6 changes: 3 additions & 3 deletions lib/assets/javascripts/jquery.drawabox.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

var mousedown = function (e) {
// only want to handle clicks on container, not on existing boxs
if (e.target != this) {
if (e.target != this || e.which != 1) {
return;
}

Expand Down Expand Up @@ -432,8 +432,8 @@
matchingBoxElement.style.top = (top || matchingBoxElement.style.top ) + "px";
matchingBoxElement.style.left = (left || matchingBoxElement.style.left ) + "px";

if (selected !== undefined && (selected === true || selected === false)) {
matchingBoxElement.setAttribute(SELECTED_ATTRIBUTE, selected.toString());
if (selected !== undefined) {
matchingBoxElement.setAttribute(SELECTED_ATTRIBUTE, (!!selected).toString());
}
}
else {
Expand Down

0 comments on commit c67af6d

Please sign in to comment.