Несколько дней назад я написал о том, как 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. Но в целом я думаю, вы поняли идею.
Во всяком случае, я надеюсь, что это полезно для людей. Я скопировал копию этого приложения и прикрепил его к записи в блоге.

