Experimental real-time search on the 'quick search' box on the top of the
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Fri, 25 Feb 2011 22:08:51 +0000 (23:08 +0100)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Sat, 26 Feb 2011 07:40:40 +0000 (08:40 +0100)
page.

Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
classes/profile.php
core
htdocs/javascript/xorg.js
include/userset.inc.php
templates/events/index.tpl
templates/skin/common.footer.tpl

index c10b069..d9b55b0 100644 (file)
@@ -19,7 +19,7 @@
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
 
-class Profile
+class Profile implements PlExportable
 {
 
     /* name tokens */
@@ -843,6 +843,24 @@ class Profile
         return ($isOk && ($maxlen > 2 || $maxlen == strlen($_lastname)));
     }
 
+    /* Export to JSON
+     */
+    public function export()
+    {
+        return array(
+            'hrpid'        => $this->hrid(),
+            'display_name' => $this->shortName(),
+            'full_name'    => $this->fullName(),
+            'directory_name' => $this->directory_name,
+            'promo'        => $this->promo(),
+            'year_promo'   => $this->yearpromo(),
+            'is_active'    => $this->isActive(),
+            'first_name'   => $this->firstName(),
+            'last_name'    => $this->lastName(),
+            'is_female'    => $this->isFemale(),
+        );
+    }
+
     private static function fetchProfileData(array $pids, $respect_order = true, $fields = 0x0000, $visibility = null)
     {
         if (count($pids) == 0) {
diff --git a/core b/core
index bc02cec..b291bc1 160000 (submodule)
--- a/core
+++ b/core
@@ -1 +1 @@
-Subproject commit bc02ceca4595728711127a2317d35e8cfc934918
+Subproject commit b291bc172a649420710073c774de6b5470376d05
index 7ed0138..704fed1 100644 (file)
@@ -850,6 +850,133 @@ function sendTestEmail(token, hruid)
 
 // }}}
 
+/***************************************************************************
+ * Quick search
+ */
+
+(function($) {
+    function findPos(obj) {
+        var curleft = obj.offsetLeft || 0;
+        var curtop = obj.offsetTop || 0;
+        while (obj = obj.offsetParent) {
+            curleft += obj.offsetLeft
+            curtop += obj.offsetTop
+        }
+        return {x:curleft,y:curtop};
+    }
+
+    $.template('quickMinifiche',
+            '<div class="contact {{if !is_active}}grayed{{/if}}" style="clear: both">' +
+                '<div class="identity">' +
+                    '<div class="photo"><img src="photo/${hrpid}" alt="${directory_name}" /></div>' +
+                    '<div class="nom">' +
+                        '{{if is_female}}&bull;{{/if}}<a href="profile/${hrpid}">${directory_name}</a>' +
+                    '</div>' +
+                    '<div class="edu">${promo}</div>' +
+                '</div>' +
+                '<div class="noprint bits"></div>' +
+                '<div class="long"></div>' +
+            '</div>');
+
+    $.fn.extend({
+        quickSearch: function(args) {
+            var query = null;
+            var previous = null;
+            var $this = this;
+            var $popup;
+            var token = (args && args.token) || $.xsrf_token;
+            var url   = 'search';
+            var pending = false;
+            var pos     = findPos(this.get(0));
+            var disabled = false;
+            var updatePopup;
+            if (token) {
+                url += '?token=' + token;
+            }
+            $popup =  $('<div>').hide()
+                .addClass('contact-list')
+                .css({
+                    position: 'absolute',
+                    width: '300px',
+                    top: $this.css('bottom'),
+                    left: pos.x - 300 + $this.width(),
+                    clear: 'both',
+                    'text-align': 'left'
+                });
+            $this.after($popup);
+
+            function formatProfile(profile) {
+                var data = $.tmpl('quickMinifiche', profile);
+                data.find('a').popWin(840, 600).click(function() { $popup.hide(); });
+                data.click(data.find('a').click());
+                return data;
+            }
+
+            function markPending() {
+                pending = true;
+            }
+
+            function doUpdatePopup()
+            {
+                var quick = $(this).val();
+                if (disabled) {
+                    $popup.hide();
+                    return true;
+                }
+                if (previous === quick) {
+                    $popup.show();
+                    return true;
+                }
+                if (query !== null) {
+                    query.abort();
+                    query = null;
+                }
+                query = $.xapi(url, $.extend({ 'quick': quick }, args), function(data) {
+                    query = null;
+                    $popup.empty();
+                    if (data.profile_count > 10) {
+                        $popup.hide();
+                        return;
+                    }
+                    for (var i = 0, len = data.profiles.length; i < len; i++) {
+                        formatProfile(data.profiles[i]).appendTo($popup);
+                    }
+                    previous = quick;
+                    $popup.show();
+                }, function() { disabled = true; });
+                updatePopup = markPending;
+                setTimeout(function() {
+                    updatePopup = doUpdatePopup;
+                    if (pending) {
+                        updatePopup();
+                    }
+                    pending = false;
+                }, 500);
+                return true;
+            }
+            updatePopup = doUpdatePopup;
+
+            return this.keyup(function(e) {
+                if (e.keyCode != 27 /* escape */) {
+                    return updatePopup.call(this);
+                }
+                return true;
+            })
+            .keydown(function(e) {
+                if (e.keyCode == 27) {
+                    $popup.hide();
+                }
+                return true;
+            })
+            .blur(function() {
+                if (!$popup.is(':hover')) {
+                    $popup.hide();
+                }
+            })
+            .focus(updatePopup);
+        }
+    });
+}(jQuery));
 
 /***************************************************************************
  * Overlib made simple
@@ -925,7 +1052,8 @@ $(function() {
         })
         .blur(function() {
             $("#quick_button").hide();
-        });
+        })
+        .quickSearch();
     $("#quick_button").click(function() {
         if ($("#quick").val() === 'Recherche dans l\'annuaire'
             || $("#quick").val() === '') {
index e6e636e..1274a86 100644 (file)
@@ -367,10 +367,11 @@ class JSonView implements PlView
     public function apply(PlPage $page)
     {
         $export = array();
-        $profiles = $this->set->get(new PlLimit());
-        while ($profile = $profiles->next()) {
+        $profiles = $this->set->get(new PlLimit(10));
+        foreach ($profiles as $profile) {
             $export[] = $profile->export();
         }
+        $page->jsonAssign('profile_count', $this->set->count());
         $page->jsonAssign('profiles', $export);
     }
 
index c151e9e..563f0d0 100644 (file)
@@ -208,19 +208,6 @@ Bienvenue {$smarty.session.user->displayName()}{if t($birthday)}
   </p>
 
   <p class="center">
-    <a id="blah">Blah  </a>
-
-    <script type="text/javascript">//<![CDATA[
-      {literal}
-      $($("#blah").click(function() {
-        $.xapi('1/search?token={/literal}{$smarty.session.xsrf_token}{literal}',
-               { 'quick': 'fruneau' },
-               function(data) { alert(JSON.stringify(data)); });
-        return false;
-      }));
-      {/literal}
-    //]]></script>
-
     {icon name=page_edit}&nbsp;
     <a href="events/submit">Proposer une information événementielle</a>&nbsp;&bull;
     <a href="nl/submit">Proposer un article pour la Lettre mensuelle</a>
index 558086e..8b7eeba 100644 (file)
   -->
 </div>
 
+<script type="text/javascript">//<![CDATA[
+  {literal}
+  (function($) {
+    $.extend({
+      xsrf_token: {/literal}'{$smarty.session.xsrf_token}'{literal}
+    });
+  }(jQuery));
+  {/literal}
+//]]></script>
+
 {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}