2011-10-13 10 views
7

sto cercando di spessorare Element.prototype.children che dovrebbe restituire un HTMLCollectioncreare un HTMLCollection

C'è un window.HTMLCollection

Tuttavia

var h = new HTMLCollection(); 
//TypeErrror: HTMLCollection is not a constructor 

e

var h = Object.create(HTMLCollection.prototype); 
h[0] = div; 
h.item(0); 
// Could not convert JavaScript argument 

test Firefox 7 e Chrome

Oltre allo shimming HTMLCollection c'è un modo per interagire con esso?

anche fornire feedback su this github issue se si può suggerire una soluzione

+0

Credo che il modo corretto per farlo sia definire il proprio costruttore personalizzato 'MyHTMLCollection' e quindi usarlo al posto del costruttore host' HTMLCollection' (che non è affidabile) –

+0

Mentre non posso rispondere alla tua domanda specifica su HTMLCollection, è generalmente considerato una cattiva pratica estendere gli oggetti DOM (hosted) nativi. Vedi questo articolo per una spiegazione dettagliata del perché: http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – skyline3000

+0

@ skyline3000 Sono perfettamente consapevole delle conseguenze. Dobbiamo fare questo per generare un DOM-shim. Non stiamo estendendo il DOM con metodi personalizzati (malvagi) ma con metodi che dovrebbero esistere secondo la specifica DOM4 – Raynos

risposta

4

Ecco come lo farei:

function MyHTMLCollection(arr) { 
    for (var i = 0; i < arr.length; i += 1) { 
     this[i] = arr[i]; 
    } 

    // length is readonly 
    Object.defineProperty(this, 'length', { 
     get: function() { 
      return arr.length; 
     } 
    }); 

    // a HTMLCollection is immutable 
    Object.freeze(this); 
} 

MyHTMLCollection.prototype = { 
    item: function (i) { 
     return this[i] != null ? this[i] : null; 
    }, 
    namedItem: function (name) { 
     for (var i = 0; i < this.length; i += 1) { 
      if (this[i].id === name || this[i].name === name) { 
       return this[i]; 
      } 
     } 
     return null; 
    } 
}; 

dove arr è una serie regolare che contiene tutti gli elementi DOM che dovrebbero essere all'interno del HTMLCollection.

per fare la lista:

  • l'argomento arr dovrebbe essere controllato in anticipo: è un array? Tutti gli elementi degli elementi DOM dell'array sono tutti?
+0

Che dire di 'instance [4] = newEl'. 'length' fallirebbe. Penso che sia necessario calcolare la lunghezza ad ogni richiamo affinché funzioni. – Raynos

+0

@Raynos Ho appena aggiornato la mia risposta. 'Object.freeze (this)' all'interno del costruttore, ma non sono sicuro di ciò che dice la specifica sull'immutabilità delle raccolte HTML. Controllerò ... –

+0

anche 'Object.defineProperty' funziona solo sul DOM in IE8, quindi il mio dom-shim è appena terminato in IE8. Immagino di poter rendere la proprietà 'length' un valore statico in IE8 e semplicemente dimenticarla. – Raynos

4

Non aspettatevi oggetti host a comportarsi come (ECMAScript) oggetti nativi, sono cose completamente diverse. Alcuni browser implementano i loro oggetti DOM come gli oggetti ECMAScript, ma non è richiesto e non dovrebbe essere invocato. Nota che la maggior parte delle raccolte HTML sono attive, è molto difficile emularle in un oggetto nativo.

+1

Sono davvero incredibilmente difficili da emulare senza un Proxy. – Raynos

0

So che questa è una domanda più vecchio, ma mi sono imbattuto in una simile esigenza di creare un HTMLCollection vuoto e l'ho fatto semplicemente creando un elemento e poi correre getElementsByClassName() contro di esso con una classe che non esiste nell'elemento

document.createElement("div").getElementsByClassName('noClassHere'); 

Restituisce un oggetto HTMLCollection vuoto.