2010-06-26 11 views
10

Hola estoy tratando de autor de un plugin de jQuery y tengo que tener métodos accesibles a los elementos después de que se inicializan como ese tipo de objeto, por ejemplo:métodos Creación sobre la marcha

$('.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 

he intentado con

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

y varios intentos diferentes, simplemente no puedo encontrar la manera de hacerlo.

EDIT:

Voy a tratar de explicar esto mejor.

Estoy tratando de convertir una tabla en una lista, básicamente como una lista en una computadora con encabezados de columna y elementos ordenables y todo lo demás. Usted inicia la tabla con un comando como

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

.list hará que el <tbody> puede ordenar y hacer algunas otras tareas iniciales, a continuación, añadir los siguientes métodos para el elemento:
.findItem(condition) le permitirá encontrar un determinado artículo por una condición (como findItem('name == "Second"')
.list(condition) una lista de todos los elementos que coinciden con una condición dada
.sort(key) clasificará todos los artículos por una clave dada
etc.

¿Cuál es la mejor manera de hacerlo?

+1

¿Puedes dar un poco más de un ejemplo? Es difícil decir lo que está buscando ... y ['.find()'] (http://api.jquery.com/find/) ya está ocupado :) –

+1

posible duplicado de [Cómo crear un jQuery plugin with methods?] (http://stackoverflow.com/questions/1117086/how-to-create-a-jquery-plugin-with-methods) – redsquare

+0

título es engañoso, estos no son métodos creados sobre la marcha. – Anurag

Respuesta

2

He encontrado esta solución aquí: http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html

Esto parece hacer exactamente lo que necesito.

(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); 

entonces he

$('.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'); 

y puedo usar taskList.findTask(condition);

Y puesto que el constructor tiene $elem También puede editar la instancia de jQuery para métodos como list(condition) etc. Esta aplicación funciona perfectamente.

+0

+1 - Me gusta este enfoque. – Anurag

0

this.each no es necesario. Esto debería hacer:

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

Tenga en cuenta que usted estaría a sobrescribir método nativo find de jQuery, y al hacerlo, no se recomienda.


Además, por lo que vale, no creo que sea una buena idea. Se supone que las instancias de jQuery solo tienen métodos heredados del objeto prototipo de jQuery, y como tal, creo que lo que desea hacer no sería coherente con el comportamiento jQuery-plugin generalmente aceptado, es decir, devolver el objeto this (instancia de jQuery) sin cambios.

+0

Aunque estoy de acuerdo * por lo general *, este no es siempre el caso, un ejemplo importante que puedo pensar es el complemento de validación ... todo depende de lo que necesites son. –

+0

Intenté hacer exactamente eso (cambié el .find a .findItem) y terminé con el error $ ('. List-box'). FindItem no es una función – Rob

+0

Lo siento, olvidé agregar que tienes que ' devuelva esto; '... – James

2

Si desea que estos métodos estén disponibles en cualquier objeto jQuery, deberá agregar cada uno de ellos al prototipo de jQuery. El motivo es que cada vez que llamas al $(".list"), se crea un objeto nuevo y se perderán todos los métodos que hayas agregado a un objeto anterior.

Asignar a cada método prototipo de jQuery como:

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

El método list aquí es especial, ya que puede ser invocada en dos ocasiones. Primero, al inicializar la lista, y segundo al encontrar elementos particulares por una condición. Tendría que diferenciar entre estos dos casos de alguna manera, ya sea por tipo de argumento u otro parámetro.

También puede usar la API data para lanzar una excepción si se solicitan estos métodos para un objeto que no se ha inicializado con el complemento de lista.Cuando se llama por primera vez al ('xyz').list({ .. }), almacene alguna variable de estado en la memoria caché de datos para ese objeto. Cuando cualquiera de los otros métodos - "list", "findItem" u "sort" son invocados más tarde, verifique si el objeto contiene esa variable de estado en su caché de datos.

Un mejor enfoque sería el espacio de nombres de su complemento para que list() devolverá el objeto extendido. Se pueden invocar los tres métodos extendidos en su valor de retorno. La interfaz sería como:

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

o guardar una referencia al objeto devuelto por primera vez, y llamar a métodos en él directamente.

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

Gracias por la información, que en realidad fue muy útil, finalmente me di cuenta de por qué mis métodos no existían. ¿No podría hacer '$ list = $ ('. List'). List ({options});' y usar $ list desde ese momento? De todos modos, encontré otra solución, la voy a publicar como respuesta. +1 a pesar de – Rob

+0

@Rob - Puedes hacerlo, siempre y cuando estés dentro del método 'list', extiendes el objeto jQuery con todas las funciones que necesitas, y desde este punto en adelante haz referencia' $ list' para llamar a esas funciones. Dicho esto, creo que su enfoque es mejor. – Anurag

Cuestiones relacionadas