José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e...

159
José Manuel Gonçalves Alves Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web José Manuel Gonçalves Alves Outubro de 2010 UMinho | 2010 Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web Universidade do Minho Escola de Engenharia

Transcript of José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e...

Page 1: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

José Manuel Gonçalves Alves

Desenvolvimento de um sistema dinâmicode georeferenciação de conteúdos web

Jos

é M

anue

l Gon

çalve

s Al

ves

Outubro de 2010UMin

ho |

201

0De

senv

olvi

men

to d

e um

sis

tem

a di

nâm

ico

de g

eore

fere

ncia

ção

de c

onte

údos

web

Universidade do MinhoEscola de Engenharia

Page 2: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

Outubro de 2010

Dissertação de MestradoCiclo de Estudos Integrados Conducentes aoGrau de Mestre em Engenharia Electrónica Industrial e Computadores

Trabalho efectuado sob a orientação doProfessor Doutor José Mendes

José Manuel Gonçalves Alves

Desenvolvimento de um sistema dinâmicode georeferenciação de conteúdos web

Universidade do MinhoEscola de Engenharia

Page 3: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

i

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Agradecimentos

Antes de tudo, queria agradecer à Câmara Municipal de Montalegre (C.M.M.), instituição onde

trabalho, na pessoa do seu presidente, Dr. Fernando Rodrigues, pelo apoio e por me ter criado

as condições para que pudesse realizar este trabalho.

A todos os colegas de trabalho e em particular ao meu colega de gabinete Luís Fidalgo, agradeço

o bom ambiente, apoio e companheirismo que sempre demonstraram.

Ao Doutor José Mendes, que no exercício de orientador, sempre teve uma relação muito aberta

comigo e me proporcionou uma disponibilidade sempre activa para qualquer tipo de

esclarecimento.

Ao meu grupo de amigos, fundamentais no meu dia-a-dia, obrigado pelo apoio que deram

quando precisei.

Por último, mas não menos importante, agradeço a toda a minha família pela educação e

dedicação que devotaram em mim, especialmente à minha mãe, durante estes longos anos de

formação pessoal e académica, são o meu orgulho.

A todos que directamente ou indirectamente participaram no alcance dos meus objectivos

atingidos até aqui os meus sinceros agradecimentos.

Page 4: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

ii

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Resumo

O Google Maps foi lançado em Fevereiro de 2005, e ainda em versão beta, tornou-se

rapidamente a referência maior da revolução que a Internet começara então a viver. Com uma

interface rica e intuitiva, a aplicação permitia acesso a uma enorme base de dados contendo

uma infinidade de mapas de cidades, bairros, ruas e avenidas nos Estados Unidos.

Com o tempo, novas localidades e países foram adicionadas ao sistema até que, em meados de

Novembro de 2008, o Google finalmente disponibilizou consultas de endereços em Portugal.

Finalmente, em Dezembro de 2008, foi disponibilizada uma versão completa para o público em

geral - e em português - foi oferecida, com a possibilidade de se localizar restaurantes, hotéis,

traçar rotas, entre outras utilidades.

Assim, cada vez mais sites incluem os mapas do Google no seu conteúdo, com as mais diversas

finalidades: desde a simples localização de estabelecimentos comerciais, até à geração de rotas

de viagem para pontos de interesse.

A inclusão de mapas personalizados em sites de terceiros é possível graças à Google Maps API.

A primeira versão da API (“Application Programming Interface”) do Google Maps foi

disponibilizada em Junho de 2005. Desde então, as funcionalidades foram bastante

aprimoradas, culminando na versão actual, lançada em Dezembro de 2009. A API consiste

basicamente num pequeno conjunto de classes JavaScript que fornecem a interface necessária

para que o programador possa construir aplicações para exibir mapas, realizar consultas por

endereços (geocoding), realizar funções de zoom, acrescentar pontos de referência e descrições

no mapa, entre outras possibilidades. Tudo dentro da "filosofia" AJAX. A API permite gerar o

mapa personalizado e adicionar marcadores através de código JavaScript.

O que se pretende implementar é um sistema de geração de mapas dinâmico baseado em

valores armazenados numa base de dados MySQL. Todas as interfaces (tanto do back-office

como do frontoffice) serão aplicações web, baseadas server-side em PHP, e client-side em

JavaScript (com formatação em HTML e CSS) com filosofia AJAX. Os dados da base de dados

terão que ser transformados dinamicamente em ficheiros XML para parsing pela API do Google

Maps. Esta aplicação permitirá actualizar e criar mapas dinamicamente sem ter que alterar o

código das páginas web onde são incluídos.

Palavras-chave: GOOGLE MAPS API, PHP, HTML, CSS, MYSQL, AJAX, JAVASCRIPT, GIS, CMS

Page 5: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

iii

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Abstract

Google Maps, was launched in February 2005 and, still in its beta stage, quickly become a major

reference of the revolution that the Internet began to live then. With a rich and intuitive interface,

the application allowed access to a huge database containing a multitude of maps of cities,

neighborhoods, streets and avenues in the United States.

Over time, new locations and countries were added to the system, until in mid-November 2008,

Google finally released the ability to search Portuguese addresses. In December 2008, a full

version was released to the general public - and in Portuguese - wich offered the ability to locate

restaurants, hotels, map routes, among other uses, now in Portugal.

Thus, more and more websites include Google maps in its content with many different purposes:

from simple location of shops, to the generation of travel routes to points of interest.

Adding custom maps on third party sites is possible thanks to the Google Maps API. The first

version of the API (“Application Programming Interface”) of Google Maps was released in June

2005. Since then, its features were fairly improved, culminating in the current version , released

in December 2009. The API basically consists of a small set of JavaScript classes that provide

the necessary interface for the programmer to build applications to display maps, perform

queries by address (geocoding), perform zoom functions, add waypoints and descriptions on the

map, among other possibilities. Everything within the AJAX philosophy. The API lets you generate

a custom map and add markers with JavaScript code.

The goal of this project is to implement a system for generating dynamic maps based on values

stored in a MySQL database All interfaces (both the back office and the frontoffice) are web

applications based on server-side in PHP and on client-side in JavaScript (with HTML formatting

and CSS) along with the AJAX philosophy. The data from the database will be processed

dynamically in XML files wich will be parsed by the Google Maps API.

This application will allow the update and creation of maps dynamically without the need to

change the code of the web pages on which the maps are included.

Keywords: GOOGLE MAPS API, PHP, HTML, CSS, MYSQL, AJAX, JAVASCRIPT, GIS, CMS

Page 6: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

iv

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Índice

INTRODUÇÃO ....................................................................................................... 1

ESTUDO/ANÁLISE DAS TECNOLOGIAS USADAS ..................................................... 3

1. Porquê PHP5, MySQL e AJAX? .................................................................................................... 3

1.1. PHP5 ................................................................................................................................................. 3

1.1.1. Usar PHP em servidores e aplicações Web em modo de produção ................................................. 4

1.1.2. Arquitectura Técnica ...................................................................................................................... 5

1.1.3. Mecanismo Interno ........................................................................................................................ 5

1.1.4. Uma plataforma que resolve problemas de integração .................................................................... 6

1.1.5. O “Ecossistema” PHP .................................................................................................................... 7

1.1.6. Integração num sistema já existente ............................................................................................... 7

1.2. Porquê usar o MySQL? ........................................................................................................................ 7

1.2.1. Visão Geral do MySQL .................................................................................................................... 7

1.2.2. Características técnicas do MySQL ................................................................................................. 8

1.3. AJAX ................................................................................................................................................. 11

1.3.1. Frameworks AJAX ........................................................................................................................ 12

1.3.1.1. Prototype ........................................................................................................................... 12

1.3.1.2. Google WebToolKit ............................................................................................................. 13

1.3.1.3. MooTools ........................................................................................................................... 13

1.3.1.4. Yahoo User Interface .......................................................................................................... 14

1.3.1.5. Adobe Spry ........................................................................................................................ 14

1.3.1.6. jQuery ............................................................................................................................... 15

2. Investigação e experiências com a API do Google Maps ........................................................... 16

2.1. Introdução ........................................................................................................................................ 16

2.2. O Exemplo mais simples do Google Maps ......................................................................................... 17

2.2.1. Carregar a API do Google Maps .................................................................................................... 18

2.2.2. Mapear elementos DOM .............................................................................................................. 18

2.2.3. GMap2 - O objecto elementar e essencial ..................................................................................... 19

2.2.4. Inicializar o mapa ........................................................................................................................ 19

2.2.5. Carregar o mapa ......................................................................................................................... 20

2.3. Latitudes e longitudes ....................................................................................................................... 20

2.4. Atributos do mapa ............................................................................................................................ 22

2.4.1. Tipos de Mapa ............................................................................................................................. 22

2.4.2. Níveis de Zoom ............................................................................................................................ 23

Page 7: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

v

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.5. Interacções com o mapa ................................................................................................................... 23

2.6. Janelas de informação ...................................................................................................................... 24

2.7. Eventos ............................................................................................................................................ 25

2.7.1. Visão geral dos eventos do mapa ................................................................................................. 25

2.7.2. Funções que respondem a eventos .............................................................................................. 25

2.7.3. Closures em funções que respondem a eventos ........................................................................... 27

2.7.4. Como usar argumentos passados por eventos .............................................................................. 28

2.7.5. Como vincular eventos a métodos de objectos ............................................................................. 29

2.7.6. Monitorizar eventos DOM ............................................................................................................. 30

2.7.7. Remover escutas de eventos ........................................................................................................ 30

2.8. Controlos .......................................................................................................................................... 31

2.8.1. Visão geral dos controlos ............................................................................................................. 31

2.8.2. Como adicionar controlos ao mapa .............................................................................................. 32

2.8.3. Como posicionar controlos no mapa ............................................................................................ 33

2.9. Sobreposições aos mapas ................................................................................................................. 35

2.9.1. Visão geral das sobreposições ao mapa ....................................................................................... 35

2.9.2. Marcadores ................................................................................................................................. 36

2.9.3. Marcadores arrastáveis ................................................................................................................ 36

2.9.4. Ícones ......................................................................................................................................... 37

2.9.5. Polylines ...................................................................................................................................... 40

2.9.5.1. Como desenhar polylines ................................................................................................... 40

2.9.6. Polígonos ..................................................................................................................................... 41

2.9.7. Sobreposições de KML/GeoRSS .................................................................................................. 42

2.9.8. Rotas ........................................................................................................................................... 43

2.9.8.1. Como carregar rotas .......................................................................................................... 43

2.9.8.2. Modos de transporte .......................................................................................................... 44

2.9.8.3. Manipular as rotas geradas ................................................................................................ 44

DESENVOLVIMENTO DO SISTEMA ...................................................................... 46

3. Modelação de Dados ................................................................................................................. 46

3.1. Modelo ER (entidades e relacionamentos) ......................................................................................... 46

3.2. Descrição das Tabelas da Base de Dados ......................................................................................... 47

3.3. Dicionário de dados .......................................................................................................................... 48

3.4. Particularidades da Modelação de Dados .......................................................................................... 49

4. Mapa Interactivo ....................................................................................................................... 50

4.1. Front-end do mapa ........................................................................................................................... 50

4.1.1. Interface do Mapa (HTML + JavaScript e CSS) .............................................................................. 55

Page 8: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

vi

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.1.1. Inicializações Básicas (JavaScript – API) ............................................................................. 57

4.1.1.2. Funções auxiliares JavaScript do front-end ......................................................................... 58

4.1.1.3. Chamadas à camada de dados – XMLHttpRequest() .......................................................... 60

4.1.1.4. Problemas que surgiram durante esta fase ......................................................................... 63

4.1.2. Camadas PHP, MySQL e XML ...................................................................................................... 64

4.1.2.1. Exemplo de output XML gerado .......................................................................................... 65

4.1.2.2. Problemas que surgiram durante esta fase ......................................................................... 66

4.2. Mapa das freguesias: um mapa com particularidades ....................................................................... 66

4.2.1. Acrescentar as delimitações das freguesias ao mapa .................................................................... 67

5. Back-Office ................................................................................................................................ 69

5.1. Gerir Tipos de Localização ................................................................................................................ 69

5.2. Georeferenciação de conteúdo .......................................................................................................... 72

5.3. Utilização da ferramenta CRUD AJAX para gerar o interface do back-office ......................................... 75

CONCLUSÕES .................................................................................................... 78

BIBLIOGRAFIA .................................................................................................... 80

ANEXOS ............................................................................................................. 81

Page 9: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

vii

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Índice de ilustrações

Ilustração 1 - Mapa com centro em Montalegre ....................................................................... 17

Ilustração 2 - Marcadores dentro da fronteira do mapa ............................................................ 21

Ilustração 3 - Mapa com imagens de satélite ........................................................................... 22

Ilustração 4 - Janelas de Informação: Info-Windows ................................................................. 25

Ilustração 5 - Escutas de eventos do mapa .............................................................................. 26

Ilustração 6 - Closures ............................................................................................................ 28

Ilustração 7 - Argumentos passados por eventos ..................................................................... 29

Ilustração 8 - Vincular eventos a métodos de objectos ............................................................. 30

Ilustração 9 - Resposta a um clique colocando um marcador no mapa .................................... 31

Ilustração 10 - Mapa com controlos "small" ............................................................................ 33

Ilustração 11 - Marcadores no mapa ....................................................................................... 36

Ilustração 12 - Mapa com ícones ............................................................................................ 38

Ilustração 13 - Ícones Personalizados ...................................................................................... 39

Ilustração 14 - Mapa com polylines ......................................................................................... 40

Ilustração 15 - Mapa com polígonos ........................................................................................ 41

Ilustração 16 - Sobreposição de GeoRSS/KML ........................................................................ 42

Ilustração 17 - Mapa com rota de viagem ................................................................................ 45

Ilustração 18 - Modelo ER da Base de Dados .......................................................................... 46

Ilustração 19 - Camadas do Front-End .................................................................................... 50

Ilustração 20 - Exemplo de mapa gerado ................................................................................. 51

Ilustração 21 - Mapa com Info-Window .................................................................................... 52

Ilustração 22 - Aba para geração da rota ................................................................................. 52

Ilustração 23 - Exemplo de rota ............................................................................................... 52

Ilustração 24 - Listagem descritiva do trajecto ......................................................................... 53

Ilustração 25 - Tabs superiores do mapa ................................................................................. 53

Ilustração 26 - Mapa com o tema "Onde Dormir" .................................................................... 54

Ilustração 27 - Marcador aberto pelo link da lista descritiva ..................................................... 54

Ilustração 28 - Mapa de freguesia com linhas divisórias entre as freguesias e tabs temáticas ... 66

Ilustração 29 - Gerar uma rota até um lugar de uma freguesia ................................................ 67

Ilustração 30 - Ferramenta SHP2KML ..................................................................................... 68

Page 10: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

viii

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 31 - Franson CoordTrans ........................................................................................ 68

Ilustração 32 - Grelha CRUD AJAX para gestão dos Tipos de Localização ................................. 70

Ilustração 33 - Formulário in-line para adicionar um novo registo ............................................. 70

Ilustração 34 - Eliminação in-line ............................................................................................. 71

Ilustração 35 - Edição in-line ................................................................................................... 71

Ilustração 36 - Filtros in-line .................................................................................................... 71

Ilustração 37 - Ordenação in-line ............................................................................................. 72

Ilustração 38 - Botão "GEOREFERENCIAR" na etapa final da criação de um conteúdo ............. 72

Ilustração 39 - Formulário de Georeferenciação ....................................................................... 73

Ilustração 40 - Escolha do tipo de localização .......................................................................... 73

Ilustração 41 - Selecção da Localidade .................................................................................... 74

Ilustração 42 - Referenciar um ponto ...................................................................................... 74

Ilustração 43 - Vários pontos associados a um conteúdo ......................................................... 75

Lista de Acrónimos

AJAX – Assincronous JavaScript And XML

API – Application Programming Interface

BD – Base de Dados

CMS – Content Management System (Sistema de Gestão de Conteúdos)

CRUD – Create, Read, Update, Delete (referente a bases de dados)

CSS – Cascade Style Sheets

DB – Database (Base de Dados)

DOM – Document Object Model

GIS – Geographical Information System

HTML – HyperText Markup Language

KML - Keyhole Markup Language

KMZ - Keyhole Markup Language, Zipped

PHP - PHP: Hypertext Preprocessor (acrónimo recursivo)

POI – Point of Interest (Ponto de Interesse)

RSS – Realy Simple Syndication

SGBD – Sistema de Gestão de Bases de Dados

Page 11: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

ix

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

SHP – ESRI ShapeFile

SIG – Sistema de Informação Geográfico

SQL – Standard Query Language

XML – Extensible Markup Language

Page 12: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

1

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Introdução

Este trabalho teve como génese (além do interesse académico) a necessidade de acrescentar

uma funcionalidade muito importante para qualquer site que promova uma região com grande

volume de turismo.

Quando pesquisamos na web um local de férias, passeio, fim-de-semana, etc. e encontramos

essa informação no site de um destino que nos despertou o interesse, o passo lógico seguinte é

saber como chegar a esse sítio...

Se tivermos toda a informação turística relevante reunida numa só plataforma e ainda por cima

essa plataforma permitir segmentar a informação, tendo ainda, para cada item que nos

interessa, a possibilidade de gerar a rota desde a nossa localização até esse destino, com

certeza terá sucesso.

Esta é a realidade do portal do Município de Montalegre, uma região fortemente turística e com

grande procura de informação de pontos de interesse neste mesmo portal, como podemos ver

na estatística das visitas do último ano:

Page 13: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

2

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Depois de toda a evolução que o portal teve desde a primeira versão este módulo faz parte da

evolução natural do Sistema de Gestão de Conteúdos pois constata-se que actualmente todos os

sites de referência incluem plataformas de mapping no seu conteúdo, grande parte deles usando

a plataforma Google Maps.

Os objectivos gerais deste trabalho são:

• Implementar sistema de geração de mapas dinâmico baseado em valores armazenados

numa base de dados MySQL:

o Todas as interfaces serão aplicações web dinâmicas, baseadas server-side em

PHP, e client-side em JavaScript (com formatação em HTML e CSS) com

filosofia AJAX.

o Os dados da base de dados terão que ser transformados dinamicamente em

ficheiros XML para parsing pela API do Google Maps.

o Esta aplicação permitirá actualizar e criar mapas dinamicamente sem ter que

alterar o código das páginas web onde são incluídos

Por envolver a interligação de tantas tecnologias diferentes, este foi um trabalho com um grau de

dificuldade algo elevado, em que o investimento na investigação foi grande e demorado, mas

que compensou largamente aquando da implementação do sistema em si.

Page 14: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

3

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Estudo/Análise das tecnologias usadas

1. Porquê PHP5, MySQL e AJAX? 1.1. PHP5

Porque usar PHP5 neste projecto?

Existem no mundo mais de 4.500.000 programadores e utilizadores de PHP.

O PHP é, assim como Java e .NET, uma linguagem de programação e uma plataforma global.

Como linguagem de programação, o PHP tem uma sintaxe bastante parecida com C, Shellscript,

PERL e Java.

Com PHP é possível desenvolver:

• Aplicações Web Dinâmicas (websites, intranets, extranets, etc.)

• Aplicações Desktop (PHP-GTK e PHP4Delphi)

• Rich Clients (PHP-XUL)

• Web Services (SOAP, XML-RPC, REST)

• Scripts de linha de comandos

• Serviços Linux

O PHP é Software Livre e pode ser compilado para várias plataformas.

A portabilidade é uma das maiores vantagens do PHP, possibilitando a sua instalação em vários

Sistemas Operativos como: Linux, Unix, Windows, IBM iSeries, SGI IRIX, RISC OS, Netware

Novell, Mac OS X e AmigaOS

Segundo a NetCraft, o PHP é utilizado em um a cada três sites na Internet. Ou seja, mais de 20

milhões de domínios. 35% da Internet corre PHP.

Page 15: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

4

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Uma das maiores plataformas do mundo - o Yahoo - utiliza PHP e chega a receber 150 mil

visitantes simultaneamente.

O Google usa uma linguagem server-side desenvolvida com base no PHP.

1.1.1. Usar PHP em servidores e aplicações Web em modo de produção

Simplicidade

O PHP é uma linguagem com um modelo de desenvolvimento muito simples. O objectivo inicial

do PHP era tornar possível um desenvolvimento rápido. Esse objectivo foi alcançado, fazendo

com que a maioria das empresas de hosting ofereça PHP nos seus servidores.

Adaptabilidade

O PHP usa duas sintaxes. Uma é procedimental e a outra é orientada a objectos. A

procedimental é mais utilizada nos scripts que geram a interface com o utilizador, já a sintaxe

Orientada a Objectos é, propositadamente similar ao Java e C#, com o objectivo de reduzir os

custos com aprendizagem e encorajar a migração para o PHP, sendo tipicamente usada nas

tarefas de processamento e gestão de dados e camada de negócio.

Interoperabilidade

O PHP pode instanciar objectos COM, .NET e JAVA, além de disponibilizar mecanismos para

comunicação com todos os principais sistemas de base de dados relacionais, assim como com

LDAP, XML, Web Services, Lotus Notes, SAP, entre outros.

Portabilidade

Disponível para a maioria dos sistemas operativos, o PHP funciona da mesma maneira que a

Maquina Virtual do Java (JVM). Após desenvolver a aplicação, ela irá funcionar imediatamente,

sem a necessidade de recompilar, independentemente de qual é o sistema operativo utilizado.

Durabilidade

A durabilidade de uma tecnologia depende principalmente da quantidade de utilizadores. O PHP

é utilizado por mais de 4.500.000 programadores no mundo, fazendo com que sua comunidade

seja extremamente forte e actuante, dando fortes garantias do futuro desta plataforma.

Performance

O PHP tem uma grande performance e estabilidade. A combinação Linux/Apache/PHP é

claramente muito forte, como revelam todos os comparativos com outras plataformas

proprietárias.

Page 16: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

5

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Retorno do investimento

Os pontos citados acima resultam num rápido retorno do investimento. Isso é possível graças à

ausência de custos com licenças, requisitos de hardware, pouco custo com formação, entre

outros.

1.1.2. Arquitectura Técnica

Na maioria das vezes o PHP é utilizado com:

• Um servidor Web: Apache ou Microsoft IIS

• Um SGDB (Base de Dados): MySQL, PostgreSQL, Oracle, SQL Server, etc.

A maioria das plataformas utiliza Linux, Apache, MySQL e PHP (conhecido como LAMP)

A plataforma pode utilizar as seguintes interfaces:

• Web (HTML, WML, etc.)

• Web Services

• Rich Clients, cliente/servidor (PHP-GTK, PHP-XUL, etc.)

• Linha de Comandos (CLI)

• Documentos Office (Open Documents, Open XML, PDF, Flash, etc.)

A classe FPDF faz com que documentos PDF complexos sejam gerados com poucas linhas de

código.

1.1.3. Mecanismo Interno

O núcleo interno do PHP 5 é o Zend Engine 2. O PHP é feito com uma arquitectura modular, e

utiliza os mesmos conceitos do Java e .NET. Um pré-compilador compila o código e envia-o para

a execução em tempo real.

Esta arquitectura permite que se possam utilizar ferramentas de optimização (opcode cache).

É possível diminuir o tempo de execução de um script em até 66%. Além disso, o PHP oferece

uma API para que seja possível estender suas funcionalidades com módulos adicionais.

Estes módulos permitem uma ligação com bases de dados ou LDAP, executar componentes

Java ou COM, “conversar” com Web Services utilizando SOAP, entre outros.

O PHP pode ser automaticamente actualizado através do PEAR e PECL.

Page 17: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

6

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Independente da interface utilizada, a execução segue sempre o mesmo processo. Em primeiro

lugar, o script PHP é interpretado pelo núcleo (core). É nesse ponto que o PHP vai, por exemplo,

ligar à base de dados. Depois disso, o resultado é enviado para o servidor Web ou o servidor GTK

para que seja enviado ao cliente final.

O repositório de classes PEAR oferece mais de 300 componentes adicionais, que são simples de

instalar e actualizar com um único comando.

1.1.4. Uma plataforma que resolve problemas de integração

Muitos conectores

Cerca de 40% dos custos de desenvolvimento estão na integração de aplicações ou fontes de

dados. Para reduzir esses custos, o PHP pode ligar directamente com a maioria das bases de

dados (Oracle, SQL Server, MySQL, dBase, ODBC, XML, etc.), directórios (LDAP, etc.), sistemas

de pagamentos online (Verisign, Cybercash, Realex, etc.) e protocolos (SMTP, IMAP, FTP, HTTP,

TCP, SSH, etc.).

Comunicação via COM, .NET e Web Services

O PHP é o “campeão” no requisito de integração de baixo nível. A plataforma pode facilmente

instanciar objectos COM, classes Java e .NET. PHP 5 com SOAP e tem uma camada de alto

nível para ler ou criar Web Services.

PHP, J2EE e .NET: Utilização concorrente

Graças à possibilidade de trabalhar bem com COM e Java, PHP está-se a tornar num padrão na

gestão da camada gráfica de aplicações que utilizam múltiplas linguagens de programação. Por

exemplo a Lufthansa (Uma das maiores empresas de transporte aéreo do mundo) utiliza PHP

para mostrar a interface visual, e J2EE para a camada de negócio.

Comunicação com .NET

É possível instanciar componentes COM. A classe (ainda experimental) dotnet_load()

permite que um componente Microsoft .NET seja instanciado pelo PHP.

Alguns compiladores do PHP para MSIL (código intermediário do .NET) estão em

desenvolvimento (PHP Sharp)

Há ainda uma implementação open-source para a plataforma .NET: o Mono

Há rumores de que a Oracle irá incluir o PHP no "Oracle Application Server".

, que permite a

instanciação dessas classes sem recorrer a plataformas proprietárias.

O PHP está disponível para as plataformas Netware 6.x.

Page 18: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

7

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

1.1.5. O “Ecossistema” PHP

Após 10 anos de vida, o PHP construiu um grande “ecossistema”. Algumas ferramentas tornam

o desenvolvimento mais fácil e rápido.

A comunidade de Software Livre tem vindo a produzir aplicações empresariais há vários anos.

Essas aplicações ajudam empresas a encontrar suas necessidades, proliferando e multiplicando-

se, como num verdadeiro ecossistema.

1.1.6. Integração num sistema já existente

O sistema já em produção onde este trabalho se vai integrar é desenvolvido em PHP. Esta é

porventura a razão que torna o uso do PHP praticamente obrigatório, em detrimento do seu

maior concorrente (que não é open-source): o ASP e ASPX da Microsoft.

1.2. Porquê usar o MySQL?

1.2.1. Visão Geral do MySQL

O MySQL, é o mais popular sistema de gestão de bases de dados SQL open-source, é

desenvolvido, distribuído e tem suporte da MySQL AB – adquirida recentemente pela ORACLE.

O Website da MySQL (http://www.mysql.com/) fornece informações mais recentes sobre e

programa MySQL e a MySQL AB.

O MySQL é um sistema de gestão de bases de dados relacional.

A parte SQL do MySQL é responsável pela “Structured Query Language – Linguagem Estruturada

de Consultas”.

SQL é linguagem padrão mais comum usada para aceder a bases de dados e é definida pelo

padrão ANSI/ISO SQL. (O padrão SQL vem evoluindo desde 1986 e existem diversas versões).

Como é Open Source qualquer pessoa pode fazer download do MySQL pela Internet e usá-lo

sem pagar nada. Se necessário, pode-se estudar o código fonte e alterá-lo para adequá-lo às

necessidades.

Page 19: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

8

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

O servidor de base de dados MySQL é extremamente rápido, fiável, e fácil de usar além de ser

grátis.

O Servidor MySQL foi desenvolvido originalmente para lidar com bases de dados muito grandes

de maneira muito mais rápida que as soluções existentes e tem sido usado em ambientes de

produção de alta performance há vários anos de maneira bem sucedida.

Apesar de estar em constante desenvolvimento, o Servidor MySQL oferece hoje um rico e

proveitoso conjunto de funções. A conectividade, velocidade, e segurança fazem com que o

MySQL seja altamente adaptável para aceder bases de dados na Internet.

1.2.2. Características técnicas do MySQL

O Sistema de Base de Dados MySQL é um sistema cliente/servidor que consiste de um servidor

SQL multi-tarefa que suporta acessos diferentes, diversos programas clientes e bibliotecas,

ferramentas administrativas e diversas interfaces de programação (API's).

Muitas aplicações e linguagens já suportam de origem o Servidor de Base de dados MySQL.

Principais Características/Vantagens do MySQL:

• Portabilidade:

o Escrito em C e C++.

o Testado numa ampla faixa de compiladores diferentes.

o Funciona em diversas plataformas.

o Utiliza o GNU Automake, Autoconf, e Libtool para portabilidade.

o APIs para C, C++, Eiffel, Java, Perl, PHP, Python, Ruby e Tcl

o Suporte total a multi-threads usando threads directamente no kernel. Isto significa

que se pode facilmente usar múltiplas CPUs, se disponíveis.

• Fornece mecanismos de armazenamento transaccional e não-transaccional:

o Tabelas em disco (MyISAM) baseadas em árvores-B extremamente rápidas com

compressão de índices.

o É relativamente fácil adicionar outros mecanismos de armazenamento.

o Sistema de alocação de memória muito rápido e baseado em processo(thread).

o Joins muito rápidas usando uma multi-join de leitura única optimizada.

o Tabelas hash em memória que são usadas como tabelas temporárias.

Page 20: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

9

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

o Funções SQL são implementadas por meio de uma biblioteca de classes altamente

optimizada e com o máximo de performance. Geralmente não há nenhuma alocação

de memória depois da inicialização da pesquisa.

• Disponível como versão cliente/servidor ou embutida (ligada).

• Tipos de Colunas:

o Aceita diversos tipos de campos: INT de 1, 2, 3, 4 e 8 bytes com e sem sinal,

FLOAT, DOUBLE, CHAR, VARCHAR, TEXT, BLOB, DATE, TIME, DATETIME,

TIMESTAMP, YEAR, SET, ENUM e GEOMETRY.

o GEOMETRY é especificado para dados geo-espaciais.

o Registos de tamanhos fixos ou variáveis.

• Comandos e Funções:

o Completo suporte a operadores e funções nas partes SELECT e WHERE das

consultas.

o Suporte pleno às cláusulas SQL GROUP BY e ORDER BY. Suporte para funções de

agrupamento (COUNT(), COUNT(DISTINCT ...), AVG(), STD(), SUM(), MAX() e MIN()).

o Suporte para LEFT OUTER JOIN e RIGHT OUTER JOIN com as sintaxes SQL e

ODBC.

o Alias em tabelas e colunas são disponíveis como definidos no padrão SQL92.

o DELETE, INSERT, REPLACE, e UPDATE retornam o número de linhas que foram

alteradas (afectadas).

o O comando específico do MySQL SHOW pode ser usado para devolver informações

sobre bases de dados, tabelas e índices. O comando EXPLAIN pode ser usado para

determinar como o optimizador resolve a consulta.

o Nomes de funções não entram em conflito com nomes de tabelas ou colunas. Por

exemplo, ABS é um nome de campo válido.

• Segurança:

o Um sistema de privilégios e palavras-chave que é muito flexível, seguro e que

permite verificação baseada em estações/máquinas. Palavras-chave são seguras

porque todo o tráfego de palavras-chave é criptografado quando na ligação ao

servidor.

Page 21: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

10

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

• Escalabilidade e limites:

o Lida com bases de dados enormes. Pode-se usar o Servidor MySQL com bases de

dados que contém 50.000.000 registos. Há conhecimento de utilizadores que usam

o Servidor MySQL com 60.000 tabelas e aproximadamente 5.000.000.000 de

linhas.

o São permitidos até 32 índices por tabela. Cada índice pode ser composto de 1 a 16

colunas ou partes de colunas. O tamanho máximo do índice é de 500 bytes (isto

pode ser alterado na compilação do MySQL). Um índice pode usar o prefixo de

campo com um tipo CHAR ou VARCHAR.

o Permite servidores em Cluster

• Conectividade:

o Os clientes podem-se ligar ao servidor MySQL usando sockets TCP/IP, em qualquer

plataforma. No sistema Windows na família NT (NT, 2000 ou XP), os clientes

podem-se ligar usando named pipes. No sistema Unix, os clientes podem se ligar

usando sockets.

o A interface Connector/ODBC fornece ao MySQL suporte a programas de clientes

que usam conexão ODBC (Open-DataBase-Connectivity). Por exemplo, pode-se usar

o MS Access para ligar ao seu servidor MySQL. Os clientes podem ser executados

no Windows ou Unix.

• IMPORTANTE:

o Contém datatypes específicos para georeferenciação e armazenamento de dados

GIS.

o É o Sistema de Gestão de Bases de Dados usado no CMS que suporta o portal,

sendo por isso essencial para a interligação com as tabelas existentes o uso do

MySQL, ao invés das alternativas também open-source como o postgreSQL ou

comerciais, como Oracle ou Microsoft SQL Server.

Page 22: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

11

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

1.3. AJAX

O AJAX (abreviatura de Asynchronous JavaScript and XML) é um conjunto de técnicas de

desenvolvimento web interligadas usada no lado do cliente para criar aplicações web

interactivas.

Com o AJAX, as aplicações web podem carregar dados do servidor de forma assíncrona em

segundo plano sem interferir com a apresentação e comportamento da página existente. A

utilização de técnicas AJAX permite um aumento de interactividade e dinâmicas nas páginas

web.

Os dados assíncronos são geralmente carregados usando o objecto XMLHttpRequest. Apesar do

nome, o uso de XML não é estritamente necessário, nem os pedidos precisam ser sempre

assíncronos.

AJAX não é uma tecnologia em si, mas um grupo de tecnologias associadas. O AJAX usa uma

combinação de HTML e CSS para visualização e formatações de estilos enquanto o DOM é

acedido com JavaScript para exibir dados dinamicamente, permitindo ao utilizador interagir com

as informações apresentadas.

Resumidamente, as funções JavaScript, em conjunto com o objecto XMLHttpRequest fornecem

um método para troca de dados de forma assíncrona entre o browser e o servidor para evitar

reloads de página inteira, permitindo assim actualizar partes ou secções de uma página

independentemente e de forma concorrente.

Constata-se que na Web actual os interfaces dos sites de referência recorrem a esta técnica

aumentando a funcionalidade e interactividade das aplicações, estando a decair rapidamente o

uso da única alternativa: o Adobe Flash, que além de ser um sistema proprietário e fechado, é

muito pouco flexível na interacção com bases de dados e sistemas de terceiros.

É quase obrigatório que todos os interfaces Web desenvolvidos actualmente utilizem interfaces

com o utilizador baseados em AJAX, daí a opção de o usar neste projecto.

Page 23: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

12

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

1.3.1. Framew orks AJAX

Com o aparecimento do termo AJAX também começaram a aparecer várias frameworks ou

bibliotecas para desenvolvimento das interfaces das aplicações web. Desde a mais simples em

que apenas ajuda a facilitar o XMLHttpRequest até às mais complicadas em que possibilitam

muito mais do que apenas o XMLHttpRequest.

Fez-se uma análise a algumas das frameworks mais conhecidas e usadas para decidir qual a

mais vantajosa. Todas estas frameworks têm pelo menos uma coisa em comum: todas facilitam

o XMLHttpRequest.

1.3.1.1. Prototype

O Prototype é uma das bibliotecas/framework mais conhecidas e bastante usada para quem

quer usar AJAX. Um dos problemas do Prototype é a actual documentação, que muitos

utilizadores acham complicada e difícil de entender.

• URL: http://www.prototypejs.org/ - Prototype JavaScript framework: Easy AJAX and

DOM manipulation for dynamic web applications – Acedida a 11/08/2010

• Documentação: http://www.prototypejs.org/api

• Sites que usam Prototype: www.digg.com, www.alexa.com

Page 24: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

13

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

1.3.1.2. Google WebToolKit

Google oferece o GWT (Google Web Toolkit) que é uma aplicação em JAVA que simplifica a

criação de scripts para usar AJAX. Basicamente permite a qualquer programador criar AJAX

usando JAVA deixando assim de seguida o GWT traduzir o código para JavaScript e HTML.

URL: http://code.google.com/webtoolkit/ - Google Web Toolkit - Acedida a 11/08/2010

• Documentação: http://code.google.com/webtoolkit/overview.html

• Sites que usam GWT: blueprint.lombardi.com, www.dotemplate.com

1.3.1.3. MooTools

A MooTools oferece uma framework para programadores já com alguma experiência em

JavaScript. Ultimamente esta framework tem vindo a crescer e com uma documentação

bastante simples de usar e dá para perceber que a Mootools é uma das frameworks com mais

potencial.

• URL: http://mootools.net - MooTools - a compact JavaScript Framework - Acedida a

11/08/2010

• Documentação: http://docs.mootools.net/

• Sites que usam MooTools: www.cnet.com, joomla.org

Page 25: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

14

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

1.3.1.4. Yahoo User Interface

A resposta da Yahoo ao mundo das frameworks. Uma das grandes vantagens de usar a YUI

framework é a possibilidade de não ser preciso fazer o download da framework e poder apenas

criar um link na nossa aplicação directamente aos servidores da Yahoo. Isto pode ser uma

vantagem na redução do tráfego e carga no nosso servidor. Esta Framework, na minha opinião

tem ainda poucos plugins disponíveis e pouca adesão da comunidade de programadores.

• URL: http://developer.yahoo.com/yui/ - YUI Library - Acedida a 12/08/2010

• Documentação: http://developer.yahoo.com/yui/docs/

• Sites que usam YUI: www.linkedin.com, slashdot.org

1.3.1.5. Adobe Spry

Claro que a Adobe não podia fugir deste segmento. Mas como a Adobe já nos habituou, esta

framework está mais inclinada para designers. Para os utilizadores do Dreamweaver, Spry

possibilita uma integração bastante fácil.

• URL: http://labs.adobe.com/technologies/spry/ - Adobe Labs | Spry framework for

AJAX - Acedida a 12/08/2010

• Documentação: http://labs.adobe.com/technologies/spry/

• Sites que usam Spry: www.adobe.com, reader.macrostandard.com

Page 26: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

15

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

1.3.1.6. jQuery

A Framework jQuery está nitidamente na frente em relação às outras todas. Tanto ao nível de

documentação, plugins disponíveis, número de utilizadores, uso em sites em produção.

A jQuery oferece mais que o Prototype e em termos de tamanho dos scripts tem muito menos

(16kb) o que é bastante impressionante.

Mais impressionante ainda é o factor de o jQuery ser usado pelo Google Code nalguns sites em

vez da sua própria Framework. (Neste site por exemplo: http://code.google.com/intl/pt-

PT/events/calendar/add - Google Calendar Events – Acedido a 12/08/2010)

• URL: http://jQuery.com - jQuery: The Write Less, Do More, JavaScript Library - Acedido

a 12/08/2010

• Documentação: http://docs.jQuery.com/Main_Page

• Sites que usam jQuery: www.dell.com, www.nbc.com, cbs.com

Depois da análise e experiencias com algumas das frameworks, a escolha recaiu sobre a jQuery.

Quer devido aos plugins já existentes satisfazerem alguns requisitos do projecto, mas também a

pela documentação e a facilidade de utilização.

Page 27: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

16

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2. Investigação e experiências com a API do Google Maps

2.1. Introdução A API do Google Maps é o elemento central deste projecto. Esta API permite incluir os mapas do

Google embebidos directamente nas páginas da nossa aplicação, funcionalidade ainda não

disponível nas plataformas de mapping concorrentes como o Bing Maps, Yahoo Maps e Sapo

Mapas.

Antes de começar a desenvolver com esta ferramenta nova, foi estudado o guia/referência para

experimentar as funções e classes fornecidas pela API. A melhor maneira de entender o seu

funcionamento foi mesmo criar pequenas aplicações onde se foram testando as possibilidades

oferecidas pela ferramenta.

Page 28: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

17

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.2. O Exemplo mais simples do Google Maps O elemento fundamental de qualquer aplicação da API do Google Maps é o próprio "mapa": o

objecto GMap2. A partir deste objecto desenvolvemos todas as operações sobre o mapa.

A maneira mais fácil de começar com a API do Google Maps v2 é um exemplo simples. O código

seguinte gera uma página web que exibe um mapa 500 x 300 centralizado em Montalegre:

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>Google Maps - Exemplo API JavaScript</title> <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=xxxxxxxxxxxxxxxxxxxxxxxxxx&sensor=true_or_false" type="text/JavaScript"></script> <script type="text/JavaScript"> function CMMinitialize() { if (GBrowserIsCompatible()) { var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(41.79179268262892, -7.86895751953125 ), 13); } } </script> </head> <body onload="CMMinitialize()" onunload="GUnload()"> <div id="map_canvas" style="width: 500px; height: 300px"></div> </body>

</html>

Ilustração 1 - Mapa com centro em Montalegre

Page 29: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

18

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Para que o Google Maps API funcione no nosso domínio web (e todos os subdomínios

secundários) precisamos de obter uma key, fazendo um processo de registo gratuito junto do

Google.

Neste exemplo simples, há cinco coisas a serem observadas:

1. Incluímos o JavaScript da API do Maps usando uma tag script.

2. Criamos um elemento div chamado "map_canvas" para conter o mapa.

3. Escrevemos uma função JavaScript para criar um objecto "map".

4. Centralizamos o mapa num determinado ponto geográfico.

5. Inicializamos o objecto de mapa a partir do evento onLoad da tag body.

Estas etapas são explicadas a seguir.

2.2.1. Carregar a API do Google Maps

<script src="http://maps.google.com/maps?file=api&v=2&key=xxxxxxxxxxxxxxxxxxxxxxxxxxx&sensor=true_or_false" type="text/JavaScript">

</script>

O URL http://maps.google.com/maps?file=api&v=2&key=xxxxxxxxx aponta para o

local do ficheiro JavaScript que inclui todos os símbolos e as definições necessárias ao uso da

API do Google Maps. A página deve conter uma tag script que aponte para este URL, usando

a chave recebida mediante a inscrição na API. Neste exemplo, a chave é mostrada como

"xxxxxxxxxxx", pois as chaves são únicas para cada cliente.

Também passamos um parâmetro sensor para indicar se esta aplicação usa um sensor para

determinar a localização do utilizador. Deixamos este exemplo como uma variável

true_or_false para enfatizar que se deve definir este valor explicitamente para true ou

false.

2.2.2. Mapear elementos DOM

<div id="map_canvas" style="width: 500px; height: 300px"></div>

Para que o mapa seja mostrado numa página web, precisamos de reservar espaço para ele.

Normalmente, fazemos isto criando um elemento div e criando uma referência a ele no DOM

(document object model ou modelo de objecto do documento) do browser.

Page 30: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

19

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

No exemplo acima, definimos uma div com o nome "map_canvas" e configuramos o tamanho

usando atributos de estilo. A menos que especifiquemos explicitamente um tamanho para o

mapa usando GMapOptions no construtor, o mapa usa implicitamente o tamanho do recipiente

para se dimensionar a si mesmo.

2.2.3. GMap2 - O objecto elementar e essencial

var map = new GMap2(document.getElementById("map_canvas"));

Como já referimos, a classe JavaScript que representa um mapa é GMap2. Os objectos desta

classe definem um único mapa numa página. Podemos criar mais do que uma instância desta

classe - cada objecto definirá um mapa separado na página. Criamos uma nova instância desta

classe usando o operador JavaScript new.

Ao criar uma nova instância do mapa, especificamos um nó DOM na página (normalmente um

elemento div) como sendo um recipiente para o mapa. Os nós HTML são filhos do objecto

JavaScript document, e obtemos uma referência a este elemento pelo método

document.getElementById().

Este código define uma variável (com o nome de map) e atribui-a a um novo objecto GMap2. A

função GMap2() é conhecida como construtor e a sua definição (cópia resumida da Referência

da API do Google Maps) é mostrada abaixo:

Construtor Descrição

GMap2(container, opts?)

Cria um novo mapa dentro do container HTML dado, que é normalmente um elemento DIV. Também podemos passar parâmetros opcionais do tipo GMap2Options no parâmetro opts.

Como o JavaScript é uma linguagem com definições de tipos “permissiva”, não precisamos de

passar nenhum parâmetro opcional ao construtor, por isso o não fazemos aqui.

2.2.4. Inicializar o mapa

map.setCenter(new GLatLng(37.4419, -122.1419), 13);

Depois de termos criado um mapa por meio de um construtor GMap2, precisamos de fazer

ainda mais: inicializá-lo. Esta inicialização é realizada por meio do uso do método setCenter()

Page 31: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

20

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

do mapa. O método setCenter() exige uma coordenada GLatLng e um nível de zoom, e este

método deve ser enviado antes que quaisquer outras operações sejam executadas no mapa,

incluindo a configuração de quaisquer outros atributos do próprio mapa.

2.2.5. Carregar o mapa

<body onload="initialize()" onunload="GUnload()">

Durante a apresentação de uma página HTML, o DOM é criado, e todas as imagens e scripts

externos são recebidos e incorporados no objecto document. Para garantir que o nosso mapa

seja colocado na página só depois de ela ter sido totalmente carregada, só executamos a função

que cria o objecto GMap2 depois de o elemento <body> da página HTML receber um evento

onload. Isto evita um comportamento imprevisível e dá-nos mais controlo sobre como e quando

o mapa é desenhado.

O atributo onload é um exemplo de um manipulador de evento. A API do Google Maps fornece

ainda uma série de eventos que indicam alterações de estado.

GUnload() é uma função da API projectada para impedir memory leaks, que deve ser sempre usada.

2.3. Latitudes e longitudes

Tendo um mapa, precisamos de uma forma de consultar e incluir os nossos locais/marcadores.

O objecto GLatLng fornece este mecanismo na API do Google Maps. Criamos um objecto

GLatLng, passando os nossos parâmetros na ordem { latitude, longitude } como é normal em

cartografia:

var myGeographicCoordinates = new GLatLng(myLatitude, myLongitude);

Este objecto, tanto é útil na simples consulta a um ponto geográfico, como também na definição

dos limites geográficos de um objecto. Por exemplo, um mapa exibe uma "janela" actual do

mundo inteiro dentro do que é definido como janela de visualização. Esta janela de visualização

pode ser definida por pontos rectangulares nos cantos. O objecto GLatLngBounds oferece esta

funcionalidade, definindo uma região rectangular usando dois objectos GLatLng representando

os cantos inferior esquerdo e superior direito da caixa delimitadora, respectivamente.

Page 32: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

21

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Os objectos GLatLng têm muitos usos na API do Google Maps. Por exemplo, o objecto

GMarker utiliza um GLatLng no seu construtor e coloca um marcador em sobreposição ao

mapa, na localização geográfica específica.

Um mapa também contém muitos atributos que vale a pena testar e estudar. Por exemplo, para

encontrar as dimensões da janela de visualização actual, usa-se o método getBounds() do

objecto GMap2 que retorna um valor GLatLngBounds.

O exemplo a seguir usa getBounds() para retornar a janela de visualização actual e coloca,

aleatoriamente, 10 marcadores no mapa dentro destes limites:

function initialize() { var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); // Adiciona 10 marcadores ao mapa em localizações aleatórias var bounds = map.getBounds(); var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast(); var lngSpan = northEast.lng() - southWest.lng(); var latSpan = northEast.lat() - southWest.lat(); for (var i = 0; i < 10; i++) { var point = new GLatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random()); map.addOverlay(new GMarker(point)); }

}

Ilustração 2 - Marcadores dentro da fronteira do mapa

Page 33: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

22

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.4. Atributos do mapa 2.4.1. Tipos de Mapa

Por defeito, os mapas aparecem na API do Google Maps usando blocos "pintados" por defeito.

Mas a API do Google Maps também suporta outros tipos de mapa. Os tipos de mapa a seguir

são os disponibilizados por defeito pela API:

• G_NORMAL_MAP – exibe os blocos 2D normais, padrão, do Google Maps • G_SATELLITE_MAP – mostra imagens de satélite/ortofotomapas do Google Earth • G_HYBRID_MAP – mostra uma mistura entre as visualizações normal e de satélite

mostrando em vectorial os recursos importantes (estradas, nomes de cidades, POIs, etc) • G_PHYSICAL_MAP – exibe blocos de mapa físico com base nas informações do terreno • G_DEFAULT_MAP_TYPES – uma matriz destes três tipos, muito útil no processamento

iterativo, ou quando queremos controlar os tipos de mapa com programação (com PHP por exemplo)

Podemos configurar o tipo de mapa usando o método setMapType() do objecto GMap2. Por

exemplo, o código a seguir define que o mapa deve usar a visualização de satélite do Google

Earth:

var map = new GMap2(document.getElementById("map_canvas")); map.setMapType(G_SATELLITE_MAP);

Também é possível definir tipos de mapas personalizados caso haja imagens ou sobreposições

definidas. O código abaixo remove G_HYBRID_MAP dos tipos disponíveis anexados a um mapa,

deixando apenas dois tipos de mapa. Depois de adicionarmos GMapTypeControl, apenas

estes dois tipos de mapa permanecem disponíveis:

var map = new GMap2(document.getElementById("map_canvas"), { size: new GSize(640,320) } ); map.removeMapType(G_HYBRID_MAP); map.setCenter(new GLatLng(42.366662,-71.106262), 11); var mapControl = new GMapTypeControl(); map.addControl(mapControl); map.addControl(new GLargeMapControl());

Ilustração 3 - Mapa com imagens de satélite

Page 34: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

23

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.4.2. Níveis de Zoom

Cada mapa também contém um nível de zoom, que define a resolução da visualização actual.

Níveis de zoom entre 0 (o mais baixo, no qual todo o mundo pode ser visto num só mapa) e 19

(o mais alto, que chega a construções individuais) são possíveis na visualização normal dos

mapas. Os níveis de zoom variam de acordo com o sítio do mundo que estamos a ver, porque os

dados nalgumas partes do mundo estão mais definidos do que em outras. Os níveis de zoom até

19 só são possíveis na visualização de satélite nalguns sítios. Em Portugal há ainda muitos sítios

onde isso não é possível e a zona de Montalegre é uma delas, permitindo nível de zoom máximo

16.

Podemos consultar o nível de zoom actual utilizado pelo mapa usando o método getZoom() do

objecto GMap2.

2.5. Interacções com o mapa Agora que temos um objecto GMap2, podemos interagir com ele. O objecto de mapa básico é

semelhante e comporta-se de maneira muito parecida com o mapa de interacção do site do

Google Maps, além de vir com uma grande quantidade de comportamentos integrados. O

objecto GMap2 também fornece vários métodos de configuração para alterar o comportamento

do próprio objecto de mapa.

Por defeito, os objectos do mapa tendem a reagir à actividade do utilizador como acontece em

http://maps.google.pt. Podemos alterar este comportamento usando vários métodos da API. Por

exemplo, o método GMap2.disableDragging() desactiva a capacidade de clicar e arrastar o

mapa para um novo local.

Também podemos interagir com o mapa via programação. O objecto GMap2 suporta vários

métodos que alteram o estado do mapa directamente. Por exemplo, os métodos setCenter(),

panTo() e zoomIn() operam no mapa de maneira programável, e não pela interacção do

utilizador.

O método panTo centraliza o mapa num determinado ponto. Caso o ponto especificado esteja

na parte visível do mapa, o mapa desloca-se lentamente até este ponto; caso contrário, o mapa

"salta" para o ponto:

Page 35: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

24

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); window.setTimeout(function() { map.panTo(new GLatLng(37.4569, -122.1569)); }, 1000);

2.6. Janelas de informação Cada mapa da API do Google Maps pode mostrar "janelas de informações" do tipo

GInfoWindow, que exibem conteúdo HTML numa janela flutuante acima do mapa. A janela de

informações parece-se um pouco com os balões das histórias de banda desenhada. Esta

apresenta uma área de conteúdo e uma base ancorada, cuja ponta permanece num ponto

específico do mapa.

O objecto GInfoWindow não possui nenhum construtor. Uma janela de informações é

automaticamente criada e anexada ao mapa quando o criamos. Não é possível mostrar mais de

uma janela de informações de cada vez num determinado mapa, mas podemos movê-la e

alterar o seu conteúdo quando necessário.

Quando abrimos uma nova janela, a que estava aberta anteriormente fecha-se automaticamente.

O objecto GMap2 fornece o método openInfoWindow() que usa um ponto e um elemento

DOM HTML como argumentos. O elemento DOM HTML é anexo ao recipiente da janela de

informações e a extremidade da janela é ancorada ao ponto específico.

O método openInfoWindowHtml() do GMap2 é semelhante, mas usa uma string HTML como

segundo argumento, em vez de um elemento DOM, para apresentar conteúdo formatado em

HTML.

Para criar a janela de informações, chama-se o método openInfoWindow(), passando um

local e um elemento DOM a serem mostrados. O código de exemplo a seguir exibe uma janela

de informações ancorada ao centro do mapa com a simples mensagem "Hello, world":

var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); map.openInfoWindow(map.getCenter(),

document.createTextNode("Hello, world"));

Page 36: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

25

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 4 - Janelas de Informação: Info-Windows

2.7. Eventos 2.7.1. Visão geral dos eventos do mapa

O JavaScript no browser é orientado a eventos, o que significa que o JavaScript responde a

interacções gerando eventos e espera que um programa/script escute os eventos que lhe

“interessam”. Por exemplo, nos browsers, interacções de rato e teclado do utilizador criam

eventos propagados no DOM. Os programas interessados em determinados eventos registam

escutas de eventos JavaScript para estes eventos e executarão o código quando os eventos

forem recebidos.

A API do Google Maps faz inclusões neste modelo de eventos, definindo eventos personalizados

para objectos da API do Google Maps. É importante observar que os eventos da API do Google

Maps são separados e distintos dos eventos DOM padrão. No entanto, como browsers diferentes

implementam modelos de evento DOM diferentes, a API do Google Maps também fornece

mecanismos para ouvir e responder a estes eventos DOM sem a necessidade de manipular as

muitas peculiaridades dos vários browsers.

2.7.2. Funções que respondem a eventos

Os eventos na API do Google Maps são manipulados com funções dentro do namespace

GEvent para registar funções que respondem a eventos. Cada objecto da API do Maps exporta

vários named events. Por exemplo, o objecto GMap2 exporta os eventos click, dblclick e

move, além de muitos outros. Cada evento acontece num determinado contexto, podendo

passar argumentos que identificam este contexto. Por exemplo, o evento mousemove é activado

quando o utilizador move o rato num objecto de mapa e passa a GLatLng da localização

geográfica na qual se encontra o rato.

Page 37: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

26

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

A lista completa dos eventos GMap2 e dos argumentos gerados está na Referência da API do

Google Maps.

Para se inscrever para receber notificações destes eventos, usa-se o método estático

GEvent.addListener(). Este método usa um objecto, um evento a ser ouvido e uma função

a ser chamada quando ocorre o evento especificado. Por exemplo, este excerto de código mostra

um alerta sempre que o utilizador clica no mapa:

var map = new GMap2(document.getElementById("map")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); GEvent.addListener(map, "click", function() { alert("Clicou no mapa.");

});

Ilustração 5 - Escutas de eventos do mapa

As funções que respondem a eventos também podem capturar o contexto do evento. No

exemplo de código abaixo, é mostrada a latitude e a longitude do centro do mapa depois de o

utilizador arrastar o mapa:

var map = new GMap2(document.getElementById("map")); GEvent.addListener(map, "moveend", function() { var center = map.getCenter(); document.getElementById("message").innerHTML = center.toString(); });

map.setCenter(new GLatLng(37.4419, -122.1419), 13);

Page 38: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

27

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.7.3. Closures em funções que respondem a eventos

Durante a execução de uma função que responde a um evento, geralmente é vantajoso ter

dados privados e persistentes anexados a um objecto. O JavaScript não oferece suporte a dados

de instância "privada", mas oferece closures1, os quais permitem que funções internas acedam

a variáveis externas. Os closures são úteis em funções que respondem a eventos para aceder a

variáveis que não são geralmente anexas aos objectos nos quais ocorrem os eventos.

O exemplo a seguir usa um closure de função na função que responde a um evento para atribuir

uma mensagem secreta a um conjunto de marcadores. Clicar em cada um dos marcadores

apresentará um excerto da mensagem secreta, que não está contida no marcador propriamente

dito:

var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); // Cria marcador num determinado ponto // Os cinco marcadores mostram uma mensagem secreta // mas a mensagem não está nos dados da instância do marcador function createMarker(point, number) { var marker = new GMarker(point); var message = ["Esta","é","a","mensagem","secreta"]; marker.value = number; GEvent.addListener(marker, "click", function() { var myHtml = "<b>#" + number + "</b><br/>" + message[number -1]; map.openInfoWindowHtml(point, myHtml); }); return marker; } // Adicionar 5 marcadores ao mapa em localizações aleatórias var bounds = map.getBounds(); var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast(); var lngSpan = northEast.lng() - southWest.lng(); var latSpan = northEast.lat() - southWest.lat(); for (var i = 0; i < 5; i++) { var point = new GLatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random()); map.addOverlay(createMarker(point, i + 1));

}

1 http://jibbering.com/faq/notes/closures/

Page 39: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

28

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 6 - Closures

2.7.4. Como usar argumentos passados por eventos

Quando accionados, muitos eventos no sistema da API do Google Maps passam argumentos.

Por exemplo, o evento de "clique" GMap2 passa argumentos overlay e overlaylatlng se o

clique do mapa ocorrer numa sobreposição; caso contrário, ele passa um latlng da

coordenada do mapa. Pode-se aceder a estes argumentos passando os símbolos especificados

directamente para as funções nas escutas de evento.

No exemplo a seguir, primeiro há um teste para garantir que o clique foi feito sobre um bloco do

mapa verificando se o argumento latlng está definido. Se estiver, abre-se uma janela de

informações acima da coordenada clicada e exibe-se a coordenada convertida em espaço de

pixel juntamente com o nível de zoom:

var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); GEvent.addListener(map,"click", function(overlay, latlng) { if (latlng) { var myHtml = "O valor GPoint é: " + map.fromLatLngToDivPixel(latlng) + " com zoom nível " + map.getZoom(); map.openInfoWindow(latlng, myHtml); } }); map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl());

Page 40: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

29

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 7 - Argumentos passados por eventos

2.7.5. Como vincular eventos a métodos de objectos

As funções são úteis quando se deseja anexar escutas de evento a instâncias específicas de um

objecto. No entanto, se quisermos chamar um método em todas as instâncias de um objecto em

resposta a eventos, podemos usar GEvent.bind(). No exemplo a seguir, uma instância da

classe de aplicação vincula eventos de mapa aos seus próprios métodos, modificando o estado

da classe quando os eventos são disparados:

function MyApplication() { this.counter = 0; this.map = new GMap2(document.getElementById("map")); this.map.setCenter(new GLatLng(37.4419, -122.1419), 13); GEvent.bind(this.map, "click", this, this.onMapClick); } MyApplication.prototype.onMapClick = function() { this.contador++; alert("Clicou no mapa " + this.contador + " " + (this.counter == 1 ? "vez" : "vezes")); }

var application = new MyApplication();

Page 41: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

30

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 8 - Vincular eventos a métodos de objectos

2.7.6. Monitorizar eventos DOM

O modelo de eventos da API do Google Maps cria e gere eventos personalizados próprios.

Porém, o DOM também cria e distribui os seus próprios eventos, de acordo com o modelo de

eventos usado pelo browser em especial. Caso se queira capturar e responder a estes eventos, a

API do Google Maps fornece mecanismos para ouvir e vincular eventos DOM sem que haja a

necessidade de código personalizado.

O método estático GEvent.addDomListener() regista um manipulador de evento para um

evento e um nó DOM. Da mesma forma, o método estático GEvent.bindDom() permite

registar manipuladores de evento para eventos DOM em instâncias de classe.

2.7.7. Remover escutas de eventos

Quando uma escuta de evento deixa de ser necessária deve remover-se. Isto pode ser necessário

até mesmo em casos nos quais o evento deve ser accionado apenas uma vez. Remover escutas

de evento definidas por meio de funções anónimas dentro dos closures pode ser difícil. No

entanto, as funções addListener(), addDomListener(), bind() e bindDom() retornam

um manipulador GEventListener, que pode ser usado para, no final, cancelar o registo deste

manipulador.

O exemplo a seguir responde a um clique colocando um marcador no mapa. Qualquer clique

subsequente remove a escuta de evento. Em consequência disto, o código removeOverlay()

nunca é executado. Além disto, pode-se remover uma escuta de evento da própria escuta de

evento:

Page 42: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

31

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

function MyApplication() { this.counter = 0; this.map = new GMap2(document.getElementById("map")); this.map.setCenter(new GLatLng(37.4419, -122.1419), 13); var myEventListener = GEvent.bind(this.map, "click", this, function(overlay, latlng) { if (this.counter == 0) { if (latlng) { this.map.addOverlay(new GMarker(latlng)) this.counter++; } else if (overlay instanceof GMarker) { this.removeOverlay(marker) } } else { GEvent.removeListener(myEventListener); } }); } function load() { var application = new MyApplication(); }

Ilustração 9 - Resposta a um clique colocando um marcador no mapa

2.8. Controlos 2.8.1. Visão geral dos controlos

Os mapas no site http://maps.google.pt contêm elementos de interface do utilizador que

possibilitam sua interacção com todo o mapa. Estes elementos são conhecidos como controlos,

e podemos incluir variações destes controlos na aplicação da API do Google Maps. Também é

possível criar controlos personalizados próprios criando subclasses na classe GControl.

A API do Google Maps contém vários controlos incorporados que podemos usar nos mapas:

• GLargeMapControl - um controlo de panorâmica/zoom grande usado no Google

Maps. Por defeito, aparece no canto superior esquerdo do mapa.

Page 43: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

32

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

• GSmallMapControl - um controlo de panorâmica/zoom pequeno usado no Google

Maps. Por defeito, aparece no canto superior esquerdo do mapa.

• GSmallZoomControl - um controlo de zoom pequeno (sem controlos de panorâmica)

usado nas janelas de ampliação do mapa que costumam mostrar instruções de rota no

Google Maps.

• GScaleControl – controlo da escala do mapa

• GMapTypeControl - botões que permitem ao utilizador alternar tipos de mapa (como,

por exemplo, Mapa e Satélite)

• GHierarchicalMapTypeControl - selector de com botões “hierarquizados” com

todos os tipos de mapa.

• GOverviewMapControl - um mapa tipo janela de “overview” que pode ser escondido

no canto da tela.

Todos estes controlos se baseiam no objecto GControl.

GMapTypeControl e GHierarchicalMapTypeControl são casos especiais porque

também podem ser configurados. Estes controlos adicionam a funcionalidade de alterar o

GMapType usado em cada momento pelo mapa na API do Google Maps.

2.8.2. Como adicionar controlos ao mapa

É possível adicionar controlos ao mapa usando o método addControl() da classe GMap2. Por

exemplo, para adicionar o controlo de panorâmica/zoom visto no site do Google Maps ao mapa,

devemos incluir esta linha na inicialização do mapa:

map.addControl(new GLargeMapControl());

Podemos adicionar vários controlos a um mapa. Neste caso, adicionamos os controlos

integrados GSmallMapControl e GMapTypeControl, que permitem obter uma visualização

panorâmica ou aplicar zoom ao mapa e alternar entre os modos de Mapa, Satélite e Híbrido

respectivamente. Uma vez incluídos num mapa, os controlos padrão ficam logo totalmente

operacionais:

Page 44: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

33

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var map = new GMap2(document.getElementById("map"));

map.addControl(new GSmallMapControl());

map.addControl(new GMapTypeControl());

map.setCenter(new GLatLng(37.4419, -122.1419), 13);

Ilustração 10 - Mapa com controlos "small"

2.8.3. Como posicionar controlos no mapa

O método addControl usa um parâmetro GControlPosition secundário opcional que

permite especificar a posição do controlo no mapa. Este valor pode ser um dos valores a seguir,

cada um especificando um canto do mapa no qual o controlo é inserido:

• G_ANCHOR_TOP_RIGHT

• G_ANCHOR_TOP_LEFT

• G_ANCHOR_BOTTOM_RIGHT

• G_ANCHOR_BOTTOM_LEFT

Caso o argumento seja excluído, a API do Google Maps usa a posição padrão especificada pelo

controlo que é G_ANCHOR_TOP_LEFT .

O Método PGControlPosition dá-nos a hipótese de especificar um deslocamento indicando

a quantos pixels da borda do mapa o controlo deve ser colocado. Estes deslocamentos são

especificados com um objecto GSize.

Este exemplo adiciona o GMapTypeControl ao canto superior direito do mapa com 10 pixels

de preenchimento.

Clicar duas vezes em qualquer sítio do mapa remove este controlo e coloca-o no canto inferior

direito do mapa:

Page 45: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

34

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var map = new GMap2(document.getElementById"map_canvas"));

var mapTypeControl = new GMapTypeControl();

var topRight = new GControlPosition(G_ANCHOR_TOP_RIGHT, new

GSize(10,10));

var bottomRight = new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new

GSize(10,10));

map.addControl(mapTypeControl, topRight);

GEvent.addListener(map, "dblclick", function() {

map.removeControl(mapTypeControl);

map.addControl(new GMapTypeControl(), bottomRight);

});

map.addControl(new GSmallMapControl());

map.setCenter(new GLatLng(37.4419, -122.1419), 13);

Page 46: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

35

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9. Sobreposições aos mapas 2.9.1. Visão geral das sobreposições ao mapa

As sobreposições são objectos incluídos no mapa e relacionados com ele através coordenadas

de latitude/longitude que se movem quando se aplica zoom ao mapa ou se arrasta. Elas

reflectem objectos "adicionados" ao mapa para designar pontos, linhas ou áreas.

A API do Google Maps conta com vários tipos de sobreposição:

• Os pontos no mapa são exibidos usando marcadores e costumam indicar um ponto

através de um ícone personalizado. Marcadores são objectos do tipo GMarker e podem

fazer uso do tipo GIcon.

• As linhas no mapa são exibidas usando polylines (que representam uma série de

pontos). As linhas são objectos do tipo GPolyline.

• As áreas no mapa são exibidas como polígonos, se forem áreas de formato aleatório,

ou como sobreposições de solo, se forem rectangulares. Os polígonos são

semelhantes às polylines por consistirem numa série de pontos que formam uma figura

fechada e poderem assumir qualquer forma. As sobreposições de solo costumam ser

usadas em áreas que fazem mapeamento directo ou indirecto para blocos do mapa.

• O próprio mapa é exibido usando uma sobreposição de blocos. Podemos modificar

isto com o seu próprio conjunto de blocos usando uma GTileLayerOverlay ou

criando seu tipo de mapa usando um GMapType.

• A janela de informações também é um tipo especial de sobreposição. No entanto, a

janela de informações é adicionada automaticamente ao mapa e só pode haver um

objecto do tipo GInfoWindow anexado ao mapa.

Cada sobreposição implementa a interface GOverlay. As sobreposições podem ser adicionadas

a um mapa usando o método GMap2.addOverlay() e removidas usando o método

GMap2.removeOverlay(). Por defeito, a janela de informações é adicionada ao mapa sem

chamar estes métodos.

Page 47: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

36

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9.2. Marcadores

Os marcadores identificam pontos no mapa. Por defeito, eles usam G_DEFAULT_ICON, muito

embora se possa especificar um ícone personalizado. O construtor GMarker usa um GLatLng e

objectos GMarkerOptions opcionais como argumentos.

Os marcadores foram projectados para serem interactivos. Por defeito, eles recebem eventos

"click", por exemplo, e costumam ser usados em escutas de evento para exibir janelas de

informações:

var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); // Adicionar 10 marcadores ao mapa em localizações aleatórias var bounds = map.getBounds(); var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast(); var lngSpan = northEast.lng() - southWest.lng(); var latSpan = northEast.lat() - southWest.lat(); for (var i = 0; i < 10; i++) { var point = new GLatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random()); map.addOverlay(new GMarker(point)); }

Ilustração 11 - Marcadores no mapa

2.9.3. Marcadores arrastáveis

Os marcadores podem ser objectos interactivos ser clicados e arrastados para um novo local.

Neste exemplo, colocamos um marcador arrastável no mapa e escutamos alguns de seus

eventos mais simples. Marcadores arrastáveis implementam quatro tipos de eventos: click,

dragstart, drag e dragend, para indicar o status do arrastamento. Por defeito, os

marcadores são clicáveis, mas não arrastáveis e, por isto, precisam de ser inicializados com a

opção de marcador adicional draggable definida como "true". Por defeito, os marcadores

Page 48: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

37

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

arrastáveis também têm a capacidade de saltar. Caso não gostemos deste comportamento,

basta definir a opção bouncy como "false", e ele permanecerá suspenso:

var map = new GMap2(document.getElementById("map_canvas")); var center = new GLatLng(37.4419, -122.1419); map.setCenter(center, 13); var marker = new GMarker(center, {draggable: true}); GEvent.addListener(marker, "dragstart", function() { map.closeInfoWindow(); }); GEvent.addListener(marker, "dragend", function() { marker.openInfoWindowHtml("A arrastar no mapa..."); }); map.addOverlay(marker);

2.9.4. Ícones

Os marcadores podem ter um ícone personalizado em vez do ícone padrão. Definir um ícone

personalizado é algo complexo por causa do número de imagens diferentes que constituem um

objecto Icon da API do Google Maps. Um ícone deve, no mínimo, definir a imagem de primeiro

plano, o tamanho do tipo GSize e uma imagem/sombra de deslocamento para posicionamento

do ícone.

Os ícones mais simples baseiam-se no tipo G_DEFAULT_ICON. Criar um ícone com base neste

tipo permite alterar rapidamente o ícone padrão modificando apenas algumas propriedades.

No exemplo abaixo, criamos um ícone usando o tipo G_DEFAULT_ICON e modificamo-lo para

usar uma imagem diferente. É preciso ter cuidado ao usar imagens diferentes, porque elas

precisam de ser configuradas de acordo com o tamanho da imagem padrão do GoogleMaps

para que sejam exibidas correctamente:

var map = new GMap2(document.getElementById("map_canvas")); map.addControl(new GSmallMapControl()); map.setCenter(new GLatLng(37.4419, -122.1419), 13); // Criar o nosso "mini" icone de marcador var blueIcon = new GIcon(G_DEFAULT_ICON); blueIcon.image = "http://localhost/gmaps/micons/blue-dot.png"; // Definir as opções do objecto GMarkerOptions markerOptions = { icon:blueIcon }; // Adicionar 10 marcadores ao mapa em localizações aleatórias var bounds = map.getBounds(); var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast();

Page 49: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

38

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var lngSpan = northEast.lng() - southWest.lng(); var latSpan = northEast.lat() - southWest.lat(); for (var i = 0; i < 10; i++) { var point = new GLatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random()); map.addOverlay(new GMarker(point, markerOptions)); }

Ilustração 12 - Mapa com ícones

A maioria dos ícones contém uma imagem em primeiro plano e uma imagem sombreada. A

imagem sombreada deve ser criada num ângulo de 45 graus, em relação à imagem em primeiro

plano, e o canto inferior esquerdo da imagem sombreada deve permanecer alinhado com o

canto inferior esquerdo da imagem em primeiro plano do ícone. Para que os limites da imagem

sejam exibidos correctamente no mapa, as imagens sombreadas devem ser PNG de 24 bits com

transparência alfa. (Que vai ser um problema em versões do Internet Explorer inferior à 8, tendo

que usar a solução do DirectXAlfa para essas versões).

O exemplo seguinte cria um novo tipo de ícone, usando "mini marcadores" personalizados.

Precisamos especificar a imagem de primeiro plano, a imagem sombreada e os pontos nos

quais ancoramos o ícone ao mapa e a janela de informações ao ícone. O ícone é passado nas

opções definidas no objecto GMarkerOptions:

var map = new GMap2(document.getElementById("map")); map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); map.setCenter(new GLatLng(37.4419, -122.1419), 13); // Criar o nosso "mini" icone de marcador e sombra var tinyIcon = new GIcon(); tinyIcon.image = "http://localhost/gmaps/micons/mm_20_castanho.png"; tinyIcon.shadow = "http://localhost/gmaps/micons/mm_20_sombra.png"; tinyIcon.iconSize = new GSize(12, 20); tinyIcon.shadowSize = new GSize(22, 20);

Page 50: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

39

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

tinyIcon.iconAnchor = new GPoint(6, 20); tinyIcon.infoWindowAnchor = new GPoint(5, 1); // Definir as opções do objecto GMarkerOptions markerOptions = { icon:tinyIcon }; // Adicionar 10 marcadores ao mapa em localizações aleatórias var bounds = map.getBounds(); var southWest = bounds.getSouthWest(); var northEast = bounds.getNorthEast(); var lngSpan = northEast.lng() - southWest.lng(); var latSpan = northEast.lat() - southWest.lat(); for (var i = 0; i < 10; i++) { var point = new GLatLng(southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random()); map.addOverlay(new GMarker(point, markerOptions)); }

Ilustração 13 - Ícones Personalizados

Page 51: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

40

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9.5. Polylines

Os objectos GPolyline criam uma sobreposição linear no mapa. GPolyline consiste numa

série de pontos e cria uma série de segmentos de recta que ligam estes pontos numa sequência

ordenada.

2.9.5.1. Como desenhar polylines

As polylines são desenhadas como uma série de segmentos de recta no mapa. Podemos

especificar cores personalizadas, densidades e opacidades para a linha. As cores devem usar o

código HTML numérico hexadecimal, por exemplo, usar #ff0000 em vez de red. GPolyline

não compreende cores com nomes.

Os objectos GPolyline usam os recursos de desenho vectorial do browser, em caso de

disponibilidade. No Internet Explorer, o Google Maps usa VML para desenhar polylines. Noutros

browsers, usa-se SVG, se disponível.

O fragmento de código a seguir cria uma polyline vermelha com 10 pixels de largura entre dois

pontos:

var polyline = new GPolyline([ new GLatLng(37.4419, -122.1419), new GLatLng(37.4519, -122.1519) ], "#ff0000", 10); map.addOverlay(polyline);

Ilustração 14 - Mapa com polylines

Page 52: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

41

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9.6. Polígonos

Os objectos GPolygon são semelhantes a objectos GPolyline, no sentido em que eles

consistem numa série de pontos numa sequência ordenada. No entanto, em vez de terem final

aberto, os polígonos foram projectados para definir regiões numa figura fechada. Assim como

acontece com as polylines, podemos definir cores, densidades e opacidades personalizadas para

a borda do polígono (a "linha"), além de cores e opacidades personalizadas para a área de

preenchimento da região abrangida. As cores devem estar em código HTML numérico

hexadecimal.

Os objectos GPolygon, assim como os objectos GPolyline, usam os recursos de desenho

vectorial do browser, quando disponível.

O fragmento de código seguinte cria uma caixa com 10 pixéis de largura usando quatro pontos.

Este polígono é "fechado" ao retornar o caminho do segmento ao seu ponto inicial:

var map = new GMap2(document.getElementById("map_canvas")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); map.addControl(new GSmallMapControl()); GEvent.addListener(map, 'click', function(overlay, latlng) { var lat = latlng.lat(); var lon = latlng.lng(); var latOffset = 0.01; var lonOffset = 0.01; var polygon = new GPolygon([ new GLatLng(lat, lon - lonOffset), new GLatLng(lat + latOffset, lon), new GLatLng(lat, lon + lonOffset), new GLatLng(lat - latOffset, lon), new GLatLng(lat, lon - lonOffset) ], "#f33f00", 5, 1, "#ff0000", 0.2); map.addOverlay(polygon); });

Ilustração 15 - Mapa com polígonos

Page 53: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

42

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9.7. Sobreposições de KML/GeoRSS

A API do Google Maps oferece suporte aos formatos de dados KML (criados no Google Earth) e

GeoRSS para exibir informações geográficas. Estes formatos de dados são adicionados ao mapa

usando o objecto GGeoXml, cujo construtor usa o URL de um ficheiro XML acessível

publicamente. Os marcadores GGeoXml são apresentados como GMarkers, ao passo que

polylines e polígonos GGeoXml são renderizados como polylines e polígonos da API do Google

Maps.

Os objectos GGeoXml são adicionados ao mapa pelo método addOverlay(). Podemos

removê-los do mapa usando removeOverlay().

Há suporte para ficheiros KML e XML GeoRSS. GGeoXml é um objecto modular da API do

Google Maps, que não será totalmente carregado até ser usado pela primeira vez. Desta forma,

só se invoca o construtor depois do carregamento completo da página. Isto costuma ser feito

chamando o construtor GGeoXml no manipulador onload do <body>:

// A API do Google Maps API determina implicitamente se o ficheiro é //KML ou GeoRSS. var map; var geoXml; function initialize() { if (GBrowserIsCompatible()) { map = new GMap2(document.getElementById("map_canvas")); geoXml = new GGeoXml("http://localhost/gmaps/teste.kml"); map.addControl(new GLargeMapControl()); map.setCenter(new GLatLng(41.875696,-87.624207), 11); map.addControl(new GLargeMapControl()); map.addOverlay(geoXml); } }

Ilustração 16 - Sobreposição de GeoRSS/KML

Page 54: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

43

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9.8. Rotas

É possível adicionar a funcionalidade de calcular rotas entre GDirections. O objecto

GDirections solicita e recebe resultados de rotas usando strings de consulta (por exemplo,

"Guimarães, Portugal para Montalegre, Portugal") ou latitudes/longitudes textuais (por exemplo,

"40.712882, -73.967257 a 41.943181,-87.770677"). O objecto GDirections também

oferece suporte a rotas de vários pontos usando uma série de waypoints. As rotas podem ser

exibidas como uma polyline que desenha uma rota num mapa ou como série de descrições

textuais num elemento <div> (por exemplo, "Vire à direita na saída da EN103"), ou ambas.

Para usar rotas na API do Google Maps, cria-se um objecto do tipo GDirections e designa-se

um objecto GMap2 e/ou <div> para receber e exibir resultados. Por defeito, o mapa é

centralizado e vinculado pela(s) rotas(s) retornada(s), embora isto possa ser alterado com

parâmetros num objecto GDirectionOptions.

2.9.8.1. Como carregar rotas

As rotas são solicitadas usando o método GDirections.load(). Este método usa uma string

de consulta e um conjunto de parâmetros GDirectionsOptions opcionais. Estão disponíveis

as seguintes opções:

• locale especifica o idioma a ser usado para retornar os resultados, substituindo o

parâmetro da API do Google Maps hl, se fornecido. Se nem o parâmetro locale nem

o hl forem especificados, será usado o idioma padrão do browser.

• travelMode especifica o método de transporte a usar para calcular resultados.

• avoidHighways especifica que as auto-estradas devem ser evitadas ao calcular rotas.

• getPolyline especifica que o objecto de rotas deve retornar dados de polyline para

desenhar as rotas retornadas. Por defeito, o objecto GDirections só retorna dados de

polyline se houver um objecto de mapa para exibi-los.

• getSteps especifica que o objecto de rotas deve retornar instruções textuais de rotas,

mesmo que nenhum contentor <div> seja fornecido para exibir estas instruções.

• preserveViewport especificam que o mapa não deve automaticamente centralizar e

aplicar zoom na caixa delimitadora das rotas retornadas. Em vez disso, o mapa

permanecerá centralizado na janela de visualização actual.

Page 55: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

44

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

2.9.8.2. Modos de transporte

Por defeito, pressupõe-se que as rotas sejam rotas de tráfego, embora possamos solicitar outros

modos de transporte passando um GTravelMode ao chamar o método Directions.load().

São suportados os seguintes modos de transporte:

• G_TRAVEL_MODE_DRIVING indica rotas de tráfego padrão usando a malha de

transporte rodoviário

• G_TRAVEL_MODE_WALKING solicita instruções a pé através de caminhos de pedestres

e calçadas, quando disponíveis.

2.9.8.3. Manipular as rotas geradas

Se o objecto GDirections tiver sido construído com um objecto GMap2 fornecido, as rotas

retornadas conterão uma sobreposição de polyline. Se o objecto GDirections tiver sido

construído com um elemento <div> fornecido, as rotas retornadas conterão um objecto

GRoute, com um conjunto de objectos GStep. Se as rotas forem multiponto, as rotas

retornadas irão conter vários objectos GRoute, cada um consistindo numa série de objectos

GStep.

Depois de as rotas serem retornadas, por defeito, o mapa exibirá uma polyline mostrando a rota,

enquanto instruções textuais da rota serão mostradas no <div> fornecido para este propósito.

O objecto GDirections também armazenará internamente resultados que podem ser

recuperados usando os métodos GDirections.getPolyline() e/ou

GDirections.getRoute(i:Number).

As etapas de uma rota podem ser recuperadas usando o método

GRoute.getStep(i:Number), e o resumo HTML desta etapa pode ser recuperado usando

GStep.getDescriptionHtml().

Page 56: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

45

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

O objecto GDirections também dispara três eventos que podem ser interceptados:

• "load": Este evento é despoletado quando um resultado de rota é retornado com êxito,

mas antes que quaisquer elementos de sobreposição sejam adicionados ao

mapa/painel.

• "addoverlay": Este evento é disparado depois dos componentes das instruções

textuais das rotas e/ou de polylines forem adicionados ao mapa e/ou a elementos DIV.

• "error": Este evento é disparado se uma solicitação de rotas resultar em erro. Pode-se

usar GDirections.getStatus() para saber mais sobre o erro.

// Criar um objecto directions e registar um mapa e DIV para receber // as rotas geradas var map; var directionsPanel; var directions; function initialize() { map = new GMap2(document.getElementById("map_canvas")); directionsPanel = document.getElementById("my_textual_div"); map.setCenter(new GLatLng(49.496675,-102.65625), 3); directions = new GDirections(map, directionsPanel); directions.load("from: Guimarães, Portugal to: Piscinas Municipais, Montalegre, Portugal"); }

Ilustração 17 - Mapa com rota de viagem

Page 57: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

46

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Desenvolvimento do Sistema

Depois de tomadas as decisões quanto às tecnologias a utilizar e explorar/estudar as

possibilidades da API do Google Maps, foi posto em prática o conhecimento resultante desse

estudo e iniciaram-se as etapas de desenvolvimento do sistema.

3. Modelação de Dados Em qualquer projecto que envolva bases de dados relacionais devemos em primeiro lugar

(depois de termos os requisitos do sistema) elaborar o modelo da base de dados. Esta

modelação deve ser a base sólida de todas as outras camadas.

Note-se que a modelação inclui a interacção com as tabelas já existentes no sistema de gestão

de conteúdos criado anteriormente, fazendo uso de algumas das particularidades do modelo de

dados desse mesmo sistema.

Nota: No diagrama abaixo apenas são mostrados, em cada tabela, os campos relevantes para

construir as relações entre elas.

3.1. Modelo ER (entidades e relacionamentos)

Ilustração 18 - Modelo ER da Base de Dados

Page 58: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

47

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

3.2. Descrição das Tabelas da Base de Dados

Tabela Descrição

freguesias Tabela com informação textual sobre cada freguesia. Campos relevantes para

a aplicação: contêm as coordenadas da sede de freguesia. Esta tabela já

existia no CMS.

lugares Contém as informações sobre os lugares de cada freguesia. Tem como FK

(foreign key) o Id da freguesia. Contém as coordenadas de cada lugar. Esta

tabela já existia no CMS.

tipo_localizacoes Esta tabela contém os tipos de localizações. Estes tipos de localizações

podem ser criados dinamicamente e permitir colocar diferentes marcadores

no mapa, por exemplo: Restaurantes, Hotéis, Bibliotecas, Museus, etc. Estão

ainda classificadas segundo a sua utilidade:

'dormir','comer','divertir','geral'; permitindo gerar mapas

por estas utilidades. Ao criar um tipo de localização vamos carregar também

um ícone personalizado para lhe associar.

localizacoes Esta é a tabela central de todo o sistema: permite-nos guardar os pontos de

interesse que vamos inserindo no mapa. As localizações estarão classificadas

por tipo (ligação á tabela tipo_localizacao) mas também por lugar,

permitindo uma compartimentação fácil dos pontos por freguesia, por

exemplo. Qualquer localização está ligada a algum conteúdo (o marcador

remete para esse conteúdo), podendo ser uma notícia, página, etc Esta

ligação é feita de um modo especial pelas duas tabelas seguintes.

tipos_documento Esta tabela é explicada no ponto Particularidades do projecto do modelo

de dados. Aí é explicado a forma particular que permite ligar os pontos a

qualquer tipo de conteúdo. Esta tabela já existia no CMS.

docs Esta tabela não existe, só foi usada para exemplificar a relação com os

diversos tipos de conteúdo. Também se entende o funcionamento no ponto

Particularidades do projecto do modelo de dados.

Page 59: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

48

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

3.3. Dicionário de dados CREATE TABLE `freguesias` ( `Id` int(6) unsigned NOT NULL auto_increment, `nome` varchar(55) default NULL, `lat` varchar(254) default NULL, `lon` varchar(254) default NULL, `pagina` longtext, `pagina_en` longtext, `pagina_fr` longtext, `hits` int(11) default '0', PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED; CREATE TABLE `lugares` ( `Id` int(6) unsigned NOT NULL auto_increment, `Id_freguesia` tinyint(4) NOT NULL default '0', `nome` char(65) default NULL, `cod_postal` char(10) character set latin1 default '5470', `lat` char(254) character set latin1 default NULL, `lon` char(254) character set latin1 default NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED; CREATE TABLE `tipo_localizacoes` ( `Id` bigint(20) unsigned NOT NULL auto_increment, `nome` char(255) default NULL COMMENT 'Nome', `utilidade` enum('dormir','comer','divertir','geral') default 'comer' COMMENT 'Utilidade', `icone` char(255) NOT NULL default '' COMMENT 'Latitude', PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED COMMENT='Tipos de Objectos georeferenciados'; CREATE TABLE `localizacoes` ( `Id` bigint(20) unsigned NOT NULL auto_increment, `nome` varchar(255) default NULL COMMENT 'Nome', `descricao` blob COMMENT 'Pequeno texto descritivo', `lat` varchar(65) NOT NULL default '' COMMENT 'Latitude', `lon` varchar(65) default NULL COMMENT 'Longitude', `tipo` int(8) default NULL COMMENT 'Tipo de Localizacao', `lugar` int(6) default NULL COMMENT 'Aldeia', `tipo_doc` varchar(10) default NULL COMMENT 'tipo de documento relacionado', `Id_doc` int(8) default NULL COMMENT 'Id do documento relacionado', PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Georeferenciacao'; CREATE TABLE `tipos_documento` ( `tipo_doc` char(4) NOT NULL default 'DF' COMMENT 'Chave primaria', `nome` char(20) default 'DEFAULT' COMMENT 'nome do documento', `tabela` char(25) default NULL, `campo_titulo` char(25) default NULL, PRIMARY KEY (`tipo_doc`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tipos de documentos

disponiveis';

Page 60: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

49

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

3.4. Particularidades da Modelação de Dados Esta base de dados tem algumas particularidades que fazem com que seja difícil entender o

esquema conceptual e relacional sem algumas explicações.

Nos tipos de conteúdos (tipos de documento), é onde a base de dados tem as suas

particularidades: Em primeiro lugar, foi criada uma tabela chamada tipos_documento, com

os seguintes campos: tipo_doc (chave primária), nome, tabela, campo_titulo.

O tipo_doc é um código de dois caracteres único para cada documento, depois o nome do

documento, o nome da tabela, onde se encontram armazenados esses documentos e qual o

campo da tabela que lhe dá titulo:

Esta tabela é uma das chaves para o funcionamento do sistema de gestão de conteúdos. A partir

do momento em que se criaram siglas para os diversos tipos de conteúdos, elas foram também

usadas para nomear os scripts php que servem para manipular esses tipos de conteúdo. Esses

nomes foram compostos a partir da sua chave tipo_doc. Por exemplo o script para retornar os

dados de uma notícia e apresentá-los tem o nome de showNT.php, tal como o de mostrar uma

informação tem o nome de showIF.php, ou o de mostrar um regulamento tem o nome de

showRG.php. Tal como o de listar as notícias tem o nome de listNT.php, ou o script para

editar tem o nome editNT.php, o que elimina deleteNT.php e assim sucessivamente para

todas as siglas e respectivos tipos de conteúdo.

Isto permite gerar links para qualquer documento a partir da tabela localizacoes

passando os valores guardados nas entradas dessa mesma tabela. Por exemplo, um ponto geo-

referenciado associado à Página com o Id 123 terá nos campos Id_doc e tipo_doc

respectivamente os valores “123” e “PG” permitindo gerar facilmente um link do tipo

http://www.cm-montalegre.pt/showPG.php?Id=123.

Page 61: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

50

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4. Mapa Interactivo Depois de definido o modelo de dados, iniciei o desenvolvimento do mapa interactivo. O front-

end é composto por diversas camadas de software que em conjunto geram o mapa, os

marcadores e as info-windows (janelas de informações) associadas a cada ponto.

4.1. Front-end do mapa A parte visível (aos utilizadores) do mapa depende de várias camadas de software para ser

gerada.

Estas camadas interagem entre si de modo a consultar os dados da BD, processá-los, gerar o

ficheiro XML de marcadores e as info-windows. Na figura seguinte podemos ver um esquema de

interacção entre as camadas:

Ilustração 19 - Camadas do Front-End

Javascript + HTML + CSS

(API Google Maps)

XMLHttpRequest

PHP

MySQL

XML

XMLHttpRequest

Page 62: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

51

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Antes de detalhar a implementação, vamos ver o aspecto e funcionalidades do front-end de um

dos mapas gerados:

Ilustração 20 - Exemplo de mapa gerado

Page 63: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

52

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Detalhe da info-window:

Ilustração 21 - Mapa com Info-Window

Aba da info-window que permite gerar rota até ao ponto escolhido:

Ilustração 22 - Aba para geração da rota

As rotas podem ser geradas tendo o marcador tanto como ponto de partida ou como ponto de

chegada.

Ilustração 23 - Exemplo de rota

Page 64: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

53

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Além do trajecto desenhado sobre o mapa, a geração de rotas contempla ainda a geração

descritiva do trajecto:

Ilustração 24 - Listagem descritiva do trajecto

Os tabs na parte superior do mapa implementam na prática o que foi descrito na modelação de

dados como a “utilidade” de cada um dos tipos de marcadores implementados: comer, dormir,

divertir e geral:

Ilustração 25 - Tabs superiores do mapa

Page 65: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

54

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Estas tabs actualizam o mapa e também a lista descritiva dos marcadores, usando AJAX, ou seja

sem recarregar a página.

Ilustração 26 - Mapa com o tema "Onde Dormir"

A listagem dos marcadores também é actualizada assincronamente. Esta lista permite, ao

clicar, localizar o marcador no mapa, abrindo a respectiva info-window:

Ilustração 27 - Marcador aberto pelo link da lista descritiva

Page 66: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

55

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.1. Interface do Mapa (HTML + JavaScript e CSS)

Para gerar o mapa, precisamos primeiro de delinear o layout da página (HTML+CSS),

respeitando o design já incluído no site. Precisamos depois de carregar o JavaScript necessário

para implementar a comunicação com a API Google Maps.

Tal como já tinha explicado nas experiências feitas com a API, no head da página precisamos de

carregar o script da API e acrescentar a função GUnload()ao evento onunload do body :

<script src="http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=xxxxxxxxxxxxxxxxx" type="text/JavaScript"></script> <body onunload="GUnload()">

Seguidamente adicionamos os contentores que vão receber o mapa, e no meu caso também um

contentor para a lista de marcadores e outro para as rotas:

<table style="border-color:#999999; border-width:1px; border-style:solid;" > <tr> <td> <div id="map" style="width: 685px; height: 600px; overflow:visible"></div> </td> </tr> <tr> <td width=685 valign="top" style="border-color:#999999; border-width:1px; border-style:solid;"> <div id="side_bar" style="color: #4444ff; line-height:15px; height:auto; overflow:auto;"></div> <div id="directions" style="overflow:auto; height:auto; visibility:hidden"> <hr color="#999999" style="border-color:#999999; color:#999999;"> <br /> </div> <div align="right"> <input type="button" id="botaolimpa" class="input2" name="botaolimpa" onclick="limpa_rota()" value="Limpar Rota" disabled="disabled" style="visibility:hidden;" /> </div> </td> </tr> </table>

Neste caso a div que vai receber os mapas tem o identificador (id) “map”, a que recebe a lista de

pontos tem o id “side_bar” (que por acaso não fica lateral - “side_bar” ao mapa: na versão

final fica por baixo do mapa, mas como já tinha muito código com esta nomenclatura e isto não

me atrapalha nada, deixei ficar) e a que recebe os pontos o id “directions”.

O mapa reutiliza o CSS geral da página, contendo alguns estilos inline aplicados aos contentores.

Page 67: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

56

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ainda no capítulo do interface, temos as tabs que se encontram por cima do mapa e que

permitem carregar os pontos pelos diversos tipos de utilidade: Onde Comer, Onde Dormir,

Pontos de Interesse/Diversão e Localizações Úteis.

<div class="borders_tab" id=comer onclick='mapa_pontos("http://www.cm-montalegre.pt/gmaps/get_pontos_geral.php?&util=comer", 41.79179268262892, -7.86895751953125, 11, "Onde Comer:")' > Onde Comer</div> <div class="borders_tab" id=dormir onclick='mapa_pontos("http://www.cm-montalegre.pt/gmaps/get_pontos_geral.php?&util=dormir", 41.79179268262892, -7.86895751953125, 11, "Onde Dormir:")' > Onde Dormir</div> <div class="borders_tab" id=divertir onclick='mapa_pontos("http://www.cm-montalegre.pt/gmaps/get_pontos_geral.php?&util=divertir", 41.79179268262892, -7.86895751953125, 11, "Pontos de Interesse/Diversão:")' > Pontos de Interesse/Divers&atilde;o</div>

<div class="borders_tab" id=geral

onclick='mapa_pontos("http://www.cm-

montalegre.pt/gmaps/get_pontos_geral.php?&util=geral",

41.79179268262892, -7.86895751953125, 11, "Localizações Úteis:")'>

Localiza&ccedil;&otilde;es &Uacute;teis</div>

Ao clicar em cada um destes tabs é chamada uma função JavaScript chamada

mapa_pontos(), a qual leva como parâmetros o ficheiro XML de marcadores, a latitude e

longitude do centro do mapa, o nível de zoom e o nome do conjunto de pontos:

mapa_pontos("http://www.cm-

montalegre.pt/gmaps/get_pontos_geral.php?&util=comer",

41.79179268262892, -7.86895751953125, 11, "Onde Comer:")

Esta é a função que invoca o XMLHttpRequest(), sendo a função nuclear de todo o front-end

do mapa.

Deixando a formatação do interface em si, temos um conjunto de funções auxiliares em

JavaScript que são necessárias para a interligação à camada de dados, mas também para

implementar as funcionalidades dos controlos disponíveis ao utilizador.

Page 68: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

57

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.1.1. Inicializações Básicas (JavaScript – API)

// variável para guardar html da lista de pontos e array para guardar os marcadores var side_bar_html = ""; var gmarkers = []; // arrays que guardam as variantes do html da tab principal da info-window var htmls = []; var names = []; // arrays que guardam as variantes do html da tab rotas da info-window var htmls2 = []; // contador var i = 0; // arrays que guardam as variantes do html da info-window quando o formulario das rotas está aberto var to_htmls = []; var from_htmls = []; // criar o mapa var map = new GMap2(document.getElementById("map")); //limites do concelho em kmz * explicação detalhada abaixo geoXml2 = new GGeoXml("http://www.cm-montalegre.pt/gmaps/limites.kmz"); // === criar objecto GDirections para rotas === var gdir = new GDirections(map, document.getElementById("directions")); // === Array para descodificar códigos de erro === var reasons=[]; reasons[G_GEO_SUCCESS] = "Successo"; reasons[G_GEO_MISSING_ADDRESS] = "Morada em Falta: A morada ou não é encontrada ou tem um valor errado. (Insira: Localidade, Concelho, País)"; reasons[G_GEO_UNKNOWN_ADDRESS] = "Morada com poucos dados: Mais do que uma morada encontarada com esse nome. (Insira: Localidade, Concelho, País)"; reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Morada não disponível: As coordenadas dessa morada não podem ser revelados por questões legais."; reasons[G_GEO_BAD_KEY] = "API Key: API key invalida ou nao e para este site/dominio"; reasons[G_GEO_TOO_MANY_QUERIES] = "Demasiados Pedidos: A quota de pedidos de georeferenciacao pra este site ultrapassou o maximo diario."; reasons[G_GEO_SERVER_ERROR] = "Erro de Servidor: O Pedido nao pode ser processado."; reasons[G_GEO_BAD_REQUEST] = "O pedido de rota nao foi processado com sucesso."; reasons[G_GEO_MISSING_QUERY] = "Nao especificou nenhuma morada para pesquisar."; reasons[G_GEO_UNKNOWN_DIRECTIONS] = "Impossivel gerar rota entre os dois pontos. (Insira: Localidade, Concelho, País)";

Page 69: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

58

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.1.2. Funções auxiliares JavaScript do front-end

//===Função que permite criar um marcador – parâmetros incluem //coordenadas do ponto, nome, html da tab 1 (default) e tab 2 (rotas) // e também o ícone==== function createMarker(point,name,html1,html2,icone) { markerOptions = { icon:icone }; var marker = new GMarker(point, markerOptions); // Versão da info-window com o formulário "Daqui" aberto to_htmls[i] = html2 + '<br>Trajecto: <b>Para Aqui</b> - <a href="JavaScript:fromhere(' + i + ')">Daqui</a><br>' + '<br>Ponto de Partida:<form action="JavaScript:getDirections()">' + '<input type="text" SIZE=40 MAXLENGTH=40 name="saddr" id="saddr" value="" /><br>' + '<INPUT value="Ver Rota" TYPE="SUBMIT">' + '<input type="hidden" id="daddr" value="'+name+"@"+ point.lat() + ',' + point.lng() + '"/>'; // Info-window com o formulário "Para Aqui" aberto from_htmls[i] = html2 + '<br>Trajecto: <a href="JavaScript:tohere(' + i + ')">Para Aqui</a> - <b>Daqui</b><br>' + '<br>Ponto de Chegada:<form action="JavaScript:getDirections()">' + '<input type="text" SIZE=40 MAXLENGTH=40 name="daddr" id="daddr" value="" /><br>' + '<INPUT value="Ver Rota" TYPE="SUBMIT">' + '<input type="hidden" id="saddr" value="'+name+"@"+ point.lat() + ',' + point.lng() + '"/>'; // Versão inactiva da informação de rotas html2 = html2 + '<br>Trajecto: <a href="JavaScript:tohere('+i+')">Para aqui</a> - <a href="JavaScript:fromhere('+i+')">Daqui</a><br>'; GEvent.addListener(marker, "click", function() { //marker.openInfoWindowHtml(html2); marker.openInfoWindowTabsHtml([new GInfoWindowTab(name,html1), new GInfoWindowTab("Rota",html2)]); }); // guardam os dados que vamos precisar para gerar a side_bar gmarkers[i] = marker; htmls[i] = html2; names[i] = name; htmls2[i] = html1; // addicionar seta ao html da side_bar e link javascrip para abrir info-window side_bar_html += '<img src="images/seta_small.gif" hspace="3" align="absmiddle"><a href="JavaScript:myclick(' + i + ')">' + name + '</a><br>'; i++; return marker; }

Page 70: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

59

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

// === Função para ouvir Erros do objecto Directions === GEvent.addListener(gdir, "error", function() { var code = gdir.getStatus().code; var reason="Code "+code; if (reasons[code]) { reason = reasons[code] } alert("Trajecto não encontrado: "+reason); }); // ===== Função que faz o pedido de rotas ao google===== function getDirections() { var saddr = document.getElementById("saddr").value var daddr = document.getElementById("daddr").value document.getElementById("botaolimpa").disabled = false; document.getElementById("botaolimpa").style.visibility = "visible"; document.getElementById("directions").style.visibility = "visible"; gdir.load("from: "+saddr+" to: "+daddr); } // == Esta função abre as info windows respectivas dos marcadores == function myclick(i) {

gmarkers[i].openInfoWindowTabsHtml([new GInfoWindowTab(names[i],htmls2[i]), new GInfoWindowTab("Rota",htmls[i])]);

} // funções que abrem os formulários das rotas daqui e para aqui function tohere(i) {

gmarkers[i].openInfoWindowTabsHtml([ new GInfoWindowTab("Rota",to_htmls[i]), new GInfoWindowTab(names[i],htmls2[i]) ]);

//map.getInfoWindow().selectTab(1); } function fromhere(i) {

gmarkers[i].openInfoWindowTabsHtml([new GInfoWindowTab("Rota",from_htmls[i]), new GInfoWindowTab(names[i],htmls2[i])]);

//map.getInfoWindow().selectTab(1); } //limpar a rota do mapa function limpa_rota(){ gdir.clear(); map.returnToSavedPosition(); document.getElementById("botaolimpa").disabled = true; document.getElementById("botaolimpa").style.visibility = "hidden"; document.getElementById("directions").style.visibility = "hidden"; }

Page 71: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

60

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Todas as funções descritas anteriormente servem para interagir com o mapa (como podemos

verificar nos comentários explicativos), mas nenhuma delas tem interacção com a camada de

dados. Isso vai ser feito pela função que descrevemos a seguir, que faz uso de chamadas a

todas elas.

4.1.1.3. Chamadas à camada de dados – XM LHttpRequest()

Todo o código visto anteriormente prepara/ajuda a preparar o mapa para receber o seu

elemento mais importante: os marcadores. Tudo gira em torno da função seguinte: a função

mapa_pontos(). Esta função faz as chamadas às camadas abaixo e recebe as respostas.

Recorre depois às funções auxiliares já descritas acima para formatar e dar funcionalidades aos

dados em bruto recebidos através do mecanismo XMLHttpRequest(). Toda a função está

explicada nos comentários ao código, e cujas variáveis de input já forma explicadas

anteriormente:

function mapa_pontos(dados, lat, lon, zoom, points_title){ //limpa o mapa, criando um objecto novo. map = new GMap2(document.getElementById("map")); // por controlos de zoom e panning no mapa map.setUIToDefault(); map.addControl(new GHierarchicalMapTypeControl()); map.setCenter(new GLatLng(lat,lon), zoom); // criar um objecto GDirections (rotas) e atribuir-lhe a div de destino “directions” gdir = new GDirections(map, document.getElementById("directions")); // inicializar as variáveis que vão receber o html das tabs, e da side_bar side_bar_html = "<b><font color=#000000>"+points_title+"</font></b><br /><br />"; gmarkers = []; htmls = []; names = []; htmls2 = []; i = 0; // arrays que guardam as variantes do html da info-window quando o formulario das rotas está aberto to_htmls = []; from_htmls = []; //testar se o browser tem capacidade para a API if (GBrowserIsCompatible()) {

Page 72: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

61

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//icones por defeito das freguesias (usado só nos mapas das freguesias) var icon = new GIcon(); icon.image = "http://www.cm-montalegre.pt/gmaps/markers/sede_freg.png"; icon.shadow = "http://www.cm-montalegre.pt/gmaps/markers/shadow2.png"; //tamanho dos icones e das ancoras das janelas icon.iconSize = new GSize(30, 30); icon.shadowSize = new GSize(45, 30); icon.iconAnchor = new GPoint(15, 30); icon.infoWindowAnchor = new GPoint(15, 30); // Método da API do Google Maps para criar uma instância do XMLHttpRequest, independentemente do browser. var request = GXmlHttp.create(); //chamada ao XMLHttpRequest usando método GET e o endereço do ficheiro de dados passado em parâmetro na função mapa_pontos request.open("GET", dados, true); //usamos um event listener que vai disparar a função de processamento dos dados retornados quando o estado do pedido muda: "onreadystatechange" request.onreadystatechange = function() { // se o pedido está no estado 4 (carregado com sucesso) vamos processar o XML retornado if (request.readyState == 4) { // carregar os dados XML numa variável var xmlDoc = GXml.parse(request.responseText); // obter o array de marcadores e percorre-lo var markers = xmlDoc.documentElement.getElementsByTagName("marker"); for (var i = 0; i < markers.length; i++) { // obtem os atributos de cada marcador var lat = parseFloat(markers[i].getAttribute("lat")); var lng = parseFloat(markers[i].getAttribute("lng")); var point = new GLatLng(lat,lng); var html = markers[i].getAttribute("html"); var label = markers[i].getAttribute("label"); var icone = markers[i].getAttribute("icone"); var size = markers[i].getAttribute("size"); //gerar os ícones e html das info-windows através dos dados lidos do XML icon.iconSize = new GSize(size, size); icon.image = "http://www.cm-montalegre.pt/gmaps/markers/"+icone;

Page 73: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

62

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

icon.shadow = "http://www.cm-montalegre.pt/gmaps/markers/shadow.png"; //Chama a função createMarker, que além de criar o marcador, gera as info-windows, rotas, etc... var marker = createMarker(point,label,html,"",icon); //ADICIONA EFECTIVAMENTE O MARCADOR AO MAPA map.addOverlay(marker); } // por o html assemblado na variavel side_bar_html (atenção que isto é feito na função createMarker)aqui só é insertido na div “side_bar” document.getElementById("side_bar").innerHTML = side_bar_html; } } // no caso de o estado não ser 4... request.send(null); } //browser nao compatível, mensagem de erro else { alert("Desculpe, os mapas Google Maps nao são compatíveis com este browser"); } // guardar posição do mapa map.savePosition(); }

Algumas considerações/explicações adicionais sobre o código acima:

Nem todos os browsers oferecem suporte à API do Google, e nem todos os utilizadores têm o

JavaScript activado. Foi usado um elemento <noscript> para detectar a situação em que não

há JavaScript e uso GBrowserIsCompatible () para detectar um browser não compatível.

A função createMarker() não só cria o marcador e o seu manipulador de eventos, mas

também faz com que cópias locais do "marcador" e variáveis "html" sejam preservados para

uso posterior quando os eventos forem accionados. Esta é a característica especial do JavaScript

já explicado anteriormente chamada "function closure".

Podemos usar quase qualquer html válido nas info-windows, desde que o browser possa calcular

a altura e a largura necessária antes da apresentação.

Page 74: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

63

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Em todas as situações em que foi usado html que precisa de aspas, foi necessário usar aspas

simples na string de JavaScript e aspas normais no html interno.

4.1.1.4. Problemas que surgiram durante esta fase

Todas estas situações aparentemente triviais tiveram resoluções algo demoradas e várias

iterações de tentativa/erro antes de chegar a estas conclusões:

1. O conteúdo da info-window herda a formatação do elemento pai. Se o <div> do mapa

for posicionado com <center>, então o conteúdo da janela de informação será

centralizado.

2. O código que decide o tamanho da info-window é executado antes da herança de estilos

CSS ocorrer. Se o conteúdo da janela de informação, em seguida, herdar estilos que

alterem o seu tamanho, por exemplo, font-size, o tamanho da janela de informação

pode não chegar para todo o conteúdo que contém. Ainda não foi encontrada uma

solução satisfatória para este problema…

3. Não colocar JavaScript dentro de uma <table> ou <div>, funciona no Firefox, mas

não no Internet Explorer. Onde colocar o JavaScript: pouco antes do </body>, e no

header dentro de uma função onLoad().

4. Esta foi de difícil descoberta e resolução: Numa função onLoad() não se pode ter o

nome "onload()" em minúsculas, porque é uma palavra reservada no Firefox…

5. Para usar tabelas ou divs dentro de uma info-window, é necessário especificar a largura

e altura. Se usarmos "width = 100%", o browser não é capaz de calcular o tamanho

da janela antes da apresentação. Isto dá resultados um bocado estranhos, desde janelas

que não aprecem, até aos tamanhos mais disparatados de janela.

6. Verificar que o ID do div do mapa é único. Ter um hyperlink (por exemplo para o mapa

do site, como neste caso) em que o id = "map" gera confusão, demorando a chegar à

causa do problema, pois é uma das coisas em que não se pensa facilmente.

Page 75: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

64

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.2. Camadas PHP, MySQL e XML

Estas três camadas são implementadas com um script PHP que é chamado pela função

mapa_pontos, através do XMLHttpRequest(). Este script, conciso e elegante, faz a consulta

à base de dados e gera, como resposta, um ficheiro XML “on-the-fly” com os marcadores para

serem processados pelo JavaScript do mapa. Todos os detalhes estão nos comentários ao

código:

<markers> <?php // importar variaves do endereço import_request_variables("gP"); // Configurar a ligação ao MySQL $MySqlHostname = "localhost"; //nome da mquina $MySqlUsername = "xpto_user"; //login $MySqlPassword = "xpto"; //password $MySqlDatabase = "xpto_db"; //base de dados $dblink=MYSQL_CONNECT($MySqlHostname, $MySqlUsername, $MySqlPassword) OR DIE("Falhou ligacao a base de dados."); //efectuar ligação @mysql_select_db("$MySqlDatabase") or die( "Impossvel escolher base de dados."); //Query SQL à base de dados construído dinamicamente a partir das variáveis de endereço $query = " select * from localizacoes where tipo in ( SELECT Id FROM tipo_localizacoes where utilidade = '$util' ) ORDER BY nome ASC "; $query = mysql_query($query); // Percorrer o array de dados while ($row=mysql_fetch_assoc($query)){ // Query para saber o ícone associado a cada ponto, localizado na tabela de tipo_localizacoes $res = mysql_query(" select * from tipo_localizacoes where Id = ".$row['tipo']." "); $icone = mysql_result($res,0,"icone"); //gerar o html para linkar á pgina de detalhe do marcador... // todas as entidades htnl estão codificadas (&gt; &lt; etc) $row['descricao'] = $row['descricao']."&lt;br&gt;&lt;br&gt;&lt;a href=show".$row['tipo_doc'].".php?Id=".$row['Id_doc']." target=_blank &gt;Mais detalhes »»&lt;/a&gt;"; //substituir os new lines por codigo html <br> $html = str_replace("\n","&lt;br&gt;", $row['descricao']); ?> <!-- gerar um row XML de um marcador --> <marker lat="<?php echo $row['lat']; ?>" lng="<?php echo $row['lon']; ?>" html="<?php echo $html; ?>" label="<?php echo $row['nome']; ?>" icone="<?php echo $icone; ?>" size="35" /> <? } ?> </markers>

Page 76: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

65

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.2.1. Exemplo de output XML gerado

Este é o XML gerado quando se chama o script desta forma:

http://www.cm-montalegre.pt/gmaps/get_pontos_geral.php?&util=comer

Resultado: <markers> <marker lat="41.72072119663713" lng="-7.885565757751465" html="Vila da Ponte &lt;br&gt;5470 – 543 Vila da Ponte &lt;br&gt;Telef.: 276556235&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="A CISTA" icone="restaurante.png" size="35" /> <marker lat="41.82512431907592" lng="-7.7904438972473144" html="Rª do Reigoso &lt;br&gt;5470 – 238 Montalegre &lt;br&gt;Telef.: 276512240&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="A MURALHA" icone="restaurante.png" size="35" /> <marker lat="41.82461264002405" lng="-7.792525291442871" html="Rª D. Afonso III &lt;br&gt;5470 – 241 Montalegre &lt;br&gt;Telem.935125010&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="ADEGA O FUMEIRO" icone="restaurante.png" size="35" />

… <marker lat="41.82522025844289" lng="-7.792160511016846" html="Rª dos Ferradores &lt;br&gt;www.djoao.com &lt;br&gt;5470 – 242 Montalegre &lt;br&gt;Telef.:276511388&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="D. JOÃO" icone="restaurante.png" size="35" /> <marker lat="41.8417748712" lng="-7.9507951436" html="Pitões &lt;br&gt;5470 – 370 Pitões das Júnias &lt;br&gt;Telef.: 276566288&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="D. PEDRO" icone="restaurante.png" size="35" /> <marker lat="41.75605868491745" lng="-7.848787307739258" html="Parafita &lt;br&gt;5470 – 525 Viade de Baixo &lt;br&gt;Telef.: 276556123&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="DIAS PARAFITA" icone="restaurante.png" size="35" /> <marker lat="41.82115869946618" lng="-7.7931904792785644" html="Rª do Avelar &lt;br&gt;5470 – 235 Montalegre &lt;br&gt;Telef.: 276512664&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="FALTA D’AR" icone="restaurante.png" size="35" /> <marker lat="41.7638879919" lng="-7.9461232579" html="Paradela do Rio &lt;br&gt;5470 – 362 Paradela do Rio &lt;br&gt;Telef.: 276566122&lt;br&gt;&lt;br&gt;&lt;a href=showPG.php?Id=119 target=_blank &gt;Mais detalhes »»&lt;/a&gt;" label="FLOR DO RIO" icone="restaurante.png" size="35" /> </markers>

Page 77: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

66

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

4.1.2.2. Problemas que surgiram durante esta fase

Tal como na fase anterior, existiram nesta situações aparentemente triviais que tiveram

resoluções algo demoradas e várias iterações de tentativa/erro antes de chegar a estas

conclusões:

1. Todos os dados retornados do XML são considerados como strings.

2. Evitar, no XML, nomes de atributos que são palavras reservadas em JavaScript ou

HTML. Por exemplo "name" é uma palavra reservada…

3. Strings de dados XML não podem conter os caracteres “&”, “<” ou “>”. Temos que usar

&amp;, &lt; e &gt;, que serão convertidos no html para “&”, “<” e “>”.

4. Não se pode ter linhas em branco ou espaços antes da primeira tag no ficheiro XML.

5. Não confundir a matriz de objectos marcador "gmarkers []" e o array de dados html dos

marcadores "markers[]"…

6. Para ver o resultado da geração do ficheiro XML tem que se utilizar o comando "ver

código fonte" do browser.

4.2. Mapa das freguesias: um mapa com particularidades

Ilustração 28 - Mapa de uma freguesia com as linhas divisórias entre as freguesias e tabs temáticas

Page 78: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

67

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Depois de ter todo o trabalho concluído para os mapas turísticos, foi reaproveitado o código para

gerar os mapas incluídos na plataforma das freguesias do site. Estes mapas reaproveitam todos

os dados turísticos gerais, filtrando apenas os que pertencem a cada freguesia em particular.

Adicionam também mais um tema ao mapa, o “Mapa da Freguesia” que contém marcadores de

todas as localidades da freguesia e a indicação da sede com um marcador diferente, como pode

ser visto acima, na ilustração 28.

Ilustração 29 - Gerar uma rota até um lugar de uma freguesia

É possível também gerar rotas até às localidades, tal como nos mapas anteriores.

4.2.1. Acrescentar as delimitações das freguesias ao mapa

A partir do momento em que se decidiu utilizar mapas nas páginas das freguesias, isso só faria

sentido apresentando as linhas que delimitam essa freguesia.

Depois de todo o estudo feito com a API, a solução óbvia seria sobrepor um ficheiro KML que

contivesse os polígonos das freguesias. Problema: como o construir?

Tínhamos esses dados disponíveis do Gabinete de SIG do Município de Montalegre, mas em

formato shape-file (shp) da plataforma ArcGis. Além disto, todos os dados geográficos do

município estão no sistema de coordenadas Hayford-Gauss Datum73 e tanto o Google Earth

como o Google Maps operam com o sistema de coordenadasWGS84. A versão do ArcGis que

tínhamos disponível ainda não possuía a funcionalidade de exportar para KML.

Depois de alguma investigação na internet e em bibliografia, encontrou-se uma ferramenta

chamada “SHP2KML”, que é freeware. Além de converter o formato, permite ainda conversão

de coordenadas. À primeira parecia encontrada a solução, mas foi mais tarde verificado que só

parcialmente. A ferramenta tem uma limitação: não consegue converter sistemas de

coordenadas projectadas (como é o caso do Datum73) em sistemas de coordenadas geográficas

(como é o WGS84).

Page 79: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

68

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Pelo menos parte do problema estava resolvida: tínhamos os polígonos em KML, mas em

coordenadas Datum73.

Ilustração 30 - Ferramenta SHP2KML

Depois de muita procura, muitos softwares testados e de muitas versões de limites de freguesias

que apareciam em sítios errados do globo, (coordenadas erradas), foi encontrada a ferramenta

que finalmente permitiu converter com sucesso entre os dois sistemas de coordenadas: o

software Franson CoordTrans. Esta ferramenta não é grátis, por isso foi necessário adquirir uma

licença.

Ilustração 31 - Franson CoordTrans

Com esta aplicação foi convertido correctamente o SHP para a posterior transformação no KML

a carregar nos mapas das freguesias, e com sucesso, como pode ser visto na ilustração 28.

Page 80: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

69

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

5. Back-Office Para que os mapas sejam criados e geridos dinamicamente necessitamos de um sistema de

back-office que permita gerir de forma eficaz quer a categorização de marcadores quer a sua

associação a conteúdos.

Todo o back-office de georeferenciação foi integrado no CMS (Content Management System –

Sistema de Gestão de Conteúdos) já em produção e portanto a questão de autenticação e

permissões foi assegurada com os mecanismos pré existentes.

Para implementar o back-office foi desenvolvido um sistema CRUD (Create, Read, Update,

Delete) – CRUD são todas as operações básicas que se podem fazer sobre uma base de dados -

baseado em jQuery (AJAX) e PHP, reutilizável com bases de dados MySQL.

Este sistema implementa todas as operações sobre a BD numa só página, recorrendo ao

XMLHttpRequest para efectuar todas as tarefas de criação, leitura, actualização e eliminação

de registos.

5.1. Gerir Tipos de Localização Tal como se pode ver no modelo de dados, os marcadores/pontos estão agrupados em

categorias (“Tipos de Localização”). Estas categorias pertencem ainda a quatro grupo maiores

(utilidade) que são “Onde Comer”, “Onde Dormir”, “Diversão”, “Localizações Úteis”.

Para criarmos marcadores necessitamos primeiro de criar categorias para os agrupar.

Implementou-se a ferramenta que permite gerir os tipos de localização recorrendo a uma grelha

CRUD AJAX que permite fazer todas as operações numa só página.

Esta grelha é editável in-place. Na listagem de tipos de localização, podemos clicar em qualquer

dos campos de um registo para o editar, sem sermos redireccionados para outra página. Ao

clicar, o texto transforma-se num controlo editável (text-box, text-area, select, calendário, etc…)

que nos permite modificar o valor. Ao terminar a edição e clicarmos no botão “OK” respectivo, o

script encarrega-se de guardar o valor na Base de Dados (assincronamente) sem para isso

recarregar absolutamente nada.

O formulário para adicionar novos registos também se encontra na mesma página, sendo

revelado no momento em que clicamos no botão de adição.

Page 81: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

70

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Como seria de esperar, todos os controlos básicos sobre a grelha (ordenação por qualquer um

dos campos em ordem ascendente ou descendente, paginação, filtragem in-line, etc.) são

efectuados sem recarregar a página, tornando o interface fluído, rápido, eficaz e menos

cansativo para quem gere os dados. As figuras seguintes ilustram todas estas características.

Ilustração 32 - Grelha CRUD AJAX para gestão dos Tipos de Localização

Ilustração 33 - Formulário in-line para adicionar um novo registo

Page 82: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

71

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 34 - Eliminação in-line

Ilustração 35 - Edição in-line

Ilustração 36 - Filtros in-line

Page 83: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

72

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 37 - Ordenação in-line

5.2. Georeferenciação de conteúdo A partir do momento em que temos os tipos de localização definidos podemos começar a

georeferenciar conteúdos.

A georeferenciação foi adicionada ao CMS como mais um passo (opcional) aquando da criação

de um conteúdo, seja uma página, uma notícia, regulamento, requerimento, etc…

No passo final da criação do conteúdo temos mais um botão que nos permite criar um marcador

que terá um link que remete para o conteúdo criado.

Ilustração 38 - Botão "GEOREFERENCIAR" na etapa final da criação de um conteúdo

Clicando no botão somos levados para a plataforma de georeferenciação:

Page 84: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

73

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 39 - Formulário de Georeferenciação

Na figura acima podemos ver que temos um mapa, o qual nos permite, ao clicar, obter as

coordenadas (Latitude e Longitude) do ponto desejado.

Temos que escolher, de seguida, o tipo de localização associado a este ponto:

Ilustração 40 - Escolha do tipo de localização

Se não se enquadrar em nenhum dos tipos pré-definidos, podemos criar um novo (link do lado

direito da select-box).

De seguida escolhemos a localidade. Inseri este campo (além das coordenadas) para depois

gerar os mapas temáticos por freguesia. Isso poderia ser feito pela intersecção das coordenadas

com os polígonos das freguesias, mas penso que não compensava o nível de complicação, além

da questão da performance – seria querys com tempo de excução elevado.

Page 85: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

74

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Ilustração 41 - Selecção da Localidade

Como podemos ver o Título/Nome do ponto é automaticamente importado do título do conteúdo

associado. Este fica editável no caso de necessitarmos de o modificar. Podemos ainda

acrescentar uma pequena descrição que aparecerá na info-window.

Na figura seguinte vemos que ao clicar colocamos um ícone no sítio do click e os campos

latitude e longitude do formulário são automaticamente preenchidos, para inserir na base de

dados.

Para capturar o click e ler as coordenadas foi utilizada uma variante do código explorado para

este efeito durante o estudo da API do Google Maps.

Ilustração 42 - Referenciar um ponto

Page 86: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

75

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Cada página pode ter um ou vários pontos associados. O exemplo abaixo mostra os pontos

associados à página de restaurantes:

Ilustração 43 - Vários pontos associados a um conteúdo

Como é óbvio podemos modificar ou apagar qualquer um dos pontos.

Desta forma expedita podemos acrescentar georeferenciação a qualquer conteúdo.

O resultado da georeferenciação já foi visto no capítulo do front-end.

5.3. Utilização da ferramenta CRUD AJAX para gerar o interface do back-of f ice

Como foi explicado no início deste capítulo, foi desenvolvida uma classe para gerar interfaces

CRUD de uma base de dados usando PHP e AJAX (através de jQuery). Para demonstrar a

facilidade com que esta ferramenta pode ser usada, coloco abaixo o código necessário para

gerar a interface de gestão dos Tipos de Localização. Todo o código está explicado nos

comentários:

<?php session_start(); require_once('../preheader.php'); #carregar a classe include ('../ajaxCRUD.class.php'); ?> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Gerir Tipos de Localizações</title> <link href="/default.css" rel="stylesheet" type="text/css"> </head> <body>

Page 87: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

76

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

<?php //ver se o utilizador está autenticado if(isset($_SESSION['cod_func'])){ ?> <h2 style="margin:30px;" align="center">Gerir Tipos de Localização</h2> <?php # criar um objecto da classe ajaxCRUD ######################################################## ## $tblLoc = new ajaxCRUD("Tipo de Localiza&ccedil;&atilde;o", "tipo_localizacoes", "Id", "../"); #omitir a chave primária #$tblLoc->omitPrimaryKey(); #definir os nomes dos campos na apresentação $tblLoc->displayAs("nome", "Nome"); $tblLoc->displayAs("utilidade", "Utilidade"); $tblLoc->displayAs("icone", "Icone"); #campos data/ input calendário dinâmico #$tblLoc->setData('data_inicio'); #$tblLoc->setData('data_fim'); //definir um campo como file upload $tblLoc->setFileUpload("icone", "../../gmaps/markers/", "http://www.cm-montalegre.pt/gmaps/markers/"); #definir a ordenação inicial $tblLoc->addOrderBy("ORDER BY Id DESC"); // definir este campo como select só de uma lista de valores $allowableValues = array("comer", "dormir", "divertir", "geral"); $tblLoc->defineAllowableValues("utilidade", $allowableValues); // numero de registos por página $tblLoc->setLimit(10); #colocar uma caixa de filtro pelo nome $tblLoc->addAjaxFilterBox('nome'); #tamanho da caixa de filtro $tblLoc->setAjaxFilterBoxSize('nome', 30); #funções para formatar apresentação de dados na tabela //$tblLoc->formatFieldWithFunction('nome', 'utf'); #$tblLoc->formatFieldWithFunction('texto', 'makeBold'); #gerar a tabela $tblLoc->showTable(); ?> <?php

Page 88: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

77

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} else{ echo "<h2>Acabou o tempo de sessao, ou o seu browser nao tem os cookies activos!</h2>"; } ?> <br> <br> </body> </html> <?php #funções extra para processar output function makeBold($val){ return "<b>$val</b>"; } function utf($val){ return utf8_encode($val); } function makeBlue($val){ return "$val"; } ?>

Como vimos em poucas linhas de código criamos uma aplicação que permite gerir todos os

dados de uma tabela. Todo o código da classe php ajaxCRUD estará em anexo, pois a sua

explicação ultrapassa o âmbito deste capítulo.

Page 89: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

78

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Conclusões

Depois de mais de um ano de trabalho podemos dizer que foram superados os objectivos iniciais

do projecto.

Os mapas, para quem consulta são de fácil navegação e leitura, intuitivos e úteis.

Para quem faz a gestão de conteúdos a plataforma é muito flexível, fácil de utilizar, rápida na

publicação e intuitiva. Permite num curto espaço de tempo georreferenciar muita informação e

compartimentá-la de forma eficaz e acessível.

A gestão de informação pode ser feita por qualquer pessoa com um domínio mínimo de

navegação Internet e Tecnologias de Informação.

Este é um trabalho que além de ser uma tese de mestrado é um sistema que está a ser usado

diariamente online e que é consultado mensalmente por centenas de pessoas, como podemos

constatar neste extracto da análise estatística da página:

Podemos ver no gráfico acima que durante o último ano o mapa foi visitado 8746 vezes o que

dá uma média mensal de 728,83 visitantes, o que é bem significativo.

Os objectivos iniciais do projecto foram claramente atingidos, sendo um projecto com muito

espaço para evoluir.

Essa evolução será a médio prazo e poderá contemplar, entre outros, a introdução de interfaces

AJAX nalgumas partes do back-office que ainda utilizam interfaces Web normais, acrescentar

Page 90: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

79

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

novas funções ao front-end como uma lista com as legendas dos marcadores, um filtro para as

categorias de marcadores, a inclusão de “mini-mapas” nas páginas de conteúdos ao invés de

todo o conteúdo georreferenciado estar num só mapa. Depois de aferido o interesse, poderá este

sistema ser integrado com sistema de SIG municipal sendo que este está assente no SGBD

postgreSQL + postGIS (extensão GIS do postgreSQL), implicando a interligação entre dois SGBD

diferentes: MySQL e postgreSQL.

80%, ou mais, dos conhecimentos necessários à realização deste projecto foram adquiridos com

estudo e investigação, pois tanto a API do Google Maps como jQuery eram para o autor

desconhecidos antes da realização deste trabalho.

Além da programação em PHP, JavaScript, HTML, CSS, SQL, da investigação em áreas da

informática ainda não estudadas, foi necessário ainda que investigar na área dos sistemas de

coordenadas, e sistemas de informação geográfica (SIG).

Recomenda-se também para que se tenha uma ideia mais completa da complexidade de

algumas aplicações e de todo o sistema, uma análise ao código que está nos anexos.

Page 91: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

80

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Bibliografia

[1] Serrão, C. et al – Programação com PHP 5.3. 1ª ed. Lisboa: FCA, 2010. ISBN 978-972-722-

341-1

[2] Coelho, P. – JavaScript - Animação e Programação em Páginas Web. 1ª ed. Lisboa: FCA,

2003. ISBN 972-722-254-4

[3] Pereira, J. – Tecnologia de Base de Dados. 1ª ed. Lisboa: FCA, 2002. ISBN 972-722-143-2

[4] Oliveira, H. – Fundamental do Dreamweaver MX 2004. 1ª ed. Lisboa: FCA, 2003. ISBN 972-

722-439-3

[5] Ramalho, J. et al – XML & XSL. 1ª ed. Lisboa: FCA, 2002. ISBN 972-722-347-8

[6] Google Code et al – Referência da API do Google Maps: Google Code, 2010.

[7] Swedberg, K. et al – Referência da API jQuery: jQuery Team, 2010.

[8] Bakken, S. et al – PHP Manual. 8ª ed. Hannover: PHP Documentation Group, 2004.

[9] Axmark, D. et al – MySQL Reference Manual. 4ª ed. Estocolmo: MySQL Documentation

Team, 2004.

Page 92: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

81

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Anexos

Referência de funções da API do Google Maps

Funções para exibição de conteúdo GMap2 GMapOptions GGoogleBarOptions

GInfoWindow GInfoWindowTab GInfoWindowOptions

GMarker GMarkerOptions GPolvline

GPolvlineOptions GPolvEditingOptions GPolvStvleOptions

GPolvgon GPolvgonOptions GScreenOverlav

GScreenPoint GScreenSize GGroundOverlav

GIcon GPoint GSize

GBounds GLatLng GLatLngBounds

GControl GTileLaverOptions GTileLaverOverlavOptions

GEvent GEventListener GXmlHttp

GXml GXslt GLog

GDraggableObject GDraggableObjectOptions GGeoStatusCode

GGeoAddressAccuracv GClientGeocoder GGeocodeCache

GFactualGeocodeCache GMarkerManager GMarkerManagerOptions

GGeoXml GDownloadUrl GBrowserIsCompatible

GDirections GDirectionsOptions GTravelModes

GRoute GStep GTrafficOverlav

GTrafficOverlavOptions GAdsManager GAdsManagerOptions

GStreetviewPanorama GStreetviewPanoramaOptions GStreetviewOverlav

GStreetviewClient GStreetviewClient.

ReturnValues

GStreetviewData

GStreetviewLocation GStreetviewLink GPov

GStreetviewPanorama.

ErrorViewer

Page 93: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

82

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Funções para extensão de funcionalidades Funções para estender as funcionalidades da API do Google Maps por meio da implementação

dos nossos próprios controlos, sobreposições ou tipos personalizados de mapas:

GGoogleBarListingTvpes

GGoogleBarLinkTarget

GGoogleBarResultList

GMapPane

GOverlav

GControl

GControlPosition

GControlAnchor

GMapTvpeControl

GMenuMapTvpeControl

GHierarchicalMapTvpeControl

GMapTvpe

GMapTvpeOptions

GLaver

GTileLaver GTileLaverOverlav

GCopvrightCollection

GCopvright

GProjection

GMercatorProjection

Page 94: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

83

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

Scr ipt AjaxCRUD Código PHP e jQuery/JavaScript da classe que permite gerar interfaces de gestão de base de

dados AJAX de uma forma expedita.

Esta classe contém os comentários em Inglês pois foi usqada para concorrer a um concurso no

site Envato CodeCanyon. Os comentários explicam bem o funcionamento dos scripts.

ajaxCRUD.class.php <?php /******************************************************/ /* ajaxCRUD.class.php v2.1 */ /* =========================== */ /* 2009 José Alves – [email protected] */ /* best PHP/jQuery class contest */ /****************************************************/ define('EXECUTING_SCRIPT', $_SERVER['PHP_SELF']); #this top part is for the AJAX actions themselves. the class is BELOW $ajaxAction = $_REQUEST['ajaxAction']; if ($ajaxAction != ""){ //these lines make sure caching do not cause AJAX saving/displaying issues header("Cache-Control: no-cache, must-revalidate"); //A date in the past header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); $table = $_REQUEST['table']; $pk = $_REQUEST['pk']; $field = trim($_REQUEST['field']); $id = $_REQUEST['id']; $val = $_REQUEST['val']; $table_num = $_REQUEST['table_num']; if (!is_numeric($id)){ $sql_id = "\"$id\""; } else{ $sql_id = $id; } if ($ajaxAction == 'add'){ echo $_SESSION[$table]; } if ($ajaxAction == 'filter'){ echo $_SESSION[$table]; } if ($ajaxAction == 'sort'){ echo $_SESSION[$table];

Page 95: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

84

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} if ($ajaxAction == 'getRowCount'){ echo $_SESSION['row_count']; } if ($ajaxAction == 'update'){ $val = str_replace("\n","<br />", $val); //$val = str_replace("<p>","<br /><br />", $val); //$val = str_replace("</P>","", $val); //$val = str_replace("</p>","", $val); //check to see if record exists $row_current_value = q1("SELECT $pk FROM $table WHERE $pk = $sql_id"); if ($row_current_value == ''){ qr("INSERT INTO $table ($pk) VALUES (\"$id\")"); } $success = qr("UPDATE $table SET $field = \"$val\" WHERE $pk = $sql_id"); if ($val == '') $val = "&nbsp;&nbsp;"; //when updating, we use the Table name, Field name, & the Primary Key (id) to feed back to client-side-processing $prefield = trim($table . $field . $id); if (isset($_REQUEST['dropdown_tbl'])){ $val = "{selectbox}"; } if ($success){ echo $prefield . "|" . stripslashes($val); } else{ echo "error|" . $prefield . "|" . stripslashes($val); } } if ($ajaxAction == 'delete'){ qr("DELETE FROM $table WHERE $pk = $sql_id"); echo $table . "|" . $id; } exit(); } // THE AJAXCRUD CLASS FOLLOWS: // Use: // Create an ajaxCRUD object. // $table = new ajaxCRUD(name of item, table name, primary key); // Example: // $tblFAQ = new ajaxCRUD("FAQ", "tblFAQ", "pkFAQID"); // $tblFAQ->showTable(); //

Page 96: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

85

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

// Note: !! Your table must have AUTO_INCREMENT enabled for the primary key !! // Note: !! Your version of mySQL must support string->INT conversion (thus "1" = 1) and "" is a NULL value !! class ajaxCRUD{ var $ajaxcrud_root; var $AJAX_file; var $css_file; var $css = true; //indicates a css spredsheet WILL be used var $add = true; //adding is ok var $doActionOnShowTable; //boolean var. When true and showTable() is called, doAction() is also called. turn off when you want to only have a table show in certain conditions but CRUD operations can take place on the table "behind the scenes" var $item_plural; var $item; var $db_table; var $db_table_pk; var $db_main_field; var $row_count; var $table_html; //the html for the table (to be modified on ADD via AJAX) var $cellspacing; var $showPaging = true; var $limit; // limit of rows to display on one page. defaults to 50 var $sql_limit; var $filtered_table = false; //the table is by default unfiltered (eg no 'where clause' on it) var $ajaxFilter_fields = array(); //array of fields that can be are filtered by AJAX (creates a textbox at the top of the table) var $ajaxFilterBoxSize = array(); //array (sub fieldname) holding size of the input box //all fields in the table var $fields = array(); var $field_count; //field datatypes var $field_datatype = array(); //$field_datatype[field] = datatype //allow delete of fields | boolean variable set to true by default var $delete; //defines if the add function uses AJAX var $AJAX_add = true; //defines if the class allows you to edit all fields var $AJAX_editing = true; //the fields to be displayed var $display_fields = array();

Page 97: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

86

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//the fields to be inputted when adding a new entry (90% time will be all fields). can be changed via the omitAddField method var $add_fields = array(); var $add_form_top = FALSE; //the add form (by default) is below the table. use displayAddFormTop() to bring it to the top //the fields which are displayed, but not editable var $uneditable_fields = array(); var $sql_where_clause; var $sql_where_clauses = array(); //array for IF there is more than one where clause var $sql_order_by; var $num_where_clauses; var $on_add_specify_primary_key = false; //table border - default is off: 0 var $border; //array containing values for a button next to the "go back" button at the bottom. [0] = value [1] = url [2] = extra tags/JavaScript var $bottom_button = array(); //array with value being the url for the buttom to go to (passing the id) [0] = value [1] = url var $row_button = array(); ################################################ # # The following are parallel arrays to help in the definition of a defined db relationship # ################################################ //values will be the name(s) of the foreign key(s) for a category table var $db_table_fk_array = array(); //values will be the name(s) of the category table(s) var $category_table_array = array(); //values will be the name(s) of the primary key for the category table(s) var $category_table_pk_array = array(); //values will be the name(s) of the field to return in the category table(s) var $category_field_array = array(); //values will be the (optional) name of the field to sort by in the category table(s) var $category_sort_field_array = array(); //for dropdown (to make an empty box). (format: array[field] = true/false) var $category_required = array(); // allowable values for a field. the key is the name of the field

Page 98: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

87

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var $allowed_values = array(); // "on" and "off" values for a checkbox. the key is the name of the field var $checkbox = array(); // holds the field names of columns that will have a "check all" checkbox var $checkboxall = array(); //values to be set to a particular field when a new row is added. the array is set as $field_name => $add_value var $add_values = array(); //destination folder to be set for a particular field that allows uploading of files. the array is set as $field_name => $destination_folder var $file_uploads = array(); var $file_upload_info = array(); //array[$field_name][destination_folder] and array[$field_name][relative_folder] var $filename_append_field = ""; //array dictating that "dropdown" fields do not show dropdown (but text editor) on edit (format: array[field] = true/false); //used in defineAllowableValues function var $field_no_dropdown = array(); //array holding the (user-defined) function to format a field with on display (format: array[field] = function_name); //used in formatFieldWithFunction function var $format_field_with_function = array(); var $onAddExecuteCallBackFunction; //(if true) put a checkbox before each row var $showCheckbox; var $loading_image_html; var $sort_direction; //used when sorting the table via AJAX ################################################ # # displayAs array is for linking a particular field to the name that displays for that field # ################################################ //the indexes will be the name of the field. the value is the displayed text var $displayAs_array = array(); //height of the textarea for certain fields. the index is the field and the value is the height var $textarea_height = array(); //campos password var $set_password = array();

Page 99: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

88

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//campos data var $set_data = array(); // Constructor //by default ajaxCRUD assumes all necessary files are in the same dir as the script calling it (eg $ajaxcrud_root = "") function ajaxCRUD($item, $db_table, $db_table_pk, $ajaxcrud_root = "") { //global variable - for allowing multiple ajaxCRUD tables on one page global $num_ajaxCRUD_tables_instantiated; if ($num_ajaxCRUD_tables_instantiated === "") $num_ajaxCRUD_tables_instantiated = 0; $this->showCheckbox = false; $this->ajaxcrud_root = $ajaxcrud_root; //$this->AJAX_file = "AJAX_ajaxCRUD.php"; $this->AJAX_file = EXECUTING_SCRIPT; $this->item = $item; $this->item_plural = $item . "s"; $this->db_table = $db_table; $this->db_table_pk = $db_table_pk; $this->fields = $this->getFields($db_table); $this->field_count = count($this->fields); //by default paging is turned on; limit is 50 $this->showPaging = true; $this->limit = 50; $this->num_where_clauses = 0; $this->delete = true; $this->add = true; //assumes the primary key is auto incrementing $this->primaryKeyAutoIncrement = true; $this->border = 0; $this->css = true; $this->AJAX_add = true; $this->doActionOnShowTable = true; $this->loading_image_html = "<center><br /><br /><img src=\'" . $this->ajaxcrud_root . "css/loading.gif\'><br /><br /></center>"; //changed via setLoadingImageHTML() $this->onAddExecuteCallBackFunction = ''; $this->onFileUploadExecuteCallBackFunction = ''; $this->onDeleteFileExecuteCallBackFunction = ''; //don't allow primary key to be editable $this->uneditable_fields[] = $this->db_table_pk; $this->display_fields = $this->fields; $this->add_fields = $this->fields;

Page 100: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

89

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//default sort direction $this->sort_direction = "desc"; if ($this->field_count == 0){ $error_msg[] = "No fields in this table!"; echo_msg_box(); exit(); } //for filtering if there is a request parameter $count_filtered = 0; $action = $_REQUEST['action']; foreach ($this->fields as $field){ if ($_REQUEST[$field] != '' && ($action != 'add' && $action != 'delete' && $action != 'update' && $action != 'upload' && $action != 'delete_file')){ $filter_field = $field; $filter_value = $_REQUEST[$field]; $filter_where_clause = "WHERE $filter_field LIKE \"%" . $filter_value . "%\""; $this->addWhereClause($filter_where_clause); $this->filtered_table = true; $count_filtered++; } } if ($count_filtered > 0){ $this->filtered_table; } else{ $this->filtered_table = false; } return true; } function setAjaxFile($AJAX_file){ $this->AJAX_file = $AJAX_file; } function turnOffAjaxADD(){ $this->AJAX_add = false; } function turnOffAjaxEditing(){ $this->AJAX_editing = false; } function turnOffPaging($limit = ""){ $this->showPaging = false; if ($limit != ''){ $this->sql_limit = " LIMIT $limit"; } } function setCSSFile($css_file){ $this->css_file = $css_file; } function setLoadingImageHTML($html){ $this->loading_image_html = $html;

Page 101: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

90

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} function addTableBorder(){ $this->border = 1; } function addAjaxFilterBox($field_name){ $this->ajaxFilter_fields[] = $field_name; $this->setAjaxFilterBoxSize($field_name, 10); } function setAjaxFilterBoxSize($field_name, $size){ $this->ajaxFilterBoxSize[$field_name] = $size; } function addAjaxFilterBoxAllFields(){ //unset($this->ajaxFilter_fields); foreach ($this->display_fields as $field){ $this->addAjaxFilterBox($field); } } function displayAddFormTop(){ $this->add_form_top = TRUE; } function addWhereClause($sql_where_clause){ $this->num_where_clauses++; $this->sql_where_clauses[] = $sql_where_clause; if ($this->num_where_clauses <= 1){ $this->sql_where_clause = " " . $sql_where_clause; } else{ foreach($this->sql_where_clauses as $where_clause){ $new_where = str_replace("WHERE", "AND", $where_clause); $this->sql_where_clause .= " $new_where "; } } } function addOrderBy($sql_order_by){ $this->sql_order_by = " " . $sql_order_by; } function formatFieldWithFunction($field, $function_name){ $this->format_field_with_function[$field] = $function_name; } function defineRelationship($fkCategoryID, $category_table, $category_table_pk, $category_field_name, $category_sort_field = "", $category_required = "1"){ $this->db_table_fk_array[] = $fkCategoryID; $this->category_table_array[] = $category_table; $this->category_table_pk_array[] = $category_table_pk; $this->category_field_array[] = $category_field_name; $this->category_sort_field_array[] = $category_sort_field;

Page 102: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

91

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//make the relationship required for the field if ($category_required == "1"){ $this->category_required[$fkCategoryID] = TRUE; } } function relationshipFieldOptional(){ $this->cat_field_required = FALSE; } function defineAllowableValues($field, $array_values, $onedit_textbox = FALSE){ //array with the setup [0] = value [1] = display name (both the same) $new_array = array(); foreach($array_values as $array_value){ if (!is_array($array_value)){ //a two-dimentential array --> set both the value and dropdown text to be the same $new_array[] = array(0=> $array_value, 1=>$array_value); } else{ //a 2-dimentential array --> value and dropdown text are different $new_array[] = $array_value; } } if ($onedit_textbox != FALSE){ $this->field_no_dropdowkn[$field] = TRUE; } $this->allowed_values[$field] = $new_array; } function defineCheckbox($field, $value_on="1", $value_off="0"){ $new_array = array($value_on, $value_off); $this->checkbox[$field] = $new_array; } function showCheckboxAll($field, $display_data) { $this->checkboxall[$field] = $display_data; } function displayAs($field, $the_field_name){ $this->displayAs_array[$field] = $the_field_name; } function setTextareaHeight($field, $height){ $this->textarea_height[$field] = $height; } function setPassword($field){ $this->set_password[$field] = 1; } function setData($field){

Page 103: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

92

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$this->set_data[$field] = 1; } function setLimit($limit){ $this->limit = $limit; } function getRowCount(){ if ($_SESSION['row_count'] == ""){ $count = q1("SELECT COUNT(*) FROM " . $this->db_table . $this->sql_where_clause . $this->sql_order_by); } else{ $count = $_SESSION['row_count']; } return "<span id='" . $this->db_table . "_RowCount'>" . $count . "</span>"; } function getTotalRowCount(){ $count = q1("SELECT COUNT(*) FROM " . $this->db_table); return $count; } function omitField($field_name){ $key = array_search($field_name, $this->display_fields); if ($this->fieldInArray($field_name, $this->display_fields)){ unset($this->display_fields[$key]); } else{ $error_msg[] = "Error in your doNotDisplay function call. There is no field named <b>$field_name</b> in the table <b>" . $this->db_table . "</b>"; } } function omitAddField($field_name){ $key = array_search($field_name, $this->add_fields); if ($key !== FALSE){ unset($this->add_fields[$key]); } else{ $error_msg[] = "Error in your omitAddField function call. There is no field named <b>$field_name</b> in the table <b>" . $this->db_table . "</b>"; } } function omitFieldCompletely($field_name){ $this->omitField($field_name); $this->omitAddField($field_name); } function addValueOnInsert($field_name, $insert_value){ //if the value is NOW() then it's a date field or if its an integer --> otherwise put quotes around it. //if ($insert_value != "NOW()" && !is_int($insert_value)){ // $insert_value = "\"" . $insert_value . "\""; //}

Page 104: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

93

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$this->add_values[] = array(0 => $field_name, 1 => $insert_value); } function onAddExecuteCallBackFunction($function_name){ $this->onAddExecuteCallBackFunction = $function_name; $this->AJAX_add = false; } function onFileUploadExecuteCallBackFunction($function_name){ $this->onFileUploadExecuteCallBackFunction = $function_name; } function onDeleteFileExecuteCallBackFunction($function_name){ $this->onDeleteFileExecuteCallBackFunction = $function_name; } function primaryKeyNotAutoIncrement(){ $this->primaryKeyAutoIncrement = false; } function setFileUpload($field_name, $destination_folder, $relative_folder = ""){ //put values into array $this->file_uploads[] = $field_name; $this->file_upload_info[$field_name][destination_folder] = $destination_folder; $this->file_upload_info[$field_name][relative_folder] = $relative_folder; //the filenames that are saved are not editable $this->disallowEdit($field_name); //have to add the row via POST now $this->AJAX_add = false; } function appendUploadFilename($append_field){ $this->filename_append_field = $append_field; } function omitPrimaryKey(){ //99% time it'll be in key 0, but just in case do search $key = array_search($this->db_table_pk, $this->display_fields); unset($this->display_fields[$key]); } function insertHeader($AJAX_file){ if ($this->css_file == ''){ $this->css_file6 = 'default.css'; } /* Load JavaScript dependencies */ echo "<script type=\"text/JavaScript\" src=\"http://AJAX.googleapis.com/AJAX/libs/jQuery/1.3.2/jQuery.min.js\"></script>\n"; //per release 8, using jQuery instead of protoculous

Page 105: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

94

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

echo "<script src=\"" . $this->ajaxcrud_root . "JavaScript_functions.js\" type=\"text/JavaScript\"></script>\n"; echo "<link href=\"" . $this->ajaxcrud_root . "css/ajaxcrud.css\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />\n"; echo "<link href=\"" . $this->ajaxcrud_root . "css/datePicker.css\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />\n"; echo "<script type=\"text/JavaScript\" src=\"" . $this->ajaxcrud_root . "date.js\"></script>\n"; echo "<script type=\"text/JavaScript\" src=\"" . $this->ajaxcrud_root . "jQuery.datePicker.js\"></script>\n"; echo "<!--[if IE]><script type=\"text/JavaScript\" src=\"" . $this->ajaxcrud_root . "jQuery.bgiframe.min.js\"></script><![endif]-->\n"; echo "<script type=\"text/JavaScript\" charset=\"utf-8\">\n Date.format = 'yyyy-mm-dd';\n $(function()\n {\n $('.date-pick').datePicker({clickInput:true})\n });\n </script>\n" ; echo " <script>\n AJAX_file = \"$this->AJAX_file\"; \n this_page = \"" . $_SERVER['PHP_SELF'] . "\"; \n loading_image_html = \"$this->loading_image_html\"; \n </script>\n"; //are we even using a stylesheet? (it can be turned off) if ($this->css){ echo "<link href=\"" . $this->ajaxcrud_root . "css/" . $this->css_file ."\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />\n"; } return true; } function disallowEdit($field){ $this->uneditable_fields[] = $field; } function disallowDelete(){ $this->delete = false; } function disallowAdd(){ $this->add = false; } function addButton($value, $url, $tags = ""){ $this->bottom_button = array(0 => $value, 1 => $url, 2 => $tags); } function addButtonToRow($value, $url, $attach_params = "", $JavaScript_tags = ""){

Page 106: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

95

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$this->row_button[] = array(0 => $value, 1 => $url, 2 => $attach_params, 3 => $JavaScript_tags); } function onAddSpecifyPrimaryKey(){ $this->on_add_specify_primary_key = true; } function doCRUDAction(){ if ($_REQUEST['action'] != ''){ $this->doAction($_REQUEST['action']); } } function doAction($action){ global $error_msg; global $report_msg; $item = $this->item; if ($action == 'delete' && $_REQUEST['id'] != ''){ $delete_id = $_REQUEST['id']; $success = qr("DELETE FROM $this->db_table WHERE $this->db_table_pk = \"$delete_id\""); if ($success){ $report_msg[] = "$item Apagado"; } else{ $error_msg[] = "$item não pôde ser apagado. Por favor tente outra vez."; } }//action = delete #adding new item (via traditional way, non-AJAX -- note: this is the ONLY way files can be uploaded with ajaxCRUD) if ($actikon == 'add'){ //this if condition is so MULTIPLE ajaxCRUD tables can be used on the same page. if ($_REQUEST['table'] == $this->db_table){ //for sql insert statement $submitted_values = array(); //for callback function (if defined) $submitted_array = array(); //this new row has (a) file(s) coming with it $uploads_on = $_REQUEST['uploads_on']; if ($uploads_on == 'true' && $_FILES){ $uploads_on = true; } foreach($this->fields as $field){ $submitted_value_cleansed = ""; if ($_REQUEST[$field] == ''){ if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){

Page 107: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

96

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$submitted_value_cleansed = 0; } } else{ $submitted_value_cleansed = $_REQUEST[$field]; } $submitted_values[] = $submitted_value_cleansed; //also used for callback function $submitted_array[$field] = $submitted_value_cleansed; } //get rid of the primary key in the fields column if (!$this->on_add_specify_primary_key){ unset($submitted_values[0]); //assumes the primary key is the FIRST field in the array } //for adding values to the row which were not in the ADD row table - but are specified by ADD on INSERT if (count($this->add_values) > 0){ foreach ($this->add_values as $add_value){ $field_name = $add_value[0]; $the_add_value = $add_value[1]; if ($submitted_array[$field_name] == ''){ $submitted_array[$field_name] = $the_add_value; } //reshuffle numeric indexed array unset($submitted_values); $submitted_values = array(); foreach($submitted_array as $field){ $submitted_values[] = $field; } //get rid of the primary key in the fields column if (!$this->on_add_specify_primary_key){ unset($submitted_values[0]); //assumes the primary key is the FIRST field in the array } } } //wrap each field in quotes $string_submitted_values = "\"" . implode("\",\"", $submitted_values) . "\"";; //for getting datestamp of new row for mysql's "NOW" to work $string_submitted_values = str_replace('"NOW()"', 'NOW()', $string_submitted_values); //print_r($submitted_values);

Page 108: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

97

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

if ($string_submitted_values != ''){ if (!$this->on_add_specify_primary_key && $this->primaryKeyAutoIncrement){ //don't allow the primary key to be inputted $fields_array_without_pk = $this->fields; unset($fields_array_without_pk[0]); //assumes the primary key is the FIRST field in the array $string_fields_without_pk = implode(",", $fields_array_without_pk); $query = "INSERT INTO $this->db_table($string_fields_without_pk) VALUES ($string_submitted_values)"; } else{ if (!$this->primaryKeyAutoIncrement){ $primary_key_value = q1("SELECT MAX($this->db_table_pk) FROM $this->db_table"); if ($primary_key_value > 0) $primary_key_value++; $primary_key_value = $primary_key_value . ", "; } $string_fields_with_pk = implode(",", $this->fields); $query = "INSERT INTO $this->db_table($string_fields_with_pk) VALUES ($primary_key_value $string_submitted_values)"; } $success = qr($query); if ($success){ $insert_id = mysql_insert_id(); //$_SESSION[insert_id] = $insert_id; $report_msg[] = "$item Adicionado"; if ($uploads_on){ foreach($this->file_uploads as $field_name){ $file_dest = $this->file_upload_info[$field_name][destination_folder]; if ($_FILES[$field_name]['name'] != ''){ $this->uploadFile($insert_id, $field_name, $file_dest); } } } if ($this->onAddExecuteCallBackFunction != ''){ $submitted_array[id] = $insert_id; $submitted_array[$this->db_table_pk] = $insert_id; call_user_func($this->onAddExecuteCallBackFunction, $submitted_array); }

Page 109: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

98

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} else{ $error_msg[] = "$item nao pode ser adicionado. Por favor tente outra vez."; } } else{ $error_msg[] = "Todos os campos foram omitidos."; } }//if POST parameter 'table' == db_table }//action = add if ($action == 'upload' && $_REQUEST['field_name'] && $_REQUEST['id'] != ''){ $update_id = $_REQUEST['id']; $file_field = $_REQUEST['field_name']; $upload_folder = $this->file_upload_info[$file_field][destination_folder]; $success = $this->uploadFile($update_id, $file_field, $upload_folder); if ($success){ $report_msg[] = "Ficheiro carregado com sucesso."; } else{ $error_msg[] = "Houve um erro ao carregar o ficheiro (ou nenhum ficheiro foi seleccionado)."; } }//action = upload if ($action == 'delete_file' && $_REQUEST['field_name'] && $_REQUEST['id'] != ''){ $delete_id = $_REQUEST['id']; $file_field = $_REQUEST['field_name']; $upload_folder = $_REQUEST['upload_folder']; $filename = q1("SELECT $file_field FROM $this->db_table WHERE $this->db_table_pk = $delete_id"); $success = qr("UPDATE $this->db_table SET $file_field = \"\" WHERE $this->db_table_pk = $delete_id"); if ($success){ $file_dest = $this->file_upload_info[$file_field][destination_folder]; unlink($file_dest . $filename); $report_msg[] = "Ficheiro apagado com sucesso."; if ($this->onDeleteFileExecuteCallBackFunction != ''){ $delete_file_array = array(); $delete_file_array[id] = $delete_id; $delete_file_array[field] = $file_field; call_user_func($this->onDeleteFileExecuteCallBackFunction, $delete_file_array); } } else{

Page 110: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

99

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$error_msg[] = "Houve um erro ao apagar o ficheiro."; } }//action = delete_file }//doAction //a file must have been "sent"/posted for this to work function uploadFile($row_id, $file_field, $upload_folder){ @$fileName = $_FILES[$file_field]['name']; @$tmpName = $_FILES[$file_field]['tmp_name']; @$fileSize = $_FILES[$file_field]['size']; @$fileType = $_FILES[$file_field]['type']; $new_filename = make_filename_safe($fileName); if ($this->filename_append_field != ""){ if ($_REQUEST[$this->filename_append_field] != ''){ $new_filename = $_REQUEST[$this->filename_append_field] . "_" . $new_filename; } else{ if ($this->filename_append_field == $this->db_table_pk){ $new_filename = $row_id . "_" . $new_filename; } else{ @$db_value_to_append = q1("SELECT $this->filename_append_field FROM $this->db_table WHERE $this->db_table_pk = $row_id"); if ($db_value_to_append != ""){ $new_filename = $db_value_to_append . "_" . $new_filename; } } } } $destination = $upload_folder . $new_filename; $success = move_uploaded_file ($tmpName, $destination); if ($success){ $update_success = qr("UPDATE $this->db_table SET $file_field = \"$new_filename\" WHERE $this->db_table_pk = $row_id"); if ($this->onFileUploadExecuteCallBackFunction != ''){ $file_info_array = array(); $file_info_array[id] = $row_id; $file_info_array[field] = $file_field; $file_info_array[fileName] = $new_filename; $file_info_array[fileSize] = $fileSize; $file_info_array[fldType] = $fldType; call_user_func($this->onFileUploadExecuteCallBackFunction, $file_info_array); } } if ($update_success){

Page 111: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

100

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

return true; //$report_msg[] = "File Uploaded."; } else{ return false; //$error_msg[] = "There was an error uploading your file (or none was selected)."; } } function showTable(){ global $error_msg; global $report_msg; global $warning_msg_displayed; global $num_ajaxCRUD_tables_instantiated; $num_ajaxCRUD_tables_instantiated++; /* Sort Table Note: this cancels out default sorting set by addOrderBy() */ if ($this->db_table == $_REQUEST['table'] && $_REQUEST['sort_field'] != ''){ $sort_field = $_REQUEST['sort_field']; $user_sort_order_direction = $_REQUEST['sort_direction']; if ($user_sort_order_direction == 'asc'){ $this->sort_direction = "desc"; } else{ $this->sort_direction = "asc"; } $sort_sql = " ORDER BY $sort_field $this->sort_direction"; $this->addOrderBy($sort_sql); $this->sorted_table = true; } //the HTML to display $top_html = ""; //top header stuff $table_html = ""; //for the html table itself $bottom_html = ""; $add_html = ""; //for the add form $html = ""; //all combined if ( $num_ajaxCRUD_tables_instantiated == 1 ){ //pull in the css and JavaScript files $this->insertHeader($this->AJAX_file); } if ($this->doActionOnShowTable){ if ($_REQUEST['action'] != ''){ $this->doAction($_REQUEST['action']); } } $item = $this->item;

Page 112: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

101

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$top_html .= "<a name='ajaxCRUD" . $num_ajaxCRUD_tables_instantiated ."' id='ajaxCRUD" . $num_ajaxCRUD_tables_instantiated ."'></a>\n"; if (count($this->ajaxFilter_fields) > 0){ $top_html .= "<form id=\"" . $this->db_table . "_filter_form\">\n"; $top_html .= "<table cellspacing='5' align='center'><tr>"; foreach ($this->ajaxFilter_fields as $filter_field){ $display_field = $filter_field; if ($this->displayAs_array[$filter_field] != ''){ $display_field = $this->displayAs_array[$filter_field]; } $textbox_size = $this->ajaxFilterBoxSize[$filter_field]; $filter_value = ""; if ($_REQUEST[$filter_field] != ''){ $filter_value = $_REQUEST[$filter_field]; } $top_html .= "<td>Filtrar por <b>$display_field</b>: <input type=\"text\" size=\"$textbox_size\" name=\"$filter_field\" value=\"$filter_value\" onKeyUp=\"filterTable(this, '" . $this->db_table . "', '$filter_field', '$extra_query_params');\"></td>"; } $top_html .= "</tr></table>\n"; $top_html .= "</form>\n"; } ############################################# # # Begin code for displaying database elements # ############################################# $select_fields = implode(",", $this->fields); $sql = "SELECT * FROM " . $this->db_table . $this->sql_where_clause . $this->sql_order_by; if ($this->showPaging){ $pageid = $_GET['pid'];//Get the pid value if(intval($pageid) == 0) $pageid = 1; $Paging = new paging(); $Paging->tableName = $this->db_table; $total_records = $Paging->myRecordCount($sql);//count records $totalpage = $Paging->processPaging($this->limit,$pageid); $rows = $Paging->startPaging($sql);//get records in the databse $links = $Paging->pageLinks(basename($PHP_SELF));//1234 links unset($Paging); }

Page 113: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

102

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

else{ $rows = q($sql . $this->sql_limit); } //$rows = q("SELECT * FROM " . $this->db_table"); $row_count = count($rows); $this->row_count = $row_count; $_SESSION['row_count'] = $row_count; if ($row_count == 0){ $report_msg[] = "Esta tabela nao tem dados."; } #this is an optional function which will allow you to display errors or report messages as desired. comment it out if desired //only show the message box if it hasn't been displayed already if ($warning_msg_displayed == 0 || $warning_msg_displayed == ''){ echo_msg_box(); } $dropdown_array = array(); foreach ($this->category_table_array as $key => $category_table){ $category_field_name = $this->category_field_array[$key]; $category_table_pk = $this->category_table_pk_array[$key]; $order_by = ''; if ($this->category_sort_field_array[$key] != ''){ $order_by = " ORDER BY " . $this->category_sort_field_array[$key]; } $dropdown_array[] = q("SELECT $category_table_pk, $category_field_name FROM $category_table $order_by"); } $top_html .= "<div id='$this->db_table'>\n"; if ($row_count > 0){ //$edit_word = "Edit"; //if ($row_count == 0) $edit_word = "No"; //$top_html .= "<h3>Edit " . $this->item_plural . "</h3>\n"; $table_html .= "<table align='center' class='ajaxCRUD' name='table_" . $this->db_table . "' id='table_" . $this->db_table . "' cellspacing='" . $this->cellspacing . "' border=" . $this->border . ">\n"; $table_html .= "<tr>\n"; //for an (optional) checkbox if ($this->showCheckbox){ $table_html .= "<th>&nbsp;</th>"; }

Page 114: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

103

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

foreach ($this->display_fields as $field){ $field_name = $field; if ($this->displayAs_array[$field] != ''){ $field = $this->displayAs_array[$field]; } if (array_key_exists($field_name, $this->checkboxall)) { $table_html .= "<th><input type=\"checkbox\" name=\"$field_name" . "_checkboxall\" value=\"checkAll\" onClick=\" if (this.checked) { setAllCheckboxes('$field_name" . "_fieldckbox',false); } else { setAllCheckboxes('$field_name" . "_fieldckbox',true); } \">"; if ($this->checkboxall[$field_name] == true) { $table_html .= "<a href='JavaScript:;' onClick=\"changeSort('$this->db_table', '$field_name', '$this->sort_direction');\" >" . $field . "</a>"; } $table_html .= "</th>"; } else { $table_html .= "<th><a href='JavaScript:;' onClick=\"changeSort('$this->db_table', '$field_name', '$this->sort_direction');\" >" . $field . "</a></th>"; } } if ($this->delete || (count($this->row_button)) > 0){ $table_html .= "<th>Ac&ccedil;&otilde;es</th>\n"; } $table_html .= "</tr>\n"; $count = 0; $class = "odd"; $attach_params = ""; foreach ($rows as $row){ $id = $row[$this->db_table_pk]; $table_html .= "<tr class='$class' id=\"" . $this->db_table . "_row_$id\" valign='top'>\n"; if ($this->showCheckbox){ $checkbox_selected = ""; if ($id == $_REQUEST[$this->db_table_pk]) $checkbox_selected = " checked"; $table_html .= "<td><input type='checkbox' $checkbox_selected onClick=\"window.location ='" . $_SERVER['PHP_SELF'] . "?$this->db_table_pk=$id'\" /></td>"; } foreach($this->display_fields as $field){ $cell_data = $row[$field];

Page 115: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

104

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//for adding a button via addButtonToRow (using "all" as the "attach params" optional third parameter) if (count($this->row_button) > 0){ $attach_params .= "&" . $field . "=" . $cell_data; } $cell_value = $cell_data; if ($this->format_field_with_function[$field] != ''){ $cell_data = call_user_func($this->format_field_with_function[$field], $cell_data); } //try to find a reference to another table relationship $found_category_index = array_search($field, $this->db_table_fk_array); //don't allow uneditable fields (which usually includes the primary key) to be editable if ( ($this->fieldInArray($field, $this->uneditable_fields) || (!$this->AJAX_editing)) && $found_category_index == ''){ $table_html .= "<td>"; $key = array_search($field, $this->display_fields); if ($this->fieldInArray($field, $this->file_uploads)){ //a file exists for this field if ($cell_data != ''){ $file_link = $this->file_upload_info[$field][relative_folder] . $row[$field]; $file_dest = $this->file_upload_info[$field][destination_folder]; $extensao = substr(strtolower($file_link), -3); if( $extensao == "jpg" || $extensao == "jpeg" ||$extensao == "png" || $extensao == "bmp" || $extensao == "gif" ){ $table_html .= "<span id='text_" . $field . $id . "'><img src=\"$file_link\"> <br> (<a style=\"font-size: 9px;\" href=\"JavaScript:\" onClick=\"document.getElementById('file_$field$id').style.display = ''; document.getElementById('text_$field$id').style.display = 'none'; \">editar</a> <a style=\"font-size: 9px;\" href=\"JavaScript:\" onClick=\"deleteFile('$field', '$id')\">apagar</a>)</span> \n"; } else{ $table_html .= "<span id='text_" . $field . $id . "'><a href=\"$file_link\" target=_blank >Ver Ficheiro</a> <br> (<a style=\"font-size: 9px;\" href=\"JavaScript:\" onClick=\"document.getElementById('file_$field$id').style.display =

Page 116: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

105

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

''; document.getElementById('text_$field$id').style.display = 'none'; \">editar</a> <a style=\"font-size: 9px;\" href=\"JavaScript:\" onClick=\"deleteFile('$field', '$id')\">apagar</a>)</span> \n"; } $table_html .= "<div id='file_" . $field . $id . "' style='display:none;'>\n"; $table_html .= $this->showUploadForm($field, $file_dest, $id); $table_html .= "</div>\n"; } if ($cell_data == ''){ $table_html .= "<span id='text_" . $field . $id . "'><a style=\"font-size: 9px;\" href=\"JavaScript:\" onClick=\"document.getElementById('file_$field$id').style.display = ''; document.getElementById('text_$field$id').style.display = 'none'; \">Adicionar Ficheiro</a></span> \n"; $table_html .= "<div id='file_" . $field. $id . "' style='display:none;'>\n"; $table_html .= $this->showUploadForm($field, $file_dest, $id); $table_html .= "</div>\n"; } } else{ $table_html .= $cell_data; } }//if field is not editable else{ $table_html .= "<td>"; if (!is_numeric($found_category_index) && $found_category_index == ''){ //was allowable values for this field defined? if (is_array($this->allowed_values[$field]) && !$this->field_no_dropdown[$field]){ $table_html .= $this->makeAjaxDropdown($id, $field, $cell_data, $this->db_table, $this->db_table_pk, $this->allowed_values[$field]); } else{ //if a checkbox if (is_array($this->checkbox[$field])){ $table_html .= $this->makeAjaxCheckbox($id, $field, $cell_data); } else{ //is an editable field

Page 117: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

106

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

if ($cell_data == '') $cell_data = "&nbsp;&nbsp;"; $field_onKeyPress = ""; if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){ $field_onKeyPress = "return fn_validateNumeric(event, this, 'n');"; if ($this->fieldIsDecimal($this->getFieldDataType($field))){ $field_onKeyPress = "return fn_validateNumeric(event, this, 'y');"; } } if ($this->fieldIsEnum($this->getFieldDataType($field))){ $allowed_enum_values_array = $this->getEnumArray($this->getFieldDataType($field)); $table_html .= $this->makeAjaxDropdown($id, $field, $cell_data, $this->db_table, $this->db_table_pk, $allowed_enum_values_array); } else{ $field_length = strlen($row[$field]); // date-calendar if ( $this->set_data[$field] == 1 ){ $table_html .= $this->makeAjaxEditor($id, $field, $cell_value, 'data', $field_length, $cell_data, $field_onKeyPress); } // texto normal else if ($this->set_data[$field] != 1 && $field_length < 51){ $table_html .= $this->makeAjaxEditor($id, $field, $cell_value, 'text', $field_length, $cell_data, $field_onKeyPress); } else{ $textarea_height = ''; if ($this->textarea_height[$field] != '') $textarea_height = $this->textarea_height[$field]; $table_html .= $this->makeAjaxEditor($id, $field, $cell_value, 'textarea', $textarea_height, $cell_data, $field_onKeyPress); } } } } } else{

Page 118: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

107

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//this field is a reference to another table's primary key (eg it must be a foreign key) $category_field_name = $this->category_field_array[$found_category_index]; $category_table_name = $this->category_table_array[$found_category_index]; $category_table_pk = $this->category_table_pk_array[$found_category_index]; $selected_dropdown_text = "&nbsp;&nbsp;"; if ($cell_data != ""){ $selected_dropdown_text = q1("SELECT $category_field_name FROM $category_table_name WHERE $category_table_pk = \"" . $cell_data . "\""); if ($selected_dropdown_text == "") $selected_dropdown_text = "--"; } if (!$this->fieldInArray($field, $this->uneditable_fields)){ $table_html .= $this->makeAjaxDropdown($id, $field, $cell_data, $category_table_name, $category_table_pk, $dropdown_array[$found_category_index], $selected_dropdown_text); } else{ $table_html .= $selected_dropdown_text; } } } $html .= "</td>"; } if ($this->delete || (count($this->row_button)) > 0){ $table_html .= "<td>\n"; if ($this->delete){ $table_html .= "<input type=\"button\" class=\"editingSize\" onClick=\"confirmDelete('$id', '" . $this->db_table . "', '" . $this->db_table_pk ."');\" value=\"Apagar\" />\n"; } if (count($this->row_button) > 0){ foreach ($this->row_button as $the_row_button){ $value = $the_row_button[0]; $url = $the_row_button[1]; $attach_param = $the_row_button[2]; $JavaScript_onclick_function = $the_row_button[3]; if ($attach_param == "all"){ $attach = "?attachments" . $attach_params; } else{ $attach = "?" . $this->db_table_pk . "=$id"; }

Page 119: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

108

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//its most likely a user-defined AJAX function if ($JavaScript_onclick_function != ""){ $JavaScript_for_button = "onClick=\"" . $JavaScript_onclick_function . "($id);\""; } else{ $JavaScript_for_button = "onClick=\"location.href='" . $url . $attach . "'\""; } $table_html .= "<input type=\"button\" $JavaScript_for_button class=\"btn editingSize\" value=\"$value\" />\n"; } } $table_html .= "</td>\n"; } $table_html .= "</tr>"; if($count%2==0){ $class="cell_row"; } else{ $class="odd"; } $count++; }//foreach row $table_html .= "</table>\n"; //paging links if ($totalpage > 1){ $table_html .= "<br /><div style='width: 800px; position: relative; left: 50%; margin-left: -400px; text-align: center;'><center> $links </center></div><br /><br />"; } }//if rows > 0 //closing div for paging links (if applicable) $bottom_html = "</div><br />\n"; //now we come to the "add" fields if ($this->add){ $add_html .= "<center>\n"; $add_html .= " <input type=\"button\" value=\"Adicionar $item\" class=\"btn editingSize\" onClick=\"$('#add_form_$this->db_table').slideDown('slow');\">\n"; if (count($this->bottom_button) > 0){ $button_value = $this->bottom_button[0]; $button_url = $this->bottom_button[1]; $button_tags = $this->bottom_button[2];

Page 120: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

109

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

if ($button_tags == ''){ $tag_stuff = "onClick=\"location.href = '$button_url';\""; } else{ $tag_stuff = $button_tags; } $add_html .= " <input type=\"button\" value=\"$button_value\" href=\"$button_url\" class=\"btn\" $tag_stuff>\n"; } //$add_html .= " <input type=\"button\" value=\"Go Back\" class=\"btn\" onClick=\"history.back();\">\n"; $add_html .= "</center>\n"; $add_html .= "<form action=\"" . $_SERVER['PHP_SELF'] ."#ajaxCRUD\" id=\"add_form_$this->db_table\" method=\"POST\" ENCTYPE=\"multipart/form-data\" style=\"display:none;\">\n"; $add_html .= " <br /><h3>Novo(a) <b>$item</b></h3>\n"; $add_html .= " <table align='center' name='form'>\n"; $add_html .= "<tr valign='top'>\n"; //for here display ALL 'addable' fields foreach($this->add_fields as $field){ if ($field != $this->db_table_pk || $this->on_add_specify_primary_key){ $field_value = ""; if ($_REQUEST[$field] != '') $field_value = $_REQUEST[$field]; if ($this->displayAs_array[$field] != ''){ $display_field = $this->displayAs_array[$field]; } else{ $display_field = $field; } //if a checkbox if (is_array($this->checkbox[$field])){ $values = $this->checkbox[$field]; $value_on = $values[0]; $value_off = $values[1]; $add_html .= "<th width='20%'>$display_field</th><td>\n"; $add_html .= "<input type='checkbox' name=\"$field\" value=\"$value_on\">\n"; $add_html .= "</td></tr>\n"; } else{ $found_category_index = array_search($field, $this->db_table_fk_array); if (!is_numeric($found_category_index) && $found_category_index == ''){ //it's from a set of predefined allowed values for this field if (is_array($this->allowed_values[$field])){

Page 121: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

110

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$add_html .= "<th width='20%'>$display_field</th><td>\n"; $add_html .= "<select name=\"$field\" class='editingSize'>\n"; foreach ($this->allowed_values[$field] as $dropdown){ $selected = ""; $dropdown_value = $dropdown[0]; $dropdown_text = $dropdown[1]; if ($field_value == $dropdown_value) $selected = " selected"; $add_html .= "<option value=\"$dropdown_value\" $selected>$dropdown_text</option>\n"; } $add_html .= "</select></td></tr>\n"; } else{ if ($this->fieldInArray($field, $this->file_uploads)){ //this field is an file upload $add_html .= "<th width='20%'>$display_field</th><td><input class=\"editingSize\" type=\"file\" name=\"$field\" size=\"15\"></td></tr>\n"; $file_uploads = true; } else{ if ($this->fieldIsEnum($this->getFieldDataType($field))){ $allowed_enum_values_array = $this->getEnumArray($this->getFieldDataType($field)); $add_html .= "<th width='20%'>$display_field</th><td>\n"; $add_html .= "<select name=\"$field\" class='editingSize'>\n"; foreach ($allowed_enum_values_array as $dropdown){ $dropdown_value = $dropdown; $dropdown_text = $dropdown; if ($field_value == $dropdown_value) $selected = " selected"; $add_html .= "<option value=\"$dropdown_value\" $selected>$dropdown_text</option>\n"; } $add_html .= "</select></td></tr>\n"; }//if enum field else{ $field_onKeyPress = ""; if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){ $field_onKeyPress = "return fn_validateNumeric(event, this, 'n');"; if ($this->fieldIsDecimal($this->getFieldDataType($field))){ $field_onKeyPress = "return fn_validateNumeric(event, this, 'y');"; }

Page 122: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

111

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} //textarea fields else if ($this->textarea_height[$field] != ''){ $add_html .= "<th width='20%'>$display_field</th><td><textarea onKeyPress=\"$field_onKeyPress\" class=\"editingSize\" name=\"$field\" style='width: 97%; height: " . $this->textarea_height[$field] . "px; min-width:150px;'>$field_value</textarea></td></tr>\n"; } //password fields else if ($this->set_password[$field] == 1){ $field_size = ""; if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){ $field_size = 7; } $add_html .= "<th width='20%'>$display_field</th><td><input onKeyPress=\"$field_onKeyPress\" class=\"editingSize\" type=\"password\" name=\"$field\" size=\"$field_size\" value=\"$field_value\" maxlength=\"96\" style=' min-width:150px;'></td></tr>\n"; } //data fields else if ($this->set_data[$field] == 1){ $field_size = ""; if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){ $field_size = 9; } $add_html .= "<th width='20%'>$display_field</th><td><input onKeyPress=\"$field_onKeyPress\" class=\"date-pick editingSize\" type=\"text\" name=\"$field\" size=\"$field_size\" value=\"$field_value\" maxlength=\"96\"></td></tr>\n"; } else{ //any ol' data will do $field_size = ""; if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){ $field_size = 7; } $add_html .= "<th width='20%'>$display_field</th><td><input onKeyPress=\"$field_onKeyPress\" class=\"editingSize\" type=\"text\" name=\"$field\" size=\"$field_size\" value=\"$field_value\" maxlength=\"96\" style=' min-width:150px;'></td></tr>\n";

Page 123: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

112

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} }//else not enum field }//not an uploaded file }//not a pre-defined value }//not from a foreign/primary key relationship else{ //field is from a defined relationship $key = $found_category_index; $add_html .= "<th>$display_field</th><td>\n"; $add_html .= "<select name=\"$field\" class='editingSize'>\n"; if ($this->category_required[$field] != TRUE){ if ($this->fieldIsInt($this->getFieldDataType($field)) || $this->fieldIsDecimal($this->getFieldDataType($field))){ $add_html .= "<option value=0>--Select--</option>\n"; } else{ $add_html .= "<option value=''>--Select--</option>\n"; } } foreach ($dropdown_array[$key] as $dropdown){ $selected = ""; $dropdown_value = $dropdown[$this->category_table_pk_array[$key]]; $dropdown_text = $dropdown[$this->category_field_array[$key]]; if ($field_value == $dropdown_value) $selected = " selected"; $add_html .= "<option value=\"$dropdown_value\" $selected>$dropdown_text</option>\n"; } $add_html .= "</select></td></tr>\n"; } }//not a checkbox }//not the primary pk }//foreach $add_html .= "</tr><tr><td>\n"; if ($this->AJAX_add){ $add_html .= "<input class=\"editingSize\" type=\"button\" onClick=\" setLoadingImage('$this->db_table'); var fields = getFormValues(document.getElementById('add_form_$this->db_table'), ''); fields = fields + '&table=$this->db_table'; var req = '" . $_SERVER[PHP_SELF] . "?action=add&' + fields; clearForm('add_form_$this->db_table'); sndAddReq(req, '$this->db_table'); return false;\" value=\"Adicionar $item\">"; }

Page 124: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

113

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

else{ $add_html .= "<input class=\"editingSize\" type=\"submit\" value=\"Adicionar $item\">"; } $add_html .= "</td><td><input style='float: right;' class=\"editingSize\" type=\"button\" onClick=\"$('#add_form_$this->db_table').slideUp('slow');\" value=\"Cancelar\"></td></tr>\n</table>\n"; $add_html .= "<input type=\"hidden\" name=\"action\" value=\"add\">\n"; $add_html .= "<input type=\"hidden\" name=\"table\" value=\"$this->db_table\">\n"; if ($file_uploads){ $add_html .= "<input type=\"hidden\" name=\"uploads_on\" value=\"true\">\n"; } $add_html .= "</form>\n"; }//if adding fields is "allowed" /* THIS IS IMPORTANT for AJAX retrieval (see top of page) */ $_SESSION[$this->db_table] = $table_html; $html = $top_html . $table_html . $bottom_html . $add_html; if ($this->add_form_top){ $html = $add_html . $top_html . $table_html . $bottom_html; } echo $html; } function getFields($table){ $query = "SHOW COLUMNS FROM $table"; $rs = q($query); //print_r($rs); $fields = array(); foreach ($rs as $r){ //r sub0 is the name of the field (tricky ... but it works) $fields[] = $r[0]; $this->field_datatype[$r[0]] = $r[1]; } if (count($fields) > 0){ return $fields; } return false; } function getFieldDataType($field_name){ return $this->field_datatype[$field_name]; }

Page 125: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

114

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

function fieldIsInt($datatype){ if (stristr($datatype, "int") !== FALSE){ return true; } return false; } function fieldIsDecimal($datatype){ if (stristr($datatype, "decimal") !== FALSE || stristr($datatype, "double") !== FALSE){ return true; } return false; } function fieldIsEnum($datatype){ if (stristr($datatype, "enum") !== FALSE){ return true; } return false; } function getEnumArray($datatype){ $enum = substr($datatype, 5); $enum = substr($enum, 0, (strlen($enum) - 1)); $enum = str_replace("'", "", $enum); $enum = str_replace('"', "", $enum); $enum_array = explode(",", $enum); return ($enum_array); } function fieldInArray($field, $the_array){ //try to find index for arrays with array[key] = field_name $found_index = array_search($field, $the_array); if ($found_index !== FALSE){ return true; } //for arrays with array[0] = field_name and array[1] = value foreach ($the_array as $the_array_values){ $field_name = $the_array_values[0]; if ($field_name == $field){ return true; } } return false; } function makeAjaxEditor($unique_id, $field_name, $field_value, $type = 'textarea', $field_size = "", $field_text = "", $onKeyPress_function = ""){ $prefield = trim($this->db_table . $field_name . $unique_id); $input_name = $type . "_" . $prefield;

Page 126: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

115

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$return_html = ""; if ($field_text == "") $field_text = $field_value; $return_html .= "<span class=\"editable hand_cursor\" id=\"" . $prefield ."_show\" onClick=\" document.getElementById('" . $prefield . "_edit').style.display = ''; document.getElementById('" . $prefield . "_show').style.display = 'none'; document.getElementById('" . $input_name . "').focus(); \">" . $field_text . "</span> <span id=\"" . $prefield ."_edit\" style=\"display: none;\"> <form style=\"display: inline;\" name=\"form_" . $prefield . "\" id=\"form_" . $prefield . "\" onsubmit=\" document.getElementById('" . $prefield . "_edit').style.display='none'; document.getElementById('" . $prefield . "_save').style.display=''; var req = '" . $this->AJAX_file . "?ajaxAction=update&id=" . $unique_id . "&field=" . $field_name . "&table=" . $this->db_table . "&pk=" . $this->db_table_pk . "&val=' + escape(document.getElementById('" . $input_name . "').value); sndUpdateReq(req); return false; \">"; //for getting rid of the html space, replace with actual no text if ($field_value == "&nbsp;&nbsp;") $field_value = ""; if ($type == 'text'){ if ($field_size == "") $field_size = 50; $return_html .= "<input ONKEYPRESS=\"$onKeyPress_function\" id=\"text_$prefield\" name=\"$input_name\" type=\"text\" class=\"editingSize editMode\" maxlength='96' size=\"".($field_size+15)."\" value=\"".utf8_encode($field_value)."\"/>\n"; $return_html .= "<br /><input type=\"submit\" class=\"editingSize\" value=\"Ok\">\n"; } else if ($type == 'data'){ if ($field_size == "") $field_size = 50; $return_html .= "<input ONKEYPRESS=\"$onKeyPress_function\" id=\"$input_name\" name=\"$input_name\" type=\"text\" class=\"editingSize editMode date-pick \" size=\"$field_size\" value=\"$field_value\"/>\n"; $return_html .= "<br /><input type=\"submit\" class=\"editingSize\" value=\"Ok\">\n"; } else{ if ($field_size == "") $field_size = 80; $return_html .= "<textarea ONKEYPRESS=\"$onKeyPress_function\" id=\"$input_name\" name=\"textarea_$prefield\" class=\"editingSize editMode\" style=\"width: 100%; height: " . $field_size . "px;\">".utf8_encode($field_value)."</textarea>\n";

Page 127: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

116

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

$return_html .= "<br /><input type=\"submit\" class=\"editingSize\" value=\"Ok\">\n"; } $return_html .= " <input type=\"button\" class=\"editingSize\" value=\"Cancel\" onClick=\" document.getElementById('" . $prefield . "_show').style.display = ''; document.getElementById('" . $prefield . "_edit').style.display = 'none'; \"/> </form> </span> <span style=\"display: none;\" id=\"" . $prefield . "_save\" class=\"savingAjaxWithBackground\">A Guardar...</span>"; return $return_html; }//makeAjaxEditor function makeAjaxDropdown($unique_id, $field_name, $field_value, $dropdown_table, $dropdown_table_pk, $array_list, $selected_dropdown_text = "NOTHING_ENTERED"){ $return_html = ""; if ($selected_dropdown_text == "NOTHING_ENTERED"){ $selected_dropdown_text = $field_value; foreach ($array_list as $list){ if (is_array($list)){ $list_val = $list[0]; $list_option = $list[1]; } else{ $list_val = $list; $list_option = $list; } if ($list_val == $field_value) $selected_dropdown_text = $list_option; } } if ($selected_dropdown_text == ''){ $no_text = true; $selected_dropdown_text = "&nbsp;&nbsp;"; } $prefield = trim($this->db_table . $field_name . $unique_id); $return_html = "<span class=\"editable hand_cursor\" id=\"" . $prefield . "_show\" onClick=\" document.getElementById('" . $prefield . "_edit').style.display = ''; document.getElementById('" . $prefield . "_show').style.display = 'none'; \">" . $selected_dropdown_text . "</span>

Page 128: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

117

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

<span style=\"display: none;\" id=\"" . $prefield . "_edit\"> <form style=\"display: inline;\" name=\"form_" . $prefield . "\" id=\"form_" . $prefield . "\"> <select class=\"editingSize editMode\" id=\"" . $prefield . "\" onChange=\" var selected_index_value = document.getElementById('" . $prefield . "').value; document.getElementById('" . $prefield . "_edit').style.display='none'; document.getElementById('" . $prefield . "_save').style.display=''; var req = '" . $this->AJAX_file . "?ajaxAction=update&id=" . $unique_id . "&field=" . $field_name . "&table=" . $this->db_table . "&pk=" . $this->db_table_pk . "&dropdown_tbl=" . $dropdown_table . "&val=' + selected_index_value; sndUpdateReq(req); return false; \">"; if ($no_text || $this->category_required[$field_name] != TRUE){ if ($this->fieldIsInt($this->getFieldDataType($field_name)) || $this->fieldIsDecimal($this->getFieldDataType($field_name))){ $return_html .= "<option value='0'>--Seleccione--</option>\n"; } else{ $return_html .= "<option value=''>--Seleccione--</option>\n"; } } foreach($array_list as $list){ $selected = ''; if (is_array($list)){ $list_val = $list[0]; $list_option = $list[1]; } else{ $list_val = $list; $list_option = $list; } if ($list_val == $field_value) $selected = " selected"; $return_html .= "<option value=\"$list_val\" $selected >$list_option</option>"; } $return_html .= "</select>"; $return_html .= "<input type=\"button\" value=\"Cancelar\" onClick=\" document.getElementById('" . $prefield . "_show').style.display = ''; document.getElementById('" . $prefield . "_edit').style.display = 'none'; \"/> </span> </form>

Page 129: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

118

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

<span style=\"display: none;\" id=\"" . $prefield . "_save\" class=\"savingAjaxWithBackground\">A Guardar...</span>\n"; return $return_html; }//makeAjaxDropdown function makeAjaxCheckbox($unique_id, $field_name, $field_value){ $prefield = trim($this->db_table) . trim($field_name) . trim($unique_id); $return_html = ""; $values = $this->checkbox[$field_name]; $value_on = $values[0]; $value_off = $values[1]; $checked = ''; if ($field_value == $value_on) $checked = "checked"; $show_value = ''; if ($checked == '') { $show_value = $value_off; } else { $show_value = $value_on; } //strip quotes $value_on = str_replace('"', "'", $value_on); $value_off = str_replace('"', "'", $value_off); $return_html .= "<input type=\"checkbox\" $checked name=\"$field_name" . "_fieldckbox\" id=\"$field_name$unique_id\" onClick=\" var " . $prefield . "_value = ''; if (this.checked){ " . $prefield . "_value = '$value_on'; if (" . (int)$this->checkboxall[$field_name] . ") { document.getElementById('$field_name$unique_id" . "_label').innerHTML = '$value_on'; } } else{ ". $prefield . "_value = '$value_off'; if (" . (int)$this->checkboxall[$field_name] . ") { document.getElementById('$field_name$unique_id" . "_label').innerHTML = '$value_off'; } } var req = '" . $this->AJAX_file . "?ajaxAction=update&id=$unique_id&field=$field_name&table=$this->db_table&pk=$this->db_table_pk&val=' + " . $prefield . "_value;

Page 130: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

119

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

sndReqNoResponseChk(req); \">"; if ($this->checkboxall[$field_name] == true) { $return_html .= "<label for=\"$field_name$unique_id\" id=\"" . $field_name . $unique_id . "_label\">$show_value</label>"; } return $return_html; }//makeAjaxCheckbox function showUploadForm($field_name, $upload_folder, $row_id){ $return_html = ""; $return_html .= "<form action=\"" . $_SERVER['PHP_SELF'] . "#ajaxCRUD\" name=\"Uploader\" method=\"POST\" ENCTYPE=\"multipart/form-data\">\n"; $return_html .= " <input type=\"file\" size=\"10\" name=\"$field_name\" />\n"; $return_html .= " <input type=\"hidden\" name=\"upload_folder\" value=\"$upload_folder\" />\n"; $return_html .= " <input type=\"hidden\" name=\"field_name\" value=\"$field_name\" />\n"; $return_html .= " <input type=\"hidden\" name=\"id\" value=\"$row_id\" />\n"; $return_html .= " <input type=\"hidden\" name=\"action\" value=\"upload\" />\n"; $return_html .= " <input type=\"submit\" name=\"submit\" value=\"Enviar\" />\n"; $return_html .= " <input type=\"button\" value=\"Cancel\" onClick=\" document.getElementById('text_$field_name$row_id').style.display = ''; document.getElementById('file_$field_name$row_id').style.display = 'none'; \"/>\n"; $return_html .= "</form>\n"; return $return_html; } }//class # In an effect to make ajaxCRUD thin i am attaching this (paging) class and a few functions all together class paging{ var $pRecordCount; var $pStartFile; var $pRowsPerPage; var $pRecord; var $pCounter;

Page 131: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

120

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var $pPageID; var $pShowLinkNotice; var $tableName; function processPaging($rowsPerPage,$pageID){ $record = $this->pRecordCount; if($record >=$rowsPerPage) $record=ceil($record/$rowsPerPage); else $record=1; if(empty($pageID) or $pageID==1){ $pageID=1; $startFile=0; } if($pageID>1) $startFile=($pageID-1)*$rowsPerPage; $this->pStartFile = $startFile; $this->pRowsPerPage = $rowsPerPage; $this->pRecord = $record; $this->pPageID = $pageID; return $record; } function myRecordCount($query){ $rs = mysql_query($query) or die(mysql_error()."<br>".$query); $rsCount = mysql_num_rows($rs); $this->pRecordCount = $rsCount; unset($rs); return $rsCount; } function startPaging($query){ $query = $query." LIMIT ".$this->pStartFile.",".$this->pRowsPerPage; $rs = q($query); //$rs = mysql_query($query) or die(mysql_error()."<br>".$query); //mysql_free_result($rs); return $rs; } function pageLinks($url){ global $choose_category,$sort, $num_ajaxCRUD_tables_instantiated; $cssclass = "paging_links"; $this->pShowLinkNotice = "&nbsp;"; if($this->pRecordCount>$this->pRowsPerPage){ $this->pShowLinkNotice = "Pagina ".$this->pPageID. " de ".$this->pRecord; //Previous link if($this->pPageID!==1){ $prevPage = $this->pPageID - 1; $link = "<a href=\"JavaScript:;\" onClick=\"" . $this->getOnClick("&pid=1&mid=$ltype&cid=$catid") . "\" class=\"$cssclass\">|<<</a>\n "; $link .= "<a href=\"JavaScript:;\" onClick=\"" . $this->getOnClick("&pid=$prevPage&mid=$ltype&cid=$catid") ."\" class=\"$cssclass\"><<</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n"; }

Page 132: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

121

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//Number links 1.2.3.4.5. for($ctr=1;$ctr<=$this->pRecord;$ctr++){ if($this->pPageID==$ctr) $link .= "<a href=\"JavaScript:;\" onClick=\"" . $this->getOnClick("&pid=$ctr") . "\" class=\"$cssclass\"><b>$ctr</b></a>\n"; else $link .= " <a href=\"JavaScript:;\" onClick=\"" . $this->getOnClick("&pid=$ctr") . "\" class=\"$cssclass\">$ctr</a>\n"; } //Previous Next link if($this->pPageID<($ctr-1)){ $nextPage = $this->pPageID + 1; $link .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"JavaScript:;\" onClick=\"" . $this->getOnClick("&pid=$nextPage&mid=$ltype&cid=$catid") . "\" class=\"$cssclass\">>></a>\n"; $link .="<a href=\"JavaScript:;\" onClick=\"" . $this->getOnClick("&pid=".$this->pRecord."&mid=$ltype&cid=$catid") . "\" class=\"$cssclass\">>>|</a>\n"; } return $link; } } function getOnClick($paging_query_string){ global $db_table; //if any hardcoding is needed... //$extra_query_params = "&Dealer=" . htmlentities($_REQUEST['Dealer']); return "pageTable('" . $extra_query_params . "$paging_query_string', '$this->tableName');"; } } /* Random functions which may or may not be used */ if (!function_exists('echo_msg_box')){ function echo_msg_box(){ global $error_msg; global $report_msg; if (is_string($error_msg)){ $error_msg = array(); } if (is_string($report_msg)){ $report_msg = array(); } //for passing errors/reports over get variables if ($_REQUEST['err_msg'] != ''){ $error_msg[] = $_REQUEST['err_msg']; } if ($_REQUEST['rep_msg'] != ''){ $report_msg[] = $_REQUEST['rep_msg']; } if(is_array($report_msg)){ $first = true; foreach ($report_msg as $e){

Page 133: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

122

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

if($first){ $reports.= "&nbsp;&nbsp; $e"; $first = false; } else $reports.= "<br /> $e"; } } if($reports != ''){ echo "<div class='report'>$reports</div>"; } if(is_array($error_msg)){ $first = true; foreach ($error_msg as $e){ if($first){ $errors.= "&nbsp;&nbsp; $e"; $first = false; } else $errors.= "<br />$e"; } } if($errors != ''){ echo "<div class='error'>$errors</div>"; } } } if (!function_exists('make_filename_safe')){ function make_filename_safe($filename){ $filename = trim(str_replace(" ","_",$filename)); $filename = str_replace("'", "", $filename); $filename = str_replace('"', '', $filename); $filename = str_replace('#', '_', $filename); $filename = str_replace('%20', '_', $filename); return stripslashes($filename); } } ?>

Page 134: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

123

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

JavaScript_functions.js (JavaScript+jQuery) //José Alves //[email protected] //ajaxCRUD var loading_image_html; //set via setLoadingImageHTML() var filterReq = ""; var sortReq = ""; var this_page; // the php file loading ajaxCRUD /* AJAX functions */ function createRequestObject() { var http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { // set type accordingly to anticipated content type //http_request.overrideMimeType('text/xml'); http_request.overrideMimeType('text/html'); } } else if (window.ActiveXObject) { // IE try { } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (!http_request) { alert('Impossivel criar uma instancia XMLHTTP'); return false; } return http_request; } var http = createRequuestObject(); var add_http = createRequestObject(); var filter_http = createRequestObject(); var sort_http = createRequestObject(); var other_http = createRequestObject(); //used for updating function sndUpdateReq(action) { http.open('get', action); http.onreadystatechange = handleResponse; http.send(null); } /* unused (for now) function sndPostReq(url, parameters) { http.open('POST', url); http.onreadystatechange = handleResponse; http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.setRequestHeader("Content-length", parameters.length); http.setRequestHeader("Connection", "close"); http.send(parameters);

Page 135: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

124

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} */ /* AJAX Deleting */ function sndDeleteReq(action) { http.open('get', action); http.onreadystatechange = function(){ if(http.readyState == 4){ var return_string = http.responseText; var broken_string = return_string.split("|"); var table = broken_string[0]; var id = broken_string[1]; $('#' + table + '_row_' + id).fadeOut('slow'); } } http.send(null); } /* AJAX Adding */ function sndAddReq(action, table) { http.open('get', action); http.onreadystatechange = function() { if(http.readyState == 4){ add_http.open('get', AJAX_file + "?ajaxAction=add&table=" + table); add_http.onreadystatechange = function(){ if(add_http.readyState == 4){ var return_string = add_http.responseText; var table_html = return_string; document.getElementById(table).innerHTML = table_html; } } add_http.send(null); } } http.send(null); } /* AJAX Filtering */ function sndFilterReq(action, table) { http.open('get', action); http.onreadystatechange = function(){ filter_http.open("get", AJAX_file + "?ajaxAction=filter&table=" + table); filter_http.onreadystatechange = function(){ if(filter_http.readyState == 4){ var table_html = filter_http.responseText; document.getElementById(table).innerHTML = table_html; } } filter_http.send(null); } http.send(null); }

Page 136: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

125

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

/* AJAX Sorting */ function sndSortReq(action, table) { http.open('get', action); http.onreadystatechange = function() { if(http.readyState == 4){ sort_http.open('get', AJAX_file + "?ajaxAction=sort&table=" + table); sort_http.onreadystatechange = function(){ if(sort_http.readyState == 4){ var table_html = sort_http.responseText; document.getElementById(table).innerHTML = table_html; } } sort_http.send(null); } } http.send(null); } function sndReqNoResponse(action) { http.open('get', action); http.onreadystatechange = doNothing; http.send(null); } function sndReqNoResponseChk(action) { //due to speed, we do this call without async http.open('get', action, false); http.onreadystatechange = doNothing; http.send(null); } //do NOTHING! :-) function doNothing(){ } /* other necessary js functions */ function changeSort(table, field_name, sort_direction){ //this should also maintain the filtering when sorting sortReq = "&sort_field=" + field_name + "&sort_direction=" + sort_direction; var req = this_page + "?table=" + table + sortReq + filterReq; sndSortReq(req, table); return false; } function pageTable(params, table){ var req = this_page + "?table=" + table + params + sortReq + filterReq; //setLoadingImage(table); sndSortReq(req, table); return false; } function setLoadingImage(table){ document.getElementById(table).innerHTML = loading_image_html; }

Page 137: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

126

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

function filterTable(obj, table, field, query_string){ var filter_fields = getFormValues(document.getElementById(table + '_filter_form'), ''); if (filter_fields != ''){ var req = this_page + "?" + filter_fields + "&" + query_string; filterReq = "&" + filter_fields + "&" + query_string; } else{ var req = this_page + "?action=unfilter"; filterReq = "&action=unfilter"; } // function to send the filter var func = function() { setLoadingImage(table); sndFilterReq(req, table); }; // Check to see if there is already a timeout and if so...cancel it and create a new one if ( obj.zid ) { clearTimeout(obj.zid); } //set a timeout after typing in filter field (reduces number of calls to db) obj.zid = setTimeout(func, 1200); } function confirmDelete(id, table, pk){ if(confirm('De certeza que quer apagar este item da base de dados? Isto nao pode ser desfeito.')) { AJAX_deleteRow(id, table, pk); } } function deleteFile(field, id){ if(confirm('De certeza que quer apagar este ficheiro? Isto nao pode ser desfeito.')) { location.href="?action=delete_file&field_name=" + field + "&id=" + id; } } function AJAX_deleteRow(id, table, pk){ var req = AJAX_file + '?ajaxAction=delete&id=' + id + '&table=' + table + '&pk=' + pk; sndDeleteReq(req); } //for handling all AJAX editing //TODO: make function name less generic function handleResponse() { if(http.readyState == 4){ var return_string = http.responseText; //if there's an error in the update if (return_string.substring(0,5) == 'error'){ var broken_string = return_string.split("|"); var id = broken_string[1];

Page 138: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

127

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

var old_value = broken_string[2]; //only enter an alert if you want to. we removed because so many people complained //window.alert('No changes made to cell.'); //display the display section, fill it with prior content document.getElementById(id+'_show').innerHTML = old_value; document.getElementById(id+'_show').style.display = ''; //hide editing and saving sections document.getElementById(id+'_edit').style.display = 'none'; document.getElementById(id+'_save').style.display = 'none'; } else{ var broken_string = return_string.split("|"); var id = broken_string[0]; var replaceText = myStripSlashes(broken_string[1]); //display the display section, fill it with new content if (replaceText != "{selectbox}"){ if (replaceText != null){ document.getElementById(id+'_show').innerHTML = replaceText; } else{ document.getElementById(id+'_show').innerHTML = ""; } } else{ var the_selectbox = document.getElementById(id); document.getElementById(id+'_show').innerHTML = the_selectbox.options[the_selectbox.selectedIndex].text; } document.getElementById(id+'_show').style.display = ''; //hide editing and saving sections document.getElementById(id+'_edit').style.display = 'none'; document.getElementById(id+'_save').style.display = 'none'; } } } function getFormValues(fobj,valFunc) { var str = ""; var valueArr = null; var val = ""; var cmd = ""; var element_type; for(var i = 0;i < fobj.elements.length;i++) { element_type = fobj.elements[i].type; if (element_type == 'text' || element_type == 'textarea'){ if(valFunc) {

Page 139: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

128

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

//use single quotes for argument so that the value of //fobj.elements[i].value is treated as a string not a literal cmd = valFunc + "(" + 'fobj.elements[i].value' + ")"; val = eval(cmd) } str += fobj.elements[i].name + "=" + escape(fobj.elements[i].value) + "&"; } else if(element_type == 'select-one'){ str += fobj.elements[i].name + "=" + fobj.elements[i].options[fobj.elements[i].selectedIndex].value + "&"; } else if(element_type == 'checkbox'){ var chkValue = ''; if (fobj.elements[i].checked){ var chkValue = escape(fobj.elements[i].value); } str += fobj.elements[i].name + "=" + chkValue + "&"; } } str = str.substr(0,(str.length - 1)); return str; } function clearForm(formIdent){ var form, elements, i, elm; form = document.getElementById ? document.getElementById(formIdent) : document.forms[formIdent]; if (document.getElementsByTagName){ elements = form.getElementsByTagName('input'); for( i=0, elm; elm=elements.item(i++); ){ if (elm.getAttribute('type') == "text"){ elm.value = ''; } else if (elm.getAttribute('type') == "checkbox"){ elm.checked = false; } } elements = form.getElementsByTagName('select'); for( i=0, elm; elm=elements.item(i++); ){ elm.options.selectedIndex=0; } elements = form.getElementsByTagName('textarea'); for( i=0, elm; elm=elements.item(i++); ){ elm.value = ''; } } else{ elements = form.elements; for( i=0, elm; elm=elements[i++]; ){ if (elm.type == "text"){ elm.value =''; } }

Page 140: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

129

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} } /* * This function is to not allow non-numeric values for fields with an INT or DECIMAL datatype */ function fn_validateNumeric(evento, elemento, dec) { var valor=elemento.value; var charWich=evento.which; var charCode=evento.keyCode; if(charWich==null){ charWich=charCode; } if ( (charWich>=48 && charWich<=57) || charCode==8 || charCode==39 || charCode==37 || charCode==46 || charWich==46 || charWich==13) { if(dec=="n" && charWich == 46){ return false; } else{ if(valor.indexOf('.')!=-1 && charWich==46){ return false; } } return true; } else{ return false; } } function myAddSlashes(str) { str=str.replace(/\"/g,'\\"'); return str; } function myStripSlashes(str) { str=str.replace(/\\'/g,'\''); str=str.replace(/\\"/g,'"'); return stor; } var prior_class = ''; function hover(obj){ //obj.className='class_hover'; obj.style.backgroundColor = '#FFFF99'; } function unHover(obj){ obj.className = ''; } function setAllCheckboxes(str, ck) { var ckboxes = document.getElementsByName(str); for (var i=0; i < ckboxes.length; i++){ if (ckboxes[i].checked == ck) { ckboxes[i].checked = ck; ckboxes[i].click(); }

Page 141: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

130

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} } //I don't know why JavaScript doesn't have this function built into the language! Array.prototype.findIndex = function(value){ var ctr = ""; for (var i=0; i < this.length; i++) { // use === to check for Matches. ie., identical (===), ; if (this[i] == value) { return i; } } return ctr; }; if('function' != typeof Array.prototype.splice) { Array.prototype.splice = function(s, dC) { s = +s || 0; var a = [], n = this.length, nI = Math.min(arguments.length - 2, 0), i, j; s = (0 > s) ? Math.max(s + n, 0) : Math.min(s, n); dC = Math.min(Math.max(+dC || 0, 0), n - s); for(i = 0; i < dC; ++i) {a[i] = this[s + i];} if(nI < dC) { for(i = s, j = n - dC; i < j; ++i) { this[i + nI] = this[i + dC]; } } else if(nI > dC) { for(i = n - 1, j = s + dC; i >= j; --i) { this[i + nI - dC] = this[i]; } } for(i = s, j = 2; j < nI; ++i, ++j) {this[i] = arguments[j];} this.length = n - dC + nI; return a; }; }

Page 142: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

131

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

CSS do BackOf f ice /* CSS da grelha CRUD AJAX do BackOffice José Alves - 2010 */ h3{ text-align: center; } .hand_cursor{ cursor: pointer; /* cursor em forma de mao */ cursor: hand; /* para o IE 5.x */ } .paging_links{font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; color:#000000;} .ajaxCRUD { background: #F4F2FD; border-color: #BBB1ED; border-style: solid; border-width: 0px; padding:4px; border-collapse:collapse; margin-top:10px; margin-bottom:10px; } .ajaxCRUD th{ background: #CFDBF3; font-weight: bold; color:#445276; font-size: 12px; } .ajaxCRUD th a{ color: #173D7F; } .ajaxCRUD td, th a{ text-decoration: none; } .ajaxCRUD td, th a:hover{ color: #000; } .ajaxCRUD td{ font-family: Arial, Verdana; font-size: 11px; background: #F9F8FB; color: #716E6E; font-weight:normal; text-align: center; vertical-align: middle;

Page 143: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

132

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} .ajaxCRUD td, .ajaxCRUD th{ padding: 5px 5px; } table td.odd, table tr.odd, tr.odd td, tbody tr.odd th{ background-color: #f2f2f2; } .editingSize{ font-size: 10px; min-width:100px; } .editable:hover{ background-color: #FFFF99; } input, select, textarea{ font-size: 100%; border-top: 1px solid #7c7c7c; border-left: 1px solid #c3c3c3; border-right: 1px solid #c3c3c3; border-bottom: 1px solid #ddd; background: #fff url("fieldbg.gif") repeat-x top; color: #333; padding: 2px 0 2px 2px; } .btn{ font-size: 11px; } .report { text-align: left; border-top: 1px solid #9c9; border-bottom: 1px solid #9c9; padding: 5px 5px 5px 30px; font-size: 11px; margin: 0 20px 15px 20px; color: #060; background: url("checkicon.gif") #e2f9e3 left no-repeat; } .error { text-align: left; font-weight: bold; border-top: 1px solid #c99; border-bottom: 1px solid #c99; padding: 5px 5px 5px 27px; font-size: 11px; margin: 0 20px 15px 20px; background: url("badicon.gif") #c00 left no-repeat; color: #fff; }

table.jCalendar { border: 1px solid #000; background: #aaa; border-collapse: separate; border-spacing: 2px;

Page 144: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

133

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} table.jCalendar th { background: #333; color: #fff; font-weight: bold; padding: 3px 5px; } table.jCalendar td { background: #ccc; color: #000; padding: 3px 5px; text-align: center; } table.jCalendar td.other-month { background: #ddd; color: #aaa; } table.jCalendar td.today { background: #666; color: #fff; } table.jCalendar td.selected { background: #f66; color: #fff; } table.jCalendar td.selected.dp-hover { background: #f33; color: #fff; } table.jCalendar td.dp-hover, table.jCalendar tr.activeWeekHover td { background: #fff; color: #000; } table.jCalendar tr.selectedWeek td { background: #f66; color: #fff; } table.jCalendar td.disabled, table.jCalendar td.disabled.dp-hover { background: #bbb; color: #888; } table.jCalendar td.unselectable, table.jCalendar td.unselectable:hover, table.jCalendar td.unselectable.dp-hover { background: #bbb; color: #888; }

Page 145: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

134

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

/* para o calendario popup */ div.dp-popup { position: relative; background: #ccc; font-size: 10px; font-family: arial, sans-serif; padding: 2px; width: 171px; line-height: 1.2em; } div#dp-popup { position: absolute; z-index: 199; } div.dp-popup h2 { font-size: 12px; text-align: center; margin: 2px 0; padding: 0; } a#dp-close { font-size: 11px; padding: 4px 0; text-align: center; display: block; } a#dp-close:hover { text-decoration: underline; } div.dp-popup a { color: #000; text-decoration: none; padding: 3px 2px 0; } div.dp-popup div.dp-nav-prev { position: absolute; top: 2px; left: 4px; width: 100px; } div.dp-popup div.dp-nav-prev a { float: left; } /* O Opera precisa destas regras */ div.dp-popup div.dp-nav-prev a, div.dp-popup div.dp-nav-next a { cursor: pointer; } div.dp-popup div.dp-nav-prev a.disabled, div.dp-popup div.dp-nav-next

a.disabled { cursor: default; } div.dp-popup div.dp-nav-next { position: absolute; top: 2px; right: 4px; width: 100px; }

Page 146: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

135

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

div.dp-popup div.dp-nav-next a { float: right; } div.dp-popup a.disabled { cursor: default; color: #aaa; } div.dp-popup td { cursor: pointer; } div.dp-popup td.disabled { cursor: default; } /* edit */ a.dp-choose-date { float: left; width: 16px; height: 16px; padding: 0; margin: 5px 3px 0; display: block; text-indent: -2000px; overflow: hidden; background: url(../images/calendar.png) no-repeat; } a.dp-choose-date.dp-disabled { background-position: 0 -20px; cursor: default; } /* cria espaço para o icon do calendario */ input.dp-applied { width: 140px; float: left; }

Page 147: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

136

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

CSS do FrontEnd /* ||||||||||||| CSS FRONT OFFICE||||||||||||||||| */ /** BASICO */ body { margin: 0px; padding: 0px; background: #FFFFFF url(images/homepage01.jpg) repeat-x left top; } /** FORMS */ form { margin: 0px; padding: 0px; } /** HEADINGS */ h1, h2, h3, h4, h5, h6 { margin: 0px; } /** TEXTOS */ body, th, td, input, textarea, select { font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #333333; } p, blockquote, ul, ol, dl { margin-top: 0px; margin-bottom: 1em; /*text-align: justify;*/ line-height: 16px; } .text1 { width: 166px; height: 21px; padding: 11px 0px 0px 16px; background: url(images/homepage05.gif) no-repeat left top; font-size: 11px; color: #FFFFFF; } .fundoverde { width: 233px; height: 32px; /*padding: 11px 0px 0px 16px;*/ background: url(images/top_tables.gif) no-repeat ; font-size: 11px; color: #FFFFFF; }

Page 148: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

137

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

.fundotabelas { background: url(images/fundo_tabelas.gif) repeat-y; } .fimtabelas { height:15px; background: url(images/fim_tabelas.gif) no-repeat; } .fundoverde2 { width: 182px; height: 32px; /*padding: 11px 0px 0px 16px;*/ background: url(images/top_tables2.gif) no-repeat ; font-size: 11px; color: #FFFFFF; } .fundotabelas2 { background: url(images/fundo_tabelas2.gif) repeat-y; } .fimtabelas2 { height:15px; background: url(images/fim_tabelas2.gif) no-repeat; } .text2 { margin-bottom: 10px; font-size: 11px; } .bold { font-weight:bold; } .text3 { text-align: center; color: #A1A1A1; } .text4 { /*width: 166px;*/ height: 21px; padding: 9px 0px 0px 16px; font-size: 11px; color: #FFFFFF; } .azul { color:#0B43B9;

Page 149: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

138

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} .verde { color:#608410; } .downloads_bg { display:block; height:31px; text-decoration:none; padding: 10px 0px 0px 15px; background: url(images/downloads_bg.gif) no-repeat left top; color: #434343; } .allborders{ border-left:1px solid #CFDFF0; border-right:1px solid #CFDFF0; border-top:1px solid #CFDFF0; border-bottom:1px solid #CFDFF0; } .allborders_dark{ border-left:1px solid #666666; border-right:1px solid #666666; border-top:1px solid #666666; border-bottom:1px solid #666666; } .links { font-weight: normal; color: #333333; background : #F4F7FF; border-color:#CFDFF0; border-style:solid; border-width:1px; } /** LISTAS */ .list1 { margin: 0px; padding: 0px; list-style: none; line-height: normal; } .list1 li { display: inline; } .list1 a { display: block; width: 166px; height: 22px; padding: 8px 0px 0px 16px; background: url(images/homepage06.gif) no-repeat left top; text-decoration: none;

Page 150: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

139

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

color: #434343; } .list1 a:hover { text-decoration: underline; } .list1 .last a { margin-bottom: 10px; background-image: url(images/homepage07.gif); } .list2 { margin: 0px; padding: 0px; list-style: none; line-height: normal; } .list2 li { display: inline; } .list2 a { display: block; text-decoration:none; width: 218px; height: 21px; margin: 0px 0px 12px 0px; padding: 10px 0px 0px 15px; background: url(images/homepage11.gif) no-repeat left top; color: #434343; } .list2 a:hover { text-decoration:underline; } /** LINKS */ a { color: #333333; } a:hover { text-decoration: none; } .link1 { color: #7A7B7B; } .link2 { text-align: center; text-decoration: none; font-weight: bold; color: #FFFFFF;

Page 151: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

140

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} .link2:hover { text-align: center; text-decoration:underline; font-weight: bold; color: #FFFFFF; } .link3 { display: block; height: 20px; padding: 5px 0px 0px 20px; background: url(images/homepage19.jpg) no-repeat left top; text-decoration: none; font-weight: bold; color: #FFFFFF; } .link3:hover { text-decoration: underline; } .link4 { text-decoration: none; font-weight:normal; color: #333333; } .link4:hover { text-decoration:underline; font-weight:normal; color: #111111; } .linkdestaque { text-decoration: none; font-weight:bold; text-transform:uppercase; color: #333333; } .linkdestaque:hover { text-decoration:underline; font-weight:bold; text-transform:uppercase; color: #444444; } .linknoticia { text-decoration: none; font-weight:bold; color: #333333;

Page 152: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

141

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

} .linknoticia:hover { text-decoration:underline; font-weight:bold; color: #444444; } /** STYLES */ .style1 { } .style1 a { } .style1 a:hover { } /** BACKGROUNDS */ .bg1 { background: url(images/homepage03.gif) repeat-x left top; } .bg2 { background: url(images/homepage20.gif) repeat-x left top; } .bg3 { background: #DDDDDD; } .bgverde { background: url(images/back_botao.gif) repeat-x left top; } .bgverde2 { color:#FFFFFF; font-weight:bold; vertical-align:middle; background: url(images/back_verde.gif) repeat-x left top; } /** FORMS 2 */ .button1 { color:#FFFFFF; border:none; padding:4px; background: url(images/homepage03.gif) repeat-x left top; } .button1:hover { color:#FFFFFF; border:none; text-decoration:underline; padding:4px; background: url(images/homepage03.gif) repeat-x left top; } .input1 { width: 271px; padding: 3px 5px; color:#AAAAAA; background: #FFFFFF url(images/back_textbox.gif) repeat-x left top; border: 1px solid #CCCCCC; } .input12 {

Page 153: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

142

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

width: 271px; padding: 3px 5px; color:#333333; background: #FFFFFF url(images/back_textbox.gif) repeat-x left top; border: 1px solid #CCCCCC; } .input2 { background: url(images/back_botao.gif) repeat-x left top; border: 1px solid #71822B; font-size: 10px; color: #FFFFFF; } .input3 { width: 200px; padding: 3px 5px; margin-bottom:5px; color:#AAAAAA; background: #FFFFFF url(images/back_textbox.gif) repeat-x left top; border: 1px solid #CCCCCC; } /** MISC **/ .align-justify { text-align: justify; } .align-right { text-align: right; } img { border: none; } .img1 { float: left; margin: 3px 15px 0px 0px; } .imgborder { float: left; /*margin: 3px 15px 0px 0px;*/ padding:4px; border-width:1px; border-style:solid; border-color:#BBBBBB; } .imgborder2 { float: right; /*margin: 3px 15px 0px 0px;*/ padding:4px; border-width:1px; border-style:solid; border-color:#BBBBBB; } .imgborder3 {

Page 154: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

143

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

/*margin: 3px 15px 0px 0px;*/ padding:4px; border-width:1px; border-style:solid; border-color:#BBBBBB; } .img2 { float: right; margin: 3px 0px 0px 15px; } hr { /*display: none;*/ noshadow; height:1px; color:#0B45BA; } .hr1 { height: 1px; } .borders_tab { position:relative; display:inline; top: 1px; float:left; padding: 4px 10px; margin: 0px 1px 0px 0px; font: bold 0.8em sans-serif; background-color: #DDD; list-style: none; border-left: solid 1px #999; border-bottom: solid 1px #999; border-top: solid 1px #999; border-right: solid 1px #999; -moz-user-select: none; -khtml-user-select: none; cursor: pointer; } .borders_tab:hover{ background-color: #BBB; } /* |||||||||||||||||||||| FIM CSS GERAL DA PAGINA |||||||||||||||||| */ /* MENUs MUNICIPIO e FREGUESIAS */ .dropmenu { position: absolute; left: -1500px; visibility: visible; z-index: 999999; float: left;

Page 155: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

144

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

width: 154px; border-width: 0px; border-style: solid; border-color: #000000; background-color: #FFFFFF; } .dropmenu ul { margin: 0; padding: 0; list-style-type: none; } .dropmenu li { display: inline; } .dropmenu a, .dropmenu a:visited, .dropmenu a:active { display: block; width: 148px; height:14px; padding: 1px; padding-bottom: 1px; margin: 1px; font-family:Verdana, Arial, Helvetica, sans-serif; font-size: 9px; /*font-weight: bold;*/ text-align: center; text-decoration: none; vertical-align:middle; color: #FFFFFF; background-color: #0C47BB; } .dropmenu a:hover { padding: 1px; padding-bottom: 1px; margin: 1px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9px; /*font-weight: bold;*/ text-align: center; text-decoration: none; color: #000000; background-color: #FFFFFF; } /* FIM MENU MUNICIPIO */ /* CALENDARIO */ .CorCelula { background-color:#ACCDFA; } .CorCelula:hover { background-color:#a0b71b; } .TituloMes { font-family: Verdana, Arial, Helvetica, sans-serif,Tahoma; font-size: 11px; text-align:center; font-weight: bold; color:#0B43B9;

Page 156: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

145

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

padding-bottom:15px; } a.TituloMes { font-family: Verdana, Arial, Helvetica, sans-serif,Tahoma; font-size: 11px; font-weight: bold; color:#003366; background-color: #FFFFFF; } /* FIM CALENDARIO */ /*LIGHTBOX lytebox*/ #lbOverlay { position: fixed; top: 0; left: 0; z-index: 999998; width: 100%; height: 500px; } #lbOverlay.blue { background-color: #011D50; } #lbOverlay.grey { background-color: #000000; } #lbOverlay.red { background-color: #330000; } #lbOverlay.green { background-color: #003300; } #lbOverlay.gold { background-color: #666600; } #lbMain { position: absolute; left: 0; width: 100%; z-index: 999999; text-align: center; line-height: 0; } #lbMain a img { border: none; } #lbOuterContainer { position: relative; background-color: #fff; width: 200px; height: 200px; margin: 0 auto; } #lbOuterContainer.blue { border: 3px solid #5F89D8; } #lbOuterContainer.grey { border: 3px solid #888888; } #lbOuterContainer.red { border: 3px solid #DD0000; } #lbOuterContainer.green { border: 3px solid #00B000; } #lbOuterContainer.gold { border: 3px solid #B0B000; } #lbDetailsContainer { font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; width: 100%; line-height: 1.4em; overflow: auto; margin: 0 auto; } #lbDetailsContainer.blue { border: 3px solid #5F89D8; border-top: none; } #lbDetailsContainer.grey { border: 3px solid #888888; border-top: none; } #lbDetailsContainer.red { border: 3px solid #DD0000; border-top: none; } #lbDetailsContainer.green { border: 3px solid #00B000; border-top: none; } #lbDetailsContainer.gold { border: 3px solid #B0B000; border-top: none; } #lbImageContainer, #lbIframeContainer { padding: 10px; } #lbLoading { position: absolute; top: 45%; left: 0%; height: 32px; width: 100%; text-align: center; line-height: 0; background: url(images/loading.gif) center no-repeat; }

Page 157: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

146

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

#lbHoverNav { position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; } #lbImageContainer>#lbHoverNav { left: 0; } #lbHoverNav a { outline: none; } #lbPrev { width: 49%; height: 100%; background: transparent url(images/blank.gif) no-repeat; display: block; left: 0; float: left; } #lbPrev.blue:hover, #lbPrev.blue:visited:hover { background: url(images/prev_blue.gif) left 15% no-repeat; } #lbPrev.grey:hover, #lbPrev.grey:visited:hover { background: url(images/prev_grey.gif) left 15% no-repeat; } #lbPrev.red:hover, #lbPrev.red:visited:hover { background: url(images/prev_red.gif) left 15% no-repeat; } #lbPrev.green:hover, #lbPrev.green:visited:hover { background: url(images/prev_green.gif) left 15% no-repeat; } #lbPrev.gold:hover, #lbPrev.gold:visited:hover { background: url(images/prev_gold.gif) left 15% no-repeat; } #lbNext { width: 49%; height: 100%; background: transparent url(images/blank.gif) no-repeat; display: block; right: 0; float: right; } #lbNext.blue:hover, #lbNext.blue:visited:hover { background: url(images/next_blue.gif) right 15% no-repeat; } #lbNext.grey:hover, #lbNext.grey:visited:hover { background: url(images/next_grey.gif) right 15% no-repeat; } #lbNext.red:hover, #lbNext.red:visited:hover { background: url(images/next_red.gif) right 15% no-repeat; } #lbNext.green:hover, #lbNext.green:visited:hover { background: url(images/next_green.gif) right 15% no-repeat; } #lbNext.gold:hover, #lbNext.gold:visited:hover { background: url(images/next_gold.gif) right 15% no-repeat; } #lbPrev2, #lbNext2 { text-decoration: none; font-weight: bold; } #lbPrev2.blue, #lbNext2.blue, #lbSpacer.blue { color: #01379E; } #lbPrev2.grey, #lbNext2.grey, #lbSpacer.grey { color: #333333; } #lbPrev2.red, #lbNext2.red, #lbSpacer.red { color: #620000; } #lbPrev2.green, #lbNext2.green, #lbSpacer.green { color: #003300; } #lbPrev2.gold, #lbNext2.gold, #lbSpacer.gold { color: #666600; } #lbPrev2_Off, #lbNext2_Off { font-weight: bold; } #lbPrev2_Off.blue, #lbNext2_Off.blue { color: #B7CAEE; } #lbPrev2_Off.grey, #lbNext2_Off.grey { color: #CCCCCC; } #lbPrev2_Off.red, #lbNext2_Off.red { color: #FFCCCC; } #lbPrev2_Off.green, #lbNext2_Off.green { color: #82FF82; } #lbPrev2_Off.gold, #lbNext2_Off.gold { color: #E1E100; } #lbDetailsData { padding: 0 10px; } #lbDetailsData.blue { color: #01379E; } #lbDetailsData.grey { color: #333333; } #lbDetailsData.red { color: #620000; } #lbDetailsData.green { color: #003300; } #lbDetailsData.gold { color: #666600; } #lbDetails { width: 60%; float: left; text-align: left; }

Page 158: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

147

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

#lbCaption { display: block; font-weight: bold; } #lbNumberDisplay { float: left; display: block; padding-bottom: 1.0em; } #lbNavDisplay { float: left; display: block; padding-bottom: 1.0em; } #lbClose { width: 64px; height: 28px; float: right; margin-bottom: 1px; } #lbClose.blue { background: url(images/close_blue.png) no-repeat; } #lbClose.grey { background: url(images/close_grey.png) no-repeat; } #lbClose.red { background: url(images/close_red.png) no-repeat; } #lbClose.green { background: url(images/close_green.png) no-repeat; } #lbClose.gold { background: url(images/close_gold.png) no-repeat; } #lbPlay { width: 64px; height: 28px; float: right; margin-bottom: 1px; } #lbPlay.blue { background: url(images/play_blue.png) no-repeat; } #lbPlay.grey { background: url(images/play_grey.png) no-repeat; } #lbPlay.red { background: url(images/play_red.png) no-repeat; } #lbPlay.green { background: url(images/play_green.png) no-repeat; } #lbPlay.gold { background: url(images/play_gold.png) no-repeat; } #lbPause { width: 64px; height: 28px; float: right; margin-bottom: 1px; } #lbPause.blue { background: url(images/pause_blue.png) no-repeat; } #lbPause.grey { background: url(images/pause_grey.png) no-repeat; } #lbPause.red { background: url(images/pause_red.png) no-repeat; } #lbPause.green { background: url(images/pause_green.png) no-repeat; } #lbPause.gold { background: url(images/pause_gold.png) no-repeat; } /* FIM LIGHTBOX */ /* Cap Slide */ .ic_container{ vertical-align:baseline; margin:10px; position:relative; /*-moz-border-radius:10px; -webkit-border-radius:10px; -khtml-border-radius:10px; -moz-box-shadow: 0 1px 3px #888; -webkit-box-shadow: 0 1px 3px #888;*/ } .overlay{ opacity:0.3; position:absolute; top:0px; bottom:0px;

Page 159: José Manuel Gonçalves Alvesintranet.dei.uminho.pt/gdmi/galeria/temas/pdf/30049.pdf · geral - e em português foi -oferecida, com a possibilidade de se localizar restaurantes, hotéis,

148

Desenvolvimento de um sistema dinâmico de georeferenciação de conteúdos web

José Manuel Gonçalves Alves

left:0px; right:0px; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50); } .ic_caption{ position:absolute; opacity:0.6; overflow:hidden; margin:0px; padding:0px; left:0px; right:0px; cursor:default; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=60); } .ic_category{ text-transform:uppercase; font-size:11px; letter-spacing:3px; padding:5px; margin:0px; } .ic_caption h3{ padding:0px 5px 5px 5px; margin:0px; font-size:18px; } .ic_text{ font:Arial, Helvetica, sans-serif; padding:5px; margin:0px; text-align:justify; font-size:11px; } /*Fim cap Silde*/