Несколько дней назад я написал о том, как JavaScript API Parse теперь позволяет загружать файлы через их SDK. Демонстрация, которую я построил, была очень быстрой и простой, и, хотя в ней использовался PhoneGap, он не был хорошим примером совместной технологии. Прежде, чем я говорил о Parse на PhoneGap Day (видимо, скоро будут опубликованы видео, я поделюсь ими, когда они появятся), я привел немного более хороший пример. Давайте взглянем.
Мой пример (извините) еще один пример приложения для заметок. Однако на этот раз я добавил возможность прикреплять картинки к заметке. Главный экран — это список ваших текущих заметок, отсортированный по дате.
Нажав на символ плюса, вы попадете в форму, позволяющую написать новую заметку.
На данный момент вы можете сделать снимок. Теперь — в целях тестирования в моем симуляторе iOS я установил источник в локальной файловой системе. В реальном приложении вы бы запрашивали саму камеру (или позволяли пользователю выбирать), но я хотел что-то быстрое и грязное.
Как только вы нажмете Сохранить, мы создадим новый объект Note в Parse. Код должен определить, сделали ли вы фотографию или нет, и будет ли она обрабатывать загрузку для вас. Теперь давайте посмотрим на код.
Сначала — домашняя страница. Я использую jQuery Mobile для приложения и разместил обе «страницы» в основном index.html. Так как в этом есть некоторая путаница, позвольте мне быть абсолютно ясным. JQuery Mobile не заставляет вас использовать одну HTML-страницу. Период. В таком случае, когда у меня есть небольшое приложение (2 страницы), тогда для меня имеет смысл включить их в один HTML-файл. Это был на 100% личный выбор, и jQuery Mobile не заставил меня сделать это.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title></title> <meta name = "format-detection" content = "telephone=no"/> <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width"> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" /> <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> <script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script> <script type="text/javascript" src="cordova.js"></script> <script src="js/parse-1.2.8.min.js"></script> <script src="js/app.js"></script> <style> div[data-role=content] img { max-width: 200px; } </style> </head> <body> <div data-role="page" id="home"> <div data-role="header" data-position="fixed"> <a href="#addNote" data-icon="plus" data-iconpos="notext" class="ui-btn-right">Add</a> <h1>Notebook</h1> </div> <div data-role="content"> </div> </div> <div data-role="page" id="addNote"> <div data-role="header"> <a href="#home" data-icon="home" data-iconpos="notext">Home</a> <h1>Notebook</h1> </div> <div data-role="content"> <h2>Add Note</h2> <textarea id="noteText"></textarea> <button id="takePicBtn">Add Pic</button> <button id="saveNoteBtn">Save</button> </div> </div> </body> </html>
HTML здесь довольно прост, так как почти весь контент динамический. Теперь давайте посмотрим на app.js.
var parseAPPID = "supersecret"; var parseJSID = "mybankpinis1234"; //Initialize Parse Parse.initialize(parseAPPID,parseJSID); var NoteOb = Parse.Object.extend("Note"); $(document).on("pageshow", "#home", function(e, ui) { $.mobile.loading("show"); var query = new Parse.Query(NoteOb); query.limit(10); query.descending("createdAt"); query.find({ success:function(results) { $.mobile.loading("hide"); var s = ""; for(var i=0; i<results.length; i++) { //Lame - should be using a template s += "<p>"; s += "<h3>Note " + results[i].createdAt + "</h3>"; s += results[i].get("text"); var pic = results[i].get("picture"); if(pic) { s += "<br/><img src='" + pic.url() + "'>"; } s += "</p>"; } $("#home div[data-role=content]").html(s); },error:function(e) { $.mobile.loading("hide"); } }); }); $(document).on("pageshow", "#addNote", function(e, ui) { var imagedata = ""; $("#saveNoteBtn").on("touchend", function(e) { e.preventDefault(); $(this).attr("disabled","disabled").button("refresh"); var noteText = $("#noteText").val(); if(noteText == '') return; /* A bit complex - we have to handle an optional pic save */ if(imagedata != "") { var parseFile = new Parse.File("mypic.jpg", {base64:imagedata}); console.log(parseFile); parseFile.save().then(function() { var note = new NoteOb(); note.set("text",noteText); note.set("picture",parseFile); note.save(null, { success:function(ob) { $.mobile.changePage("#home"); }, error:function(e) { console.log("Oh crap", e); } }); cleanUp(); }, function(error) { console.log("Error"); console.log(error); }); } else { var note = new NoteOb(); note.set("text",noteText); note.save(null, { success:function(ob) { $.mobile.changePage("#home"); }, error:function(e) { console.log("Oh crap", e); } }); cleanUp(); } }); $("#takePicBtn").on("click", function(e) { e.preventDefault(); navigator.camera.getPicture(gotPic, failHandler, {quality:50, destinationType:navigator.camera.DestinationType.DATA_URL, sourceType:navigator.camera.PictureSourceType.PHOTOLIBRARY}); }); function gotPic(data) { console.log('got here'); imagedata = data; $("#takePicBtn").text("Picture Taken!").button("refresh"); } function failHandler(e) { alert("ErrorFromC"); alert(e); console.log(e.toString()); } function cleanUp() { imagedata = ""; $("#saveNoteBtn").removeAttr("disabled").button("refresh"); $("#noteText").val(""); $("#takePicBtn").text("Add Pic").button("refresh"); } });
Сначала взгляните на событие pagehow для #home. Здесь мы получаем данные из Parse. Это делается с помощью простого запроса, который упорядочивает при создании объекта. Я ограничил счет до 10, и если бы я хотел, мог бы добавить пейджинг.
Логика addNote немного сложнее. Сохранение данных анализа выполняется асинхронно, поэтому, если нам нужно сохранить файл, у нас есть два, а не один, асинхронных вызова. Отсюда большой блок IF, который проверяет, есть ли у нас уже выбранное изображение. Честно говоря, это может быть сделано немного лучше, возможно. Например, первоначальное создание объекта Note может быть определенно исключено из предложения IF, а также строки, в которой я устанавливаю свойство text. Но в целом я думаю, вы поняли идею.
Во всяком случае, я надеюсь, что это полезно для людей. Я скопировал копию этого приложения и прикрепил его к записи в блоге.