Пишем клиент для любимого сайта на phoneGap

от автора

Бывает что есть сайт, но пользоваться им с мобильного телефона не очень удобно и было бы замечательно иметь отдельное приложение для него. Любители веб разработки легко смогут это сделать использую phoneGap. Под катом речь пойдет про сервис отслеживания почтовых отправлений, которым я часто пользуюсь и написанный для него демонстрационный клиент с базовым функционалом: авторизация, получение списка треков и описания к ним и возможность добавить новый трек. Я не связывался с разработчиком по этому поводу и очень надеюсь что он на меня не обидится за наглость, за копание в JavaScript коде и за то что в приложении не будет показана реклама. Так же прошу простить за костыльность и велосипедность кода, воспринимайте его как пример.

Статья подразумевает, что вы сами сможете разобраться как работает сайт, информация с которого будет отображаться в приложении.
Те кто читали прошлую статью об авторизации через некоторые сайты уже знаю что в phoneGap есть замечательная штука inAppBrowser, которая не только открывает сайт внутри приложения, но и позволяет внедрить в него свой JavaScript код и поменять стили, что пригодится для форм авторизации.
На её основе, по образу и подобию авторизации на хабре был написан вот такой код:

var plugin_www_post_tracker_ru = { 		wwwref: false, 		authOk: false,  		auth: function (force) { 			if (!window.localStorage.getItem("plugin_www_post_tracker_ru_PHPSESSID") || force) { //если нет данных об авторизации или принудительная авторизация 				var authURL="http://post-tracker.ru/login.php"; 				this.wwwref = window.open(encodeURI(authURL), '_blank', 'location=no'); // открываем сайт внутри приложения 				this.wwwref.addEventListener('loadstop', this.auth_jsinjection); // по завершении загрузки делаем инъекцию в код 			} else { 				plugin_www_post_tracker_ru.authOk=true; 			} 		}, 		 		auth_event_url: function (url) { 			var tmp=url_parser.get_args_cookie(url); // парсин ответов с куками 			if (tmp['PHPSESSID'] && tmp['userid'] && tmp['securehash']) { // если все нужные куки есть, то видимо авторизировалис 				plugin_www_post_tracker_ru.wwwref.close(); // закроем браузер и сохраним полученные параметры 				window.localStorage.setItem("plugin_www_post_tracker_ru_PHPSESSID", tmp['PHPSESSID']); 				window.localStorage.setItem("plugin_www_post_tracker_ru_userid", tmp['userid']); 				window.localStorage.setItem("plugin_www_post_tracker_ru_securehash", tmp['securehash']); 				plugin_www_post_tracker_ru.authOk=true; 				перейдем тут на получение контента 			} 		}, 		 		auth_cssinjection: function(){ 			plugin_www_post_tracker_ru.wwwref.insertCSS({code:".topline {display:none} .top {display:none} .logo {display:none} .menu {display:none} .counters {display:none} .bottom {display:none} .links {display:none} @-viewport {width: device-width; zoom: 1;"},function(){}); 		}, 		 		auth_jsinjection: function () { 			plugin_www_post_tracker_ru.auth_cssinjection(); // вставляем CSS код в форму авторизации, для скрытия лишних блоков 			plugin_www_post_tracker_ru.wwwref.executeScript({ // JS код для получения куков 	            code: "document.cookie;" 	        }, function(arg) { 	        	plugin_www_post_tracker_ru.auth_event_url(arg); 	        }); 		} } 

Для получения контента будем использовать небольшую AJAX библиотеку, способную делать POST и GET запросы, которая умеет вставлять cookie и отдающая полученный результат в callback функцию (основа взята из miniajax):

AJAX

var ajax = { 	init: function(){ 		return new XMLHttpRequest(); 		}, 	send: function(url,method,args,cookies,async,_callback){ 		var q=ajax.init(); 		q.open(method,url,async); 		q.onreadystatechange=function(){ 				if(this.readyState==4 && this.status==200) { 					_callback(this.responseText); 				} 			}; 		if (cookies) { 			q.setRequestHeader('Cookie',cookies); 		} 		if(method=='POST') { 			q.setRequestHeader('Content-type','application/x-www-form-urlencoded'); 			q.send(args); 		} else { 			q.send(null); 		} 	} } 

Для получения контента делаем GET запрос на страничку post-tracker.ru/my/ при этом, если в ответе в одном из блоков мы встретим строку <a href="/login.php">Войдите</a> или <a href="/register.php">Зарегистрируйтесь</a>, то нас явно разлогинили и придется пройти процедуру еще раз:

		get_content: function (async) { // делам запрос на страницу с трек кодами 			var cookies="PHPSESSID="+window.localStorage.getItem("plugin_www_post_tracker_ru_PHPSESSID")+"; userid="+window.localStorage.getItem("plugin_www_post_tracker_ru_userid")+"; securehash="+window.localStorage.getItem("plugin_www_post_tracker_ru_securehash"); // формируем cookie 			plugin_www_post_tracker_ru.dataReady=false; 			ajax.send("http://post-tracker.ru/my/",'GET',null,cookies,async,this._parse_content); // делаем ajax запрос и посылаем его содержимое для распарсивания 		}, 		 		_parse_content: function (data) { 			var wrapper=document.createElement('div'); // заворачиваем html код внутрь объекта, чтобы удобнее с ним работать 				wrapper.innerHTML=data; 			plugin_www_post_tracker_ru._get_inside_data(wrapper,'trackcode,date,status,comment'); // и отправляем его на получение данных о треккоде, даты последнего изменения, статусе и описании посылки 		}, 		 		_get_inside_data: function (wrapper,types) { 			var tmp=wrapper.getElementsByClassName('login')[0].innerHTML; // на всякий случай получаем содежимое div блока login 			if (tmp=='<a href="/login.php">Войдите</a> или <a href="/register.php">Зарегистрируйтесь</a>') { // если там такое, то придется авторизироватья 				plugin_www_post_tracker_ru.auth(true); 			} else { // а иначе продолжаем 				plugin_www_post_tracker_ru.default_folder=wrapper.getElementsByTagName('input')[0].value; // получи ID стандартной папки с кодами, чтобы в дальнейшем можно было добавлять туда новые коды отправлений 				var types=types.split(","); 				for (var typeid in types) { // разбираем html-ку по блокам с заданными типами 					var tmp=wrapper.getElementsByClassName(types[typeid]); 					var id=0; 					for (var i in tmp) { 						if (tmp[i].innerHTML) { 							if (!plugin_www_post_tracker_ru.postdata[id]) plugin_www_post_tracker_ru.postdata[id]=new Array(); 							plugin_www_post_tracker_ru.postdata[id][(types[typeid])]=tmp[i].innerHTML.replace(/(\r\n|\n|\r)/gm,"").replace(/<\/?[^>]+>/gmi,"").replace(/^\s+|\s+$/gm,""); // убираем все ненужности в виде переносов строки, html кода для оформления и лишние пробелы 							id++; 						} 					} 				} 				plugin_www_post_tracker_ru.dataReady=true; 				show_list(); // даем команду на отображение полученных данных 			} 		}, 		 		get_list: function () { // это будет запрошено функцией show_list() для "красоты" оформления 			var tmp=new Array(); 			for (var i in plugin_www_post_tracker_ru.postdata) { 				tmp[i]="<b>"+plugin_www_post_tracker_ru.postdata[i]['trackcode']+"</b> "+plugin_www_post_tracker_ru.postdata[i]['comment']+"<br/>"+plugin_www_post_tracker_ru.postdata[i]['date']+" "+plugin_www_post_tracker_ru.postdata[i]['status']; 			} 			return tmp; 		} 

show_list() в данном коде добавит блоки с подготовленной html-кой внтури div-а со скроллером (кстати рекомендую Overthrow и крайне не рекомендую iscroll-4 по причине ужасной скорости работы).

Настала пора добавить возможность отправки новых кодов для отслеживания, но сперва добавим действие на кнопку MENU вашего Android смартфона. Делается это с помощью события menubutton. К которому мы привяжем появления блока с кнопкой «Добавить трек код», которая, при нажатии, начнет процесс.

		put_trackCode: function(){ // то что будет выполнятя после нажатия на кнопку "Добавить трек код" 			var trackCode = prompt("Введите трек код"); // запросим у пользователя сам треккод 			if (trackCode) { 				this._put_trackCode_getPath(trackCode); // запросим у сайта направление для этого кода (например из Китая в Россию), внимание тут снова не используем асинхронный запрос 				if (plugin_www_post_tracker_ru.default_path) { // если получили направление, добавим описание 					var comment = prompt("комментарий"); 					if (comment) { 						this._put_trackCode(trackCode,comment); // и отправим эти данные на сайт 					} 				} else { 					alert("Не правильный трек код"); 				} 			} else { 				menuButtonHide(); // если пользователь не захотел вводить, то не забудем скрыть блок с менюшкой 			} 		}, 		_put_trackCode_getPath: function (trackCode) { // запрашиваем направление 			var cookies="PHPSESSID="+window.localStorage.getItem("plugin_www_post_tracker_ru_PHPSESSID")+"; userid="+window.localStorage.getItem("plugin_www_post_tracker_ru_userid")+"; securehash="+window.localStorage.getItem("plugin_www_post_tracker_ru_securehash"); 			var data="act=getPathForm&trackcode="+encodeURIComponent(trackCode); 			ajax.send("http://post-tracker.ru/ajax/userTrackcodes.php",'POST',data,cookies,false,this._put_trackCode_getPath_result);			 		}, 		_put_trackCode_getPath_result: function (data){ 			var wrapper=document.createElement('div'); // заворачиваем ответ, представляющий собой html 			wrapper.innerHTML=data; 			var tmp=wrapper.getElementsByTagName('input'); // смотрим есть ли в ответе input 			if (tmp.length>0) { 				plugin_www_post_tracker_ru.default_path=tmp[0].value; // если есть, то значение в нем нам очень пригодится 			}else{ 				plugin_www_post_tracker_ru.default_path=false; 			} 		}, 		_put_trackCode: function (trackCode,comment){ // отправляем треко код и комментарий к нему, снова не асинхронно 			var cookies="PHPSESSID="+window.localStorage.getItem("plugin_www_post_tracker_ru_PHPSESSID")+"; userid="+window.localStorage.getItem("plugin_www_post_tracker_ru_userid")+"; securehash="+window.localStorage.getItem("plugin_www_post_tracker_ru_securehash"); 			var data="act=addTrackcodeAction&folderid="+plugin_www_post_tracker_ru.default_folder+"&trackcode="+encodeURIComponent(trackCode)+"&path="+plugin_www_post_tracker_ru.default_path+"&comment="+encodeURIComponent(comment); 			ajax.send("http://post-tracker.ru/ajax/userTrackcodes.php",'POST',data,cookies,false,this._put_trackCode_result); 		}, 		_put_trackCode_result: function(data){ // данные отправились 			menuButtonHide(); // скрываем меню 			plugin_www_post_tracker_ru.get_content(true); // и снова запрашиваем содержимое страницы с кодами посылок 		} 

Что бы еще можно было бы добавить к приложение, чтобы потренироваться с phoneGap? В первую очередь не помешает локализация, чтобы в коде не хранился текст и для разных стран не выводился только русский язык. Так же не помешает отрабатывать некоторые состояния, например пропажу интернет соединения или нажатие на кнопку «назад».
В плане самого сервиса отслеживания, стоило бы добавит рекламу, на которую содержится ресурс, а так же увеличить функционал, добавив создание папок, автоматическую проверку с оповещениями и свистелкопезвуковыми эффектами.

Исходный код проекта и собранное приложение для тестов и экспериментов заинтересованных лиц.

Продолжать ли писать о phoneGap и эксперименты с ним?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Никто ещё не голосовал. Воздержавшихся нет.

ссылка на оригинал статьи http://habrahabr.ru/post/181610/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *