c80_map_floors 0.1.0.9 → 0.1.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/lib/awesomplete.js +450 -0
- data/app/assets/javascripts/map_objects/area.js +12 -8
- data/app/assets/javascripts/map_objects/building.js +23 -6
- data/app/assets/javascripts/src/main.js +12 -2
- data/app/assets/javascripts/src/state_controller.js +50 -8
- data/app/assets/javascripts/svg_elements/admin_building_label.js +6 -6
- data/app/assets/javascripts/svg_elements/building_label.js +88 -60
- data/app/assets/javascripts/ui/tabs/tabs.js +55 -2
- data/app/assets/javascripts/view/building_info/building_info.js +85 -8
- data/app/assets/javascripts/view/building_info/mobj_info_parser.js +316 -12
- data/app/assets/javascripts/view/search_gui.js +295 -0
- data/app/assets/stylesheets/c80_map_floors.scss +3 -1
- data/app/assets/stylesheets/lib/awesomplete.scss +104 -0
- data/app/assets/stylesheets/lib_custom/awesomplete.scss +8 -0
- data/app/assets/stylesheets/map.scss +61 -16
- data/app/assets/stylesheets/ui/search_gui.scss +51 -0
- data/app/assets/stylesheets/ui/tabs_js.scss +25 -0
- data/app/assets/stylesheets/view/buttons/back_to_map_button.scss +1 -1
- data/app/assets/stylesheets/view/elems/building_info.scss +1 -1
- data/app/assets/stylesheets/view/elems/free_areas_label.scss +6 -1
- data/app/controllers/c80_map_floors/ajax_controller.rb +82 -0
- data/app/helpers/c80_map_floors/search_gui_helper.rb +19 -0
- data/app/models/c80_map_floors/area.rb +1 -1
- data/app/models/c80_map_floors/area_representator.rb +13 -22
- data/app/models/c80_map_floors/building_representator.rb +8 -1
- data/app/models/c80_map_floors/floor.rb +1 -1
- data/app/models/c80_map_floors/map_building.rb +2 -2
- data/app/models/c80_map_floors/map_json.rb +2 -1
- data/app/views/c80_map_floors/_map_row_index.html.erb +5 -0
- data/app/views/c80_map_floors/shared/map_row/_search_gui.html.erb +11 -0
- data/config/routes.rb +2 -0
- data/lib/c80_map_floors/version.rb +1 -1
- metadata +9 -2
@@ -2,32 +2,185 @@
|
|
2
2
|
|
3
3
|
// в задачи этого кода входит преобразование JSON объектов в human-читаемый текст с характеристиками
|
4
4
|
|
5
|
-
|
5
|
+
function MobjInfoParser() {
|
6
6
|
|
7
7
|
var _this = this;
|
8
8
|
|
9
9
|
// с помощью этого хелпера можно понять, например, что square это "общая площадь" (типа locales/ru.yml)
|
10
10
|
var _i18n = null;
|
11
11
|
|
12
|
-
|
12
|
+
// todo-clear22:: необходимо сбрасывать это значение после того, как сбросили поиск
|
13
|
+
// текущий результат поиска - какие полигоны площадей соответствуют поиску и содержат искомые магазины
|
14
|
+
var _sresults_areas = null;
|
15
|
+
|
16
|
+
// используется в _row_area_with_shop() и в _row_area_shop()
|
17
|
+
var _row_area_shop_pattern = "<li><a href='{HREF}' title='{TITLE}' target='_blank'>{TITLE}</a> ({AREA_TITLE}), {PHONE}</li>";
|
18
|
+
|
19
|
+
// используется в _row_area_data()
|
20
|
+
var _row_area_pattern = "<li><a href='{HREF}' title='{AREA_TITLE}' target='_blank'>{AREA_TITLE}</a></li>";
|
21
|
+
|
22
|
+
// режимы отображения данных - user mode. Их два: "режим арендатора" и "режим обычного пользователя"
|
23
|
+
var _umode = 'umode_simple_user'; // umode_arendator, umode_simple_user
|
24
|
+
|
25
|
+
//--[ public ]------------------------------------------------------------------------------------------------------
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Лабаем html текст из json-данных полигона Этажа/Здания/Площади.
|
13
29
|
*
|
14
30
|
* @param json
|
15
31
|
*/
|
16
32
|
this.makeHtmlText = function (json) {
|
17
|
-
console.log("<makeHtmlText> Лабаем html текст из json данных полигона.");
|
33
|
+
console.log("<MobjInfoParser.makeHtmlText> Лабаем html текст из json данных полигона.");
|
18
34
|
|
19
35
|
var result = "";
|
20
36
|
|
21
37
|
//#-> предполагается, что json в поряде и данные целостны (т.е. уровнем выше была проверка json на корректность)
|
22
38
|
switch (json["class_name"]) {
|
23
39
|
case "C80MapFloors::Floor":
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
40
|
+
|
41
|
+
/* [aa34qq] json:
|
42
|
+
{
|
43
|
+
<...свойства картинки этажа, чисто класс C80MapFloors::Floor..>
|
44
|
+
|
45
|
+
"areas": [ // полигоны площадей этой картинки этажа
|
46
|
+
{ "id": 5,
|
47
|
+
<...C80MapFloors::Floor..>
|
48
|
+
|
49
|
+
"data": { // данные привязанной к плоигону Площади
|
50
|
+
"id": 9,
|
51
|
+
"title": "Дом-1",
|
52
|
+
"square": null,
|
53
|
+
"desc": "",
|
54
|
+
"price_string": null,
|
55
|
+
"communications": null,
|
56
|
+
"is_free": false,
|
57
|
+
"shop": { // данные Магазина, который занимает эту Площадь
|
58
|
+
"id": 130,
|
59
|
+
"title": "ИП Кибардин",
|
60
|
+
"desc": "",
|
61
|
+
"tel": "(910) 514 08 68",
|
62
|
+
"site": "",
|
63
|
+
"url": "/shops/ip-kibardin.html"
|
64
|
+
}
|
65
|
+
}
|
66
|
+
},
|
67
|
+
],
|
68
|
+
|
69
|
+
"data": // данные Этажа, привязанного к картинке этажа
|
70
|
+
"id": 40,
|
71
|
+
"ord": 1,
|
72
|
+
"title": "1 этаж",
|
73
|
+
"square": 0.0,
|
74
|
+
"square_free": 0.0,
|
75
|
+
"areas_count": 2,
|
76
|
+
"areas_free_count": 2,
|
77
|
+
"price_string": "от до руб./кв.м",
|
78
|
+
"floor_height": null,
|
79
|
+
"communications": ""
|
80
|
+
}
|
81
|
+
}*/
|
82
|
+
|
83
|
+
/* [aa34qq] или сокращённо
|
84
|
+
json:
|
85
|
+
{
|
86
|
+
"areas": [ // полигоны площадей этой картинки этажа
|
87
|
+
{ "id": 5,
|
88
|
+
|
89
|
+
"data": { // данные привязанной к плоигону Площади
|
90
|
+
"id": 9,
|
91
|
+
"title": "Дом-1",
|
92
|
+
"is_free": false,
|
93
|
+
"shop": { // данные Магазина, который занимает эту Площадь
|
94
|
+
"id": 130,
|
95
|
+
"title": "ИП Кибардин",
|
96
|
+
}
|
97
|
+
}
|
98
|
+
},
|
99
|
+
],
|
100
|
+
|
101
|
+
"data": // данные Этажа, привязанного к картинке этажа
|
102
|
+
"id": 40,
|
103
|
+
"title": "1 этаж",
|
104
|
+
}
|
105
|
+
}
|
106
|
+
*/
|
107
|
+
|
108
|
+
// при наличии результатов поиска
|
109
|
+
if (_sresults_areas != null) {
|
110
|
+
|
111
|
+
//<editor-fold desc="// посмотрим, нету ли в json полигонов площадей, чьи айдишники перечислены в _sresults_areas">
|
112
|
+
|
113
|
+
// подготовительно: соберём айдишники полигонов площадей в отдельный массив
|
114
|
+
var arr_map_areas_ids = $.map(json['areas'], function (val, index) {
|
115
|
+
return val['id'];
|
116
|
+
});
|
117
|
+
|
118
|
+
console.log('<MobjInfoParser.makeHtmlText> В массиве [' + arr_map_areas_ids.join(', ') +'] ищем элементы: [' + _sresults_areas.join(', ') + '].');
|
119
|
+
|
120
|
+
//<editor-fold desc="// 1. переберём айдишники из _sresults_areas и поищем их в arr_json_areas_ids.">
|
121
|
+
/* результат (индексы объектов для отображения из массива json['areas']) соберём в массиве [**] */
|
122
|
+
|
123
|
+
var i, len = _sresults_areas.length;
|
124
|
+
var i_search_index; // индекс айдишника `искомой пользователем полигона площади` в массиве json['areas'] полигонов площадей (просматриваемого этажа)
|
125
|
+
var isaid; // iterated searched area's id
|
126
|
+
var arr_search_indexes = []; // [**] - индексы объектов полигонов площадей просматриваемого этажа (для отображения в инфо панели) из массива json['areas']
|
127
|
+
|
128
|
+
for (i=0; i<len; i++) {
|
129
|
+
isaid = _sresults_areas[i];
|
130
|
+
i_search_index = arr_map_areas_ids.indexOf(isaid);
|
131
|
+
// если в map-массиве полигонов площадей просматриваемого этажа обнаружен айдишник `искомой пользователем площади`
|
132
|
+
if (i_search_index != -1) {
|
133
|
+
console.log('<MobjInfoParser.makeHtmlText> В массиве [' + arr_map_areas_ids.join(', ') +'] обнаружен ' + isaid + '.');
|
134
|
+
// запомним каждый i_search_index (затем я намереваюсь обработать их в отдельном цикле: найти соответствующие данные полигонов площадей (просматриваемого этажа) в массиве json['areas'], и собрать html-сроки для каждого объекта с данными в один список
|
135
|
+
arr_search_indexes.push(i_search_index);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
//</editor-fold>
|
139
|
+
|
140
|
+
//<editor-fold desc="// 2. Теперь переберём найденные индексы, собирая по ходу html-строки для отображения">
|
141
|
+
|
142
|
+
len = arr_search_indexes.length;
|
143
|
+
// если на этаже есть площади, удовлетворяющие поиску
|
144
|
+
if (len > 0) {
|
145
|
+
var i_json_area;
|
146
|
+
// переберём индексы
|
147
|
+
for (i=0; i<len; i++) {
|
148
|
+
|
149
|
+
// зафиксируем индекс и соотв. данные
|
150
|
+
i_search_index = arr_search_indexes[i];
|
151
|
+
i_json_area = json['areas'][i_search_index];
|
152
|
+
|
153
|
+
//#-> если всё в порядке (есть данные полигона площади по этому индексу) - лабаем из них html-строку
|
154
|
+
if (i_json_area != undefined) {
|
155
|
+
result += _this._row_area_with_shop(i_json_area);
|
156
|
+
}
|
157
|
+
|
158
|
+
// иначе - сообщим об ошибке в лог
|
159
|
+
else {
|
160
|
+
console.log('<MobjInfoParser.makeHtmlText> [ERROR] Вроде индекс есть ('+i_search_index+'), а данных по этому адресу не нашлось...');
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
// если же на этаже нету результатов, удовлетворяющих поиску
|
166
|
+
else {
|
167
|
+
// "просто отобразим данные об этаже согласно режиму"
|
168
|
+
result = _this._makeHtmlText_Umode_Floor(json);
|
169
|
+
}
|
170
|
+
|
171
|
+
|
172
|
+
//</editor-fold>
|
173
|
+
|
174
|
+
//</editor-fold>
|
175
|
+
|
176
|
+
}
|
177
|
+
|
178
|
+
// если это не поиск
|
179
|
+
else {
|
180
|
+
// "просто отобразим данные об этаже согласно режиму"
|
181
|
+
result = _this._makeHtmlText_Umode_Floor(json);
|
182
|
+
}
|
183
|
+
|
31
184
|
break;
|
32
185
|
}
|
33
186
|
|
@@ -36,6 +189,96 @@ var MobjInfoParser = function () {
|
|
36
189
|
|
37
190
|
};
|
38
191
|
|
192
|
+
/**
|
193
|
+
* Задаём текущие результаты поиска (вызывается из BuildingInfo).
|
194
|
+
* @param sresult_areas
|
195
|
+
*/
|
196
|
+
this.setSearchResultAreas = function (sresult_areas) {
|
197
|
+
_sresults_areas = sresult_areas;
|
198
|
+
};
|
199
|
+
|
200
|
+
/** Извне задаём текущий режим просмотра данных.
|
201
|
+
*
|
202
|
+
* @param umode
|
203
|
+
*/
|
204
|
+
this.setUmode = function (umode) {
|
205
|
+
_umode = umode;
|
206
|
+
};
|
207
|
+
|
208
|
+
//--[ private ]-----------------------------------------------------------------------------------------------------
|
209
|
+
|
210
|
+
/**
|
211
|
+
* На основе режима пользователя карты (Арендатор или ОбычныйПокупатель) выдать html-строку с `просто данными` об Этаже.
|
212
|
+
*
|
213
|
+
* @param json_floor - данные полигона этажа от C80MapFloors::Floor.my_as_json (пример можно лицезреть в [aa34qq]
|
214
|
+
* @returns {string} - html-строка, которая завернётся в <ul>...</ul>
|
215
|
+
* @private
|
216
|
+
*/
|
217
|
+
this._makeHtmlText_Umode_Floor = function (json_floor) {
|
218
|
+
|
219
|
+
var result = '';
|
220
|
+
|
221
|
+
// todo-umode:: внедрить и использовать режим пользователя карты (Арендатор или ОбычныйПокупатель) и соответствующим образом отрисовать `просто данные` об Этаже
|
222
|
+
|
223
|
+
if (_umode == 'umode_arendator') {
|
224
|
+
//<editor-fold desc=" // отобразим данные Этажа: метраж, кол-во площадей, коммуникации, цена за кв.м (режим Арендатора)">
|
225
|
+
result += _this._row('square', json_floor);
|
226
|
+
result += _this._row('square_free', json_floor);
|
227
|
+
//result += _this._row('floor_height', json);
|
228
|
+
result += _this._row('communications', json_floor);
|
229
|
+
result += _this._row('areas_count', json_floor);
|
230
|
+
result += _this._row('areas_free_count', json_floor);
|
231
|
+
result += _this._row('price_string', json_floor);
|
232
|
+
//</editor-fold>
|
233
|
+
}
|
234
|
+
|
235
|
+
else if (_umode == 'umode_simple_user') {
|
236
|
+
|
237
|
+
// отобразим всех арендаторов на этом этаже
|
238
|
+
|
239
|
+
var areas = json_floor['areas'];
|
240
|
+
if (areas != null) {
|
241
|
+
|
242
|
+
var len = areas.length;
|
243
|
+
var i, iar, iard; // i_area, i_area_data
|
244
|
+
|
245
|
+
for (i=0; i<len; i++) {
|
246
|
+
|
247
|
+
// фиксируем данные полигона площади
|
248
|
+
iar = areas[i];
|
249
|
+
// фиксируем данные Площади, которая привязана к полигону
|
250
|
+
iard = iar['data'];
|
251
|
+
|
252
|
+
// если имеются данные Площади - работаем дальше (т.е. на выходе из if полюбому будет добавлена строка)
|
253
|
+
if (iard != null) {
|
254
|
+
|
255
|
+
// если имеются данные о Магазине (т.е. если есть Магазин, занимающий эту Площадь)
|
256
|
+
if (iard['shop'] != null) {
|
257
|
+
// соорудим строку, которая описывает этот Магазин
|
258
|
+
result += _this._row_area_shop(iar);
|
259
|
+
}
|
260
|
+
|
261
|
+
// если же нет данных о Магазине (т.е. Площадь свободна)
|
262
|
+
else {
|
263
|
+
// соорудим строку, которая описывает эту Площадь
|
264
|
+
result += _this._row_area_data(iard);
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
return result;
|
273
|
+
};
|
274
|
+
|
275
|
+
/**
|
276
|
+
* Соорудить html-строку для списка свойств Этажа.
|
277
|
+
* @param key
|
278
|
+
* @param json
|
279
|
+
* @returns {string}
|
280
|
+
* @private
|
281
|
+
*/
|
39
282
|
this._row = function (key, json) {
|
40
283
|
var s = '';
|
41
284
|
if (key == 'price_string') {
|
@@ -46,6 +289,68 @@ var MobjInfoParser = function () {
|
|
46
289
|
return s;
|
47
290
|
};
|
48
291
|
|
292
|
+
/**
|
293
|
+
* Соорудить html-строку, описывающую только Площадь (согласно паттерну _row_area_pattern).
|
294
|
+
* Т.е. даже если есть Магазин, занимающий эту Площадь - он не будет браться в рассчёт.
|
295
|
+
*
|
296
|
+
* Нет защиты от ошибок (это значит, что этот метод должен использоваться в if..else конструкции,
|
297
|
+
* которая проверяет наличие необходимых данных).
|
298
|
+
*
|
299
|
+
* @param area_data_json - это узел 'data' объекта, описывающего полигон площади.
|
300
|
+
* @private
|
301
|
+
*/
|
302
|
+
this._row_area_data = function (area_data_json) {
|
303
|
+
var res = _row_area_pattern;
|
304
|
+
res = res.split('{HREF}').join('#'); // todo:: какой должен быть href у свободной Площади?
|
305
|
+
res = res.split('{AREA_TITLE}').join(area_data_json['title']);
|
306
|
+
return res;
|
307
|
+
};
|
308
|
+
|
309
|
+
/**
|
310
|
+
* Этот служебный метод является контейнером кода, который желательно использовать только в makeHtmlText.
|
311
|
+
* Выдать человекочитаемую html-строку <li>...</li>, которая описывает искомый Магазин.
|
312
|
+
* Т.к. ВСЕГДА в таком случае ожидается наличие магазина - то в случае ошибки результат будет содержать
|
313
|
+
* сообщение об ошибке.
|
314
|
+
*
|
315
|
+
* @param area_json - данные об полигоне площади, сформированные методом C80MapFloors::Area.my_as_json4
|
316
|
+
* @returns {string} - <li><a href='' title='' target='_blank'>Магазин такой-то</a>(площадь такая-то), телефоны<li>
|
317
|
+
* @private
|
318
|
+
*
|
319
|
+
*/
|
320
|
+
this._row_area_with_shop = function (area_json) {
|
321
|
+
var res = '<li>[ERROR] Нет данных о магазине в полигоне площади с id='+area_json['id']+'</li>';
|
322
|
+
if (area_json['data'] != undefined && area_json['data']['shop'] != undefined) {
|
323
|
+
res = _this._row_area_shop(area_json);
|
324
|
+
}
|
325
|
+
return res;
|
326
|
+
};
|
327
|
+
|
328
|
+
/**
|
329
|
+
* Соорудить строку, описывающую Магазин (согласно паттерну _row_area_shop_pattern).
|
330
|
+
*
|
331
|
+
* На вход подаётся json полигона площади.
|
332
|
+
* Нет защиты от ошибок (это значит, что этот метод должен использоваться в if..else конструкции,
|
333
|
+
* которая проверяет наличие необходимых данных)..
|
334
|
+
*
|
335
|
+
* Метод (контейнер кода) родился из метода _row_area_with_shop, когда начали внедрять режим _umode
|
336
|
+
* и расширять функционал _makeHtmlText_Umode_Floor.
|
337
|
+
*
|
338
|
+
* @param area_json
|
339
|
+
* @returns {string}
|
340
|
+
* @private
|
341
|
+
*/
|
342
|
+
this._row_area_shop = function (area_json) {
|
343
|
+
var shop = area_json['data']['shop'];
|
344
|
+
var res = _row_area_shop_pattern;
|
345
|
+
res = res.split('{TITLE}').join(shop['title']);
|
346
|
+
res = res.split('{HREF}').join(shop['url']);
|
347
|
+
res = res.split('{PHONE}').join(shop['tel']);
|
348
|
+
res = res.split('{AREA_TITLE}').join(area_json['data']['title']);
|
349
|
+
return res;
|
350
|
+
};
|
351
|
+
|
352
|
+
//--[ init ]--------------------------------------------------------------------------------------------------------
|
353
|
+
|
49
354
|
var _fInit = function () {
|
50
355
|
|
51
356
|
// кастуем locales-помощника
|
@@ -54,5 +359,4 @@ var MobjInfoParser = function () {
|
|
54
359
|
};
|
55
360
|
|
56
361
|
_fInit();
|
57
|
-
}
|
58
|
-
|
362
|
+
}
|
@@ -0,0 +1,295 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
4
|
+
//
|
5
|
+
// На экране присутствует div#search_gui, в котором содержится форма поиска (поле ввода и кнопка).
|
6
|
+
// SearchGUI обслуживает этот див, а именно:
|
7
|
+
// - позволяет управлять видимостью,
|
8
|
+
// - позволяет двигать его РОДИТЕЛЯ так, чтобы он не загораживался ничем при смене состояния приложения,
|
9
|
+
// - отправляет поисковые запросы на сервер и принимает ответы,
|
10
|
+
// - парсит ответы,
|
11
|
+
// - и содержит публичный метод, подсвечивающий результаты поиска (полигоны) на карте и табы в инфо-панели
|
12
|
+
//
|
13
|
+
//----------------------------------------------------------------------------------------------------------------------
|
14
|
+
|
15
|
+
function SearchGUI(link_to_map) {
|
16
|
+
|
17
|
+
var _this = this;
|
18
|
+
var _map = null; // ссылка на класс карты
|
19
|
+
var _$container = null; // родительский див (добавлен только для того, чтобы можно было двигать форму при смене состояния приложения)
|
20
|
+
var _$search_gui = null; // ссылка на обслуживаемый div с формой
|
21
|
+
var _$input = null; // поле ввода (сюда юзер вводит искомый текст)
|
22
|
+
var _$submit = null; // кнопка "найти"
|
23
|
+
var _current_search_results = null; // текущие результаты поиска
|
24
|
+
var _counter = 0; // счётчик отправленных запросов
|
25
|
+
var _$reset_btn = null; // ссылка/кнопка "сбросить результаты поиска"
|
26
|
+
|
27
|
+
//--[ public ]------------------------------------------------------------------------------------------------------
|
28
|
+
|
29
|
+
/**
|
30
|
+
* На основе текущих результатов поиска и
|
31
|
+
* в зависимости от текущего состояния приложения
|
32
|
+
* метод подсвечивает полигоны на карте и табы в инфо-панели
|
33
|
+
*
|
34
|
+
*/
|
35
|
+
this.handleSearchResults = function () {
|
36
|
+
if (_current_search_results != null) {
|
37
|
+
console.log('<SearchGUI.handleSearchResults> Подсветим результаты поиска.');
|
38
|
+
|
39
|
+
//<editor-fold desc="// подсветим полигоны на карте...">
|
40
|
+
var s = _map.svg;
|
41
|
+
var c = s.children();
|
42
|
+
var l = c.length;
|
43
|
+
var i, ig, igobj, imbid, imaid; // <i_map_building_id>, <i_map_area_id>
|
44
|
+
var imb; // <i_map_buidling>
|
45
|
+
var iindex; // индекс (айдишника полигона здания) в массиве (полигонов зданий, удовлетворающих поиску)
|
46
|
+
var ibscount; // <i_buildings_shops_count>
|
47
|
+
|
48
|
+
for (i=0; i<l; i++) {
|
49
|
+
ig = s[0].children[i]; // именно [0]
|
50
|
+
//console.log(ig['obj']); // => Polygon
|
51
|
+
if (ig != undefined) { // такое тоже бывает
|
52
|
+
if (ig['obj'] != undefined) {
|
53
|
+
igobj = ig['obj'];
|
54
|
+
//console.log('[breakpoint]');
|
55
|
+
|
56
|
+
// добираемся до класса Building.js
|
57
|
+
if (ig['obj']['building'] != undefined) {
|
58
|
+
//console.log("Полигон здания: " + ig['obj']['building'].id); => Полигон здания: 10
|
59
|
+
|
60
|
+
imb = ig['obj']['building'];
|
61
|
+
imbid = imb.id;
|
62
|
+
iindex = _current_search_results['buildings'].indexOf(imbid);
|
63
|
+
|
64
|
+
//#-> если в результатах поиска присутствует перебираемый map_building_id - полигону добавим класс 'found'
|
65
|
+
if (iindex != -1) {
|
66
|
+
console.log('<SearchGUI.handleSearchResults> addClass "found" на полигон здания imdid=' + imbid);
|
67
|
+
$(ig).find('polygon').addClass('found');
|
68
|
+
|
69
|
+
// и зажгём лейбл с подсказкой
|
70
|
+
ibscount = _current_search_results['buildings_shops_count'][iindex];
|
71
|
+
imb.greenCircleShow(ibscount);
|
72
|
+
}
|
73
|
+
|
74
|
+
//#-> иначе - удалим (возможный) класс `found` и скроем (возможный) лейбл с подсказкой
|
75
|
+
else {
|
76
|
+
$(ig).find('polygon').removeClass('found');
|
77
|
+
imb.greenCircleHide();
|
78
|
+
}
|
79
|
+
|
80
|
+
}
|
81
|
+
|
82
|
+
// добираемся до класса Area.js
|
83
|
+
else if (ig['obj']['area'] != undefined) {
|
84
|
+
imaid = ig['obj']['area'].id;
|
85
|
+
|
86
|
+
// если в результатах поиска присутствует перебираемый map_area_id - полигону добавим класс 'found_area'
|
87
|
+
if (_current_search_results['areas'].indexOf(imaid) != -1) {
|
88
|
+
console.log('<SearchGUI.handleSearchResults> addClass "found_area" на полигон площади imaid=' + imaid);
|
89
|
+
$(ig).find('polygon').addClass('found_area');
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
}
|
96
|
+
//</editor-fold>
|
97
|
+
|
98
|
+
// подсветим вкладки этажей в инфопанели
|
99
|
+
_map.building_info_klass.searchResultsShow(_current_search_results);
|
100
|
+
}
|
101
|
+
};
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Вернуть родительский div-контейнер в начальную (исходную, `нормальную`) позицию.
|
105
|
+
*/
|
106
|
+
this.position_init = function () {
|
107
|
+
// если еще ниразу никуда не сдвигали с начальной позиции
|
108
|
+
if (_$container.data('init_position_top') == undefined) {
|
109
|
+
// запомним начальную позицию
|
110
|
+
_$container.data('init_position_top', _$container.css("top"));
|
111
|
+
_$container.data('init_position_left', _$container.css("left"));
|
112
|
+
}
|
113
|
+
_$container.css("top", _$container.data('init_position_top'));
|
114
|
+
_$container.css("left", _$container.data('init_position_left'));
|
115
|
+
};
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Установить div-контейнер чуть левее исходной позиции так, чтобы инфо-панель не загораживала форму поиска.
|
119
|
+
* Используется при переходе в режимы, где видна инфо-панель: внутри здания, например. Или внутри этажа.
|
120
|
+
*/
|
121
|
+
this.position_inside = function () {
|
122
|
+
//console.log('<position_inside> [breakpoint].');
|
123
|
+
_$container.css("left", -200);
|
124
|
+
_$container.css("top", _$container.data('init_position_top'));
|
125
|
+
};
|
126
|
+
|
127
|
+
/**
|
128
|
+
* Спрятать контейнер (задвинуть его за пределы экрана).
|
129
|
+
* Например, когда переходим в режим редактирования.
|
130
|
+
*/
|
131
|
+
this.position_hide = function () {
|
132
|
+
_$container.css("top", -200);
|
133
|
+
};
|
134
|
+
|
135
|
+
//--[ private ]-----------------------------------------------------------------------------------------------------
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Отправляем запрос с текстом для поиска на сервер.
|
139
|
+
*
|
140
|
+
* @param stext - название категории, которой должны соответствовать арендаторы
|
141
|
+
* @private
|
142
|
+
*/
|
143
|
+
this._sendSearchRequest = function (stext) {
|
144
|
+
console.log('<_sendSearchRequest> Отправляем поисковый запрос на сервер: stext = ' + stext);
|
145
|
+
|
146
|
+
// покажем прелоадер
|
147
|
+
_map.save_preloader_klass.show();
|
148
|
+
|
149
|
+
// todo-search: реализовать проверку "слишком короткий текст, не отправляем" тут (перенести проверку из _submitOnClick)
|
150
|
+
// todo-search: реализовать проверку "такая строка только что отправлялась и текущие результаты по ней содержатся в _current_search_results)
|
151
|
+
|
152
|
+
// увеличим счётчик запросов
|
153
|
+
_counter = _counter + 1;
|
154
|
+
|
155
|
+
// отправим запрос на сервер
|
156
|
+
$.ajax({
|
157
|
+
url: '/ajax/find_shops',
|
158
|
+
type: 'POST',
|
159
|
+
data: {
|
160
|
+
stext: stext,
|
161
|
+
counter: _counter
|
162
|
+
},
|
163
|
+
dataType: 'json'
|
164
|
+
}).done(_this._sendSearchRequestDone);
|
165
|
+
|
166
|
+
};
|
167
|
+
|
168
|
+
/**
|
169
|
+
* Получили [какой-то] ответ от сервера на запрос о поиске.
|
170
|
+
*
|
171
|
+
* @param data - результат поиска (внутри метода в комментах пример ответа)
|
172
|
+
* @param result
|
173
|
+
* @private
|
174
|
+
*/
|
175
|
+
this._sendSearchRequestDone = function (data, result) {
|
176
|
+
console.log('<_sendSearchRequestDone> Получили [какой-то] ответ от сервера на запрос о поиске:');
|
177
|
+
|
178
|
+
//console.log(data);
|
179
|
+
// {
|
180
|
+
// buildings: [7,10],
|
181
|
+
// floors: [2,6,40],
|
182
|
+
// areas: [3,5,8,6]
|
183
|
+
//}
|
184
|
+
|
185
|
+
// один из вариантов (unused)
|
186
|
+
//{
|
187
|
+
// buildings: [
|
188
|
+
// { id: 7,
|
189
|
+
// floors: [
|
190
|
+
// { id: 2,
|
191
|
+
// areas: [3]
|
192
|
+
// }
|
193
|
+
// ]
|
194
|
+
// },
|
195
|
+
// {
|
196
|
+
// id: 10,
|
197
|
+
// floors: [
|
198
|
+
// { id: 6,
|
199
|
+
// areas: [5,8]
|
200
|
+
// },
|
201
|
+
// { id: 48,
|
202
|
+
// areas: [6]
|
203
|
+
// }
|
204
|
+
// ]
|
205
|
+
// }
|
206
|
+
// ]
|
207
|
+
//}
|
208
|
+
|
209
|
+
_current_search_results = data;
|
210
|
+
|
211
|
+
// скроем прелоадер
|
212
|
+
_map.save_preloader_klass.hide();
|
213
|
+
|
214
|
+
// покажем кнопку "сбросить результаты поиска"
|
215
|
+
_$reset_btn.css('display', 'block');
|
216
|
+
|
217
|
+
// обработаем результаты поиска
|
218
|
+
_this.handleSearchResults();
|
219
|
+
|
220
|
+
};
|
221
|
+
|
222
|
+
/**
|
223
|
+
* Нажали на кнопку "найти". -> Отправляем запрос на сервер.
|
224
|
+
*
|
225
|
+
* @param e
|
226
|
+
* @private
|
227
|
+
*/
|
228
|
+
var _submitOnClick = function (e) {
|
229
|
+
e.preventDefault();
|
230
|
+
var search_text = _$input.val();
|
231
|
+
if (search_text.length > 2) {
|
232
|
+
console.log('<_submitOnClick> Нажали на кнопку "найти", отправляем текст "' + search_text + '" на поиск.');
|
233
|
+
_this._sendSearchRequest(search_text);
|
234
|
+
} else {
|
235
|
+
console.log('<_submitOnClick> Нажали на кнопку "найти", но искать нечего...');
|
236
|
+
}
|
237
|
+
};
|
238
|
+
|
239
|
+
/**
|
240
|
+
* Нажали на кнопку "сбросить результаты поиска".
|
241
|
+
*
|
242
|
+
* @param e
|
243
|
+
* @private
|
244
|
+
*/
|
245
|
+
var _resetOnClick = function (e) {
|
246
|
+
e.preventDefault();
|
247
|
+
|
248
|
+
// "обнуляем" результаты поиска (пустые массивы разойдутся в подклассы и там все переменные почистятся)
|
249
|
+
// NOTE:: если в AjaxController.find_shops поменяется вид объекта с результатами поиска - то его надо будет поменять и тут
|
250
|
+
_current_search_results['buildings'] = [];
|
251
|
+
_current_search_results['buildings_shops_count'] = [];
|
252
|
+
_current_search_results['floors'] = [];
|
253
|
+
_current_search_results['floors_shops_count'] = [];
|
254
|
+
_current_search_results['areas'] = [];
|
255
|
+
|
256
|
+
// очищаем поле ввода
|
257
|
+
_$input.val('');
|
258
|
+
|
259
|
+
// прячем саму кнопку "сбросить результаты поиска"
|
260
|
+
_$reset_btn.css('display', 'none');
|
261
|
+
|
262
|
+
// обработаем пустые результаты поиска
|
263
|
+
_this.handleSearchResults();
|
264
|
+
|
265
|
+
};
|
266
|
+
|
267
|
+
//--[ init ]--------------------------------------------------------------------------------------------------------
|
268
|
+
|
269
|
+
var _init = function (link_to_map) {
|
270
|
+
console.log('<SearchGUI.init>');
|
271
|
+
|
272
|
+
_map = link_to_map;
|
273
|
+
|
274
|
+
// найдём обслуживаемый div
|
275
|
+
_$search_gui = $('div#search_gui');
|
276
|
+
if (_$search_gui.length > 0) { // работать будем только тогда, когда элемент имеется
|
277
|
+
|
278
|
+
// зафиксируем элементы
|
279
|
+
_$container = $('div.container#search_container'); // зафиксируем родителя
|
280
|
+
_$input = _$search_gui.find('input.form-control');
|
281
|
+
_$submit = _$search_gui.find('button.btn');
|
282
|
+
_$reset_btn = _$container.find('a.reset');
|
283
|
+
|
284
|
+
// при клике по кнопке 'submit' - отправим текст на сервер, заблокируем форму поиска, сгенерим событие
|
285
|
+
_$submit.on('click', _submitOnClick);
|
286
|
+
|
287
|
+
// при клике по кнопке 'reset' - сбросим текущие результаты поиска
|
288
|
+
_$reset_btn.on('click', _resetOnClick);
|
289
|
+
}
|
290
|
+
|
291
|
+
};
|
292
|
+
|
293
|
+
_init(link_to_map);
|
294
|
+
|
295
|
+
}
|