Skip to content

Commit

Permalink
Now we store virtual URL instead of update it in the browser address …
Browse files Browse the repository at this point in the history
…bar (#112)

* Copy URL, Frame URL and object URL functionality in a context menu
* Shift key in order to don't select any objects
  • Loading branch information
bsekachev authored and nmanovic committed Oct 4, 2018
1 parent 886f5e0 commit b8e0683
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 62 deletions.
52 changes: 50 additions & 2 deletions cvat/apps/engine/static/engine/js/annotationUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/

/* exported callAnnotationUI translateSVGPos blurAllElements drawBoxSize */
/* exported callAnnotationUI translateSVGPos blurAllElements drawBoxSize copyToClipboard */
"use strict";

function callAnnotationUI(jid) {
Expand Down Expand Up @@ -55,8 +55,46 @@ function buildAnnotationUI(job, shapeData, loadJobEvent) {
z_order: job.z_order,
id: job.jobid
},
search: {
value: window.location.search,

set: function(name, value) {
let searchParams = new URLSearchParams(this.value);

if (typeof value === 'undefined' || value === null) {
if (searchParams.has(name)) {
searchParams.delete(name);
}
}
else searchParams.set(name, value);
this.value = `${searchParams.toString()}`;
},

get: function(name) {
try {
let decodedURI = decodeURIComponent(this.value);
let urlSearchParams = new URLSearchParams(decodedURI);
if (urlSearchParams.has(name)) {
return urlSearchParams.get(name);
}
else return null;
}
catch (error) {
showMessage('Bad URL has been found');
this.value = window.location.href;
return null;
}
},

toString: function() {
return `${window.location.origin}/?${this.value}`;
}
}
};

// Remove external search parameters from url
window.history.replaceState(null, null, `${window.location.origin}/?id=${job.jobid}`);

window.cvat.config = new Config();

// Setup components
Expand Down Expand Up @@ -137,7 +175,7 @@ function buildAnnotationUI(job, shapeData, loadJobEvent) {
playerModel.subscribe(shapeBufferView);
playerModel.subscribe(shapeGrouperView);
playerModel.subscribe(polyshapeEditorView);
playerModel.shift(getURISearchParameter('frame') || 0, true);
playerModel.shift(window.cvat.search.get('frame') || 0, true);

let shortkeys = window.cvat.config.shortkeys;

Expand Down Expand Up @@ -185,6 +223,16 @@ function buildAnnotationUI(job, shapeData, loadJobEvent) {
});
}


function copyToClipboard(text) {
let tempInput = $("<input>");
$("body").append(tempInput);
tempInput.prop('value', text).select();
document.execCommand("copy");
tempInput.remove();
}


function setupFrameFilters() {
let brightnessRange = $('#playerBrightnessRange');
let contrastRange = $('#playerContrastRange');
Expand Down
41 changes: 1 addition & 40 deletions cvat/apps/engine/static/engine/js/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/

/* exported confirm showMessage showOverlay dumpAnnotationRequest getURISearchParameter setURISearchParameter */
/* exported confirm showMessage showOverlay dumpAnnotationRequest */
"use strict";

Math.clamp = function(x, min, max) {
Expand Down Expand Up @@ -160,45 +160,6 @@ function dumpAnnotationRequest(dumpButton, taskID) {
}
}


function setURISearchParameter(name, value) {
let searchParams = new URLSearchParams(window.location.search);
if (typeof value === 'undefined' || value === null) {
if (searchParams.has(name)) {
searchParams.delete(name);
}
}
else searchParams.set(name, value);

window.history.replaceState(null, null, `?${searchParams.toString()}`);
}


function resetURISearchParameters() {
let searchParams = new URLSearchParams();
searchParams.set('id', window.cvat.job.id);
window.history.replaceState(null, null, `?${searchParams.toString()}`);
}


function getURISearchParameter(name) {
let decodedURI = '';
try {
decodedURI = decodeURIComponent(window.location.search);
}
catch (error) {
showMessage('Bad URL has been found');
resetURISearchParameters();
}

let urlSearchParams = new URLSearchParams(decodedURI);
if (urlSearchParams.has(name)) {
return urlSearchParams.get(name);
}
else return null;
}


/* These HTTP methods do not require CSRF protection */
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
Expand Down
34 changes: 33 additions & 1 deletion cvat/apps/engine/static/engine/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ class PlayerView {
this._frameNumber = $('#frameNumber');
this._playerGridPattern = $('#playerGridPattern');
this._playerGridPath = $('#playerGridPath');
this._contextMenuUI = $('#playerContextMenu');

$('*').on('mouseup', () => this._controller.frameMouseUp());
this._playerUI.on('wheel', (e) => this._controller.zoom(e));
Expand Down Expand Up @@ -763,6 +764,38 @@ class PlayerView {
this._multiplePrevButtonUI.find('polygon').append($(document.createElementNS('http://www.w3.org/2000/svg', 'title'))
.html(`${shortkeys['backward_frame'].view_value} - ${shortkeys['backward_frame'].description}`));


this._contextMenuUI.click((e) => {
$('.custom-menu').hide(100);
switch($(e.target).attr("action")) {
case "job_url": {
window.cvat.search.set('frame', null);
window.cvat.search.set('filter', null);
copyToClipboard(window.cvat.search.toString());
break;
}
case "frame_url":
window.cvat.search.set('frame', window.cvat.player.frames.current);
window.cvat.search.set('filter', null);
copyToClipboard(window.cvat.search.toString());
window.cvat.search.set('frame', null);
break;
}
});

this._playerContentUI.on('contextmenu.playerContextMenu', (e) => {
$('.custom-menu').hide(100);
this._contextMenuUI.finish().show(100).offset({
top: e.pageY - 10,
left: e.pageX - 10,
});
e.preventDefault();
});

this._playerContentUI.on('mousedown.playerContextMenu', () => {
$('.custom-menu').hide(100);
});

playerModel.subscribe(this);
}

Expand All @@ -780,7 +813,6 @@ class PlayerView {
this._loadingUI.addClass('hidden');
if (this._playerBackgroundUI.css('background-image').slice(5,-2) != image.src) {
this._playerBackgroundUI.css('background-image', 'url(' + '"' + image.src + '"' + ')');
setURISearchParameter('frame', frames.current);
}

if (model.playing) {
Expand Down
24 changes: 21 additions & 3 deletions cvat/apps/engine/static/engine/js/shapeCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,10 @@ class ShapeCollectionController {
get filterController() {
return this._filterController;
}

get activeShape() {
return this._model.activeShape;
}
}

class ShapeCollectionView {
Expand Down Expand Up @@ -1103,7 +1107,10 @@ class ShapeCollectionView {
});

this._frameContent.on('mousemove', function(e) {
if (e.ctrlKey || e.which === 2 || e.target.classList.contains('svg_select_points')) {
if (e.ctrlKey || e.shiftKey || e.which === 2 || e.target.classList.contains('svg_select_points')) {
if (e.shiftKey) {
this._controller.resetActive();
}
return;
}

Expand All @@ -1117,9 +1124,20 @@ class ShapeCollectionView {

$('#shapeContextMenu li').click((e) => {
let menu = $('#shapeContextMenu');
menu.hide(100);
$('.custom-menu').hide(100);

switch($(e.target).attr("action")) {
case "object_url": {
let active = this._controller.activeShape;
if (active) {
window.cvat.search.set('frame', window.cvat.player.frames.current);
window.cvat.search.set('filter', `*[id="${active.id}"]`);
copyToClipboard(window.cvat.search.toString());
window.cvat.search.set('frame', null);
window.cvat.search.set('filter', null);
}
break;
}
case "change_color":
this._controller.switchActiveColor();
break;
Expand Down Expand Up @@ -1162,7 +1180,7 @@ class ShapeCollectionView {
$('#pointContextMenu li').click((e) => {
let menu = $('#pointContextMenu');
let idx = +menu.attr('point_idx');
menu.hide(100);
$('.custom-menu').hide(100);

switch($(e.target).attr("action")) {
case "remove_point":
Expand Down
13 changes: 5 additions & 8 deletions cvat/apps/engine/static/engine/js/shapeFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,10 @@ class FilterView {
let value = $.trim(e.target.value);
if (this._controller.updateFilter(value, false)) {
this._filterString.css('color', 'green');
setURISearchParameter('filter', value || null);
}
else {
this._filterString.css('color', 'red');
setURISearchParameter('filter', null);
this._controller.updateFilter('', false);
}
});

Expand All @@ -129,17 +128,15 @@ class FilterView {
this._resetFilterButton.on('click', () => {
this._filterString.prop('value', '');
this._controller.updateFilter('', false);
setURISearchParameter('filter', null);
});

if (getURISearchParameter('filter')) {
let value = getURISearchParameter('filter');
this._filterString.prop('value', value);
if (this._controller.updateFilter(value, true)) {
let initialFilter = window.cvat.search.get('filter');
if (initialFilter) {
this._filterString.prop('value', initialFilter);
if (this._controller.updateFilter(initialFilter, true)) {
this._filterString.css('color', 'green');
}
else {
setURISearchParameter('filter', null);
this._filterString.prop('value', '');
this._filterString.css('color', 'red');
}
Expand Down
10 changes: 4 additions & 6 deletions cvat/apps/engine/static/engine/js/shapes.js
Original file line number Diff line number Diff line change
Expand Up @@ -1492,16 +1492,15 @@ class ShapeView extends Listener {
// Setup context menu
this._uis.shape.on('mousedown.contextMenu', (e) => {
if (e.which === 1) {
this._shapeContextMenu.hide(100);
this._pointContextMenu.hide(100);
$('.custom-menu').hide(100);
}
if (e.which === 3) {
e.stopPropagation();
}
});

this._uis.shape.on('contextmenu.contextMenu', (e) => {
this._pointContextMenu.hide(100);
$('.custom-menu').hide(100);
let type = this._controller.type.split('_');
if (type[0] === 'interpolation') {
this._shapeContextMenu.find('.interpolationItem').removeClass('hidden');
Expand Down Expand Up @@ -1553,8 +1552,7 @@ class ShapeView extends Listener {
this._flags.editable = false;
}

this._pointContextMenu.hide(100);
this._shapeContextMenu.hide(100);
$('.custom-menu').hide(100);
}


Expand Down Expand Up @@ -2829,7 +2827,7 @@ class PolyShapeView extends ShapeView {
point = $(point);

point.on('contextmenu.contextMenu', (e) => {
this._shapeContextMenu.hide(100);
$('.custom-menu').hide(100);
this._pointContextMenu.attr('point_idx', point.index());
this._pointContextMenu.attr('dom_point_id', point.attr('id'));

Expand Down
7 changes: 7 additions & 0 deletions cvat/apps/engine/templates/engine/annotation.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@
</defs>
<rect width="100%" height="100%" fill="url(#playerGridPattern)" />
</svg>

<ul id="shapeContextMenu" class='custom-menu' oncontextmenu="return false;">
<li action="object_url"> Copy Object URL </li>
<li action="change_color"> Change Color </li>
<li action="remove_shape"> Remove Shape </li>
<li action="switch_occluded"> Switch Occluded </li>
Expand All @@ -86,6 +88,11 @@
<li class="polygonItem" action="drag_polygon"> Enable Dragging </li>
</ul>

<ul id="playerContextMenu" class='custom-menu' oncontextmenu="return false;">
<li action="job_url"> Copy Job URL </li>
<li action="frame_url"> Copy Frame URL </li>
</ul>

<ul id="pointContextMenu" class='custom-menu' oncontextmenu="return false;">
<li action="remove_point"> Remove </li>
</ul>
Expand Down
3 changes: 1 addition & 2 deletions tests/eslintrc.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,12 @@ module.exports = {
'translateSVGPos': true,
'blurAllElements': true,
'drawBoxSize': true,
'copyToClipboard': true,
// from base.js
'showMessage': true,
'showOverlay': true,
'confirm': true,
'dumpAnnotationRequest': true,
'getURISearchParameter': true,
'setURISearchParameter': true,
// from shapeCollection.js
'ShapeCollectionModel': true,
'ShapeCollectionController': true,
Expand Down

0 comments on commit b8e0683

Please sign in to comment.