web/lib/metadataplayer/KnowledgeConcierge.js
changeset 0 7f8907368bd5
equal deleted inserted replaced
-1:000000000000 0:7f8907368bd5
       
     1 IriSP.Widgets.KnowledgeConcierge = function(player, config) {
       
     2     IriSP.Widgets.Widget.call(this, player, config);
       
     3 };
       
     4 
       
     5 IriSP.Widgets.KnowledgeConcierge.prototype = new IriSP.Widgets.Widget();
       
     6 
       
     7 IriSP.Widgets.KnowledgeConcierge.prototype.defaults = {
       
     8     width: 600,
       
     9     height: 500,
       
    10     sketch_path: "tmgraph",
       
    11     sketch_files: [ "tmgraph.pde", "physics.pde", "model.pde", "javascript.pde", "menu.pde", "event.pde", "constants.pde", "initialdata.pde"],
       
    12     kc_api_root: "/kn-concierge/",
       
    13     related_api_endpoint: "",
       
    14     use_word_boundaries: false,
       
    15     related_data_type: 'json', // SET TO "jsonp" FOR CROSS-DOMAIN OPERATION
       
    16     related_count: 8,
       
    17 };
       
    18 
       
    19 IriSP.Widgets.KnowledgeConcierge.prototype.messages = {
       
    20     "fr": {
       
    21         related_videos: "Vidéos liées",
       
    22         duration_: "Durée\u00a0:",
       
    23         for_keywords_: "pour le(s) mots-clé(s)\u00a0:",
       
    24         no_matching_videos: "Pas de vidéos correspondantes"
       
    25     },
       
    26     "en": {
       
    27         related_videos: "Related Videos",
       
    28         duration_: "Duration:",
       
    29         for_keywords_: "for keyword(s):",
       
    30         no_matching_videos: "No matching videos"
       
    31     }
       
    32 };
       
    33 
       
    34 IriSP.Widgets.KnowledgeConcierge.prototype.template =
       
    35     '<div class="Ldt-Kc-Slider"></div><canvas class="Ldt-Kc-Canvas" />'
       
    36     + '<div class="Ldt-Kc-Related"><h2>{{ l10n.related_videos }}</h2>'
       
    37     + '<h3 class="Ldt-Kc-For-Keywords">{{l10n.for_keywords_}} <span class="Ldt-Kc-Keywords"></span></h3>'
       
    38     + '<div class="Ldt-Kc-Waiting"></div>'
       
    39     + '<div class="Ldt-Kc-Related-List"></div></div>';
       
    40 
       
    41 IriSP.Widgets.KnowledgeConcierge.prototype.draw = function() {
       
    42     this.renderTemplate();
       
    43     var _canvasHeight = this.height - 16,
       
    44         _canvasWidth = this.width - 2,
       
    45         _canvas = this.$.find(".Ldt-Kc-Canvas"),
       
    46         _tmpId = IriSP._.uniqueId("Processing-"),
       
    47         _slider = this.$.find(".Ldt-Kc-Slider"),
       
    48         radius = .375 * Math.min(_canvasHeight, _canvasWidth);
       
    49     _canvas.attr({
       
    50         width: _canvasWidth,
       
    51         height: _canvasHeight,
       
    52         id: _tmpId
       
    53     }).css({
       
    54         width: _canvasWidth,
       
    55         height: _canvasHeight
       
    56     });
       
    57     var _this = this,
       
    58         _pjsfiles = IriSP._(this.sketch_files).map(function(_f) { return _this.sketch_path + "/" + _f; }),
       
    59         _selectedText = "",
       
    60         currentNodesList = "",
       
    61         relatedCache = {},
       
    62         relatedRequests = {},
       
    63         relatedTemplate = '<div class="Ldt-Kc-Related-Item"><a href="{{ widget.video_url_base }}{{ media.iri_id }}#keyword={{ escaped_keyword }}"><img src="{{ media.image }}"></a>'
       
    64             + '<h3><a href="{{ widget.video_url_base }}{{ media.iri_id }}#keyword={{ escaped_keyword }}">{{ media.title }}</a></h3><p>{{ description }}</p>'
       
    65             + '<p>{{ widget.l10n.duration_ }} <span class="Ldt-Kc-Item-Duration">{{ duration }}</span></p>'
       
    66             + '</a><div class="Ldt-Kc-Clearer"></div></div>';
       
    67             
       
    68     Processing.loadSketchFromSources(_canvas[0],_pjsfiles);
       
    69     
       
    70     function renderRelated() {
       
    71         var keywords = currentNodesList;
       
    72         _this.$.find(".Ldt-Kc-Related").show();
       
    73         if (typeof relatedCache[keywords] === "undefined") {
       
    74             return;
       
    75         }
       
    76         _this.$.find(".Ldt-Kc-Waiting").hide();
       
    77         if (relatedCache[keywords].length) {
       
    78             var _html = '<div class="Ldt-Kc-Row">';
       
    79             IriSP._(relatedCache[keywords]).each(function(media, i) {
       
    80                 var _tmpldata = {
       
    81                     widget: _this,
       
    82                     media: media,
       
    83                     description: media.description.replace(/(\n|\r|\r\n)/mg,' ').replace(/(^.{120,140})[\s].+$/m,'$1&hellip;'),
       
    84                     duration: new IriSP.Model.Time(media.duration).toString(),
       
    85                     escaped_keyword: encodeURIComponent(keywords.split(",")[0])
       
    86                 };
       
    87                 _html += Mustache.to_html(relatedTemplate, _tmpldata);
       
    88                 if (i % 2) {
       
    89                     _html += '</div><div class="Ldt-Kc-Row">';
       
    90                 }
       
    91             });
       
    92             _html += '</div>';
       
    93             _this.$.find(".Ldt-Kc-Related-List").html(_html);
       
    94         } else {
       
    95             _this.$.find(".Ldt-Kc-Related-List").html("<p class='Ldt-Kc-Related-Empty'>" + _this.l10n.no_matching_videos + "</p>");
       
    96         }
       
    97     }    
       
    98 
       
    99     function triggerSearch(text) {
       
   100         if (_selectedText !== text) {
       
   101             _selectedText = text;
       
   102             _this.source.getAnnotations().search(text);
       
   103         }
       
   104     }
       
   105     
       
   106     function searchNodes(tags) {
       
   107         var _tlist = (_this.use_word_boundaries ? IriSP._(tags).map(function(t) { return "\\\\y" + t + "\\\\y" }) : tags),
       
   108             _q = "(?i)(" + _tlist.join("|") + ")";
       
   109         jQuery.getJSON(
       
   110             _this.kc_api_root + "topics.jsp",
       
   111             {
       
   112                 proj: _this.project_id,
       
   113                 q: _q
       
   114             },
       
   115             function(data) {
       
   116                 if (data && data.items && data.items.length) {
       
   117                     for (var i=0, l=data.items.length; i<l; i++) {
       
   118                         var node = data.items[i];
       
   119                         if (i == 0) {
       
   120                             _pjs.initNode(node.id, node.name, node.grp, node.uid, node.proj);
       
   121                             var node = _pjs.findNode(node.id, node.proj);
       
   122                         } else {
       
   123                             var node = _pjs.newNode(node.id, node.name, node.grp, node.uid, node.proj);
       
   124                             node.root = true;
       
   125                             node.fix();
       
   126                         }
       
   127                         _fns.countassoc(node.id, node.proj);
       
   128                         if (l > 1) {
       
   129                             node.position(Math.floor(radius*Math.sin(2 * Math.PI * i / l)),Math.floor(radius*Math.cos(2 * Math.PI * i / l)));
       
   130                         }
       
   131                     }
       
   132                 }
       
   133             }
       
   134         );
       
   135     }
       
   136     
       
   137     function showRelated(nodetexts) {
       
   138         currentNodesList = nodetexts;
       
   139         _this.$.find(".Ldt-Kc-Related-List").html("");
       
   140         _this.$.find(".Ldt-Kc-Keywords").html(nodetexts.replace(/\,/g,", "));
       
   141         if (typeof relatedCache[nodetexts] === "undefined") {
       
   142             _this.$.find(".Ldt-Kc-Waiting").show();
       
   143             if (relatedRequests[nodetexts]) {
       
   144                 return;
       
   145             }
       
   146             relatedRequests[nodetexts] = true;
       
   147             IriSP.jQuery.ajax({
       
   148                 url: _this.related_api_endpoint,
       
   149                 data: {
       
   150                     format: _this.related_data_type,
       
   151                     keywords: nodetexts
       
   152                 },
       
   153                 dataType: _this.related_data_type,
       
   154                 success: function(data) {
       
   155                     relatedCache[nodetexts] = IriSP._(data.objects)
       
   156                         .chain()
       
   157                         .filter(function(o) {
       
   158                             return o.iri_id !== _this.media.id;
       
   159                         })
       
   160                         .sortBy(function(o) {
       
   161                             return - o.score;
       
   162                         })
       
   163                         .first(_this.related_count)
       
   164                         .value();
       
   165                     renderRelated();
       
   166                 }
       
   167             });
       
   168         } else {
       
   169             renderRelated();
       
   170         }
       
   171     }
       
   172     
       
   173     function rootNode(id, proj) {
       
   174         jQuery.getJSON(
       
   175             _this.kc_api_root + "topic.jsp",
       
   176             {
       
   177                 id: id,
       
   178                 proj: proj
       
   179             },
       
   180             function(response) {
       
   181                 if (response != null && response.items.length > 0){
       
   182                     item = response.items[0];
       
   183                     _pjs.initNode(item.id, item.name, item.grp, item.uid, item.proj);
       
   184                     _fns.countassoc(item.id, item.proj);
       
   185                 }
       
   186             }
       
   187         );
       
   188     }
       
   189     
       
   190     function bindJavascript() {
       
   191         _pjs = Processing.getInstanceById(_tmpId);
       
   192         if (_pjs && typeof _pjs.bindJavascript === "function") {
       
   193             setTimeout(function() {
       
   194                 _pjs.bindJavascript(_fns);
       
   195                 _pjs.setSize(_canvasWidth,_canvasHeight);
       
   196                 var _edit = false,
       
   197                     _teamMode = true;
       
   198                 _pjs.saveMode("en",false,_teamMode,false,"both",_edit);
       
   199                 rootNode(_this.topic_id, _this.project_id);
       
   200                 _slider.slider({
       
   201                     min: -20,
       
   202                     max: 20,
       
   203                     value: 0,
       
   204                     range: "min",
       
   205                     slide: function(event, ui) {
       
   206                         _pjs.zoom(Math.exp(ui.value / 10));
       
   207                     }
       
   208                 });
       
   209             }, 1000);
       
   210         } else {
       
   211             setTimeout(bindJavascript, 1000); 
       
   212         }
       
   213     }
       
   214     var currentSelection = null;
       
   215     var _fns = {
       
   216         adjacentnodes: function(id, proj, adj, both) {
       
   217             jQuery.ajax({
       
   218                 url: _this.kc_api_root + "associations-bd.jsp",
       
   219                 cache: false,
       
   220                 data: {
       
   221                     id: id,
       
   222                     proj: proj,
       
   223                     both: both,
       
   224                     adj: adj
       
   225                 },
       
   226                 success: function(response) {
       
   227                     if (response.items.length > 0){
       
   228                         for(i = 0, end = response.items.length; i < end; i++) {
       
   229                             item = response.items[i];
       
   230                             _pjs.addEdge(item.asc_id, item.id, item.from_proj, item.to_id, item.to_proj,
       
   231                                         item.r_name, item.r_from,  item.r_to, item.uid, item.proj);
       
   232                             _pjs.setNodeName( item.id,   item.from_proj,item.name);
       
   233                             _pjs.setNodeValue(item.id,   item.from_proj,item.name,   item.grp,   item.abst,   item.from_uid);
       
   234                             if (item.from_assoc!=null) {
       
   235                                 _pjs.setNodeAssoc(item.id, item.from_proj, item.from_assoc);
       
   236                             }
       
   237                             _pjs.setNodeName( item.to_id,item.to_proj,  item.to_name);
       
   238                             _pjs.setNodeValue(item.to_id,item.to_proj,  item.to_name,item.to_grp,item.to_abst,item.to_uid);
       
   239                             if (item.to_assoc!=null) {
       
   240                                 _pjs.setNodeAssoc(item.to_id, item.to_proj, item.to_assoc);
       
   241                             }
       
   242                         }
       
   243                         return response;
       
   244                     } else {
       
   245                         //.debug('No such topic.');
       
   246                         return null;
       
   247                     }
       
   248                 }
       
   249             });
       
   250         },
       
   251         setscale: function(scl){
       
   252             _slider.slider("value", 10*Math.log(scl));
       
   253         },
       
   254         countassoc: function(id, proj) {
       
   255             jQuery.ajax({
       
   256                 url: _this.kc_api_root + "count-assoc.jsp",
       
   257                 data: {
       
   258                     id: id,
       
   259                     proj: proj
       
   260                 },
       
   261                 success: function(response) {
       
   262                     if (response.items.length > 0){
       
   263                         for(i = 0, end = response.items.length; i < end; i++) {
       
   264                             item = response.items[i];
       
   265                             _pjs.setNodeValue(item.id, item.proj, item.name, item.grp, item.abst);
       
   266                             if (item.assoc!=null) _pjs.setNodeAssoc(item.id, item.proj, item.assoc);
       
   267                             if (item.mass!=null) _pjs.setNodeMass( item.id, item.proj, item.mass);
       
   268                         }
       
   269                     }
       
   270                 }
       
   271             });
       
   272         },
       
   273         username: function() {
       
   274             var nodes = _pjs.getNodes().values().toArray(),
       
   275                 nodetexts = IriSP._(nodes).chain().pluck("name").sortBy().value().join(",");
       
   276             showRelated(nodetexts);
       
   277         },
       
   278         mousemove: function(selection) {
       
   279             if (selection !== currentSelection) {
       
   280                 if (selection) {
       
   281                     triggerSearch(selection.name);
       
   282                 }
       
   283                 currentSelection = selection;
       
   284             }
       
   285         },
       
   286         click: function(selection) {
       
   287             if (selection) {
       
   288                 triggerSearch(selection.name);
       
   289                 showRelated(selection.name);
       
   290             } else {
       
   291                 triggerSearch();
       
   292             }
       
   293         }
       
   294     };
       
   295     var uselessfuncts = [
       
   296         "selectnode", "selectedge", "topicnode","group_shapes",
       
   297         "allbackup", "allretrieve", "new_topic", "pedia", "set_mode",
       
   298         "new_relation", "startexpand", "endexpand", "new_select" //, "mouseover" //, "username"
       
   299     ];
       
   300     
       
   301     IriSP._(uselessfuncts).each(function(funcname) {
       
   302         _fns[funcname] = function() {
       
   303 //            console.log("Function", funcname, "called with arguments", arguments);
       
   304         }
       
   305     });
       
   306     
       
   307     this.getWidgetAnnotations().forEach(function(annotation) {
       
   308         annotation.on("click", function() {
       
   309             var _tags = annotation.getTagTexts();
       
   310             if (_tags.length) {
       
   311                 searchNodes(_tags);
       
   312             }
       
   313         });
       
   314     });
       
   315     
       
   316     this.source.getTags().forEach(function(tag) {
       
   317         tag.on("click", function() {
       
   318             if (tag.title) {
       
   319                 searchNodes([tag.title]);
       
   320             }
       
   321         });
       
   322     });
       
   323     
       
   324     var keywmatch = document.location.hash.match(/keyword=([^#?&]+)/);
       
   325     if (keywmatch) {
       
   326         this.player.on("widgets-loaded", function() {
       
   327             triggerSearch(decodeURIComponent(keywmatch[1]));
       
   328         });
       
   329     }
       
   330     
       
   331     bindJavascript();
       
   332     
       
   333 };