2016-05-31 35 views
5

Ho una serie di elementi personalizzati che iniziano con "food-cta-". Sto cercando un modo in JavaScript/jQuery per essere in grado di selezionare questi elementi. Questo è simile a come posso usare $('*[class^="food-cta-"]') per selezionare tutte le classi che iniziano con food-cta-. È possibile fare una ricerca di elementi che iniziano con 'food-cta-'?Trova elementi personalizzati che iniziano con un prefisso specificato

Nota che inserirò questa ricerca nella pagina, quindi non avrò accesso ad Angular.

Esempio di elementi personalizzati:

  • <food-cta-download>
  • <food-cta-external>
  • <food-cta-internal>

EDIT: Il codice che sto guardando assomiglia:

<food-cta-download type="primary" description="Download Recipe"> 
    <img src=""> 
    <h2></h2> 
    <p></p> 
</food-cta-download> 

L'app utilizza AngularJS per creare elementi personalizzati che, a mio avviso, si chiamano Direttive.

+2

@EvanCarroll, [sono elementi personalizzati] (https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements), che è uno standard più recente per HTML. – zzzzBov

+1

@EvanCarroll, oppure è un [elemento html personalizzato] (https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements) che erediterà da [HTMLElement] (https: //developer.mozilla .org/it-it/docs/Web/API/HTMLElement) o [HTMLUnknownElement] (https://developer.mozilla.org/en-US/docs/Web/API/HTMLUnknownElement) se non registrato –

+1

È possibile aggiungere la funzione di collegamento di ogni direttiva 'element.addClass ('food-cta')' e quindi tutti gli elementi con quella direttiva avranno la stessa classe, ma AFAIK non puoi selezionare l'elemento in questo modo come fai con la classe - Hai per elencare gli elementi 'food-cta-download, food-cta-external, food-cta-internal {background: red;}' –

risposta

0

Probabilmente avete andare solo agli elementi in questione e verificare se il loro tagName inizia con quella stringa data ...

var myPrefix = "mycustom-thing-"; 

$("body").children().each(function() { 
    if (this.tagName.substr(0, myPrefix.length).toLowerCase() == myPrefix) { 
    console.log(this.innerHTML); // or what ever 
    } 
}) 

https://jsfiddle.net/svArtist/duLo2d0z/

EDIT: Incluso per l'amor di efficienza:

Se è possibile prevedere dove saranno gli elementi, è possibile naturalmente specificare tale circostanza. Nel mio esempio, gli elementi in questione erano figli diretti di body, quindi è possibile utilizzare .children() per ottenerli. Questo non avrebbe attraversato i livelli più bassi.

Ridurre la necessità di attraversamento dal seguente:

Start sul più basso livello necessario ($("#specific-id") piuttosto che $("body"))

Se gli elementi sono tutti da trovare come figli diretti di un contenitore:

  • Usa $.children() sul contenitore per ottenere solo i bambini immediati

Else

  • Usa $.find("*")

Se si può dire qualcosa a proposito del contesto contenente, filtro che

Per esempio $("#specific-id").find(".certain-container-class .child-class *")

+0

Questa sembra una chiamata molto costosa in quanto dovrà attraversare praticamente l'intero DOM. – Jon

+0

Quindi devi usare '.find()' invece? ... Beh, in un certo senso, jQ dovrebbe farlo comunque se fosse un controllo per una classe o qualcos'altro supportato in modo nativo. Ma sì, lo capisco e ovviamente vorrei anche che fosse supportato –

+0

Oh! Non mi rendevo conto che '$ .find()' attraversa anche l'intero DOM. Lol. Ho pensato che fosse qualcosa di subdolo per l'algoritmo che risparmia le prestazioni. – Jon

0

Prova questo ..

let customElements = $('*') 
    .filter((index,element) => /FOOD-CTI-/.test(element.tagName)); 

nota, .tagName dovrebbe restituire il risultato in maiuscolo. Questo dovrebbe darti un oggetto jQuery degli elementi che desideri. Comunque attraverserà l'intero DOM. Sarà lento.

Utilizza lo "all selector".

Attenzione: il selettore all, o universal, è estremamente lento, tranne se utilizzato da solo.

È possibile attraversare anche meno dom intera, specificando qualcosa come $("body *"). Non sei sicuro di dove hai inserito gli elementi personalizzati e dove sono consentiti.

Come parte, non userei Elementi personalizzati, i microformati sono un'idea migliore almeno ora, sono anche meglio supportati e hanno meno probabilità di cambiare.

1

È possibile utilizzare XPath con l'espressione

//*[starts-with(name(),'food-cta-')] 

Dove

  • //* è jolly per tutti i nodi
  • starts-with() è una funzione XPath per testare una stringa inizia con un certo valore
  • name() ottiene il QName (nome nodo)
  • e 'food-cta-' è il termine di ricerca

Passo in document.evaluate e si otterrà un XPathResult che vi darà i nodi che sono stati abbinati.

var result = document.evaluate("//*[starts-with(name(),'food-cta-')]", document, null, XPathResult.ANY_TYPE, null); 

Nota è possibile utilizzare qualsiasi nodo come la radice, non è necessario utilizzare document. Così si potrebbe, per esempio sostituire document con il qualche div:

var container = document.getElementById("#container"); 
var result = document.evaluate("//*[starts-with(name(),'food-cta-')]", container, null, XPathResult.ANY_TYPE, null); 

Demo

let result = document.evaluate("//*[starts-with(name(),'food-cta-')]", document, null, XPathResult.ANY_TYPE, null); 
 

 
let nodes = []; 
 
let anode = null; 
 

 
while((anode = result.iterateNext())){ 
 
    nodes.push(anode.nodeName); 
 
} 
 

 
console.log(nodes);
<div id="container"> 
 
    <br> 
 
    <food-cta-download type="primary" description="Download Recipe"> 
 
    <img src=""> 
 
    <h2></h2> 
 
    <p></p> 
 
    </food-cta-download> 
 
    <span>Some span</span> 
 
    <food-cta-something> 
 
    <img src=""> 
 
    <h2></h2> 
 
    <p></p> 
 
    </food-cta-something> 
 
    <div>In between 
 
     <food-cta-sub> 
 
     <img src=""> 
 
     <h2></h2> 
 
     <p></p> 
 
     </food-cta-sub> 
 
    </div> 
 
    <food-cta-hello> 
 
    <img src=""> 
 
    </food-cta-hello> 
 
    <food-cta-whattt> 
 
    </food-cta-whattt> 
 
</div>

+0

È intelligente e mi piace, ma la domanda ha richiesto specificamente JavaScript/jQuery. –

+1

@EvanCarroll, che è javascript, quindi perché è possibile eseguirlo nello snippet –

0

Perché non extend jquery selectors?

$(':tag(^=food-cta-)') 

sarebbe possibile con la seguente implementazione:

$.expr[':'].tag = function tag(element, index, match) { 
 
    // prepare dummy attribute 
 
    // avoid string processing when possible by using element.localName 
 
    // instead of element.tagName.toLowerCase() 
 
    tag.$.attr('data-tag', element.localName || element.tagName.toLowerCase()); 
 
    // in :tag(`pattern`), match[3] = `pattern` 
 
    var pattern = tag.re.exec(match[3]); 
 
    // [data-tag`m`="`pattern`"] 
 
    var selector = '[data-tag' + (pattern[1] || '') + '="' + pattern[2] + '"]'; 
 
    // test if custom tag selector matches element 
 
    // using dummy attribute polyfill 
 
    return tag.$.is(selector); 
 
}; 
 

 
// dummy element to run attribute selectors on 
 
$.expr[':'].tag.$ = $('<div/>'); 
 
// cache RegExp for parsing ":tag(m=pattern)" 
 
$.expr[':'].tag.re = /^(?:([~\|\^\$\*])?=)?(.*)$/; 
 

 
// some tests 
 
console.log('^=food-cta-', $(':tag(^=food-cta-)').toArray()); 
 
console.log('*=cta-s', $(':tag(*=cta-s)').toArray()); 
 
console.log('food-cta-hello', $(':tag(food-cta-hello)').toArray());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="container"> 
 
    <br> 
 
    <food-cta-download type="primary" description="Download Recipe"> 
 
    <img src=""> 
 
    <h2></h2> 
 
    <p></p> 
 
    </food-cta-download> 
 
    <span>Some span</span> 
 
    <food-cta-something> 
 
    <img src=""> 
 
    <h2></h2> 
 
    <p></p> 
 
    </food-cta-something> 
 
    <div>In between 
 
    <food-cta-sub> 
 
     <img src=""> 
 
     <h2></h2> 
 
     <p></p> 
 
    </food-cta-sub> 
 
    </div> 
 
    <food-cta-hello> 
 
    <img src=""> 
 
    </food-cta-hello> 
 
    <food-cta-whattt> 
 
    </food-cta-whattt> 
 
</div>

Questo supporta una pseudo-CSS-style attribute selector con la sintassi:

:tag(m=pattern) 

O semplicemente

:tag(pattern) 

dove m è ~,|,^,$,* e pattern è il vostro selettore di tag.