對於有幾年Web開發經驗的人來說,這是一個有點小問題,但是在程序員堆棧交換或Google找不到答案後,我決定在這裏問一下。如何從Express/Node.js中動態生成的內容中分離內聯javascript?
我使用爲的Node.js快遞 web框架,但這個問題是不特定於任何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 =「價格殺手 - 信條」。 #{}可變 - 是你如何引用翡翠的變量,從服務器中通過。
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
});
乘上游戲的數量,這就是我多少內嵌腳本有一個頁面上。
更糟糕的是,我必須考慮以下情況:
- 用戶未登陸:以只讀模式顯示上述評級的腳本。
- 用戶登錄,但尚未投票:
...在這種情況下,使用下面的腳本:
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到單獨的文件我怎麼知道哪個遊戲am我的評價?我如何知道用戶點擊了哪個購買按鈕?
現在沒有歧義,因爲ň比賽,我有N個購買按鈕,ñ模態對話框和ñ評級腳本。不管任何人對這種編程風格的看法,這是維護代碼的一種可怕的方式。
請與noobie分享一些見解!
預先感謝您。
這是我的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!');
});
});
大牆文字,但一個很好的問題+1 – Ben