c80_map_floors 0.1.0.9 → 0.1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/lib/awesomplete.js +450 -0
  3. data/app/assets/javascripts/map_objects/area.js +12 -8
  4. data/app/assets/javascripts/map_objects/building.js +23 -6
  5. data/app/assets/javascripts/src/main.js +12 -2
  6. data/app/assets/javascripts/src/state_controller.js +50 -8
  7. data/app/assets/javascripts/svg_elements/admin_building_label.js +6 -6
  8. data/app/assets/javascripts/svg_elements/building_label.js +88 -60
  9. data/app/assets/javascripts/ui/tabs/tabs.js +55 -2
  10. data/app/assets/javascripts/view/building_info/building_info.js +85 -8
  11. data/app/assets/javascripts/view/building_info/mobj_info_parser.js +316 -12
  12. data/app/assets/javascripts/view/search_gui.js +295 -0
  13. data/app/assets/stylesheets/c80_map_floors.scss +3 -1
  14. data/app/assets/stylesheets/lib/awesomplete.scss +104 -0
  15. data/app/assets/stylesheets/lib_custom/awesomplete.scss +8 -0
  16. data/app/assets/stylesheets/map.scss +61 -16
  17. data/app/assets/stylesheets/ui/search_gui.scss +51 -0
  18. data/app/assets/stylesheets/ui/tabs_js.scss +25 -0
  19. data/app/assets/stylesheets/view/buttons/back_to_map_button.scss +1 -1
  20. data/app/assets/stylesheets/view/elems/building_info.scss +1 -1
  21. data/app/assets/stylesheets/view/elems/free_areas_label.scss +6 -1
  22. data/app/controllers/c80_map_floors/ajax_controller.rb +82 -0
  23. data/app/helpers/c80_map_floors/search_gui_helper.rb +19 -0
  24. data/app/models/c80_map_floors/area.rb +1 -1
  25. data/app/models/c80_map_floors/area_representator.rb +13 -22
  26. data/app/models/c80_map_floors/building_representator.rb +8 -1
  27. data/app/models/c80_map_floors/floor.rb +1 -1
  28. data/app/models/c80_map_floors/map_building.rb +2 -2
  29. data/app/models/c80_map_floors/map_json.rb +2 -1
  30. data/app/views/c80_map_floors/_map_row_index.html.erb +5 -0
  31. data/app/views/c80_map_floors/shared/map_row/_search_gui.html.erb +11 -0
  32. data/config/routes.rb +2 -0
  33. data/lib/c80_map_floors/version.rb +1 -1
  34. metadata +9 -2
@@ -2,32 +2,185 @@
2
2
 
3
3
  // в задачи этого кода входит преобразование JSON объектов в human-читаемый текст с характеристиками
4
4
 
5
- var MobjInfoParser = function () {
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
- /** Лабаем html текст из json-данных полигона Этажа/Здания/Площади
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
- result += _this._row('square', json);
25
- result += _this._row('square_free', json);
26
- result += _this._row('floor_height', json);
27
- result += _this._row('communications', json);
28
- result += _this._row('areas_count', json);
29
- result += _this._row('areas_free_count', json);
30
- result += _this._row('price_string', json);
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
+ }