2010-06-26 2 views
10

Salut, je suis en train de l'auteur d'un plugin jQuery et je dois avoir des méthodes accessibles à des éléments après leur initialisés comme ce genre d'objet, par exemple:Création de méthodes à la volée

$('.list').list({some options}); //This initializes .list as a list 

//now I want it to have certain methods like: 
$('.list').find('List item'); //does some logic that I need 

J'ai essayé avec

$.fn.list = function (options) { 
    return this.each(function() { 
     // some code here 
     this.find = function(test) { 
      //function logic 
     } 
    } 
} 

et plusieurs autres tentatives, je ne peux pas comprendre comment le faire.

EDIT:

Je vais essayer d'expliquer mieux. J'essaye de transformer une table en une liste, fondamentalement comme une liste sur un ordinateur avec des en-têtes de colonne et des articles triables et tout entre deux. Vous initiez la table avec une commande comme

$(this).list({ 
    data: [{id: 1, name:'My First List Item', date:'2010/06/26'}, {id:2, name:'Second', date:'2010/05/20'}] 
}); 

.list fera la <tbody> triables et faire quelques autres tâches initiales, puis ajoutez les méthodes suivantes à l'élément:
.findItem(condition) vous permettra de trouver un certain point par une condition (comme findItem('name == "Second"')
.list(condition) listera tous les éléments qui correspondent à une condition
.sort(key) triera tous les éléments d'une clé donnée
etc.

012 donné

Quelle est la meilleure façon de faire cela?

+1

Pouvez-vous donner un peu plus d'exemple? Il est difficile de dire ce que vous recherchez ... et ['.find()'] (http://api.jquery.com/find/) est déjà pris :) –

+1

duplication possible de [Comment créer un jQuery plugin avec des méthodes?] (http://stackoverflow.com/questions/1117086/how-to-create-a-jquery-plugin-with-methods) – redsquare

+0

le titre est trompeur, ce ne sont pas des méthodes créées à la volée. – Anurag

Répondre

2

Je trouve cette solution ici: http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html

Cela semble faire exactement ce que je dois.

(function($) { 
    var TaskList = function(element, options) 
    { 
     var $elem = $(element); 
     var options = $.extend({ 
      tasks: [], 
      folders: [] 
     }, options || {}); 

     this.changed = false; 
     this.selected = {}; 

     $elem.sortable({ 
      revert: true, 
      opacity: 0.5 
     }); 

     this.findTask = function(test, look) { 
      var results = []; 

      for (var i = 0,l = options.tasks.length; i < l; i++) 
      { 
       var t = options['tasks'][i]; 
       if (eval(test)) 
       { 
        results.push(options.tasks[i]); 
       } 
      } 
      return results; 
     } 

     var debug = function(msg) { 
      if (window.console) { 
       console.log(msg); 
      } 
     } 
    } 

    $.fn.taskList = function(options) 
    { 
     return this.each(function() { 
      var element = $(this); 

      if (element.data('taskList')) { return; } 

      var taskList = new TaskList(this, options); 

      element.data('taskList', taskList); 

     }); 
    } 

})(jQuery); 

Ensuite, je dois

$('.task-list-table').taskList({ 
     tasks: eval('(<?php echo mysql_real_escape_string(json_encode($tasks)); ?>)'), 
     folders: eval('(<?php echo mysql_real_escape_string(json_encode($folders)); ?>)') 
    }); 
    var taskList = $('.task-list-table').data('taskList'); 

et je peux utiliser taskList.findTask(condition);

Et puisque le constructeur a $elem je peux également modifier l'instance jQuery pour des méthodes comme list(condition) etc. Cela fonctionne parfaitement.

+0

+1 - J'aime cette approche. – Anurag

0

this.each n'est pas nécessaire. Cela devrait faire:

$.fn.list = function (options) { 
    this.find = function(test) { 
     //function logic 
    }; 
    return this; 
}; 

Notez que vous seriez écrasez méthode find native de jQuery, et ce, n'est pas recommandé.


Aussi, pour ce que ça vaut, je ne pense pas que ce soit une bonne idée. Les instances de jQuery sont supposées n'avoir que des méthodes héritées de l'objet prototype de jQuery, et en tant que tel je pense que ce que vous voulez faire ne serait pas cohérent avec le comportement jQuery-plugin généralement accepté - c'est-à-dire l'objet this (l'occurrence de jQuery) inchangé.

+0

Bien que je sois d'accord * habituellement *, ce n'est pas toujours le cas, un exemple majeur auquel je peux penser est le plugin de validation ... tout dépend de ce que vous avez besoin sont. –

+0

J'ai essayé de le faire (j'ai changé le .find en .findItem) et je me suis retrouvé avec l'erreur $ ('. List-box'). FindItem n'est pas une fonction – Rob

+0

Désolé, j'ai oublié d'ajouter que vous devez '' retour ceci; '... – James

2

Si vous souhaitez que ces méthodes soient disponibles sur n'importe quel objet jQuery, vous devrez ajouter chacune d'entre elles au prototype de jQuery. La raison en est que chaque fois que vous appelez $(".list") un nouvel objet est créé et toutes les méthodes que vous avez attachées à un objet précédent seront perdues.

Attribuez à chaque méthode pour le prototype de jQuery:

jQuery.fn.extend({ 
    list: function() { .. }, 
    findItem: function() { .. }, 
    sort: function() { .. } 
}); 

La méthode list ici est spécial car il peut être invoqué à deux reprises. D'abord, lors de l'initialisation de la liste, et ensuite lors de la recherche d'éléments particuliers par une condition. Vous auriez à différencier ces deux cas d'une manière ou d'une autre - soit par type d'argument, soit par un autre paramètre.

Vous pouvez également utiliser l'API data pour déclencher une exception si ces méthodes sont appelées pour un objet qui n'a pas été initialisé avec le plug-in list.Lorsque ('xyz').list({ .. }) est appelée en premier, stockez une variable d'état dans le cache de données pour cet objet. Lorsque l'une des autres méthodes - "list", "findItem" ou "sort" est appelée ultérieurement, vérifiez si l'objet contient cette variable d'état dans son cache de données.

Une meilleure approche serait de namespace votre plugin de sorte que list() retournera l'objet étendu. Les trois méthodes étendues peuvent être appelées sur sa valeur de retour. L'interface serait comme:

$('selector').list({ ... }); 
$('selector').list().findOne(..); 
$('selector').list().findAll(..); 
$('selector').list().sort(); 

Ou enregistrer une référence à l'objet retourné la première fois, et appeler des méthodes sur directement.

var myList = $('selector').list({ ... }); 
myList.findOne(..); 
myList.findAll(..); 
myList.sort(); 
+0

Merci pour l'info, qui était en fait très utile je me rends finalement compte pourquoi mes méthodes n'existaient pas. Ne pourrais-je pas faire '$ list = $ ('. List'). List ({options});' et utiliser $ list à partir de ce point? Quoi qu'il en soit, j'ai trouvé une autre solution, je vais l'afficher comme réponse. +1 bien merci – Rob

+0

@Rob - Vous pouvez le faire, tant que dans la méthode 'list', vous étendez l'objet jQuery avec toutes les fonctions dont vous avez besoin, et à partir de ce moment référence' $ list' pour appeler ces fonctions. Cela dit, je pense que votre approche est meilleure. – Anurag