2015-02-22 16 views
8

C'è un modo per concatenare il concatenamento dell'API classList HTML5 ?.concatenamento dell'API classList HTML5 senza (Jquery)

questo non funzionerà

var sidebar = document.querySelector("#sidebar"); 

sidebar.classList.toggle("active").classList.remove("hover") 

mentre questo funzionerà

var sidebar = document.querySelector("#sidebar"); 

sidebar.classList.toggle("active"); 
sidebar.classList.remove("hover") 

NOTA: NO jquery prega

+1

Si potrebbe scrivere la propria funzione che funziona come jQuery. – SLaks

+0

Oppure è possibile evitare del tutto il concatenamento. –

+1

http://jsfiddle.net/7f8ud2s0/ – undefined

risposta

9

È possibile creare chainability tramite un piccolo oggetto con metodi chainable:

function classList(elt) { 
    var list = elt.classList; 

    return { 
     toggle: function(c) { list.toggle(c); return this; }, 
     add: function(c) { list.add (c); return this; }, 
     remove: function(c) { list.remove(c); return this; } 
    }; 

} 

Poi si può catena al contenuto del vostro cuore:

classList(elt).remove('foo').add('bar').toggle('baz') 
2

per il concatenamento di lavorare, un metodo deve restituire l'oggetto che vuoi catena. Poiché i metodi .classList non restituiscono né l'oggetto classList né l'oggetto DOM, non è possibile eseguire in modo nativo il concatenamento.

Si potrebbe, naturalmente, scrivere i propri metodi e farli restituire l'oggetto appropriato e quindi reimplementare la funzionalità in modo concatenabile, ma si dovrebbe metterli su un prototipo di sistema per essere in grado di usali con la stessa facilità.

Senza reimplementare i metodi chainable, si potrebbe ridurre il codice di un po ':

var sidebarList = document.querySelector("#sidebar").classList; 

sidebarList.toggle("active"); 
sidebarList.remove("hover"); 

Se si desidera aggiungere metodi chainable sugli oggetti reali HTML5, si potrebbe fare questo:

(function() { 
    var p = HTMLElement.prototype; 
    p.clAdd = function(cls) { 
     this.classList.add(cls); 
     return this; 
    }; 

    p.clRemove = function(cls) { 
     this.classList.remove(cls); 
     return this; 
    }; 

    p.clToggle = function(cls) { 
     this.classList.toggle(cls); 
     return this; 
    } 
})(); 

// sample use 
document.querySelector("#sidebar").clAdd("active").clRemove("inactive"); 

Demo di lavoro: http://jsfiddle.net/jfriend00/t6w4aj0w/


.210

Oppure, se si desidera un'interfaccia .classList tipo, si potrebbe fare questo:

Object.defineProperty(HTMLElement.prototype, "classListChain", { 
    get: function() { 
     var self = this; 
     return { 
      add: function(cls) { 
       self.classList.add(cls); 
       return self; 
      }, 
      remove: function(cls) { 
       self.classList.remove(cls); 
       return self; 
      }, 
      toggle: function(cls) { 
       self.classList.toggle(cls); 
       return self; 
      } 
     } 
    } 
}); 

// sample use 
document.querySelector("#sidebar").classListChain.add("active").classListChain.remove("inactive"); 

demo di lavoro: http://jsfiddle.net/jfriend00/pxm11vcq/


FYI, perché entrambe queste opzioni catena l'elemento effettivo DOM (a differenza il metodo di torazaburo cui le catene un oggetto personalizzato), è possibile aggiungere un elemento DOM metodo/proprietà alla fine come in:

el.classListChain.add("active").style.visibility = "visible"; 

In alternativa, si può fare qualcosa di simile:

var el = document.querySelector("#sidebar").classListChain.add("active"); 
+0

@Tambo - La tua domanda ha chiesto un "metodo per concatenare l'API classList HTML5", che non è ciò che la risposta che hai accettato effettivamente fa. Rende possibile una funzione globale della propria creazione che non si concatena sull'API classList HTML5. Apparentemente è quello che vuoi ora, ma in tutta onestà non è quello che hai chiesto. Ad ogni modo, ho aggiunto due modi diversi di fare concatenamento, se lo desideri. – jfriend00

0

Se si supportano solo i browser moderni, il concatenamento è uno dei vantaggi rari jQuery detiene ancora contro vaniglia JavaScript, ma questo non si deve interrompere. Come @ jfriend00 suggerito sopra, puoi creare i tuoi metodi add/remove/toggle che possono essere concatenati semplicemente restituendo l'oggetto this.

Eccoli:

Element.prototype.addClassC = Element.prototype.addClassC || function (htmlClass) { 
    this.classList.add(htmlClass); 
    return this; 
} 
Element.prototype.removeClassC = Element.prototype.removeClassC || function (htmlClass) { 
    this.classList.remove(htmlClass); 
    return this; 
} 
Element.prototype.toggleClassC = Element.prototype.toggleClassC || function (htmlClass) { 
    this.classList.toggle(htmlClass); 
    return this; 
} 

Nel tuo caso si sarebbe poi applicarle in questo modo:

sidebar.toggleClassC('active').removeClassC('hover'); 

Una nota sulla denominazione.Vorrei suggerire contro semplicemente usando addClass e removeClass perché quelli potrebbero entrare in conflitto con i metodi di jQuery, o qualcuno che legge il codice li scambia per i metodi di jQuery. Qui ho aggiunto una C che sta per Chaining, ma puoi chiamarla qualcosa di più significativo per te.

Modifica: Ho aggiunto un controllo per verificare che i nostri metodi non fossero già stati definiti in precedenza per evitare di ignorare. Ho anche cambiato il nome della variabile di classe da cssClass a htmlClass perché è più corretto (html ha classi, css ha selettori).

+0

Solo curioso perché hai deciso di nominare i parametri "classi". È un nome di una singola classe, giusto? (Anche se alcuni browser supportano apparentemente variadicità.) –

+0

Il codice potrebbe essere stato refactored per supportare effettivamente più classi tramite un 'array', ma poi hai ragione, il supporto del browser per più classi non è al 100% ([IE è il solito colpevole] (http://caniuse.com/#feat=classlist)), quindi ho corretto il codice per evitare confusione. Le funzioni possono essere concatenate, comunque. Grazie per averlo notato –