src/widgets/EnrichedPlan.js
changeset 1072 ac1eacb3aa33
parent 1068 7623f9af9272
equal deleted inserted replaced
1071:02c04d2c8fd8 1072:ac1eacb3aa33
     1 /* TODO
     1 /* TODO
     2 - add callbacks
     2 - add callbacks
     3  */
     3  */
       
     4 // EnrichedPlan
       
     5 import Mustache from "mustache";
     4 
     6 
     5 IriSP.Widgets.EnrichedPlan = function(player, config) {
     7 import enrichedPlanStyles from "./EnrichedPlan.module.css";
     6     IriSP.Widgets.Widget.call(this, player, config);
       
     7 }
       
     8 
     8 
     9 IriSP.Widgets.EnrichedPlan.prototype = new IriSP.Widgets.Widget();
     9 const EnrichedPlan = function (ns) {
       
    10   return class extends ns.Widgets.Widget {
       
    11     constructor(player, config) {
       
    12       super(player, config);
       
    13     }
    10 
    14 
    11 IriSP.Widgets.EnrichedPlan.prototype.defaults = {
    15     static defaults = {
    12     // Main type for slide segmentation
    16       // Main type for slide segmentation
    13     annotation_type: "Slides",
    17       annotation_type: "Slides",
    14     // If no annotation type list is specified, use all other types
    18       // If no annotation type list is specified, use all other types
    15     annotation_types: [],
    19       annotation_types: [],
    16     show_controls: true,
    20       show_controls: true,
    17     show_slides: true,
    21       show_slides: true,
    18     show_teacher_notes: true,
    22       show_teacher_notes: true,
    19     show_other_notes: true,
    23       show_other_notes: true,
    20     show_own_notes: true
    24       show_own_notes: true,
    21 }
       
    22 
       
    23 IriSP.Widgets.EnrichedPlan.prototype.template =
       
    24       '<div class="Ldt-EnrichedPlan-Container">'
       
    25     + '{{#show_controls}}<form class="Ldt-EnrichedPlan-Controls">'
       
    26     + ' <input id="{{prefix}}teacher_note_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Teacher" {{#show_teacher_notes}}checked{{/show_teacher_notes}} type="checkbox">'
       
    27     + ' <label for="{{prefix}}teacher_note_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Teacher">Notes Enseignant</label>'
       
    28     + ' <input id="{{prefix}}other_note_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Other" {{#show_other_notes}}checked{{/show_other_notes}} type="checkbox">'
       
    29     + ' <label for="{{prefix}}other_note_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Other">Notes Autres</label>'
       
    30     + ' <input id="{{prefix}}simplified_plan_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Own" {{#show_own_notes}}checked{{/show_own_notes}} type="checkbox">'
       
    31     + ' <label for="{{prefix}}simplified_plan_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Own">Notes perso.</label>'
       
    32     + ' <input id="{{prefix}}slide_display_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Slide-Display" {{#show_slides}}checked{{/show_slides}} type="checkbox">'
       
    33     + ' <label for="{{prefix}}slide_display_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Slide-Display">Diapo<br/>&nbsp;</label>'
       
    34     + ' <input class="Ldt-EnrichedPlan-Search-Input" type="search" incremental placeholder="Recherchez"/>'
       
    35     + '</form>{{/show_controls}}'
       
    36     + '<div class="Ldt-EnrichedPlan-Content"></div>'
       
    37     + '</div>';
       
    38 
       
    39 IriSP.Widgets.EnrichedPlan.prototype.slideTemplate =
       
    40       '<div data-id="{{ id }}" class="Ldt-EnrichedPlan-Slide">'
       
    41     + '  <div class="Ldt-EnrichedPlan-SlideItem Ldt-EnrichedPlan-SlideTimecode">{{ begin }}</div>'
       
    42     + '  <div data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideItem {{^show_slides}}filtered_out{{/show_slides}} Ldt-EnrichedPlan-SlideThumbnail Ldt-EnrichedPlan-Slide-Display"><img title="{{ begin }} - {{ atitle }}" src="{{ thumbnail }}"></div>'
       
    43     + '  <div class="Ldt-EnrichedPlan-SlideContent">'
       
    44     + '     <div data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideTitle Ldt-EnrichedPlan-SlideTitle{{ level }}">{{ atitle }}</div>'
       
    45     + '     <div class="Ldt-EnrichedPlan-SlideNotes">{{{ notes }}}</div>'
       
    46     + '  </div>'
       
    47     + '</div>';
       
    48 
       
    49 IriSP.Widgets.EnrichedPlan.prototype.annotationTemplate = '<div title="{{ begin }} - {{ atitle }}" data-id="{{ id }}" data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideItem Ldt-EnrichedPlan-Note {{category}} {{filtered}}"><span class="Ldt-EnrichedPlan-Note-Text">{{{ text }}}</span> <span class="Ldt-EnrichedPlan-Note-Author">{{ author }}</span></div>';
       
    50 
       
    51 IriSP.Widgets.EnrichedPlan.prototype.draw = function() {
       
    52     var _this = this;
       
    53     // Generate a unique prefix, so that ids of input fields
       
    54     // (necessary for label association) are unique too.
       
    55     _this.prefix = "TODO";
       
    56     // slides content: title, level (for toc)
       
    57     var _slides = this.getWidgetAnnotations().sortBy(function(_annotation) {
       
    58         return _annotation.begin;
       
    59     });
       
    60     // All other annotations
       
    61     var _annotations = this.media.getAnnotations().filter( function (a) {
       
    62         return a.getAnnotationType().title != _this.annotation_type;
       
    63     }).sortBy(function(_annotation) {
       
    64         return _annotation.begin;
       
    65     });
       
    66 
       
    67     // Reference annotations in each slide: assume that end time is
       
    68     // correctly set.
       
    69     _slides.forEach( function (slide) {
       
    70         slide.annotations = _annotations.filter( function (a) {
       
    71             return a.begin >= slide.begin && a.begin <= slide.end;
       
    72         });
       
    73     });
       
    74 
       
    75     _this.renderTemplate();
       
    76     var container = _this.$.find('.Ldt-EnrichedPlan-Container');
       
    77     var content = _this.$.find('.Ldt-EnrichedPlan-Content');
       
    78 
       
    79     // Returns the note category: Own, Other, Teacher
       
    80     function note_category(a) {
       
    81         return a.title.indexOf('Anonyme') < 0 ? "Own" : "Other";
       
    82     };
    25     };
    83 
    26 
    84     _slides.forEach(function(slide) {
    27     static template =
    85         var _html = Mustache.to_html(_this.slideTemplate, {
    28       '<div class="Ldt-EnrichedPlan-Container">' +
    86             id : slide.id,
    29       '{{#show_controls}}<form class="Ldt-EnrichedPlan-Controls">' +
    87             atitle : IriSP.textFieldHtml(slide.title),
    30       ' <input id="{{prefix}}teacher_note_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Teacher" {{#show_teacher_notes}}checked{{/show_teacher_notes}} type="checkbox">' +
    88             level: slide.content.level || 1,
    31       ' <label for="{{prefix}}teacher_note_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Teacher">Notes Enseignant</label>' +
    89             begin : slide.begin.toString(),
    32       ' <input id="{{prefix}}other_note_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Other" {{#show_other_notes}}checked{{/show_other_notes}} type="checkbox">' +
    90             begintc: slide.begin.milliseconds,
    33       ' <label for="{{prefix}}other_note_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Other">Notes Autres</label>' +
    91             thumbnail: slide.thumbnail,
    34       ' <input id="{{prefix}}simplified_plan_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Note-Own" {{#show_own_notes}}checked{{/show_own_notes}} type="checkbox">' +
    92             show_slides: _this.show_slides,
    35       ' <label for="{{prefix}}simplified_plan_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Note-Own">Notes perso.</label>' +
    93             notes: slide.annotations.map( function (a) {
    36       ' <input id="{{prefix}}slide_display_checkbox" class="Ldt-EnrichedPlan-Control-Checkbox Ldt-EnrichedPlan-Slide-Display" {{#show_slides}}checked{{/show_slides}} type="checkbox">' +
    94                 return Mustache.to_html(_this.annotationTemplate, {
    37       ' <label for="{{prefix}}slide_display_checkbox" class="Ldt-EnrichedPlan-Control-Label Ldt-EnrichedPlan-Slide-Display">Diapo<br/>&nbsp;</label>' +
    95                     id: a.id,
    38       ' <input class="Ldt-EnrichedPlan-Search-Input" type="search" incremental placeholder="Recherchez"/>' +
    96                     text: IriSP.textFieldHtml(a.description || a.title),
    39       "</form>{{/show_controls}}" +
    97                     author: a.creator,
    40       '<div class="Ldt-EnrichedPlan-Content"></div>' +
    98                     begin: a.begin.toString(),
    41       "</div>";
    99                     begintc: a.begin.milliseconds,
    42 
   100                     atitle: a.title.slice(0, 20),
    43     static slideTemplate =
   101                     // FIXME: Temporary hack waiting for a proper metadata definition
    44       '<div data-id="{{ id }}" class="Ldt-EnrichedPlan-Slide">' +
   102                     category: "Ldt-EnrichedPlan-Note-" + note_category(a),
    45       '  <div class="Ldt-EnrichedPlan-SlideItem Ldt-EnrichedPlan-SlideTimecode">{{ begin }}</div>' +
   103                     filtered: ( (note_category(a) == 'Own' && ! _this.show_own_notes)
    46       '  <div data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideItem {{^show_slides}}filtered_out{{/show_slides}} Ldt-EnrichedPlan-SlideThumbnail Ldt-EnrichedPlan-Slide-Display"><img title="{{ begin }} - {{ atitle }}" src="{{ thumbnail }}"></div>' +
   104                                 || (note_category(a) == 'Other' && ! _this.show_other_notes)
    47       '  <div class="Ldt-EnrichedPlan-SlideContent">' +
   105                                 || (note_category(a) == 'Teacher' && ! _this.show_teacher_notes) ) ? 'filtered_out' : ''
    48       '     <div data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideTitle Ldt-EnrichedPlan-SlideTitle{{ level }}">{{ atitle }}</div>' +
   106                 });
    49       '     <div class="Ldt-EnrichedPlan-SlideNotes">{{{ notes }}}</div>' +
   107             }).join("\n")
    50       "  </div>" +
       
    51       "</div>";
       
    52 
       
    53     annotationTemplate =
       
    54       '<div title="{{ begin }} - {{ atitle }}" data-id="{{ id }}" data-timecode="{{begintc}}" class="Ldt-EnrichedPlan-SlideItem Ldt-EnrichedPlan-Note {{category}} {{filtered}}"><span class="Ldt-EnrichedPlan-Note-Text">{{{ text }}}</span> <span class="Ldt-EnrichedPlan-Note-Author">{{ author }}</span></div>';
       
    55 
       
    56     draw() {
       
    57       var _this = this;
       
    58       // Generate a unique prefix, so that ids of input fields
       
    59       // (necessary for label association) are unique too.
       
    60       _this.prefix = "TODO";
       
    61       // slides content: title, level (for toc)
       
    62       var _slides = this.getWidgetAnnotations().sortBy(function (_annotation) {
       
    63         return _annotation.begin;
       
    64       });
       
    65       // All other annotations
       
    66       var _annotations = this.media
       
    67         .getAnnotations()
       
    68         .filter(function (a) {
       
    69           return a.getAnnotationType().title != _this.annotation_type;
       
    70         })
       
    71         .sortBy(function (_annotation) {
       
    72           return _annotation.begin;
   108         });
    73         });
   109         var _el = IriSP.jQuery(_html);
    74 
       
    75       // Reference annotations in each slide: assume that end time is
       
    76       // correctly set.
       
    77       _slides.forEach(function (slide) {
       
    78         slide.annotations = _annotations.filter(function (a) {
       
    79           return a.begin >= slide.begin && a.begin <= slide.end;
       
    80         });
       
    81       });
       
    82 
       
    83       _this.renderTemplate();
       
    84       var container = _this.$.find(".Ldt-EnrichedPlan-Container");
       
    85       var content = _this.$.find(".Ldt-EnrichedPlan-Content");
       
    86 
       
    87       // Returns the note category: Own, Other, Teacher
       
    88       function note_category(a) {
       
    89         return a.title.indexOf("Anonyme") < 0 ? "Own" : "Other";
       
    90       }
       
    91 
       
    92       _slides.forEach(function (slide) {
       
    93         var _html = Mustache.render(_this.slideTemplate, {
       
    94           id: slide.id,
       
    95           atitle: ns.textFieldHtml(slide.title),
       
    96           level: slide.content.level || 1,
       
    97           begin: slide.begin.toString(),
       
    98           begintc: slide.begin.milliseconds,
       
    99           thumbnail: slide.thumbnail,
       
   100           show_slides: _this.show_slides,
       
   101           notes: slide.annotations
       
   102             .map(function (a) {
       
   103               return Mustache.render(_this.annotationTemplate, {
       
   104                 id: a.id,
       
   105                 text: ns.textFieldHtml(a.description || a.title),
       
   106                 author: a.creator,
       
   107                 begin: a.begin.toString(),
       
   108                 begintc: a.begin.milliseconds,
       
   109                 atitle: a.title.slice(0, 20),
       
   110                 // FIXME: Temporary hack waiting for a proper metadata definition
       
   111                 category: "Ldt-EnrichedPlan-Note-" + note_category(a),
       
   112                 filtered:
       
   113                   (note_category(a) == "Own" && !_this.show_own_notes) ||
       
   114                   (note_category(a) == "Other" && !_this.show_other_notes) ||
       
   115                   (note_category(a) == "Teacher" && !_this.show_teacher_notes)
       
   116                     ? "filtered_out"
       
   117                     : "",
       
   118               });
       
   119             })
       
   120             .join("\n"),
       
   121         });
       
   122         var _el = ns.jQuery(_html);
   110         content.append(_el);
   123         content.append(_el);
   111     });
   124       });
   112 
   125 
   113     container.on("click", "[data-timecode]", function () {
   126       container.on("click", "[data-timecode]", function () {
   114         _this.media.setCurrentTime(Number(this.dataset.timecode));
   127         _this.media.setCurrentTime(Number(this.dataset.timecode));
   115     });
   128       });
   116 
   129 
   117     container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () {
   130       container.on("click", ".Ldt-EnrichedPlan-Control-Checkbox", function () {
   118         var classname = _.first(_.filter(this.classList, function (s) { return s != "Ldt-EnrichedPlan-Control-Checkbox"; }));
   131         var classname = _.first(
       
   132           _.filter(this.classList, function (s) {
       
   133             return s != "Ldt-EnrichedPlan-Control-Checkbox";
       
   134           })
       
   135         );
   119         if (classname !== undefined) {
   136         if (classname !== undefined) {
   120             if ($(this).is(':checked')) {
   137           if ($(this).is(":checked")) {
   121                 content.find(".Ldt-EnrichedPlan-Slide ." + classname).removeClass("filtered_out");
   138             content
   122             } else {
   139               .find(".Ldt-EnrichedPlan-Slide ." + classname)
   123                 content.find(".Ldt-EnrichedPlan-Slide ." + classname).addClass("filtered_out");
   140               .removeClass("filtered_out");
   124              }
   141           } else {
       
   142             content
       
   143               .find(".Ldt-EnrichedPlan-Slide ." + classname)
       
   144               .addClass("filtered_out");
       
   145           }
   125         }
   146         }
       
   147       });
   126 
   148 
   127     });
   149       container
   128 
   150         .find(".Ldt-EnrichedPlan-Search-Input")
   129     container.find(".Ldt-EnrichedPlan-Search-Input").on("search", function () {
   151         .on("search", function () {
   130         var q = $(this).val().toLocaleLowerCase();
   152           var q = $(this).val().toLocaleLowerCase();
   131         if (q === "") {
   153           if (q === "") {
   132             // Show all
   154             // Show all
   133             content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching");
   155             content.find(".Ldt-EnrichedPlan-Note").removeClass("non_matching");
   134         } else {
   156           } else {
   135             $(".Ldt-EnrichedPlan-Note").each( function () {
   157             $(".Ldt-EnrichedPlan-Note").each(function () {
   136                 var node = $(this);
   158               var node = $(this);
   137                 if (node.text().toLocaleLowerCase().indexOf(q) > -1) {
   159               if (node.text().toLocaleLowerCase().indexOf(q) > -1) {
   138                     node.removeClass("non_matching");
   160                 node.removeClass("non_matching");
   139                 } else {
   161               } else {
   140                     node.addClass("non_matching");
   162                 node.addClass("non_matching");
   141                 }
   163               }
   142             });
   164             });
   143         }
   165           }
   144     });
   166         });
       
   167     }
       
   168   };
   145 };
   169 };
       
   170 
       
   171 export { EnrichedPlan, enrichedPlanStyles };