2010-01-29 14 views
8

He creado un plugin jQuery que funciona muy bien, con la excepción de poder llamar al plugin en diferentes objetos y cada objeto conservando las opciones que se le dieron. El problema es que si llamo el plug-in en un objeto, por ejemplo:jQuery Plugin Authoring - Establecer diferentes opciones para diferentes elementos

$('#myDiv1').myPlugin({ 
    option1: 'some text', 
    option2: true, 
    option3: 'another option value' 
}); 

luego llamar al plug-in de nuevo en otro objeto, por ejemplo:

Entonces, si vuelvo y trato de hacer algo con # myDiv1 que las necesidades de sus opciones originales que aún estaba intacta, es decir:

$('#myDiv1').myPlugin.update(); 

no tendrá sus opciones originales, sino que será anulado por las opciones de # myDiv2. ¿Cuál es la forma correcta de hacer esto para que cada objeto retenga las opciones originales que se le asignaron? (Y esto es un código de ejemplo de lo que estoy haciendo en el plug-in)

(function($) { 
$.fn.myPlugin = function(options) { 

    // build main options before element iteration 
    var opts = $.extend({}, $.fn.myPlugin.defaults, options); 

    _option1 = opts.option1; 
    _option2 = opts.option2; 
    _option3 = opts.option3; 

    // iterate all matched elements 
    return this.each(function() { 
     callPluginFunctions(this, opts); 
    }); 

}; 

    ....code continued.... 

Comprendo que esto es algún tipo de corrupción del alcance o algo así. Entonces, ¿cómo puedo obtener mis opciones para permanecer adjunto y permanecer en el alcance del objeto original (es decir, # myDiv1) que se les dio.

EDIT: Al hacer algunas investigaciones veo que puede almacenar datos en un objeto usando la función .data de jQuery, y los documentos dicen que jQuery UI lo usa extensamente. ¿Sería lo correcto hacer aquí almacenar las opciones en el objeto utilizando .data, luego, cuando se hace referencia más tarde utilizar las opciones almacenadas en .data ???

+0

En respuesta a su edición y la respuesta correcta de reinerpost, sí, el objeto de datos es una buena forma de hacerlo. Sin embargo, consulte usando la fábrica de jQuery UI (http://jqueryui.com/docs/Developer_Guide#The_widget_factory).Lo utilicé para crear el código de la presentación de diapositivas para http://2010.newsweek.com (ver: jquery.slideshow.js) –

Respuesta

16

En primer lugar, generalmente querrá manejar el comando dentro de su método de extensión. En segundo lugar, se debe a conectar configuraciones para cada elemento ...

(function($){ 
var defaultOptions = { /* default settings here */ }; 

//called on the native object directly, wrap with $(obj) if needed. 
function initializeObject(obj, options) { 
    //assign the options to the object instance. 
    $(obj).data('myPlugin-options', $.extend(defaultOptions, options)); 
    //do other initialization tasks on the individual item here... 
} 

function updateObject(obj) { 
    // use $(obj).data('myPlugin-options'); 
} 

function setOption(obj, key, value) { 
    var d = $(obj).data('myPlugin-options'); 
    d[key] = value; 
    $(obj).data('myPlugin-options', d); 
} 

$.fn.myPlugin = function(command, option, val) { 
    if (typeof command == "object") { 
    //initialization 
    return this.each(function(){ 
     initializeObject(this, command); 
    }); 
    } 
    if (typeof command == "string") { 
    // method or argument query 
    switch (command.toLowerCase()) { 
     case 'option': 
     //get value, return the first item's value 
     if (typeof val == undefined) return this.eq(0).data('myPlugin-options')[option]; 
     //set option value 
     return this.each(function() { 
      setOption(this, option, val); 
     }); 

     case 'update': 
     return this.each(function() { 
      updateObject(this); 
     }); 
     //other commands here. 
    } 
    } 
} 
})(jQuery) 

Con el ejemplo anterior, tiene una plantilla genérica para una extensión de jQuery, es una buena costumbre el tener la siguiente convención para su uso ..

Initialization: 
    $(...).myPlugin({ initialization-options-here }); 
Command: 
    $(...).myPlugin('command-name'); //where command can be update, etc. 
Get Option: 
    var myValue = $(...).myPlugin('option', 'option-name'); 
Set Option: 
    $(...).myPlugin('option', 'option-name', newValue); 

Se actualizó para usar .data de cada obj individual.

+0

Impresionante, gracias. Me faltaba la parte 'adjuntar configuraciones a cada objeto'. Terminé usando $ .data para adjuntar la configuración en lugar de su sugerencia. ¿Hay algún pros/contra para cualquiera de los métodos? Me imagino que probablemente sean más o menos lo mismo. Además, me gusta mucho su configuración de complementos, muy similar a jQuery UI. También lo he adoptado =) ¡Gracias! – Ryan

+0

No utilizaría .data para cada objeto, ya que el complemento podría usar la delegación de eventos ... también, si se llama al complemento sin ningún argumento, ¿entonces qué? en el ejemplo, no pasaría nada ... – vsync

+0

@vsync Era principalmente una guía ... podía verificar si los valores predeterminados y la inicialización de objetos estaban predeterminados. También creo que la aplicación de datos debería aplicarse a cada elemento, ya que cada elemento conectado podría ajustarse para tener diferentes opciones más adelante. Sé que no es perfecto ... solo trato de señalar el patrón general que parece usarse en la interfaz de usuario y otras extensiones de jQuery. – Tracker1

-1

Sus opciones son para todo el plugin. Muévelos dentro de cada(). (¿Por qué hace esta pregunta? Deletrea la solución usted mismo.)

+0

que pregunto porque obviamente no conozco la solución. He movido todo lo que vino antes de esta función cada uno a la función this.each (función() y aún estoy obteniendo los mismos resultados. ¿Podría aclarar qué quiere decir? – Ryan

+0

Ahora estoy realmente perplejo. Lo que quiero decir es que desea que el _option1, etc. sea separado para cada elemento coincidente, por lo que debe copiarlos, por ejemplo, como lo hace Pickle. No nos ha mostrado cómo accede a las opciones más adelante, quizás haya otro problema allí. – reinierpost

+0

Sí, ese era todo mi problema ... acceder a las opciones más tarde. No estaba adjuntando la configuración al objeto en sí. Agregué un $ (esto) .data ('opts', opts); en el ciclo each(), y ahora todo funciona como un amuleto. Gracias de todos modos. – Ryan

0

He estado teniendo el mismo problema, pero solo las funciones aprobadas se sobrescribieron. Las propiedades directas persistían.

De todos modos, para explicar mejor qué ~ reinierpost significaba, cambiar su código a esto debería funcionar. Tendrás que pasar 'opts' a todas partes, pero creo que es necesario sacar las opciones del espacio de nombre de todo el complemento.

$.fn.myPlugin = function(options) { 

    // iterate all matched elements 
    return this.each(function() { 
     // build main options before element iteration 
     var opts = $.extend({}, $.fn.myPlugin.defaults, options); 
     callPluginFunctions(this, opts); 
    }); 
}; 

Editar: Aquí está el código de mi plugin de

this.each(function() { 
    var thisConfig = config; 
    thisConfig = $.extend(thisConfig,settings); 
    $.attach($(this),thisConfig); 
}); 

... 

$.attach = function($target,config){ 

Así que no tengo en todo el plug-in "config" - justo dentro de cada función.

+0

Oye, lo intenté después de la publicación de Reinierpost, pero sigo teniendo el mismo problema. El problema no es que no pueda llamar a los diferentes con diferentes opciones, sino después de ' inicializó el complemento en un objeto, luego inicializó un con diferentes opciones, cuando regreso y llamo a cualquier función de complemento en el primer elemento, usa la configuración que se le dio al segundo elemento, y no al primero. Espero que haya sido claro, avíseme si no. – Ryan

+0

He actualizado mi entrada inicial para mostrar cómo utilicé esta técnica en mi complemento. ¿Tal vez te estás refiriendo a un objeto de configuración de todo el complemento en lugar del que se inicializó en tu ciclo this this every()? – Pickle

+0

Sí, estaba adjuntando las opciones al objeto que me faltaba. Veo que usaste $ .attached, terminé usando $ .data ($ (this) .data ('opts', opts);). ¿Hay alguna diferencia real entre los dos? Gracias – Ryan

Cuestiones relacionadas