Your SlideShare is downloading. ×
0
Parse Basic
Building Web Apps WITHOUT Programming Server.
http://goo.gl/8IqkAa
2014 Spring Web Programming, NCCU
Author: p...
So far,你的網頁都是一成不變的
http://www.pmichaud.com/toast/ (從1994年後都沒變過)
但實際上,很多網站是隨時在改變的
為什麼網站可以不斷的、及時變化?
因為有後端啊。
*Web伺服器:接收http請求、產生或委派http回應並傳回client
端
*應用程式伺服器:根據使用者的請求產生相對的回應
資料庫:像一張巨大的Excel表,存各地來的資料
Backend Technology Stack
What if?
如果有一個工具可以讓我不用寫後端程式碼,但
還是可以使用後端的功能,該有多好啊......
Parse來拯救咧!
Parse是什麼
Parse是一個BaaS(Backend as Service)。
只要會用Parse提供的SDK, 還有正確的設定。開發者毋需擔
心後端的開發撰寫以及主機的擴張和維護。
這讓開發者免於開發者實現的繁瑣細節,而將高度提升到更
...
Parse開發模式概覽
Your Code
Parse SDK (黑箱)
Parse Cloud
知道Parse SDK怎麼用就可以寫互動式網站
了(SDK還跨平台喔!)
很好很強大!
● localStorage:
○ jsbin.com/rubej/1/watch?html,js,output
● Parse:
○ jsbin.com/fezuq/5/watch?html,js,output
Ex: localStorag...
● Data Store
○ Database + File
● User Management
● Background Jobs
● ……
○ (see also: https://parse.com/products)
What Pars...
Website vs. Web Application
Website vs. Web Application
● Information Oriented vs. Action Oriented
● Creation vs. Consumption
● Way of designing
● Any...
Class vs. Object
(雖然JavaScript不是Class-based object-
oriented programming language.)
Class -> 食譜
Object (instacne) -> 菜
Cla...
Model-View-Controller
SOURCE: http://online.stanford.edu/course/developing-ios7-apps-fall-2013
範例:Parse Store
● 模仿 ‘GetMore 二次時尚’ (其實根本抄襲)
● 二手洋裝專賣網站
● 能瀏覽商品、放入購物車
● 每個使用者有自己專屬的購物車(登入才能使
用)
● 沒有結賬功能
● http://pa4373.github.io/parsest...
商品 (Dress)
購物清單 (Order)
使用者 (User)
Parse Store (Model)
Parse Store (View)
選單
產品型錄
Parse Store (View)
選單
產品細項
Parse Store (View)
選單
登入 & 註冊
● 版型引擎 (Template Engine)
○ 解決navbar困境
○ Template Tag -> 編譯-> 能產生HTML的JS函數
○ 以doT.js為例
● 路由器 (Router)
○ Facebook Photo
○ 網址...
Use Parse SDK
Use Parse SDK
Use Parse SDK
記下Application Key以及JavaScript Key
Use Parse SDK
<!doctype html>
<head>
<meta charset="utf-8">
<title>My Parse App</title>
<meta name="description" content="...
Parse App Dashboard
Analytics: App使用狀況分析
Data Browser: 瀏覽儲存App的資料庫
Cloud Code: Server Code (進階)
Push Notifications: iOS、An...
下載Startup Project
https://github.
com/pa4373/parsestore_js/archive/startkit.zip
index.html
css/style.css
js/app.js
Dig into HTML.
<!doctype html>
…….
</body>
<!--網站各個組件的版型,包在script裏面讓template engine調用(稍後回提到)-->
<script id="loginTemplate"...
Dig into JavaScript. (app.js)
// 防止潛在和其他套件的衝突
(function(){
初始化Parse SDK();
將版型編譯(compile)並載入記憶體中();
各個View相對應的處理函數();
設定Ro...
Template Engine (doT.js)
● 解決navbar困境
● 編譯
○ var tempFn = doT.template("<h1>Here is a sample template {{=it.foo}}
</h1>");...
Router
● linkable, bookmarkable, shareable URLs for important locations in the app
● Hash vs. pushState (Why use Hash in t...
Router
● 當訪問#page/1/發生了什麼事呢?
var App = Parse.Router.extend({
routes: {
'': 'index',
'page/:page/': 'catalog',
'dress/:dres...
Router
● 讓Router活起來。
// this = window
this.Router = new App();
Parse.history.start();
Handler Function
var handlers = {
A: function(){},
B: function(){},
C: function(){},
};
vs.
var handlerA = function(){};
v...
Handler Function
與Router相關:
index: function(){
return handlers.catalog(1);
}, -> 視同瀏覽產品型錄第一頁
catalog: handlers.catalog, ->...
Handler Function (Login / Signup)
if (登入了){
重新導向到首頁();
} else {
印出登入+註冊版型();
綁定登入按鈕觸發事件(); // Parse User Object
綁定兩次密碼一致與否...
Handler Function (Login / Signup)
// 綁定登入按鈕觸發事件();
document.getElementById('loginForm').addEventListener('submit', functio...
Handler Function (Login / Signup)
// 還記得這段語法嗎?
var currentUser = Parse.User.current();
if (currentUser) {
...
}else{
...
}...
Handler Function (Login / Signup)
// 綁定兩次密碼一致與否檢查事件();
document.getElementById('singupForm_password1').
addEventListener('...
Handler Function (Login / Signup)
// 綁定註冊按鈕觸發事件();
document.getElementById('singupForm').addEventListener('submit', functi...
Handler Function (Login / Signup)
// 綁定註冊按鈕觸發事件();
// 在本地創建一個User物件
var user = new Parse.User();
// 設定帳號密碼電子郵件
user.set("u...
Handler Function (Catalog)
移動到文件最上方 // 按next時會怎麼樣?
設定分頁參數(); // pagination = skip + limit;
設定查詢參數(); // Parse Query
查詢Pars...
Handler Function (Catalog)
var handler = function(page){
// page意指現今頁數
window.scrollTo(0,0); // 移動到文件最上方
var limit = 16; /...
Handler Function (Catalog)
{success: function(results){
var objList = results.map(function(e){ return e.toJSON() }); // 將物...
Handler Function (Dress Detail)
if(有洋裝Id參數){
設定查詢參數(); // Parse Query
查詢Parse伺服器資料庫(); // 取回物件內容
印出產品細則版型();
綁定加入購物車功能(); ...
Handler Function (Dress Detail)
var handler = function(dress_id){
if(dress_id){
var Dress = Parse.Object.extend("Dress"); ...
Parse Relational Object
var John = {
‘height’: 180,
‘girlfriend’: Jenny
}
What is the relationship between John and Jenny?...
Parse Relational Object
var order = {
‘user’: <User obj>,
‘dress’: <Dress obj>,
‘amount’: 10,
}
Handler Function (Dress Detail)
document.getElementById('addToCart').addEventListener('click', function(){
var currentUser...
myCart.setAmoutTo
myCart = {
setAmountTo: function(user, dress, amount, callback){
var Order = Parse.Object.extend("Order"...
myCart.setAmoutTo
{
success: function(order){
if( amount === 0 && order ){ // 如果已經有存在的order,並收到將數量設成0的話,等於消滅order物件
order....
Handler Function (My Cart)
if (登入了){
設定查詢參數(); // Parse Query for Order
查詢Parse伺服器資料庫(); // 取回物件內容
迴圈印出各訂單並綁上修改數量和刪除的事件();...
Handler Function (My Cart)
mycart: function(){
var currentUser = Parse.User.current();
if (currentUser) {
var Order = Pars...
Handler Function (My Cart)
{
success: function (results) {
var objList = results.map(function (e) {
return {
'dressId': e....
Handler Function
// See the pattern?
function(){
預處理(); // ex: 檢查登入狀況
載入模型(); // optional
使用樣板引擎將模型顯示到browser上();
事件綁定(); ...
Privilege Issues
How to protect data?
Parse Class-Based Privilege (Data
Browser)
Ref: https://parse.com/docs/data#security-classes
Parse Class-Based Privilege (Data
Browser)
Parse ACL (more complicated!)
ACL: Access Control List
“...each object has a list of users and roles
along with what permi...
Parse ACL
{ "*":{"read":true}, "SaMpLeUsErId":{"write":
true,"read":true} }
SaMpLeUsErId 這個user可以讀寫這個物件
其他人只能讀
Parse ACL
How to make the certain ‘Order’ object
available only to the owner?
var orderACL = new Parse.ACL();
orderACL.set...
Parse ACL
Parse Store
All Source codes are available on GitHub:
https://github.com/pa4373/parsestore_js
using git to clone!
$ git cl...
More Topics…...
● Parse JavaScript Tutorial
● Parse JavaScript SDK Reference
● Pricing
● Loading indicator
● Backbone.js
○...
Introduction to Parse JavaScript SDK
Upcoming SlideShare
Loading in...5
×

Introduction to Parse JavaScript SDK

633

Published on

Published in: Engineering
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
633
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Transcript of "Introduction to Parse JavaScript SDK"

  1. 1. Parse Basic Building Web Apps WITHOUT Programming Server. http://goo.gl/8IqkAa 2014 Spring Web Programming, NCCU Author: pa4373 (Licensed by CC-By 4.0)
  2. 2. So far,你的網頁都是一成不變的 http://www.pmichaud.com/toast/ (從1994年後都沒變過)
  3. 3. 但實際上,很多網站是隨時在改變的
  4. 4. 為什麼網站可以不斷的、及時變化? 因為有後端啊。 *Web伺服器:接收http請求、產生或委派http回應並傳回client 端 *應用程式伺服器:根據使用者的請求產生相對的回應 資料庫:像一張巨大的Excel表,存各地來的資料
  5. 5. Backend Technology Stack
  6. 6. What if? 如果有一個工具可以讓我不用寫後端程式碼,但 還是可以使用後端的功能,該有多好啊......
  7. 7. Parse來拯救咧!
  8. 8. Parse是什麼 Parse是一個BaaS(Backend as Service)。 只要會用Parse提供的SDK, 還有正確的設定。開發者毋需擔 心後端的開發撰寫以及主機的擴張和維護。 這讓開發者免於開發者實現的繁瑣細節,而將高度提升到更 接近心智建模(Mental Modeling)的層級。
  9. 9. Parse開發模式概覽 Your Code Parse SDK (黑箱) Parse Cloud
  10. 10. 知道Parse SDK怎麼用就可以寫互動式網站 了(SDK還跨平台喔!) 很好很強大!
  11. 11. ● localStorage: ○ jsbin.com/rubej/1/watch?html,js,output ● Parse: ○ jsbin.com/fezuq/5/watch?html,js,output Ex: localStorage vs. Parse
  12. 12. ● Data Store ○ Database + File ● User Management ● Background Jobs ● …… ○ (see also: https://parse.com/products) What Parse can do?
  13. 13. Website vs. Web Application
  14. 14. Website vs. Web Application ● Information Oriented vs. Action Oriented ● Creation vs. Consumption ● Way of designing ● Anything else? ● http://www.visionmobile.com/blog/2013/07/web-sites-vs- web-apps-what-the-experts-think/
  15. 15. Class vs. Object (雖然JavaScript不是Class-based object- oriented programming language.) Class -> 食譜 Object (instacne) -> 菜 Class -> 藍圖 Object (instacne) -> 建築物
  16. 16. Model-View-Controller SOURCE: http://online.stanford.edu/course/developing-ios7-apps-fall-2013
  17. 17. 範例:Parse Store
  18. 18. ● 模仿 ‘GetMore 二次時尚’ (其實根本抄襲) ● 二手洋裝專賣網站 ● 能瀏覽商品、放入購物車 ● 每個使用者有自己專屬的購物車(登入才能使 用) ● 沒有結賬功能 ● http://pa4373.github.io/parsestore_js/ Parse Store
  19. 19. 商品 (Dress) 購物清單 (Order) 使用者 (User) Parse Store (Model)
  20. 20. Parse Store (View) 選單 產品型錄
  21. 21. Parse Store (View) 選單 產品細項
  22. 22. Parse Store (View) 選單 登入 & 註冊
  23. 23. ● 版型引擎 (Template Engine) ○ 解決navbar困境 ○ Template Tag -> 編譯-> 能產生HTML的JS函數 ○ 以doT.js為例 ● 路由器 (Router) ○ Facebook Photo ○ 網址和處理函數的對應 ■ ex: ‘#mycart/’ -> 處理函數1 ■ ‘#login/’ -> 處理函數2 ○ Hash (#) vs HTML5 pushState ○ Provided by Backbone.js (Parse SDK是Backbone.js的變種) ● EventListener ○ 監聽特定事件的發生,觸發行為 ○ DOM.addEventListener(事件行為, 處理函數); ○ 重複綁定? ■ https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener Parse Store (Controller)
  24. 24. Use Parse SDK
  25. 25. Use Parse SDK
  26. 26. Use Parse SDK 記下Application Key以及JavaScript Key
  27. 27. Use Parse SDK <!doctype html> <head> <meta charset="utf-8"> <title>My Parse App</title> <meta name="description" content="My Parse App"> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="css/reset.css"> <link rel="stylesheet" href="css/styles.css"> </head> <body> ……. </body> <!--匯入Parse SDK--> <script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.2.18.min.js" ></script> <script type="text/javascript"> // 初始化SDK (把你剛剛抄下來的Application ID和 JavaScript Key放上去) Parse.initialize("APPLICATION_ID", "JAVASCRIPT_KEY"); </script> </html>
  28. 28. Parse App Dashboard Analytics: App使用狀況分析 Data Browser: 瀏覽儲存App的資料庫 Cloud Code: Server Code (進階) Push Notifications: iOS、Android推播通知 Settings: App設定
  29. 29. 下載Startup Project https://github. com/pa4373/parsestore_js/archive/startkit.zip index.html css/style.css js/app.js
  30. 30. Dig into HTML. <!doctype html> ……. </body> <!--網站各個組件的版型,包在script裏面讓template engine調用(稍後回提到)--> <script id="loginTemplate" type="text/x-dot-template"> <div class='grid_6 prefix_3 suffix_3'> …… </div> </script> <!--jQuery, required by Prase SDK--> <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> <!--Prase SDK--> <script src='https://www.parsecdn.com/js/parse-1.2.18.min.js'></script> <!--doT.js, the template engine--> <script src='./js/vendors/doT.min.js'></script> <script src='./js/app.js'></script> </html>
  31. 31. Dig into JavaScript. (app.js) // 防止潛在和其他套件的衝突 (function(){ 初始化Parse SDK(); 將版型編譯(compile)並載入記憶體中(); 各個View相對應的處理函數(); 設定Router以及相對應的處理函數(); 初始化整個App(); })();
  32. 32. Template Engine (doT.js) ● 解決navbar困境 ● 編譯 ○ var tempFn = doT.template("<h1>Here is a sample template {{=it.foo}} </h1>"); ○ tempFn = function(it) { var out='<h1>Here is a sample template '+(it.foo) +'</h1>';return out; } ○ 調用doT.template是有翻譯成本的,把編譯好的存起來以供以後使用。 ● 編譯在HTML裡的版型(Little DOM Magic) ○ var tpl = document.getElementById("loginTemplate").text; ○ dot.template(tpl); ● 調用:var out = tempFN({foo: 'Sherlock'}); // <h1>Here is a sample template Sherlock</h1> ○ 把它put回HTML裡面 (Little DOM Magic) ○ document.getElementById("content").innerHTML = out; ● 語法請參考:http://olado.github.io/doT/tutorial.html#intro
  33. 33. Router ● linkable, bookmarkable, shareable URLs for important locations in the app ● Hash vs. pushState (Why use Hash in the example?) var App = Parse.Router.extend({ routes: { '': 'index', 'page/:page/': 'catalog', 'dress/:dress_id/': 'dress_detail', 'mycart/': 'mycart', 'login/*redirect': 'login', }, // If frontpage is requested, show the first page of catalog. index: function(){ return handlers.catalog(1); }, catalog: handlers.catalog, dress_detail: handlers.dress_detail, mycart: handlers.mycart, login: handlers.login, }); 路徑規則和相對應的處理函數 (從物件的其他方法找 查) 處理函數名稱以及函數本體 (匿名宣告 or 參照) :page -> 參數 function catalog (page) (*redirect也是另外一 種參數) Ref: http://backbonejs.org/#Router
  34. 34. Router ● 當訪問#page/1/發生了什麼事呢? var App = Parse.Router.extend({ routes: { '': 'index', 'page/:page/': 'catalog', 'dress/:dress_id/': 'dress_detail', 'mycart/': 'mycart', 'login/*redirect': 'login', }, // If frontpage is requested, show the first page of catalog. index: function(){ return handlers.catalog(1); }, catalog: handlers.catalog, dress_detail: handlers.dress_detail, mycart: handlers.mycart, login: handlers.login, }); 路徑匹配 呼叫handlers.catalog(1)函數。 (1 = :page) Ref: https://developer.mozilla.org/en-US/docs/Web/API/Window.onhashchange
  35. 35. Router ● 讓Router活起來。 // this = window this.Router = new App(); Parse.history.start();
  36. 36. Handler Function var handlers = { A: function(){}, B: function(){}, C: function(){}, }; vs. var handlerA = function(){}; var handlerB = function(){}; var handlerC = function(){};
  37. 37. Handler Function 與Router相關: index: function(){ return handlers.catalog(1); }, -> 視同瀏覽產品型錄第一頁 catalog: handlers.catalog, -> 顯示產品型錄 dress_detail: handlers.dress_detail, -> 顯示商品細項 mycart: handlers.mycart, -> 顯示購物車 login: handlers.login, -> 顯示 與Router無關: navbar -> 根據使用者登入與否顯示navbar內容
  38. 38. Handler Function (Login / Signup) if (登入了){ 重新導向到首頁(); } else { 印出登入+註冊版型(); 綁定登入按鈕觸發事件(); // Parse User Object 綁定兩次密碼一致與否檢查事件(); 綁定註冊按鈕觸發事件(); // Parse User Object }
  39. 39. Handler Function (Login / Signup) // 綁定登入按鈕觸發事件(); document.getElementById('loginForm').addEventListener('submit', function(){ Parse.User.logIn(document.getElementById('loginForm_username').value, document.getElementById('loginForm_password').value, { success: function(user) { // Do stuff after successful login postAction(); }, error: function(user, error) { // The login failed. Check error to see why. } }); }); /* Parse.User : Parse SDK提供的User物件,讓開發者可以簡便的建立會員機制 * Parse.User.logIn(帳號, 密碼, * {success: 登入成功的回調函數, error: 登入失敗的回調函數}); * 登入成功後,會在瀏覽器裡面留下session cookie, 可以透過Parse SDK調用的函數。 */
  40. 40. Handler Function (Login / Signup) // 還記得這段語法嗎? var currentUser = Parse.User.current(); if (currentUser) { ... }else{ ... } /* 如果使用者有登入的話,Parse.User.current()會回傳現今登入的 * 使用者物件,透過檢查物件物件的存在,我們能夠設計需要登入的函數。 */
  41. 41. Handler Function (Login / Signup) // 綁定兩次密碼一致與否檢查事件(); document.getElementById('singupForm_password1'). addEventListener('keyup', function(){ // 動態抓密碼欄的值 (Why?) var singupForm_password = document.getElementById('singupForm_password'); var message = (this.value !== singupForm_password.value) ? '密碼不一致,請再 確認一次。' : ''; document.getElementById('signupForm_message').innerHTML = message; });
  42. 42. Handler Function (Login / Signup) // 綁定註冊按鈕觸發事件(); document.getElementById('singupForm').addEventListener('submit', function(){ var user = new Parse.User(); user.set("username", document.getElementById('singupForm_username').value); user.set("password", document.getElementById('singupForm_password').value); user.set("email", document.getElementById('singupForm_emailAddress').value); user.signUp(null, { success: function(user) { postAction(); // Hooray! Let them use the app now. }, error: function(user, error) { // Show the error message somewhere and let the user try again. document.getElementById('signupForm_message').innerHTML = error.message + '['+error.code+']'; } }); }, false);
  43. 43. Handler Function (Login / Signup) // 綁定註冊按鈕觸發事件(); // 在本地創建一個User物件 var user = new Parse.User(); // 設定帳號密碼電子郵件 user.set("username", 帳號); user.set("password", 密碼); user.set("email", 電子郵件地址); /* 註冊一個新的使用者並直接登入(不用做兩次!) * 第一個null是啥? * Extra fields to set on the new user, or null. */ user.signUp(null, {success: 登入成功的回調函數, error: 登入失敗的回調函數});
  44. 44. Handler Function (Catalog) 移動到文件最上方 // 按next時會怎麼樣? 設定分頁參數(); // pagination = skip + limit; 設定查詢參數(); // Parse Query 查詢Parse伺服器資料庫(); // 取回物件列表 印出產品型錄版型(); 設定查詢參數(); // 解除所有限制 印出分頁版型(); // Parse Dress Object (為什麼晚查?) // 因為分頁版型要加附的DOM在型錄版型內
  45. 45. Handler Function (Catalog) var handler = function(page){ // page意指現今頁數 window.scrollTo(0,0); // 移動到文件最上方 var limit = 16; // 每頁顯示多少筆資料 var skip = (page-1) * limit; // 要略過多少筆之前的資料 var Dress = Parse.Object.extend("Dress"); // 取得Parse的Dress class var query = new Parse.Query(Dress); // 創建一個找查Dress的Query物件 query.limit(limit); // 設定Query條件 query.skip(skip); query.descending("createdAt"); // 按照創造時間降冪排序 // 執行query (網路連結直到此處才會觸發) query.find({success: function(results){ // 處理回傳的結果,results變數指向回傳的物件列表 ... }}); }
  46. 46. Handler Function (Catalog) {success: function(results){ var objList = results.map(function(e){ return e.toJSON() }); // 將物件列表轉化成版型能消化的格式 document.getElementById('content').innerHTML = templates.catalogTemplate(objList); // 呼叫型錄的模板函數。 query.limit(0); query.skip(0); // 設成0, 我們才能找到所有Dress object總數 var option = {}; query.count({success: function(count){ var totalPage = Math.ceil(count / limit); // Math.celi(3.1415926) = 4; var currentPage = parseInt(page); // 轉型( string => int ) option = { // Watch out the limit. 'previous': (currentPage === 1) ? 1 : currentPage-1, 'next': (currentPage === totalPage) ? currentPage : currentPage+1, // 不可以超過最前最後頁 'current': currentPage, 'last': totalPage, }; document.getElementById('pagination').innerHTML = templates.catalogPaginationTemplate(option); // 呼叫分頁的模板函數。 }, error: function(err){} }); }
  47. 47. Handler Function (Dress Detail) if(有洋裝Id參數){ 設定查詢參數(); // Parse Query 查詢Parse伺服器資料庫(); // 取回物件內容 印出產品細則版型(); 綁定加入購物車功能(); // Parse Relational Object } else { 重新導向到首頁(); }
  48. 48. Handler Function (Dress Detail) var handler = function(dress_id){ if(dress_id){ var Dress = Parse.Object.extend("Dress"); // 取得Parse的Dress class var query = new Parse.Query(Dress); // 創建一個找查Dress的Query物件 query.get(dress_id, { // 執行query,注意get方法 -> 給定物件ID, 回傳物件 success: function(dress){ document.getElementById('content').innerHTML = templates.dress_detialTemplate(dress.toJSON()); 綁定加入購物車功能 (); // 下一張slide會解釋 }, error: function(object, error){ } }); } else { window.location.hash = ''; } }
  49. 49. Parse Relational Object var John = { ‘height’: 180, ‘girlfriend’: Jenny } What is the relationship between John and Jenny? How tall is John’s girlfriend? John.girlfriend.height = 167 Why? Data Consistency. var Jenny = { ‘height’: 167, }
  50. 50. Parse Relational Object var order = { ‘user’: <User obj>, ‘dress’: <Dress obj>, ‘amount’: 10, }
  51. 51. Handler Function (Dress Detail) document.getElementById('addToCart').addEventListener('click', function(){ var currentUser = Parse.User.current(); // 檢查登入 if(currentUser){ var e = document.getElementById('amount'); var amount = parseInt(e.options[e.selectedIndex].value); myCart.setAmountTo(currentUser, dress, amount, function(){ alert("此商品已加入到您的購物車。 "); }); // 下一張slide會解釋 } else { // 重新導向到登入頁面,登入後會回到商品 window.location.hash = 'login/'+ window.location.hash; } });
  52. 52. myCart.setAmoutTo myCart = { setAmountTo: function(user, dress, amount, callback){ var Order = Parse.Object.extend("Order"); // 取得Parse的Order class // 創建一個找查Order的Query物件 var query = new Parse.Query(Order); // 設定Query條件(object的user欄位指向到給定的User object) query.equalTo('user', user); // 設定Query條件(object的dress欄位指向到給定的Dress object) query.equalTo('dress', dress); // 執行query,注意first方法 -> 給定物件ID, 回傳物件列表第一項(可能會沒有) query.first({success: 查詢成功的回調函數, error: 查詢失敗的回調函數}); }, }; /* * myCart.setAmountTo(User物件, Dress物件, 數量(int), 回調函數); */
  53. 53. myCart.setAmoutTo { success: function(order){ if( amount === 0 && order ){ // 如果已經有存在的order,並收到將數量設成0的話,等於消滅order物件 order.destroy({ // 消滅Parse物件 success: function(order){ callback(); //調用當作參數的callback函數 } }); } else { if( order === undefined ){ // 如果order還不存在,創一個新的object order = new Order(); order.set('user', user); // 指定新object的user欄位指向到給定的Dress object order.set('dress', dress); // 指定新object的dress欄位指向到給定的Dress object } order.set('amount', amount); order.save(null, { // 將新增或更改過的order object 存到Parse Server success: function(order){ callback(); } }); } }, error: function(object, err){ } }
  54. 54. Handler Function (My Cart) if (登入了){ 設定查詢參數(); // Parse Query for Order 查詢Parse伺服器資料庫(); // 取回物件內容 迴圈印出各訂單並綁上修改數量和刪除的事件(); } else { 重新導向到首頁(); }
  55. 55. Handler Function (My Cart) mycart: function(){ var currentUser = Parse.User.current(); if (currentUser) { var Order = Parse.Object.extend("Order"); var query = new Parse.Query(Order); query.equalTo('user', currentUser); query.include('dress'); query.find({success: 登入成功的回調函數 , error: 登入失敗的回調函數 }); } else { window.location.hash = 'login/'+ window.location.hash; } }
  56. 56. Handler Function (My Cart) { success: function (results) { var objList = results.map(function (e) { return { 'dressId': e.get('dress').id, 'amount': e.get('amount'), 'name': e.get('dress').get('name'), 'previewUrl': e.get('dress').get('previewUrl'), } }); document.getElementById('content').innerHTML = templates.mycartTemplate(objList); results.forEach(function (e) { var changeAmount = document.getElementById('change_amount_' + e.get('dress').id); changeAmount.addEventListener('change', function () { var amount = parseInt(this.options[this.selectedIndex].value); myCart.setAmountTo(currentUser, e.get('dress'), amount, function () {}); }); var cancelOrderBtn = document.getElementById('cancel_order_' + e.get('dress').id); cancelOrderBtn.addEventListener('click', function () { myCart.setAmountTo(currentUser, e.get('dress'), 0, function () { if (cancelOrderBtn.parentNode.parentNode.childElementCount === 1) { handlers.mycart(); } else { cancelOrderBtn.parentNode.remove(); } }); }); }); document.getElementById('payButton').parentNode.addEventListener('click', function () { alert('沒做這功能喔'); }); }, error: function (error){ }, }
  57. 57. Handler Function // See the pattern? function(){ 預處理(); // ex: 檢查登入狀況 載入模型(); // optional 使用樣板引擎將模型顯示到browser上(); 事件綁定(); // Event binding (eg. click) }; 註:這樣的設計只是參考不是絕對,應按照合理的情況去撰寫 相對應的程序
  58. 58. Privilege Issues How to protect data?
  59. 59. Parse Class-Based Privilege (Data Browser) Ref: https://parse.com/docs/data#security-classes
  60. 60. Parse Class-Based Privilege (Data Browser)
  61. 61. Parse ACL (more complicated!) ACL: Access Control List “...each object has a list of users and roles along with what permissions that user or role has...” user vs. roles Ref: https://parse.com/docs/data#security-objects
  62. 62. Parse ACL { "*":{"read":true}, "SaMpLeUsErId":{"write": true,"read":true} } SaMpLeUsErId 這個user可以讀寫這個物件 其他人只能讀
  63. 63. Parse ACL How to make the certain ‘Order’ object available only to the owner? var orderACL = new Parse.ACL(); orderACL.setPublicReadAccess(false); orderACL.setPublicWriteAccess(false); orderACL.setReadAccess(user, true); orderACL.setWriteAccess(user, true); // 附加到物件實體(instance)上 order.setACL(postACL); order.save(); Ref: http://parse.com/docs/js/symbols/Parse.ACL.html
  64. 64. Parse ACL
  65. 65. Parse Store All Source codes are available on GitHub: https://github.com/pa4373/parsestore_js using git to clone! $ git clone https://github.com/pa4373/parsestore_js.git
  66. 66. More Topics…... ● Parse JavaScript Tutorial ● Parse JavaScript SDK Reference ● Pricing ● Loading indicator ● Backbone.js ○ Data-Binding
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×