Merge with 869410bab434d795e30405f50f176a3aee14faad
authorymh <ymh.work@gmail.com>
Mon, 31 Dec 2012 13:37:31 +0100
changeset 49 d0da34fda4b4
parent 48 01fb9167ad75 (current diff)
parent 44 869410bab434 (diff)
child 50 7b517a54b708
Merge with 869410bab434d795e30405f50f176a3aee14faad
--- a/client/css/renkan.css	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/css/renkan.css	Mon Dec 31 13:37:31 2012 +0100
@@ -71,7 +71,7 @@
 }
 
 .Rk-PadTitle {
-    float: left; font-size: 14px; height: 16px; margin: 4px 5px; width: 130px; background: #666666; padding: 4px; border: 1px solid #333333;
+    float: left; font-size: 14px; height: 16px; margin: 4px 5px; width: 200px; background: #666666; padding: 4px; border: 1px solid #333333;
     border-radius: 3px; box-shadow: 0 1px 0 #505050; color: #ffffff; font-weight: bold;
 }
 
@@ -146,6 +146,22 @@
 .Rk-AddEdge-Button:hover {
     background-position: -68px -35px;
 }
+
+.Rk-Save-Button {
+    width: 34px; background-position: -102px 0;
+}
+
+.Rk-Save-Button.disabled {
+    opacity: .5; cursor: default;
+}
+
+.Rk-Save-Button:hover {
+    background-position: -102px -35px;
+}
+
+.Rk-Save-Button.disabled:hover {
+    opacity: 1; background-position: -102px 0;
+}
 /* Canvas */
 
 .Rk-Canvas {
@@ -260,24 +276,36 @@
 /* Bin Search Field */
 
 .Rk-Search-Form {
-    padding: 10px; height: 27px;
+    padding: 5px 10px; height: 27px;
     background: #666666;
     background: -moz-linear-gradient(top, #606060 20%, #909090 80%);
     background: -webkit-linear-gradient(top, #606060 20%, #909090 80%);
 }
 
 .Rk-Search-Input, .Rk-Search-Select {
-    float: left; border-width: 1px; border-color: #003050;
+    float: left;  margin: 0;
 }
 
 .Rk-Search-Input {
-    border-top-left-radius: 5px; border-bottom-left-radius: 5px; border-style: solid;
-    font-size: 13px; width: 190px; background: #ffffff; height: 15px; padding: 5px;
+    border-top-left-radius: 5px; border-bottom-left-radius: 5px; border: 1px solid #003050;
+    font-size: 13px; background: #ffffff; height: 25px; padding: 0 5px; line-height: 25px;
+    -webkit-appearance: none;
+    -webkit-box-sizing: content-box;
+    -moz-box-sizing: content-box;
+    box-sizing: content-box; 
+}
+
+.Rk-Web-Search-Input {
+     width: 190px;
+}
+
+.Rk-Bins-Search-Input {
+     width: 235px;
 }
 
 .Rk-Search-Select {
     display: inline-block; position: relative; width: 45px;
-    border-style: solid none; cursor: pointer;
+    border-width: 1px; border-color: #003050; border-style: solid none; cursor: pointer;
     height: 25px; background: #ffffff url(../img/more.png) 30px 10px no-repeat;
 }
 
@@ -348,6 +376,11 @@
     background-position: -18px 0;
 }
 
+.Rk-Bin-Count {
+    float: right; background: #c000a0; color: #FFFFFF; text-shadow: 1px 1px 1px #000000; display: none;
+    border-radius: 4px; padding: 1px 3px; font-size: 10px; font-weight: bold; margin-top: 4px;
+}
+
 .Rk-Bin-Title-Icon {
     float: left; width: 25px; margin: 2px;
 }
Binary file client/img/topbarbuttons.png has changed
--- a/client/js/i18n.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/i18n.js	Mon Dec 31 13:37:31 2012 +0100
@@ -11,6 +11,7 @@
         full_screen: "Full Screen",
         add_node: "Add Node",
         add_edge: "Add Edge",
+        save_project: "Archive Project",
         created_by: "Created by:",
         zoom_in: "Zoom In",
         zoom_out: "Zoom Out",
@@ -39,6 +40,7 @@
         full_screen: "Mode plein écran",
         add_node: "Ajouter un nœud",
         add_edge: "Ajouter un lien",
+        save_project: "Archiver le projet",
         created_by: "Créé par :",
         zoom_in: "Agrandir l’échelle",
         zoom_out: "Rapetisser l’échelle",
--- a/client/js/ldtjson-bin.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/ldtjson-bin.js	Mon Dec 31 13:37:31 2012 +0100
@@ -4,12 +4,12 @@
 
 Rkns.Ldt.ProjectBin.prototype.tagTemplate = Rkns._.template(
     '<li class="Rk-Bin-Item" data-image="img/ldt-tag.png" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/search/?search=<%=encodedtitle%>&field=all" data-title="<%-title%>" data-description="Tag \'<%-title%>\'">'
-    + '<img class="Rk-Ldt-Tag-Icon" src="img/ldt-tag.png" /><h4><%-title%></h4><div class="Rk-Clear"></div></li>'
+    + '<img class="Rk-Ldt-Tag-Icon" src="img/ldt-tag.png" /><h4><%=htitle%></h4><div class="Rk-Clear"></div></li>'
 );
 
 Rkns.Ldt.ProjectBin.prototype.annotationTemplate = Rkns._.template(
     '<li class="Rk-Bin-Item" data-image="<%=image%>" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/player/<%=mediaid%>/#id=<%=annotationid%>" data-title="<%-title%>" data-description="<%-description%>">'
-    + '<img class="Rk-Ldt-Annotation-Icon" src="<%=image%>"/><h4><%-title%></h4><p><%-description%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class="Rk-Clear"></div></li>'
+    + '<img class="Rk-Ldt-Annotation-Icon" src="<%=image%>"/><h4><%=htitle%></h4><p><%=hdescription%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class="Rk-Clear"></div></li>'
 );
 
 Rkns.Ldt.ProjectBin.prototype._init = function(_renkan, _opts) {
@@ -19,8 +19,15 @@
     this.refresh();
 }
 
-Rkns.Ldt.ProjectBin.prototype.refresh = function() {
-    var _this = this;
+Rkns.Ldt.ProjectBin.prototype.render = function(searchstr) {
+    if (searchstr) {
+        var rxbase = searchstr.replace(/(\W)/g,'\\$1'),
+            _rgxp = new RegExp('('+rxbase+')','gi'),
+            rxtest = new RegExp(rxbase,'i')
+    }
+    function highlight(_text) {
+        return searchstr ? _text.replace(_rgxp, "<span class='searchmatch'>$1</span>") : _text;
+    }
     function convertTC(_ms) {
         function pad(_n) {
             var _res = _n.toString();
@@ -40,46 +47,76 @@
         _res += pad(_minutes) + ':' + pad(_seconds);
         return _res;
     }
+    
+    var _html = '<li><h3>Tags</h3></li>',
+        _projtitle = this.data.meta["dc:title"],
+        _this = this,
+        count = 0;
+    _this.title_$.text('LDT Project: "' + _projtitle + '"');
+    Rkns._(_this.data.tags).map(function(_tag) {
+        var _title = _tag.meta["dc:title"];
+        if (searchstr && !rxtest.test(_title)) {
+            return;
+        }
+        count++;
+        _html += _this.tagTemplate({
+            ldt_platform: _this.ldt_platform,
+            title: _title,
+            htitle: highlight(_title),
+            encodedtitle : encodeURIComponent(_title)
+        })
+    });
+    _html += '<li><h3>Annotations</h3></li>';
+    Rkns._(_this.data.annotations).map(function(_annotation) {
+        var _description = _annotation.content.description,
+            _title = _annotation.content.title.replace(_description,"");
+        if (searchstr && !rxtest.test(_title) && !rxtest.test(_description)) {
+            return;
+        }
+        count++;
+        var _duration = _annotation.end - _annotation.begin,
+            _img = (
+                (_annotation.content && _annotation.content.img && _annotation.content.img.src)
+                ? _annotation.content.img.src
+                : ( _duration ? "img/ldt-segment.png" : "img/ldt-point.png" )
+            );
+        _html += _this.annotationTemplate({
+            ldt_platform: _this.ldt_platform,
+            title: _title,
+            htitle: highlight(_title),
+            description: _description,
+            hdescription: highlight(_description),
+            start: convertTC(_annotation.begin),
+            end: convertTC(_annotation.end),
+            duration: convertTC(_duration),
+            mediaid: _annotation.media,
+            annotationid: _annotation.id,
+            image: _img
+        });
+    });
+    
+    this.main_$.html(_html);
+    if (searchstr && count) {
+        this.count_$.text(count).show();
+    } else {
+        this.count_$.hide();
+    }
+    if (searchstr && !count) {
+        this.$.hide();
+    } else {
+        this.$.show();
+    }
+    _renkan.resizeBins();
+}
+
+Rkns.Ldt.ProjectBin.prototype.refresh = function() {
+    var _this = this;
     Rkns.$.ajax({
         url: this.ldt_platform + 'ldtplatform/ldt/cljson/id/' + this.proj_id,
         dataType: "jsonp",
         success: function(_data) {
-            var _html = '<li><h3>Tags</h3></li>',
-                _projtitle = _data.meta["dc:title"];
-            _this.title_$.html('LDT Project: "' + _projtitle + '"');
-            _html += Rkns._(_data.tags).map(function(_tag) {
-                var _title = _tag.meta["dc:title"]
-                return _this.tagTemplate({
-                    ldt_platform: _this.ldt_platform,
-                    title: _title,
-                    encodedtitle : encodeURIComponent(_title)
-                })
-            }).join("");
-            _html += '<li><h3>Annotations</h3></li>';
-            _html += Rkns._(_data.annotations).map(function(_annotation) {
-                var _description = _annotation.content.description,
-                    _title = _annotation.content.title.replace(_description,""),
-                    _duration = _annotation.end - _annotation.begin,
-                    _img = (
-                        (_annotation.content && _annotation.content.img && _annotation.content.img.src)
-                        ? _annotation.content.img.src
-                        : ( _duration ? "img/ldt-segment.png" : "img/ldt-point.png" )
-                    );
-                return _this.annotationTemplate({
-                    ldt_platform: _this.ldt_platform,
-                    title: _title,
-                    description: _description,
-                    start: convertTC(_annotation.begin),
-                    end: convertTC(_annotation.end),
-                    duration: convertTC(_duration),
-                    mediaid: _annotation.media,
-                    annotationid: _annotation.id,
-                    image: _img
-                });
-            }).join("");
-            
-            _this.main_$.html(_html);
-            _renkan.resizeBins();
+            _this.data = _data;
+            _this.render();
         }
     });
 }
\ No newline at end of file
--- a/client/js/main.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/main.js	Mon Dec 31 13:37:31 2012 +0100
@@ -56,6 +56,9 @@
                 _this.refresh();
                 return false;
             });
+        this.count_$ = Rkns.$('<div>')
+            .addClass("Rk-Bin-Count")
+            .appendTo(this.$);
         this.title_$ = Rkns.$('<h2>')
             .addClass("Rk-Bin-Title")
             .appendTo(this.$);
@@ -110,12 +113,12 @@
         _this.$.find(".Rk-Bin-Item.dragging").removeClass("dragging");
     });
     if (!_opts.search.length) {
-        this.$.find(".Rk-Search-Form").detach();
+        this.$.find(".Rk-Web-Search-Form").detach();
     } else {
         var _tmpl = Rkns._.template('<li class="<%= className %>" data-key="<%= key %>"><%= title %></li>'),
             _select = this.$.find(".Rk-Search-List"),
-            _input = this.$.find(".Rk-Search-Input")
-            _form = this.$.find(".Rk-Search-Form");
+            _input = this.$.find(".Rk-Web-Search-Input")
+            _form = this.$.find(".Rk-Web-Search-Form");
         Rkns._(_opts.search).each(function(_search, _key) {
             var _searchObj = new _search.type(_this, _search);
             _this.search_engines.push(_searchObj);
@@ -186,13 +189,25 @@
     Rkns.$(window).resize(function() {
         _this.resizeBins();
     });
+    
+    this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input", function() {
+       var val = Rkns.$(this).val();
+       Rkns._(_this.tabs).each(function(tab) {
+           tab.render(val);
+       });
+    });
+    this.$.find(".Rk-Bins-Search-Form").submit(function() {
+        return false
+    });
 }
 
 Rkns.Renkan.prototype.template = Rkns._.template(
     '<div class="Rk-Title"><h1>Hyper Plateau</h1></div><div class="Rk-Bins">'
-    + '<form class="Rk-Search-Form"><input class="Rk-Search-Input" type="text" placeholder="Search" />'
+    + '<form class="Rk-Web-Search-Form Rk-Search-Form"><input class="Rk-Web-Search-Input Rk-Search-Input" type="search" placeholder="Search the Web" />'
     + '<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>'
-    + '<input type="submit" value="" class="Rk-Search-Submit" /></form>'
+    + '<input type="submit" value="" class="Rk-Web-Search-Submit Rk-Search-Submit" /></form>'
+    + '<form class="Rk-Bins-Search-Form Rk-Search-Form"><input class="Rk-Bins-Search-Input Rk-Search-Input" type="search" placeholder="Search in Bins" />'
+    + '<input type="submit" value="" class="Rk-Bins-Search-Submit Rk-Search-Submit" /></form>'
     + '<ul class="Rk-Bin-List"></ul></div><div class="Rk-Render Rk-Render-Panel"></div>'
 );
 
@@ -203,8 +218,8 @@
 }
 
 Rkns.Renkan.prototype.resizeBins = function() {
-    var _d = + this.$.find(".Rk-Search-Form").outerHeight();
-    this.$.find(".Rk-Bin-Title").each(function() {
+    var _d = + this.$.find(".Rk-Web-Search-Form").outerHeight() + this.$.find(".Rk-Bins-Search-Form").outerHeight();
+    this.$.find(".Rk-Bin-Title:visible").each(function() {
         _d += Rkns.$(this).outerHeight();
     });
     this.$.find(".Rk-Bin-Main").css({
--- a/client/js/paper-renderer.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/paper-renderer.js	Mon Dec 31 13:37:31 2012 +0100
@@ -939,9 +939,7 @@
     this.renkan = _renkan;
     this.$ = Rkns.$(".Rk-Render");
     this.representations = [];
-    this.$.html(this.template({
-        l10n: _renkan.l10n
-    }))
+    this.$.html(this.template(_renkan));
     this.canvas_$ = this.$.find(".Rk-Canvas");
     this.editor_$ = this.$.find(".Rk-Editor");
     this.notif_$ = this.$.find(".Rk-Notifications");
@@ -1058,9 +1056,17 @@
     
     this.addRepresentations("Node", this.renkan.project.get("nodes"));
     this.addRepresentations("Edge", this.renkan.project.get("edges"));
+    this.renkan.project.on("change:title", function() {
+        _this.$.find(".Rk-PadTitle").val(_renkan.project.get("title"));
+    });
+    
+    this.$.find(".Rk-PadTitle").on("keyup input paste", function() {
+        _renkan.project.set({"title": $(this).val()});
+    })
+    
     this.renkan.project.get("users").each(function(_user) {
         _this.addUser(_user);
-    })
+    });
     
     this.renkan.project.on("add:users", function(_user) {
         _this.addUser(_user);
@@ -1078,11 +1084,12 @@
 }
 
 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
-    '<div class="Rk-TopBar"><h3 class="Rk-PadTitle"><%=l10n.untitled_project%></h3>'
+    '<div class="Rk-TopBar"><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%=l10n.untitled_project%>" />'
     + '<div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.full_screen%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.add_node%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.add_edge%></div></div></div>'
+    + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Save-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.save_project%></div></div></div>'
     + '<div class="Rk-TopBar-Separator"></div></div>'
     + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%=l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%=l10n.zoom_out%>"></div></div>'
@@ -1132,7 +1139,7 @@
         this.setScale(_scale);
     }
     if (nodes.length === 1) {
-        this.offset = paper.view.center.subtract(new paper.Point([nodes[0].get("position").x, nodes[0].get("position").y]));
+        this.offset = paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
         this.setScale(1);
     }
 }
--- a/client/js/renkan-publish.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/renkan-publish.js	Mon Dec 31 13:37:31 2012 +0100
@@ -905,9 +905,10 @@
 }
 
 Rkns.Renderer.Scene.prototype.autoScale = function() {
-    if (this.project.get("nodes").length) {
-        var _xx = this.project.get("nodes").map(function(_node) { return _node.get("position").x }),
-            _yy = this.project.get("nodes").map(function(_node) { return _node.get("position").y }),
+    var nodes = this.project.get("nodes")
+    if (nodes.length > 1) {
+        var _xx = nodes.map(function(_node) { return _node.get("position").x }),
+            _yy = nodes.map(function(_node) { return _node.get("position").y }),
             _minx = Math.min.apply(Math, _xx),
             _miny = Math.min.apply(Math, _yy),
             _maxx = Math.max.apply(Math, _xx),
@@ -916,6 +917,11 @@
         this.offset = paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(this.scale));
         this.redraw();
     }
+    if (nodes.length === 1) {
+        this.scale = 1;
+        this.offset = paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
+        this.redraw();
+    }
 }
 
 Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) {
--- a/client/js/twitter-bin.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/twitter-bin.js	Mon Dec 31 13:37:31 2012 +0100
@@ -44,81 +44,110 @@
     this.refresh();
 }
 
+Rkns.Twitter.Bin.prototype.render = function(searchstr) {
+    var _rgxp = new RegExp('('+(searchstr || this.search).replace(/(\W)/g,'\\$1')+')','gi');
+    if (searchstr) {
+        var rxtest = new RegExp(searchstr.replace(/(\W)/g,'\\$1'),'i');
+    }
+    function highlight(_text) {
+        return _text.replace(_rgxp, "<span class='searchmatch'>$1</span>");
+    }
+    var _html = ""
+        _this = this,
+        count = 0;
+    Rkns._(this.data.results).each(function(_result) {
+        if (searchstr && !rxtest.test(_result.text)) {
+            return;
+        }
+        count++;
+        var _entities = [],
+            _users = _result.text.match(/@[\w_]+/gm),
+            _lastpos = 0;
+        if (_users) {
+            for (var _i = 0; _i < _users.length; _i++) {
+                var _m = _users[_i],
+                    _start = _lastpos + _result.text.substr(_lastpos).search(_m),
+                    _lastpos = _start + _m.length;
+                _entities.push({
+                    "text" : _m,
+                    "start" : _start,
+                    "end" : _lastpos,
+                    "link" :'<a href="http://twitter.com/' + _m.substr(1) + '" onclick="filtrerTexte(\'' + _m + '\'); return false;" target="_blank">',
+                });
+            }
+        }
+        var _hashes = _result.text.match(/([^&]|^)#[^\s,.!?=#@&;()]+/gm),
+            _lastpos = 0;
+        if (_hashes) {
+            for (var _i = 0; _i < _hashes.length; _i++) {
+                var _m = _hashes[_i],
+                    _h = ( _m[0] == '#' ? _m : _m.substr(1) ),
+                    _start = _lastpos + _result.text.substr(_lastpos).search(_h),
+                    _lastpos = _start + _h.length;
+                _entities.push({
+                    "text" : _h,
+                    "start" : _start,
+                    "end" : _lastpos,
+                    "link" :'<a href="http://twitter.com/search?q=' + encodeURIComponent(_h) + '" onclick="filtrerTexte(\'' + _.escape(_h) + '\'); return false;" target="_blank">',
+                });
+            }
+        }
+        
+        var _urls = _result.text.match(/(www\.|https?:\/\/)[\w./_\-]+/gim),
+            _lastpos = 0;
+        if (_urls) {
+            for (var _i = 0; _i < _urls.length; _i++) {
+                var _m = _urls[_i],
+                    _start = _lastpos + _result.text.substr(_lastpos).search(_m),
+                    _lastpos = _start + _m.length;
+                _entities.push({
+                    "text" : _m,
+                    "start" : _start,
+                    "end" : _lastpos,
+                    "link" :'<a href="' + _m + '" target="_blank">',
+                });
+            }
+        }
+        _entities = Rkns._(_entities).sortBy(function(a) { return a.start });
+        var _lastend = 0,
+            _text = Rkns._(_entities).map(function(_e) {
+                var _txt = highlight(_result.text.substring(_lastend, _e.start)) + _e.link + highlight(_e.text) + '</a>';
+                _lastend = _e.end;
+                return _txt;
+            }).join("") + highlight(_result.text.substring(_lastend));
+        
+        _html += _this.tweetTemplate({
+            tweet: _result,
+            date: new Date(_result.created_at.replace(/(\+|-)/,'UTC$1')).toLocaleString(),
+            text: _text
+        });
+    });
+    this.main_$.html(_html);
+    if (searchstr && count) {
+        this.count_$.text(count).show();
+    } else {
+        this.count_$.hide();
+    }
+    if (searchstr && !count) {
+        this.$.hide();
+    } else {
+        this.$.show();
+    }
+    _renkan.resizeBins();
+}
+
 Rkns.Twitter.Bin.prototype.refresh = function() {
     var _this = this;
     Rkns.$.ajax({
-        url: "http://search.twitter.com/search.json?q=" + encodeURIComponent(this.search),
+        url: "http://search.twitter.com/search.json",
         dataType: "jsonp",
+        data: {
+            q: this.search,
+            rpp: 100
+        },
         success: function(_data) {
-            var _rgxp = new RegExp('('+_this.search.replace(/(\W)/g,'\\$1')+')','gi');
-            function highlight(_text) {
-                return _text.replace(_rgxp, "<span class='searchmatch'>$1</span>");
-            }
-            var _html = Rkns._(_data.results).map(function(_result) {
-                var _entities = [],
-                    _users = _result.text.match(/@[\w_]+/gm),
-                    _lastpos = 0;
-                if (_users) {
-                    for (var _i = 0; _i < _users.length; _i++) {
-                        var _m = _users[_i],
-                            _start = _lastpos + _result.text.substr(_lastpos).search(_m),
-                            _lastpos = _start + _m.length;
-                        _entities.push({
-                            "text" : _m,
-                            "start" : _start,
-                            "end" : _lastpos,
-                            "link" :'<a href="http://twitter.com/' + _m.substr(1) + '" onclick="filtrerTexte(\'' + _m + '\'); return false;" target="_blank">',
-                        });
-                    }
-                }
-                var _hashes = _result.text.match(/([^&]|^)#[^\s,.!?=#@&;()]+/gm),
-                    _lastpos = 0;
-                if (_hashes) {
-                    for (var _i = 0; _i < _hashes.length; _i++) {
-                        var _m = _hashes[_i],
-                            _h = ( _m[0] == '#' ? _m : _m.substr(1) ),
-                            _start = _lastpos + _result.text.substr(_lastpos).search(_h),
-                            _lastpos = _start + _h.length;
-                        _entities.push({
-                            "text" : _h,
-                            "start" : _start,
-                            "end" : _lastpos,
-                            "link" :'<a href="http://twitter.com/search?q=' + encodeURIComponent(_h) + '" onclick="filtrerTexte(\'' + _.escape(_h) + '\'); return false;" target="_blank">',
-                        });
-                    }
-                }
-                
-                var _urls = _result.text.match(/(www\.|https?:\/\/)[\w./_\-]+/gim),
-                    _lastpos = 0;
-                if (_urls) {
-                    for (var _i = 0; _i < _urls.length; _i++) {
-                        var _m = _urls[_i],
-                            _start = _lastpos + _result.text.substr(_lastpos).search(_m),
-                            _lastpos = _start + _m.length;
-                        _entities.push({
-                            "text" : _m,
-                            "start" : _start,
-                            "end" : _lastpos,
-                            "link" :'<a href="' + _m + '" target="_blank">',
-                        });
-                    }
-                }
-                _entities = Rkns._(_entities).sortBy(function(a) { return a.start });
-                var _lastend = 0,
-                    _text = Rkns._(_entities).map(function(_e) {
-                        var _txt = highlight(_result.text.substring(_lastend, _e.start)) + _e.link + highlight(_e.text) + '</a>';
-                        _lastend = _e.end;
-                        return _txt;
-                    }).join("") + highlight(_result.text.substring(_lastend));
-                
-                return _this.tweetTemplate({
-                    tweet: _result,
-                    date: new Date(_result.created_at.replace(/(\+|-)/,'UTC$1')).toLocaleString(),
-                    text: _text
-                });
-            }).join("");
-            _this.main_$.html(_html);
-            _renkan.resizeBins();
+            _this.data = _data;
+            _this.render();
         }
     });
 }
--- a/client/js/wikipedia-bin.js	Mon Dec 31 12:19:10 2012 +0100
+++ b/client/js/wikipedia-bin.js	Mon Dec 31 13:37:31 2012 +0100
@@ -26,10 +26,10 @@
 Rkns.Wikipedia.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
 
 Rkns.Wikipedia.Bin.prototype.resultTemplate = Rkns._.template(
-    '<li class="Rk-Wikipedia-Result Rk-Bin-Item" data-uri="<%=wpurl%>" '
-    + 'data-title="Wikipedia: <%=result.title%>" data-description="<%=wpdesc%>" data-image="img/wikipedia.png">'
-    + '<img class="Rk-Wikipedia-Icon" src="img/wikipedia.png"></div><h4 class="Rk-Wikipedia-Title"><a href="<%=wpurl%>" target="_blank"><%=highlightedtitle%></a></h4>'
-    + '<p class="Rk-Wikipedia-Snippet"><%=result.snippet%></p></li>'
+    '<li class="Rk-Wikipedia-Result Rk-Bin-Item" data-uri="<%-url%>" '
+    + 'data-title="Wikipedia: <%-title%>" data-description="<%-description%>" data-image="img/wikipedia.png">'
+    + '<img class="Rk-Wikipedia-Icon" src="img/wikipedia.png"></div><h4 class="Rk-Wikipedia-Title"><a href="<%-url%>" target="_blank"><%=htitle%></a></h4>'
+    + '<p class="Rk-Wikipedia-Snippet"><%=hdescription%></p></li>'
 );
 
 Rkns.Wikipedia.Bin.prototype._init = function(_renkan, _opts) {
@@ -40,23 +40,54 @@
     this.refresh();
 }
 
+Rkns.Wikipedia.Bin.prototype.render = function(searchstr) {
+    var _rgxp = new RegExp('('+(searchstr || this.search).replace(/(\W)/g,'\\$1')+')','gi');
+    if (searchstr) {
+        var rxtest = new RegExp(searchstr.replace(/(\W)/g,'\\$1'),'i');
+    }
+    function highlight(_text) {
+        return _text.replace(_rgxp, "<span class='searchmatch'>$1</span>");
+    }
+    var _html = "",
+        _this = this;
+    Rkns._(this.data.query.search).each(function(_result) {
+        var title = _result.title,
+            url = "http://" + _this.lang + ".wikipedia.org/wiki/" + encodeURI(title.replace(/ /g,"_")),
+            description = Rkns.$('<div>').html(_result.snippet).text();
+        if (searchstr && !rxtest.test(title) && !rxtest.test(description)) {
+            return;
+        }
+        count++;
+        _html += _this.resultTemplate({
+            url: url,
+            title: title,
+            htitle: highlight(title),
+            description: description,
+            hdescription: highlight(description)
+        });
+    });
+    _this.main_$.html(_html);
+    if (searchstr && count) {
+        this.count_$.text(count).show();
+    } else {
+        this.count_$.hide();
+    }
+    if (searchstr && !count) {
+        this.$.hide();
+    } else {
+        this.$.show();
+    }
+    _renkan.resizeBins();
+}
+    
 Rkns.Wikipedia.Bin.prototype.refresh = function() {
     var _this = this;
     Rkns.$.ajax({
         url: "http://" + _this.lang + ".wikipedia.org/w/api.php?action=query&list=search&srsearch=" + encodeURIComponent(this.search) + "&format=json",
         dataType: "jsonp",
         success: function(_data) {
-            var _rgxp = new RegExp('('+_this.search.replace(/(\W)/g,'\\$1')+')','gi'),
-                _html = Rkns._(_data.query.search).map(function(_result) {
-                return _this.resultTemplate({
-                    result: _result,
-                    wpurl: "http://" + _this.lang + ".wikipedia.org/wiki/" + encodeURI(_result.title.replace(/ /g,"_")),
-                    highlightedtitle: _result.title.replace(_rgxp, "<span class='searchmatch'>$1</span>"),
-                    wpdesc: Rkns.$('<div>').html(_result.snippet).text()
-                });
-            }).join("");
-            _this.main_$.html(_html);
-            _renkan.resizeBins();
+            _this.data = _data;
+            _this.render();
         }
     });
 }
\ No newline at end of file