2012-11-27 9 views
6

Questo è un po 'noob-domanda per qualcuno che ha avuto un paio di anni di esperienza di sviluppo web, ma dopo non trovando la risposta su entrambi i programmatore Pila Cambio o Google, ho deciso di chiedere qui.Come separare javascript in linea da contenuti generati dinamicamente in Express/Node.js?

Sto usando espresso quadro web per Node.js, ma questa domanda non è specifico per ogni framework web o di linguaggio di programmazione.

Ecco un elenco di giochi che vengono interrogati dal database. Ogni entità gioco è una singola riga della tabella, generato utilizzando un ciclo for:

table.table 
     tbody 
     for game in games 
      tr 
      td.span2 
       img.img-polaroid(src='/img/games/#{game.largeImage}') 
       // continues further 

enter image description here

Ogni Valutazione blocco, così come ogni finestra Acquisto tasto/modal sono generati da il ciclo for con un ID che corrisponde al gioco. Ad esempio, il pulsante Acquista per Assassin's Creed avrà id = "price-assassins-creed". # {variable} - è il modo in cui si fa riferimento a una variabile in Jade, passata dal server.

button.btn.btn-primary.btn-mini(id='price-#{game.slug}', href='#buyModal', role='button', data-toggle='modal') 

e

.modal.hide.fade(id='modal-#{game.slug}', tabindex='-1', role='dialog', aria-labelledby='myModalLabel', aria-hidden='true') 
      .modal-header 
       span.lead Game Checkout 
       img.pull-right(src='/img/new_visa_medium.gif') 
      .modal-body 
       label 
       i.icon-user 
       | Name on Card 
       input.input-medium(type='text') 
       label 
       i.icon-barcode 
       | Card Number 
       input.input-medium(type='text', placeholder='•••• •••• •••• ••••', maxlength=16) 

       label 
       i.icon-time 
       | Expiration Date 
       input.input-mini(type='text', placeholder='MMYY', maxlength=4) 
       label 
       i.icon-qrcode 
       | Card Code 
       input.input-mini(type='text', placeholder='CVC', maxlength=4) 
      .modal-footer 
       button.btn(data-dismiss='modal', aria-hidden='true') Cancel 
       button.btn.btn-primary(id='#{game.slug}') Buy 

e

script(type='text/javascript') 
    $('#_#{game.slug}').raty({ 
    path: '/img', 
    round : { down: .25, full: .6, up: .76 }, 
    score: #{game.rating}/#{game.votes}, 
    readOnly: true 
    }); 

moltiplicare per il numero di giochi e questo è il numero di script in linea che ho su una sola pagina.

ancora peggio, devo rendere conto dei seguenti casi:

  • utente non è loggato: display sopra scritto rating in modalità di sola lettura.
  • utente connesso in, ma non ha ancora votato:

... in questo caso, utilizzare il seguente script:

script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: false, 
         click: function (score, event) { 
         var self = this; 
         $.meow({ 
          message: 'Thanks for voting. Your rating has been recorded.', 
          icon: 'http://png-3.findicons.com/files/icons/1577/danish_royalty_free/32/smiley.png' 
         }); 
         $.ajax({ 
          type: 'POST', 
          url: '/games/rating', 
          data: { 
          slug: $(self).attr('id').slice(1), 
          rating: score 
          }, 
          success: function() { 
          console.log('setting to read-only'); 
          $(self).raty('readOnly', true); 
          } 
         }); 
         } 
        }); 
  • utente autenticato ma sospeso dalla classificazione: copia e incolla ancora un altro script di sola lettura per questa particolare condizione if-else.

Per farla breve, è diventato un incubo di manutenzione cercando di mantenere tutto questo JavaScript nei miei .jade file di modello, e il mio margine di profitto sembra inaccettabilmente sporco.

Qual è una soluzione per questo? Questo sembra uno scenario così comune per le applicazioni CRUD. Idealmente, mi piacerebbe spostare tutto il javascript in un separato .js file. Ma se potessi rimuovere del codice duplicato, sarebbe fantastico.

Il problema è se si sposta in linea javascript in un file separato come faccio a sapere qual è il gioco? Come faccio a sapere su quale pulsante Acquista è stato fatto clic su utente?

In questo momento non c'è ambiguità perché per N giochi che ho N comprare pulsanti, N finestre di dialogo modali e N script di rating. Indipendentemente da ciò che qualcuno pensa di questo stile di programmazione, è un modo terribile per mantenere il codice.

Si prega di condividere qualche intuizione con un noobie!

Grazie in anticipo.

Ecco un frammento di codice completo del mio file games.jade:

extends layout 

block content 
    br 
    ul.nav.nav-pills 
    if heading === 'Top 25' 
     li.active 
     a(href='/games') Top 25 
    else 
     li 
     a(href='/games') Top 25 

    if heading === 'Action' 
     li.active 
     a(href='/games/genre/action') Action 
    else 
     li 
     a(href='/games/genre/action') Action 

    if heading === 'Adventure' 
     li.active 
     a(href='/games/genre/adventure') Adventure 
    else 
     li 
     a(href='/games/genre/adventure') Adventure 

    if heading === 'Driving' 
     li.active 
     a(href='/games/genre/driving') Driving 
    else 
     li 
     a(href='/games/genre/driving') Driving 

    if heading === 'Puzzle' 
     li.active 
     a(href='/games/genre/puzzle') Puzzle 
    else 
     li 
     a(href='/games/genre/puzzle') Puzzle 

    if heading === 'Role-Playing' 
     li.active 
     a(href='/games/genre/role-playing') Role-Playing 
    else 
     li 
     a(href='/games/genre/role-playing') Role-Playing 

    if heading === 'Simulation' 
     li.active 
     a(href='/games/genre/simulation') Simulation 
    else 
     li 
     a(href='/games/genre/simulation') Simulation 

    if heading === 'Strategy' 
     li.active 
     a(href='/games/genre/strategy') Strategy 
    else 
     li 
     a(href='/games/genre/strategy') Strategy 

    if heading === 'Sports' 
     li.active 
     a(href='/games/genre/sports') Sports 
    else 
     li 
     a(href='/games/genre/sports') Sports 


    if games.length == 0 
    .alert.alert-warning 
     | Database query returned no results. 
    else 
    table.table 
     tbody 
     for game in games 
      .modal.hide.fade(id='modal-#{game.slug}', tabindex='-1', role='dialog', aria-labelledby='myModalLabel', aria-hidden='true') 
      .modal-header 
       span.lead Game Checkout 
       img.pull-right(src='/img/new_visa_medium.gif') 
      .modal-body 
       label 
       i.icon-user 
       | Name on Card 
       input.input-medium(type='text') 
       label 
       i.icon-barcode 
       | Card Number 
       input.input-medium(type='text', placeholder='•••• •••• •••• ••••', maxlength=16) 

       label 
       i.icon-time 
       | Expiration Date 
       input.input-mini(type='text', placeholder='MMYY', maxlength=4) 
       label 
       i.icon-qrcode 
       | Card Code 
       input.input-mini(type='text', placeholder='CVC', maxlength=4) 
      .modal-footer 
       button.btn(data-dismiss='modal', aria-hidden='true') Cancel 
       button.btn.btn-primary(id='#{game.slug}') Buy 
      tr 
      td.span2 
       img.img-polaroid(src='/img/games/#{game.largeImage}') 
      td 
       a(href='/games/#{game.slug}') 
       strong 
        = game.title 
       |   

       if user.userName 
       button.btn.btn-primary.btn-mini(id='price-#{game.slug}', href='#modal-#{game.slug}', role='button', data-toggle='modal') 
        i.icon-shopping-cart.icon-white 
        = game.price 
       if user.purchasedGames && user.purchasedGames.length > 0 
        for mygame in user.purchasedGames 
        if mygame.game.slug == game.slug 
         script(type='text/javascript') 
         $('#price-#{game.slug}').removeAttr('href'); 
         $('#price-#{game.slug}').html('<i class="icon-shopping-cart icon-white"></i> Purchased'); 

       div 
       span(id='_' + game.slug) 
       span(id='votes', name='votes') 
       | (#{game.votes} votes) 
       div 
       small.muted 
        div #{game.releaseDate} | #{game.publisher} 
        div #{game.genre} 
       p 
       =game.description 

      // logged-in users 
      if user.userName 
      if game.votedPeople.length > 0 
       for voter in game.votedPeople 
       if voter == user.userName || user.suspendedRating 
        script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: true 
        }); 
       else 
        script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: false, 
         click: function (score, event) { 
         var self = this; 
         $.meow({ 
          message: 'Thanks for voting. Your rating has been recorded.', 
          icon: 'http://png-3.findicons.com/files/icons/1577/danish_royalty_free/32/smiley.png' 
         }); 
         $.ajax({ 
          type: 'POST', 
          url: '/games/rating', 
          data: { 
          slug: $(self).attr('id').slice(1), 
          rating: score 
          }, 
          success: function() { 
          console.log('setting to read-only'); 
          $(self).raty('readOnly', true); 
          } 
         }); 
         } 
        }); 
      else 
       if (user.suspendedRating) 
       script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
        path: '/img', 
        round : { down: .25, full: .6, up: .76 }, 
        score: #{game.rating}/#{game.votes}, 
        readOnly: true 
        }); 
       else 
       script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img/', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: false, 
         click: function (score, event) { 
          var self = this; 
          $.meow({ 
          message: 'Thanks for voting. Your rating has been recorded.', 
          icon: 'http://png-3.findicons.com/files/icons/1577/danish_royalty_free/32/smiley.png' 
          }); 
          $.ajax({ 
          type: 'POST', 
          url: '/games/rating', 
          data: { 
           slug: $(self).attr('id').slice(1), 
           rating: score 
          }, 
          success: function() { 
           console.log('setting to read-only'); 
           $(self).raty('readOnly', true); 
          } 
          }); 
         } 
         }); 
      else 
      script(type='text/javascript') 
       $('#_#{game.slug}').raty({ 
       path: '/img', 
       round : { down: .25, full: .6, up: .76 }, 
       score: #{game.rating}/#{game.votes}, 
       readOnly: true 
       }); 

      script(type='text/javascript') 
      $('##{game.slug}').click(function() { 
       var game = this; 
       $.ajax({ 
       type: 'post', 
       url: '/buy', 
       data: { 
        slug: $(game).attr('id') 
       } 
       }).success(function() { 
       $('#price-#{game.slug}').attr('disabled', 'true'); 
       $('#modal-' + $(game).attr('id')).modal('hide'); 
       humane.log('Your order has been submitted!'); 
       }); 
      }); 
+3

Grande muro di testo ma una domanda piuttosto buona +1 – Ben

risposta

3

Quella era troppo lungo da leggere. In ogni modo, penso che ho l'essenza di quello che stai dicendo e vorrei utilizzare un formato simile a questo:

<div id="some_container"> 
    <!-- The following div would be generated in each iteration of the for loop you speak of --> 
    <div class="item-container" data-game-name="Your game name" data-game-id="23"> 
     <span class="button delete-button">X</span> 
    </div> 
</div> 

E lo script sarebbe qualcosa con delega (per ridurre al minimo il numero di attacchi di molto):

$(document).ready(function() { 
    $("#some_container").on("click", ".delete-button", function() { 
     var $this = $(this); 
     var $container = $this.closest(".item-container"); 
     var game_name = $container.data("game-name"); 
     var game_id = $container.data("game-id"); 
     // Do whatever with the above 2 variables 
    }); 
}); 

Per quanto riguarda il materiale modale, è possibile creare uno <div> con un "modello" per ciò che deve essere visualizzato. Quindi, quando si fa clic su qualsiasi pulsante, si utilizza la logica come sopra (ottenere il primo genitore .item-container per ottenere dettagli sull'elemento, questi compilano il "modello" nel modale con queste informazioni. Quindi in questo modo, "OK" il pulsante non ha bisogno di un milione di cose hardcoded - solo uno - prendi le informazioni dal modello e fai qualunque chiamata o invia il modulo

+1

Grazie, ho finito per usare qualcosa di simile inserendo i miei dati server in attributi HTML- * Sebbene non sia possibile inserire troppe informazioni, come tutti i nomi utente che hanno votato su un particolare gioco (problemi di privacy), quindi finisco per fare qualche logica nel mio modello che restituisce una variabile booleana True/False che verrà passata al lato client all'interno dell'attributo data- *. –

Problemi correlati