6

これは、Web開発の経験が数年ある人にとってはやや難しい質問ですが、Programmer Stack ExchangeGoogleのどちらでも答えが見つからなかったため、ここで質問することにしました。

Node.jsにExpressWebフレームワークを使用していますが、この質問はWebフレームワークやプログラミング言語に固有のものではありません。

これは、データベースから照会されるゲームのリストです。各ゲームエンティティは、 forループを使用して生成された単一のテーブル行です。

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

ここに画像の説明を入力してください

レーティングブロック、および各購入ボタン/モーダルダイアログは、ゲームに一致するIDを持つforループによって生成されます。たとえば、アサシンクリードの購入ボタンにはid="price-assassins-creed"があります。#{variable} -サーバーから渡されたJadeの変数を参照する方法です。

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

.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

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

これにゲームの数を掛けると、1ページにあるインラインスクリプトの数になります。

さらに悪いことに、私は次の場合を説明する必要があります。

  • ユーザーがログインしていません:読み取り専用モードで上記の評価スクリプトを表示します。
  • ユーザーはログインしていますが、まだ投票していません

...その場合、次のスクリプトを使用します。

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);
                          }
                        });
                      }
                    });
  • ユーザーがログインしているが評価が一時停止されている:この特定のif-else条件に対して、さらに別の読み取り専用スクリプトをコピーして貼り付けます。

簡単に言うと、このJavaScriptをすべて.jadeテンプレートファイルで維持しようとするのはメンテナンスの悪夢になり、マークアップは容認できないほど汚れているように見えます。

これに対する解決策は何ですか?これは、CRUDアプリケーションの一般的なシナリオのようです。理想的には、すべてのjavascriptを別の.jsファイルに移動したいと思います。しかし、コードの重複を削除できれば、それも素晴らしいことです。

問題は、インラインJavaScriptを別のファイルに移動した場合、どのゲームを評価しているかをどのように知ることができるかということです。ユーザーがクリックした[購入]ボタンを確認するにはどうすればよいですか?

現在、 N個のゲームには、N個の購入ボタン、N個のモーダルダイアログ、およびN個の評価スクリプトがあるため、あいまいさはありません。誰もがこのスタイルのプログラミングについてどう思っているかに関係なく、それはコードを維持するためのひどい方法です。

初心者と洞察を共有してください!

前もって感謝します。

これが私の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!');
              });
            });
4

1 に答える 1

3

それは長すぎて読むことができませんでした。とにかく、私はあなたが言っていることの要点を理解し、次のような形式を使用すると思います:

<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>

そして、スクリプトは委任を伴うものになります(バインディングの数を大幅に最小限に抑えるため):

$(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
    });
});

<div>モーダルなものに関しては、何のために何を表示するかについての「テンプレート」を持つを作成することができます。次に、任意のボタンをクリックすると、上記のようなロジックを使用します(最初の親.item-containerにアイテムの詳細を取得させ、モーダルの「テンプレート」にこの情報を入力します。次に、「OK」ボタン何百万ものハードコードされたものを必要としません-たった1つ-テンプレートから情報を取得し、電話をかけるか、フォームを送信します。

于 2012-11-27T07:37:36.897 に答える