
é±æ«ãéå±ãšä»äºã®äžè¶³ãããç§ã¯2ã€ã®ãã°ãããã©ã€ãã©ãª
ractive.jsãš
sails.jsã®æ©èœã調æ»ããããã®ææãšããŠæ©èœããå°ããªã¢ããªã±ãŒã·ã§ã³ãäœæããããšã§
楜ããããš
決ããŸãããåé¡ã®å£°æ
ä»äºã®åŸãå€ãã®å Žåã次ã®ã¿ã¹ã¯ïŒç§ã¯ããªãŒã©ã³ãµãŒïŒãå®äºããåŸããµãŒãã¹ã®æ¯æãã«ã€ããŠé¡§å®¢ã«è«æ±ããå¿
èŠããããŸãã ç¹ã«æ³äººãæ±ãå Žåã ãããè¡ãããã«ãåçŽãªhtmlãã³ãã¬ãŒãã䜿çšããŠãããŒã¿ãæã§å
¥åãã次ã®ãã®ãä¿®æ£ããŸãã...
ãããªæã

ç§ã¯ãã¹ã¿ã€ã«ãšã¬ã€ã¢ãŠããfreshbooks.comããçãŸããããšãèªããŠããŸãã æ®å¿µãªããããã·ã¢ã®ã¯ã©ã€ã¢ã³ãã«ãšã£ãŠããã¯ç§ã«ã¯åãããåçŽãªhtmlãã³ãã¬ãŒãã§ååã§ããã
æè¡ã®éžæ
ãã¹ãŠã®ã¹ãã©ã€ãã®jsãã¬ãŒã ã¯ãŒã¯ãšãµãŒããŒãµã€ãã®jséçºã®äººæ°ã®çŸåšã®åŸåã§ã¯ãå°ã幞çŠã®jsãå°ãã®éç¶æããããã«ããããããã®ãšãªã¢ã¯ãã£ããªãã®ã䜿çšããããšæããŸãã...ãããŠãããã®ããã¡ãã䞊è¡ããŠè©ŠããŠã¿ãŠãã ããã
ããã€ãã®èª¿æ»ãæ¯èŒãããã³çŽæçãªæŽå¯ã®åŸãç§ã¯
sails.jsããµãŒããŒãšããŠäœ¿çšããããšã«
決ããŸããã ç§ã¯ããŒããŒãšã»ã€ã«ã®ã©ã¡ãããéžã³ãŸãã-çµå±ããšãããéžãã ã®ã¯ãäž»ã«ãã®ã·ã³ãã«ãïŒããã¯ãèªã¿ããããŠããŠãã ããã§ãïŒã«å ããŠãç®±ããåºããŠéåžžã«ã¯ãŒã«ãªã¬ã¹ãAPIãžã§ãã¬ãŒã¿ãŒãåããŠããŸãã åŠç¿ãšããç¹ã§ã®ããŒããŒã¯ãããé£ãããããæªããããã«èŠããŸããïŒãã®äŸã§ã¯ãæ瀺çãªãªãŒããŒãããïŒã
ã¯ã©ã€ã¢ã³ãã§
㯠ã
ractive.jsã
ãããããšã«æ±ºããŸããã ãã®åŸãbackbone.jsãæ¥ç¶ããããšã決å®ãããŸãã-äž»ã«ã¢ãã«ãšã®äŸ¿å©ãªäœæ¥ã®ãã
ãã®äŸã®åã¯ã
sails.jsãš
ractive.jsã®çµéšããããŸãã
ã§ãã ã äœæ¥ã§ã¯ãããã¯ããŒã³ã®ã¿ã䜿çšããŸããã
å§ããŸãããã
ãµãŒããŒ
ãã®äŸã§ã¯ãsails v0.10ã䜿çšããŸããããã¯ãŸã ããŒã¿çã§ãããçŸåšã®å®å®ããŒãžã§ã³0.9.xãšæ¯èŒãããšãããã€ãã®äŸ¿å©ãªæ©èœããããŸãã ç¹ã«ã1察å€ãå€å¯Ÿå€ïŒããã³ã¢ãã«éã®ãã®ä»ã®é¢ä¿ïŒãæå®ã§ãã
ã¢ãã«ã¢ãœã·ãšãŒã·ã§ã³ ããŸã
0.10ã§ã¯ã
ããªã声ã¿ã¹ã¯ã·ã¹ãã ãåèšèšãããŸããã 0.10ã®
ããã¯ã§ã¯ããã¹ãŠãã¯ã£ãããšæžãããŠããŸã
sails v0.10ã¯npmçµç±ã§é
ä¿¡ã§ããŸãïŒã°ããŒãã«ã«ã€ã³ã¹ããŒã«ããŸããïŒ
sudo npm install -g "git://github.com/balderdashy/sails.git#v0.10"
確èªãã
sails -v
0.10.0-ãã°ããã
ã¹ã±ã«ãã³ã®sailsjsã¢ããªã±ãŒã·ã§ã³ã®äœæ
è«æ±æžãªã©ã®æ°ããã¢ããªã±ãŒã·ã§ã³ãäœæããäŸåé¢ä¿ãé
眮ããŸã
sails new invoicer cd invoicer npm install
次ã«ã
sails lift
ã³ãã³ããå®è¡ããããšã«ãããçµã¿èŸŒã¿ã®express.jsãµãŒããŒãå®è¡ã§ããŸãã
localhost:1337
APIãšã³ãã£ãã£ïŒã¢ãã«ïŒã®äœæ
ã¢ããªã±ãŒã·ã§ã³ã«ã¯3ã€ã®ã¢ãã«ãå¿
èŠã§ãã
user
ãŠãŒã¶ãŒæ
å ±ãä¿åããŸãinvoice
-ã¢ã«ãŠã³ãã®ãªã¹ãçštask
ã¢ã«ãŠã³ãå
ã®ã¿ã¹ã¯ïŒè«æ±æžïŒ
sails generate api <api_name>
APIçæ zaebee@zaeboo$ sails generate api user debug: Generated a new model `User` at api/models/User.js! debug: Generated a new controller `user` at api/controllers/UserController.js! info: REST API generated @ http://localhost:1337/user info: and will be available the next time you run `sails lift`. zaebee@zaeboo$ sails generate api invoice debug: Generated a new model `Invoice` at api/models/Invoice.js! debug: Generated a new controller `invoice` at api/controllers/InvoiceController.js! info: REST API generated @ http://localhost:1337/invoice info: and will be available the next time you run `sails lift`. zaebee@zaeboo$ sails generate api task debug: Generated a new controller `task` at api/controllers/TaskController.js! debug: Generated a new model `Task` at api/models/Task.js! info: REST API generated @ http://localhost:1337/task info: and will be available the next time you run `sails lift`.
ãã®åŸã3ã€ã®ãã¡ã€ã«ãapi / controllersãã©ã«ããŒã«è¡šç€ºãããŸã
-rw-r--r-- 1 146 28 17:15 InvoiceController.js -rw-r--r-- 1 143 28 17:15 TaskController.js -rw-r--r-- 1 143 28 17:15 UserController.js
API /ã¢ãã«ã
-rw-r--r-- 1 146 28 17:15 Invoice.js -rw-r--r-- 1 143 28 17:15 Task.js -rw-r--r-- 1 143 28 17:15 User.js
ç°¡åã§ã·ã³ãã«ãªåžã¯ã3ã€ã®æ¹æ³ãäœæããŸãã
localhost:1337/user
localhost:1337/invoice
localhost:1337/task
CRUDæäœããµããŒãããŸãã ãããã®ãšã€ãªã¢ã¹ããããŸããããšãã°ã
localhost:1337/user/create?name=Andrey&address=Russia
localhost:1337/user/create?name=Andrey&address=Russia
æ°ãããŠãŒã¶ãŒã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
éµäŸ¿é
éå¡ãéããŠéã¶ããšãã§ããŸã
ãŸã
ãã³ã³ãããŒã©ã®ããã¥ã¡ã³ããèªãããšããå§ãããŸã
ã¹ãã¬ãŒãžæ§æïŒDBïŒ
äœæãããããŒã¿ã¯ã©ãã«ä¿åãããŸããïŒ ããã©ã«ãã§ã¯ããã£ã¹ã¯ãã¹ãã¬ãŒãžãšããŠäœ¿çšãããŸããããã¯ã
config/connections.js
ããã³
config/models.js
èšå®ã§ç€ºãããŸã
config / connections.jsã³ãŒã module.exports.connections = { localDiskDb: { adapter: 'sails-disk' }, someMysqlServer: { adapter : 'sails-mysql', host : 'YOUR_MYSQL_SERVER_HOSTNAME_OR_IP_ADDRESS', user : 'YOUR_MYSQL_USER', password: 'YOUR_MYSQL_PASSWORD', database: 'YOUR_MYSQL_DB' }, someMongodbServer: { adapter : 'sails-mongo', host : 'localhost', port : 27017,
mongoã䜿çšããŠã¬ã³ãŒããä¿åããŸãããã®ãããconfig / models.jsããããã«å€æŽããŸãã
config / models.jsã³ãŒã module.exports.models = {
å¿
èŠãªãŠãŒã¶ãŒãè«æ±æžãã¿ã¹ã¯ã¢ãã«ã®ãã£ãŒã«ãã«ã€ããŠèª¬æããŸã
api / models / User.js module.exports = { attributes: { name: 'string', email: 'string', avatar: 'string', address: 'text', account: 'text', invoices: { collection: 'invoice', via: 'owner', } }, };
API /ã¢ãã«/ Invoice.js module.exports = { attributes: { total_amount: 'float', name: 'string', address: 'text', owner: { required: false, model: 'user', }, tasks: { required: false, collection: 'task', via: 'invoice', } }, };
api / models / Task.js module.exports = { attributes: { name: 'string', description: 'text', hours: 'float', rate: 'float', invoice: { required: false, model: 'invoice', via: 'tasks', } }, };
mongoã¢ããã¿ã䜿çšããã«ã¯ãsails-mongoããã±ãŒãžãã€ã³ã¹ããŒã«ããå¿
èŠããããŸã
npm install sails-mongo@0.10
ã³ã³ãããŒã©ãŒã®ãã¢ã¯ã·ã§ã³ããšããã®ãã³ãã¬ãŒãïŒãã¥ãŒïŒãè¿œå ãã
ã¡ã€ã³ã¿ã¹ã¯ïŒè«æ±æžã®äœæïŒã®ããŒãžãçæããã³ã³ãããŒã©ãŒãäœæããå¿
èŠããããŸãã
sails generate controller main generate
æ°ãã
MainController.js
ãäœæãã1ã€ã®
generate
é¢æ°ãããããã¢ã¯ã·ã§ã³ãäœæããŸã
URLã«è¡ããš
localhost:1337/main/generate
localhost:1337/main/generate
generate
é¢æ°ãè¿ããã®ã確èªããŸã
ããã©ã«ãã§ã¯jsonãè¿ããŸã
return res.json({ todo: 'Not implemented yet!' });
ãã©ãŠã¶ãŒã§htmlããŒãžã衚瀺ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãäžèšã®ã³ãŒãã次ã®ããã«çœ®ãæããŸã
return res.view()
ãã©ãŠã¶ã§ããŒãžãæŽæ°ãããšãšã©ãŒã衚瀺ãããŸã
{ "view": { "name": "main/generate", "root": "/home/zaebee/projects/invoicer/views", "defaultEngine": "ejs", "ext": ".ejs" } }
ããã¯ã衚瀺çšã®ãã³ãã¬ãŒããäœæããŠããªãããšãæå³ããŸãã ã³ã³ãããŒã©ãŒã®ãã¹ãŠã®htmlãã³ãã¬ãŒãã¯ãã¥ãŒãã©ã«ããŒã«ããã次ã®
views/<controller_name>/<action_name>
ãæã¡ãŸã
空ã®ãã¥ãŒãäœæ/ã¡ã€ã³/ãã³ãã¬ãŒããçæ
zaebee@zaeboo$ mkdir views/main zaebee@zaeboo$ touch views/main/generate.ejs
ããã©ã«ãã§ã¯ãejsã¯ãã³ãã¬ãŒããšã³ãžã³ãšããŠäœ¿çšãããŸãã Sailsã¯å€ãã®ãã³ãã¬ãŒããšã³ãžã³ããµããŒãããŠãããconfig / views.jsãã¡ã€ã«ã§ãããã奜ã¿ã«å€æŽã§ããŸãã
ejs, jade, handlebars, mustache
underscore, hogan, haml, haml-coffee, dust
atpl, eco, ect, jazz, jqtpl, JUST, liquor, QEJS,
swig, templayed, toffee, walrus, & whiskers
泚æïŒ ã»ãŒã«ããŒãžã§ã³0.10ã§ã¯ãã©ã€ãã¢ãŠãã®ãµããŒãã¯ejsã§ã®ã¿æ©èœããŸãã èŠããã«ãä»ã®ãã¹ãŠã®
views/layout.ejs
ãç¶æ¿ãããåºæ¬
views/layout.ejs
ããã
views/layout.ejs
ã ãŸãããã³ãã¬ãŒããšã³ãžã³ã䜿çšããå Žåãejs以å€ã®ç¶æ¿ã¯ãããŸããã
config/views.js
ãšã³ãžã³ãªãã·ã§ã³ãå€æŽãããšãSailsã¯ãããæ確ã«ããŸã
warn: Sails' built-in layout support only works with the `ejs` view engine. warn: You're using `hogan`. warn: Ignoring `sails.config.views.layout`...
ã客æ§
ãµãŒããŒã®æºåãã§ããŸãããè«æ±æžã¢ããªã±ãŒã·ã§ã³ã®ã¯ã©ã€ã¢ã³ãéšåã®äœæãå§ããŸãããã
éçæ¥ç¶
ãã¹ãŠã®éçïŒãŸãã¯ãããªãã¯ã¯ã©ã€ã¢ã³ãã³ãŒãïŒã¯ãassetsãã©ã«ããŒã«ãããŸãã æ°ãããã¡ã€ã«ããã³ãã¬ãŒãã«æ¥ç¶ããã«ã¯ãããããé©åãªãã©ã«ããŒïŒã¢ã»ãã/ jsã®ã¹ã¯ãªãããã¢ã»ãã/ã¹ã¿ã€ã«ã®ã¹ã¿ã€ã«ãã¢ã»ãã/ãã³ãã¬ãŒãã®ã¯ã©ã€ã¢ã³ããã³ãã¬ãŒãïŒã«é
眮ããã ãã§ãã .ejs-ç¹å¥ãªã»ã¯ã·ã§ã³ïŒ
ãœãŒã¹ãã¡ã€ã«/views/layout.ejsã®ãªã¹ã <!DOCTYPE html> <html> <head> <title>New Sails App</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link rel="stylesheet" href="/styles/importer.css"> </head> <body> <%- body %> <script src="/js/dependencies/sails.io.js"></script> </body> </html>
å¿
èŠãªã©ã€ãã©ãªïŒJqueryãUnderscoreãBackboneãRactiveïŒãcdnãä»ããŠã¬ã€ã¢ãŠãã«æ¥ç¶ãã
bootstrap.min.css
ãšå®æãã
app.css
ãã¡ã€ã«ã
assets/styles
ãã©ã«ããŒã«é
眮ããŸãã ãŸããå¿
èŠãªè¿œå ã®jsïŒ
bootstrap.min.css
ã
moment.ru.js
ããã³
moment.min.js
moment.ru.js
ã
moment.min.js
ããããã®ã©ã€ãã©ãªïŒã
assets/js/vendor
ãã©ã«ããŒã«
app.js
ãã
assets/js
ãã©ã«ããŒã«ç©ºã®
app.js
ãã¡ã€ã«ãé
眮ããŸã
assets/js
sails lift
ãå®è¡ãããã¡ã€ã«
views/layout.ejs
ã§çŸåšã®å
容ã確èªããŸã
ãœãŒã¹ãã¡ã€ã«/views/layout.ejsã®ãªã¹ã <!DOCTYPE html> <html> <head> <title>New Sails App</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link rel="stylesheet" href="/styles/app.css"> <link rel="stylesheet" href="/styles/bootstrap.min.css"> <link rel="stylesheet" href="/styles/importer.css"> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script> <script src="//cdn.ractivejs.org/latest/ractive.min.js"></script> <script src="//api.filepicker.io/v1/filepicker.js"></script </head> <body> <%- body %> <!--TEMPLATES--> <!--TEMPLATES END--> <!--SCRIPTS--> <script src="/js/dependencies/sails.io.js"></script> <script src="/js/app.js"></script> <script src="/js/vendor/bootstrap.min.js"></script> <script src="/js/vendor/moment.min.js"></script> <script src="/js/vendor/moment.ru.js"></script> </body> </html>
çŽ æŽããããåžã¯ç§ãã¡ã®ããã«ãã¹ãŠãããŸããã 確ãã«ããã€ãã¹ã1ã€ãããŸãããã³ããŒã¹ã¯ãªããã¯app.jsã®äžã«æ¥ç¶ãããŠããŸãã
tasks/pipeline.js
ãã¡ã€ã«ãä¿®æ£ãããã³ããŒãã©ã«ããŒãå
ã«æ¥ç¶ããå¿
èŠãããããšãgruntã«äŒããŸãã
tasks / pipeline.jsãã¡ã€ã«ã®äžéšããªã¹ããã ã¯ã©ã€ã¢ã³ãéšåã®æºåãå®äºããŸãã-ã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã®èšè¿°ã«çŽæ¥é²ãããšãã§ããŸãã
ããŒãžã¬ã€ã¢ãŠãã¹ã±ã«ãã³ãäœæããŸãã Ractive.jsãã³ãã¬ãŒã
ããäžåºŠã¬ã€ã¢ãŠããèŠãŠã¿ãŸãããã ãã®äžã§ãåçããŒã¿ã«ãã€ã³ããããããã¯ã匷調ããŸããã

ã¯ã©ã€ã¢ã³ããã³ãã¬ãŒããå«ãŸãããã¡ã€ã«ãã¥ãŒ/ main / generate.ejsã§åºæ¬çãªããŒã¯ã¢ãããäœæããŸããã
ãã¡ã€ã«ãã¥ãŒã®ãªã¹ã/ main / generate.ejs <div class="main_bg"> <div class="container primary-content"> <div class="invoice-container rounded-container peel-shadows col-sm-8 col-sm-offset-2"> <h2 style="text-align:center;margin-bottom:30px;"> </h2> <div class="invheader"> <div class="invheader-upper"> </div> <div class="invheader-lower"> </div> </div> <div class="invbody"> <div class="invbody-tasks"> </div> <div class="clearb" style="height: 1px; overflow: hidden;"></div> <div class="invbody-account"> </div> </div> </div> </div> </div>
ããã§ãåºæ¬çãªããŒã¯ã¢ããã®æºåãã§ããŸãã
-ractive.jsãã³ãã¬ãŒãã®æéã§ã
ãããã¯ããšã«ãã³ãã¬ãŒããäœæãïŒåèšã§4ã€ãããŸãïŒãããããã¢ã»ãã/ãã³ãã¬ãŒãã«é
眮ããŸã
ã¢ã»ãã/ãã³ãã¬ãŒã/invheader-upper.htmlã®ãªã¹ã <div class="invheader-address-account" on-hover="toggleBtn"> <a role="button" title="{{ .editing ? '' : ' ' }}" class="hidden-print btn btn-primary btn-sm hide" on-click="edit"><i class="glyphicon glyphicon-{{ .editing ? 'ok' : 'pencil' }}"></i> </a> <b>:</b> <div class="user-name {{ .editing ? 'editing' : '' }}"> <span>{{^name}} {{/name}}{{name}}</span> {{#.editing}} <div class='edit-container'> <input intro="select" value="{{name}}" class="form-control" placeholder=" "> </div> {{/.editing}} </div> <div class="user-address {{ .editing ? 'editing' : '' }}"> <span>{{^address}} {{/address}}{{{address}}}</span> {{#.editing}} <div class='edit-container'> <textarea value="{{address}}" class='edit form-control' placeholder=" ">{{address}}</textarea> </div> {{/.editing}} </div> </div> <div on-hover="togglePicker" class="invheader-logo-container"> <div class="invheader-logo"> {{#avatar}} <img src="{{avatar}}/convert?h=110&w=250" alt="{{name}}"> {{/avatar}} <div class="hidden-print BoardCreateRep {{ avatar ? 'hide' : '' }}"> <input type="filepicker-dragdrop" data-fp-mimetype="image/png" data-fp-apikey="A3lXl09sRSejY4e0pOOSQz" data-fp-button-class="btn btn-primary hidden-print" data-fp-button-text=" " data-fp-drag-text=" " data-fp-drag-class="hidden-print drop-avatar" onchange="app.user.fire('setAvatar', event)"> </div> </div> </div>
ã¢ã»ãã/ãã³ãã¬ãŒã/invheader-lower.htmlã®ãªã¹ã <div class="invheader-address-client" on-hover="toggleBtn"> <a role="button" title="{{ .editing ? '' : ' ' }}" class="hidden-print btn btn-primary btn-sm hide" on-click="edit"><i class="glyphicon glyphicon-{{ .editing ? 'ok' : 'pencil' }}"></i> </a> <b>:</b> <div class="cleint-name {{ .editing ? 'editing' : '' }}"> <span>{{^invoice.name}} {{/invoice.name}}{{invoice.name}}</span> {{#.editing}} <div class='edit-container'> <input intro="select" value="{{invoice.name}}" class="form-control" placeholder=" "> </div> {{/.editing}} </div> <div class="client-address {{ .editing ? 'editing' : '' }}"> <span>{{^invoice.address}} {{/invoice.address}}{{{invoice.address}}}</span> {{#.editing}} <div class='edit-container'> <textarea value="{{invoice.address}}" class="edit form-control" placeholder=" ">{{invoice.address}}</textarea> </div> {{/.editing}} </div> </div> <div class="invheader-invoicedetails"> <table cellspacing="0"> <tbody> <tr> <th> </th> <td>#{{ lastFour(invoice.id) }}</td> </tr> <tr> <th> </th> <td>{{ date(invoice.createdAt) }}</td> </tr> <tr class="invheader-invoicedetails-balance"> <th><div> </div></th> <td><div> {{^invoice.total_amount}}0.00{{/invoice.total_amount}}{{ invoice.total_amount }} </div></td> </tr> </tbody> </table> </div>
ã¢ã»ãã/ãã³ãã¬ãŒã/invbody-tasks.htmlã®ãªã¹ã <table class="invbody-items" cellspacing="0"> <thead> <tr> <th class="first"><div class="item"> </div></th> <th><div class="description">, </div></th> <th><div class="unitcost"> ()</div></th> <th><div class="quantity"> </div></th> <th class="last"><div class="linetotal"> ()</div></th> </tr> </thead> <tbody> {{#tasks}} <tr> <td style="width: 160px;"> <a on-tap="destroy:{{this}}" role="button" class='hidden-print destroy'></a> <div on-click="edit" class="item">{{name}}</div> <input intro="select" class="form-control hide" value="{{name}}" on-blur-enter="hide:{{this}}"> </td> <td> <div on-click="edit" class="description">{{description}}</div> <textarea class="form-control hide" value="{{description}}" on-blur-enter="hide:{{this}}">{{description}}</textarea> </td> <td style="width: 85px;"> <div on-click="edit" class="unitcost">{{ format(rate) }}</div> <input class="form-control hide" value="{{rate}}" on-blur-enter="hide:{{this}}"> </td> <td style="width: 80px;"> <div on-click="edit" class="quantity">{{ format(hours) }}</div> <input class="form-control hide" value="{{hours}}" on-blur-enter="hide:{{this}}"> </td> <td style="width: 90px;"> <div class="linetotal">{{ format(rate * hours) }}</div> </td> </tr> {{/tasks}} <tr> <td class="hidden-print text-center" colspan="5"> <button on-click="add" class="btn btn-primary btn-sm"><i class="glyphicon glyphicon-plus "></i> </button> </td> </tr> </tbody> </table> <table class="invbody-summary" cellspacing="0"> <tbody> <tr> <td class="invbody-summary-clean"> </td> <td style="width: 150px;"><strong> : </strong></td> <td style="width: 120px;"><strong> {{ total(tasks) }} </strong></td> </tr> <tr class="invbody-summary-paid"> <td class="invbody-summary-clean"> </td> <td style="width: 150px;"> </td> <td style="width: 120px;">-0.00</td> </tr> <tr class="invbody-summary-total"> <td class="invbody-summary-clean"> </td> <td style="width: 150px;"><div><strong> : </strong></div></td> <td style="width: 120px;"><div><strong> {{ total(tasks) }} </strong></div></td> </tr> </tbody> </table>
ã¢ã»ãã/ãã³ãã¬ãŒã/invbody-account.htmlã®ãªã¹ã <div class="invbody-terms" on-hover="toggleBtn"> <a role="button" title="{{ .editing ? '' : ' ' }}" class="hidden-print btn btn-primary btn-sm hide" on-click="edit"><i class="glyphicon glyphicon-{{ .editing ? 'ok' : 'pencil' }}"></i> </a> <b>:</b> <div class="user-account {{ .editing ? 'editing' : '' }}"> <span>{{^account}} {{/account}}{{{account}}}</span> {{#.editing}} <div class='edit-container'> <textarea value="{{account}}" class='edit form-control' placeholder=" ">{{account}}</textarea> </div> {{/.editing}} </div> </div>
äžè¬ã«ãããã¯éåžžã®htmlã§ããã
ractive.jsãããŒã¿ãæ¿å
¥ããå£ã²ãã®ãããªã¿ã°
{{}}
æ£åšããŠããŸãã ãŸããããã€ãã®ãã£ã¬ã¯ãã£ã
on-click="edit"
æ°ä»ããããããŸãã-ã¯ãªãã¯ã«ãã£ãŠ
edit
ã¡ãœãããå®è¡ããŸãã
on-hover="toggleBtn"
ã
on-tap="destroy:{{this}}"
ãã®ç¹ã«ã€ããŠã¯åŸã§èª¬æããŸããä»ã®ãšããã
ractive.jsã€ãã³ãã®
ããã¥ã¡ã³ããåŠç¿ã§ããŸã
ã€ãã³ãã¯ãã©ã°ã€ã³ã®åœ¢åŒã§ractiveã§æ¥ç¶ãããŸã-ãããããããã·ã€ãã³ãã ã€ãã³ããæ©èœãããã«ã¯ãå¿
èŠ
ãªãã®ãããŠã³ããŒãã㊠ïŒã€ãã³ãã®ãã¹ãŠã®ãã©ã°ã€ã³ãããŠã³ããŒãããïŒã
assets/js/vendor
ãã©ã«ããŒã«é
眮ããå¿
èŠããããŸã
ractive.jsãããã¯ããŒã³ã¢ãã«ãããŒã¿ãœãŒã¹ãšããŠäœ¿çšã§ããããã«ã
Backboneçšã®
ã¢ããã¿ãŒãåããã©ã«ããŒã«é
眮ããŸãã
ããŒã¿ã®åæåã ããŒã¿ãšãã³ãã¬ãŒãã®ãã€ã³ã
çŸæç¹ã§äœã§ãããçµæãšããŠåŸãããã®ãèŠçŽãã
- REST APIã䜿çšããŠåžãµãŒããŒäžã§ãŠãŒã¶ãŒãè«æ±æžãã¿ã¹ã¯ãäœæã§ããŸãã ã¢ãã«ã®é¢é£ä»ããä»ããŠããããæ¥ç¶ããŸãã ããŒã¿ã¯mongodbããŒã¿ããŒã¹ã«ä¿åãããŸã
- ããã¯ããŒã³ã¯ã©ã€ã¢ã³ãã§ã¯ãã¢ãã«ã¯ãŠãŒã¶ãŒãå
¥åããããŒã¿ãä¿åããrest APIãä»ããŠã»ãŒã«ãµãŒããŒãšåæããŸãã
- ã¯ã©ã€ã¢ã³ãã§ã¯ãractiveã¯htmlãã³ãã¬ãŒããšããã¯ããŒã³ã¢ãã«éã®åæ¹åãã€ã³ãã£ã³ã°ãå®è£
ããŸãïŒ Backboneã®ã¢ããã¿ãŒã«ããïŒ
- ....
- å©çïŒ
æåã«ã空ã®
assets/js/app.js
å¿
èŠãªBackboneã¢ãã«ãäœæã
assets/js/app.js
ã
ã¢ã»ããã®ãªã¹ã/ js / app.js var app = app || {}; (function (app) { app.User = Backbone.Model.extend({ urlRoot: '/user', }); app.Invoice = Backbone.Model.extend({ urlRoot: '/invoice', }); app.Task = Backbone.Model.extend({ urlRoot: '/task', }); app.Tasks = Backbone.Collection.extend({ url: '/task', model: app.Task }); })(app);
ããŠãapp.Userã¢ãã«ã«ãã€ã³ãããã
assets/templates/invheader-upper.html
ãš
assets/templates/invbody-account.html
assets/templates/invheader-upper.html
ãã¬ã³ããªã³ã°ããractiveã€ã³ã¹ã¿ã³ã¹ãäœæããŸã
ã¢ã»ãã/ js / user.jsãã¡ã€ã«ãäœæããŸã
ã¢ã»ããã®ãªã¹ã/js/user.js var app = app || {}; (function (app) { var backboneUser = new app.User;
ã³ãŒãã¯éåžžã«ç°¡åã§ãã ããã§ãåºæ¬ã¯ã©ã¹
RactiveUser
ãäœæããŸãã éåžžã
new Ractive({})
ã䜿çšããŠã€ã³ã¹ã¿ã³ã¹ãäœæã§ããŸãããç¹ã«ããã§ã¯ãåãã¢ãã«ã«é¢é£ä»ããããã»ãŒåãã€ãã³ãããµãã¹ã¯ã©ã€ããã2ã€ã®èŠçŽ ããŠãŒã¶ãŒã«å¿
èŠã§ãã ã€ãã³ãèªäœã¯ã
init
é¢æ°ã®æ¬äœã§ç€ºãããŸãã
ããã«é²ãã§ã
assets/js/invoice.js
ãš
assets/js/task.js
é¡æšããŠäœæã
assets/js/invoice.js
ã¢ã»ããã®ãªã¹ã/ js / invoice.js var app = app || {}; (function (app) { app.invoice = new Ractive({ el: '.invheader-lower', template: JST['assets/templates/invheader-lower.html'](), data: { invoice: new app.Invoice,
ã¢ã»ããã®ãªã¹ã/ js / task.js var app = app || {}; (function (app) { app.tasks = new Ractive({ el: '.invbody-tasks', template: JST['assets/templates/invbody-tasks.html'](), data: { tasks: new app.Tasks,
ããã§ãã³ãŒãã¯ååã«æ確ã§ãããã€ãã³ãã«ã³ã¡ã³ããè¿œå ããŸããã ããã¯åºæ¬çã«ãã¹ãŠã®ã¯ã©ã€ã¢ã³ãã³ãŒãã§ãã ãŸããIDã«åºã¥ããŠéçãªè«æ±æžãçæããæ¹æ³ãåºå®ããããšãèšç»ããŸãã
localhost:1337/main/generate/535ea7aa6113230d773fd160
localhost:1337/main/generate/535ea7aa6113230d773fd160
ïŒãŸãã¯api pdfcrowd.comã䜿çšããŸãã幞ããªããšã«ãURLã§pdfãäœæã§ããããŒãçšã®ã¢ãžã¥ãŒã«ããããŸãã ä»ãç§ã¯ctrp + PïŒå°å·ã«éä¿¡ïŒ-> "ãã¡ã€ã«ã«å°å·"ã§PDFãäœæããŠããŸãã ãŸããäžèŠãªhtmlèŠçŽ ïŒãã¿ã³ãªã©ïŒãåºãªãããã«ããããã«ã
hidden-print
ã¯ã©ã¹ãè¿œå ããŸããã
ãµãŒããŒã«ãããã€ãã
ããã§ã»ãŒãã¹ãŠã§ã-ã¢ããªã±ãŒã·ã§ã³ã®æºåãã§ããŸããã ãã®äŸ
ã¯githubã«ãããŸããµãŒããŒã§ããªããžããªãè€è£œããäŸåé¢ä¿ãã€ã³ã¹ããŒã«ããæ¬çªã¢ãŒãã§åžãå®è¡ããŸãã
node app.js --port=8000 --prod
æ¬çªã¢ãŒãã§åäœãã
ãã¢ãéå§ããŸãã
ãŸãšã
sailsjsãšractiveã®äž¡æ¹ã䜿çšããçµæã¯éåžžã«æºè¶³ããŠããŸãã
Sailsjs-é·æïŒ
+ã»ãŒã«ã§APIãç°¡åã«äœæã§ãã
+ãã³ãã¬ãŒããšã³ãžã³ãããŒã¿ããŒã¹ã䜿çšãããORMããå§ãŸãéåžžã«ã¯ãŒã«ãªæ§æãªãã·ã§ã³ïŒ
bookshelfjs.orgãåžã«ãã蟌ãäºå®ã§ãïŒ
+ç§ã¯ãprodãšmaidã®äž¡æ¹ã®ãã³ãã«ãçæããã®ã«è¯ãä»äºãããæ¢è£œã®ããªã声ã®ã¿ã¹ã¯ãããããšããšãŠãæ°ã«å
¥ããŸããã
+ (
sails www
) â .
+ ( , , )
çæïŒ
â model assocoations (, v0.10 â , v0.9.x â )
â ejs
Ractivejs â :
+ backbone
+ ( )
+ mustache ( ejs â )
+ ,
Ractive â .
ãæž
èŽããããšãããããŸããã