如何在Express/Node.js中将内联javascript与动态生成的内容分离?
对于有几年web开发经验的人来说,这是一个有点不着边际的问题,但在程序员Stack Exchange或Google上都找不到答案后,我决定在这里提问 我正在为Node.js使用Expressweb框架,但这个问题并不特定于任何web框架或编程语言 下面是从数据库查询的游戏列表。每个游戏实体都是一个表行,使用for循环生成: 每个评级块以及每个购买按钮/模式对话框都由for循环生成,id与游戏匹配。例如,刺客信条的购买按钮将显示id=“价格刺客信条”#{variable}-是如何在Jade中引用从服务器传入的变量如何在Express/Node.js中将内联javascript与动态生成的内容分离?,javascript,node.js,refactoring,express,pug,Javascript,Node.js,Refactoring,Express,Pug,对于有几年web开发经验的人来说,这是一个有点不着边际的问题,但在程序员Stack Exchange或Google上都找不到答案后,我决定在这里提问 我正在为Node.js使用Expressweb框架,但这个问题并不特定于任何web框架或编程语言 下面是从数据库查询的游戏列表。每个游戏实体都是一个表行,使用for循环生成: 每个评级块以及每个购买按钮/模式对话框都由for循环生成,id与游戏匹配。例如,刺客信条的购买按钮将显示id=“价格刺客信条”#{variable}-是如何在Jade中引用
button.btn.btn-primary.btn-mini(id='price-#{game.slug}', href='#buyModal', role='button', data-toggle='modal')
及
及
乘以游戏的数量,这就是我在一个页面上有多少内联脚本
更糟糕的是,我必须解释以下情况:
- 用户未登录:以只读模式显示高于额定值的脚本
- 用户已登录,但尚未投票:
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条件的另一个只读脚本
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!');
});
});
扩展布局
块内容
溴
ul.nav.nav-pills
如果标题==“前25名”
李:很活跃
a(href='/games')前25名
其他的
锂
a(href='/games')前25名
如果标题=='操作'
李:很活跃
(href='/games/genre/action')动作
其他的
锂
(href='/games/genre/action')动作
如果标题===‘冒险’
李:很活跃
(href='/games/genre/advention')冒险
其他的
锂
(href='/games/genre/advention')冒险
如果航向==‘驾驶’
李:很活跃
a(href='/games/genre/driving')驾驶
其他的
锂
a(href='/games/genre/driving')驾驶
如果标题===‘拼图’
李:很活跃
(href='/games/genre/puzzle')拼图
其他的
锂
(href='/games/genre/puzzle')拼图
如果标题==“角色扮演”
李:很活跃
a(href='/games/genre/role-playing')角色扮演
其他的
锂
a(href='/games/genre/role-playing')角色扮演
如果航向==“模拟”
李:很活跃
a(href='/games/genre/simulation')模拟
其他的
锂
a(href='/games/genre/simulation')模拟
如果标题==‘策略’
李:很活跃
(href='/games/genre/strategy')策略
其他的
锂
(href='/games/genre/strategy')策略
如果标题==‘运动’
李:很活跃
a(href='/games/genre/sports')运动
其他的
锂
a(href='/games/genre/sports')运动
如果games.length==0
警告
|数据库查询未返回任何结果。
其他的
桌子
表格主体
游戏中的游戏
.modal.hide.fade(id='modal-{game.slug}',tabindex='1',role='dialog',aria labelledby='myModalLabel',aria hidden='true')
.模态标题
span.lead游戏签出
img.pull right(src='/img/new\u visa\u medium.gif')
.模态体
标签
i、 图标用户
|卡片上的名字
输入。输入媒体(type='text')
标签
i、 图标条码
|卡号
输入。输入媒体(类型='text',占位符='••,最大长度=16)
标签
i、 图标时间
|有效期
input.input mini(type='text',占位符='MMYY',maxlength=4)
标签
i、 图标QR码
|卡码
input.input mini(type='text',placeholder='CVC',maxlength=4)
.模态页脚
btn(data dismise='modal',aria hidden='true')取消
button.btn.btn主(id='{game.slug}')购买
tr
td.span2
img.img宝丽来(src='/img/games/#{game.largeImage}'))
运输署
a(href='/games/#{game.slug}')
坚强的
=游戏名称
|
如果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
=游戏价格
如果user.purchasedGames&&user.purchasedGames.length>0
用于user.purchasedGames中的mygame
如果mygame.game.slug==game.slug
脚本(type='text/javascript')
$('price-{game.slug}').removeAttr('href'))
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);
}
});
}
});
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!');
});
});
<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
});
});