Fix bad redirect to search page.
[platal.git] / htdocs / javascript / xorg.js
index f025d67..20221e2 100644 (file)
@@ -18,8 +18,6 @@
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
 
-var is_IE       = $.browser.msie;
-
 // {{{ function getNow()
 var days   = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
 var months = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
@@ -471,7 +469,6 @@ function hash_xor(a, b) {
     return c;
 }
 
-
 function getType(c) {
     if (c >= 'a' && c <= 'z') {
         return 1;
@@ -603,12 +600,12 @@ function correctUserName() {
     var mots;
 
     // login with no space
-    if (u.value.contains(' ')) {
+    if (!u.value.contains(' ')) {
         return true;
     }
     mots = u.value.split(' ');
     // jean paul.du pont -> jean-paul.du-pont
-    if (u.value.indexOf('.') > 0) {
+    if (u.value.contains('.')) {
         u.value = mots.join('-');
         return true;
     }
@@ -692,7 +689,478 @@ function sendTestEmail(token, hruid)
 }
 
 // }}}
+// {{{ jQuery object extension
+
+(function($) {
+    /* Add new functions to jQuery namesapce */
+    $.extend({
+        /* The goal of the following functions is to provide an AJAX API that
+         * take a different callback in case of HTTP success code (2XX) and in
+         * other cases.
+         */
+
+        xajax: function(source, method, data, onSuccess, onError, type) {
+            /* Shift argument */
+            if ($.isFunction(data)) {
+                type = type || onError;
+                onError = onSuccess;
+                onSuccess = data;
+                data = null;
+            }
+            if (onError != null && !$.isFunction(onError)) {
+                type = type || onError;
+                onError = null;
+            }
+
+            function ajaxHandler(data, textStatus, xhr) {
+                if (textStatus == 'success') {
+                    if (onSuccess) {
+                        onSuccess(data, textStatus, xhr);
+                    }
+                } else if (textStatus == 'error') {
+                    if (onError) {
+                        onError(data, textStatus, xhr);
+                    } else {
+                        alert("Une error s'est produite lors du traitement de la requête.\n"
+                            + "Ta session a peut-être expiré");
+                    }
+                }
+            }
+            return $.ajax({
+                url: source,
+                type: method,
+                success: ajaxHandler,
+                data : data,
+                dataType: type
+            });
+        },
+
+        xget: function(source, data, onSuccess, onError, type) {
+            return $.xajax(source, 'GET', data, onSuccess, onError, type);
+        },
+
+        xgetJSON: function(source, data, onSuccess, onError) {
+            return $.xget(source, data, onSuccess, onError, 'json');
+        },
+
+        xgetScript: function(source, onSuccess, onError) {
+            return $.xget(source, null, onSuccess, onError, 'script');
+        },
+
+        xgetText: function(source, data, onSuccess, onError) {
+            return $.xget(source, data, onSuccess, onError, 'text');
+        },
+
+        xpost: function(source, data, onSuccess, onError, type) {
+            return $.xajax(source, 'POST', data, onSuccess, onError, type);
+        }
+    });
+
+    /* Add new functions to jQuery objects */
+    $.fn.extend({
+        tmpMessage: function(message, success) {
+            if (success) {
+                this.html("<img src='images/icons/wand.gif' alt='' /> " + message)
+                    .css('color', 'green');
+            } else {
+                this.html("<img src='images/icons/error.gif' alt='' /> " + message)
+                    .css('color', 'red');
+            }
+            return this.css('fontWeight', 'bold')
+                       .show()
+                       .delay(1000)
+                       .fadeOut(500);
+        },
+
+        updateHtml: function(source, callback) {
+            var elements = this;
+            function handler(data) {
+                elements.html(data);
+                if (callback) {
+                    callback(data);
+                }
+            }
+            $.xget(source, handler, 'text');
+            return this;
+        },
+
+        successMessage: function(source, message) {
+            var elements = this;
+            $.xget(source, function() {
+                elements.tmpMessage(message, true);
+            });
+            return this;
+        },
+
+        wiki: function(text, withTitle) {
+            if (text == '') {
+                return this.html('');
+            }
+            var url = 'wiki_preview';
+            if (!withTitle) {
+                url += '/notitile';
+            }
+            var $this = this;
+            $.post(url, { text: text },
+                   function (data) {
+                       $this.html(data);
+                   }, 'text');
+            return this;
+        },
+
+        popWin: function(w, h) {
+            return this.click(function() {
+                window.open(this.href, '_blank',
+                            'toolbar=0,location=0,directories=0,status=0,'
+                           +'menubar=0,scrollbars=1,resizable=1,'
+                           +'width='+w+',height='+h);
+                return false;
+            });
+        }
+    });
+})(jQuery);
+
+// }}}
+// {{{ preview wiki
+
+function previewWiki(idFrom, idTo, withTitle, idShow)
+{
+    $('#' + idTo).wiki($('#' + idFrom).val(), withTitle);
+    if (idShow != null) {
+        $('#' + idShow).show();
+    }
+}
+
+// }}}
+// {{{ send test email
+
+function sendTestEmail(token, hruid)
+{
+    var url = 'emails/test';
+    var msg = "Un email a été envoyé avec succès";
+    if (hruid != null) {
+        url += '/' + hruid;
+        msg += " sur l'adresse de " + hruid + ".";
+    } else {
+        msg += " sur ton addresse.";
+    }
+    $('#mail_sent').successMessage($url + '?token=' + token, msg);
+    return false;
+}
+
+// }}}
+
+/***************************************************************************
+ * 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>${directory_name}</a>' +
+                    '</div>' +
+                    '<div class="edu">${promo}</div>' +
+                '</div>' +
+                '<div class="noprint bits"></div>' +
+                '<div class="long"></div>' +
+            '</div>');
+
+
+    function buildPopup(input, destination, linkBindFunction)
+    {
+        var pos    = findPos(input.get(0));
+        var $popup = destination;
+        var selected = null;
+        var hovered  = 0;
+
+        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)
+                .css('cursor', 'pointer')
+                .hover(function() {
+                    selected = i;
+                    updateSelection();
+                    hovered++;
+                }, function() {
+                    if (selected === i) {
+                        selected = null;
+                        updateSelection();
+                    }
+                    hovered--;
+                }).mouseup(function() {
+                    var sel = $(this).find('a');
+                    if (!sel.attr('hovered')) {
+                        sel.click();
+                    }
+                });
+            data.find('a').hover(function() { $(this).attr('hovered', true) },
+                                 function() { $(this).attr('hovered', false) });
+            return data;
+        }
 
+        if (!$popup) {
+            $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'
+            });
+            input.after($popup);
+        }
+
+        return {
+            hide: function(ignoreIfHover) {
+                if (ignoreIfHover && hovered !== 0) {
+                    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, extra) {
+                var profile;
+                var $this;
+                $popup.empty();
+                for (var i = 0, len = profiles.length; i < len; i++) {
+                    (function(elt) {
+                        var profile = formatProfile(i, elt);
+                        profile.find('a').each(function() {
+                            linkBindFunction.call(this, elt, $this, extra);
+                        });
+                        profile.appendTo($popup);
+                    }(profiles[i]));
+                }
+                if (len === 1) {
+                    selected = 0;
+                } else {
+                    selected = null;
+                }
+                updateSelection();
+                if (len > 0) {
+                    this.show();
+                } else {
+                    this.hide();
+                }
+                return true;
+            }
+        };
+    }
+
+    $.fn.extend({
+        quickSearch: function(options) {
+            return this.each(function() {
+            var $this  = $(this);
+            var $input = this;
+            var $popup;
+            var previous = null;
+            var pending  = false;
+            var disabled = false;
+            var updatePopup;
+
+            options = options || { };
+            options = $.extend({
+                destination:       null,
+                minChars:          3,
+                shortChars:        5,
+                shortTimeout:      300,
+                longTimeout:       100,
+                queryParams:       {
+                    offset: 0,
+                    count:  10,
+                    allow_special: true,
+                },
+                loadingClassLeft:  'ac_loading',
+                loadingClassRight: 'ac_loading_left',
+                selectAction: function(profile, popup, extra) {
+                    var type = extra.link_type || 'profile';
+                    switch (type) {
+                      case 'profile':
+                        $(this).attr('href', 'profile/' + profile.hrpid)
+                        .popWin(840, 600)
+                        .click(function() { $popup.hide(); return false; });
+                        break;
+                      case 'admin':
+                        $(this).attr('href', 'admin/user/' + profile.hrpid)
+                        .click(function() { window.open($(this).attr('href')); return false });
+                        break;
+                    }
+                }
+            }, options);
+            options.loadingClass = $this.css('text-align') === 'right' ? options.loadingClassRight
+                                                                       : options.loadingClassLeft;
+            $this.attr('autocomplete', 'off');
+            $popup = buildPopup($this, options.destination, options.selectAction);
+
+            function markPending() {
+                pending = true;
+            }
+
+            function performUpdate(quick)
+            {
+                if (updatePopup === markPending) {
+                    return true;
+                }
+                updatePopup = markPending;
+                $this.addClass(options.loadingClass);
+                $.xapi('search', $.extend({ 'quick': quick }, options.queryParams), function(data) {
+                    if (data.profile_count > options.queryParams.count || data.profile_count < 0) {
+                        return $popup.hide();
+                    }
+                    $popup.updateContent(data.profiles, data);
+                    previous = quick;
+                }, function(data, text) {
+                    if (text !== 'abort') {
+                        disabled = true;
+                    }
+                }).complete(function() {
+                    $this.removeClass(options.loadingClass);
+                    updatePopup = doUpdatePopup;
+                    if (pending) {
+                        updatePopup();
+                    }
+                });
+                return true;
+            }
+
+            function doUpdatePopup(dontDelay)
+            {
+                var quick = $this.val();
+                if ($.isFunction(quick.trim)) {
+                    quick = quick.trim();
+                }
+                pending = false;
+                if (disabled || quick.length < options.minChars) {
+                    previous = quick;
+                    return $popup.hide();
+                } else if (!dontDelay) {
+                    var timeout = quick.length < options.shortChars ? options.shortTimeout : options.longTimeout;
+                    setTimeout(function() {
+                        updatePopup(true);
+                    }, timeout);
+                    return true;
+                } else if (previous === quick) {
+                    return $popup.show();
+                }
+                return performUpdate(quick);
+            }
+
+            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();
+                }
+                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
@@ -707,10 +1175,10 @@ function sendTestEmail(token, hruid)
             if (typeof text === 'string') {
                 args.push(text);
                 if (width) {
-                    args.push(width);
+                    args.push(WIDTH, width);
                 }
                 if (height) {
-                    args.push(height);
+                    args.push(HEIGHT, height);
                 }
             } else {
                 for (key in text) {
@@ -749,7 +1217,7 @@ function sendTestEmail(token, hruid)
         }
     });
 }(jQuery));
-
+/* }}} */
 
 /***************************************************************************
  * The real OnLoad
@@ -768,7 +1236,8 @@ $(function() {
         })
         .blur(function() {
             $("#quick_button").hide();
-        });
+        })
+        .quickSearch();
     $("#quick_button").click(function() {
         if ($("#quick").val() === 'Recherche dans l\'annuaire'
             || $("#quick").val() === '') {