Split code in order to make it a bit more readable.
[platal.git] / htdocs / javascript / xorg.js
index 7ed0138..e9bc0af 100644 (file)
@@ -850,6 +850,265 @@ function sendTestEmail(token, hruid)
 
 // }}}
 
+/***************************************************************************
+ * Quick search
+ */
+
+/* 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 grayed" 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>');
+
+
+    function buildPopup(input, linkBindFunction)
+    {
+        var pos    = findPos(input.get(0));
+        var $popup = $('<div>').hide()
+            .addClass('contact-list')
+            .css({
+                position: 'absolute',
+                width: '300px',
+                top: input.css('bottom'),
+                left: pos.x - 300 + input.width(),
+                clear: 'both',
+                'text-align': 'left'
+            });
+        var selected = null;
+
+        function updateSelection()
+        {
+            var sel = $popup.children('.contact').addClass('grayed');
+            if (selected !== null) {
+                while (selected < 0) {
+                    selected += sel.length;
+                }
+                if (selected >= sel.length) {
+                    selected -= sel.length;
+                }
+                sel.eq(selected).removeClass('grayed');
+            }
+        }
+
+        function formatProfile(i, profile) {
+            var data = $.tmpl('quickMinifiche', profile)
+                .hover(function() {
+                    selected = i;
+                    updateSelection();
+                }, function() {
+                    if (selected === i) {
+                        selected = null;
+                        updateSelection();
+                    }
+                }).mouseup(function() {
+                    if (!($(this).find('a').is(':hover'))) {
+                        $(this).find('a').click();
+                    }
+                });
+            return data;
+        }
+
+        input.after($popup);
+
+        return {
+            hide: function(ignoreIfHover) {
+                if (ignoreIfHover && $popup.is(':hover')) {
+                    return true;
+                }
+                selected = null;
+                updateSelection();
+                $popup.hide();
+                return true;
+            },
+
+            show: function() {
+                $popup.show();
+                return true;
+            },
+
+            selected: function() {
+                return selected !== null;
+            },
+
+            unselect: function() {
+                selected = null;
+                updateSelection();
+            },
+
+            selectNext: function() {
+                if (selected === null) {
+                    selected = 0;
+                } else {
+                    selected++;
+                }
+                updateSelection();
+                return true;
+            },
+
+            selectPrev: function() {
+                if (selected === null) {
+                    selected = -1;
+                } else {
+                    selected--;
+                }
+                updateSelection();
+                return true;
+            },
+
+            activeCurrent: function() {
+                var sel = $popup.children('.contact');
+                if (selected !== null) {
+                    sel.eq(selected).find('a').click();
+                    return false;
+                }
+                return true;
+            },
+
+            updateContent: function(profiles) {
+                var profile;
+                $popup.empty();
+                for (var i = 0, len = profiles.length; i < len; i++) {
+                    profile = formatProfile(i, profiles[i]);
+                    profile.find('a').each(linkBindFunction);
+                    profile.appendTo($popup);
+                }
+                if (len === 1) {
+                    selected = 0;
+                } else {
+                    selected = null;
+                }
+                updateSelection();
+                if (len > 0) {
+                    this.show();
+                } else {
+                    this.hide();
+                }
+                return true;
+            }
+        };
+    }
+
+    $.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 disabled = false;
+            var updatePopup;
+            if (token) {
+                url += '?token=' + token;
+            }
+
+            $popup = buildPopup(this, function() {
+                $(this).popWin(840, 600)
+                    .click(function() {
+                        $popup.hide();
+                    });
+            });
+
+            function markPending() {
+                pending = true;
+            }
+
+            function doUpdatePopup()
+            {
+                var quick = $(this).val();
+                if (query !== null) {
+                    query.abort();
+                }
+                if (disabled || quick.length < 3) {
+                    previous = quick;
+                    $popup.hide();
+                    return true;
+                }
+                if (previous === quick) {
+                    $popup.show();
+                    return true;
+                }
+                query = $.xapi(url, $.extend({ 'quick': quick }, args), function(data) {
+                    query = null;
+                    if (data.profile_count > 10 || data.profile_count < 0) {
+                        $popup.hide();
+                        return;
+                    }
+                    $popup.updateContent(data.profiles);
+                    previous = quick;
+                }, function() { disabled = true; });
+                updatePopup = markPending;
+                setTimeout(function() {
+                    updatePopup = doUpdatePopup;
+                    if (pending) {
+                        updatePopup.call($this.get(0));
+                    }
+                    pending = false;
+                }, 500);
+                return true;
+            }
+
+            updatePopup = doUpdatePopup;
+
+            return this.keyup(function(e) {
+                if (e.keyCode !== 27 /* escape */ && e.keyCode !== 13 /* enter */
+                    && e.keyCode !== 9 /* tab */ && e.keyCode !== 38 /* up */
+                    && e.keyCode !== 40 /* down */) {
+                    return updatePopup.call(this);
+                }
+                return true;
+            })
+            .keydown(function(e) {
+                switch (e.keyCode) {
+                  case 9: /* Tab */
+                  case 40: /* Down */
+                    $popup.selectNext();
+                    return false;
+
+                  case 38:
+                    $popup.selectPrev();
+                    return false;
+
+                  case 13: /* Return */
+                    return $popup.activeCurrent();
+
+                  case 27: /* Escape */
+                    if ($popup.selected()) {
+                        $popup.unselect();
+                    } else {
+                        $popup.hide();
+                    }
+                    return true;
+                }
+                return true;
+            })
+            .blur(function() {
+                return $popup.hide(true);
+            })
+            .focus(updatePopup);
+        }
+    });
+}(jQuery));
 
 /***************************************************************************
  * Overlib made simple
@@ -906,7 +1165,7 @@ function sendTestEmail(token, hruid)
         }
     });
 }(jQuery));
-
+/* }}} */
 
 /***************************************************************************
  * The real OnLoad
@@ -925,7 +1184,8 @@ $(function() {
         })
         .blur(function() {
             $("#quick_button").hide();
-        });
+        })
+        .quickSearch();
     $("#quick_button").click(function() {
         if ($("#quick").val() === 'Recherche dans l\'annuaire'
             || $("#quick").val() === '') {