2013-07-17 9 views
6

Basti dire che voglio ramificare un po 'il mio plugin scrivendo un po' e ho deciso di voler "namespace". Finora, riscrivere le $.method a $.namespace.method è stato facile.Come creare jQuery Element Methods con NameSpace

Il problema che sto riscontrando è l'elaborazione di Method Methods come $('element').method(), ma per utilizzare uno spazio dei nomi; ad esempio $('element').namespace.method(). Ho provato un po 'di soluzioni alternative e posso creare $.fn.namespace.method, tuttavia, quando chiamo this da questo metodo, ottengo solo $.fn.namespace e non lo 'element' che mi piacerebbe avere.

Esempio: se chiamo $('body').namespace.test(), poi dentro il metodo test, voglio this essere l'elemento <body></body>

Qualsiasi aiuto per capire come tirare fuori questo molto apprezzato. Probabilmente solo le cose eccessive come al solito.

attualmente cercando possibili modi di aggirare per qualcosa come $('body').namespace().method(), finora, non funziona così bene ...: P

+0

+1 - Non penso che sia possibile in JavaScript. Dovresti solo aggiungere un prefisso ai nomi dei metodi (ad es. 'NamespaceTest'). Se il vero namespacing è così importante per te, allora temo che non puoi usare il prototipo di jQuery. –

+0

Forse manca il punto, ma stai cercando '$ .fn.myMethod (/ * function code * /);' che poi chiamerai '$ (" div "). MyMethod()'? – Archer

+1

@JosephSilber È JavaScript! Sono sicuro che c'è un modo! LoL, dopo tutto, questa è la lingua "più libera" là fuori! – SpYk3HH

risposta

3

Se non c'è bisogno di essere compatibile con IE8, è possibile utilizzare Object.defineProperty.

esempio di lavoro:

Object.defineProperty($.fn, 'namespace', { 
    get: function(){ 
    var t = this; 
    return { 
     lowercasehtml: function(){ 
     return t.html(function(_,h){ return h.toLowerCase() }); 
     } 
    } 
    } 
}); 

$('#a').namespace.lowercasehtml(); // changes the html of #a to lowercase (yes, it's stupid, I know) 

Demonstration

Ma io non sono convinto che sia una buona idea in spazi dei nomi in questo modo. Avrei semplicemente definito

$.fn.namespace_lowercasehtml = function() ... 

Questo è quello che personalmente faccio per la mia applicazione estensioni specifiche per jQuery.

+0

bel suggerimento, ci proverò subito dopo pranzo, qualsiasi pensiero su IE8 funziona in giro? – SpYk3HH

+0

Ad essere sincero penso che il mio secondo suggerimento, anche se non di fantasia, sia il migliore. –

2

Mentre io non lo consiglio, è possibile generare un nuovo oggetto per ogni chiamata a namespace():

(function($){ 

    var plugin = { 
     test: function(){ 
      console.log(this); 
     } 
    }; 

    var methods = Object.keys(plugin); 

    $.fn.namespace = function(){ 

     var self = this, 
      localMethods = {}; 

     $.each(methods, function() { 
      localMethods[ this ] = plugin[ this ].bind(self); 
     }); 

     return localMethods; 
    }; 

}(jQuery)); 

Ecco il violino: http://jsfiddle.net/WaXzL/


È possibile polyfill Object.keys for older browsers, o semplicemente creare manualmente l'array methods.

Lo stesso vale per bind: o lo riempie automaticamente, oppure call manualmente.

Ecco una versione che avrebbe funzionato in vecchi browser:

(function($){ 

    var plugin = { 
     test: function(){ 
      console.log(this); 
     } 
    }; 

    var methods = []; 

    for (var i in plugin) { 
     if (plugin.hasOwnProperty(i)) { 
      methods.push(i); 
     } 
    } 

    $.fn.namespace = function(){ 

     var self = this, 
      localMethods = {}; 

     $.each(methods, function (i, method) { 
      localMethods[ method ] = function() { 
       plugin[ method ].call(self); 
      }; 
     }); 

     return localMethods; 
    }; 

}(jQuery)); 

Ed ecco il violino: http://jsfiddle.net/WaXzL/1/

+0

Grazie per il tuo suggerimento. Ho aggiunto il supporto per passare argomenti a qualsiasi metodo locale: http://jsfiddle.net/WaXzL/2/ –

2

ne dite invece di fare:

$('element').namespace.method() 

a semplificare e fare

$('element').namespace('method') 

?Questo è molto più semplice:

(function($){ 
    var methods = { 
     test: function(a, b){ 
      console.log(this, a, b); 
     } 
    }; 

    $.fn.namespace = function(method){ 
     var params = Array.prototype.slice.call(arguments, 1); 
     return methods[method].apply(this, params); 
    }; 
}(jQuery)); 

allora si sarebbe fare qualcosa di simile: $('body').namespace('test', 1, 2);

+0

perché il mio intellisense nel mio IDE leggerà '$ ('ele'). Namespace.method()' ma ha vinto ' t leggere un nome di metodo passato come stringa param – SpYk3HH

+3

@ SpYk3HH: stavo cercando di mantenerlo semplice. Non uso un IDE "di fantasia". –

2

Una soluzione migliore è quella di avere solo un metodo principale, e passare il nome del metodo come una stringa:

(function($){ 

    var plugin = { 
     test: function(){ 
      console.log(this); 
     }, 
     otherTest: function(){ 
      console.log(this); 
     } 
    }; 

    $.fn.namespace = function (method){ 
     var args = Array.prototype.slice.call(arguments, 1); 
     return plugin[ method ].call(this, args); 
    }; 

}(jQuery)); 

Ecco il violino: http://jsfiddle.net/yYNDH/

+0

Non è già un'altra risposta (di Rocket)? –

+1

@dystroy - Sì. Ero passato a JSFiddle per creare il violino prima di pubblicare, e quando sono tornato, non mi rendevo conto che l'aveva già pubblicato. –