JAVASCRIPT : jQuery - keyChange (juillet 2012)

Vous qui lisez ces lignes, vous devez connaître tous les plugins d'autocomplete et autres qui existent de part la toile.

Ils sont tous plus ou moins sympas, mais en voulant en chercher un qui ne s'occupe que de la mécanique de détection de la frappe, je me suis retrouvé face au néant.

J'avais simplement besoin d'un plugin qui me déclenche un évènement de frappe de texte pour effectuer un filtrage sur les données d'un select, impossible d'en trouver un.

Force a été de constater qu'il était plus rentable de le coder que de passer des heures à chercher.

Exemples

Exemple le plus basique

Javascript :

$(function(){
    $('input.demo1').keyChange(function(evt, text){
        $('span.demo1').html(text);
    });
});

Html :

<p>
    <input type="text" class="demo1" /><br />
    saisie : <span class="demo1"></span>
</p>

Résultat :


saisie :

On déclare simplement une fonction de callback qui vient écrire le texte tapé dans un span. Une utilisation réelle serait pour filtrer des données ou faire une requête ajax de filtrage etc ...

Exemple avec plus de paramètres

Javascript :

$(function(){
    $('input.demo2').keyChange({
        minLength: 3,
        delay: 1000
    }, function(evt, text){
        $('span.demo2').html(text);
    });
});

Html :

<p>
    <input type="text" class="demo2" /><br />
    saisie : <span class="demo2"></span>
</p>

Résultat :


saisie :

La syntaxe doit vous rappeler le binding d'évènement jQuery, c'est normal, le principe est le même, vous pouvez passer des options au binding. Dans le cas ou vous voulez utiliser ces options, il doit d'agir du premier appel à keyChange pour les éléments considérés, sinon, les options seront ignorées.

Exemple "live" bindé sur document

Javascript :

$(function () {
    $(document).keyChange('input.demo3', function (evt, text) {
        $(this).next('span.res3').html(text);
    });
});

Html :

<p class="demo3">
    <input type="text" class="demo3" /> 
    saisie : <span class="res3"></span>
</p>

Résultat :

saisie :


cette syntaxe JS ext un équivalent de ce qu'on voudrait naturellement écrire $(document).on('keyChange', ...).
Il est obligatoire de passer par cette syntaxe $(document).keyChange(...) car cela positionne correctement les events dépendants.

Exemple plus exotique

Javascript :

$(function(){
    $('input.demo4')
    .keyChange()
    .bind('keyChange', 
        function(evt, text){
            $('span.res4').html(text);
        }
    )
    .bind('keyChange', 
        function(evt, text){
            var nb = $('span.cpt4').html();
            $('span.cpt4').html(parseInt(nb) + 1);
        }
    );
});

Html :

<p>
    <input type="text" class="demo4" /><br />
    saisie : <span class="res4"></span><br />
    compteur : <span class="cpt4">0</span>
</p>

Résultat :


saisie :
compteur : 0

Le code JS déclenche le système de binding .keyChange(), puis connecte ensuite deux évènements via le bind jQuery.
La syntaxe .bind('keyChange', function(evt, text) { ... })
est en fait complètement équivalente à .keyChange(function(evt, text) { ... })

Code source du plugin

(function ($) {
    $.fn.keyChange = function (options, selector, callback) {

        if ($.isFunction(options)) {
            callback = options;
            options = {};
            selector = undefined;
        }
        if ($.isFunction(selector)) {
            callback = selector;
            if (typeof (options) === 'string') {
                selector = options;
                options = {};
            } else {
                selector = undefined;
            }
        }

        options = $.extend({
            minLength: 0,
            delay: 300
        }, options || {});

        function init(val) {
            var $this = $(this);
            if (!$this.data('kcInitialized')) {
                if ($this.is('input') || $this.is('textarea')) {
                    $this.data('kcText', typeof (val) === 'undefined' ? String($this.val()) : val);
                    $this.data('kcFunction', null);
                }
                $this.data('kcInitialized', true);
            }
        }

        function keyup() {
            init.call(this, '');
            var $this = $(this);
            if ($this.data('kcInitialized')) {
                var val = String($this.val());
                var text = $this.data('kcText');
                var delayedFunction = $this.data('kcFunction');
                if (text !== val && val.length >= options.minLength) {
                    $this.data('kcText', val);
                    delayedFunction && clearTimeout(delayedFunction);
                    $this.data('kcFunction', setTimeout(function () {
                        $this.trigger('keyChange', val);
                    }, options.delay));
                }
            }
        }

        if (typeof (selector) === 'string') {
            this.on('change', selector, keyup);
            this.on('keyup', selector, keyup);
            if ($.isFunction(callback)) {
                this.on('keyChange', selector, callback);
            }
        } else {
            this.each(function () {
                init.apply(this);
            });
            this.change(keyup);
            this.keyup(keyup);
            if ($.isFunction(callback)) {
                this.bind('keyChange', callback);
            }
        }
        return this;
    };
})(jQuery);