Centro Estadual de Educação Tecnológica Paula Souza Faculdade de Tecnologia da Zona Sul Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas BLACKBOARD Como desenvolver aplicativos para o Firefox OS Nicholas Camp Barcellos RA 1370481111242 São Paulo 2014 2 SUMÁRIO Introdução …............................................................................................................... 3 Metodologia …............................................................................................................ 4 1. Primeiros passos .................................................................................................... 5 2. Organização do ambiente …................................................................................... 6 3. Desenvolvendo o Blackboard ............................................................................... 10 Conclusão ................................................................................................................. 22 Referências .............................................................................................................. 23 3 INTRODUÇÃO O Firefox OS é um novo Sistema Operacional desenvolvido pela Mozilla & sua comunidade de desenvolvedores para dispositivos móveis. É baseado no navegador Mozilla Firefox e em tecnologias livres e abertas, como HTML, CSS, JavaScript e Linux. Ter o seu aplicativo em múltiplos sistemas operacionais costumava ser algo trabalhoso. Cada um deles possui sua linguagem – Java no Android, Objective C no iOS. Desta forma, para a criação de aplicativos nativos, era preciso pensar também em como portabilizar o código para as outras plataformas. O paradigma do Firefox OS mostra que a web é a plataforma, sendo assim, aplicativos devem ser instalados no dispositivo a partir dela mesma. São conhecidos como aplicativos da web aberta, open web apps. Este trabalho trata de explicar como cadastrar um aplicativo no Firefox Marketplace passo a passo, descrevendo todo o processo até esta etapa: desde os recursos utilizados (como um framework de front-end, biblioteca utilizada que facilita o início da codificação e fontes baixadas de “baús” de fontes) até os códigos escritos. 4 METODOLOGIA Este trabalho foi feito através do levantamento de diversos materiais e artigos disponíveis na internet a respeito do Firefox OS e da criação/conversão de aplicações em aplicativos. Artigos principalmente da Mozilla Developer Network (https://developer.mozilla.org/). Até o momento no qual foi escrito, haviam poucas informações e materiais na internet disponíveis para criação de um aplicativo, do início ao fim, para o Firefox OS, tal qual é o objetivo deste trabalho. Além disso, com a introdução da internet móvel em mercados emergentes com o Firefox OS, este documento, por explicar detalhadamente cada módulo do aplicativo, pode vir a ser o primeiro contato com o desenvolvimento de ideia/projeto/conteúdo/código com a web. Há disponível no Firefox Marketplace alguns milhares de aplicativos, quantidade ainda bastante pequena, se comparada ao milhão disponível nos Sistemas Operacionais Android e iOS. Este documento visa também a popularização do desenvolvimento da web e de aplicativos da web aberta. 5 1. PRIMEIROS PASSOS Antes de começar a desenvolver um aplicativo, é necessário ter uma ideia do que gostaria de ser feito. Essa ideia pode vir observando o funcionamento de outros aplicativos, procurando funcionalidades não disponíveis no dispositivo, no banho ou durante uma conversa. Tendo a ideia, passa-se à etapa de desenvolvimento. Aplicativos para o Firefox OS são feitos assim como páginas da web: com HTML (Hyper Text Markup Language), CSS (Cascading Style Sheets) e JS (JavaScript). HTML é linguagem de marcação de conteúdo, CSS, de estilização, e JS, de manipulação. Além destas, é importantíssimo conhecimento intermediário de inglês. Essas são as linguagens que precisa-se aprender a “falar” para desenvolver aplicativos para o Firefox OS e para a web. Este trabalho tem como intuito caminhar pelas etapas de desenvolvimento de um aplicativo, neste caso o Blackboard. 6 2. ORGANIZAÇÃO DO AMBIENTE Como aplicativos para o Firefox OS são feitos utilizando HTML, CSS e JS, utiliza-se um modelo, um template, para basear a aplicação e evitar repetição de código a cada novo projeto. Como ainda não há um modelo específico para o Firefox OS, pode-se usar o HTML5 Boilerplate (http://www.html5boilerplate.com/). É a mesma base que muitos desenvolvedores front-end (aquele que mexe com HTML, CSS e JS – que trabalha a interface) utilizam para desenvolver sites. Abrindo o modelo, vemos a seguinte estrutura: Figura 1: Estrutura do HTML5 Boilerplate Fonte: Colaborado pelo autor, 2014 A pasta doc pode ser apagada, pois contém manual do modelo HTML5 Boilerplate (não requerido pelo aplicativo). Nas pastas css, img e js ficarão, respectivamente, o CSS, as imagens e o JS. O Blackboard não utilizará os arquivos 404.html, appletouch-icon-precomposed.png, CHANGELOG.md, CONTRIBUTING.md, 7 crossdomain.xml, LICENSE.md, README.md e robots.txt; podem ser deletados. Juntamente com todos os arquivos da pasta js – o JS será escrito desde o ínicio. Na pasta css, copiar o conteúdo do arquivo normalize.css (serve para dar consistência de renderização aos elementos entre navegadores. Semelhante aos CSS reset) e colar no início do main.css. Dessa forma usa-se menos uma requisição, a qual é custosa para o navegador (mais informações: https://stackoverflow.com/questions/9855545/http-requests-vs-file-size). Feito, abrir a index.html com um editor de código. O autor utiliza o Sublime Text 3 (http://www.sublimetext.com/3). Remover os if da tag html – necessários somente ao desenvolvimento para o Internet Explorer. Deixar somente <html>. As referências ao normalize e ao modernizr não são necessárias – o normalize foi agregado ao main.css e o modernizr, utilizado para detectar funcionalidades dos navegadores, não será utilizado. Definir o <title> como Blackboard e apagar todo o conteúdo dentro do body. A página está assim: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Blackboard</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="css/main.css"> </head> <body></body> </html> Agora, para transformar o pacote num aplicativo para o Firefox OS, basta criar, na raiz do projeto, ao lado da index.html, o manifest.webapp: { "name": "Blackboard", "description": "Paint the board", "launch_path": "/index.html", "icons": { "128": "/img/icon-128.png" }, "developer": { 8 "name": "Nicholas Camp Barcellos", "url": "http://nicholascamp.com.br" }, "default_locale": "en" } Este arquivo especifica as informações do aplicativo e do autor, tais como nome, descrição, ícone e contato com o desenvolvedor. Sendo assim, temos um aplicativo. Mais informações e outros parâmetros de especificação do App Manifest podem ser encontrados aqui: App manifest https://developer.mozilla.org/en- US/Apps/Build/Manifest. A partir da versão 26 do navegador Mozilla Firefox, é possível simular o Firefox OS dentro dele. Para isso, basta ir em configurações (ícone ≡, no canto direito superior), desenvolvedor e gerenciador de aplicativos. Lá há opção de conectar seu Firefox OS ou rodar o simulador. Neste trabalho, faz-se a última opção. Aberto o simulador do Firefox OS, tem-se a interface do Sistema Operacional, com grande parte de suas funcionalidades, tais como navegador, mensagens, relógio, configurações. Pode-se inclusive fazer a instalação de aplicativos. Para isso, voltar para a janela anterior (que abriu o simulador), clicar na aba Apps e adicionar a pasta aonde se encontra o aplicativo. Assim, o aplicativo é instalado e seu ícone aparece ao lado dos outros no simulador: 9 Figura 2: Blackboard instalado no simulador Fonte: Colaborado pelo autor, 2014 10 3. DESENVOLVIMENTO DO APLICATIVO O Blackboard é uma lousa. Suas funcionalidades consistem em pintá-la com diversas cores e mudar a grossura da linha. Agora se trata de desenvolver essas funcionalidades. Introduzir no body a tag canvas, com id e class blackboard. id para manipular o JavaScript, class para o CSS. Em HTML5, a tag canvas é responsável por renderizar gráficos e outras imagens. No Blackboard, é a própria lousa. No CSS, definir para a classe blackboard background: #000. Tem-se então uma lousa preta. Criar script chamado blackboard.js na pasta js. Inserir no HTML a tag script e apontar o atributo src para o arquivo recém criado. Inserir então no arquivo o objeto app, responsável pela estruturação das propriedades e métodos do aplicativo: var app = { blackboard: document.getElementById('blackboard'), ctx: this.blackboard.getContext('2d'), lineColor: '#fff', // default color lineThickness: 4, ongoingTouches: [], // touches in-progress startup: function () { app.blackboard.width = window.innerWidth; app.blackboard.height = window.innerHeight; app.blackboard.addEventListener('touchstart', handleTStart, false); // app.blackboard.addEventListener('touchcancel', handleTCancel, false); app.blackboard.addEventListener('touchmove', handleTMove, false); app.blackboard.addEventListener('touchend', handleTEnd, false); app.blackboard.addEventListener('touchleave', handleTEnd, false); } } document.addEventListener('DOMContentLoaded', app.startup); 11 Foi definido a propriedade blackboard, que captura a tag canvas pelo id. ctx define o contexto 2d da lousa, no qual desenha-se. LineColor e lineThickness definem a cor e a grossura da linha, respectivamente. ongoingTouches para registrar os toques, trabalhado e, em seguida, startup, método de inicialização da aplicação, que define a largura e altura da lousa para a largura do dispositivo e adiciona EventListeners de toque à app.blackboard. Em JavaScript, manipula-se os eventos de toque – iniciar, cancelar, mover, terminar e deixar – com os EventListeners touchstart, touchcancel, touchmove, touchend e touchleave, respectivamente. Então, depois que o documento estiver carregado (DOMContentLoaded), executa-se a função startup de app. Agora é necessário definir as 3 funções adicionadas aos eventos de toque, handleTStart, handleTMove e handleTEnd. handleTStart(): function handleTStart(evt) { evt.preventDefault(); var touches = evt.changedTouches; var i = 0; var len = touches.length; for(; i < len; i++) { app.ongoingTouches.push(touches[i]); app.ctx.beginPath(); app.ctx.arc(touches[i].pageX, touches[i].pageY, app.lineThickness, 0, 2*Math.PI, false); // a circle app.ctx.fillStyle = app.lineColor; app.ctx.fill(); } } A primeira linha da função impede a ação padrão do toque (caso fosse um botão, preveniria a mudança de página, ou limpar campos de um formulário, etc). A variável touches registra por meio de um identificador único todos os dados referente a cada toque (se o dispositivo suporta múltiplos toques – múltiplos objetos dentro da variável, que é um array de objetos –, será criado um para cada toque). A ordem dos toques, que começa em 0, é estabelecida de acordo com o contato de cada toque simultâneo na tela. 12 Após temos as variáveis i e len, cacheadas para otimizar a performance do laço for. Nele, itera-se (inicia e termina o laço, recomeçando-o) por cada touches, e, a seguir, a explicação de cada linha deste laço: 1. adiciona-se a app.ongoingTopuches o objeto do toque em questão (o qual contém todas suas informações); 2. beginPath() cria um novo caminho a ser desenhado; 3. arc() cria um arco, no caso, um círculo: o primeiro parâmetro representa o ponto x onde o arco começará a ser traçado, o segundo, o ponto y, o terceiro, o raio, o quarto, o ângulo inicial, o quinto, o ângulo final e, finalmente, o sexto, boolean referente ao sentido dos ponteiros do relógio – anti-horário, verdadeiro, horário, falso; 4. fillStyle é usado para determinar uma cor para o path; 5. E fill() é usado para preencher a área do path. Assim, quando clicamos na tela, desenha-se pontos (ainda que não segmentados) brancos (que é a cor definida em app.lineColor): 13 Figura 3: Pontos brancos desenhados na tela Fonte: Colaborado pelo autor, 2014 Terminada handleTStart(), para a função handleTMove(). Até o laço for da função, foi definido o mesmo que em handleTStart(), portanto, para breviedade, expõe-se somente o conteúdo dentro do for: var idx = ongoingTouchIndexById(touches[i].identifier); // There's a touch? if(idx >= 0) { app.ctx.beginPath(); app.ctx.moveTo(app.ongoingTouches[idx].pageX, app.ongoingTouches[idx].pageY); app.ctx.lineTo(touches[i].pageX, touches[i].pageY); app.ctx.lineWidth = app.lineThickness; app.ctx.strokeStyle = app.lineColor; app.ctx.stroke(); app.ongoingTouches.splice(idx, 1, touches[i]); // swap in the new touch record } Fora do escopo da função, ongoingTouchIndexById(), função usada por idx: function ongoingTouchIndexById(idToFind) { var i = 0; var len = app.ongoingTouches.length; for(; i < len; i++) { 14 var id = app.ongoingTouches[i].identifier; if (id === idToFind) { return i; } } return -1; // not found } A função ongoingTouchIndexById() captura o idenficador único do touch em questão (idToFind) para abstrair suas informações, que estão armazenadas em app.ongoingTouches, sendo armazenado na variável idx. Como é um array, inicia do zero, por isso a verificação do if >= 0. Então temos: 1. o início do path; 2. a movimentação do dedo representada pelo método moveTo(), que pede os eixos x e y; 3. lineTo(), que pede os mesmos eixos x e y, ou seja, é feita uma linha do ponto anterior até o ponto atual; 4. lineThickness(), que define a largura da linha; 5. strokeStyle(), que define a cor do preenchimento; 6. stroke(), que preenche a linha com a estilo definido; 7. o método splice(), que troca o ponto idx anterior pelo novo touches[i]. A função handleTEnd() também tem o mesmo início das anteriores; difere o conteúdo do for: var idx = ongoingTouchIndexById(touches[i].identifier); // There's a touch? if(idx >= 0) { app.ctx.beginPath(); app.ctx.moveTo(app.ongoingTouches[idx].pageX, app.ongoingTouches[idx].pageY); app.ctx.lineTo(touches[i].pageX, touches[i].pageY); app.ctx.arc(touches[i].pageX, touches[i].pageY, app.lineThickness / 2, 0, 2 * Math.PI, false); app.ctx.fillStyle = app.lineColor; app.ctx.fill(); app.ongoingTouches.splice(idx, 1); // remove it; we're done 15 } idx captura o idenficador único do touch em questão, passado o if, temos o início do path, a movimentação e a linha até o ponto, o arco (círculo, como definido em handleTStart()), preenchendo-o com a cor definida, e então, a remoção do ponto com o método splice(), fechando o ciclo. Agora é possível desenhar continuamente na lousa! Figura 4: Desenhando na lousa Fonte: Colaborado pelo autor, 2014 A próxima etapa é adicionar cores à Blackboard. Adicione ao body uma lista com o atributo data-color com as cores que você desejar: <ul id="colors" class="colors"> <li data-color="#FFFFFF"></li> <li data-color="#CCCCCC"></li> <li data-color="#000000"></li> <li data-color="#C90000"></li> <li data-color="#2111B9"></li> <li data-color="#01AC11"></li> <li data-color="#FFFF00"></li> <li data-color="#005ED2"></li> <li data-color="#E65700"></li> <li data-color="#9E005D"></li> <!-- <li class="more-colors">+</li> --> </ul> 16 Para estilizá-la: .colors { bottom: 3%; left: 3%; margin: 0 0 -5px -5px; padding: 0; position: absolute; } .colors li { border: 1px solid #666; border-radius: 50%; cursor: pointer; display: inline-block; height: 12px; margin: 5px; width: 12px; } Dessa forma temos ícones redondos lado a lado. Adicionar a app.startup a chamada à função colors(), definida a seguir: function colors() { var colors = document.getElementById('colors'); var li = colors.getElementsByTagName('li'); var i = 0; var len = li.length; for(; i < len; i++) { var color = li[i].getAttribute('data-color'); li[i].style.backgroundColor = color; } colors.addEventListener('click', function (evt) { var color = evt.target.getAttribute('data-color'); app.lineColor = color; }); } Faz-se referência à lista de cores nas duas primeiras variáveis, itera-se sobre cada uma delas no laço, aonde captura-se o atributo data-color da li e o adiciona ao backgroundColor. Fora do laço, adiciona-se um EventListener de click à lista, aonde captura-se o atributo data-color do objeto clicado e atribui-o à cor da linha. Legal, não é? Agora é possível mudar a cor do tracejado. 17 Figura 5: Desenhando com várias cores Fonte: Colaborado pelo autor, 2014 Blackboard está quase pronta, falta adicionar a funcionalidade de mudar a grossura da linha. Para isso, adiciona-se o elemento de lista não ordenada, ul, ao documento: <ul class="line-thickness"> <li id="thinner-line" class="thinner-line"></li> <li id="thicker-line" class="thicker-line"></li> </ul> E o CSS, para posicioná-lo no canto direito superior: .colors { bottom: 3%; left: 3%; margin: 0 0 -12px -5px; padding: 0; position: absolute; } .colors li, .line-thickness li { border: 1px solid #333; border-radius: 50%; cursor: pointer; display: inline-block; height: 12px; margin: 5px; width: 12px; } .line-thickness { margin: -7px -5px 0 0; padding: 0; position: absolute; right: 3%; top: 3%; } .line-thickness li { background: url(../img/line-thickness.png); backgroundsize: 24px; } .line-thickness .thicker-line { background-position: right 0; } Foi adicionado uma imagem para representar o tracejado menor e maior. A junção de uma ou mais imagens em uma chama-se sprite (http://www.maujor.com/tutorial/css-sprites.php) – serve para economizar requisições 18 de arquivos. Foi utilizado background-size para diminuir o tamanho da imagem em relação ao tamanho do círculo, 12x12px. Esta é a imagem utilizada para representar o tracejado menor e maior, respectivamente: Figura 6: line-thickness.png (ampliada) Fonte: Colaborado pelo autor, 2014 Agora o JavaScript: function lineThickness() { var plusBtn = document.getElementById('thicker-line'); var lessBtn = document.getElementById('thinner-line'); plusBtn.addEventListener('click', function () { console.log('+1'); app.lineThickness += 1; }); lessBtn.addEventListener('click', function () { if (app.lineThickness > 1) { console.log('-1'); app.lineThickness -= 1; } }); } 19 Figura 7: Funcionalidade de espessura da linha implementada Fonte: Colaborado pelo autor, 2014 Captura-se os elementos de aumentar e diminuir a espessura da linha e adiciona-se EventListeners de clique, que aumentam e diminuem o valor de app.lineThickness. Lembre-se de adicionar à app.startup a chamada à função, como em colors(). Pronto! Pode-se terminar por aqui. Mas pode-se ainda escrever o nome do Blackboard no canto esquerdo superior e, ao mudar a cor da linha, mudar o nome da cor em Blackboard, ou seja, mudando para branco, tem-se escrito Whiteboard. Assim tem-se uma representação da cor ativa do Blackboard. Para isso, precisamos adicionar o título Blackboard ao documento, buscar uma fonte adequada, embuti-la no CSS, alterar a função colors() e adicionar os nomes das cores à lista de cores. <h1><span id="color-board">Black</span>board</h1> Adicionada a logo ao body. Nenhuma fonte padrão do sistema representou bem o Blackboard, então foi buscada uma em FontSquirrel: HVD Comic Serif Pro http://www.fontsquirrel.com/fonts/HVD-Comic-Serif-Pro. Baixar somente o formato woff, formato livre, que é usado pelo Firefox. Criar uma pasta chamada font na raiz do aplicativo e adicionar a fonte à ela. 20 Adicionar o CSS gerado ao main.css, excluir os src não utilizados (.eot, .svg, etc) e mudar a url de acordo com a pasta aonde se encontra a fonte: @font-face { font-family: 'HVD Comic'; src: url('../font/HVD_Comic_Serif_Pro-webfont.woff') format('woff'); font-weight: normal; font-style: normal; } Adicionar também o CSS para o título: h1 { color: #000; font: 30px/1 'HVD Comic', sans-serif; left: 3%; margin: 0; position: absolute; text-shadow: 0 0 1px #ddd; top: 2%; } Figura 8: Logo do aplicativo Fonte: Colaborado pelo autor, 2014 Agora, adicionar os respectivos nomes das cores à lista de cores: <li <li <li <li <li <li <li <li <li <li data-color="#FFFFFF" data-color="#CCCCCC" data-color="#000000" data-color="#C90000" data-color="#2111B9" data-color="#01AC11" data-color="#FFFF00" data-color="#005ED2" data-color="#E65700" data-color="#9E005D" data-name="White"></li> data-name="Grey"></li> data-name="Black"></li> data-name="Red"></li> data-name="Blue"></li> data-name="Green"></li> data-name="Yellow"></li> data-name="LightBlue"></li> data-name="Orange"></li> data-name="Pink"></li> No JavaScript é preciso capturar também o atributo data-name e escrevê-lo no span#color-board, da logo. As linhas adicionadas à função para isso estão em negrito: function colors() { var colorNameInLogo = document.getElementById('color-board'); var colors = document.getElementById('colors'); var li = colors.getElementsByTagName('li'); 21 var i = 0; var len = li.length; for(; i < len; i++) { var color = li[i].getAttribute('data-color'); li[i].style.backgroundColor = color; } colors.addEventListener('click', function (evt) { var color = evt.target.getAttribute('data-color'); var name = evt.target.getAttribute('data-name'); app.lineColor = color; colorNameInLogo.innerHTML = name; colorNameInLogo.style.color = color; }); } Agora, quando a cor da linha é alterada, é alterada também o nome da cor em Blackboard. O Blackboard, independentemente da cor ativa, continua preta, porém representa, por meio da logo, visual e textualmente a cor da linha ativa. Assim, terminamos o aplicativo. Figura 9: Desenhando com o Blackboard Fonte: Colaborado pelo autor, 2014 Dica: para salvar o desenho utilizando o Firefox OS, pressione o botão de travar a tela simultaneamente com o botão de início. 22 O Blackboard pode ser encontrada no Firefox Marketplace. Este trabalho, assim como o aplicativo, é código aberto, https://github.com/nicholascamp/Blackboard. e está disponível no Github: 23 CONCLUSÃO O Firefox OS é um Sistema Operacional produto da web, que veio trazer a web livre para os dispositivos móveis. Utiliza, em si e em seus aplicativos, as mesmas tecnologias de desenvolvimento de aplicativos que a web utiliza para desenvolver sites. Não há um filtro, um impecílio, uma outra linguagem pela qual o aplicativo tem que passar, diferentemente dos Sistemas Operacionais concorrentes. Como o Firefox OS utiliza tecnologias livres e abertas, já conhecidas por desenvolvedores web, é fácil populá-lo de aplicativos e melhorá-lo. A beleza do Sistema Operacional se vê em sua extensionalidade. Além dos aplicativos serem feitos utilizando estas tecnologias livres, toda a interface gráfica também é, portanto trata-se de algo facilmente expansível e customizável. Foi visto neste documento que, tecnicamente, não é algo de dificuldade elevada desenvolver aplicativos para o Sistema Operacional e, inclusive, não requer muita habilidade e conhecimento em programação. Sendo assim, basta interesse e curiosidade para desenvolver aplicativos. Mais pra frente, pode vir a tornar-se um grande Sistema Operacional, utilizado tanto em dispositivos móveis (óculos, celulares e tabletes), quanto nos fixos (computadores de mesa, geladeiras e televisões). 24 REFERÊNCIAS Mozilla Developer Network. Touch events. Disponível em: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Touch_events. Acesso em: 12/04/14. Mozilla Developer Network. TouchEvent. Disponível em: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent. Acesso em: 13/04/14 Mozilla Developer Network. EventListener. Disponível em: https://developer.mozilla.org/en-US/docs/Web/API/EventListener. Acesso em: 14/04/14 Mozilla Developer Network. Touch. Disponível em: https://developer.mozilla.org/enUS/docs/Web/API/Touch. Acesso em: 15/04/14 Mozilla Developer Network. App manifest. Disponível em: https://developer.mozilla.org/en-US/Apps/Build/Manifest. Acesso em: 16/04/14 Mozilla Developer Network. Drawing Shapes. Disponível em: https://developer.mozilla.org/enUS/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes. Acesso em: 17/04/14 Font Squirrel. Disponível em: http://www.fontsquirrel.com/. Acesso em: 28/04/14