Поддержка
E-mail
Имя
Тема
Суть проблемы
Загрузить

Gradoservice
developers community
Авторизация
Close
Авторизация
Забыли пароль?
Регистрация
или
Регистрация
  • Главная
  • Статьи
  • Документация
  • Продукты
Поддержка
You are here: Home / 2013 / Май / 16 / Написание модуля mapSurfer

Написание модуля mapSurfer

16 мая 2013 admin

В данной статье будет рассмотрено создание модуля системы mapSurfer.

mapSurfer

1) Первый этап. Создание нового проекта при помощи Play Framework 2.1.0
Полную документацию по работе с фреймворком можно найти на официальном сайте http://www.playframework.com/documentation/2.1.0/Home

Для написания модуля необходимо использовать jdk версии 1.6, так как основной проект написан именно на этой версии java, и с другими версиями могут возникнуть ошибки.
В первую очередь нужно установить Play Framework 2.1.0, полное описание того, как это делается есть на официальном сайте http://www.playframework.com/documentation/2.1.0/Installing .
Далее необходимо создать новый проект http://www.playframework.com/documentation/2.1.0/NewApplication , указав при создании template «gradoservice/mapsurfergs-module», введя его название как показано на картинке:

create

Для редактирования проекта удобно использовать IntelliJ IDEA. Для работы с IntelliJ IDEA необходимо выполнить команду play idea, находясь в папке с проектом. Более подробно о разработке проекта в различных IDE: http://www.playframework.com/documentation/2.1.0/IDE .

2) Подключение базы данных
application.conf
В этот файл в первую очередь необходимо добавить информацию для подключения к базе данных.

db.default.driver=org.postgresql.Driver //драйвер для использования БД postgreSQL

db.default.url=»jdbc:postgresql://’IP адрес БД’:’порт БД’/my_DB» //адрес БД
db.default.user=user_name //имя пользователя для подключения к БД
db.default.password=user_password //пароль пользователя для подключения к БД

3. Пути
Файл «geoportal.modules.module_name.routes».

Внутри этого файла прописываются соответствия для HTTP запросов в следующем формате:

тип запросапуть относительно корня модуля, по которому будут обрабатываться запросы. Итоговый путь относительно всего сайта будет выглядеть следующим образом: /modules/myModule/myRouteфункция, обрабатывающая запросы по данному пути.

GET
POST
/myRoute controllers.geoportal.modules.module_name.
MyController.myFunction

4. Создание серверной части модуля

Модели
все классы — модели необходимо поместить в package «models.geoportal.modules.’название модуля'» это необходимо для того, чтобы не возникло конфликтов с классам основного проекта и других модулей.

для того, чтобы связать класс с таблицей в базе данных перед определением класса необходимо добавить следующие аннотации:

@Entity
@Table(schema = «shema», name = «table_name»)

после этого каждое поле класса сопоставится по названию со столбцом в таблице «table_name». Для полей так же существует множество аннотаций, таких как
@Id — ставится перед полем primary key
@OneToMany, @OneToOne и т.д. — задают связи между разными таблицами

существуют и многие другие аннотации, про которые можно прочитать на официальном сайте Ebean ORM.

Ebean так же позволяет удобно выбирать из БД необходимую информацию посредством finder, для этого необходимо создать в классе статическую переменную:

public static Finder<Long,MyClass> find = new Finder(Long.class, MyClass.class);

после этого становится доступным удобный поиск необходимых объектов данного класса из БД.

Пример:

List myClass = MyClass.find.where().like("name", name).findList();

Контроллеры
Контроллеры нужны для оперирования моделями и ответами на HTTP запросы, все контроллеры должны находиться в package «controllers.geoportal.modules.’название модуля'».

пример отдачи пользователю Json объекта

/****/
ObjectNode result = Json.newObject();
/****/
result.put("key", Json.toJson(value));
return crossdomain(ok(result).
as("Content-Type: application/json; charset=UTF-8"));

5. Создание front-end части модуля
Вся front-end часть модуля должна находиться в отдельной папке названной так же как модуль , которая находится в директории public/modules.. В этой директории находятся 3 папки:
javascripts — в этой папке должны находиться все файлы с java-script
images — все картинки
stylesheets — стили

В этой же директории находится файл MyModule.json, в котором необходимо записать подключаемые все js и css файлы с расположением в формате:

[{
        "path": "stylesheets/MyStyles.css",
        "type": "css"
    },
    {
        "path": "javascripts/controllers/MyController.js",
        "type": "script"
    }]

Определение
Для построения структуры модуля нужно определить его в системе:

GP.Module.MyModule = {};

Так же, при необходимости использовать контроллеры, виджеты, сторы и т.д. их тоже нужно определить:

GP.Module.MyModule.Controller = {};
GP.Module.MyModule.Widget = {};
GP.Module.MyModule.Store = {};

Наследование
В нашей системе существует наследование классов в JavaScript, оно осуществляется по следующей схеме:
Допустим, нам нужно создать класс MyController, который должен наследоваться от класса GP.Controller

GP.Module.MyModule.Controller.MyController = GP.Controller.extend({
    /* тело класса */
});

M.Util.bind
Для вызова функции в определенном контексте необходимо сделать следующее:

M.Util.bind(
    this._saveToStore,//выполняемая функция
    this) // контекст, в котором функция будет выполняться

События
В ядре javaScript части приложения реализована система событий: для любого экземпляра класса, наследующего от GP.Widget, GP.Controller, GP.Store можно создать событие, которое возможно «поймать» в любом другом месте.
Пример создания события внутри функции виджета:

this.fire(
    "event", //событие
    {variable:value} //передаваемые переменные
);

Пример отслеживания события:

GP.widgets.myWidget.on(
     "event", //событие
     function, //функция, которая будет выполняться при срабатывании события
     context //контекст, в котором будет выполняться функция, например this
);

Контроллеры
Выполнение модуля должно начинаться с создания экземпляра класса, наследующегося от GP.Controller,
например GP.Module.MyModule.Controller.MyController.

написание контроллера:

GP.Module.MyModule.Controller.MyController = GP.Controller.extend({
    initialize: function() {
        GP.Controller.prototype.initialize.call(this,{});
            /* действия контроллера */
    }
});

Создание контроллера:

GP.controllers.MyController = new GP.Module.Controller.MyController();

В качестве конструктора контроллера используется функция initialize, в которой необходимо вызвать конструктор родителя, т.е. контроллер должен выглядеть следующим образом:

initialize: function() {
GP.Controller.prototype.initialize.call(this,{});
      /* действия контроллера */
}

Хранилище данных Store, Model .
Для хранения данных удобно использовать Store.
В первую очередь нужно создать модель, в которой необходимо описать все составляющие элементов стора.
Пример модели стора с различными типами данных:

GP.Module.MyModule.Model.MyModel = GP.Model.extend({
      fields: [
            /* описание полей объектов, которые будут храниться в Store */
          {
                name: "id", //имя поля
                type: "integer", //тип значений поля
                dvalue: 0, //значение по умолчанию
                notNull: true, //может ли поле быть undefined, если false, то да
                rusName: "Id" //русское название
          },

          {name: "title", type: "string", dvalue: "", notNull:true, rusName: "заголовок"},
          {name: "subTitle", type: "string", dvalue: "", notNull:true, rusName: "подзаголовок"},
          {name: "geom", type: "object", dvalue: "", notNull:true, rusName: "геометрия"},
          {name: "districtFields", type: "object", dvalue: [], notNull:true, rusName: "fields"},
          {name: "bbox", type: "object",dvalue: "", notNull:true,rusName:"bBox"}
       ]});

Следующим шагом нужно описать Store.

GP.Module.MyModule.Store.DistrictsStore = GP.Store.extend({
          model: GP.Module.MyModule.Model.MyModel
});

События Store:

Событие «ready» срабатывает, когда Store готов к использованию.

GP.stores.module.myModule.myStore.on(
     "ready",    //название события
      function () {      //функция, выполняемая при срабатывании события
         this.hideMap(this._curtainDragging.offset().left);
      }, 
      this //контекст выполнения функции
    );

Виджеты
В виджетах, как правило, происходит непосредственно отрисовка и управление содержимого в HTML.
Конструктор GP.Widget принимает два элемента: первый записывается в options, и к нему можно обращаться во время написания класса, второй объект может быть объектом jQuery или текстовой строчкой(String), хранящей в себе id HTML элемента и нужен для того, чтобы записать jQuery объект, указывающий на HTML элемент во внутреннюю переменную _mainElement.
При создании виджета, наследуемого от GP.Widget, выполняется функция _createWidget, которая обязательно должна быть определена. В виджетах, которые наследуются от других классов, например GP.Widget.LeftPanel (оперирующие левой панелью) функция — конструктор может быть другой.

Написание виджета:

GP.Module.MyModule.Widget.MyWidget= GP.Widget.extend({
    _createWidget: function() {      
            /* действия виджета*/
    }
});

Создание виджета:

GP.widgets.myWidget= new GP.Module.Widget.MyWidget();

Событие создания виджета, выполняемая функция принимает на вход переменную, содержащую создаваемый виджет.

GP.on("widgetCreate", myFunction, context);

Событие удаления виджета, выполняемая функция принимает на вход переменную, содержащую удаляемый виджет.

GP.on("widgetDestroy", myFunction, context);

Авторизация
Событие выполнения авторизации можно отследить следующим образом:

GP.widgets.authentication.on(
     "authenticationSuccess",
     function(user){}
);

Диалоговое окно (GP.Widget.DialogBox)

Пример работы с DialogBox

if(this._myDialogBox == undefined){ //предупреждения открытия одного окна несколько раз
     this._myDialogBox = new GP.Widget.DialogBox( //создание DialogBox
        {
           dialogBoxId:"myDialogBox", //id DOM элемента диалового окна
           width:110, //ширина окна
           height:200px, //высота окна
           top:87, //расположение сверху
           left:106 //расположение слева
        },
        "#wrap" //элемент, в который помещается диалоговое окно
      );
     this._myDialogBox.on(
                   "closeDialog",       //событие, срабатывающее при закрытии окна
                   this._disableMyDialogBox,   //функция, которая будет выполняться
                   this                //контекст, в котором будет выполняться функция
             );                                                  
     this._myDialogBox.setTitle("заголовок"); //установить заголовок окна
     this._myDialogBox.setContainer('<div>внутренность DialogBox</div>'); //добавить содержимое 
                                                                                              //в диалоговое окно
     this._myDialogBox.show(); //показать диалоговое окно
     this._myDialogBox.left(0); //установить расположение окна слева
     this._myDialogBox.top(0); //установить расположение окна сверху
     this._myDialogBox.clear(); //удалить содержимое окна
     this._myDialogBox.close(); //закрыть окно (удалить содержимое и сделать невидимым)
}

Добавление кнопок в верхнюю панель
Виджет, управляющий кнопкой в верхней панели, должен наследоваться от GP.Widget.DirectButton.

GP.Module.Widget.myDirectButtonWidget = GP.Widget.DirectButton.extend{

}

Создание кнопки
После создания экземпляра класса GP.Widget.MyDirectButtonWidget будет выполняться функция _createWidget, в которой необходимо выполнить вызов функции _createWidget родителя:

GP.Widget.DirectButton.prototype._createWidget.call(this);

Далее необходимо создать функции, отвечающие за активацию и деактивацию кнопки, в которых нужно обязательно вызвать функцию родителя

_activateControl: function(){ //активация
    GP.Widget.DirectButton.prototype._activateControl.call(this);
    /*  активация действия кнопки  */
}
_disableControl: function(){ //деактивация
    GP.Widget.DirectButton.prototype._disableControl.call(this);
    /* деактивация действия кнопки */
}

Также обязательно описать следующие опции:

mainOptions:{
    buttonId: "",     //id кнопки
    title: "",        //заголовок кнопки
    image: "",        //картинка кнопки
    bindClick: true   //if false, то функция _activateControl 
                      //не будет автоматически выполняться при клике на кнопку.
},

Пример кнопки:

GP.Module.Widget.myDirectButtonWidget = GP.Widget.DirectButton.extend{
      mainOptions:{
      buttonId: "",     //id кнопки
      title: "",        //заголовок кнопки
      image: "",        //картинка кнопки
      bindClick: true   //if false, то функция _activateControl 
                        //не будет автоматически выполняться при клике на кнопку.
    },
   _createWidget: function(){
        GP.Widget.DirectButton.prototype._createWidget.call(this);
   },

   _activateControl: function(){ //активация
        GP.Widget.DirectButton.prototype._activateControl.call(this);
        /*активация действия кнопки  */
    },

    _disableControl: function(){ //деактивация
        GP.Widget.DirectButton.prototype._disableControl.call(this);
        /* деактивация действия кнопки */
    }   
}

Правая панель

Добавление вкладки в правую панель:

GP.widgets.tabs.addTab({
    name : "MyTab", //надпись, выводимая при наведении
    image : GP.imagesPath + "/icons/tab-icon.png", //иконка, отображаемая, когда вкладка неактивна
    imageWhite : GP.imagesPath + "/icons/tab-icon-white.png", //иконка, отображаемая, 
                                                              //когда вкладка активна
    divId : "my-tab-block" //id, присваиваемый элементу вкладки
});

После этого можно изменять внутренность вкладки, изменяя соответствующий DOM элемент.

События правой панели

Следующее событие срабатывает при развертывании правой панели

GP.widgets.tabs.on("tab:rightPanelShow", myFunction, context);

Следующее событие срабатывает при скрывании правой панели

GP.widgets.tabs.on("tab:rightPanelHide", myFunction, context);

Следующее событие срабатывает при изменении размера правой панели

GP.widgets.tabs.on("tab:resize");

Левая панель
Виджет, управляющий левой панелью, должен наследоваться от GP.Widget.LeftPanel.

GP.Module.Widget.myLeftPanel = GP.Widget.LeftPanel.extend{

}

Пример создания левой панели:

if(GP.widgets.leftPanel == undefined || !(GP.widgets.leftPanel instanceof GP.Widget.MyLeftPanel)){
    GP.widgets.leftPanel = new GP.Widget.MyLeftPanel({
        template:"myTemplate", //сюда можно передать название template, 
                           //который должен лежать в assets/templates и иметь расширешие tl.
        dustObject:myDustObject //параметр используется в построении template, более подробно
                        // в описании плагина, который дает такую возможность http://akdubya.github.io/dustjs/
    });
    GP.widgets.leftPanel.on(
                           "leftPanel:destroy", //при срабатывании события закрытия левой панели
                            this._widgetDestroy,//выполнить функцию this._widgetDestroy
                            this                //контекст выполнения функции
                          );
}
else
    GP.widgets.leftPanel.reload(      //если ранее левую панель занимал этот же виджет,
                                      //тогда перерисовать панель, используя параметры
                             "myTemplate",
                              dustObject
                            );

Создание левой панели
После создания экземпляра класса GP.Module.MyModule.Widget.MyLeftPanelWidget будет выполняться функция _createContent, которую мы в своем классе GP.Module.MyModule.Widget.MyLeftPanelWidget переопределяем для отрисовки нужной нам информации.

В классах, отвечающих за отрисовку левой панели можно определить функцию _onResize которая будет автоматически выполняться при изменении размеров левой панели.
функция _close — при закрытии левой панели,
reload — функция выполняется при открытии левой панели, если до этого левую панель занимал виджет — экземпляр этого же класса. При определении функции reload после выполнения всех действий необходимо выполнить следующие действия:

reload: function(template,dustObject){
    /****/
    GP.fire("leftPanel:reload",{leftPanel:this});
    this.options.template = template;
    dustRender(template,dustObject,this._dustRender,this);
}

Для простого отображения левой панели можно не создавать свой класс — виджет, а просто создать экземпляр класса GP.Widget.leftPanel и передать конструктору template и dustObject:

GP.widgets.leftPanel = new 
                          GP.Widget.leftPanel({template:"myTemplate",dustObject:dustObject},"#wrap");
GP.widgets.leftPanel.on("leftPanel:destroy",this._widgetDestroy,this);

События левой панели
Событие происходит при отображении левой панели, выполняемая функция принимает на вход 2 аргумента: переменную, содержащую левую панель и ширину панели.

GP.on(
    "leftPanel:show",
    function(leftPanel,width){},
    context
);

Событие происходит при закрытии левой панели, выполняемая функция принимает на вход переменную, содержащую левую панель

GP.widgets.leftPanel.on(
    "leftPanel:destroy",
    myFunction,
    context
);

Событие происходит при замене левой панели на другую, выполняемая функция принимает на вход переменную, содержащую левую панель

GP.on(
    "leftPanel:reload",
    myFunction,
    context
);

Карта

Примеры работы с картой:
Создание слоя из геометрии

var object = jQuery.parseJSON(geom); //geom - геометрия слоя в строковой переменной
this._layer = new M.GeoJSON(object); //создаем слой из геометрии
GP.mainMap.map.addLayer(this._layer); //добавляем слой на карту
GP.mainMap.setBBox(bbox.minX,bbox.minY,bbox.maxX,bbox.maxY,bbox.projection); //переходим к
                              // выбранному участку на карте, устанавливая карте bBox

Создание wms слоя

mapLayer = new M.TileLayer.WMS(
        requestUrl, //url запроса
        {                        //wms параметры слоя
           layers: typeName,     //typeName слоя
           styles: style,        //style слоя
           format: 'image/png',  //формат отдачи данных, по умолчанию image/jpeg
           transparent: true     //прозрачность
        }
     );
mapLayer.wmsParams.cql_filter = filterCQL.filterString(); //добавления CQL фильтров слою.

Создание wfs слоя

 mapLayer = new M.WFS(
    requestUrl,   //Url запроса
    typeName,    //typeName слоя
    styleUrl,    //путь к .sld файлу стиля
    undefined,  //формат отдачи данных, по умолчанию application/json
    wfsOptions  //wfs опции запроса
  );

Удаление слоя с карты
Для того, чтобы убрать слой с карты необходимо выполнить следующую функцию: GP.mainMap.map.removeLayer(layer), где layer – слой, который нужно убрать.

Основные события карты:

Cобытие «click» сработает при клике на карту, в переменную data придет объект, содержащий в себе:

latlng: объект, содержащий координаты (долгота и широта) точки.
layerPoint: координаты клика относительно экрана, начало координат в нижней левой точке
originalEvent: событие клик, отдаваемое браузером
target: контейнер, в котором находится карта
type: строковая переменная, содержащая "click"
GP.mainMap.map.on("click", function (data) {
    this.hideMap(this._curtainDragging.offset().left);
}, this);

Событие «dblclick» сработает при двойном клике на карту, в переменную data придет объект, содержащий в себе:

latlng: объект, содержащий координаты (долгота и широта) точки.
layerPoint: координаты клика относительно экрана, начало координат в нижней левой точке
originalEvent: событие клик, отдаваемое браузером
target: контейнер, в котором находится карта
type: строковая переменная, содержащая ""dblclick""
GP.mainMap.map.on("dblclick", function () {
    this.hideMap(this._curtainDragging.offset().left);
}, this);

Событие срабатывает после приближения/удаления карты

GP.mainMap.map.on("zoomend", function () {
    this.hideMap(this._curtainDragging.offset().left);
}, this);

Событие «move» срабатывает во время и после заканчивания передвижения карты

GP.mainMap.map.on("move", function () {
    this.hideMap(this._curtainDragging.offset().left);
}, this);

Событие «viewreset» срабатывает после перезагрузки карты, выполняемая функция принимает на вход один параметр, содержащий в себе boolean переменную hard (если true — перезагрузка со смещением карты)

GP.mainMap.map.on("viewreset", myFunction, context);

Событие «popupopen» срабатывает при открывании всплывающего окошка на карте, выполняемая функция принимает на вход один параметр — popup

GP.mainMap.map.on("popupopen", myFunction, context);

Событие «popupclose» срабатывает при закрывании всплывающего окошка на карте, выполняемая функция принимает на вход один параметр — popup

GP.mainMap.map.on("popupclose", myFunction, context);

Событие «changeCenter» срабатывает после изменения центра карты

GP.mainMap.map.on("changeCenter", function () {
    this.hideMap(this._curtainDragging.offset().left);
}, this);

Posted in mapSurfer, Статьи Tagged mapSurfer, Модули

Нажмите здесь, чтобы отменить ответ.

Для добавления комментариев пожалуйста, Войдите на сайт с паролем или Зарегистрируйтесь

Next →
  • Главная
  • Статьи
  • Документация
  • Продукты
Поддержка

Copyright © 2005-2025 Gradoservice™. All rights reserved