diff --git a/capsule-prototype/index.html b/capsule-prototype/index.html
index 42d139c96b41170d7ea324bf77d45012eff41b21..1f72e94888394a3671918586ffd09d7b507cd73e 100644
--- a/capsule-prototype/index.html
+++ b/capsule-prototype/index.html
@@ -40,6 +40,7 @@
 	<script language="javascript" type='text/javascript' src='../shared/js/online-rekall/Timeline.js'></script>
 	<script language="javascript" type='text/javascript' src="../shared/js/online-rekall/RekallApplication.js"></script>
 	<script language="javascript" type="text/javascript" src='../shared/js/MosaicPanelWidget.js'></script>
+	<script language="javascript" type="text/javascript" src='../shared/js/PopupPanelWidget.js'></script>
 
 	<script language="javascript" type='text/javascript' src='../shared/js/iannix.js'></script>
 	<script language="javascript" type='text/javascript' src='../shared/js/online-script.js'></script>
diff --git a/capsule-prototype/js/PopupPanelWidget.js b/capsule-prototype/js/PopupPanelWidget.js
new file mode 100644
index 0000000000000000000000000000000000000000..8420d6130cf907871e42930c2e63fbc228411681
--- /dev/null
+++ b/capsule-prototype/js/PopupPanelWidget.js
@@ -0,0 +1,917 @@
+function convertToTime(seconds) {
+    let minutes = Math.floor(seconds / 60);
+    let remainingSeconds = Math.floor(seconds - (minutes * 60));
+    if (minutes < 10) minutes = "0" + minutes;
+    if (remainingSeconds < 10) remainingSeconds = "0" + remainingSeconds;
+    return minutes + ":" + remainingSeconds;
+}
+
+function PanelInputEditor(data) {
+    this.tag = data.tag;
+    this.readonlyDiv = undefined;
+    this.editDiv = undefined;
+    this.canEdit = data.canEdit;
+    this.popupPanelWidget = data.popupPanelWidget;
+}
+PanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+}
+PanelInputEditor.prototype.closeEdition = function () {
+    this.popupPanelWidget.setCurrentOpenedInput(undefined);
+    this.editDiv?.hide();
+    this.readonlyDiv?.show();
+}
+PanelInputEditor.prototype.openEdition = function () {
+    this.popupPanelWidget.ensureLastOpenedEditionClosed();
+    if (this.canEdit) {
+        this.popupPanelWidget.setCurrentOpenedInput(this);
+        this.readonlyDiv.hide();
+        if (this.editDiv) {
+            this.editDiv.show().focus();
+        }
+    }
+}
+
+function AnnotationNamePanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+}
+AnnotationNamePanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+AnnotationNamePanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+    this.readonlyDiv = $('<div>');
+    this.readonlyDiv
+        .attr('id', 'popupNom')
+        .addClass('popupRightItem');
+
+    if (this.canEdit) {
+        this.readonlyDiv
+            .click(function (event) {
+                event.stopPropagation();
+                that.openEdition.call(that);
+            });
+    }
+
+    if (this.tag.getMetadata("Rekall->Name")?.length) {
+        this.readonlyDiv.html(this.tag.getMetadata("Rekall->Name"));
+        this.readonlyDiv.css('color', this.tag.color)
+    } else {
+        if (this.canEdit) {
+            this.readonlyDiv.html('+ Add a name').addClass('empty');
+        }
+    }
+
+    parentDiv.append(this.readonlyDiv);
+
+    if (this.canEdit) {
+        this.editDiv = $('<input>');
+        this.editDiv
+            .attr('id', 'popupNomInput')
+            .attr('type', 'text')
+            .attr('value', this.tag.getMetadata("Rekall->Name") ?? '')
+            .click(function (event) {
+                event.stopPropagation();
+            })
+            .keyup(function (event) {
+                event.stopPropagation();
+                if (13 === event.which) {
+                    that.closeEdition();
+                }
+            })
+            .hide();
+        this.editDiv.val(this.tag.getMetadata("Rekall->Name"));
+        parentDiv.append(this.editDiv);
+    }
+}
+AnnotationNamePanelInputEditor.prototype.closeEdition = function () {
+    if (this.canEdit) {
+        let newValue = this.editDiv.val();
+        this.editDiv.val(newValue);
+        if (this.tag.getMetadata('Rekall->name') !== newValue) {
+            this.tag.setMetadata('Rekall->name', newValue);
+            window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                metadata: "Rekall->name",
+                tag: this.tag
+            });
+        }
+
+        if (newValue.length) {
+            $('#popupNom').html(newValue).removeClass("empty");
+        } else {
+            $('#popupNom').html('+ Add a name').addClass("empty");
+        }
+    }
+    PanelInputEditor.prototype.closeEdition.call(this);
+}
+
+function AuthorPanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+}
+AuthorPanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+AuthorPanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+    this.readonlyDiv = $('<div>');
+    this.readonlyDiv.addClass('popupRightItem')
+        .attr('id', 'popupAuthor');
+
+    if (this.canEdit) {
+        this.readonlyDiv
+            .click(function (event) {
+                event.stopPropagation();
+                that.openEdition.call(that);
+            });
+    }
+
+    let popupAuthorName = this.tag.getMetadata("Rekall->Author");
+    if (popupAuthorName?.length) {
+        this.readonlyDiv.html(popupAuthorName);
+    } else {
+        if (this.canEdit) {
+            this.readonlyDiv.html('+ Add an author').addClass('empty');
+        }
+    }
+    parentDiv.append(this.readonlyDiv);
+
+
+    if (this.canEdit) {
+        this.editDiv = $('<input>');
+        this.editDiv
+            .attr('id', 'popupAuthorInput')
+            .attr('type', 'text')
+            .attr('value', popupAuthorName ?? '')
+            .click(function (event) {
+                event.stopPropagation();
+            })
+            .keyup(function (event) {
+                event.stopPropagation();
+                if (13 === event.which) {
+                    that.closeEdition();
+                }
+            })
+            .addClass('popupInput')
+            .hide();
+        parentDiv.append(this.editDiv);
+    }
+}
+AuthorPanelInputEditor.prototype.closeEdition = function () {
+    if (this.canEdit) {
+        let newValue = this.editDiv.val();
+        this.editDiv.val(newValue);
+        if (this.tag.getMetadata('Rekall->Author') !== newValue) {
+            this.tag.setMetadata('Rekall->Author', newValue);
+            window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                metadata: "Rekall->Author",
+                tag: this.tag
+            });
+        }
+
+        if (newValue.length) {
+            this.readonlyDiv.html(newValue).removeClass("empty");
+        } else {
+            this.readonlyDiv.html('+ Add an author').addClass("empty");
+        }
+    }
+    PanelInputEditor.prototype.closeEdition.call(this);
+}
+
+function TCPanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+}
+TCPanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+TCPanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+
+    this.readonlyDiv = $('<div>');
+    this.readonlyDiv
+        .attr('id', 'popupTC')
+        .addClass('popupRightItem')
+        .click(function (event) {
+            event.stopPropagation();
+            that.openEdition.call(that);
+        });
+
+    this.popupTcInDiv = $('<div>');
+    this.popupTcInDiv
+        .attr('id', 'popupTCin')
+        .addClass('popupTCdisplay')
+        .html(convertToTime(that.tag.getTimeEnd()))
+    this.readonlyDiv.append(this.popupTcInDiv);
+
+    this.popupTcOutDiv = $('<div>');
+    this.popupTcOutDiv
+        .attr('id', 'popupTCout')
+        .addClass('popupTCdisplay')
+        .html(convertToTime(that.tag.getTimeEnd()))
+    this.readonlyDiv.append(this.popupTcOutDiv);
+    parentDiv.append(this.readonlyDiv);
+
+    if (this.canEdit) {
+        this.editDiv = $('<div>');
+        this.editDiv
+            .attr('id', 'popupTCedit')
+            .hide()
+        this.editDiv.click(function (event) {
+            event.stopPropagation();
+        })
+        this.editDiv.append($('<span>').addClass('popupTClabel').html('start'));
+        this.popupTCeditDivMinStart = $('<input class="popupTCeditfield" id="popupTCinMin" maxLength="2" type="text" value="">');
+        this.popupTCeditDivMinStart.click(function (event) {
+            event.stopPropagation();
+        });
+        this.editDiv.append(this.popupTCeditDivMinStart);
+        this.editDiv.append(':');
+        this.popupTCeditDivSecStart = $('<input class="popupTCeditfield" id="popupTCinSec" maxLength="2" type="text" value="">');
+        this.popupTCeditDivSecStart.click(function (event) {
+            event.stopPropagation();
+        });
+        this.editDiv.append(this.popupTCeditDivSecStart);
+        let popupTCeditStartDivNow = $('<div className="nowTCbtn" id="nowTCin">now</div>');
+        popupTCeditStartDivNow.click(function (event) {
+            event.stopPropagation();
+            let timeCurrent = convertToTime(Math.round(rekall.timeline.timeCurrent));
+            that.popupTCeditDivMinStart.val(timeCurrent.split(":")[0]);
+            that.popupTCeditDivSecStart.val(timeCurrent.split(":")[1]);
+        });
+        this.editDiv.append(popupTCeditStartDivNow);
+        this.editDiv.append($('<br>'));
+
+        this.editDiv.append($('<span>').addClass('popupTClabel').html('end'));
+        this.popupTCeditDivMinEnd = $('<input>');
+        this.popupTCeditDivMinEnd
+            .attr('id', 'popupTCoutMin')
+            .attr('maxlength', '2')
+            .attr('type', 'text')
+            .addClass('popupTCeditfield')
+            .val('');
+        this.popupTCeditDivMinEnd.click(function (event) {
+            event.stopPropagation();
+        });
+        this.editDiv.append(this.popupTCeditDivMinEnd);
+        this.editDiv.append(':');
+        this.popupTCeditDivSecEnd = $('<input>');
+        this.popupTCeditDivSecEnd
+            .attr('id', 'popupTCoutSec')
+            .attr('maxlength', '2')
+            .attr('type', 'text')
+            .addClass('popupTCeditfield')
+            .val('')
+            .click(function (event) {
+                event.stopPropagation();
+            });
+        this.editDiv.append(this.popupTCeditDivSecEnd);
+        let popupTCeditEndDivNow = $('<div className="nowTCbtn" id="nowTCin">now</div>');
+        popupTCeditEndDivNow.click(function (event) {
+            event.stopPropagation();
+            let timeCurrent = convertToTime(Math.round(rekall.timeline.timeCurrent));
+            that.popupTCeditDivMinEnd.val(timeCurrent.split(":")[0]);
+            that.popupTCeditDivSecEnd.val(timeCurrent.split(":")[1]);
+        });
+        this.editDiv.append(popupTCeditEndDivNow);
+        this.editDiv.append('/');
+        let popupTcEditEndDivEndVideo = $('<div class="nowTCbtn" id="eovTCout">end of video</div>');
+        popupTcEditEndDivEndVideo.click(function (event) {
+            event.stopPropagation();
+            let endVideo = rekall.videoPlayer.duration();
+            let timeEnd = convertToTime(Math.round(endVideo));
+            that.popupTCeditDivMinEnd.val(timeEnd.split(":")[0]);
+            that.popupTCeditDivSecEnd.val(timeEnd.split(":")[1]);
+        });
+        this.editDiv.append(popupTcEditEndDivEndVideo);
+        parentDiv.append(this.editDiv);
+    }
+}
+TCPanelInputEditor.prototype.closeEdition = function () {
+    if (this.canEdit) {
+        let tcInMin = this.popupTCeditDivMinStart.val();
+        let tcInSec = this.popupTCeditDivSecStart.val();
+        let tcOutMin = this.popupTCeditDivMinEnd.val();
+        let tcOutSec = this.popupTCeditDivSecEnd.val();
+        let tcIn = (60 * tcInMin) + tcInSec;
+        let tcOut = (60 * tcOutMin) + tcOutSec;
+
+        let endVideo = Math.ceil(rekall.videoPlayer.duration());
+
+        if ((tcInMin >= 120) || (tcInSec >= 60) || (tcOutMin >= 120) || (tcOutSec >= 60) || (tcInMin < 0) || (tcInSec < 0) || (tcOutMin < 0) || (tcOutSec < 0)) {
+            window.app.rekall.Rekall('pubSub').publish('alert', {message: 'Invalid time code', buttons: "ok"});
+        } else if (tcIn > tcOut) {
+            window.app.rekall.Rekall('pubSub').publish('alert', {
+                message: "Start time must be set before end time",
+                buttons: "ok"
+            });
+        } else if (tcOut > endVideo) {
+            window.app.rekall.Rekall('pubSub').publish('alert', {
+                message: "End time must not be set after " + convertToTime(endVideo) + " (end of the video)",
+                buttons: "ok"
+            });
+        } else {
+            this.tag.setTimeStart(tcIn);
+            this.tag.setTimeEnd(tcOut);
+            this.popupTcInDiv.html(tcInMin + ":" + tcInSec);
+            this.popupTcOutDiv.html(tcOutMin + ":" + tcOutSec);
+            window.app.rekall.Rekall('pubSub').publish('tag.tc.updated', {tag: this.tag});
+        }
+    }
+    PanelInputEditor.prototype.closeEdition.call(this);
+}
+
+function CommentPanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+}
+CommentPanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+CommentPanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+    this.readonlyDiv = $('<div>');
+    this.readonlyDiv.addClass('popupRightItem')
+        .attr('id', 'popupLegende')
+        .attr('title', 'Comment');
+
+    if (this.canEdit) {
+        this.readonlyDiv
+            .click(function (event) {
+                event.stopPropagation();
+                that.openEdition.call(that);
+            });
+    }
+
+    let comments = this.tag.getMetadata("Rekall->Comments");
+    if (comments && comments.length) {
+        this.readonlyDiv.html(comments).removeClass('empty');
+    } else {
+        if (this.canEdit) {
+            this.readonlyDiv.html('+ Add a comment').addClass('empty');
+        }
+    }
+    parentDiv.append(this.readonlyDiv);
+
+    if (this.canEdit) {
+        this.editDiv = $('<textarea>');
+        this.editDiv
+            .attr('id', 'popupLegendeInput')
+            .attr('type', 'text')
+            .addClass('popupInput')
+            .click(function (event) {
+                event.stopPropagation();
+            });
+        this.editDiv.val(comments ? comments : '');
+        parentDiv.append(this.editDiv);
+    }
+}
+CommentPanelInputEditor.prototype.closeEdition = function () {
+    if (this.canEdit) {
+        let newValue = this.editDiv.val();
+        this.editDiv.val(newValue);
+        if (this.tag.getMetadata('Rekall->Comments') !== newValue) {
+            newValue = newValue.replace(/\n/gi, "<br/>");
+            this.tag.setMetadata('Rekall->Comments', newValue);
+            window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                metadata: "Rekall->Comments",
+                tag: this.tag
+            });
+        }
+
+        if (newValue.length) {
+            this.readonlyDiv.html(newValue).removeClass("empty");
+        } else {
+            this.readonlyDiv.html('+ Add an author').addClass("empty");
+        }
+    }
+    PanelInputEditor.prototype.closeEdition.call(this);
+}
+
+function LinkPanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+}
+LinkPanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+LinkPanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+    this.readonlyDiv = $('<div>');
+    this.readonlyDiv.addClass('popupRightItem')
+        .attr('id', 'popupLink')
+        .attr('title', 'Link');
+
+    if (this.canEdit) {
+        this.readonlyDiv
+            .click(function (event) {
+                event.stopPropagation();
+                that.openEdition.call(that);
+            });
+    }
+
+    let linkValue = this.tag.getMetadata("Rekall->Link");
+    if (linkValue && linkValue.length) {
+        if (this.canEdit) {
+            this.readonlyDiv.html(linkValue).removeClass('empty');
+        } else {
+            this.readonlyDiv.html("<a href='" + linkValue + "' target='_blank'>" + linkValue + "</a>").removeClass('empty');
+        }
+    } else {
+        if (this.canEdit) {
+            this.readonlyDiv.html("+ Add a link").addClass("empty");
+        }
+    }
+    parentDiv.append(this.readonlyDiv);
+
+    if (this.canEdit) {
+        this.editDiv = $('<textarea>');
+        this.editDiv
+            .attr('id', 'popupLinkInput')
+            .attr('type', 'text')
+            .addClass('popupInput')
+            .click(function (event) {
+                event.stopPropagation();
+            })
+            .keyup(function (event) {
+                event.stopPropagation();
+                if (event.which == 13) {
+                    that.closeEdition();
+                }
+            })
+            .hide();
+
+        parentDiv.append(this.editDiv);
+    }
+}
+LinkPanelInputEditor.prototype.closeEdition = function () {
+    if (this.canEdit) {
+        let newValue = this.editDiv.val();
+        newValue = newValue.trim();
+        if (newValue && newValue.length && newValue.indexOf("http") != 0) {
+            newValue = "http://" + newValue;
+        }
+        this.editDiv.val(newValue);
+
+        if (this.tag.getMetadata('Rekall->Link') !== newValue) {
+            this.tag.setMetadata('Rekall->Link', newValue);
+            window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                metadata: "Rekall->Link",
+                tag: this.tag
+            });
+        }
+
+        if (newValue.length) {
+            this.readonlyDiv.html(newValue).removeClass("empty");
+        } else {
+            this.readonlyDiv.html('+ Add a Link').addClass("empty");
+        }
+    }
+    PanelInputEditor.prototype.closeEdition.call(this);
+}
+
+function SpeedPanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+}
+SpeedPanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+SpeedPanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+    this.readonlyDiv = $('<form>');
+    this.readonlyDiv.addClass('popupRightItem')
+        .attr('id', 'popupSpeedInput')
+        .addClass('flex-row playback_form popupInput popupInputNoHide');
+
+    let input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_025')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(0.25);
+    let inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_025')
+        .html('0.25')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_05')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .prop('disabled', this.canEdit ? null : 'disabled')
+        .val(0.5);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_05')
+        .html('0.5')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_075')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(0.75);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_075')
+        .html('0.75')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_1')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(1);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_1')
+        .html('normal')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_125')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(1.25);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_125')
+        .html('1.25')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_15')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(1.5);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_15')
+        .html('1.5')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_175')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(1.75);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_175')
+        .html('1.75')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    input = $('<input>');
+    input
+        .attr('id', 'annotation_playback_speed_2')
+        .attr('type', 'radio')
+        .attr('name', 'playback_rate')
+        .attr('disabled', this.canEdit ? null : 'disabled')
+        .val(2);
+    inputLabel = $('<label>');
+    inputLabel
+        .attr('for', 'annotation_playback_speed_2')
+        .html('2')
+        .addClass('left_menu_item');
+    this.readonlyDiv.append(input);
+    this.readonlyDiv.append(inputLabel);
+
+    let speed = this.tag.getMetadata("Rekall->Speed");
+    if (!speed || speed == '')
+        speed = 1;
+    this.readonlyDiv.children('input[value="' + speed + '"]').attr('checked', true);
+    this.readonlyDiv.children('input[name=playback_rate]').change(function (event) {
+        event.stopPropagation();
+        that.closeEdition.call(that);
+    })
+
+    parentDiv.append(this.readonlyDiv);
+}
+SpeedPanelInputEditor.prototype.closeEdition = function () {
+    if (this.canEdit) {
+        let newValue = this.readonlyDiv.children('input:checked').val();
+        if (this.tag.getMetadata('Rekall->Speed') !== newValue) {
+            this.tag.setMetadata('Rekall->Speed', newValue);
+            window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                metadata: "Rekall->Speed",
+                tag: this.tag
+            });
+        }
+    }
+}
+SpeedPanelInputEditor.prototype.openEdition = function () {
+    this.popupPanelWidget.ensureLastOpenedEditionClosed();
+    if (this.canEdit) {
+        this.popupPanelWidget.setCurrentOpenedInput(this);
+    }
+}
+
+function TagPanelInputEditor(data) {
+    PanelInputEditor.call(this, data);
+    this.annotationInputTemplate = $('<input class="" type="checkbox" id="" value="">')
+    this.annotationLabelTemplate = $('<label class="" for=""></label>')
+}
+TagPanelInputEditor.prototype = Object.create(PanelInputEditor.prototype);
+TagPanelInputEditor.prototype.appendInputEditorDiv = function (parentDiv) {
+    let that = this;
+
+    function getLabelArray(tag) {
+        let labels = tag.document.project.labels;
+        if (!labels)
+            return [];
+
+        return labels;
+    }
+
+    function appendTagInputWithLabel(panel, currentLabel) {
+        let input = panel.annotationInputTemplate.clone();
+        let id = 'annotation_label_' + panel.tag.document.project.labels.indexOf(currentLabel);
+        input
+            .attr('id', id)
+            .attr('value', currentLabel)
+            .addClass('annotation_labels')
+            .change(function (event) {
+                event.stopPropagation();
+                that.closeEdition.call(that);
+                that.openEdition.call(that);
+            })
+            .hide();
+
+        let html_label = panel.annotationLabelTemplate.clone();
+        html_label
+            .attr('for', id)
+            .html(currentLabel)
+            .addClass('annotation_labels');
+
+        panel.readonlyDiv.append(input);
+        panel.readonlyDiv.append(html_label);
+    }
+
+    this.tagPanelLabel = $('<div class="popupNewTitles">+ Tags</div>');
+    parentDiv.append(this.tagPanelLabel);
+
+    this.tagCreationDiv = $('<input type="text" id="new_annotation_label" placeholder="Add a new tag">');
+    this.tagCreationDiv.keypress(function (event) {
+        that.openEdition.call(that);
+        let keycode = (event.keyCode ? event.keyCode : event.which);
+        if (keycode != 13) {
+            return;
+        }
+
+        let labelToAdd = $(this).val();
+        let labels = getLabelArray(that.tag);
+        if (labels.indexOf(labelToAdd) === -1) {
+            that.tag.document.project.labels.push(labelToAdd);
+            appendTagInputWithLabel(that, labelToAdd);
+        }
+        that.readonlyDiv.children('input[value=' + labelToAdd + ']').attr('checked', 'checked');
+        $(this).val('');
+        that.closeEdition.call(that);
+    });
+    parentDiv.append(this.tagCreationDiv);
+
+    this.readonlyDiv = $('<div>');
+    this.readonlyDiv
+        .addClass('flex-col popupInput popupInputNoHide')
+        .attr('id', 'popupLabelsInput');
+
+    let _labels = getLabelArray(this.tag);
+    for (let currentLabel of _labels) {
+        appendTagInputWithLabel(this, currentLabel);
+    }
+    parentDiv.append(this.readonlyDiv);
+}
+TagPanelInputEditor.prototype.save = function () {
+    if (this.canEdit) {
+        let newValue = '';
+        this.readonlyDiv
+            .children('input:checked')
+            .each(function () {
+                newValue += $(this).val() + ';'
+            });
+        if (newValue.length) {
+            newValue = newValue.slice(0, newValue.length - 1);
+        }
+
+        if (this.tag.getMetadata('Rekall->Labels') !== newValue) {
+            this.tag.setMetadata('Rekall->Labels', newValue);
+            window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                metadata: "Rekall->Labels",
+                tag: this.tag
+            });
+        }
+    }
+}
+TagPanelInputEditor.prototype.closeEdition = function () {
+    if (this !== this.popupPanelWidget.getCurrentOpenedInput())
+        this.popupPanelWidget.ensureLastOpenedEditionClosed();
+    this.save();
+}
+TagPanelInputEditor.prototype.openEdition = function () {
+    if (this !== this.popupPanelWidget.getCurrentOpenedInput()) {
+        this.popupPanelWidget.ensureLastOpenedEditionClosed();
+        if (this.canEdit) {
+            this.popupPanelWidget.setCurrentOpenedInput(this);
+        }
+    }
+}
+
+
+function PopupPanelWidget(data) {
+    this.canEdit = data?.canEdit ?? function () {
+        return false;
+    };
+    this.currentOpenedInput = undefined;
+}
+
+PopupPanelWidget.prototype.getCurrentOpenedInput = function () {
+    return this.currentOpenedInput;
+}
+PopupPanelWidget.prototype.setCurrentOpenedInput = function (input) {
+    this.currentOpenedInput = input;
+}
+PopupPanelWidget.prototype.ensureLastOpenedEditionClosed = function () {
+    if (this.currentOpenedInput) {
+        this.currentOpenedInput.closeEdition();
+        this.currentOpenedInput = undefined;
+    }
+}
+PopupPanelWidget.prototype.createPopupContent = function (tag) {
+
+    let that = this;
+
+    function createLeftPopup(popupPanelWidget) {
+        let that = this;
+        $('#popupLeft').empty();
+        let bgColorLeft = this.getTagGradientColor();
+        $("#popupLeft").css("background", bgColorLeft);
+        $("#popupLet").attr('keydoc', this.document.key)
+
+        let highlightDiv = $('<div>')
+            .attr('id', 'popupSetHighlight')
+            .text("★ Highlight")
+            .attr("ishighlight", this.getMetadata("Rekall->Highlight")?.length ? "true" : "false")
+            .click(function (event) {
+                event.stopPropagation();
+                let isHL = that.getMetadata("Rekall->Highlight") ? true : false;
+
+                if (isHL) {
+                    that.setMetadata("Rekall->Highlight", "");
+                    $(this).attr("isHighlight", "false").removeClass("selected");
+                    $("#popupEdit").removeClass("highlightPopup");
+                } else {
+                    that.setMetadata("Rekall->Highlight", "true");
+                    $(this).attr("isHighlight", "true").addClass("selected");
+                    $("#popupEdit").addClass("highlightPopup");
+                }
+
+                window.app.rekall.Rekall('pubSub').publish('tag.metadata.updated', {
+                    metadata: "Rekall->Highlight",
+                    tag: that
+                });
+            });
+
+        if (this.getMetadata("Rekall->Highlight")?.length) {
+            highlightDiv
+                .addClass('selected');
+        }
+
+        $('#popupLeft').append(highlightDiv);
+
+        let imageBoxDiv = $('<div>');
+        imageBoxDiv.addClass('popupLeftItem')
+            .attr('id', 'popupImgBox');
+
+        let image = $('<img>');
+        if (this.isMarker()) {
+            image.attr('src', "../shared/css/images/img-note.png");
+        } else {
+            if (this.thumbnail.url) {
+                image.attr("src", this.getDownloadLink() || this.thumbnail.url);
+            } else {
+                let type = this.getMetadata("Rekall->Type");
+                if (type.indexOf("image") > -1) image.attr("src", "../shared/css/images/img-image.png")
+                else if (type.indexOf("pdf") > -1) image.attr("src", "../shared/css/images/img-pdf.png")
+                else if (type.indexOf("audio") > -1) image.attr("src", "../shared/css/images/img-music.png")
+                else if (type.indexOf("vcard") > -1) image.attr("src", "../shared/css/images/img-user.png")
+                else if (type.indexOf("video") > -1) image.attr("src", "../shared/css/images/img-video.png")
+                else if (type.indexOf("msword") > -1) image.attr("src", "../shared/css/images/img-word.png")
+                else if (type.indexOf("link") > -1) image.attr("src", "../shared/css/images/img-link.png")
+                else $("#popupImg").attr("src", "../shared/css/images/img-document.png");
+            }
+
+            image
+                .attr('id', 'popupImg')
+                .click(function (event) {
+                    event.stopPropagation();
+                    if (that.isLink()) {
+                        if (this.getMetadata("Rekall->Link")) window.open(this.getMetadata("Rekall->Link"), '_blank')
+                    } else {
+                        window.open(image.attr('src'), '_blank');
+                    }
+                });
+        }
+
+        imageBoxDiv.append(image);
+
+        let popupTypeDiv = $('<div>');
+        popupTypeDiv
+            .attr('id', 'popupType')
+            .addClass('popupLeftItem')
+            .html(this.getMetadata("Rekall->Type"))
+            .css('color', this.color);
+        imageBoxDiv.append(popupTypeDiv);
+
+        if (this.getMetadata("Rekall->Type")?.length
+            && this.getMetadata("Rekall->Type").split('/')[0] === 'image') {
+            let editAnnotationPic = $('<div>');
+            editAnnotationPic
+                .attr('id', 'editAnnotationPic')
+                .html('edit')
+                .addClass('popupLeftItem');
+            editAnnotationPic.click(function () {
+                window.app.rekall.Rekall('pubSub').publish('image.annotation.edit.open', that);
+            });
+            imageBoxDiv.append(editAnnotationPic);
+
+            let displayOriginalImage = $('<div>');
+            displayOriginalImage
+                .attr('id', 'linkToOriginalImage')
+                .addClass('popupLeftItem')
+                .html('Open original image')
+                .click(function () {
+                    window.open(that.getDownloadLink(true), '_blank');
+                });
+            imageBoxDiv.append(displayOriginalImage);
+        }
+        $('#popupLeft').append(imageBoxDiv);
+
+        if (popupPanelWidget.canEdit()) {
+            let deleteElement = $('<div>');
+            if (this.isMarker()) {
+                deleteElement.html("Delete Note");
+            } else {
+                deleteElement.html("Delete File");
+            }
+            deleteElement
+                .click(function () {
+                    window.app.rekall.Rekall('pubSub').publish('', {
+                        message: "Do you really want to delete this file from the project ?",
+                        buttons: "yesnodelete"
+                    });
+                })
+                .addClass('popupLeftItem')
+                .attr('id', 'popupEditSupprimer');
+            $('#popupLeft').append(deleteElement);
+        }
+    }
+
+    function createRightPopup(popupPanelWidget) {
+        let popupRightTd = $('#popupRight');
+        popupRightTd.empty();
+
+        let commonDataForPanels = {
+            canEdit: popupPanelWidget.canEdit(),
+            tag: this,
+            popupPanelWidget: popupPanelWidget
+        };
+        let projectNameInput = new AnnotationNamePanelInputEditor(commonDataForPanels)
+        projectNameInput.appendInputEditorDiv(popupRightTd);
+
+        let projectAuthorInput = new AuthorPanelInputEditor(commonDataForPanels);
+        projectAuthorInput.appendInputEditorDiv(popupRightTd);
+
+        let tcInput = new TCPanelInputEditor(commonDataForPanels);
+        tcInput.appendInputEditorDiv(popupRightTd);
+
+        let commentPanel = new CommentPanelInputEditor(commonDataForPanels);
+        commentPanel.appendInputEditorDiv(popupRightTd);
+
+        let linkPanel = new LinkPanelInputEditor(commonDataForPanels);
+        linkPanel.appendInputEditorDiv(popupRightTd);
+
+        let speedPanel = new SpeedPanelInputEditor(commonDataForPanels);
+        speedPanel.appendInputEditorDiv(popupRightTd);
+
+        let tagPanel = new TagPanelInputEditor(commonDataForPanels);
+        tagPanel.appendInputEditorDiv(popupRightTd);
+    }
+
+    createRightPopup.call(tag, this);
+    createLeftPopup.call(tag, this);
+    $('#popupEdit').unbind('click');
+    $('#popupEdit').click(function (event) {
+        event.stopPropagation();
+        that.ensureLastOpenedEditionClosed();
+    });
+}
\ No newline at end of file
diff --git a/capsule-prototype/js/TimelinesWidget.js b/capsule-prototype/js/TimelinesWidget.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/capsule-prototype/js/online-rekall/Project.js b/capsule-prototype/js/online-rekall/Project.js
index 8f655f6e5b00dd549e9d1e1a9c4741d3972a0916..7ec93b4ec09d6e1316f416bedc0900be41177ae5 100644
--- a/capsule-prototype/js/online-rekall/Project.js
+++ b/capsule-prototype/js/online-rekall/Project.js
@@ -39,6 +39,7 @@ function Project(url, rekall) {
     });
     this.metadata["Title"] = urlItems[urlItems.length - 1];
     this.rekall = rekall;
+    this.labels = [];
 }
 
 Project.prototype.addDocument = function (key, document) {
@@ -70,7 +71,7 @@ Project.prototype.loadXML = function (xml) {
                 delete this.rekall.project.sources["Files"].documents[rekallDoc.key];
             }
         } else {
-            let rekallDoc = new Document();
+            let rekallDoc = new Document({project: thiss});
             counts.documents++;
             counts.tags++;
             $(this).find('meta').each(function () {
@@ -129,7 +130,8 @@ Project.prototype.timelineUpdate = function () {
 Project.prototype.analyse = function () {
     $('#flattentimeline').html("<div id='flattentimeline_highlight'></div>");
 
-    let parsed_labels = $('input.annotation_labels').toArray().map(i => i.value);
+    // let parsed_labels = $('input.annotation_labels').toArray().map(i => i.value);
+    let parsed_labels = this.labels;
 
     //Analyse
     Tags.reset();
@@ -144,30 +146,13 @@ Project.prototype.analyse = function () {
                 Tags.push(tag);
                 let labels = tag.getMetadata('Rekall->Labels');
                 if (labels && labels != '') {
-                    let input_template = $('input.annotation_labels_template').first();
-                    let html_label_template = $('label.annotation_labels_template').first();
                     let _labels = labels.split(';');
                     for (let i in _labels) {
                         let label = _labels[i];
-                        if (label == '') continue;
+                        if (label.length === 0) continue;
                         if (parsed_labels.indexOf(label) != -1)
                             continue;
                         parsed_labels.push(label);
-                        let inp = input_template.clone();
-                        let id = 'annotation_label_' + parsed_labels.indexOf(label);
-                        inp.attr('id', id);
-                        inp.attr('value', label);
-
-                        let html_label = html_label_template.clone();
-                        html_label.attr('for', id);
-                        html_label.html(label);
-
-                        html_label.show();
-                        html_label.addClass('annotation_labels').removeClass('annotation_labels_template');
-                        inp.addClass('annotation_labels').removeClass('annotation_labels_template');
-
-                        $('#popupLabelsInput').append(inp);
-                        $('#popupLabelsInput').append(html_label);
                     }
                 }
             }
@@ -238,130 +223,7 @@ Project.prototype.analyse = function () {
             let thumbUrl = Utils.getPreviewPath(tag);
             tag.thumbnail = {url: thumbUrl, tag: tag};
 
-
-            if ((tag.getMetadata("Rekall->Highlight") != undefined) && (tag.getMetadata("Rekall->Highlight") != "")) {
-
-                //Dom
-                $('#flattentimeline').append(function () {
-                    let styleColor = "background-color: " + tag.color + ";";
-                    let textColor = "color: " + tag.color + ";";
-
-                    let colorTransp = "";
-
-                    let styleColor2 = styleColor;
-                    let styleImage = "";
-                    if (tag.thumbnail.url != undefined) {
-
-                        styleImage = "background-image: -webkit-linear-gradient(right bottom,  rgba(20,46,51,.60) 0%,rgba(20,46,51,.90) 100%), url(" + tag.thumbnail.url + "); background-image: -moz-linear-gradient(right bottom,  rgba(20,46,51,.60) 0%,rgba(20,46,51,.90) 100%), url(" + tag.thumbnail.url + "); background-image: -o-linear-gradient(right bottom,  rgba(20,46,51,.60) 0%,rgba(20,46,51,.90) 100%), url(" + tag.thumbnail.url + ");";
-                    } else styleImage = "background-color: " + tag.color + "; background-image: -webkit-linear-gradient(right bottom, rgba(20,46,51,.5) 0%,rgba(20,46,51,.8) 100%); background-image: -moz-linear-gradient(right bottom, rgba(20,46,51,.5) 0%,rgba(20,46,51,.8) 100%); background-image: -o-linear-gradient(right bottom, rgba(20,46,51,.5) 0%,rgba(20,46,51,.8) 100%);";//styleColor.replace(/rgb/g, "rgba").replace(/\)/g, ",.85)");//"background-color: rgba(255,255,255,.25)";
-
-                    let icnType = "";
-                    let tmpType = tag.getMetadata("Rekall->Type");
-                    if (tmpType.indexOf("application/msword") >= 0) icnType = "background-image:url(css/images/icn-word.png);";
-                    else if (tmpType.indexOf("application/pdf") >= 0) icnType = "background-image:url(css/images/icn-pdf.png);";
-                    else if (tmpType.indexOf("application/") >= 0) icnType = "background-image:url(css/images/icn-document.png);";
-                    else if (tmpType.indexOf("audio/") >= 0) icnType = "background-image:url(css/images/icn-music.png);";
-                    else if (tmpType.indexOf("image/") >= 0) icnType = "background-image:url(css/images/icn-image.png);";
-                    else if (tmpType.indexOf("text/x-vcard") >= 0) icnType = "background-image:url(css/images/icn-user.png);";
-                    else if (tmpType.indexOf("text/") >= 0) icnType = "background-image:url(css/images/icn-document.png);";
-                    else if (tmpType.indexOf("video/") >= 0) icnType = "background-image:url(css/images/icn-video.png);";
-
-                    let typeTxt = tmpType.split("/")[1].replace(/marker/g, "note");
-
-                    let htmlHighlight = "";
-                    htmlHighlight += "<div draggable=true class='flattentimeline_item flattentimeline_highlightitem' style='" + colorTransp + " " + styleImage + "'>";
-                    htmlHighlight += "<div class='flattentimeline_title' 		style='" + textColor + "' title='" + tag.getMetadata("Rekall->Name") + "'>" + tag.getMetadata("Rekall->Name") + "</div>";
-
-
-                    if (tag.getMetadata("Rekall->Comments") != "") {
-
-                        let tmpComments = tag.getMetadata("Rekall->Comments");
-                        if (tmpComments.length > 150) {
-                            tmpComments = tmpComments.substring(0, 150) + "...";
-                        }
-
-                        let tmpcount = 0;
-                        let tmpIndex = tmpComments.indexOf("<br/>");
-                        while ((tmpcount < 3) && (tmpIndex != -1)) {
-                            tmpcount++;
-                            tmpIndex = tmpComments.indexOf("<br/>", tmpIndex + 1);
-                        }
-                        if (tmpIndex != -1) {
-                            tmpComments = tmpComments.substring(0, tmpIndex) + "...";
-                        }
-                        htmlHighlight += "<div class='flattentimeline_description'>" + tmpComments + "</div>";
-                    }
-
-                    if (tag.getMetadata("Rekall->Author") != "") htmlHighlight += "<div class='flattentimeline_author'>" + tag.getMetadata("Rekall->Author") + "</div>";
-
-
-                    htmlHighlight += "<div class='flattentimeline_typeTxt'		>" + typeTxt + "</div>";
-                    htmlHighlight += "<div class='flattentimeline_opacifiant' style='" + styleColor2 + "'></div>";
-                    htmlHighlight += "</div>";
-
-                    tag.flattenTimelineDom = $(htmlHighlight);
-                    tag.flattenTimelineDom.click(function (event) {
-                        tag.openPopupEdit();
-                    });
-                    tag.flattenTimelineDom.on({
-                        dragstart: function (event) {
-                            event.dataTransfer.setData("key", tag.document.key);
-                            event.dataTransfer.setData("version", tag.version);
-                        }
-                    });
-
-                    return tag.flattenTimelineDom;
-
-                });
-
-            } else {
-
-                //Dom
-                $('#flattentimeline').append(function () {
-                    let styleColor = "background-color: " + tag.color + ";";
-                    let textColor2 = "color: rgba(255,255,255,.8)";
-
-                    let styleColor2 = styleColor;
-                    let styleImage = "";
-                    if (tag.thumbnail.url != undefined) {
-                        styleImage = "background-image: url(" + encodeURI(tag.thumbnail.url) + ");";//" opacity: 0.5;";
-                    } else styleImage = "background-color: rgba(255,255,255,.25)";
-
-                    let icnType = "";
-                    let tmpType = tag.getMetadata("Rekall->Type");
-                    if (tmpType.indexOf("application/msword") >= 0) icnType = "background-image:url(css/images/icn-word.png);";
-                    else if (tmpType.indexOf("application/pdf") >= 0) icnType = "background-image:url(css/images/icn-pdf.png);";
-                    else if (tmpType.indexOf("application/") >= 0) icnType = "background-image:url(css/images/icn-document.png);";
-                    else if (tmpType.indexOf("audio/") >= 0) icnType = "background-image:url(css/images/icn-music.png);";
-                    else if (tmpType.indexOf("image/") >= 0) icnType = "background-image:url(css/images/icn-image.png);";
-                    else if (tmpType.indexOf("text/x-vcard") >= 0) icnType = "background-image:url(css/images/icn-user.png);";
-                    else if (tmpType.indexOf("text/") >= 0) icnType = "background-image:url(css/images/icn-document.png);";
-                    else if (tmpType.indexOf("video/") >= 0) icnType = "background-image:url(css/images/icn-video.png);";
-
-
-                    let html = "";
-                    html += "<div draggable=true class='flattentimeline_item' title='" + tag.getMetadata("Rekall->Comments") + "' >";
-                    html += "<div class='flattentimeline_image'      style='" + styleImage + "'></div>";
-                    html += "<div class='flattentimeline_opacifiant' style='" + styleColor2 + "'></div>";
-                    html += "<div class='flattentimeline_type'		style='" + icnType + "' title='" + tmpType + "'></div>";
-                    html += "<div class='flattentimeline_title' 		style='" + textColor2 + "' title='" + tag.getMetadata("Rekall->Name") + "'>" + tag.getMetadata("Rekall->Name") + "</div>";
-                    html += "</div>";
-
-                    tag.flattenTimelineDom = $(html);
-                    tag.flattenTimelineDom.click(function (event) {
-                        tag.openPopupEdit();
-                    });
-                    tag.flattenTimelineDom.on({
-                        dragstart: function (event) {
-                            event.dataTransfer.setData("key", tag.document.key);
-                            event.dataTransfer.setData("version", tag.version);
-                        }
-                    });
-
-                    return tag.flattenTimelineDom;
-
-                });
-            }
+            $('#flattentimeline').append(tag.createTimelineDiv.call(tag));
 
             //Ouverture du popup
             if ((Tag.keyToOpenAfterLoading != undefined) && (tag.document.key == Tag.keyToOpenAfterLoading)) {
diff --git a/capsule-prototype/js/online-rekall/Tag.js b/capsule-prototype/js/online-rekall/Tag.js
index f6cd7fe6bfd0195d6e861e3b3cee41cf94f72d0b..155367fce439d57a4deb41231ea6d15d1fc85368 100644
--- a/capsule-prototype/js/online-rekall/Tag.js
+++ b/capsule-prototype/js/online-rekall/Tag.js
@@ -23,125 +23,234 @@
 */
 
 function Tag(document) {
-	this.document         = document;
-	this.documentOriginal = this.document;
-	this.version          = document.currentVersion;
-	this.versionOriginal  = this.version;
-	this.timeStart = 0;
-	this.timeEnd   = 1;
-	this.color     = "#FFFFFF";
-	this.shown     = false;
+    this.document = document;
+    this.documentOriginal = this.document;
+    this.version = document.currentVersion;
+    this.versionOriginal = this.version;
+    this.timeStart = 0;
+    this.timeEnd = 1;
+    this.color = "#FFFFFF";
+    this.shown = false;
+    this.thumbnail = undefined;
 }
-Tag.keyToOpenAfterLoading = undefined;
 
+Tag.keyToOpenAfterLoading = undefined;
 
-Tag.prototype.getMetadata = function(metadataKey, metadataValue) {
-	return this.document.getMetadata(metadataKey, this.version);
+Tag.prototype.getMetadata = function (metadataKey, metadataValue) {
+    return this.document.getMetadata(metadataKey, this.version);
 }
-Tag.prototype.setMetadata = function(metadataKey, metadataValue) {
-	return this.document.setMetadata(metadataKey, metadataValue, this.version);
+Tag.prototype.setMetadata = function (metadataKey, metadataValue) {
+    return this.document.setMetadata(metadataKey, metadataValue, this.version);
 }
-Tag.prototype.getMetadatas = function() {
-	return this.document.getMetadatas(this.version);
+Tag.prototype.getMetadatas = function () {
+    return this.document.getMetadatas(this.version);
 }
-Tag.prototype.isVideoOrAudio = function() {
-	return this.document.isVideoOrAudio(this.version); 
+Tag.prototype.isVideoOrAudio = function () {
+    return this.document.isVideoOrAudio(this.version);
 }
-Tag.prototype.isAudio = function() {
-	return this.document.isAudio(this.version); 
+Tag.prototype.isAudio = function () {
+    return this.document.isAudio(this.version);
 }
-Tag.prototype.isVideo = function() {
-	return this.document.isVideo(this.version); 
+Tag.prototype.isVideo = function () {
+    return this.document.isVideo(this.version);
 }
-Tag.prototype.isMarker = function() {
-	return this.document.isMarker(this.version); 
+Tag.prototype.isMarker = function () {
+    return this.document.isMarker(this.version);
 }
-Tag.prototype.isImage = function() {
-	return this.document.isImage(this.version); 
+Tag.prototype.isImage = function () {
+    return this.document.isImage(this.version);
 }
-Tag.prototype.isLink = function() {
-	return this.document.isLink(this.version); 
+Tag.prototype.isLink = function () {
+    return this.document.isLink(this.version);
 }
 
+Tag.prototype.getTagGradientColor = function() {
+    var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;  // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
+    var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
+    var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;   // At least Safari 3+: "[object HTMLElementConstructor]"
+    var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
+    var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
 
-Tag.prototype.getTimeStart = function() {
-	return this.timeStart;
+    if (isOpera) {
+        return "-o-linear-gradient(right bottom,  rgba(20,46,51,1) 0%, " + this.color + " 100%)";
+    }
+    if (isFirefox) {
+        return "-moz-linear-gradient(right bottom,  rgba(20,46,51,1) 0%, " + this.color + " 100%)";
+    }
+    if ((isSafari) || (isChrome)) {
+        return "-webkit-linear-gradient(right bottom,  rgba(20,46,51,1) 0%, " + this.color + " 100%)";
+    }
 }
-Tag.prototype.getTimeEnd = function() {
-	return this.timeEnd;
+Tag.prototype.getTimeStart = function () {
+    return this.timeStart;
 }
-Tag.prototype.setTimeStart = function(val) {
-	if(!isNaN(val))
-		this.timeStart = val;
+Tag.prototype.getTimeEnd = function () {
+    return this.timeEnd;
 }
-Tag.prototype.setTimeEnd = function(val) {
-	if(!isNaN(val))
-		this.timeEnd = val;
+Tag.prototype.setTimeStart = function (val) {
+    if (!isNaN(val))
+        this.timeStart = val;
 }
-
-
-
-Tag.prototype.isGoodVersion = function() {
-	return this.version == this.document.goodVersion;
+Tag.prototype.setTimeEnd = function (val) {
+    if (!isNaN(val))
+        this.timeEnd = val;
 }
-
-
-Tag.prototype.openFile = function() {
-	return this.document.openFile();
+Tag.prototype.isGoodVersion = function () {
+    return this.version == this.document.goodVersion;
+}
+Tag.prototype.openFile = function () {
+    return this.document.openFile();
+}
+Tag.prototype.openFinder = function () {
+    return this.document.openFinder();
 }
-Tag.prototype.openFinder = function() {
-	return this.document.openFinder();
+Tag.prototype.openQuickLook = function () {
+    return this.document.openQuickLook();
 }
-Tag.prototype.openQuickLook = function() {
-	return this.document.openQuickLook();
+Tag.prototype.downloadFile = function () {
+    return this.document.downloadFile();
 }
-Tag.prototype.downloadFile = function() {
-	return this.document.downloadFile();
+Tag.prototype.getDownloadLink = function (original = false) {
+    return this.document.getDownloadLink(original);
 }
-Tag.prototype.getDownloadLink = function(original = false) {
-  return this.document.getDownloadLink(original);
+Tag.prototype.getFileName = function () {
+    return this.document.getFileName();
 }
-Tag.prototype.getFileName = function() {
-  return this.document.getFileName();
+Tag.prototype.openBrowser = function () {
+    return this.document.openBrowser();
+}
+Tag.prototype.openPopupEdit = function () {
+    fillPopupEdit(this);
+}
+Tag.prototype.update = function (color, strong) {
+    if (color != undefined) {
+        this.colorRaw = color;
+        this.color = color.toString();
+        this.isMarkerCache = this.isMarker();
+    }
+    if (this.color == undefined)
+        this.color = "#000000";
+}
+Tag.prototype.createTimelineDiv = function () {
+    let that = this;
+    let styleColor = "background-color: " + this.color + ";";
+    let textColor2 = "color: rgba(255,255,255,.8)";
+
+    let styleColor2 = styleColor;
+    let styleImage = "";
+    if (this.thumbnail.url != undefined) {
+        styleImage = "background-image: url(" + encodeURI(this.thumbnail.url) + ");";
+    } else styleImage = "background-color: rgba(255,255,255,.25)";
+
+    let icnType = "";
+    let tmpType = this.getMetadata("Rekall->Type");
+    if (tmpType.indexOf("application/msword") >= 0) icnType = "background-image:url(css/images/icn-word.png);";
+    else if (tmpType.indexOf("application/pdf") >= 0) icnType = "background-image:url(css/images/icn-pdf.png);";
+    else if (tmpType.indexOf("application/") >= 0) icnType = "background-image:url(css/images/icn-document.png);";
+    else if (tmpType.indexOf("audio/") >= 0) icnType = "background-image:url(css/images/icn-music.png);";
+    else if (tmpType.indexOf("image/") >= 0) icnType = "background-image:url(css/images/icn-image.png);";
+    else if (tmpType.indexOf("text/x-vcard") >= 0) icnType = "background-image:url(css/images/icn-user.png);";
+    else if (tmpType.indexOf("text/") >= 0) icnType = "background-image:url(css/images/icn-document.png);";
+    else if (tmpType.indexOf("video/") >= 0) icnType = "background-image:url(css/images/icn-video.png);";
+
+
+    let html = "";
+    html += "<div draggable=true class='flattentimeline_item' title='" + this.getMetadata("Rekall->Comments") + "' >";
+    html += "<div class='flattentimeline_image'      style='" + styleImage + "'></div>";
+    html += "<div class='flattentimeline_opacifiant' style='" + styleColor2 + "'></div>";
+    html += "<div class='flattentimeline_type'		style='" + icnType + "' title='" + tmpType + "'></div>";
+    html += "<div class='flattentimeline_title' 		style='" + textColor2 + "' title='" + this.getMetadata("Rekall->Name") + "'>" + this.getMetadata("Rekall->Name") + "</div>";
+    html += "</div>";
+
+    this.flattenTimelineDom = $(html);
+    this.flattenTimelineDom.click(function () {
+        that.openPopupEdit();
+    });
+    this.flattenTimelineDom.on({
+        dragstart: function (event) {
+            event.dataTransfer.setData("key", that.document.key);
+            event.dataTransfer.setData("version", that.version);
+        }
+    });
+
+    return this.flattenTimelineDom;
+
 }
-Tag.prototype.openBrowser = function() {
-	return this.document.openBrowser();
-}   
-Tag.prototype.openPopupEdit = function() {
-	fillPopupEdit(this);  
+
+function HighLightedTag(data) {
+    Tag.call(this, data.Document);
 }
 
-Tag.prototype.update = function(color, strong) {
-	if(color != undefined) {
-		this.colorRaw  = color;
-		this.color     = color.toString();
-		
-		this.isMarkerCache = this.isMarker();
-		/*
-		if(this.isMarkerCache) {
-			this.visuel.rect.setCornerRadius(0);
-		}
-		else {
-			this.visuel.rect.setCornerRadius(Tag.tagHeight/3);
-		}
-		*/
-	}
-	if(this.color == undefined)
-		this.color = "#000000";
+HighLightedTag.prototype = Object.create(Tag.prototype);
+HighLightedTag.prototype.createTimelineDiv = function () {
+    let that = this;
+    let styleColor = "background-color: " + this.color + ";";
+    let textColor = "color: " + this.color + ";";
+
+    let colorTransp = "";
+
+    let styleColor2 = styleColor;
+    let styleImage = "";
+    if (this.thumbnail?.url) {
+        styleImage = "background-image: -webkit-linear-gradient(right bottom,  rgba(20,46,51,.60) 0%,rgba(20,46,51,.90) 100%), url(" + this.thumbnail.url + "); background-image: -moz-linear-gradient(right bottom,  rgba(20,46,51,.60) 0%,rgba(20,46,51,.90) 100%), url(" + this.thumbnail.url + "); background-image: -o-linear-gradient(right bottom,  rgba(20,46,51,.60) 0%,rgba(20,46,51,.90) 100%), url(" + this.thumbnail.url + ");";
+    } else {
+        styleImage = "background-color: " + this.color + "; background-image: -webkit-linear-gradient(right bottom, rgba(20,46,51,.5) 0%,rgba(20,46,51,.8) 100%); background-image: -moz-linear-gradient(right bottom, rgba(20,46,51,.5) 0%,rgba(20,46,51,.8) 100%); background-image: -o-linear-gradient(right bottom, rgba(20,46,51,.5) 0%,rgba(20,46,51,.8) 100%);";
+    }
+
+    let tmpType = this.getMetadata("Rekall->Type");
+    let typeTxt = tmpType.split("/")[1].replace(/marker/g, "note");
+
+    let htmlHighlight = "";
+    htmlHighlight += "<div draggable=true class='flattentimeline_item flattentimeline_highlightitem' style='" + colorTransp + " " + styleImage + "'>";
+    htmlHighlight += "<div class='flattentimeline_title' 		style='" + textColor + "' title='" + this.getMetadata("Rekall->Name") + "'>" + this.getMetadata("Rekall->Name") + "</div>";
+
+
+    if (this.getMetadata("Rekall->Comments") != "") {
+
+        let tmpComments = this.getMetadata("Rekall->Comments");
+        if (tmpComments.length > 150) {
+            tmpComments = tmpComments.substring(0, 150) + "...";
+        }
 
-	var fillColor   = '';
-	var strokeColor = '';
-	var strokeWidth = 0;
-	var opacity = 1;
-		
-	if(this.isGoodVersion()) {
-		fillColor   = this.color;
-		strokeWidth = 0;
-		strokeColor = "";
-	}
-	else {
-		fillColor   = tinycolor(this.colorRaw.toString()).setAlpha(0.1).toString();
-		strokeColor = this.color;
-		strokeWidth = 0.8;
-	}
+        let tmpcount = 0;
+        let tmpIndex = tmpComments.indexOf("<br/>");
+        while ((tmpcount < 3) && (tmpIndex != -1)) {
+            tmpcount++;
+            tmpIndex = tmpComments.indexOf("<br/>", tmpIndex + 1);
+        }
+        if (tmpIndex != -1) {
+            tmpComments = tmpComments.substring(0, tmpIndex) + "...";
+        }
+        htmlHighlight += "<div class='flattentimeline_description'>" + tmpComments + "</div>";
+    }
+
+    if (this.getMetadata("Rekall->Author") != "") htmlHighlight += "<div class='flattentimeline_author'>" + this.getMetadata("Rekall->Author") + "</div>";
+
+
+    htmlHighlight += "<div class='flattentimeline_typeTxt'		>" + typeTxt + "</div>";
+    htmlHighlight += "<div class='flattentimeline_opacifiant' style='" + styleColor2 + "'></div>";
+    htmlHighlight += "</div>";
+
+    this.flattenTimelineDom = $(htmlHighlight);
+    this.flattenTimelineDom.click(function () {
+        that.openPopupEdit();
+    });
+    this.flattenTimelineDom.on({
+        dragstart: function (event) {
+            event.dataTransfer.setData("key", that.document.key);
+            event.dataTransfer.setData("version", that.version);
+        }
+    });
+
+    return this.flattenTimelineDom;
 }
+
+
+const TagFactory = function (document) {
+
+    if (document.getMetadata("Rekall->Highlight", document.currentVersion)) {
+        return new HighLightedTag({document: document})
+    }
+
+    return new Tag(document);
+}
\ No newline at end of file
diff --git a/capsule-prototype/js/online-script.js b/capsule-prototype/js/online-script.js
index ddda241364803cd5d8ff99fffe23fa3ebde655d1..3ec267af4b319f051c2e51e3a33d58eff8a038e4 100644
--- a/capsule-prototype/js/online-script.js
+++ b/capsule-prototype/js/online-script.js
@@ -1,6 +1,7 @@
 var rekall = new Rekall();
 var rekall_common = new Object();
 var pubSub = null;
+var popupPanel = new PopupPanelWidget({ canEdit: () => rekall_common.owner.canEdit });
 
 window.onload = function() {
 	pubSub = window.top.PubSub;
@@ -15,9 +16,10 @@ window.onload = function() {
 	pubSub.subscribe('alert', openAlertWrapper);
 	pubSub.subscribe('roulette.terminated', rouletteEnd);
 	pubSub.subscribe('roulette.started', rouletteStart);
-};
+	pubSub.subscribe('tag.metadata.updated', onMetaFromDomUpdated);
+	pubSub.subscribe('tag.tc.updated', onTcUpdated);
+	pubSub.subscribe('image.annotation.edit.open', openImageEdition);
 
-$(document).ready(function() {
 	window.app.rekall.Rekall('init', {
 		Rekall: rekall
 	});
@@ -132,53 +134,53 @@ $(document).ready(function() {
 		var tmp = shareLink();
 		openAlert("input",tmp);
 	});
-});
+};
 
 function setEditionControls() {
 
-  $('#new_annotation_label').keypress(function(event) {
-    var keycode = (event.keyCode ? event.keyCode : event.which);
-    if (keycode != 13) {
-      return;
-    }
-    var label = $('#new_annotation_label').val();
-    var input = $('input.annotation_labels_template').first().clone();
-    var html_label = $('label.annotation_labels_template').first().clone();
-    var id = 'annotation_label_' + Math.floor((Math.random()*1000));
-
-    input.attr('name', 'annotation_labels');
-    input.attr('checked', 'true');
-    input.attr('id', id);
-    input.attr('value', label);
-
-    html_label.attr('for', id);
-    html_label.html(label);
-
-    html_label.show();
-    html_label.addClass('annotation_labels').removeClass('annotation_labels_template');
-    input.addClass('annotation_labels').removeClass('annotation_labels_template');
-
-    $('#popupLabelsInput').append(input);
-    $('#popupLabelsInput').append(html_label);
-    $('#new_annotation_label').val('');
-  })
+	$('#new_annotation_label').keypress(function (event) {
+		var keycode = (event.keyCode ? event.keyCode : event.which);
+		if (keycode != 13) {
+			return;
+		}
+		var label = $('#new_annotation_label').val();
+		var input = $('input.annotation_labels_template').first().clone();
+		var html_label = $('label.annotation_labels_template').first().clone();
+		var id = 'annotation_label_' + Math.floor((Math.random() * 1000));
+
+		input.attr('name', 'annotation_labels');
+		input.attr('checked', 'true');
+		input.attr('id', id);
+		input.attr('value', label);
+
+		html_label.attr('for', id);
+		html_label.html(label);
+
+		html_label.show();
+		html_label.addClass('annotation_labels').removeClass('annotation_labels_template');
+		input.addClass('annotation_labels').removeClass('annotation_labels_template');
+
+		$('#popupLabelsInput').append(input);
+		$('#popupLabelsInput').append(html_label);
+		$('#new_annotation_label').val('');
+	})
 
 	//Drag&drop files
 	$(document).on({
-		dragenter: function(event) {
+		dragenter: function (event) {
 			event.stopImmediatePropagation();
 			event.preventDefault();
 		},
-		dragleave: function(event) {
+		dragleave: function (event) {
 			event.stopImmediatePropagation();
 			event.preventDefault();
 		},
-		dragover: function(event) {
+		dragover: function (event) {
 			event.stopImmediatePropagation();
 			event.preventDefault();
 		},
-		drop: function(event) {
-			if(event.originalEvent.dataTransfer.files.length) {
+		drop: function (event) {
+			if (event.originalEvent.dataTransfer.files.length) {
 				event.stopImmediatePropagation();
 				event.preventDefault();
 				uploadFiles(event.originalEvent.dataTransfer.files);
@@ -187,18 +189,25 @@ function setEditionControls() {
 	});
 
 	$("#flattentimeline").on({
-		dragenter: function(event) { /*$(".flattentimeline_item").removeClass("draggable").addClass("drag");*/ },
-		dragleave: function(event) {  $("#flattentimeline").removeClass("draggable").removeClass("drag"); },
-		dragover: function(event) { $("#flattentimeline").removeClass("draggable").addClass("drag"); },
-		drop: function(event) { $("#flattentimeline").removeClass("draggable").removeClass("drag");  }
+		dragenter: function (event) { /*$(".flattentimeline_item").removeClass("draggable").addClass("drag");*/
+		},
+		dragleave: function (event) {
+			$("#flattentimeline").removeClass("draggable").removeClass("drag");
+		},
+		dragover: function (event) {
+			$("#flattentimeline").removeClass("draggable").addClass("drag");
+		},
+		drop: function (event) {
+			$("#flattentimeline").removeClass("draggable").removeClass("drag");
+		}
 	});
 
-	$("#left_menu_item_settings").click(function(event){
+	$("#left_menu_item_settings").click(function (event) {
 		event.stopPropagation();
 		rekall.timeline.pause();
 		$("#popupSettingsSpace").show();
 
-		if(window.app.rekall.Rekall('projectName') && window.app.rekall.Rekall('projectName') != "") {
+		if (window.app.rekall.Rekall('projectName') && window.app.rekall.Rekall('projectName') != "") {
 			$("#popupSettingsTitle").html(window.app.rekall.Rekall('projectName')).removeClass("empty");
 			$("#popupSettingsTitleLabel").show();
 		} else {
@@ -206,7 +215,7 @@ function setEditionControls() {
 			$("#popupSettingsTitleLabel").hide();
 		}
 
-		if(rekall.project.metadata["Author"]!="") {
+		if (rekall.project.metadata["Author"] != "") {
 			$("#popupSettingsAuthor").html(rekall.project.metadata["Author"]).removeClass("empty");
 			$("#popupSettingsAuthorLabel").show();
 		} else {
@@ -214,7 +223,7 @@ function setEditionControls() {
 			$("#popupSettingsAuthorLabel").hide();
 		}
 
-		if(rekall.project.metadata["Email"]!="") {
+		if (rekall.project.metadata["Email"] != "") {
 			$("#popupSettingsEmail").html(rekall.project.metadata["Email"]).removeClass("empty");
 			$("#popupSettingsEmailLabel").show();
 		} else {
@@ -222,7 +231,7 @@ function setEditionControls() {
 			$("#popupSettingsEmailLabel").hide();
 		}
 
-		if(rekall.project.metadata["Comments"]!="") {
+		if (rekall.project.metadata["Comments"] != "") {
 			$("#popupSettingsCredits").html(rekall.project.metadata["Comments"].replace(/\n/gi, "<br/>")).removeClass("empty");
 			$("#popupSettingsCreditsLabel").show();
 		} else {
@@ -230,119 +239,123 @@ function setEditionControls() {
 			$("#popupSettingsCreditsLabel").hide();
 		}
 
-		if(rekall_common.owner.canEdit) {
+		if (rekall_common.owner.canEdit) {
 			$(".empty").show();
 		}
 	});
 
-	$("#popupSettingsTitleDiv").click(function(event){
+	$("#popupSettingsTitleDiv").click(function (event) {
 		event.stopPropagation();
 		closeSettingsInputs();
 		$(this).hide();
-		if(!$("#popupSettingsTitle").hasClass("empty")) $("#popupSettingsTitleInput").val($("#popupSettingsTitle").html());
+		if (!$("#popupSettingsTitle").hasClass("empty")) $("#popupSettingsTitleInput").val($("#popupSettingsTitle").html());
 		$("#popupSettingsTitleInput").show().focus();
 	});
-	$("#popupSettingsAuthorDiv").click(function(event){
+	$("#popupSettingsAuthorDiv").click(function (event) {
 		event.stopPropagation();
 		closeSettingsInputs();
 		$(this).hide();
-		if(!$("#popupSettingsAuthor").hasClass("empty")) $("#popupSettingsAuthorInput").val($("#popupSettingsAuthor").html());
+		if (!$("#popupSettingsAuthor").hasClass("empty")) $("#popupSettingsAuthorInput").val($("#popupSettingsAuthor").html());
 		$("#popupSettingsAuthorInput").show().focus();
 	});
-	$("#popupSettingsEmailDiv").click(function(event){
+	$("#popupSettingsEmailDiv").click(function (event) {
 		event.stopPropagation();
 		closeSettingsInputs();
 		$(this).hide();
-		if(!$("#popupSettingsEmail").hasClass("empty")) $("#popupSettingsEmailInput").val($("#popupSettingsEmail").html());
+		if (!$("#popupSettingsEmail").hasClass("empty")) $("#popupSettingsEmailInput").val($("#popupSettingsEmail").html());
 		$("#popupSettingsEmailInput").show().focus();
 	});
-	$("#popupSettingsCreditsDiv").click(function(event){
+	$("#popupSettingsCreditsDiv").click(function (event) {
 		event.stopPropagation();
 		closeSettingsInputs();
 		$(this).hide();
-		if(!$("#popupSettingsCredits").hasClass("empty")) $("#popupSettingsCreditsInput").val($("#popupSettingsCredits").html());
+		if (!$("#popupSettingsCredits").hasClass("empty")) $("#popupSettingsCreditsInput").val($("#popupSettingsCredits").html());
 		$("#popupSettingsCreditsInput").show().focus();
 	});
 
-	$(".popupSettingsInput").keyup(function(event){
+	$(".popupSettingsInput").keyup(function (event) {
 		event.stopPropagation();
-		if(event.which == 13) {
+		if (event.which == 13) {
 			closeSettingsInputs();
 		}
 	});
 
-	$(".popupSettingsInput").click(function(event){
-			event.stopPropagation();
+	$(".popupSettingsInput").click(function (event) {
+		event.stopPropagation();
 	});
 
-	$("#popupSettingsCreditsInput").unbind( "keyup" );
-	$("#popupSettingsCreditsInput").keyup(function(event){
+	$("#popupSettingsCreditsInput").unbind("keyup");
+	$("#popupSettingsCreditsInput").keyup(function (event) {
 		event.stopPropagation();
 
 		var isEnter = false;
 		if (event.key !== undefined) {
 			if (event.key === 'Enter' && event.altKey) {
-			} else if(event.key === 'Enter') isEnter = true;
+			} else if (event.key === 'Enter') isEnter = true;
 		} else if (event.keyIdentifier !== undefined) {
 			if (event.keyIdentifier === "Enter" && event.altKey) {
-			} else if(event.keyIdentifier === 'Enter') isEnter = true;
+			} else if (event.keyIdentifier === 'Enter') isEnter = true;
 		} else if (event.keyCode !== undefined) {
 			if (event.keyCode === 13 && event.altKey) {
-			} else if(event.keyCode === 13) isEnter = true;
+			} else if (event.keyCode === 13) isEnter = true;
 		}
 
-		if(isEnter == true) {
+		if (isEnter == true) {
 			closeSettingsInputs();
 		}
 	});
 
-	$("#popupSettings").click(function(event){
+	$("#popupSettings").click(function (event) {
 		event.stopPropagation();
 		closeSettingsInputs();
 	});
 
-	$("#popupSettingsSpace").click(function(event){
+	$("#popupSettingsSpace").click(function (event) {
 		event.stopPropagation();
 		closeSettingsPopup();
 	});
 
-	$("#left_menu_item_preview").click(function(event){
+	$("#left_menu_item_preview").click(function (event) {
 		event.stopPropagation();
 		window.open(window.app.rekall.Rekall('getUrl', 'projectPreview'), '_blank');
 	});
 
-	$("#popupSettingsBtnDownloadXml").click(function(event){
+	$("#popupSettingsBtnDownloadXml").click(function (event) {
 		event.stopPropagation();
 		window.open("php/project.php?downloadXML=1", '_self');
 	});
-	$("#popupSettingsBtnDelete").click(function(event){
+	$("#popupSettingsBtnDelete").click(function (event) {
 		event.stopPropagation();
 		openAlert("Do you really want to delete this project ?", "yesnodeleteproject");
 	});
 
-	$("#btn_add_note").click(function(event){
+	$("#btn_add_note").click(function (event) {
 		event.stopPropagation();
 		rekall.timeline.pause();
 		uploadFiles(["New note"]);
 	});
 
-	$("#btn_add_file").mousedown(function(event) {
+	$("#btn_add_file").mousedown(function (event) {
 		rekall.timeline.pause();
 		$("#left_menu_item_btn_addfile").click();
 	});
-	$("#left_menu_item_btn_addfile").change(function(event){
+	$("#left_menu_item_btn_addfile").change(function (event) {
 		event.stopPropagation();
 		uploadFiles($("#left_menu_item_btn_addfile").get(0).files);
 	});
 
-	$("#btn_add_paste").click(function(event) { pubSub.publish('open_paste_modal'); });
-	$("#paste_modal button.cancel").click(function(event) { pubSub.publish('close_paste_modal'); });
+	$("#btn_add_paste").click(function (event) {
+		pubSub.publish('open_paste_modal');
+	});
+	$("#paste_modal button.cancel").click(function (event) {
+		pubSub.publish('close_paste_modal');
+	});
 
-	$("#paste_modal_content").on("paste", function(event) {
+	$("#paste_modal_content").on("paste", function (event) {
 		$('#paste_modal_content').empty();
 	});
 
-	$("#paste_modal button.validate").click(function(event) {
+	$("#paste_modal button.validate").click(function (event) {
 		var img = $("#paste_modal img");
 		if (img.length < 1)
 			return;
@@ -353,78 +366,80 @@ function setEditionControls() {
 		var n = b64data.length;
 		var uar = new Uint8Array(n);
 		while (n--) uar[n] = bin_str.charCodeAt(n);
-		var file = new File([uar], 'pasted_' + Math.floor(Math.random()*100000) + '.' + subtype, {type: type+'/'+subtype});
+		var file = new File([uar], 'pasted_' + Math.floor(Math.random() * 100000) + '.' + subtype, {type: type + '/' + subtype});
 		$('#left_menu_item_btn_addfile').files += file;
 		uploadFiles([file]);
 		pubSub.publish('close_paste_modal');
 	});
 
-	$("#btn_add_link").click(function(event){
+	$("#btn_add_link").click(function (event) {
 		event.stopPropagation();
 		rekall.timeline.pause();
 		$("#popupAddLinkSpace").show();
 		$("#popupAddLinkInput").focus();
 	});
 
-	$("#popupAddLinkButtonCancel").click(function(event){
+	$("#popupAddLinkButtonCancel").click(function (event) {
 		event.stopPropagation();
 		closeAddLinkPopup();
 	});
-	$("#popupAddLinkSpace").click(function(event){
+	$("#popupAddLinkSpace").click(function (event) {
 		event.stopPropagation();
 		closeAddLinkPopup();
 	});
 
-	$("#popupAddLinkButtonOk").click(function(event){
+	$("#popupAddLinkButtonOk").click(function (event) {
 		var myLink = $("#popupAddLinkInput").val();
 		addLink(myLink);
 	});
 
-	$("#popupAddLinkInput").keyup(function(event){
+	$("#popupAddLinkInput").keyup(function (event) {
 		event.stopPropagation();
-		if(event.which == 13) {
+		if (event.which == 13) {
 			var myLink = $("#popupAddLinkInput").val();
 			addLink(myLink);
 		}
 	});
 
-	$('#tab_selector_form').change(function(event) { pubSub.publish(event.target.value) });
+	$('#tab_selector_form').change(function (event) {
+		pubSub.publish(event.target.value)
+	});
 
-	$("#popupEdit").click(function(event){
+	$("#popupEdit").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 	});
 
-	$("#popupNom").click(function(event){
+	$("#popupNom").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$(this).hide();
 		$("#popupNomInput").show().focus();
 	});
 
-	$("#popupTC").click(function(event){
+	$("#popupTC").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$("#popupTC").hide();
 		$("#popupTCedit").show();
 	});
 
-	$(".popupTCeditfield").click(function(event){
+	$(".popupTCeditfield").click(function (event) {
 		event.stopPropagation();
 	});
-	$("#nowTCin").click(function(event){
+	$("#nowTCin").click(function (event) {
 		event.stopPropagation();
 		var timeCurrent = convertToTime(Math.round(rekall.timeline.timeCurrent));
 		$("#popupTCinMin").val(timeCurrent.split(":")[0]);
 		$("#popupTCinSec").val(timeCurrent.split(":")[1]);
 	});
-	$("#nowTCout").click(function(event){
+	$("#nowTCout").click(function (event) {
 		event.stopPropagation();
 		var timeCurrent = convertToTime(Math.round(rekall.timeline.timeCurrent));
 		$("#popupTCoutMin").val(timeCurrent.split(":")[0]);
 		$("#popupTCoutSec").val(timeCurrent.split(":")[1]);
 	});
-	$("#eovTCout").click(function(event){
+	$("#eovTCout").click(function (event) {
 		event.stopPropagation();
 		var endVideo = rekall.videoPlayer.duration();
 		var timeEnd = convertToTime(Math.round(endVideo));
@@ -432,30 +447,30 @@ function setEditionControls() {
 		$("#popupTCoutSec").val(timeEnd.split(":")[1]);
 	});
 
-	$("#TCvalidModif").click(function(event){
+	$("#TCvalidModif").click(function (event) {
 		event.stopPropagation();
 		var keyDoc = $(this).parent().parent().attr("keydoc");
 		var inMin = $("#popupTCinMin").val();
 		var inSec = $("#popupTCinSec").val();
 		var outMin = $("#popupTCoutMin").val();
 		var outSec = $("#popupTCoutSec").val();
-		var TCin = (inMin*60)+(inSec*1);
-		var TCout = (outMin*60)+(outSec*1);
+		var TCin = (inMin * 60) + (inSec * 1);
+		var TCout = (outMin * 60) + (outSec * 1);
 
 		var endVideo = Math.ceil(rekall.videoPlayer.duration());
 
-		if(TCin>TCout) 			openAlert("Start time must be set before end time", "ok");
-		else if(TCout>endVideo) openAlert("End time must not be set after " + convertToTime(endVideo) + " (end of the video)", "ok");
+		if (TCin > TCout) openAlert("Start time must be set before end time", "ok");
+		else if (TCout > endVideo) openAlert("End time must not be set after " + convertToTime(endVideo) + " (end of the video)", "ok");
 		else {
 			setTCFromDom(keyDoc, TCin, TCout);
 
-			$("#popupTCin").html(inMin+":"+inSec);
-			$("#popupTCout").html(outMin+":"+outSec);
+			$("#popupTCin").html(inMin + ":" + inSec);
+			$("#popupTCout").html(outMin + ":" + outSec);
 
 			closeInputs();
 		}
 	});
-	$("#TCinvalidModif").click(function(event){
+	$("#TCinvalidModif").click(function (event) {
 		event.stopPropagation();
 		var TCin = $("#popupTCin").html().split(":");
 		var TCout = $("#popupTCout").html().split(":");
@@ -466,71 +481,71 @@ function setEditionControls() {
 		closeInputs();
 	});
 
-	$("#popupLabels").click(function(event){
+	$("#popupLabels").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$(this).hide();
 		$("#popupLabelsInput").show().focus();
 	});
 
-	$("#popupSpeed").click(function(event){
+	$("#popupSpeed").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$(this).hide();
 		$("#popupSpeedInput").show().focus();
 	});
 
-	$("#popupLegende").click(function(event){
+	$("#popupLegende").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$(this).hide();
 		$("#popupLegendeInput").show().focus();
 	});
 
-	$("#popupAuthor").click(function(event){
+	$("#popupAuthor").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$(this).hide();
 		$("#popupAuthorInput").show().focus();
 	});
 
-	$("#popupLink").click(function(event){
+	$("#popupLink").click(function (event) {
 		event.stopPropagation();
 		closeInputs();
 		$(this).hide();
 		$("#popupLinkInput").show().focus();
 	});
 
-	$(".popupInput").click(function(event){
+	$(".popupInput").click(function (event) {
 		event.stopPropagation();
 	});
 
-	$("#popupNomInput").keyup(function(event){
+	$("#popupNomInput").keyup(function (event) {
 		event.stopPropagation();
-		if(event.which == 13) {
+		if (event.which == 13) {
 			closeInputs();
 		}
 	});
 
-	$("#popupAuthorInput").keyup(function(event){
+	$("#popupAuthorInput").keyup(function (event) {
 		event.stopPropagation();
-		if(event.which == 13) {
+		if (event.which == 13) {
 			closeInputs();
 		}
 	});
 
-	$("#popupLinkInput").keyup(function(event){
+	$("#popupLinkInput").keyup(function (event) {
 		event.stopPropagation();
-		if(event.which == 13) {
+		if (event.which == 13) {
 			closeInputs();
 		}
 	});
 
-	$("#popupSetHighlight").click(function(event){
+	$("#popupSetHighlight").click(function (event) {
 		event.stopPropagation();
 		var keyDoc = $(this).parent().attr("keydoc");
 		var isHL = $(this).attr("isHighlight");
-		if(isHL=="true") {
+		if (isHL == "true") {
 			setMetaFromDom(keyDoc, "Rekall->Highlight", "");
 			$(this).attr("isHighlight", "false").removeClass("selected");
 			$("#popupEdit").removeClass("highlightPopup");
@@ -542,45 +557,14 @@ function setEditionControls() {
 		}
 	});
 
-	$("#popupEditSupprimer").click(function(){
+	$("#popupEditSupprimer").click(function () {
 		openAlert("Do you really want to delete this file from the project ?", "yesnodelete");
 	});
 
-  $("#playback_speed_form").change(function(event) {
-    console.debug("set playback rate to " + event.target.value);
-    window.app.rekall.Rekall().videoPlayer.playbackRate(Number(event.target.value));
-  });
-
-  $('#editAnnotationPic').click(function(ev) {
-    $('#edit_pic_modal').show();
-    var keyDoc = ev.target.parentElement.parentElement.attributes['keydoc'];
-    var markerArea = new markerjs2.MarkerArea(document.getElementById('annotation_img_edit'));
-    markerArea.targetRoot = document.getElementById('edit_pic_modal');
-    markerArea.addEventListener('render', (event) => {
-      var state = markerArea.getState();
-      window.my_current_markerjs_data_in_ugly_global = state;
-      markerArea.close(true);
-      setMetaFromDom(keyDoc.value, "Rekall->MarkerjsState", btoa(JSON.stringify(state)));
-
-      var b64img = event.dataUrl;
-      var data = b64img.match(/data:([a-z]+)\/([a-z]+);base64,(.*)/);
-      var type = data[1], subtype = data[2], b64data = data[3];
-      var bin_str = atob(b64data);
-      var n = b64data.length;
-      var uar = new Uint8Array(n);
-      while (n--) uar[n] = bin_str.charCodeAt(n);
-      var file = new File([uar], keyDoc.value.substr(1), {type: type+'/'+subtype});
-      $('#left_menu_item_btn_addfile').files = [file];
-      uploadFiles([file], {'edited': 1});
-      $('#popupImg').attr('src', $('#popupImg').attr('src') + '&time=' + performance.now());
-    });
-    markerArea.addEventListener('close', () => $('#edit_pic_modal').hide());
-    markerArea.renderAtNaturalSize = true;
-    markerArea.show();
-    if (window.my_current_markerjs_data_in_ugly_global)
-      markerArea.restoreState(window.my_current_markerjs_data_in_ugly_global);
-
-  })
+	$("#playback_speed_form").change(function (event) {
+		console.debug("set playback rate to " + event.target.value);
+		window.app.rekall.Rekall().videoPlayer.playbackRate(Number(event.target.value));
+	});
 }
 
 function closeSettingsPopup() {
@@ -736,97 +720,8 @@ function closeSettingsInputs() {
 }
 
 function closeInputs() {
-	$.each($(".popupInput"), function() {
-		if($(this).css("display") != "none") {
-			if($(this).attr("id")=="popupNomInput") {
-
-				var keyDoc = $(this).parent().attr("keydoc");
-				var newName = $(this).val().trim();
-				$(this).val(newName);
-				setMetaFromDom(keyDoc, "Rekall->Name", newName);
-
-				if(newName!="") $("#popupNom").html(newName).removeClass("empty");
-				else $("#popupNom").html("+ Add a name").addClass("empty");
-
-			} else if($(this).attr("id")=="popupLegendeInput") {
-
-				var keyDoc = $(this).parent().attr("keydoc");
-				var newComment = $(this).val().trim();
-				$(this).val(newComment);
-				setMetaFromDom(keyDoc, "Rekall->Comments", newComment.replace(/\n/gi, "<br/>"));
-
-				if(newComment!="") $("#popupLegende").html(newComment.replace(/\n/gi, "<br/>")).removeClass("empty");
-				else $("#popupLegende").html("+ Add a comment").addClass("empty");
-
-			} else if($(this).attr("id")=="popupSpeedInput") {
-
-				var keyDoc = $(this).parent().attr("keydoc");
-				var newSpeed = $('#popupSpeedInput input:checked').val();
-				setMetaFromDom(keyDoc, "Rekall->Speed", newSpeed);
-
-			} else if($(this).attr("id")=="popupLabelsInput") {
-
-				var keyDoc = $(this).parent().attr("keydoc");
-        var newLabels = '';
-        $('input.annotation_labels:checked').toArray().forEach(e => newLabels += e.value + ';')
-        setMetaFromDom(keyDoc, "Rekall->Labels", newLabels);
-
-			} else if($(this).attr("id")=="popupAuthorInput") {
-
-				var keyDoc = $(this).parent().attr("keydoc");
-				var newAuthor = $(this).val().trim();
-				$(this).val(newAuthor);
-				setMetaFromDom(keyDoc, "Rekall->Author", newAuthor);
-
-				if(newAuthor!="") $("#popupAuthor").html(newAuthor).removeClass("empty");
-				else $("#popupAuthor").html("+ Add an author").addClass("empty");
-
-			} else if($(this).attr("id")=="popupLinkInput") {
-
-				var keyDoc = $(this).parent().attr("keydoc");
-				var newLink = $(this).val().trim();
-
-				if(newLink!="") if(newLink.indexOf("http")!=0) newLink = "http://"+newLink;
-
-				$(this).val(newLink);
-				setMetaFromDom(keyDoc, "Rekall->Link", newLink);
-
-				if(newLink!="") {
-          if(rekall_common.owner.canEdit) $("#popupLink").html(newLink).removeClass("empty");
-					else $("#popupLink").html("<a href='"+newLink+"' target='_blank'>"+newLink+"</a>").removeClass("empty");
-				}
-				else $("#popupLink").html("+ Add a link").addClass("empty");
-
-			} else if($(this).attr("id")=="popupTCedit") {
-				var keyDoc = $("#popupRight").attr("keydoc");
-				var inMin = $("#popupTCinMin").val();
-				var inSec = $("#popupTCinSec").val();
-				var outMin = $("#popupTCoutMin").val();
-				var outSec = $("#popupTCoutSec").val();
-				var TCin = (inMin*60)+(inSec*1);
-				var TCout = (outMin*60)+(outSec*1);
-
-				var endVideo = Math.ceil(rekall.videoPlayer.duration());
-
-				var isReturn = true;
-
-				if((inMin>=120)||(inSec>=60)||(outMin>=120)||(outSec>=60)||(inMin<0)||(inSec<0)||(outMin<0)||(outSec<0)) openAlert("Invalid time code", "ok");
-				else if(TCin>TCout) 			openAlert("Start time must be set before end time", "ok");
-				else if(TCout>endVideo)			openAlert("End time must not be set after " + convertToTime(endVideo) + " (end of the video)", "ok");
-				else {
-					setTCFromDom(keyDoc, TCin, TCout);
-					$("#popupTCin").html(inMin+":"+inSec);
-					$("#popupTCout").html(outMin+":"+outSec);
-					isReturn = false;
-				}
-				if(isReturn) return true;
-			}
-		}
-	});
-	$(".popupInput:not(.popupInputNoHide)").hide();
+	popupPanel.ensureLastOpenedEditionClosed();
 	$(".popupRightItem").show();
-	$("#popupTC").show();
-	$("#popupTCedit").hide();
 }
 
 function closeEdit() {
@@ -852,132 +747,34 @@ function openMosaic() {
 
 function fillPopupEdit(tag) {
 
+	popupPanel.createPopupContent(tag);
 	var isPaused = rekall.timeline.isPaused();
 	rekall.timeline.pause();
 
 	$("#popupEdit").attr("isPaused",isPaused);
 	$("#popupTC").css("background",tag.color);
 
-	var bgColorLeft = tag.color.replace(/rgb/g, "rgba").replace(/\)/g, ",.35)");
-
-  bgColorLeft = getTagGradientColor(tag);
-
-	$("#popupLeft").css("background",bgColorLeft);
-
-  var type = tag.getMetadata("Rekall->Type");
-
-  $("#popupImg").unbind( "click" );
-	if(tag.isMarker()==true){
-		$("#popupImg").show();
-		$("#popupImg").attr("src","../shared/css/images/img-note.png");
-	} else {
-		if(tag.thumbnail.url){
-			$("#popupImg").attr("src", tag.getDownloadLink() || tag.thumbnail.url);
-      $('#annotation_img_edit').attr('src', tag.getDownloadLink(true));
-		} else {
-			if(type.indexOf("image") > -1) $("#popupImg").attr("src","../shared/css/images/img-image.png")
-			else if(type.indexOf("pdf") > -1) $("#popupImg").attr("src","../shared/css/images/img-pdf.png")
-			else if(type.indexOf("audio") > -1) $("#popupImg").attr("src","../shared/css/images/img-music.png")
-			else if(type.indexOf("vcard") > -1) $("#popupImg").attr("src","../shared/css/images/img-user.png")
-			else if(type.indexOf("video") > -1) $("#popupImg").attr("src","../shared/css/images/img-video.png")
-			else if(type.indexOf("msword") > -1) $("#popupImg").attr("src","../shared/css/images/img-word.png")
-			else if(type.indexOf("link") > -1) $("#popupImg").attr("src","../shared/css/images/img-link.png")
-			else $("#popupImg").attr("src","../shared/css/images/img-document.png");
-		}
-		$("#popupImg").click(function(event){
-			event.stopPropagation();
-			if(tag.isLink()) {
-				if(link != "") window.open(link,'_blank');
-			}
-			else
-				window.open($('#popupImg')[0].src, '_blank');
-		});
-	}
-
 	$("#popupNom").css("color",tag.color);
 
-  window.my_current_markerjs_data_in_ugly_global = null;
-  $('#editAnnotationPic').hide();
-  $('#linkToOriginalImage').hide();
-  if (type.split('/')[0] == 'image') {
-    $('#editAnnotationPic').html('edit');
-    $('#editAnnotationPic').show();
-    $('#linkToOriginalImage').show();
-    $('#linkToOriginalImage').unbind('click');
-    $('#linkToOriginalImage').click(() => window.open(tag.getDownloadLink(true), '_blank'));
-    var data = tag.getMetadata('Rekall->MarkerjsState');
-    if (data)
-      window.my_current_markerjs_data_in_ugly_global = JSON.parse(atob(data));
-  }
-
-	$("#popupType").html(type).css("color",tag.color);
-
-	var name = tag.getMetadata("Rekall->Name");
-	if(name!="") $("#popupNom").html(name).removeClass("empty");
-	else $("#popupNom").html("+ Add a name").addClass("empty");
-
-	var startVerb = convertToTime(tag.getTimeStart());
-	$("#popupTCin").html(startVerb);
-
-	var endVerb = convertToTime(tag.getTimeEnd());
-	$("#popupTCout").html(endVerb);
-
-	var speed = tag.getMetadata("Rekall->Speed");
-  if (!speed || speed == '')
-    speed = 1;
-  $('#popupSpeedInput input').attr('checked', false);
-  $('#popupSpeedInput input[value="'+speed+'"]').attr('checked', true);
-
-	var labels = tag.getMetadata("Rekall->Labels");
-  $('input.annotation_labels').attr('checked', false);
-  if (labels && labels != '') {
-    var _labels = labels.split(';');
-    $('input.annotation_labels').toArray().forEach(e => {
-      e.checked = (_labels.indexOf(e.value) != -1);
-    })
-  }
-
-	var comments = tag.getMetadata("Rekall->Comments");
-	if((comments)&&(comments!="")) $("#popupLegende").html(comments).removeClass("empty");
-	else $("#popupLegende").html("+ Add a comment").addClass("empty");
-
-	var author = tag.getMetadata("Rekall->Author");
-	if((author)&&(author!="")) $("#popupAuthor").html(author).removeClass("empty");
-	else $("#popupAuthor").html("+ Add an author").addClass("empty");
-
-	var link = tag.getMetadata("Rekall->Link");
-	if((link)&&(link!="")) {
-		if(rekall_common.owner.canEdit) $("#popupLink").html(link).removeClass("empty");
-		else $("#popupLink").html("<a href='"+link+"' target='_blank'>"+link+"</a>").removeClass("empty");
-	}
-	else $("#popupLink").html("+ Add a link").addClass("empty");
+	// var labels = tag.getMetadata("Rekall->Labels");
+  // $('input.annotation_labels').attr('checked', false);
+  // if (labels && labels != '') {
+  //   var _labels = labels.split(';');
+  //   $('input.annotation_labels').toArray().forEach(e => {
+  //     e.checked = (_labels.indexOf(e.value) != -1);
+  //   })
+  // }
 
 	if(rekall_common.owner.canEdit) {
-		if(tag.isMarker()==true) $("#popupEditSupprimer").html("Delete Note");
-		else $("#popupEditSupprimer").html("Delete File");
-
 		$(".empty").show();
 		$(".displayMode").hide();
 		$("#popupNomInput").val(tag.getMetadata("Rekall->Name"));
 
-		$("#popupTCinMin").val(startVerb.split(":")[0]);
-		$("#popupTCinSec").val(startVerb.split(":")[1]);
-
-		$("#popupTCoutMin").val(endVerb.split(":")[0]);
-		$("#popupTCoutSec").val(endVerb.split(":")[1]);
-
-		$("#popupLegendeInput").val(""+comments.replace(/<br\/>/gi, '\n'));
-		$("#popupAuthorInput").val(""+author);
-		$("#popupLinkInput").val(""+link);
-		$("#popupSpeedInput").val(""+speed);
-
 		var highlight = tag.getMetadata("Rekall->Highlight");
 		if(highlight=="true") {
-			$("#popupSetHighlight").attr("isHighlight","true").addClass("selected");
 			$("#popupEdit").addClass("highlightPopup");
 		}
 		else {
-			$("#popupSetHighlight").attr("isHighlight","false").removeClass("selected");
 			$("#popupEdit").removeClass("highlightPopup");
 		}
 	} else {
@@ -986,9 +783,6 @@ function fillPopupEdit(tag) {
 		$(".displayMode").show();
 	}
 
-	$("#popupLeft") .attr("keydoc", tag.document.key);
-	$("#popupRight").attr("keydoc", tag.document.key);
-
 	$("#popupSpace").show();
 	$("#popupEdit").show();
 }
@@ -1057,6 +851,14 @@ function setMetaFromDom(keyDoc, metaType, meta) {
 	});
 }
 
+function onMetaFromDomUpdated(message, data){
+	setMetaFromDom(data.tag.document.key, data.metadata, data.tag.getMetadata(data.metadata));
+}
+
+function onTcUpdated(message, data){
+	setTCFromDom(data.tag.document.key, data.tag.getTimeStart(), data.tag.getTimeEnd());
+}
+
 function setTCFromDom(keyDoc, TCin, TCout) {
 	rouletteStart();
 	$.ajax("php/project.php", {
@@ -1100,7 +902,7 @@ function deleteFromDomFinished() {
 
 //Gestion d'upload
 var filesToUpload = [], fileIsUploading = false;
-function uploadFiles(files, additionnal_post_data={}) {
+function uploadFiles(files, additionnal_post_data={}, callBack = undefined) {
 	$.each(files, function(index, file) {
 		var formData = new FormData();
 
@@ -1173,6 +975,9 @@ function uploadFiles(files, additionnal_post_data={}) {
 
 					rouletteEnd();
 					uploadFilesNext();
+					if(callBack && typeof callBack === 'function'){
+						callBack();
+					}
 				},
 				error: function(data) {
 					openAlert("Uploading error. Try again.");
@@ -1181,6 +986,9 @@ function uploadFiles(files, additionnal_post_data={}) {
 
 					rouletteEnd();
 					uploadFilesNext();
+					if(callBack && typeof callBack === 'function'){
+						callBack();
+					}
 				}
 			});
 			uploadFilesNext();
@@ -1260,3 +1068,42 @@ $(window).trigger("resize");
 function openPasteModal() { $('#paste_modal').css('display', 'flex'); $('#paste_modal_content').first().focus() }
 function closePasteModal() { $('#paste_modal').hide(); $('#paste_modal_content').empty();  }
 
+function openImageEdition(message, tag) {
+	$('#edit_pic_modal').show();
+	let keyDoc = tag.document.key;
+	$('#annotation_img_edit').attr('src', tag.getDownloadLink(true));
+	let markerArea = new markerjs2.MarkerArea($('#annotation_img_edit')[0]);
+	let imageState;
+
+	if (tag.getMetadata("Rekall->MarkerjsState").length){
+		imageState = JSON.parse(atob(tag.getMetadata("Rekall->MarkerjsState")));
+	}
+
+	markerArea.targetRoot = document.getElementById('edit_pic_modal');
+	markerArea.addEventListener('render', (event) => {
+		imageState = markerArea.getState();
+		markerArea.close(true);
+		tag.setMetadata("Rekall->MarkerjsState", btoa(JSON.stringify(imageState)));
+
+		let b64img = event.dataUrl;
+		let data = b64img.match(/data:([a-z]+)\/([a-z]+);base64,(.*)/);
+		let type = data[1], subtype = data[2], b64data = data[3];
+		let bin_str = atob(b64data);
+		let n = b64data.length;
+		let uar = new Uint8Array(n);
+		while (n--) uar[n] = bin_str.charCodeAt(n);
+		let file = new File([uar], keyDoc.substr(1), {type: type+'/'+subtype});
+		$('#left_menu_item_btn_addfile').files = [file];
+		uploadFiles([file], {'edited': 1}, function(){$('#popupImg').attr('src', tag.getDownloadLink());});
+		setMetaFromDom(tag.document.key, "Rekall->MarkerjsState", tag.getMetadata('Rekall->MarkerjsState'));
+	});
+
+	markerArea.addEventListener('close', () => {
+		$('#edit_pic_modal').hide();
+	});
+	markerArea.renderAtNaturalSize = true;
+	markerArea.show();
+	if (imageState)
+		markerArea.restoreState(imageState);
+
+}
\ No newline at end of file
diff --git a/capsule-prototype/js/rekall/Document.js b/capsule-prototype/js/rekall/Document.js
index f06c3ba2a28ebff72c67ad5c36c079a063531700..926063491c1f0a9906183669d84c30994cbc021a 100644
--- a/capsule-prototype/js/rekall/Document.js
+++ b/capsule-prototype/js/rekall/Document.js
@@ -21,13 +21,14 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-function Document() {
+function Document(data) {
 	this.tags      		   = new Array();
 	this.metadatas		   = new Array();
 	this.currentVersion    = 0;
 	this.goodVersion       = 0;
 	this.setMetadata("Rekall->Group", "");
 	this.setMetadata("Rekall->Visibility", "");
+	this.project = data.project;
 }
 Document.prototype.addTag = function(tag) {
 	this.tags.push(tag);
@@ -88,7 +89,7 @@ Document.prototype.isLink = function(version) {
 }
 Document.prototype.getDownloadLink = function(original = false) {
   var path = Utils.getLocalFilePath(this, "file");
-  return original ? path.replace('file.php?r=', 'file.php?r=rk_original_af7ef02e_') : path;
+  return original ? path.replace('file.php?r=', 'file.php?r=rk_original_af7ef02e_') : path + '&timegeneration=' + performance.now();
 }
 Document.prototype.getFileName = function() {
   var path = Utils.getLocalFilePath(this, "file");
@@ -152,7 +153,7 @@ Document.prototype.addVersion = function(document) {
 		for (var index in this.tags) {
 			var tag = this.tags[index];
 			if(tag.version == thisVersion) {
-				var newTag = new Tag(this);
+				var newTag = TagFactory(this);
 				newTag.timeStart = tag.getTimeStart();
 				newTag.timeEnd   = tag.getTimeEnd();
 				this.addTag(newTag);
diff --git a/capsule-prototype/js/rekall/Source.js b/capsule-prototype/js/rekall/Source.js
index 7a1e631cb3b436f6ec9c31372231c814c2b96bcc..58080ed262002951a4cff5f97f867416f6d5b4a3 100644
--- a/capsule-prototype/js/rekall/Source.js
+++ b/capsule-prototype/js/rekall/Source.js
@@ -35,7 +35,7 @@ Source.prototype.addDocument = function(document) {
 
 	if(this.documents[document.key] == undefined) {
 		if(document.tags.length == 0) {
-			var tag = new Tag(document);
+			var tag = TagFactory(document);
 			document.addTag(tag);
 		}
 		document.metadatas[-1] = document.cloneMetadatas();