2009-10-08 24 views
25

Come si crea un plug-in jQuery in modo da poter utilizzare gli spazi dei nomi nel mio plug-in?Spazio dei nomi jQuery Plugin

$("#id1").amtec.foo1(); 
$("#id1").amtec.foo2(); 

Nessuno di questi sembra funzionare.

(function($) { 
    var amtec = { 
     $.fn.foo1 : function(){ return this.each(function(){}); }, 
     $.fn.foo2 : function(){ return this.each(function(){}); } 
     }; 

    })(jQuery); 
(function($) { 
    $.fn.amtec = function(){ 
     var foo1 = function(){ return this.each(function(){}); }; 
     var foo2 = function(){ return this.each(function(){}); }; 
     } 
    })(jQuery); 
+0

vorresti verificare la mia soluzione. è più preciso a ciò che stai cercando di ottenere. –

risposta

21
(function($) { 
    $.fn.amtec = function() { 
     var jq = this; 
     return { 
      foo1: function(){ 
       return jq.each(function(){}); 
      }, 

      foo2: function(){ 
       return jq.each(function(){}); 
      } 
     } 
    }; 
})(jQuery); 
+0

Alexander, console di errore in FireBug mostra: this.each non è una funzione – MotionGrafika

+0

Immagino di aver incasinato le cose - Ho aggiornato la mia risposta. –

+4

Grazie mille Alexandar! Funziona ma come $ ("# id1"). Amtec(). Foo1(); e non come $ ("# id1"). Amtec.foo2(); – MotionGrafika

3
(function($){ 
    $.namespace = function(ns, functions){ 
    $.fn[ns] = function() {return this.extend(functions)}; 
    }; 
    $.namespace('$', $.fn); // the default namespace 
})(jQuery); 

Così ora si può avere un plugin:

$.fn.func = function(){alert('plugin'); return this'}; 

e creare plug-in uno spazio dei nomi:

$.namespace ('mynamespace', { 
    func: function() {alert('namespaced plugin'); return this;}, 
    otherfunc: function() {return this.css('color', 'yellow');} 
}); 

E se lo fai

$('div').func(); // alerts 'plugin' -- no namespace 

Ma

$('div').mynamespace().func(); // alerts 'namespaced plugin' 

E

$('div').mynamespace().func().$().func(); // alerts 'namespaced 

plugin', quindi azzera la jquery normale e avvisi 'plug-in'

+1

Per chiamare otherFunc sarebbe jsut essere $ (div) .mynamespace.otherFunc(); ? – Chris

+1

Stai attento a questo. Risposta intelligente ma si comporta più come [Decorator Pattern] (http://en.wikipedia.org/wiki/Decorator_pattern) che come Namespace. Questo potrebbe metterti nei guai se non hai familiarità con i soliti pro e contro di quel modello. – colllin

2

Lo so che è una vecchia questione ... Ma perché scrivere tutto questo codice aggiuntivo quando puoi semplicemente sostituire . con _?

$.fn.amtec_foo1 = function(){ return this.each(function(){}); } 
$.fn.amtec_foo2 = function(){ return this.each(function(){}); } 

Meglio ancora, dare il plugin un nome che è originale & progetto agnostico.

$.fn.fooize = function(){ return this.html('Element has been Fooized!'); } 
+0

Questo rende lo spazio dei nomi più rigido e non sembra affatto buono. – WhyNotHugo

+0

piacevolmente pragmatico. Grazie! – colllin

12

so che sono quasi tre anni di ritardo alla festa, ma si spera che i futuri lettori di questa domanda può beneficiare la mia risposta. La risposta di GSto ha un bell'aspetto dal punto di vista del design di un plug-in jQuery, ma presenta un piccolo problema: chiamare mynamespace() i clobbers con l'istanza di jQuery restituita con nuovi metodi. Ecco un esempio di che essere un problema:

$myDiv = $('.mydiv'); 
$myDiv.mynamespace().height(); // this will be `height' from mynamespace 
$myDiv.height();    // this will STILL be `height' from mynamespace 
           // because it has overwritten $myDiv.height 

La risposta scelta non ha questo problema perché c'è amtec() non è un'istanza jQuery ed è invece un oggetto che chiama i suoi metodi con l'istanza jQuery come contesto. Ho preso i concetti da entrambe le risposte e scritto il plugin spazio dei nomi di seguito:

(function($) { 
    $.namespace = function(namespaceName, closures) { 

    if ($.fn[namespaceName] === undefined) { 
     $.fn[namespaceName] = function executor(context) { 
     if (this instanceof executor) { 
      this.__context__ = context; 
     } 
     else { 
      return new executor(this); 
     } 
     }; 
    } 

    $.each(closures, function(closureName, closure) { 
     $.fn[namespaceName].prototype[closureName] = function() { 
     return closure.apply(this.__context__, arguments); 
     }; 
    }); 

    }; 
})(jQuery); 

Esempio di utilizzo:

$.namespace('milosz', { 
    redify: function() { 
     $(this).css('color', '#ff0000'); 
    }, 
    greenify: function() { 
     $(this).css('color', '#00ff00'); 
    } 
}); 

$.namespace('milosz', { 
    blueify: function() { 
     $(this).css('color', '#0000ff'); 
    } 
}); 

$('.mydiv').milosz().redify(); // The HTML elements with class `mydiv' are now red 

Il codice utilizza alcune belle dettagli di basso livello di JavaScript che sono ben spiegati da John Resig's Advanced JavaScript tutorial, ma in senso lato ciò che sta accadendo in questo esempio è:

Quando milosz (internamente $.fn[namespaceName]) è chiamato, this punti all'istanza jQuery restituiti b y $('.mydiv').Pertanto, l'istruzione if ricade nel blocco else e viene richiamata la versione del costruttore di milosz (indicata internamente come executor per motivi che stanno per diventare evidenti). Il costruttore riceve un singolo parametro: this, un puntatore allo jQuery l'istanza che sarà il contesto di esecuzione per tutti i membri dello spazio dei nomi milosz. Inseriamo nuovamente l'istruzione if, questa volta eseguendo il primo blocco, in cui l'istanza jQuery passata è memorizzata in una variabile membro denominata __context__ (che si spera abbia una bassa possibilità di essere sovrascritta). Viene restituito l'oggetto costruito, completo con un riferimento all'istanza originale jQuery e qualsiasi wrapper aggiunto al suo prototipo mediante invocazioni di $.namespace. Questi wrapper eseguono semplicemente i metodi passati nello spazio dei nomi milosz con l'oggetto originale jQuery come contesto, come accade quando viene eseguito redify.

Bah, so che è un boccone, comunque il punto è che funziona come la risposta accettata, ma sembra la risposta jQueryish, che per me è il meglio di entrambi i mondi.

+1

Ottimo approccio, grazie da un anno dopo, tre anni dopo la festa. – cmsjr

+1

Userò questa tecnica nella mia nuova libreria di factory plugin jQuery. Mi fa male alla testa, ma funziona! –

+0

So che è passato un po 'di tempo, ma questo metodo non mi permette di chiamare una funzione $ .myNamespace(). Function() - ma funziona come $(). MyNamespace(). Function() - anybody have una soluzione a questo? –

1
$.cg = { 
    foo1: function(weq){ 
     return console.log(weq); 
    }, 
    foo2: function(rw){ 
     return console.log(rw); 
} 
}; 
$.cg = { // will result in error because $.cg is already declared above 

    foo4: function(rw){ // will result in error 
     return console.log(rw); // will result in error 
} // will result in error 
}; // will result in error 

$.cg.foo3 = function(weq){ //to add anything new to $.cg , you have to do it this way. 
     return console.log(weq); 
    } 

$.cg.foo1("12"); 
$.cg.foo2("22"); //works fine. 
$.cg.foo3("112"); //works fine. 
+0

Il problema con questo è che le funzioni non riceveranno il selettore jQuery all'interno del contesto 'this'. –

Problemi correlati