src/widgets/AnnotationsList.js
changeset 1072 ac1eacb3aa33
parent 1069 2409cb4cebaf
child 1075 92cb33eb7a75
equal deleted inserted replaced
1071:02c04d2c8fd8 1072:ac1eacb3aa33
     1 IriSP.Widgets.AnnotationsList = function(player, config) {
     1 import annotationsListStyles from "./AnnotationsList.module.css";
     2     IriSP.Widgets.Widget.call(this, player, config);
     2 
     3     this.lastIds = [];
     3 import Mustache from "mustache";
     4     var _this = this;
     4 import _ from "lodash";
     5     this.throttledRefresh = IriSP._.throttle(function(full) {
     5 import jQuery from "jquery";
       
     6 
       
     7 const AnnotationsList = function (ns) {
       
     8   return class extends ns.Widgets.Widget {
       
     9     constructor(player, config) {
       
    10       super(player, config);
       
    11       this.lastIds = [];
       
    12       var _this = this;
       
    13       this.throttledRefresh = _.throttle(function (full) {
     6         _this.refresh(full);
    14         _this.refresh(full);
     7     }, 800);
    15       }, 800);
     8     this.searchString = false;
    16       this.searchString = false;
     9     this.lastSearch = false;
    17       this.lastSearch = false;
    10     this.localSource = undefined;
    18       this.localSource = undefined;
    11 };
    19     }
    12 
    20 
    13 IriSP.Widgets.AnnotationsList.prototype = new IriSP.Widgets.Widget();
    21     static defaults = {
    14 
    22       pre_draw_callback: function () {
    15 IriSP.Widgets.AnnotationsList.prototype.defaults = {
       
    16     pre_draw_callback: function(){
       
    17         return this.importUsers();
    23         return this.importUsers();
    18     },
    24       },
    19     /*
    25       /*
    20      * URL when the annotations are to be reloaded from an LDT-like segment API
    26        * URL when the annotations are to be reloaded from an LDT-like segment API
    21      * e.g.
    27        * e.g.
    22      * http://ldt.iri.centrepompidou.fr/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}?callback=?
    28        * http://ldt.iri.centrepompidou.fr/ldtplatform/api/ldt/segments/{{media}}/{{begin}}/{{end}}?callback=?
    23      */
    29        */
    24     ajax_url : false,
    30       ajax_url: false,
    25     /*
    31       /*
    26      * number of milliseconds before/after the current timecode when calling the
    32        * number of milliseconds before/after the current timecode when calling the
    27      * segment API
    33        * segment API
    28      */
    34        */
    29     ajax_granularity : 600000,
    35       ajax_granularity: 600000,
    30     default_thumbnail : "",
    36       default_thumbnail: "",
    31     custom_external_icon : "",
    37       custom_external_icon: "",
    32     /*
    38       /*
    33      * URL when the annotation is not in the current project, e.g.
    39        * URL when the annotation is not in the current project, e.g.
    34      * http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/{{media}}/{{project}}/{{annotationType}}#id={{annotation}}
    40        * http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/{{media}}/{{project}}/{{annotationType}}#id={{annotation}}
    35      */
    41        */
    36     foreign_url : "",
    42       foreign_url: "",
    37     annotation_type : false,
    43       annotation_type: false,
    38     refresh_interval : 0,
    44       refresh_interval: 0,
    39     limit_count : 20,
    45       limit_count: 20,
    40     newest_first : false,
    46       newest_first: false,
    41     show_title: true,
    47       show_title: true,
    42     show_audio: true,
    48       show_audio: true,
    43     show_creator: true,
    49       show_creator: true,
    44     show_controls: false,
    50       show_controls: false,
    45     show_end_time: true,
    51       show_end_time: true,
    46     show_publish: false,
    52       show_publish: false,
    47     show_twitter: false,
    53       show_twitter: false,
    48     twitter_hashtag: '',
    54       twitter_hashtag: "",
    49     // Callback for Edit action. Leave undefined for default action.
    55       // Callback for Edit action. Leave undefined for default action.
    50     on_edit: undefined,
    56       on_edit: undefined,
    51     publish_type: "PublicContribution",
    57       publish_type: "PublicContribution",
    52     // Used to publish annotations
    58       // Used to publish annotations
    53     api_endpoint_template: "",
    59       api_endpoint_template: "",
    54     api_serializer: "ldt_annotate",
    60       api_serializer: "ldt_annotate",
    55     api_method: "POST",
    61       api_method: "POST",
    56     editable: false,
    62       editable: false,
    57     // Id that will be used as localStorage key
    63       // Id that will be used as localStorage key
    58     editable_storage: "",
    64       editable_storage: "",
    59     widget_max_height: 680,
    65       widget_max_height: 680,
    60     always_visible : false,
    66       always_visible: false,
    61     start_visible: true,
    67       start_visible: true,
    62     show_audio : true,
    68       show_audio: true,
    63     show_filters : false,
    69       show_filters: false,
    64     keyword_filter: true,
    70       keyword_filter: true,
    65     date_filter: true,
    71       date_filter: true,
    66     user_filter: true,
    72       user_filter: true,
    67     segment_filter: true,
    73       segment_filter: true,
    68     latest_contributions_filter: false,
    74       latest_contributions_filter: false,
    69     current_day_filter: true,
    75       current_day_filter: true,
    70     show_header : false,
    76       show_header: false,
    71     custom_header : false,
    77       custom_header: false,
    72     annotations_count_header : true,
    78       annotations_count_header: true,
    73     annotations_count_header_string: "annotations",
    79       annotations_count_header_string: "annotations",
    74     show_creation_date : false,
    80       show_creation_date: false,
    75     show_timecode : true,
    81       show_timecode: true,
    76     show_end_time : true,
    82       show_end_time: true,
    77     project_id: "",
    83       project_id: "",
    78     /*
    84       /*
    79      * Only annotation in the current segment will be displayed. Designed to work with the Segments Widget.
    85        * Only annotation in the current segment will be displayed. Designed to work with the Segments Widget.
    80      */
    86        */
    81     allow_annotations_deletion: false,
    87       allow_annotations_deletion: false,
    82     /*
    88       /*
    83      * URL to call when deleting annotation. Expects a mustache template with {{annotation_id}}, ex /api/anotations/{{annotation_id}}/
    89        * URL to call when deleting annotation. Expects a mustache template with {{annotation_id}}, ex /api/anotations/{{annotation_id}}/
    84      */
    90        */
    85     api_delete_endpoint : "",
    91       api_delete_endpoint: "",
    86     api_delete_method: "DELETE",
    92       api_delete_method: "DELETE",
    87     api_users_endpoint: "",
    93       api_users_endpoint: "",
    88     api_users_method: "GET",
    94       api_users_method: "GET",
    89     make_name_string_function: function(params){
    95       make_name_string_function: function (params) {
    90         return params.username ? params.username : "Anonymous";
    96         return params.username ? params.username : "Anonymous";
    91     },
    97       },
    92     filter_by_segments: false,
    98       filter_by_segments: false,
    93     segment_filter: true,
    99       segment_filter: true,
    94     segments_annotation_type: "chap",
   100       segments_annotation_type: "chap",
    95     /*
   101       /*
    96      * Set to a username if you only want to display annotations from a given user
   102        * Set to a username if you only want to display annotations from a given user
    97      */
   103        */
    98     show_only_annotation_from_user: false,
   104       show_only_annotation_from_user: false,
    99     /*
   105       /*
   100      * Show a text field that filter annotations by username
   106        * Show a text field that filter annotations by username
   101      */
   107        */
   102     tags : true,
   108       tags: true,
   103 
   109 
   104     polemics : [{
   110       polemics: [
   105         keyword: "++",
   111         {
   106         background_color: "#c9ecc6"
   112           keyword: "++",
   107     },{
   113           background_color: "#c9ecc6",
   108         keyword: "--",
   114         },
   109         background_color: "#f9c5c6"
   115         {
   110     },{
   116           keyword: "--",
   111         keyword: "??",
   117           background_color: "#f9c5c6",
   112         background_color: "#cec5f9"
   118         },
   113     },{
   119         {
   114         keyword: "==",
   120           keyword: "??",
   115         background_color: "#f9f4c6"
   121           background_color: "#cec5f9",
   116     }]
   122         },
   117 };
   123         {
   118 
   124           keyword: "==",
   119 IriSP.Widgets.AnnotationsList.prototype.importUsers = function(){
   125           background_color: "#f9f4c6",
   120     if (!this.source.users_data && this.api_users_endpoint){
   126         },
       
   127       ],
       
   128     };
       
   129 
       
   130     importUsers() {
       
   131       if (!this.source.users_data && this.api_users_endpoint) {
   121         this.usernames = Array();
   132         this.usernames = Array();
   122         var _this = this,
   133         var _this = this,
   123             _list = this.getWidgetAnnotations(),
   134           _list = this.getWidgetAnnotations(),
   124             usernames_list_string = "";
   135           usernames_list_string = "";
   125 
   136 
   126         _list.forEach(function(_annotation){
   137         _list.forEach(function (_annotation) {
   127             if(_this.usernames.indexOf(_annotation.creator) == -1){
   138           if (_this.usernames.indexOf(_annotation.creator) == -1) {
   128                 _this.usernames.push(_annotation.creator);
   139             _this.usernames.push(_annotation.creator);
   129             }
   140           }
   130         });
   141         });
   131         this.usernames.forEach(function(_username){
   142         this.usernames.forEach(function (_username) {
   132             usernames_list_string+=_username+","
   143           usernames_list_string += _username + ",";
   133         })
   144         });
   134         usernames_list_string = usernames_list_string.substring(0, usernames_list_string.length - 1);
   145         usernames_list_string = usernames_list_string.substring(
   135         _url = Mustache.to_html(this.api_users_endpoint, {usernames_list_string: encodeURIComponent(usernames_list_string), usernames_list_length: this.usernames.length});
   146           0,
   136         return IriSP.jQuery.ajax({
   147           usernames_list_string.length - 1
   137             async: false,
   148         );
   138             url: _url,
   149         _url = Mustache.render(this.api_users_endpoint, {
   139             type: "GET",
   150           usernames_list_string: encodeURIComponent(usernames_list_string),
   140             success: function(_data) {
   151           usernames_list_length: this.usernames.length,
   141                 _this.source.users_data = _data.objects
   152         });
   142             },
   153         return jQuery.ajax({
   143             error: function(_xhr, _error, _thrown) {
   154           async: false,
   144                 console.log(_xhr)
   155           url: _url,
   145                 console.log(_error)
   156           type: "GET",
   146                 console.log(_thrown)
   157           success: function (_data) {
   147             }
   158             _this.source.users_data = _data.objects;
   148         })
   159           },
       
   160           error: function (_xhr, _error, _thrown) {
       
   161             console.log(_xhr);
       
   162             console.log(_error);
       
   163             console.log(_thrown);
       
   164           },
       
   165         });
       
   166       }
   149     }
   167     }
   150 }
   168 
   151 
   169     static messages =  {
   152 IriSP.Widgets.AnnotationsList.prototype.messages = {
   170       en: {
   153     en: {
       
   154         voice_annotation: "Voice Annotation",
   171         voice_annotation: "Voice Annotation",
   155         now_playing: "Now playing...",
   172         now_playing: "Now playing...",
   156         previous: "Previous",
   173         previous: "Previous",
   157         next: "Next",
   174         next: "Next",
   158         set_time: "Double-click to update to current player time",
   175         set_time: "Double-click to update to current player time",
   159         edit_annotation: "Edit note",
   176         edit_annotation: "Edit note",
   160         delete_annotation: "Delete note",
   177         delete_annotation: "Delete note",
   161         publish_annotation: "Make note public",
   178         publish_annotation: "Make note public",
   162         import_annotations: "Paste or load notes in this field and press Import.",
   179         import_annotations:
   163         confirm_delete_message: "You are about to delete {{ annotation.title }}. Are you sure you want to delete it?",
   180           "Paste or load notes in this field and press Import.",
   164         confirm_publish_message: "You are about to publish {{ annotation.title }}. Are you sure you want to make it public?",
   181         confirm_delete_message:
       
   182           "You are about to delete {{ annotation.title }}. Are you sure you want to delete it?",
       
   183         confirm_publish_message:
       
   184           "You are about to publish {{ annotation.title }}. Are you sure you want to make it public?",
   165         tweet_annotation: "Tweet annotation",
   185         tweet_annotation: "Tweet annotation",
   166         external_annotation: "This annotation was submitted to another project",
   186         external_annotation: "This annotation was submitted to another project",
   167         everyone: "Everyone",
   187         everyone: "Everyone",
   168         header: "Annotations for this content",
   188         header: "Annotations for this content",
   169         segment_filter: "All cuttings",
   189         segment_filter: "All cuttings",
   172         confirm: "Confirm",
   192         confirm: "Confirm",
   173         cancel: "Cancel",
   193         cancel: "Cancel",
   174         annotation_deletion_delete: "You will delete this annotation",
   194         annotation_deletion_delete: "You will delete this annotation",
   175         annotation_deletion_sending: "Your deletion request is being sent ... ",
   195         annotation_deletion_sending: "Your deletion request is being sent ... ",
   176         annotation_deletion_success: "The annotation has been deleted.",
   196         annotation_deletion_success: "The annotation has been deleted.",
   177         annotation_deletion_error: "There was an error contacting the server. The annotation has not been deleted."
   197         annotation_deletion_error:
   178     },
   198           "There was an error contacting the server. The annotation has not been deleted.",
   179     fr: {
   199       },
       
   200       fr: {
   180         voice_annotation: "Annotation Vocale",
   201         voice_annotation: "Annotation Vocale",
   181         now_playing: "Lecture en cours...",
   202         now_playing: "Lecture en cours...",
   182         previous: "Précédent",
   203         previous: "Précédent",
   183         next: "Suivant",
   204         next: "Suivant",
   184         set_time: "Double-cliquer pour fixer au temps du lecteur",
   205         set_time: "Double-cliquer pour fixer au temps du lecteur",
   185         edit_annotation: "Éditer la note",
   206         edit_annotation: "Éditer la note",
   186         delete_annotation: "Supprimer la note",
   207         delete_annotation: "Supprimer la note",
   187         publish_annotation: "Rendre la note publique",
   208         publish_annotation: "Rendre la note publique",
   188         import_annotations: "Copiez ou chargez des notes dans ce champ et appuyez sur Import",
   209         import_annotations:
   189         confirm_delete_message: "Vous allez supprimer {{ annotation.title }}. Êtes-vous certain(e) ?",
   210           "Copiez ou chargez des notes dans ce champ et appuyez sur Import",
   190         confirm_publish_message: "Vous allez publier {{ annotation.title }}. Êtes-vous certain(e) ?",
   211         confirm_delete_message:
       
   212           "Vous allez supprimer {{ annotation.title }}. Êtes-vous certain(e) ?",
       
   213         confirm_publish_message:
       
   214           "Vous allez publier {{ annotation.title }}. Êtes-vous certain(e) ?",
   191         tweet_annotation: "Tweeter l'annotation",
   215         tweet_annotation: "Tweeter l'annotation",
   192         external_annotation: "Cette annotation a été postée sur un autre projet",
   216         external_annotation:
       
   217           "Cette annotation a été postée sur un autre projet",
   193         everyone: "Tous",
   218         everyone: "Tous",
   194         header: "Annotations sur ce contenu",
   219         header: "Annotations sur ce contenu",
   195         segment_filter: "Tous les segments",
   220         segment_filter: "Tous les segments",
   196         latest_contributions: "Dernières contributions",
   221         latest_contributions: "Dernières contributions",
   197         close_widget: "Fermer",
   222         close_widget: "Fermer",
   198         confirm: "Confirmer",
   223         confirm: "Confirmer",
   199         cancel: "Annuler",
   224         cancel: "Annuler",
   200         annotation_deletion_delete: "Vous allez supprimer cette annotation",
   225         annotation_deletion_delete: "Vous allez supprimer cette annotation",
   201         annotation_deletion_sending: "Votre demande de suppression est en cours d'envoi ... ",
   226         annotation_deletion_sending:
       
   227           "Votre demande de suppression est en cours d'envoi ... ",
   202         annotation_deletion_success: "L'annotation a été supprimée.",
   228         annotation_deletion_success: "L'annotation a été supprimée.",
   203         annotation_deletion_error: "Une erreur s'est produite en contactant le serveur. L'annotation n'a pas été supprimée."
   229         annotation_deletion_error:
       
   230           "Une erreur s'est produite en contactant le serveur. L'annotation n'a pas été supprimée.",
       
   231       },
       
   232     };
       
   233 
       
   234     static template =
       
   235       '{{#show_header}}<p class="Ldt-AnnotationsList-header">' +
       
   236       "{{#custom_header}}{{custom_header}}{{/custom_header}}" +
       
   237       "{{^custom_header}}{{l10n.header}}{{/custom_header}}" +
       
   238       "</p>{{/show_header}}" +
       
   239       '<div class="Ldt-AnnotationsListWidget">' +
       
   240       '<div class="Ldt-AnnotationsList-ScreenMain">' +
       
   241       "{{#show_filters}}" +
       
   242       '<div class="Ldt-AnnotationsList-Filters">' +
       
   243       '{{#keyword_filter}}<input class="Ldt-AnnotationsList-filter-text" id="Ldt-AnnotationsList-keywordsFilter" type="text" value=""></input>{{/keyword_filter}}' +
       
   244       '{{#user_filter}}<select class="Ldt-AnnotationsList-filter-dropdown" id="Ldt-AnnotationsList-userFilter"><option selected value="">{{l10n.everyone}}</option></select>{{/user_filter}}' +
       
   245       '{{#date_filter}}<label class="Ldt-AnnotationsList-filter-date">Date: <input id="Ldt-AnnotationsList-dateFilter" type="text"></input></label>{{/date_filter}}' +
       
   246       '{{#segment_filter}}<label class="Ldt-AnnotationsList-filter-checkbox"><input type="checkbox" id="Ldt-AnnotationsList-ignoreSegmentsFilter">{{l10n.segment_filter}}</label>{{/segment_filter}}' +
       
   247       '{{#latest_contributions_filter}}<label class="Ldt-AnnotationsList-filter-checkbox"><input type="checkbox" id="Ldt-AnnotationsList-latestContributionsFilter">{{l10n.latest_contributions}}</label>{{/latest_contributions_filter}}' +
       
   248       "</div>" +
       
   249       "{{/show_filters}}" +
       
   250       '{{#show_controls}}<div class="Ldt-AnnotationsList-Controls"><span class="Ldt-AnnotationsList-Control-Prev">{{ l10n.previous }}</span> | <span class="Ldt-AnnotationsList-Control-Next">{{ l10n.next }}</span></div>{{/show_controls}}' +
       
   251       '{{#show_audio}}<div class="Ldt-AnnotationsList-Audio"></div>{{/show_audio}}' +
       
   252       '<ul class="Ldt-AnnotationsList-ul">' +
       
   253       "</ul>" +
       
   254       "</div>" +
       
   255       "{{#allow_annotations_deletion}}" +
       
   256       '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenDelete">' +
       
   257       '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>' +
       
   258       "{{l10n.annotation_deletion_delete}}" +
       
   259       '<ul class="Ldt-AnnotationsList-ul-ToDelete"></ul>' +
       
   260       '<a class="Ldt-AnnotationsList-ConfirmDelete">{{l10n.confirm}}</a> <a class="Ldt-AnnotationsList-CancelDelete">{{l10n.cancel}}</a>' +
       
   261       "</div>" +
       
   262       '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSending">' +
       
   263       '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>' +
       
   264       "{{l10n.annotation_deletion_sending}}" +
       
   265       "</div>" +
       
   266       '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSuccess">' +
       
   267       '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>' +
       
   268       "{{l10n.annotation_deletion_success}}" +
       
   269       "</div>" +
       
   270       '<div data.annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenError">' +
       
   271       '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>' +
       
   272       "{{l10n.annotation_deletion_error}}" +
       
   273       "</div>" +
       
   274       "{{/allow_annotations_deletion}}" +
       
   275       "</div>";
       
   276 
       
   277     static annotationTemplate =
       
   278       '<li class="Ldt-AnnotationsList-li Ldt-Highlighter-Annotation Ldt-TraceMe" data-annotation="{{ id }}" data-begin="{{ begin_ms }}" data-end="{{ end_ms }}" trace-info="annotation-id:{{id}}, media-id:{{media_id}}" style="{{specific_style}}">' +
       
   279       '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-ThumbContainer Ldt-AnnotationsList-Annotation-Screen Ldt-AnnotationsList-Annotation-ScreenMain">' +
       
   280       '<a {{#url}}href="{{url}}"{{/url}} draggable="true">' +
       
   281       '<img title="{{^external}}{{ begin }} - {{ end }}{{/external}}{{#external}}{{l10n.external_annotation}}{{/external}}" class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />' +
       
   282       '{{#external}}<div title="{{l10n.external_annotation}}" class="Ldt-AnnotationsList-External-Icon"></div>{{/external}}' +
       
   283       "</a>" +
       
   284       "</div>" +
       
   285       "{{#allow_annotations_deletion}}" +
       
   286       '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-DeleteButton">&#10006;</div>' +
       
   287       "{{/allow_annotations_deletion}}" +
       
   288       '{{#show_timecode}}<div title="{{l10n.set_time}}" class="Ldt-AnnotationsList-Duration"><span class="Ldt-AnnotationsList-Begin Ldt-live-editable Ldt-AnnotationsList-TimeEdit" data-editable_value="{{begin}}" data-editable_id="{{id}}" data-editable_field="begin" data-editable_type="timestamp">{{begin}}</span>{{#show_end_time}} - <span class="Ldt-AnnotationsList-End Ldt-live-editable" data-editable_value="{{end}}" data-editable_id="{{id}}" data-editable_field="end" data-editable_type="timestamp">{{end}}</span>{{/show_end_time}}</div>{{/show_timecode}}' +
       
   289       '<h3 class="Ldt-AnnotationsList-Title Ldt-Annotation-Timecode" data-timecode="{{ begin_ms }}" draggable="true">' +
       
   290       '{{#show_title}}<span class="Ldt-AnnotationsList-TitleContent Ldt-live-editable" data-editable_value="{{title}}" data-editable_type="multiline" data-editable_id="{{id}}" data-editable_field="title">{{{htitle}}}</span>{{/show_title}}' +
       
   291       '{{#show_creator}}<span class="Ldt-AnnotationsList-Creator">{{ creator }}</span>{{/show_creator}}' +
       
   292       "</h3>" +
       
   293       '<p class="Ldt-AnnotationsList-Description Ldt-live-editable" data-editable_type="multiline" data-editable_value="{{description}}" data-editable_id="{{id}}" data-editable_field="description">{{{hdescription}}}</p>' +
       
   294       "{{#created}}" +
       
   295       '<div class="Ldt-AnnotationsList-CreationDate">{{{created}}}</div>' +
       
   296       "{{/created}}" +
       
   297       "{{#tags.length}}" +
       
   298       '<ul class="Ldt-AnnotationsList-Tags">' +
       
   299       "{{#tags}}" +
       
   300       "{{#.}}" +
       
   301       '<li class="Ldt-AnnotationsList-Tag-Li">' +
       
   302       "<span>{{.}}</span>" +
       
   303       "</li>" +
       
   304       "{{/.}}" +
       
   305       "{{/tags}}" +
       
   306       "</ul>" +
       
   307       "{{/tags.length}}" +
       
   308       '{{#audio}}<div class="Ldt-AnnotationsList-Play" data-annotation-id="{{id}}">{{l10n.voice_annotation}}</div>{{/audio}}' +
       
   309       '<div class="Ldt-AnnotationsList-EditControls">' +
       
   310       '{{#show_twitter}}<a title="{{l10n.tweet_annotation}}" target="_blank" href="https://twitter.com/intent/tweet?{{twitter_param}}"><img width="16" height="16" src="metadataplayer/img/twitter.svg"></a>{{/show_twitter}}' +
       
   311       '{{#show_publish}}<div title="{{l10n.publish_annotation}}" class="Ldt-AnnotationsList-PublishAnnotation" data-editable_id="{{id}}"></div>{{/show_publish}}' +
       
   312       '{{#editable}}<div title="{{l10n.edit_annotation}}" class="Ldt-AnnotationsList-Edit" data-editable_id="{{id}}"></div>' +
       
   313       '<div title="{{l10n.delete_annotation}}" class="Ldt-AnnotationsList-Delete" data-editable_id="{{id}}"></div>{{/editable}}' +
       
   314       "</div>" +
       
   315       "</li>";
       
   316 
       
   317     // obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project
       
   318     // + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id;
       
   319 
       
   320     ajaxSource() {
       
   321       var _currentTime = this.media.getCurrentTime(),
       
   322         _duration = this.media.duration;
       
   323       this.lastAjaxQuery = _currentTime;
       
   324       var _url = Mustache.render(this.ajax_url, {
       
   325         media: this.source.currentMedia.id,
       
   326         begin: Math.max(0, _currentTime - this.ajax_granularity),
       
   327         end: Math.min(
       
   328           _duration.milliseconds,
       
   329           _currentTime + this.ajax_granularity
       
   330         ),
       
   331       });
       
   332       this.currentSource = this.player.loadMetadata(
       
   333         _.defaults(
       
   334           {
       
   335             url: _url,
       
   336           },
       
   337           this.metadata
       
   338         )
       
   339       );
   204     }
   340     }
   205 };
   341 
   206 
   342     showScreen(_screenName) {
   207 IriSP.Widgets.AnnotationsList.prototype.template =
   343       this.$.find(".Ldt-AnnotationsList-Screen" + _screenName)
   208     '{{#show_header}}<p class="Ldt-AnnotationsList-header">'
   344         .show()
   209     +     '{{#custom_header}}{{custom_header}}{{/custom_header}}'
   345         .siblings()
   210     +     '{{^custom_header}}{{l10n.header}}{{/custom_header}}'
   346         .hide();
   211     + '</p>{{/show_header}}'
   347     }
   212     + '<div class="Ldt-AnnotationsListWidget">'
   348 
   213     +     '<div class="Ldt-AnnotationsList-ScreenMain">'
   349     ajaxMashup() {
   214     +         '{{#show_filters}}'
   350       var _currentTime = this.media.getCurrentTime();
   215     +         '<div class="Ldt-AnnotationsList-Filters">'
   351       var _currentAnnotation =
   216     +             '{{#keyword_filter}}<input class="Ldt-AnnotationsList-filter-text" id="Ldt-AnnotationsList-keywordsFilter" type="text" value=""></input>{{/keyword_filter}}'
   352         this.source.currentMedia.getAnnotationAtTime(_currentTime);
   217     +             '{{#user_filter}}<select class="Ldt-AnnotationsList-filter-dropdown" id="Ldt-AnnotationsList-userFilter"><option selected value="">{{l10n.everyone}}</option></select>{{/user_filter}}'
   353       if (
   218     +             '{{#date_filter}}<label class="Ldt-AnnotationsList-filter-date">Date: <input id="Ldt-AnnotationsList-dateFilter" type="text"></input></label>{{/date_filter}}'
   354         typeof _currentAnnotation !== "undefined" &&
   219     +             '{{#segment_filter}}<label class="Ldt-AnnotationsList-filter-checkbox"><input type="checkbox" id="Ldt-AnnotationsList-ignoreSegmentsFilter">{{l10n.segment_filter}}</label>{{/segment_filter}}'
   355         _currentAnnotation.id !== this.lastMashupAnnotation
   220     +             '{{#latest_contributions_filter}}<label class="Ldt-AnnotationsList-filter-checkbox"><input type="checkbox" id="Ldt-AnnotationsList-latestContributionsFilter">{{l10n.latest_contributions}}</label>{{/latest_contributions_filter}}'
   356       ) {
   221     +         '</div>'
       
   222     +         '{{/show_filters}}'
       
   223     +         '{{#show_controls}}<div class="Ldt-AnnotationsList-Controls"><span class="Ldt-AnnotationsList-Control-Prev">{{ l10n.previous }}</span> | <span class="Ldt-AnnotationsList-Control-Next">{{ l10n.next }}</span></div>{{/show_controls}}'
       
   224     +         '{{#show_audio}}<div class="Ldt-AnnotationsList-Audio"></div>{{/show_audio}}'
       
   225     +         '<ul class="Ldt-AnnotationsList-ul">'
       
   226     +         '</ul>'
       
   227     +     '</div>'    
       
   228     +     '{{#allow_annotations_deletion}}'
       
   229     +     '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenDelete">'
       
   230     +         '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>' 
       
   231     +         '{{l10n.annotation_deletion_delete}}'
       
   232     +         '<ul class="Ldt-AnnotationsList-ul-ToDelete"></ul>'
       
   233     +         '<a class="Ldt-AnnotationsList-ConfirmDelete">{{l10n.confirm}}</a> <a class="Ldt-AnnotationsList-CancelDelete">{{l10n.cancel}}</a>'
       
   234     +     '</div>'
       
   235     +     '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSending">'
       
   236     +         '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'  
       
   237     +         '{{l10n.annotation_deletion_sending}}'
       
   238     +     '</div>'
       
   239     +     '<div data-annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenSuccess">'
       
   240     +         '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'  
       
   241     +         '{{l10n.annotation_deletion_success}}'
       
   242     +     '</div>'
       
   243     +     '<div data.annotation="{{id}}" class="Ldt-AnnotationsList-Screen Ldt-AnnotationsList-ScreenError">'
       
   244     +         '<a title="{{l10n.close_widget}}" class="Ldt-AnnotationsList-Close" href="#"></a>'  
       
   245     +         '{{l10n.annotation_deletion_error}}'
       
   246     +     '</div>'
       
   247     +     '{{/allow_annotations_deletion}}'
       
   248     + '</div>';
       
   249 
       
   250 IriSP.Widgets.AnnotationsList.prototype.annotationTemplate =
       
   251     '<li class="Ldt-AnnotationsList-li Ldt-Highlighter-Annotation Ldt-TraceMe" data-annotation="{{ id }}" data-begin="{{ begin_ms }}" data-end="{{ end_ms }}" trace-info="annotation-id:{{id}}, media-id:{{media_id}}" style="{{specific_style}}">'
       
   252     + '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-ThumbContainer Ldt-AnnotationsList-Annotation-Screen Ldt-AnnotationsList-Annotation-ScreenMain">'
       
   253     +   '<a {{#url}}href="{{url}}"{{/url}} draggable="true">'
       
   254     +     '<img title="{{^external}}{{ begin }} - {{ end }}{{/external}}{{#external}}{{l10n.external_annotation}}{{/external}}" class="Ldt-AnnotationsList-Thumbnail" src="{{thumbnail}}" />'
       
   255     +     '{{#external}}<div title="{{l10n.external_annotation}}" class="Ldt-AnnotationsList-External-Icon"></div>{{/external}}'
       
   256     +   '</a>'
       
   257     + '</div>'
       
   258     + '{{#allow_annotations_deletion}}'
       
   259     + '<div data-annotation="{{ id }}" class="Ldt-AnnotationsList-DeleteButton">&#10006;</div>'
       
   260     + '{{/allow_annotations_deletion}}'
       
   261     + '{{#show_timecode}}<div title="{{l10n.set_time}}" class="Ldt-AnnotationsList-Duration"><span class="Ldt-AnnotationsList-Begin Ldt-live-editable Ldt-AnnotationsList-TimeEdit" data-editable_value="{{begin}}" data-editable_id="{{id}}" data-editable_field="begin" data-editable_type="timestamp">{{begin}}</span>{{#show_end_time}} - <span class="Ldt-AnnotationsList-End Ldt-live-editable" data-editable_value="{{end}}" data-editable_id="{{id}}" data-editable_field="end" data-editable_type="timestamp">{{end}}</span>{{/show_end_time}}</div>{{/show_timecode}}'
       
   262     + '<h3 class="Ldt-AnnotationsList-Title Ldt-Annotation-Timecode" data-timecode="{{ begin_ms }}" draggable="true">'
       
   263     + '{{#show_title}}<span class="Ldt-AnnotationsList-TitleContent Ldt-live-editable" data-editable_value="{{title}}" data-editable_type="multiline" data-editable_id="{{id}}" data-editable_field="title">{{{htitle}}}</span>{{/show_title}}'
       
   264     + '{{#show_creator}}<span class="Ldt-AnnotationsList-Creator">{{ creator }}</span>{{/show_creator}}'
       
   265     + '</h3>'
       
   266     + '<p class="Ldt-AnnotationsList-Description Ldt-live-editable" data-editable_type="multiline" data-editable_value="{{description}}" data-editable_id="{{id}}" data-editable_field="description">{{{hdescription}}}</p>'
       
   267     + '{{#created}}'
       
   268     + '<div class="Ldt-AnnotationsList-CreationDate">{{{created}}}</div>'
       
   269     + '{{/created}}'
       
   270     + '{{#tags.length}}'
       
   271     + '<ul class="Ldt-AnnotationsList-Tags">'
       
   272     +   '{{#tags}}'
       
   273     +   '{{#.}}'
       
   274     +   '<li class="Ldt-AnnotationsList-Tag-Li">'
       
   275     +     '<span>{{.}}</span>'
       
   276     +   '</li>'
       
   277     +   '{{/.}}'
       
   278     +   '{{/tags}}'
       
   279     + '</ul>'
       
   280     + '{{/tags.length}}'
       
   281     + '{{#audio}}<div class="Ldt-AnnotationsList-Play" data-annotation-id="{{id}}">{{l10n.voice_annotation}}</div>{{/audio}}'
       
   282     + '<div class="Ldt-AnnotationsList-EditControls">'
       
   283     +    '{{#show_twitter}}<a title="{{l10n.tweet_annotation}}" target="_blank" href="https://twitter.com/intent/tweet?{{twitter_param}}"><img width="16" height="16" src="metadataplayer/img/twitter.svg"></a>{{/show_twitter}}'
       
   284     +    '{{#show_publish}}<div title="{{l10n.publish_annotation}}" class="Ldt-AnnotationsList-PublishAnnotation" data-editable_id="{{id}}"></div>{{/show_publish}}'
       
   285     +    '{{#editable}}<div title="{{l10n.edit_annotation}}" class="Ldt-AnnotationsList-Edit" data-editable_id="{{id}}"></div>'
       
   286     +    '<div title="{{l10n.delete_annotation}}" class="Ldt-AnnotationsList-Delete" data-editable_id="{{id}}"></div>{{/editable}}'
       
   287     + '</div>'
       
   288     + '</li>';
       
   289 
       
   290 // obj.url = this.project_url + "/" + media + "/" + annotations[i].meta.project
       
   291 // + "/" + annotations[i].meta["id-ref"] + '#id=' + annotations[i].id;
       
   292 
       
   293 IriSP.Widgets.AnnotationsList.prototype.ajaxSource = function() {
       
   294     var _currentTime = this.media.getCurrentTime(),
       
   295         _duration = this.media.duration;
       
   296     this.lastAjaxQuery = _currentTime;
       
   297     var _url = Mustache.to_html(this.ajax_url, {
       
   298         media : this.source.currentMedia.id,
       
   299         begin : Math.max(0, _currentTime - this.ajax_granularity),
       
   300         end : Math.min(_duration.milliseconds, _currentTime + this.ajax_granularity)
       
   301     });
       
   302     this.currentSource = this.player.loadMetadata(IriSP._.defaults({
       
   303         "url" : _url
       
   304     }, this.metadata));
       
   305 };
       
   306 
       
   307 IriSP.Widgets.AnnotationsList.prototype.showScreen = function(_screenName) {
       
   308     this.$.find('.Ldt-AnnotationsList-Screen' + _screenName).show()
       
   309         .siblings().hide();
       
   310 }
       
   311 
       
   312 IriSP.Widgets.AnnotationsList.prototype.ajaxMashup = function() {
       
   313     var _currentTime = this.media.getCurrentTime();
       
   314     var _currentAnnotation = this.source.currentMedia.getAnnotationAtTime(_currentTime);
       
   315     if (typeof _currentAnnotation !== "undefined" && _currentAnnotation.id !== this.lastMashupAnnotation) {
       
   316         this.lastMashupAnnotation = _currentAnnotation.id;
   357         this.lastMashupAnnotation = _currentAnnotation.id;
   317         var _currentMedia = _currentAnnotation.getMedia(),
   358         var _currentMedia = _currentAnnotation.getMedia(),
   318             _url = Mustache.to_html(this.ajax_url, {
   359           _url = Mustache.render(this.ajax_url, {
   319                 media : _currentMedia.id,
   360             media: _currentMedia.id,
   320                 begin : Math.max(0, _currentAnnotation.annotation.begin.milliseconds - this.ajax_granularity),
   361             begin: Math.max(
   321                 end : Math.min(_currentMedia.duration.milliseconds, _currentAnnotation.annotation.end.milliseconds + this.ajax_granularity)
   362               0,
   322             });
   363               _currentAnnotation.annotation.begin.milliseconds -
   323         this.currentSource = this.player.loadMetadata(IriSP._.defaults({
   364                 this.ajax_granularity
   324             "url" : _url
   365             ),
   325         }, this.metadata));
   366             end: Math.min(
       
   367               _currentMedia.duration.milliseconds,
       
   368               _currentAnnotation.annotation.end.milliseconds +
       
   369                 this.ajax_granularity
       
   370             ),
       
   371           });
       
   372         this.currentSource = this.player.loadMetadata(
       
   373           _.defaults(
       
   374             {
       
   375               url: _url,
       
   376             },
       
   377             this.metadata
       
   378           )
       
   379         );
       
   380       }
   326     }
   381     }
   327 };
   382 
   328 
   383     /*
   329 /*
   384      * Import annotations
   330  * Import annotations
   385      */
   331  */
   386     importAnnotations() {
   332 IriSP.Widgets.AnnotationsList.prototype.importAnnotations = function () {
   387       var widget = this;
   333     var widget = this;
   388       var $ = jQuery;
   334     var $ = IriSP.jQuery;
   389       var textarea = $("<textarea>");
   335     var textarea = $("<textarea>");
   390       var el = $("<div>")
   336     var el = $("<div>")
   391         .append(
   337             .append($("<span>")
   392           $("<span>")
   338                     .addClass("importAnnotationsLabel")
   393             .addClass("importAnnotationsLabel")
   339                     .text(widget.messages.import_annotations))
   394             .text(widget.messages.import_annotations)
   340             .addClass("importContainer")
   395         )
   341             .dialog({
   396         .addClass("importContainer")
   342                 title: "Annotation import",
   397         .dialog({
   343                 autoOpen: true,
   398           title: "Annotation import",
   344                 width: '80%',
   399           autoOpen: true,
   345                 minHeight: '400',
   400           width: "80%",
   346                 height: 400,
   401           minHeight: "400",
   347                 buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } },
   402           height: 400,
   348                            // { text: "Load", click: function () {
   403           buttons: [
   349                            //     // TODO
   404             {
   350                            //     // http://www.html5rocks.com/en/tutorials/file/dndfiles/?redirect_from_locale=fr
   405               text: "Close",
   351                            //     console.log("Load from a file");
   406               click: function () {
   352                            // } },
   407                 $(this).dialog("close");
   353                            { text: "Import", click: function () {
   408               },
   354                                // FIXME: this should be a model.Source method
   409             },
   355                                var time_regexp = /(\[[\d:]+\])/;
   410             // { text: "Load", click: function () {
   356                                console.log("Import data");
   411             //     // TODO
   357                                // widget.localSource
   412             //     // http://www.html5rocks.com/en/tutorials/file/dndfiles/?redirect_from_locale=fr
   358                                // Dummy parsing for the moment
   413             //     console.log("Load from a file");
   359                                var data = textarea[0].value
   414             // } },
   360                                        .split(time_regexp)
   415             {
   361                                        .filter( function (s) { return ! s.match(/^\s*$/)});
   416               text: "Import",
   362                                var begin = null,
   417               click: function () {
   363                                    end = null,
   418                 // FIXME: this should be a model.Source method
   364                                    content = null,
   419                 var time_regexp = /(\[[\d:]+\])/;
   365                                    // Previous is either null, timestamp or text
   420                 // widget.localSource
   366                                    previous = null;
   421                 // Dummy parsing for the moment
   367                                for (var i = 0; i < data.length; i++) {
   422                 var data = textarea[0].value
   368                                    var el = data[i];
   423                   .split(time_regexp)
   369                                    if (el.match(time_regexp)) {
   424                   .filter(function (s) {
   370                                        if (previous == 'text') {
   425                     return !s.match(/^\s*$/);
   371                                            // Timestamp following text. Let's make it an annotation
   426                   });
   372                                            end = IriSP.timestamp2ms(el.slice(1, -1));
   427                 var begin = null,
   373                                            TODO.createAnnotation(begin, end, content);
   428                   end = null,
   374                                            // Preserve the end value, which may be the begin value of the next annotation.
   429                   content = null,
   375                                            begin = end;
   430                   // Previous is either null, timestamp or text
   376                                            end = null;
   431                   previous = null;
   377                                            content = null;
   432                 for (var i = 0; i < data.length; i++) {
   378                                        } else {
   433                   var el = data[i];
   379                                            //  (previous == 'timestamp' || previous == null)
   434                   if (el.match(time_regexp)) {
   380                                            // 2 consecutive timestamps. Let's start a new annotation
   435                     if (previous == "text") {
   381                                            content = null;
   436                       // Timestamp following text. Let's make it an annotation
   382                                            begin = IriSP.timestamp2ms(el.slice(1, -1));
   437                       end = ns.timestamp2ms(el.slice(1, -1));
   383                                            end = null;
   438                       TODO.createAnnotation(begin, end, content);
   384                                        };
   439                       // Preserve the end value, which may be the begin value of the next annotation.
   385                                        previous = 'timestamp';
   440                       begin = end;
   386                                    } else {
   441                       end = null;
   387                                        // Text content
   442                       content = null;
   388                                        content = el;
   443                     } else {
   389                                        previous = 'text';
   444                       //  (previous == 'timestamp' || previous == null)
   390                                    }
   445                       // 2 consecutive timestamps. Let's start a new annotation
   391                                    // Last textual value
   446                       content = null;
   392                                    if (previous == 'text' && begin !== null) {
   447                       begin = ns.timestamp2ms(el.slice(1, -1));
   393                                        TODO.createAnnotation(begin, begin, content);
   448                       end = null;
   394                                    }
   449                     }
   395                                }
   450                     previous = "timestamp";
   396                            } } ]
   451                   } else {
   397             });
   452                     // Text content
   398 
   453                     content = el;
   399 }
   454                     previous = "text";
   400 
   455                   }
   401 IriSP.Widgets.AnnotationsList.prototype.refresh = function(_forceRedraw) {
   456                   // Last textual value
   402     _forceRedraw = (typeof _forceRedraw !== "undefined" && _forceRedraw);
   457                   if (previous == "text" && begin !== null) {
   403     if (this.currentSource.status !== IriSP.Model._SOURCE_STATUS_READY) {
   458                     TODO.createAnnotation(begin, begin, content);
       
   459                   }
       
   460                 }
       
   461               },
       
   462             },
       
   463           ],
       
   464         });
       
   465     }
       
   466 
       
   467     refresh(_forceRedraw) {
       
   468       _forceRedraw = typeof _forceRedraw !== "undefined" && _forceRedraw;
       
   469       if (this.currentSource.status !== ns.Model._SOURCE_STATUS_READY) {
   404         return 0;
   470         return 0;
   405     }
   471       }
   406     var _this = this,
   472       var _this = this,
   407         _currentTime = this.media.getCurrentTime();
   473         _currentTime = this.media.getCurrentTime();
   408     var _list = this.annotation_type ? this.currentSource.getAnnotationsByTypeTitle(this.annotation_type) : this.currentSource.getAnnotations();
   474       var _list = this.annotation_type
   409     if (this.mashupMode) {
   475         ? this.currentSource.getAnnotationsByTypeTitle(this.annotation_type)
   410         var _currentAnnotation = this.source.currentMedia.getAnnotationAtTime(_currentTime);
   476         : this.currentSource.getAnnotations();
       
   477       if (this.mashupMode) {
       
   478         var _currentAnnotation =
       
   479           this.source.currentMedia.getAnnotationAtTime(_currentTime);
   411         if (typeof _currentAnnotation !== "undefined") {
   480         if (typeof _currentAnnotation !== "undefined") {
   412             _currentTime = _currentTime - _currentAnnotation.begin + _currentAnnotation.annotation.begin;
   481           _currentTime =
   413             var _mediaId = _currentAnnotation.getMedia().id;
   482             _currentTime -
   414             _list = _list.filter(function(_annotation) {
   483             _currentAnnotation.begin +
   415                 return _annotation.getMedia().id === _mediaId;
   484             _currentAnnotation.annotation.begin;
   416             });
   485           var _mediaId = _currentAnnotation.getMedia().id;
   417         }
   486           _list = _list.filter(function (_annotation) {
   418     }
   487             return _annotation.getMedia().id === _mediaId;
   419     _list = _list.filter(function(_annotation) {
   488           });
       
   489         }
       
   490       }
       
   491       _list = _list.filter(function (_annotation) {
   420         return _annotation.found !== false;
   492         return _annotation.found !== false;
   421     });
   493       });
   422     
   494 
   423     if ((this.filter_by_segments)&&(!(this.show_filters && this.segment_filter && this.ignoresegmentcheckbox_$[0].checked))) {
   495       if (
       
   496         this.filter_by_segments &&
       
   497         !(
       
   498           this.show_filters &&
       
   499           this.segment_filter &&
       
   500           this.ignoresegmentcheckbox_$[0].checked
       
   501         )
       
   502       ) {
   424         /*
   503         /*
   425          *  A given annotation is considered "in" segment if the middle of it is between the segment beginning and the segment end. 
   504          *  A given annotation is considered "in" segment if the middle of it is between the segment beginning and the segment end.
   426          *  Note this is meant to be used for "markings" annotations (not segments)
   505          *  Note this is meant to be used for "markings" annotations (not segments)
   427          */
   506          */
   428         _segmentsAnnotation = this.currentSource.getAnnotationsByTypeTitle(this.segments_annotation_type)
   507         _segmentsAnnotation = this.currentSource.getAnnotationsByTypeTitle(
   429         if (this.media.getTimeRange()){
   508           this.segments_annotation_type
   430             _currentSegments = _segmentsAnnotation.filter(function(_segment){
   509         );
   431                 return (_this.media.getTimeRange()[0] == _segment.begin && _this.media.getTimeRange()[1] == _segment.end)
   510         if (this.media.getTimeRange()) {
       
   511           _currentSegments = _segmentsAnnotation.filter(function (_segment) {
       
   512             return (
       
   513               _this.media.getTimeRange()[0] == _segment.begin &&
       
   514               _this.media.getTimeRange()[1] == _segment.end
       
   515             );
       
   516           });
       
   517         } else {
       
   518           _currentSegments = _segmentsAnnotation.filter(function (_segment) {
       
   519             return (
       
   520               _currentTime >= _segment.begin && _currentTime <= _segment.end
       
   521             );
       
   522           });
       
   523         }
       
   524         if (_currentSegments.length == 0) {
       
   525           _list = _list.filter(function (_annotation) {
       
   526             return false;
       
   527           });
       
   528         } else {
       
   529           _list = _list.filter(function (_annotation) {
       
   530             _annotation_time = (_annotation.begin + _annotation.end) / 2;
       
   531             return (
       
   532               _currentSegments[0].begin <= _annotation_time &&
       
   533               _currentSegments[0].end >= _annotation_time
       
   534             );
       
   535           });
       
   536         }
       
   537         if (
       
   538           this.annotations_count_header &&
       
   539           this.annotations_count != _list.length
       
   540         ) {
       
   541           this.annotations_count = _list.length;
       
   542           this.refreshHeader();
       
   543         }
       
   544       }
       
   545       if (this.show_only_annotation_from_user) {
       
   546         _list = _list.filter(function (_annotation) {
       
   547           return _annotation.creator == _this.show_only_annotation_from_user;
       
   548         });
       
   549       }
       
   550       if (this.limit_count) {
       
   551         /* Get the n annotations closest to current timecode */
       
   552         _list = _list
       
   553           .sortBy(function (_annotation) {
       
   554             return Math.abs(
       
   555               (_annotation.begin + _annotation.end) / 2 - _currentTime
       
   556             );
       
   557           })
       
   558           .slice(0, this.limit_count);
       
   559       }
       
   560 
       
   561       if (this.newest_first) {
       
   562         _list = _list.sortBy(function (_annotation) {
       
   563           return -_annotation.created.valueOf();
       
   564         });
       
   565       } else {
       
   566         _list = _list.sortBy(function (_annotation) {
       
   567           return _annotation.begin;
       
   568         });
       
   569       }
       
   570 
       
   571       if (this.show_filters) {
       
   572         if (this.user_filter) {
       
   573           _username =
       
   574             this.userselect_$[0].options[this.userselect_$[0].selectedIndex]
       
   575               .value;
       
   576           if (_username != "false") {
       
   577             _list = _list.filter(function (_annotation) {
       
   578               return _annotation.creator == _username;
   432             });
   579             });
   433         }
   580           }
   434         else {
   581         }
   435             _currentSegments = _segmentsAnnotation.filter(function(_segment){
   582         if (this.keyword_filter) {
   436                 return (_currentTime >= _segment.begin && _currentTime <= _segment.end)
   583           _keyword = this.keywordinput_$[0].value;
       
   584           if (_keyword != "") {
       
   585             _list = _list.filter(function (_annotation) {
       
   586               return _annotation.description
       
   587                 .toLowerCase()
       
   588                 .match(_keyword.toLowerCase());
   437             });
   589             });
   438         }
   590           }
   439         if (_currentSegments.length == 0) {
   591         }
   440             _list = _list.filter(function(_annotation){
   592         if (this.date_filter) {
   441                 return false;
   593           if (this.datefilterinput_$[0].value != "") {
       
   594             _date = this.datefilterinput_$.datepicker("getDate");
       
   595             _list = _list.filter(function (_annotation) {
       
   596               return (
       
   597                 _annotation.created.getDate() == _date.getDate() &&
       
   598                 _annotation.created.getMonth() == _date.getMonth() &&
       
   599                 _annotation.created.getFullYear() == _date.getFullYear()
       
   600               );
   442             });
   601             });
   443         }
   602           }
   444         else {
   603         }
   445             _list = _list.filter(function(_annotation){
   604         if (
   446                 _annotation_time = (_annotation.begin+_annotation.end)/2;
   605           this.latest_contributions_filter &&
   447                 return (_currentSegments[0].begin <= _annotation_time && _currentSegments[0].end >= _annotation_time)
   606           this.latestcontributionscheckbox_$[0].checked
       
   607         ) {
       
   608           _list = _list.sortBy(function (_annotation) {
       
   609             return -_annotation.created.valueOf();
       
   610           });
       
   611           this.usernames.forEach(function (_user) {
       
   612             latest_ann = _list.filter(function (_annotation) {
       
   613               return _annotation.creator == _user;
       
   614             })[0];
       
   615             _list = _list.filter(function (_annotation) {
       
   616               return (
       
   617                 _annotation.id == (latest_ann ? latest_ann.id : false) ||
       
   618                 _annotation.creator != _user
       
   619               );
   448             });
   620             });
   449         }
   621           });
   450         if(this.annotations_count_header && this.annotations_count != _list.length){
   622         }
   451             this.annotations_count = _list.length;
   623       }
   452             this.refreshHeader();
   624 
   453         }
   625       var _ids = _list.idIndex;
   454     }
   626 
   455     if (this.show_only_annotation_from_user){
   627       if (
   456         _list = _list.filter(function(_annotation){
   628         _forceRedraw ||
   457            return _annotation.creator == _this.show_only_annotation_from_user;
   629         !_.isEqual(_ids, this.lastIds) ||
   458         });
   630         this.searchString !== this.lastSearch
   459     }
   631       ) {
   460     if (this.limit_count) {
       
   461         /* Get the n annotations closest to current timecode */
       
   462         _list = _list.sortBy(function(_annotation) {
       
   463             return Math.abs((_annotation.begin + _annotation.end) / 2 - _currentTime);
       
   464         }).slice(0, this.limit_count);
       
   465     }
       
   466     
       
   467     if (this.newest_first) {
       
   468         _list = _list.sortBy(function(_annotation) {
       
   469             return -_annotation.created.valueOf();
       
   470         });
       
   471     } else {
       
   472         _list = _list.sortBy(function(_annotation) {
       
   473             return _annotation.begin;
       
   474         });
       
   475     }
       
   476     
       
   477     if (this.show_filters){
       
   478         if (this.user_filter){
       
   479             _username = this.userselect_$[0].options[this.userselect_$[0].selectedIndex].value;
       
   480             if (_username != "false")
       
   481             {
       
   482                 _list = _list.filter(function(_annotation){
       
   483                     return _annotation.creator == _username
       
   484                 })
       
   485             }
       
   486         }
       
   487         if (this.keyword_filter){
       
   488         _keyword = this.keywordinput_$[0].value;
       
   489             if (_keyword != ""){
       
   490                 _list = _list.filter(function(_annotation){
       
   491                    return _annotation.description.toLowerCase().match(_keyword.toLowerCase());
       
   492                 });
       
   493             }
       
   494         }
       
   495         if (this.date_filter){
       
   496             if(this.datefilterinput_$[0].value != ""){
       
   497                 _date = this.datefilterinput_$.datepicker("getDate");
       
   498                 _list = _list.filter(function(_annotation){
       
   499                     return ((_annotation.created.getDate() == _date.getDate())&&(_annotation.created.getMonth() == _date.getMonth())&&(_annotation.created.getFullYear() == _date.getFullYear()));
       
   500                 });
       
   501             }
       
   502         }
       
   503         if (this.latest_contributions_filter && this.latestcontributionscheckbox_$[0].checked){
       
   504             _list = _list.sortBy(function(_annotation) {
       
   505                 return -_annotation.created.valueOf();
       
   506             });
       
   507             this.usernames.forEach(function(_user){
       
   508                 
       
   509                 latest_ann = _list.filter(function(_annotation){
       
   510                     return _annotation.creator == _user;
       
   511                 })[0];
       
   512                 _list = _list.filter(function(_annotation){
       
   513                     return _annotation.id == (latest_ann ? latest_ann.id : false) || _annotation.creator != _user;
       
   514                 });
       
   515             });
       
   516         }
       
   517         
       
   518     }
       
   519     
       
   520     var _ids = _list.idIndex;
       
   521 
       
   522     if (_forceRedraw || !IriSP._.isEqual(_ids, this.lastIds) || this.searchString !== this.lastSearch) {
       
   523         /* This part only gets executed if the list needs updating */
   632         /* This part only gets executed if the list needs updating */
   524         this.lastSearch = this.searchString;
   633         this.lastSearch = this.searchString;
   525         this.lastIds = _ids;
   634         this.lastIds = _ids;
   526         this.list_$.html("");
   635         this.list_$.html("");
   527         _list.forEach(function(_annotation) {
   636         _list.forEach(function (_annotation) {
   528             var _url = (
   637           var _url =
   529                 ( typeof _annotation.url !== "undefined" && _annotation.url)
   638               typeof _annotation.url !== "undefined" && _annotation.url
   530                 ? _annotation.url
   639                 ? _annotation.url
   531                 : (
   640                 : typeof _this.source.projectId !== "undefined" &&
   532                     ( typeof _this.source.projectId !== "undefined" && typeof _annotation.project !== "undefined" && _annotation.project && _this.source.projectId !== _annotation.project )
   641                   typeof _annotation.project !== "undefined" &&
   533                     ? Mustache.to_html(
   642                   _annotation.project &&
   534                         _this.foreign_url,
   643                   _this.source.projectId !== _annotation.project
   535                         {
   644                 ? Mustache.render(_this.foreign_url, {
   536                             project : _annotation.project,
   645                     project: _annotation.project,
   537                             media : _annotation.media.id,
   646                     media: _annotation.media.id,
   538                             annotation : _annotation.id,
   647                     annotation: _annotation.id,
   539                             annotationType : _annotation.annotationType.id
   648                     annotationType: _annotation.annotationType.id,
   540                         }
   649                   })
   541                     )
   650                 : document.location.href.replace(/#.*$/, "") +
   542                     : document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id + '&t=' + (_annotation.begin / 1000.0)
   651                   "#id=" +
   543                     )
   652                   _annotation.id +
   544                 ),
   653                   "&t=" +
   545                 _external = _annotation.project != _this.source.projectId ? true : false,
   654                   _annotation.begin / 1000.0,
   546                 _title = "",
   655             _external =
   547                 _description = _annotation.description,
   656               _annotation.project != _this.source.projectId ? true : false,
   548                 _thumbnail = (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail ? _annotation.thumbnail : _this.default_thumbnail);
   657             _title = "",
   549             if (_this.show_creator){
   658             _description = _annotation.description,
   550                 if (_annotation.creator) {
   659             _thumbnail =
   551                     var _users = [],
   660               typeof _annotation.thumbnail !== "undefined" &&
   552                         _user = {},
   661               _annotation.thumbnail
   553                         _creator = "";
   662                 ? _annotation.thumbnail
   554                     if (_this.source.users_data) {
   663                 : _this.default_thumbnail;
   555                         _users = _this.source.users_data.filter(function(_user_data){
   664           if (_this.show_creator) {
   556                             return _user_data.username == _annotation.creator;
   665             if (_annotation.creator) {
   557                         });
   666               var _users = [],
   558                     }
   667                 _user = {},
   559                     if (_users.length == 0){
   668                 _creator = "";
   560                         _user.username = _annotation.creator
   669               if (_this.source.users_data) {
   561                     }
   670                 _users = _this.source.users_data.filter(function (_user_data) {
   562                     else{
   671                   return _user_data.username == _annotation.creator;
   563                         _user = _users[0]
   672                 });
   564                     }
   673               }
   565                     _creator = _this.make_name_string_function(_user);
   674               if (_users.length == 0) {
       
   675                 _user.username = _annotation.creator;
       
   676               } else {
       
   677                 _user = _users[0];
       
   678               }
       
   679               _creator = _this.make_name_string_function(_user);
       
   680             }
       
   681           }
       
   682           if (_this.show_title && _annotation.title) {
       
   683             var _title = _annotation.title;
       
   684           }
       
   685           var _bgcolor;
       
   686           _(_this.polemics).each(function (_polemic) {
       
   687             var _rgxp = ns.Model.regexpFromTextOrArray(
       
   688               _polemic.keyword,
       
   689               true
       
   690             );
       
   691             if (_rgxp.test(_title + " " + _description)) {
       
   692               _bgcolor = _polemic.background_color;
       
   693             }
       
   694           });
       
   695           var _created = false;
       
   696           if (_this.show_creation_date) {
       
   697             _created =
       
   698               _annotation.created.toLocaleDateString() +
       
   699               ", " +
       
   700               _annotation.created
       
   701                 .toLocaleTimeString()
       
   702                 .replace(/\u200E/g, "")
       
   703                 .replace(/^([^\d]*\d{1,2}:\d{1,2}):\d{1,2}([^\d]*)$/, "$1$2");
       
   704           }
       
   705           if (_this.tags == true) {
       
   706             var _tags = _annotation.getTagTexts();
       
   707           } else {
       
   708             var _tags = false;
       
   709           }
       
   710           var _data = {
       
   711             id: _annotation.id,
       
   712             media_id: _annotation.getMedia().id,
       
   713             htitle: ns.textFieldHtml(_title),
       
   714             title: _title,
       
   715             creator: _creator,
       
   716             hdescription: ns.textFieldHtml(_description),
       
   717             description: _description,
       
   718             begin: _annotation.begin.toString(),
       
   719             end: _annotation.end.toString(),
       
   720             created: _created,
       
   721             show_timecode: _this.show_timecode,
       
   722             show_end_time: _this.show_end_time,
       
   723             show_title: _this.show_title && _title,
       
   724             thumbnail: _thumbnail,
       
   725             url: _url,
       
   726             tags: _tags,
       
   727             specific_style:
       
   728               typeof _bgcolor !== "undefined"
       
   729                 ? "background-color: " + _bgcolor
       
   730                 : "",
       
   731             l10n: _this.l10n,
       
   732             editable: _this.editable,
       
   733             external: _external,
       
   734             show_publish: _this.show_publish,
       
   735             show_creator: _this.show_creator,
       
   736             show_twitter: _this.show_twitter,
       
   737             twitter_param: jQuery.param({
       
   738               url: _url,
       
   739               text:
       
   740                 ns.textFieldHtml(_title) +
       
   741                 (_this.twitter_hashtag ? " #" + _this.twitter_hashtag : ""),
       
   742             }),
       
   743             allow_annotations_deletion: _this.allow_annotations_deletion,
       
   744           };
       
   745           // if (
       
   746           //   _this.show_audio &&
       
   747           //   _annotation.audio &&
       
   748           //   _annotation.audio.href &&
       
   749           //   _annotation.audio.href != "null"
       
   750           // ) {
       
   751           //   _data.audio = true;
       
   752           //   if (!_this.jwplayers[_annotation.id]) {
       
   753           //     var _audiofile = _annotation.audio.href;
       
   754           //     if (_this.audio_url_transform) {
       
   755           //       _audiofile = _this.audio_url_transform(_annotation.audio.href);
       
   756           //     }
       
   757           //     var _tmpId = "jwplayer-" + ns.Model.getUID();
       
   758           //     _this.jwplayers[_annotation.id] = _tmpId;
       
   759           //     _this.$.find(".Ldt-AnnotationsList-Audio").append(
       
   760           //       jQuery("<div>").attr("id", _tmpId)
       
   761           //     );
       
   762           //     jwplayer(_tmpId).setup({
       
   763           //       //flashplayer: ns.getLib("jwPlayerSWF"),
       
   764           //       file: _audiofile,
       
   765           //       fallback: false,
       
   766           //       primary: "flash",
       
   767           //       controls: false,
       
   768           //       width: 1,
       
   769           //       height: 1,
       
   770           //       events: {
       
   771           //         onPause: function () {
       
   772           //           _this.$.find(
       
   773           //             ".Ldt-AnnotationsList-Play[data-annotation-id=" +
       
   774           //               _annotation.id +
       
   775           //               "]"
       
   776           //           ).text(_this.l10n.voice_annotation);
       
   777           //         },
       
   778           //         onPlay: function () {
       
   779           //           _this.$.find(
       
   780           //             ".Ldt-AnnotationsList-Play[data-annotation-id=" +
       
   781           //               _annotation.id +
       
   782           //               "]"
       
   783           //           ).text(_this.l10n.now_playing);
       
   784           //         },
       
   785           //       },
       
   786           //     });
       
   787           //   }
       
   788           //}
       
   789           var _html = Mustache.render(_this.constructor.annotationTemplate, _data),
       
   790             _el = jQuery(_html),
       
   791             _onselect = function () {
       
   792               _this.$.find(".Ldt-AnnotationsList-li").removeClass("selected");
       
   793               _el.addClass("selected");
       
   794             },
       
   795             _onunselect = function () {
       
   796               _this.$.find(".Ldt-AnnotationsList-li").removeClass("selected");
       
   797             };
       
   798           _el
       
   799             .mouseover(function () {
       
   800               _annotation.trigger("select");
       
   801             })
       
   802             .mouseout(function () {
       
   803               _annotation.trigger("unselect");
       
   804             })
       
   805             .click(function () {
       
   806               if (_this.filter_by_segments && _this.media.getTimeRange()) {
       
   807                 _ann_time = (_annotation.begin + _annotation.end) / 2;
       
   808                 if (
       
   809                   _ann_time <= _this.media.getTimeRange()[0] ||
       
   810                   _ann_time >= _this.media.getTimeRange()[1]
       
   811                 ) {
       
   812                   _this.media.resetTimeRange();
   566                 }
   813                 }
       
   814               }
       
   815               _annotation.trigger("click");
       
   816             })
       
   817             .appendTo(_this.list_$);
       
   818           ns.attachDndData(_el.find("[draggable]"), {
       
   819             title: _title,
       
   820             description: _description,
       
   821             uri: _url,
       
   822             image: _annotation.thumbnail,
       
   823             text: "[" + _annotation.begin.toString() + "] " + _title,
       
   824           });
       
   825           _el.on("remove", function () {
       
   826             _annotation.off("select", _onselect);
       
   827             _annotation.off("unselect", _onunselect);
       
   828           });
       
   829           _annotation.on("select", _onselect);
       
   830           _annotation.on("unselect", _onunselect);
       
   831         });
       
   832 
       
   833         /* Correct the empty tag bug */
       
   834         this.$.find(".Ldt-AnnotationsList-Tag-Li").each(function () {
       
   835           var _el = jQuery(this);
       
   836           if (!_el.text().replace(/(^\s+|\s+$)/g, "")) {
       
   837             _el.remove();
       
   838           }
       
   839         });
       
   840 
       
   841         if (this.editable) {
       
   842           var widget = _this;
       
   843           var $ = jQuery;
       
   844 
       
   845           var edit_element = function (_this, insertion_point) {
       
   846             var feedback_wrong = "#FF9999";
       
   847             var feedback_ok = "#99FF99";
       
   848 
       
   849             // insertion_point can be used to specify where to
       
   850             // insert the input field.  Firefox is buggy wrt input
       
   851             // fields inside <a> or <h?> tags, it does not
       
   852             // propagate mouse clicks. If _this is a <a> then we
       
   853             // have to specify the ancestor before which we can
       
   854             // insert the input widget.
       
   855             if (insertion_point === undefined) insertion_point = _this;
       
   856 
       
   857             // Insert input element
       
   858             var input_element = $(
       
   859               _this.dataset.editable_type === "multiline"
       
   860                 ? "<textarea>"
       
   861                 : "<input>"
       
   862             )
       
   863               .addClass("editableInput")
       
   864               .insertBefore($(insertion_point));
       
   865             input_element[0].value = _this.dataset.editable_value;
       
   866             $(input_element).show().focus();
       
   867             $(_this).addClass("editing");
       
   868 
       
   869             function feedback(color) {
       
   870               // Give some feedback
       
   871               $(_this).removeClass("editing");
       
   872               input_element.remove();
       
   873               var previous_color = $(_this).css("background-color");
       
   874               $(_this)
       
   875                 .stop()
       
   876                 .css("background-color", color)
       
   877                 .animate({ backgroundColor: previous_color }, 1000);
   567             }
   878             }
   568             if (_this.show_title && _annotation.title){
   879 
   569                     var _title = _annotation.title;
   880             function cancelChanges(s) {
       
   881               feedback(feedback_wrong);
   570             }
   882             }
   571             var _bgcolor;
   883             function validateChanges() {
   572             IriSP._(_this.polemics).each(function(_polemic) {
   884               var n = input_element[0].value;
   573                 var _rgxp = IriSP.Model.regexpFromTextOrArray(_polemic.keyword, true);
   885               if (n == _this.dataset.editable_value) {
   574                 if (_rgxp.test(_title + " " + _description)) {
   886                 // No change
   575                     _bgcolor = _polemic.background_color;
   887                 feedback(feedback_ok);
       
   888                 return;
       
   889               }
       
   890               if (n == "") {
       
   891                 // Delete annotation
       
   892                 delete_local_annotation(_this.dataset.editable_id);
       
   893                 widget.player.trigger(
       
   894                   "Annotation.delete",
       
   895                   _this.dataset.editable_id
       
   896                 );
       
   897                 return;
       
   898               } else {
       
   899                 // Convert value if necessary.
       
   900                 var val = n;
       
   901                 if (_this.dataset.editable_type == "timestamp") {
       
   902                   val = ns.timestamp2ms(n);
       
   903                   if (Number.isNaN(val)) {
       
   904                     // Invalid value. Cancel changes
       
   905                     cancelChanges();
       
   906                     return;
       
   907                   }
   576                 }
   908                 }
       
   909                 _this.dataset.editable_value = n;
       
   910                 n = val;
       
   911                 $(_this).text(val);
       
   912               }
       
   913 
       
   914               // We cannot use .getElement since it fetches
       
   915               // elements from the global Directory
       
   916               var an = get_local_annotation(_this.dataset.editable_id);
       
   917               if (an === undefined) {
       
   918                 console.log("Strange error: cannot find edited annotation");
       
   919                 feedback(feedback_wrong);
       
   920               } else {
       
   921                 _this.dataset.editable_value = n;
       
   922                 // Update annotation for storage
       
   923                 if (_this.dataset.editable_field == "begin") an.setBegin(n);
       
   924                 else if (_this.dataset.editable_field == "end") an.setEnd(n);
       
   925                 else an[_this.dataset.editable_field] = n;
       
   926                 an.modified = new Date();
       
   927                 // FIXME: use user name, when available
       
   928                 an.contributor = widget.player.config.username || "COCo User";
       
   929                 widget.player.addLocalAnnotation(an);
       
   930                 widget.player.trigger("Annotation.update", an);
       
   931                 feedback(feedback_ok);
       
   932               }
       
   933             }
       
   934             $(input_element)
       
   935               .bind("keydown", function (e) {
       
   936                 if (e.which == 13) {
       
   937                   e.preventDefault();
       
   938                   validateChanges();
       
   939                 } else if (e.which == 27) {
       
   940                   e.preventDefault();
       
   941                   cancelChanges();
       
   942                 }
       
   943               })
       
   944               .bind("blur", function (e) {
       
   945                 validateChanges();
       
   946               });
       
   947           };
       
   948 
       
   949           var get_local_annotation = function (ident) {
       
   950             return widget.player.getLocalAnnotation(ident);
       
   951           };
       
   952 
       
   953           var save_local_annotations = function () {
       
   954             widget.player.saveLocalAnnotations();
       
   955             // Merge modifications into widget source
       
   956             widget.source.merge(widget.player.localSource);
       
   957           };
       
   958 
       
   959           var delete_local_annotation = function (ident) {
       
   960             widget.source.getAnnotations().removeId(ident, true);
       
   961             widget.player.deleteLocalAnnotation(ident);
       
   962             widget.refresh(true);
       
   963           };
       
   964 
       
   965           this.$.find(".Ldt-AnnotationsList-Delete").click(function (e) {
       
   966             // Delete annotation
       
   967             var _annotation = get_local_annotation(this.dataset.editable_id);
       
   968             if (
       
   969               confirm(
       
   970                 Mustache.render(widget.l10n.confirm_delete_message, {
       
   971                   annotation: _annotation,
       
   972                 })
       
   973               )
       
   974             )
       
   975               delete_local_annotation(this.dataset.editable_id);
       
   976             widget.refresh(true);
       
   977           });
       
   978           this.$.find(".Ldt-AnnotationsList-Edit").click(function (e) {
       
   979             if (widget.on_edit) {
       
   980               var _annotation = get_local_annotation(this.dataset.editable_id);
       
   981               widget.on_edit(_annotation);
       
   982             } else {
       
   983               // Edit annotation title. We have to specify the insertion point.
       
   984               var element = $(this)
       
   985                 .parents(".Ldt-AnnotationsList-li")
       
   986                 .find(".Ldt-AnnotationsList-TitleContent.Ldt-live-editable");
       
   987               edit_element(element[0]);
       
   988             }
       
   989           });
       
   990           this.$.find(".Ldt-AnnotationsList-PublishAnnotation").click(function (
       
   991             e
       
   992           ) {
       
   993             var _annotation = get_local_annotation(this.dataset.editable_id);
       
   994             // Publish annotation to the server
       
   995             if (
       
   996               !confirm(
       
   997                 Mustache.render(widget.l10n.confirm_publish_message, {
       
   998                   annotation: _annotation,
       
   999                 })
       
  1000               )
       
  1001             )
       
  1002               return;
       
  1003             var _url = Mustache.render(widget.api_endpoint_template, {
       
  1004               id: widget.source.projectId,
   577             });
  1005             });
   578             var _created = false;
  1006             if (_url !== "") {
   579             if (_this.show_creation_date) {
  1007               var _export = widget.player.sourceManager.newLocalSource({
   580                 _created = _annotation.created.toLocaleDateString()+", "+_annotation.created.toLocaleTimeString().replace(/\u200E/g, '').replace(/^([^\d]*\d{1,2}:\d{1,2}):\d{1,2}([^\d]*)$/, '$1$2');;
  1008                 serializer: ns.serializers[widget.api_serializer],
       
  1009               });
       
  1010 
       
  1011               if (widget.publish_type) {
       
  1012                 // If publish_type is specified, try to set the annotation type of the exported annotation
       
  1013                 var at = widget.source
       
  1014                   .getAnnotationTypes()
       
  1015                   .filter(function (at) {
       
  1016                     return at.title == widget.publish_type;
       
  1017                   });
       
  1018                 if (at.length == 1) {
       
  1019                   _annotation.setAnnotationType(at[0].id);
       
  1020                 }
       
  1021               }
       
  1022               var _exportedAnnotations = new ns.Model.List(
       
  1023                 widget.player.sourceManager
       
  1024               );
       
  1025               _exportedAnnotations.push(_annotation);
       
  1026               _export.addList("annotation", _exportedAnnotations);
       
  1027               jQuery.ajax({
       
  1028                 url: _url,
       
  1029                 type: widget.api_method,
       
  1030                 contentType: "application/json",
       
  1031                 data: _export.serialize(),
       
  1032                 success: function (_data) {
       
  1033                   $(this).addClass("published");
       
  1034                   // Save the published information
       
  1035                   var an = get_local_annotation(_annotation.id);
       
  1036                   // FIXME: handle "published" tag
       
  1037                   an.setTags(["published"]);
       
  1038                   save_local_annotations();
       
  1039                   widget.player.trigger("Annotation.publish", _annotation);
       
  1040                 },
       
  1041                 error: function (_xhr, _error, _thrown) {
       
  1042                   ns.log("Error when sending annotation", _thrown);
       
  1043                 },
       
  1044               });
   581             }
  1045             }
   582             if(this.tags == true){
  1046           });
   583                 var _tags = _annotation.getTagTexts();
  1047           this.$.find(".Ldt-AnnotationsList-TimeEdit").dblclick(function (e) {
       
  1048             var _this = this;
       
  1049             // Use current player time
       
  1050             var an = get_local_annotation(_this.dataset.editable_id);
       
  1051             if (an !== undefined) {
       
  1052               // FIXME: implement Undo feature
       
  1053               an.setBegin(widget.media.getCurrentTime().milliseconds);
       
  1054               save_local_annotations();
       
  1055               widget.player.trigger("Annotation.update", an);
       
  1056               widget.refresh(true);
   584             }
  1057             }
   585             else {
  1058           });
   586                 var _tags = false;
  1059         }
   587             }
  1060 
   588             var _data = {
  1061         this.$.find(".Ldt-AnnotationsList-Tag-Li").click(function () {
   589                 id : _annotation.id,
  1062           _this.source.getAnnotations().search(
   590                 media_id : _annotation.getMedia().id,
  1063             jQuery(this)
   591                 htitle : IriSP.textFieldHtml(_title),
  1064               .text()
   592                 title: _title,
  1065               .replace(/(^\s+|\s+$)/g, "")
   593                 creator: _creator,
  1066           );
   594                 hdescription : IriSP.textFieldHtml(_description),
       
   595                 description: _description,
       
   596                 begin : _annotation.begin.toString(),
       
   597                 end : _annotation.end.toString(),
       
   598                 created : _created,
       
   599                 show_timecode : _this.show_timecode,
       
   600                 show_end_time : _this.show_end_time,
       
   601                 show_title : _this.show_title && _title,
       
   602                 thumbnail : _thumbnail,
       
   603                 url : _url,
       
   604                 tags : _tags,
       
   605                 specific_style : (typeof _bgcolor !== "undefined" ? "background-color: " + _bgcolor : ""),
       
   606                 l10n: _this.l10n,
       
   607                 editable: _this.editable,
       
   608                 external: _external,
       
   609                 show_publish: _this.show_publish,
       
   610                 show_creator: _this.show_creator,
       
   611                 show_twitter: _this.show_twitter,
       
   612                 twitter_param: IriSP.jQuery.param({ url: _url, text: IriSP.textFieldHtml(_title) + (_this.twitter_hashtag ? ' #' + _this.twitter_hashtag : "") }),
       
   613                 allow_annotations_deletion: _this.allow_annotations_deletion
       
   614             };
       
   615             if (_this.show_audio && _annotation.audio && _annotation.audio.href && _annotation.audio.href != "null") {
       
   616                 _data.audio = true;
       
   617                 if (!_this.jwplayers[_annotation.id]) {
       
   618                     var _audiofile = _annotation.audio.href;
       
   619                     if (_this.audio_url_transform) {
       
   620                         _audiofile = _this.audio_url_transform(_annotation.audio.href);
       
   621                     }
       
   622                     var _tmpId = "jwplayer-" + IriSP.Model.getUID();
       
   623                     _this.jwplayers[_annotation.id] = _tmpId;
       
   624                     _this.$.find(".Ldt-AnnotationsList-Audio").append(IriSP.jQuery("<div>").attr("id", _tmpId));
       
   625                     jwplayer(_tmpId).setup({
       
   626                         flashplayer: IriSP.getLib("jwPlayerSWF"),
       
   627                         file: _audiofile,
       
   628                         fallback: false,
       
   629                         primary: "flash",
       
   630                         controls: false,
       
   631                         width: 1,
       
   632                         height: 1,
       
   633                         events: {
       
   634                             onPause: function() {
       
   635                                 _this.$.find(".Ldt-AnnotationsList-Play[data-annotation-id=" + _annotation.id + "]").text(_this.l10n.voice_annotation);
       
   636                             },
       
   637                             onPlay: function() {
       
   638                                 _this.$.find(".Ldt-AnnotationsList-Play[data-annotation-id=" + _annotation.id + "]").text(_this.l10n.now_playing);
       
   639                             }
       
   640                         }
       
   641                     });
       
   642                 }
       
   643             }
       
   644             var _html = Mustache.to_html(_this.annotationTemplate, _data),
       
   645                 _el = IriSP.jQuery(_html),
       
   646                 _onselect = function() {
       
   647                     _this.$.find('.Ldt-AnnotationsList-li').removeClass("selected");
       
   648                     _el.addClass("selected");
       
   649                 },
       
   650                 _onunselect = function() {
       
   651                     _this.$.find('.Ldt-AnnotationsList-li').removeClass("selected");
       
   652                 };
       
   653             _el.mouseover(function() {
       
   654                     _annotation.trigger("select");
       
   655                 })
       
   656                 .mouseout(function() {
       
   657                     _annotation.trigger("unselect");
       
   658                 })
       
   659                 .click(function() {
       
   660                     if (_this.filter_by_segments && _this.media.getTimeRange()){
       
   661                         _ann_time = ( _annotation.begin + _annotation.end ) / 2;
       
   662                         if ((_ann_time <= _this.media.getTimeRange()[0]) || (_ann_time >= _this.media.getTimeRange()[1])){
       
   663                             _this.media.resetTimeRange()
       
   664                         }
       
   665                     }
       
   666                     _annotation.trigger("click");
       
   667                 })
       
   668                 .appendTo(_this.list_$);
       
   669             IriSP.attachDndData(_el.find("[draggable]"), {
       
   670             	title: _title,
       
   671             	description: _description,
       
   672             	uri: _url,
       
   673                 image: _annotation.thumbnail,
       
   674                 text: '[' + _annotation.begin.toString() + '] ' + _title
       
   675             });
       
   676             _el.on("remove", function() {
       
   677                 _annotation.off("select", _onselect);
       
   678                 _annotation.off("unselect", _onunselect);
       
   679             });
       
   680             _annotation.on("select", _onselect);
       
   681             _annotation.on("unselect", _onunselect);
       
   682         });
  1067         });
   683 
  1068         this.$.find(".Ldt-Annotation-Timecode").click(function () {
   684         /* Correct the empty tag bug */
  1069           _this.media.setCurrentTime(Number(this.dataset.timecode));
   685         this.$.find('.Ldt-AnnotationsList-Tag-Li').each(function() {
       
   686             var _el = IriSP.jQuery(this);
       
   687             if (!_el.text().replace(/(^\s+|\s+$)/g,'')) {
       
   688                 _el.remove();
       
   689             }
       
   690         });
  1070         });
   691 
  1071 
   692         if (this.editable) {
  1072         this.$.find(".Ldt-AnnotationsList-Play").click(function () {
   693             var widget = _this;
  1073           var _el = jQuery(this),
   694             var $ = IriSP.jQuery;
  1074             _annid = _el.attr("data-annotation-id");
   695 
  1075           if (_this.jwplayers[_annid]) {
   696             var edit_element = function (_this, insertion_point) {
  1076             jwplayer(_this.jwplayers[_annid]).play();
   697                 var feedback_wrong = "#FF9999";
  1077           }
   698                 var feedback_ok = "#99FF99";
  1078           _this.media.pause();
   699 
       
   700                 // insertion_point can be used to specify where to
       
   701                 // insert the input field.  Firefox is buggy wrt input
       
   702                 // fields inside <a> or <h?> tags, it does not
       
   703                 // propagate mouse clicks. If _this is a <a> then we
       
   704                 // have to specify the ancestor before which we can
       
   705                 // insert the input widget.
       
   706                 if (insertion_point === undefined)
       
   707                     insertion_point = _this;
       
   708 
       
   709                 // Insert input element
       
   710                 var input_element = $(_this.dataset.editable_type === 'multiline' ? "<textarea>" : "<input>")
       
   711                         .addClass("editableInput")
       
   712                         .insertBefore($(insertion_point));
       
   713                 input_element[0].value = _this.dataset.editable_value;
       
   714                 $(input_element).show().focus();
       
   715                 $(_this).addClass("editing");
       
   716 
       
   717                 function feedback(color) {
       
   718                     // Give some feedback
       
   719                     $(_this).removeClass("editing");
       
   720                     input_element.remove();
       
   721                     var previous_color = $(_this).css("background-color");
       
   722                     $(_this).stop().css("background-color", color)
       
   723                         .animate({ backgroundColor: previous_color}, 1000);
       
   724                 }
       
   725 
       
   726                 function cancelChanges(s) {
       
   727                     feedback(feedback_wrong);
       
   728                 }
       
   729                 function validateChanges() {
       
   730                     var n = input_element[0].value;
       
   731                     if (n == _this.dataset.editable_value) {
       
   732                         // No change
       
   733                         feedback(feedback_ok);
       
   734                         return;
       
   735                     }
       
   736                     if (n == '') {
       
   737                         // Delete annotation
       
   738                         delete_local_annotation(_this.dataset.editable_id);
       
   739                         widget.player.trigger("Annotation.delete", _this.dataset.editable_id);
       
   740                         return;
       
   741                     } else {
       
   742                         // Convert value if necessary.
       
   743                         var val = n;
       
   744                         if (_this.dataset.editable_type == 'timestamp') {
       
   745                             val = IriSP.timestamp2ms(n);
       
   746                             if (Number.isNaN(val)) {
       
   747                                 // Invalid value. Cancel changes
       
   748                                 cancelChanges();
       
   749                                 return;
       
   750                             }
       
   751                         }
       
   752                         _this.dataset.editable_value = n;
       
   753                         n = val;
       
   754                         $(_this).text(val);
       
   755                     }
       
   756 
       
   757                     // We cannot use .getElement since it fetches
       
   758                     // elements from the global Directory
       
   759                     var an = get_local_annotation(_this.dataset.editable_id);
       
   760                     if (an === undefined) {
       
   761                         console.log("Strange error: cannot find edited annotation");
       
   762                         feedback(feedback_wrong);
       
   763                     } else {
       
   764                         _this.dataset.editable_value = n;
       
   765                         // Update annotation for storage
       
   766                         if (_this.dataset.editable_field == 'begin')
       
   767                             an.setBegin(n);
       
   768                         else if (_this.dataset.editable_field == 'end')
       
   769                             an.setEnd(n);
       
   770                         else
       
   771                             an[_this.dataset.editable_field] = n;
       
   772                         an.modified = new Date();
       
   773                         // FIXME: use user name, when available
       
   774                         an.contributor = widget.player.config.username || "COCo User";
       
   775                         widget.player.addLocalAnnotation(an);
       
   776                         widget.player.trigger("Annotation.update", an);
       
   777                         feedback(feedback_ok);
       
   778                     }
       
   779                 }
       
   780                 $(input_element).bind('keydown', function(e) {
       
   781                     if (e.which == 13) {
       
   782                         e.preventDefault();
       
   783                         validateChanges();
       
   784                     } else if (e.which == 27) {
       
   785                         e.preventDefault();
       
   786                         cancelChanges();
       
   787                     }
       
   788                 }).bind("blur", function (e) {
       
   789                     validateChanges();
       
   790                 });
       
   791             };
       
   792 
       
   793             var get_local_annotation = function (ident) {
       
   794                 return widget.player.getLocalAnnotation(ident);
       
   795             };
       
   796 
       
   797             var save_local_annotations = function() {
       
   798                 widget.player.saveLocalAnnotations();
       
   799                 // Merge modifications into widget source
       
   800                 widget.source.merge(widget.player.localSource);
       
   801             };
       
   802 
       
   803             var delete_local_annotation = function(ident) {
       
   804                 widget.source.getAnnotations().removeId(ident, true);
       
   805                 widget.player.deleteLocalAnnotation(ident);
       
   806                 widget.refresh(true);
       
   807             };
       
   808 
       
   809             this.$.find('.Ldt-AnnotationsList-Delete').click(function(e) {
       
   810                 // Delete annotation
       
   811                 var _annotation = get_local_annotation(this.dataset.editable_id);
       
   812                 if (confirm(Mustache.to_html(widget.l10n.confirm_delete_message, { annotation: _annotation })))
       
   813                     delete_local_annotation(this.dataset.editable_id);
       
   814                 widget.refresh(true);
       
   815             });
       
   816             this.$.find('.Ldt-AnnotationsList-Edit').click(function(e) {
       
   817                 if (widget.on_edit) {
       
   818                     var _annotation = get_local_annotation(this.dataset.editable_id);
       
   819                     widget.on_edit(_annotation);
       
   820                 } else {
       
   821                     // Edit annotation title. We have to specify the insertion point.
       
   822                     var element = $(this).parents(".Ldt-AnnotationsList-li").find(".Ldt-AnnotationsList-TitleContent.Ldt-live-editable");
       
   823                     edit_element(element[0]);
       
   824                 }
       
   825             });
       
   826             this.$.find('.Ldt-AnnotationsList-PublishAnnotation').click(function(e) {
       
   827                 var _annotation = get_local_annotation(this.dataset.editable_id);
       
   828                 // Publish annotation to the server
       
   829                 if (!confirm(Mustache.to_html(widget.l10n.confirm_publish_message, { annotation: _annotation })))
       
   830                     return;
       
   831                 var _url = Mustache.to_html(widget.api_endpoint_template, {id: widget.source.projectId});
       
   832                 if (_url !== "") {
       
   833                     var _export = widget.player.sourceManager.newLocalSource({serializer: IriSP.serializers[widget.api_serializer]});
       
   834 
       
   835                     if (widget.publish_type) {
       
   836                         // If publish_type is specified, try to set the annotation type of the exported annotation
       
   837                         var at = widget.source.getAnnotationTypes().filter(function(at) { return at.title == widget.publish_type; });
       
   838                         if (at.length == 1) {
       
   839                             _annotation.setAnnotationType(at[0].id);
       
   840                         }
       
   841                     }
       
   842                     var _exportedAnnotations = new IriSP.Model.List(widget.player.sourceManager);
       
   843                     _exportedAnnotations.push(_annotation);
       
   844                     _export.addList("annotation", _exportedAnnotations);
       
   845                     IriSP.jQuery.ajax({
       
   846                         url: _url,
       
   847                         type: widget.api_method,
       
   848                         contentType: 'application/json',
       
   849                         data: _export.serialize(),
       
   850                         success: function(_data) {
       
   851                             $(this).addClass("published");
       
   852                             // Save the published information
       
   853                             var an = get_local_annotation(_annotation.id);
       
   854                             // FIXME: handle "published" tag
       
   855                             an.setTags( [ "published" ]);
       
   856                             save_local_annotations();
       
   857                             widget.player.trigger("Annotation.publish", _annotation);
       
   858                         },
       
   859                         error: function(_xhr, _error, _thrown) {
       
   860                             IriSP.log("Error when sending annotation", _thrown);
       
   861                         }
       
   862                     });
       
   863                 }
       
   864             });
       
   865             this.$.find('.Ldt-AnnotationsList-TimeEdit').dblclick(function(e) {
       
   866                 var _this = this;
       
   867                 // Use current player time
       
   868                 var an = get_local_annotation(_this.dataset.editable_id);
       
   869                 if (an !== undefined) {
       
   870                     // FIXME: implement Undo feature
       
   871                     an.setBegin(widget.media.getCurrentTime().milliseconds);
       
   872                     save_local_annotations();
       
   873                     widget.player.trigger("Annotation.update", an);
       
   874                     widget.refresh(true);
       
   875                 }
       
   876             });
       
   877         };
       
   878 
       
   879         this.$.find('.Ldt-AnnotationsList-Tag-Li').click(function() {
       
   880             _this.source.getAnnotations().search(IriSP.jQuery(this).text().replace(/(^\s+|\s+$)/g,''));
       
   881         });
  1079         });
   882         this.$.find('.Ldt-Annotation-Timecode').click(function () {
       
   883             _this.media.setCurrentTime(Number(this.dataset.timecode));
       
   884         });
       
   885 
       
   886         this.$.find(".Ldt-AnnotationsList-Play").click(function() {
       
   887             var _el = IriSP.jQuery(this),
       
   888                 _annid = _el.attr("data-annotation-id");
       
   889             if (_this.jwplayers[_annid]) {
       
   890                 jwplayer(_this.jwplayers[_annid]).play();
       
   891             }
       
   892             _this.media.pause();
       
   893         });
       
   894 
  1080 
   895         if (this.source.getAnnotations().searching) {
  1081         if (this.source.getAnnotations().searching) {
   896             var rx = _this.source.getAnnotations().regexp || false;
  1082           var rx = _this.source.getAnnotations().regexp || false;
   897             this.$.find(".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description").each(function() {
  1083           this.$.find(
   898                 var _$ = IriSP.jQuery(this);
  1084             ".Ldt-AnnotationsList-Title a, .Ldt-AnnotationsList-Description"
   899                 _$.html(IriSP.textFieldHtml(_$.text(), rx));
  1085           ).each(function () {
   900             });
  1086             var _$ = jQuery(this);
   901         }
  1087             _$.html(ns.textFieldHtml(_$.text(), rx));
   902 
  1088           });
   903         this.$.find(".Ldt-AnnotationsList-DeleteButton").click(_this.functionWrapper("onDeleteClick"))
  1089         }
       
  1090 
       
  1091         this.$.find(".Ldt-AnnotationsList-DeleteButton").click(
       
  1092           _this.functionWrapper("onDeleteClick")
       
  1093         );
       
  1094       }
       
  1095 
       
  1096       if (this.ajax_url) {
       
  1097         if (this.mashupMode) {
       
  1098           this.ajaxMashup();
       
  1099         } else {
       
  1100           if (
       
  1101             Math.abs(_currentTime - this.lastAjaxQuery) > this.ajax_granularity
       
  1102           ) {
       
  1103             this.ajaxSource();
       
  1104           }
       
  1105         }
       
  1106       }
       
  1107 
       
  1108       return _list.length;
   904     }
  1109     }
   905 
  1110 
   906     if (this.ajax_url) {
  1111     onDeleteClick(event) {
   907         if (this.mashupMode) {
  1112       _list = this.getWidgetAnnotations();
   908             this.ajaxMashup();
  1113       ann_id = event.target.dataset.annotation;
   909         } else {
  1114       delete_preview_$ = this.$.find(".Ldt-AnnotationsList-ul-ToDelete");
   910             if (Math.abs(_currentTime - this.lastAjaxQuery) > (this.ajax_granularity)) {
  1115       delete_preview_$.html("");
   911                 this.ajaxSource();
  1116       _list = _list.filter(function (_annotation) {
   912             }
  1117         return _annotation.id == ann_id;
   913         }
  1118       });
   914     }
  1119       var _annotation = _list[0],
   915     
       
   916     return _list.length;
       
   917 };
       
   918 
       
   919 IriSP.Widgets.AnnotationsList.prototype.onDeleteClick = function(event){
       
   920     _list = this.getWidgetAnnotations();
       
   921     ann_id = event.target.dataset.annotation;
       
   922     delete_preview_$ = this.$.find(".Ldt-AnnotationsList-ul-ToDelete");
       
   923     delete_preview_$.html("");
       
   924     _list = _list.filter(function(_annotation){
       
   925         return _annotation.id == ann_id
       
   926     })
       
   927     var _annotation = _list[0],
       
   928         _title = "",
  1120         _title = "",
   929         _creator = "",
  1121         _creator = "",
   930         _this = this;
  1122         _this = this;
   931     if (_annotation.creator) {
  1123       if (_annotation.creator) {
   932         var _users = [],
  1124         var _users = [],
   933             _user = {};
  1125           _user = {};
   934         if (_this.source.users_data) {
  1126         if (_this.source.users_data) {
   935             _users = _this.source.users_data.filter(function(_user_data){
  1127           _users = _this.source.users_data.filter(function (_user_data) {
   936                 return _user_data.username == _annotation.creator;
  1128             return _user_data.username == _annotation.creator;
   937             });
  1129           });
   938         }
  1130         }
   939         if (_users.length == 0){
  1131         if (_users.length == 0) {
   940             _user.username = _annotation.creator
  1132           _user.username = _annotation.creator;
   941         }
  1133         } else {
   942         else{
  1134           _user = _users[0];
   943             _user = _users[0]
       
   944         }
  1135         }
   945         _creator = _this.make_name_string_function(_user);
  1136         _creator = _this.make_name_string_function(_user);
       
  1137       }
       
  1138       if (_annotation.title) {
       
  1139         var tempTitle = _annotation.title;
       
  1140         if (tempTitle.substr(0, _title.length + 1) == _title + ":") {
       
  1141           _title = "";
       
  1142         }
       
  1143         _title = _title + (_title == "" ? "" : ": ") + _annotation.title;
       
  1144       }
       
  1145       var _created = false;
       
  1146       if (this.show_creation_date) {
       
  1147         _created =
       
  1148           _annotation.created.toLocaleDateString() +
       
  1149           ", " +
       
  1150           _annotation.created.toLocaleTimeString();
       
  1151       }
       
  1152       var _data = {
       
  1153         id: _annotation.id,
       
  1154         media_id: _annotation.getMedia().id,
       
  1155         htitle: ns.textFieldHtml(_title),
       
  1156         hdescription: ns.textFieldHtml(_annotation.description),
       
  1157         begin: _annotation.begin.toString(),
       
  1158         end: _annotation.end.toString(),
       
  1159         created: _created,
       
  1160         show_timecode: this.show_timecode,
       
  1161         show_creator: this.show_creator,
       
  1162         creator: _creator,
       
  1163         tags: false,
       
  1164         l10n: this.l10n,
       
  1165         allow_annotations_deletion: false,
       
  1166       };
       
  1167       _html = Mustache.render(this.constructor.annotationTemplate, _data);
       
  1168       delete_preview_$.html(_html);
       
  1169 
       
  1170       this.$.find(".Ldt-AnnotationsList-ConfirmDelete").click(function () {
       
  1171         _this.sendDelete(ann_id);
       
  1172       });
       
  1173 
       
  1174       this.showScreen("Delete");
   946     }
  1175     }
   947     if (_annotation.title) {
  1176 
   948         var tempTitle = _annotation.title;
  1177     refreshHeader() {
   949         if( tempTitle.substr(0, _title.length + 1) == (_title + ":") ){
  1178       var annotation_count_string =
   950             _title = "";
  1179         " (" +
   951         }
  1180         this.annotations_count +
   952         _title = _title + ( (_title=="") ? "" : ": ") + _annotation.title;
  1181         " " +
       
  1182         this.annotations_count_header_string +
       
  1183         ")";
       
  1184       this.$.find(".Ldt-AnnotationsList-header").html("");
       
  1185       this.$.find(".Ldt-AnnotationsList-header").html(
       
  1186         this.custom_header && typeof this.custom_header == "string"
       
  1187           ? this.custom_header + annotation_count_string
       
  1188           : this.l10n.header + annotation_count_string
       
  1189       );
   953     }
  1190     }
   954     var _created = false;
  1191 
   955     if (this.show_creation_date) {
  1192     hide() {
   956         _created = _annotation.created.toLocaleDateString()+", "+_annotation.created.toLocaleTimeString();
  1193       var _this = this;
       
  1194       if (this.visible) {
       
  1195         this.visible = false;
       
  1196         this.widget_$.slideUp(function () {
       
  1197           _this.$.find(".Ldt-AnnotationsList-header").hide();
       
  1198         });
       
  1199         this.showScreen("Main");
       
  1200       }
   957     }
  1201     }
   958     var _data = {
  1202 
   959             id : _annotation.id,
  1203     show() {
   960             media_id : _annotation.getMedia().id,
  1204       if (!this.visible) {
   961             htitle : IriSP.textFieldHtml(_title),
  1205         this.visible = true;
   962             hdescription : IriSP.textFieldHtml(_annotation.description),
  1206         this.$.find(".Ldt-AnnotationsList-header").show();
   963             begin : _annotation.begin.toString(),
  1207         this.widget_$.slideDown();
   964             end : _annotation.end.toString(),
  1208         this.showScreen("Main");
   965             created : _created,
  1209       }
   966             show_timecode : this.show_timecode,
       
   967             show_creator : this.show_creator,
       
   968             creator : _creator,
       
   969             tags : false,
       
   970             l10n: this.l10n,
       
   971             allow_annotations_deletion: false
       
   972     }
  1210     }
   973     _html = Mustache.to_html(this.annotationTemplate, _data)
  1211 
   974     delete_preview_$.html(_html)
  1212     toggle() {
   975     
  1213       if (!this.always_visible) {
   976     this.$.find(".Ldt-AnnotationsList-ConfirmDelete").click(function(){
  1214         if (this.visible) {
   977         _this.sendDelete(ann_id);
  1215           this.hide();
   978     });
  1216         } else {
   979     
  1217           this.show();
   980     this.showScreen("Delete");    
  1218         }
   981 }
  1219       }
   982 
  1220     }
   983 IriSP.Widgets.AnnotationsList.prototype.refreshHeader = function() {
  1221 
   984     var annotation_count_string = " (" + this.annotations_count +" "+this.annotations_count_header_string+")";
  1222     revertToMainScreen() {
   985     this.$.find('.Ldt-AnnotationsList-header').html("");
  1223       if (this.$.find(".Ldt-AnnotationsList-ScreenMain").is(":hidden")) {
   986     this.$.find('.Ldt-AnnotationsList-header').html(
  1224         this.showScreen("Main");
   987         this.custom_header && typeof this.custom_header == "string"? this.custom_header + annotation_count_string : this.l10n.header + annotation_count_string
  1225       }
   988     );
  1226     }
   989 }
  1227 
   990 
  1228     sendDelete(id) {
   991 IriSP.Widgets.AnnotationsList.prototype.hide = function() {
  1229       var _this = this,
   992     var _this = this;
  1230         _url = Mustache.render(this.api_delete_endpoint, {
   993     if (this.visible){
  1231           annotation_id: id,
   994         this.visible = false;
  1232           project_id: this.project_id,
   995         this.widget_$.slideUp(function(){
       
   996             _this.$.find('.Ldt-AnnotationsList-header').hide();            
       
   997         });
  1233         });
   998         this.showScreen("Main")
  1234 
   999     }
  1235       jQuery.ajax({
  1000 }
       
  1001 
       
  1002 IriSP.Widgets.AnnotationsList.prototype.show = function() {
       
  1003     if(!this.visible){
       
  1004         this.visible = true;
       
  1005         this.$.find('.Ldt-AnnotationsList-header').show();
       
  1006         this.widget_$.slideDown();
       
  1007         this.showScreen("Main")
       
  1008     }
       
  1009 }
       
  1010 
       
  1011 
       
  1012 IriSP.Widgets.AnnotationsList.prototype.toggle = function() {
       
  1013     if (!this.always_visible) {
       
  1014         if (this.visible) {
       
  1015             this.hide();
       
  1016         } else {
       
  1017             this.show();
       
  1018         }
       
  1019     }
       
  1020 };
       
  1021 
       
  1022 IriSP.Widgets.AnnotationsList.prototype.revertToMainScreen = function(){
       
  1023     if (this.$.find(".Ldt-AnnotationsList-ScreenMain").is(":hidden")){
       
  1024         this.showScreen("Main");
       
  1025     }
       
  1026 }
       
  1027 
       
  1028 IriSP.Widgets.AnnotationsList.prototype.sendDelete = function(id){
       
  1029     var _this = this,
       
  1030         _url = Mustache.to_html(this.api_delete_endpoint, {annotation_id: id, project_id: this.project_id})
       
  1031     
       
  1032     IriSP.jQuery.ajax({
       
  1033         url: _url,
  1236         url: _url,
  1034         type: this.api_delete_method,
  1237         type: this.api_delete_method,
  1035         contentType: 'application/json',
  1238         contentType: "application/json",
  1036         success: function(_data) {
  1239         success: function (_data) {
  1037             _this.showScreen('Success');
  1240           _this.showScreen("Success");
  1038             window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 2000));
  1241           window.setTimeout(
  1039             _this.currentSource.getAnnotations().removeId(id);
  1242             _this.functionWrapper("revertToMainScreen"),
       
  1243             _this.after_send_timeout || 2000
       
  1244           );
       
  1245           _this.currentSource.getAnnotations().removeId(id);
       
  1246           _this.player.trigger("AnnotationsList.refresh");
       
  1247         },
       
  1248         error: function (_xhr, _error, _thrown) {
       
  1249           ns.log("Error when sending annotation", _thrown);
       
  1250           _this.showScreen("Error");
       
  1251           window.setTimeout(
       
  1252             _this.functionWrapper("revertToMainScreen"),
       
  1253             _this.after_send_timeout || 2000
       
  1254           );
       
  1255         },
       
  1256       });
       
  1257       this.showScreen("Sending");
       
  1258     }
       
  1259 
       
  1260     draw() {
       
  1261       this.jwplayers = {};
       
  1262       this.mashupMode = this.media.elementType === "mashup";
       
  1263 
       
  1264       this.renderTemplate();
       
  1265 
       
  1266       var _this = this;
       
  1267       this.list_$ = this.$.find(".Ldt-AnnotationsList-ul");
       
  1268       this.widget_$ = this.$.find(".Ldt-AnnotationsListWidget");
       
  1269 
       
  1270       if (this.widget_max_height) {
       
  1271         this.widget_$.css("max-height", this.widget_max_height);
       
  1272       }
       
  1273 
       
  1274       if (this.show_filters) {
       
  1275         if (this.user_filter) {
       
  1276           this.userselect_$ = this.$.find("#Ldt-AnnotationsList-userFilter");
       
  1277           this.userselect_$.change(function () {
  1040             _this.player.trigger("AnnotationsList.refresh");
  1278             _this.player.trigger("AnnotationsList.refresh");
  1041         },
  1279           });
  1042         error: function(_xhr, _error, _thrown) {
  1280           this.userselect_$.html(
  1043             IriSP.log("Error when sending annotation", _thrown);
  1281             "<option selected value='false'>" + this.l10n.everyone + "</option>"
  1044             _this.showScreen('Error');
  1282           );
  1045             window.setTimeout(_this.functionWrapper("revertToMainScreen"),(_this.after_send_timeout || 2000));
  1283           this.usernames.forEach(function (_user) {
  1046         }
  1284             var _users = _this.source.users_data.filter(function (_user_data) {
  1047     });
  1285                 return _user_data.username == _user;
  1048     this.showScreen('Sending');
  1286               }),
  1049 }
  1287               _user_data = {};
  1050 
  1288             if (_users.length == 0) {
  1051 IriSP.Widgets.AnnotationsList.prototype.draw = function() {
  1289               _user_data.username = _user;
  1052     this.jwplayers = {};
  1290             } else {
  1053     this.mashupMode = (this.media.elementType === "mashup");
  1291               _user_data = _users[0];
  1054 
       
  1055     this.renderTemplate();
       
  1056 
       
  1057     var _this = this;
       
  1058     this.list_$ = this.$.find(".Ldt-AnnotationsList-ul");
       
  1059     this.widget_$ = this.$.find(".Ldt-AnnotationsListWidget");
       
  1060     
       
  1061     if (this.widget_max_height){
       
  1062         this.widget_$.css("max-height", this.widget_max_height)
       
  1063     }
       
  1064     
       
  1065     if (this.show_filters){
       
  1066         if (this.user_filter){
       
  1067             this.userselect_$ = this.$.find("#Ldt-AnnotationsList-userFilter");
       
  1068             this.userselect_$.change(function(){
       
  1069                 _this.player.trigger("AnnotationsList.refresh");
       
  1070             });
       
  1071             this.userselect_$.html("<option selected value='false'>"+this.l10n.everyone+"</option>");
       
  1072             this.usernames.forEach(function(_user){
       
  1073                 var _users = _this.source.users_data.filter(function(_user_data){
       
  1074                     return _user_data.username == _user;
       
  1075                 }),
       
  1076                     _user_data = {};
       
  1077                 if (_users.length == 0){
       
  1078                     _user_data.username = _user;
       
  1079                 }
       
  1080                 else{
       
  1081                     _user_data = _users[0];
       
  1082                 }
       
  1083                 _this.userselect_$.append("<option value='"+_user+"'>"+_this.make_name_string_function(_user_data)+"</option>");
       
  1084             });
       
  1085         }
       
  1086         if (this.keyword_filter){
       
  1087             this.keywordinput_$ = this.$.find("#Ldt-AnnotationsList-keywordsFilter");
       
  1088             this.keywordinput_$.keyup(function(){
       
  1089                 _this.player.trigger("AnnotationsList.refresh");
       
  1090             });
       
  1091             
       
  1092         }
       
  1093         if (this.segment_filter){
       
  1094             this.ignoresegmentcheckbox_$ = this.$.find("#Ldt-AnnotationsList-ignoreSegmentsFilter");
       
  1095             this.ignoresegmentcheckbox_$.click(function(){
       
  1096                 _this.player.trigger("AnnotationsList.refresh");
       
  1097             });
       
  1098         }
       
  1099         if(this.date_filter){
       
  1100             this.datefilterinput_$ = this.$.find("#Ldt-AnnotationsList-dateFilter");
       
  1101             this.datefilterinput_$.datepicker({ dateFormat: 'dd/mm/yy' });
       
  1102             this.datefilterinput_$.change(function(){
       
  1103                 _this.player.trigger("AnnotationsList.refresh")
       
  1104             })
       
  1105             if (this.current_day_filter){
       
  1106                 currentDate = new Date();
       
  1107                 this.datefilterinput_$.datepicker("setDate",currentDate);
       
  1108             }
  1292             }
  1109         }
  1293             _this.userselect_$.append(
  1110         if(this.latest_contributions_filter){
  1294               "<option value='" +
  1111             this.latestcontributionscheckbox_$ = this.$.find("#Ldt-AnnotationsList-latestContributionsFilter");
  1295                 _user +
  1112             this.latestcontributionscheckbox_$.click(function(){
  1296                 "'>" +
  1113                 _this.player.trigger("AnnotationsList.refresh");
  1297                 _this.make_name_string_function(_user_data) +
  1114             });
  1298                 "</option>"
  1115         }
  1299             );
  1116     }
  1300           });
  1117     
  1301         }
  1118     this.source.getAnnotations().on("search", function(_text) {
  1302         if (this.keyword_filter) {
       
  1303           this.keywordinput_$ = this.$.find(
       
  1304             "#Ldt-AnnotationsList-keywordsFilter"
       
  1305           );
       
  1306           this.keywordinput_$.keyup(function () {
       
  1307             _this.player.trigger("AnnotationsList.refresh");
       
  1308           });
       
  1309         }
       
  1310         if (this.segment_filter) {
       
  1311           this.ignoresegmentcheckbox_$ = this.$.find(
       
  1312             "#Ldt-AnnotationsList-ignoreSegmentsFilter"
       
  1313           );
       
  1314           this.ignoresegmentcheckbox_$.click(function () {
       
  1315             _this.player.trigger("AnnotationsList.refresh");
       
  1316           });
       
  1317         }
       
  1318         if (this.date_filter) {
       
  1319           this.datefilterinput_$ = this.$.find(
       
  1320             "#Ldt-AnnotationsList-dateFilter"
       
  1321           );
       
  1322           this.datefilterinput_$.datepicker({ dateFormat: "dd/mm/yy" });
       
  1323           this.datefilterinput_$.change(function () {
       
  1324             _this.player.trigger("AnnotationsList.refresh");
       
  1325           });
       
  1326           if (this.current_day_filter) {
       
  1327             currentDate = new Date();
       
  1328             this.datefilterinput_$.datepicker("setDate", currentDate);
       
  1329           }
       
  1330         }
       
  1331         if (this.latest_contributions_filter) {
       
  1332           this.latestcontributionscheckbox_$ = this.$.find(
       
  1333             "#Ldt-AnnotationsList-latestContributionsFilter"
       
  1334           );
       
  1335           this.latestcontributionscheckbox_$.click(function () {
       
  1336             _this.player.trigger("AnnotationsList.refresh");
       
  1337           });
       
  1338         }
       
  1339       }
       
  1340 
       
  1341       this.source.getAnnotations().on("search", function (_text) {
  1119         _this.searchString = _text;
  1342         _this.searchString = _text;
  1120         if (_this.source !== _this.currentSource) {
  1343         if (_this.source !== _this.currentSource) {
  1121             _this.currentSource.getAnnotations().search(_text);
  1344           _this.currentSource.getAnnotations().search(_text);
  1122             _this.throttledRefresh();
  1345           _this.throttledRefresh();
  1123         }
  1346         }
  1124     });
  1347       });
  1125     this.source.getAnnotations().on("found", function() {
  1348       this.source.getAnnotations().on("found", function () {
  1126         _this.throttledRefresh();
  1349         _this.throttledRefresh();
  1127     });
  1350       });
  1128     this.source.getAnnotations().on("not-found", function() {
  1351       this.source.getAnnotations().on("not-found", function () {
  1129         _this.throttledRefresh();
  1352         _this.throttledRefresh();
  1130     });
  1353       });
  1131     this.source.getAnnotations().on("clear-search", function() {
  1354       this.source.getAnnotations().on("clear-search", function () {
  1132         _this.searchString = false;
  1355         _this.searchString = false;
  1133         if (_this.source !== _this.currentSource) {
  1356         if (_this.source !== _this.currentSource) {
  1134             _this.currentSource.getAnnotations().trigger("clear-search");
  1357           _this.currentSource.getAnnotations().trigger("clear-search");
  1135         }
  1358         }
  1136     });
  1359       });
  1137     
  1360 
  1138     this.$.find(".Ldt-AnnotationsList-Close").click(function(){
  1361       this.$.find(".Ldt-AnnotationsList-Close").click(function () {
  1139         _this.showScreen("Main");
  1362         _this.showScreen("Main");
  1140     })
  1363       });
  1141     
  1364 
  1142     this.source.getAnnotations().on("search-cleared", function() {
  1365       this.source.getAnnotations().on("search-cleared", function () {
  1143         _this.throttledRefresh();
  1366         _this.throttledRefresh();
  1144     });
  1367       });
  1145 
  1368 
  1146     this.onMdpEvent("AnnotationsList.refresh", function() {
  1369       this.onMdpEvent("AnnotationsList.refresh", function () {
  1147         if (_this.ajax_url) {
  1370         if (_this.ajax_url) {
  1148             if (_this.mashupMode) {
  1371           if (_this.mashupMode) {
  1149                 _this.ajaxMashup();
  1372             _this.ajaxMashup();
  1150             } else {
  1373           } else {
  1151                 _this.ajaxSource();
  1374             _this.ajaxSource();
  1152             }
  1375           }
  1153         }
  1376         }
  1154         _this.throttledRefresh(false);
  1377         _this.throttledRefresh(false);
  1155     });
  1378       });
  1156 
  1379 
  1157     this.onMdpEvent("AnnotationsList.update", function() {
  1380       this.onMdpEvent("AnnotationsList.update", function () {
  1158         if (_this.ajax_url) {
  1381         if (_this.ajax_url) {
  1159             if (_this.mashupMode) {
  1382           if (_this.mashupMode) {
  1160                 _this.ajaxMashup();
  1383             _this.ajaxMashup();
  1161             } else {
  1384           } else {
  1162                 _this.ajaxSource();
  1385             _this.ajaxSource();
  1163             }
  1386           }
  1164         }
  1387         }
  1165         _this.throttledRefresh(true);
  1388         _this.throttledRefresh(true);
  1166     });
  1389       });
  1167 
  1390 
  1168     if (this.ajax_url) {
  1391       if (this.ajax_url) {
  1169         if (this.mashupMode) {
  1392         if (this.mashupMode) {
  1170             this.ajaxMashup();
  1393           this.ajaxMashup();
  1171         } else {
  1394         } else {
  1172             this.ajaxSource();
  1395           this.ajaxSource();
  1173         }
  1396         }
  1174     } else {
  1397       } else {
  1175         this.currentSource = this.source;
  1398         this.currentSource = this.source;
       
  1399       }
       
  1400 
       
  1401       if (this.refresh_interval) {
       
  1402         window.setInterval(function () {
       
  1403           _this.currentSource.get();
       
  1404         }, this.refresh_interval);
       
  1405       }
       
  1406 
       
  1407       if (this.annotations_count_header) {
       
  1408         this.annotations_count = false;
       
  1409       }
       
  1410 
       
  1411       this.onMdpEvent("AnnotationsList.toggle", "toggle");
       
  1412       this.onMdpEvent("AnnotationsList.hide", "hide");
       
  1413       this.onMdpEvent("AnnotationsList.show", "show");
       
  1414 
       
  1415       this.onMdpEvent(
       
  1416         "createAnnotationWidget.addedAnnotation",
       
  1417         this.throttledRefresh
       
  1418       );
       
  1419       var _events = ["timeupdate", "seeked", "loadedmetadata", "settimerange"];
       
  1420       for (var _i = 0; _i < _events.length; _i++) {
       
  1421         this.onMediaEvent(_events[_i], this.throttledRefresh);
       
  1422       }
       
  1423 
       
  1424       this.throttledRefresh();
       
  1425 
       
  1426       this.showScreen("Main");
       
  1427       this.$.find(".Ldt-AnnotationsList-CancelDelete").click(function () {
       
  1428         _this.showScreen("Main");
       
  1429       });
       
  1430 
       
  1431       this.visible = true;
       
  1432       if (!this.start_visible) {
       
  1433         this.hide();
       
  1434       }
  1176     }
  1435     }
  1177 
  1436   };
  1178     if (this.refresh_interval) {
       
  1179         window.setInterval(function() {
       
  1180             _this.currentSource.get();
       
  1181         }, this.refresh_interval);
       
  1182     }
       
  1183     
       
  1184     if (this.annotations_count_header){
       
  1185         this.annotations_count = false;
       
  1186     }
       
  1187     
       
  1188     this.onMdpEvent("AnnotationsList.toggle","toggle");
       
  1189     this.onMdpEvent("AnnotationsList.hide", "hide");
       
  1190     this.onMdpEvent("AnnotationsList.show", "show");
       
  1191     
       
  1192     this.onMdpEvent("createAnnotationWidget.addedAnnotation", this.throttledRefresh);
       
  1193     var _events = [
       
  1194         "timeupdate",
       
  1195         "seeked",
       
  1196         "loadedmetadata",
       
  1197         "settimerange"
       
  1198     ];
       
  1199     for (var _i = 0; _i < _events.length; _i++) {
       
  1200         this.onMediaEvent(_events[_i], this.throttledRefresh);
       
  1201     }
       
  1202 
       
  1203     this.throttledRefresh();
       
  1204     
       
  1205     this.showScreen("Main");
       
  1206     this.$.find(".Ldt-AnnotationsList-CancelDelete").click(function(){
       
  1207         _this.showScreen("Main")
       
  1208     });
       
  1209     
       
  1210     this.visible = true;
       
  1211     if (!this.start_visible){
       
  1212         this.hide();
       
  1213     }
       
  1214 };
  1437 };
       
  1438 
       
  1439 export { AnnotationsList, annotationsListStyles };