c80_map_floors 0.1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +67 -0
- data/Rakefile +1 -0
- data/app/admin/c80_map_floors/floors.rb +57 -0
- data/app/admin/c80_map_floors/map_buildings.rb +49 -0
- data/app/admin/c80_map_floors/settings.rb +32 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_area_link.js +91 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_building_link.js +91 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_cancel_create.js +21 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_cancel_remove.js +23 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_complete_create.js +22 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_edit.js +96 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_new.js +46 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_remove.js +23 -0
- data/app/assets/javascripts/buttons/admin_buttons/button_save.js +111 -0
- data/app/assets/javascripts/buttons/button_back_to_map.js +84 -0
- data/app/assets/javascripts/buttons/zoom_buttons.js +78 -0
- data/app/assets/javascripts/c80_map_floors.js.coffee +23 -0
- data/app/assets/javascripts/events/app_event.js +15 -0
- data/app/assets/javascripts/map_objects/area.js +251 -0
- data/app/assets/javascripts/map_objects/building.js +294 -0
- data/app/assets/javascripts/map_objects/dot.js +14 -0
- data/app/assets/javascripts/map_objects/floor.js +10 -0
- data/app/assets/javascripts/src/main.js +1421 -0
- data/app/assets/javascripts/src/state_controller.js +322 -0
- data/app/assets/javascripts/src/utils/map_utils.js +23 -0
- data/app/assets/javascripts/src/utils/opacity_buttons_utils.js +15 -0
- data/app/assets/javascripts/src/utils/utils.js +140 -0
- data/app/assets/javascripts/svg_elements/area_label.js +25 -0
- data/app/assets/javascripts/svg_elements/building_label.js +65 -0
- data/app/assets/javascripts/svg_elements/helper.js +36 -0
- data/app/assets/javascripts/svg_elements/polygon.js +194 -0
- data/app/assets/javascripts/view/save_preloader.js +30 -0
- data/app/assets/stylesheets/c80_map_floors.scss +4 -0
- data/app/assets/stylesheets/map.scss +1464 -0
- data/app/assets/stylesheets/view/buttons/area_order_button.scss +16 -0
- data/app/assets/stylesheets/view/buttons/back_to_map_button.scss +28 -0
- data/app/assets/stylesheets/view/elems/building_info.scss +54 -0
- data/app/assets/stylesheets/view/elems/free_areas_label.scss +116 -0
- data/app/assets/stylesheets/view/elems/map_objects/map_object_image_bg.scss +10 -0
- data/app/assets/stylesheets/view/modal_window.scss +13 -0
- data/app/assets/stylesheets/view/save_preloader.scss +206 -0
- data/app/controllers/c80_map_floors/ajax_controller.rb +65 -0
- data/app/controllers/c80_map_floors/application_controller.rb +6 -0
- data/app/controllers/c80_map_floors/map_ajax_controller.rb +70 -0
- data/app/helpers/c80_map_floors/application_helper.rb +28 -0
- data/app/models/c80_map_floors/area.rb +20 -0
- data/app/models/c80_map_floors/area_representator.rb +75 -0
- data/app/models/c80_map_floors/base_map_object.rb +41 -0
- data/app/models/c80_map_floors/building_representator.rb +72 -0
- data/app/models/c80_map_floors/floor.rb +37 -0
- data/app/models/c80_map_floors/map_building.rb +45 -0
- data/app/models/c80_map_floors/map_json.rb +35 -0
- data/app/models/c80_map_floors/setting.rb +32 -0
- data/app/uploaders/c80_map_floors/building_image_uploader.rb +31 -0
- data/app/uploaders/c80_map_floors/floor_image_uploader.rb +33 -0
- data/app/uploaders/c80_map_floors/map_image_uploader.rb +31 -0
- data/app/views/c80_map_floors/_map_row_index.html.erb +40 -0
- data/app/views/c80_map_floors/ajax/fetch_unlinked_areas.js.erb +7 -0
- data/app/views/c80_map_floors/ajax/fetch_unlinked_buildings.js.erb +7 -0
- data/app/views/c80_map_floors/ajax/map_edit_buttons.js.erb +36 -0
- data/app/views/c80_map_floors/ajax/shared/_map_creating.html.erb +6 -0
- data/app/views/c80_map_floors/ajax/shared/_map_editing.html.erb +4 -0
- data/app/views/c80_map_floors/ajax/shared/_map_removing.html.erb +5 -0
- data/app/views/c80_map_floors/ajax/shared/_select_list_unlinked_areas.html.erb +6 -0
- data/app/views/c80_map_floors/ajax/shared/_select_list_unlinked_buildings.html.erb +10 -0
- data/app/views/c80_map_floors/shared/_modal_window.html.erb +28 -0
- data/app/views/c80_map_floors/shared/_save_preloader.html.erb +3 -0
- data/app/views/c80_map_floors/shared/map_row/_area_order_button.html.erb +7 -0
- data/app/views/c80_map_floors/shared/map_row/_building_info.html.erb +17 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/c80_map_floors.gemspec +28 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20161015190000_create_c80_map_floors_settings.rb +8 -0
- data/db/migrate/20161015190001_create_c80_map_floors_map_buildings.rb +10 -0
- data/db/migrate/20161015190002_create_c80_map_floors_areas.rb +12 -0
- data/db/migrate/20161015190003_add_building_representator_to_c80_map_floors_buildings.rb +6 -0
- data/db/migrate/20161015190004_create_c80_map_floors_floors.rb +16 -0
- data/db/migrate/20161019111010_add_title_to_c80_map_floors_buildings.rb +5 -0
- data/db/migrate/20161020184040_add_coords_img_to_c80_map_floors_buildings.rb +5 -0
- data/db/seeds/c80_map_floors_01_fill_map_settings.rb +6 -0
- data/db/seeds/c80_map_floors_02_create_test_area.rb +7 -0
- data/lib/c80_map_floors.rb +8 -0
- data/lib/c80_map_floors/engine.rb +23 -0
- data/lib/c80_map_floors/version.rb +3 -0
- metadata +218 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
function Dot() {
|
3
|
+
|
4
|
+
var _this = this;
|
5
|
+
var _options = null;
|
6
|
+
var _polygon = null;
|
7
|
+
|
8
|
+
_this.init = function (options,pself) {
|
9
|
+
console.log('<Dot.init>');
|
10
|
+
_options = options;
|
11
|
+
_polygon = Polygon.createFromSaved(options, false, pself);
|
12
|
+
}
|
13
|
+
|
14
|
+
}
|
@@ -0,0 +1,1421 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
var IS_ADMIN = false;
|
4
|
+
var map_on_index_page = null;
|
5
|
+
|
6
|
+
var InitMap = function (params) {
|
7
|
+
|
8
|
+
var dnd_enable = true;
|
9
|
+
if (params != undefined && params["dnd_enable"] != undefined) {
|
10
|
+
dnd_enable = params["dnd_enable"];
|
11
|
+
}
|
12
|
+
|
13
|
+
// - to delete start -----------------------------------------------------------------------------------------------------------------------
|
14
|
+
var scale = 0.599999;
|
15
|
+
|
16
|
+
var window_height = $(window).height() - 200;
|
17
|
+
if (window_height < 400) window_height = 400;
|
18
|
+
|
19
|
+
var window_width = $(window).width();
|
20
|
+
var image_width = MAP_WIDTH * scale;
|
21
|
+
var image_height = MAP_HEIGHT * scale;
|
22
|
+
|
23
|
+
var x = (window_width - image_width)/2;
|
24
|
+
var y = (window_height - image_height)/2;
|
25
|
+
// - to delete end -----------------------------------------------------------------------------------------------------------------------
|
26
|
+
|
27
|
+
map_on_index_page = $('#map_wrapper').beMap(
|
28
|
+
{
|
29
|
+
source:LOCS_HASH,
|
30
|
+
scale: scale,
|
31
|
+
x: x,
|
32
|
+
y: y,
|
33
|
+
mapwidth: MAP_WIDTH,
|
34
|
+
mapheight: MAP_HEIGHT,
|
35
|
+
height: window_height,
|
36
|
+
dnd_enable: dnd_enable
|
37
|
+
}
|
38
|
+
);
|
39
|
+
|
40
|
+
};
|
41
|
+
|
42
|
+
var clog = function () {
|
43
|
+
console.log(arguments[0]);
|
44
|
+
};
|
45
|
+
|
46
|
+
(function () {
|
47
|
+
|
48
|
+
var Map = function () {
|
49
|
+
var self = this;
|
50
|
+
|
51
|
+
self.debug = true;
|
52
|
+
self.o = {
|
53
|
+
source: 'locations.json', // data
|
54
|
+
height: 400, // viewbox height, pixels
|
55
|
+
mapwidth: 100, // actual image size, in pixels
|
56
|
+
mapheight: 100,
|
57
|
+
mapfill: true,
|
58
|
+
zoom: true,
|
59
|
+
zoombuttons: true,
|
60
|
+
maxscale: 1,
|
61
|
+
fitscale: 0.51,
|
62
|
+
skin: '', // css class name
|
63
|
+
scale: 1,
|
64
|
+
x: 0,
|
65
|
+
y: 0,
|
66
|
+
dnd_enable: true
|
67
|
+
};
|
68
|
+
self.svg = null;
|
69
|
+
self.svg_overlay = null;
|
70
|
+
self.container = null;
|
71
|
+
self.mode = 'viewing';
|
72
|
+
self.prev_mode = null;
|
73
|
+
self.setMode = null;
|
74
|
+
self.selected_area = null; // ссылка на полигон из #svg_overlay
|
75
|
+
self.drawing_poligon = null;
|
76
|
+
self.events = [];
|
77
|
+
self.edit_type = null;
|
78
|
+
self.remove_button_klass = null;
|
79
|
+
self.new_button_klass = null;
|
80
|
+
self.edit_button_klass = null;
|
81
|
+
self.complete_creating_button_klass = null;
|
82
|
+
self.back_to_map_button_klass = null;
|
83
|
+
self.current_building = null;
|
84
|
+
self.current_area = null;
|
85
|
+
self.is_draw = false;
|
86
|
+
self.save_button_klass = null;
|
87
|
+
self.area_link_button_klass = null;
|
88
|
+
self.drawn_areas = []; // если имеются нарисованные но несохранённые Площади - они хранятся тут
|
89
|
+
self.drawn_buildings = []; // если имеются нарисованные но несохранённые Здания - они хранятся тут
|
90
|
+
self.save_preloader_klass = null;
|
91
|
+
self.last_clicked_g = null; // начали просматривать area\building (запустили сессию), и здесь храним ссылку на последний кликнутый полигон из svg_overlay в течение сессии
|
92
|
+
self.dnd_enable = null; // если да, то можно карту dnd мышкой
|
93
|
+
|
94
|
+
// во время анимации каждый шаг рассчитывается мгновенный scale
|
95
|
+
self.scale_during_animation = null;
|
96
|
+
|
97
|
+
// true, если:
|
98
|
+
//- юзер еще не кликал по кнопкам zoom
|
99
|
+
//- юзер еще не делал drag-n-drop
|
100
|
+
//- юзер ещё не вошёл ни в здание ни в площадь
|
101
|
+
// Т.Е., другими словами, true до момента, пока пользователь не начал взаимодействовать с картой
|
102
|
+
self.mark_virgin = true;
|
103
|
+
|
104
|
+
// здесь сохранятся параметры для метода moveTo
|
105
|
+
// чтобы вернуть карту в исходное состояние после нажатия кнопки "назад на карту"
|
106
|
+
self.initial_map_position = null;
|
107
|
+
|
108
|
+
self.init = function (el, params) {
|
109
|
+
// extend options
|
110
|
+
self.o = $.extend(self.o, params);
|
111
|
+
|
112
|
+
self.x = self.o.x;
|
113
|
+
self.y = self.o.y;
|
114
|
+
self.scale = self.o.scale; /* NOTE:: инициализация: начальные значения */
|
115
|
+
|
116
|
+
self.el = el.addClass('melem mloading').addClass(self.o.skin).height(self.o.height);
|
117
|
+
|
118
|
+
// Disable modules when landmark mode is active
|
119
|
+
/*if (self.o.landmark) {
|
120
|
+
self.o.sidebar = false;
|
121
|
+
self.o.zoombuttons = false;
|
122
|
+
self.o.deeplinking = false;
|
123
|
+
}*/
|
124
|
+
|
125
|
+
if (typeof self.o.source === 'string') {
|
126
|
+
// Loading .json file with AJAX
|
127
|
+
$.getJSON(self.o.source, function (data) { // Success
|
128
|
+
initProcessData(data);
|
129
|
+
self.el.removeClass('mloading');
|
130
|
+
//setTimeout(invalidateZoom,1000);
|
131
|
+
|
132
|
+
}).fail(function () { // Failure: couldn't load JSON file, or it is invalid.
|
133
|
+
console.error('Couldn\'t load map data. (Make sure you are running the script through a server and not just opening the html file with your browser)');
|
134
|
+
self.el.removeClass('mloading').addClass('merror');
|
135
|
+
alert('Data file missing or invalid!');
|
136
|
+
});
|
137
|
+
}
|
138
|
+
else {
|
139
|
+
// Inline json object
|
140
|
+
initProcessData(self.o.source);
|
141
|
+
self.el.removeClass('mloading');
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
return self;
|
146
|
+
|
147
|
+
|
148
|
+
};
|
149
|
+
|
150
|
+
var initProcessData = function (data) {
|
151
|
+
|
152
|
+
self.data = data;
|
153
|
+
|
154
|
+
//var nrlevels = 0;
|
155
|
+
//var shownLevel;
|
156
|
+
|
157
|
+
self.container = $('.mcontainer'); //$('<div></div>').addClass('mcontainer').appendTo(self.el);
|
158
|
+
self.map = self.container.find('.mmap'); //$('<div></div>').addClass('mmap').appendTo(self.container);
|
159
|
+
if (self.o.zoom) self.map.addClass('mapplic-zoomable');
|
160
|
+
self.map_layers = self.map.find('.layers');
|
161
|
+
self.map_overlay_layers = self.map.find('.overlay_layers');
|
162
|
+
|
163
|
+
self.svg = $("#svg");
|
164
|
+
self.svg_overlay = $('#svg_overlay');
|
165
|
+
//$('<svg></svg>')
|
166
|
+
//.attr('xmlns','http://www.w3.org/2000/svg')
|
167
|
+
//.attr('version','1.2')
|
168
|
+
//.attr('baseProfile','tiny')
|
169
|
+
//.attr('id','svg')
|
170
|
+
//.appendTo(self.map);
|
171
|
+
|
172
|
+
self.levelselect = $('<select></select>').addClass('mlevels_select');
|
173
|
+
|
174
|
+
self.container.css('width', '100%'); // if (!self.o.sidebar)
|
175
|
+
|
176
|
+
self.contentWidth = parseInt(data.mapwidth);
|
177
|
+
self.contentHeight = parseInt(data.mapheight);
|
178
|
+
|
179
|
+
self.hw_ratio = data.mapheight / data.mapwidth;
|
180
|
+
|
181
|
+
self.map.css({
|
182
|
+
'width': data.mapwidth,
|
183
|
+
'height': data.mapheight
|
184
|
+
});
|
185
|
+
|
186
|
+
/* NOTE:: важная строка: определяет css и js поведение кое-где [qwwqq]:
|
187
|
+
2016-10-19
|
188
|
+
|
189
|
+
1. Всё начинается в JSON - в самом начале разработки проектировался JSON:
|
190
|
+
2. там для root объекта указан был
|
191
|
+
руками
|
192
|
+
набор характеристик. Среди которых был и object_type[переименован в class_name].
|
193
|
+
3. на тот момент object_type был равен строке "main_map".
|
194
|
+
4. Затем эта строка (в процессе разработки) стала использоваться, как
|
195
|
+
имя css класса, и были накиданы стили для оформления.
|
196
|
+
5. Затем, уже css класс был использован внутри StateController.js, который
|
197
|
+
работает с состоянием приложения и видимостью детей '.main_map'.
|
198
|
+
|
199
|
+
По хорошему - надо убрать из JSON этот параметр,
|
200
|
+
а здесь рукми напишем строку 'main_map', что и сделаем.
|
201
|
+
*/
|
202
|
+
// Create new map layer
|
203
|
+
var layer = $('<div></div>')
|
204
|
+
.addClass('mlayer')
|
205
|
+
//.addClass(data["class_name"])/* [qwwqq] */
|
206
|
+
.addClass("main_map")/* [qwwqq] */
|
207
|
+
.appendTo(self.map_layers); // .hide()
|
208
|
+
$('<img>').attr('src', data["img"]).addClass('mmap-image').appendTo(layer);
|
209
|
+
|
210
|
+
// Zoom buttons
|
211
|
+
if (self.o.zoombuttons) {
|
212
|
+
self.zoombuttons = new ZoomButtons();
|
213
|
+
self.zoombuttons.init({height: self.o.height}, self);
|
214
|
+
//if (!self.o.clearbutton) self.zoombuttons.el.css('bottom', '0');
|
215
|
+
}
|
216
|
+
|
217
|
+
var sc = new StateController();
|
218
|
+
sc.init(self);
|
219
|
+
self.setMode = sc.setMode;
|
220
|
+
|
221
|
+
// Admin buttons
|
222
|
+
$.ajax({
|
223
|
+
url: '/ajax/map_edit_buttons',
|
224
|
+
type: 'POST',
|
225
|
+
dataType: 'script',
|
226
|
+
data: {
|
227
|
+
div_css_selector: '#container_buttons .mzoom_buttons'
|
228
|
+
}
|
229
|
+
}).done(function () {
|
230
|
+
clog('<ajax.done>');
|
231
|
+
|
232
|
+
self.edit_button_klass = new EditButton();
|
233
|
+
self.edit_button_klass.init('.mapplic-edit-button', self);
|
234
|
+
|
235
|
+
var e = new NewButton();
|
236
|
+
e.init('.mapplic-new-button', self);
|
237
|
+
self.new_button_klass = e;
|
238
|
+
|
239
|
+
e = new RemoveButton();
|
240
|
+
e.init('.mapplic-remove-button', self);
|
241
|
+
self.remove_button_klass = e;
|
242
|
+
|
243
|
+
e = new CancelRemoveButton();
|
244
|
+
e.init('#cancelRemoving', self);
|
245
|
+
|
246
|
+
e = new CancelCreatingButton();
|
247
|
+
e.init("#cancelCreating", self);
|
248
|
+
|
249
|
+
e = new CompleteCreatingButton();
|
250
|
+
e.init("#completeCreating", self);
|
251
|
+
|
252
|
+
self.save_button_klass = new SaveChangesButton();
|
253
|
+
self.save_button_klass.init('.mapplic-save-button', self);
|
254
|
+
|
255
|
+
// при клике на эту кнопку произойдет показ модального окна
|
256
|
+
self.area_link_button_klass = new AreaLinkButton();
|
257
|
+
self.area_link_button_klass.init('.mapplic-area-link-button', self);
|
258
|
+
|
259
|
+
// при клике на эту кнопку произойдет показ модального окна, в котором можно будет указать здание, соответствующее полигону
|
260
|
+
self.building_link_button_klass = new BuildingLinkButton();
|
261
|
+
self.building_link_button_klass.init('.mapplic-building-link-button', self);
|
262
|
+
|
263
|
+
$('[data-toggle="tooltip"]').tooltip();
|
264
|
+
|
265
|
+
});
|
266
|
+
|
267
|
+
// Controls
|
268
|
+
initAddControls();
|
269
|
+
|
270
|
+
self.draw_childs(data["buildings"]);
|
271
|
+
|
272
|
+
self.ivalidateViewArea();
|
273
|
+
|
274
|
+
// Browser resize
|
275
|
+
$(window).resize(function () {
|
276
|
+
|
277
|
+
// Mobile
|
278
|
+
//if ($(window).width() < 668) {
|
279
|
+
// self.container.height($(window).height() - 66);
|
280
|
+
//}
|
281
|
+
//else self.container.height('100%');
|
282
|
+
|
283
|
+
// Контейнер с картой должен слушать изменения габаритов окна и подгоняться по высоте
|
284
|
+
var window_height = $(window).height() - 200;
|
285
|
+
if (window_height < 400) window_height = 400;
|
286
|
+
self.el.height(window_height + "px");
|
287
|
+
|
288
|
+
// 20161003: заодно после редизайна необходимо позиционировать текстовый блок с адресом
|
289
|
+
var hh = _$address_p.outerHeight(true);
|
290
|
+
_$address_p.css('margin-top',(window_height - hh - 200)+"px");
|
291
|
+
|
292
|
+
// ------------------------------------------------------------------------------------------------------------------------
|
293
|
+
|
294
|
+
// если пользователь еще не взаимодействовал с картой или вне здания\площади
|
295
|
+
// вписываем картинку карты в главный прямоугольник карты
|
296
|
+
// т.е. меняем масштаб
|
297
|
+
if (self.mark_virgin) {
|
298
|
+
// рассчитаем масштаб, при котором можно вписать главный прямоугольник карты в прямоугольник рабочей области
|
299
|
+
var scaleX = self.calcScale(self.o.mapwidth*0.05, self.o.mapwidth *.95, self.X10, self.X20);
|
300
|
+
var scaleY = self.calcScale(self.o.mapheight*0.05, self.o.mapheight *.95, self.Y10, self.Y20);
|
301
|
+
var scale = (scaleX < scaleY) ? scaleX : scaleY;
|
302
|
+
self.scale = scale; /* NOTE:: вызывается во время window resize */
|
303
|
+
}
|
304
|
+
|
305
|
+
// совмещаем точку на экране, в которую надо центрировать карту,
|
306
|
+
// с центром карты (или с центром здания\площади, в котором находится юзер),
|
307
|
+
// с учётом рассчитанного масштаба
|
308
|
+
|
309
|
+
// если пользователь еще не взаимодействовал с картой или вне здания\площади,
|
310
|
+
// то фокусируемся на центр карты,
|
311
|
+
// иначе - фокусируемся на центр здания\площади, в котором находится пользователь и
|
312
|
+
// фокус сдвигаем, с учётом того, что сбоку открыта панель с информацией о здании
|
313
|
+
|
314
|
+
// NOTE-25::хардкод
|
315
|
+
// логические координаты - геометрический центр картинки
|
316
|
+
var cx = self.o.mapwidth/2;
|
317
|
+
var cy = self.o.mapheight/2;
|
318
|
+
var mark_do_moving = false;
|
319
|
+
|
320
|
+
if (self.current_building) {
|
321
|
+
cx = self.current_building.cx();
|
322
|
+
cy = self.current_building.cy();
|
323
|
+
mark_do_moving = true;
|
324
|
+
} else if (self.current_area) {
|
325
|
+
cx = self.current_area.cx();
|
326
|
+
cy = self.current_area.cy();
|
327
|
+
mark_do_moving = true;
|
328
|
+
} else if (self.mark_virgin) {
|
329
|
+
mark_do_moving = true;
|
330
|
+
}
|
331
|
+
|
332
|
+
if (mark_do_moving) {
|
333
|
+
self.x = self.normalizeX({
|
334
|
+
x: self.CX - self.scale * cx - self.container.offset().left,
|
335
|
+
scale: self.scale
|
336
|
+
});
|
337
|
+
self.y = self.normalizeY({
|
338
|
+
y: self.CY - self.scale * cy - self.container.offset().top,
|
339
|
+
scale: self.scale
|
340
|
+
});
|
341
|
+
clog("<$(window).resize> call moveTo");
|
342
|
+
self.moveTo(self.x, self.y, self.scale, 100);
|
343
|
+
|
344
|
+
// если пользователь ещё не взаимодействовал с картой (т.е. она только загрузилась и готова к использованию)
|
345
|
+
// запомним позицию, чтобы при нажатии на кнопку "назад на карту" происходил возврат с исходному
|
346
|
+
// состоянию
|
347
|
+
if (self.mark_virgin) {
|
348
|
+
self.initial_map_position = {
|
349
|
+
x: self.x,
|
350
|
+
y: self.y,
|
351
|
+
scale: self.scale
|
352
|
+
}
|
353
|
+
}
|
354
|
+
|
355
|
+
}
|
356
|
+
|
357
|
+
// ------------------------------------------------------------------------------------------------------------------------
|
358
|
+
|
359
|
+
|
360
|
+
self.ivalidateViewArea();
|
361
|
+
|
362
|
+
}).resize();
|
363
|
+
|
364
|
+
};
|
365
|
+
|
366
|
+
var initAddControls = function () {
|
367
|
+
var map = self.map,
|
368
|
+
mapbody = $('.mmap-image', self.map);
|
369
|
+
|
370
|
+
document.ondragstart = function () {
|
371
|
+
return false;
|
372
|
+
}; // IE drag fix
|
373
|
+
|
374
|
+
function onSvgMousedown(e) {
|
375
|
+
clog("<onSvgMousedown> self.mode = " + self.mode);
|
376
|
+
|
377
|
+
if (self.mode === 'editing' || self.mode === "edit_building" || self.mode === 'edit_area') {
|
378
|
+
if (e.target.parentNode.tagName === 'g') {
|
379
|
+
clog("<onSvgMousedown> e = ");
|
380
|
+
//clog(e.pageX);
|
381
|
+
//clog("<mouseDown> e.target.parentNode.tagName = " + e.target.parentNode.tagName);
|
382
|
+
//clog(e.target);
|
383
|
+
//info.unload();
|
384
|
+
|
385
|
+
// запомним ссылку на "выбранную" область
|
386
|
+
self.selected_area = e.target.parentNode.obj;
|
387
|
+
|
388
|
+
//app.deselectAll();
|
389
|
+
|
390
|
+
// поменяем внешний вид полигона - добавим класс .selected
|
391
|
+
self.selected_area.select();
|
392
|
+
|
393
|
+
// запомним начальные координаты кликаы
|
394
|
+
self.selected_area.delta = {
|
395
|
+
'x': e.pageX,
|
396
|
+
'y': e.pageY
|
397
|
+
};
|
398
|
+
|
399
|
+
// если взаимодействуем с вершиной
|
400
|
+
if (utils.hasClass(e.target, 'helper')) {
|
401
|
+
var helper = e.target;
|
402
|
+
//clog("<mouseDown> helper.action = ");
|
403
|
+
//clog(helper.action);
|
404
|
+
self.edit_type = helper.action; // pointMove
|
405
|
+
|
406
|
+
if (helper.n >= 0) { // if typeof selected_area == polygon
|
407
|
+
self.selected_area.selected_point = helper.n;
|
408
|
+
}
|
409
|
+
|
410
|
+
self.addEvent(self.el[0], 'mousemove', self.onEdit)
|
411
|
+
//self.addEvent(self.el[0], 'mousemove', self.selected_area.onEdit)
|
412
|
+
.addEvent(self.el[0], 'mouseup', self.onEditStop);
|
413
|
+
}
|
414
|
+
|
415
|
+
else if (e.target.tagName === 'rect' || e.target.tagName === 'circle' || e.target.tagName === 'polygon') {
|
416
|
+
self.edit_type = 'move';
|
417
|
+
self.addEvent(self.el[0], 'mousemove', self.onEdit)
|
418
|
+
.addEvent(self.el[0], 'mouseup', self.onEditStop);
|
419
|
+
}
|
420
|
+
} else {
|
421
|
+
//app.deselectAll();
|
422
|
+
//info.unload();
|
423
|
+
}
|
424
|
+
}
|
425
|
+
}
|
426
|
+
|
427
|
+
self.svg.on('mousedown', onSvgMousedown);
|
428
|
+
//self.el[0].addEventListener('mousedown', onSvgMousedown, false);
|
429
|
+
|
430
|
+
|
431
|
+
// Drag & drop
|
432
|
+
function onDragNdrop(event) {
|
433
|
+
//clog("<mousedown> edit_type = " + self.edit_type);
|
434
|
+
clog("<mousedown> mode = " + self.mode);
|
435
|
+
//clog(event);
|
436
|
+
|
437
|
+
// если в данный момент не редактируем фигуру (т.е. не двигаем вершину фигуры)
|
438
|
+
if (self.edit_type == null) {
|
439
|
+
self.dragging = false;
|
440
|
+
map.stop();
|
441
|
+
|
442
|
+
map.data('mouseX', event.pageX);
|
443
|
+
map.data('mouseY', event.pageY);
|
444
|
+
map.data('lastX', self.x);
|
445
|
+
map.data('lastY', self.y);
|
446
|
+
map.data('startX', self.x);
|
447
|
+
map.data('startY', self.y);
|
448
|
+
|
449
|
+
map.addClass('mdragging');
|
450
|
+
|
451
|
+
self.map.on('mousemove', function (event) {
|
452
|
+
self.dragging = true;
|
453
|
+
|
454
|
+
if (self.dnd_enable) {
|
455
|
+
var x = event.pageX - map.data('mouseX') + self.x;
|
456
|
+
var y = event.pageY - map.data('mouseY') + self.y;
|
457
|
+
|
458
|
+
x = self.normalizeX({
|
459
|
+
x:x,
|
460
|
+
scale: self.scale
|
461
|
+
});
|
462
|
+
y = self.normalizeY({
|
463
|
+
y:y,
|
464
|
+
scale: self.scale
|
465
|
+
});
|
466
|
+
|
467
|
+
//clog("<Map.mousemove> x = " + x + "; y = " + y);
|
468
|
+
//clog("<Map.mousemove> Call moveTo.");
|
469
|
+
self.moveTo(x, y); /* NOTE:: вызывается во время dnd */
|
470
|
+
map.data('lastX', x);
|
471
|
+
map.data('lastY', y);
|
472
|
+
}
|
473
|
+
});
|
474
|
+
|
475
|
+
$(document).on('mouseup', function (event) {
|
476
|
+
//clog("<mouseup> dragging = " + self.dragging + ", mode = " + self.mode + "; is_draw = " + self.is_draw + "; scale = " + self.scale);
|
477
|
+
//clog("<mouseup> event = ");
|
478
|
+
//clog(event);
|
479
|
+
//clog("<mouseup> event.target = ");
|
480
|
+
//clog($(event.target).parent()[0].obj);
|
481
|
+
|
482
|
+
//clog("<mouseup> [qq] screen: " + event.pageX + ", " + event.pageY +
|
483
|
+
//"; logic: " + self.rightX(event.pageX) + ", " + self.rightY(event.pageY));
|
484
|
+
|
485
|
+
clog("<mouseup> self.mode = " + self.mode);
|
486
|
+
|
487
|
+
// исключаем случайный dnd дрожащей рукой
|
488
|
+
var dx = map.data('startX') - map.data('lastX');
|
489
|
+
var dy = map.data('startY') - map.data('lastY');
|
490
|
+
var delta = Math.sqrt(dx*dx + dy*dy);
|
491
|
+
var is_real_dragging = delta > 10;
|
492
|
+
|
493
|
+
// если это в самом деле был drag\n\drop
|
494
|
+
if (self.dragging && is_real_dragging) {
|
495
|
+
|
496
|
+
self.x = map.data('lastX');
|
497
|
+
self.y = map.data('lastY');
|
498
|
+
}
|
499
|
+
|
500
|
+
// иначе - пытаемся выяснить, в каком режиме находимся
|
501
|
+
else {
|
502
|
+
|
503
|
+
var p;
|
504
|
+
|
505
|
+
/* если находимся в режиме просмотра всей карты - входим в здание */
|
506
|
+
if (self.mode == 'viewing') {
|
507
|
+
//clog($(event.target).parent()[0].obj.building);
|
508
|
+
|
509
|
+
// добираемся до объекта класса Здание, который обслуживает полигон
|
510
|
+
p = $(event.target).parent()[0];
|
511
|
+
if (p.obj && p.obj.building) {
|
512
|
+
var building = p.obj.building;
|
513
|
+
clog("<mouseup> Входим в здание.");
|
514
|
+
building.enter();
|
515
|
+
}
|
516
|
+
|
517
|
+
}
|
518
|
+
|
519
|
+
/* если находимся в режиме рисования - рисуем */
|
520
|
+
else if (self.mode == 'creating') {
|
521
|
+
|
522
|
+
// и если ещё пока не начали рисовать (т.е. если это первый клик)
|
523
|
+
if (!self.is_draw) {
|
524
|
+
|
525
|
+
var xx = self.rightX(event.pageX);
|
526
|
+
var yy = self.rightY(event.pageY);
|
527
|
+
//clog("<mouseup> " + xx + "; " + yy);
|
528
|
+
|
529
|
+
self.drawing_poligon = new Polygon(xx, yy, false, self);
|
530
|
+
|
531
|
+
//self.addEvent(self.el[0], 'mousemove', self.drawing_poligon.onDraw)
|
532
|
+
self.addEvent(self.el[0], 'mousemove', function (e) {
|
533
|
+
var _n_f = self.drawing_poligon;
|
534
|
+
var right_angle = !!e.shiftKey; //e.shiftKey ? true : false;
|
535
|
+
|
536
|
+
_n_f.dynamicDraw(self.rightX(e.pageX), self.rightY(e.pageY), right_angle);
|
537
|
+
})
|
538
|
+
//.addEvent(self.drawing_poligon.helpers[0].helper, 'click', self.drawing_poligon.onDrawStop)
|
539
|
+
//.addEvent(self.el[0], 'click', self.drawing_poligon.onDrawAddPoint);
|
540
|
+
.addEvent(self.el[0], 'click', function (e) {
|
541
|
+
|
542
|
+
// если кликнули в первую точку фигуры - заканчиваем рисование
|
543
|
+
var $et = $(e.target);
|
544
|
+
var $h = $(self.drawing_poligon.helpers[0].helper);
|
545
|
+
if ($et.attr('x') == $h.attr('x') && $et.attr('y') == $h.attr('y')) {
|
546
|
+
//self.drawing_poligon.onDrawStop();
|
547
|
+
self.onDrawStop();
|
548
|
+
return;
|
549
|
+
}
|
550
|
+
|
551
|
+
var x = self.rightX(e.pageX),
|
552
|
+
y = self.rightY(e.pageY),
|
553
|
+
_n_f = self.drawing_poligon;
|
554
|
+
|
555
|
+
if (e.shiftKey) {
|
556
|
+
var right_coords = _n_f.right_angle(x, y);
|
557
|
+
x = right_coords.x;
|
558
|
+
y = right_coords.y;
|
559
|
+
}
|
560
|
+
_n_f.addPoint(x, y);
|
561
|
+
})
|
562
|
+
.addEvent(document, 'keydown', self.onDrawStop);
|
563
|
+
}
|
564
|
+
}
|
565
|
+
|
566
|
+
/* если находимся в режиме просмотра здания - входим в площадь */
|
567
|
+
/* если находится в режиме просмотра площади - переключаемся на другую площадь */
|
568
|
+
else if (self.mode == 'view_building' || self.mode == 'view_area') {
|
569
|
+
|
570
|
+
//console.log($(event.target).parent());
|
571
|
+
// => g, который живёт в #svg_overlay, или, другими словами,
|
572
|
+
// тот g, по которому кликнули последний раз,
|
573
|
+
// просматривая либо здание, либо площадь
|
574
|
+
var $viewing_g_from_svg_overlay = $(event.target).parent();
|
575
|
+
|
576
|
+
// добираемся до объекта класса Area, который обслуживает полигон
|
577
|
+
p = $viewing_g_from_svg_overlay[0];
|
578
|
+
//clog($(event.target).parent()[0].obj.area_hash);
|
579
|
+
|
580
|
+
if (p.obj && p.obj.area) {
|
581
|
+
|
582
|
+
// запомним последний кликнутый полигон
|
583
|
+
self.last_clicked_g = $viewing_g_from_svg_overlay;
|
584
|
+
|
585
|
+
var area = p.obj.area;
|
586
|
+
clog("<mouseup> Входим в площадь. self.last_clicked_g = ");
|
587
|
+
clog(self.last_clicked_g);
|
588
|
+
area.enter();
|
589
|
+
}
|
590
|
+
|
591
|
+
}
|
592
|
+
}
|
593
|
+
|
594
|
+
self.map.off('mousemove');
|
595
|
+
$(document).off('mouseup');
|
596
|
+
|
597
|
+
map.removeClass('mdragging');
|
598
|
+
});
|
599
|
+
}
|
600
|
+
}
|
601
|
+
|
602
|
+
self.svg.on('mousedown', onDragNdrop);
|
603
|
+
self.svg_overlay.on('mousedown', onDragNdrop);
|
604
|
+
|
605
|
+
self.el[0].addEventListener('mousemove', function (e) {
|
606
|
+
//coords_info.innerHTML = 'x: ' + rightX(e.pageX) + ', ' + 'y: ' + rightY(e.pageY);
|
607
|
+
}, false);
|
608
|
+
|
609
|
+
self.el[0].addEventListener('mouseleave', function () {
|
610
|
+
//coords_info.innerHTML = '';
|
611
|
+
}, false);
|
612
|
+
|
613
|
+
/* Disable selection */
|
614
|
+
//self.el[0].addEventListener('mousedown', function(e) { e.preventDefault(); }, false);
|
615
|
+
|
616
|
+
/* Disable image dragging */
|
617
|
+
self.el[0].addEventListener('dragstart', function (e) {
|
618
|
+
e.preventDefault();
|
619
|
+
}, false);
|
620
|
+
|
621
|
+
self.back_to_map_button_klass = new BackToMapButton();
|
622
|
+
self.back_to_map_button_klass.init("#ui", self);
|
623
|
+
|
624
|
+
self.save_preloader_klass = new SavePreloader();
|
625
|
+
self.save_preloader_klass.init();
|
626
|
+
|
627
|
+
};
|
628
|
+
|
629
|
+
// какой должен быть минимальный масштаб, чтобы вписать отрезок [min,max] в отрезок [p1,p2]
|
630
|
+
self.calcScale = function (min, max, p1, p2) {
|
631
|
+
//clog("<calcScale> [" + min + "," + max + '] to [' + p1 + "," + p2 + "]");
|
632
|
+
return (p2 - p1) / (max - min);
|
633
|
+
};
|
634
|
+
|
635
|
+
self.calcCoord = function (scale, pageC, logicC) {
|
636
|
+
return pageC - scale * logicC;
|
637
|
+
};
|
638
|
+
|
639
|
+
/* --- ivalidateViewArea BEGIN --------------------------------------------------------------------------------- */
|
640
|
+
|
641
|
+
var _$m = $("#map_wrapper");
|
642
|
+
var _$b = $('.container');//$('footer .container');
|
643
|
+
var $building_info = $('.building_info'); // "layouts/shared/map_row/building_info"
|
644
|
+
var $area_order_button = $('.area_order_button');
|
645
|
+
var $container_buttons = $('#container_buttons');
|
646
|
+
var _is_debug_drawn = true;
|
647
|
+
var _$address_p = $('#paddress'); // 20161003: после редизайна надо дополнительно позиционировать блок с адресом
|
648
|
+
|
649
|
+
self.ivalidateViewArea = function () {
|
650
|
+
//clog('<init> _$b.offset().left = ' + _$b.offset().left);
|
651
|
+
|
652
|
+
// рассчитаем "константы" - прямоугольник, в который надо вписывать картинки зданий при входе в них
|
653
|
+
self.X1 = _$b.offset().left + 100;
|
654
|
+
self.X1S = _$b.offset().left + 200;
|
655
|
+
self.Y1 = 73;
|
656
|
+
self.Y1S = 140;
|
657
|
+
self.X2 = self.X1 + _$b.width() * .5;
|
658
|
+
self.X2S = self.X1 + _$b.width() * .4;
|
659
|
+
self.X3 = self.X1 + _$b.width() - 100;
|
660
|
+
self.Y2 = _$m.height() - 20;
|
661
|
+
self.Y2S = _$m.height() - 80;
|
662
|
+
self.CX = (self.X2 - self.X1) / 2 - 2 + self.X1;
|
663
|
+
self.CY = (self.Y2 - self.Y1) / 2 - 2 + self.Y1;
|
664
|
+
|
665
|
+
self.X10 = _$b.offset().left + 15;
|
666
|
+
self.X20 = self.X10 + _$b.width();
|
667
|
+
self.Y10 = 73;
|
668
|
+
self.Y20 = _$m.height();
|
669
|
+
|
670
|
+
// позиционируем элементы
|
671
|
+
$building_info.css("left", self.X2 + "px");
|
672
|
+
$area_order_button.css("left", self.X2 + "px");
|
673
|
+
if (self.container) $container_buttons.css("margin-top", (self.container.height() -10) + "px");
|
674
|
+
|
675
|
+
// DEBUG
|
676
|
+
if (self.debug) {
|
677
|
+
|
678
|
+
if (!_is_debug_drawn) {
|
679
|
+
_is_debug_drawn = true;
|
680
|
+
|
681
|
+
var style = "display:block;position:absolute;background-color:#00ff00;opacity:0.4;";
|
682
|
+
var style_x = style + "width:1px;height:800px;top:0;left:{X}px;";
|
683
|
+
var style_y = style + "width:3000px;height:1px;left:0;top:{Y}px;";
|
684
|
+
var style_dot = style + 'width:4px;height:4px;left:{X}px;top:{Y}px;';
|
685
|
+
|
686
|
+
var to_draw = [
|
687
|
+
{x: self.X10},
|
688
|
+
{x: self.X20},
|
689
|
+
{y: self.Y10},
|
690
|
+
{y: self.Y20},
|
691
|
+
{x: self.CX},
|
692
|
+
{y: self.CY},
|
693
|
+
];
|
694
|
+
|
695
|
+
|
696
|
+
var i, istyle, xx, yy, ip;
|
697
|
+
for (i = 0; i < to_draw.length; i++) {
|
698
|
+
ip = to_draw[i];
|
699
|
+
|
700
|
+
if (ip.x != undefined) {
|
701
|
+
istyle = style_x.split("{X}").join(ip.x);
|
702
|
+
} else if (ip.y != undefined) {
|
703
|
+
istyle = style_y.split("{Y}").join(ip.y);
|
704
|
+
}
|
705
|
+
|
706
|
+
_$m.append($("<div style=" + istyle + "></div>"));
|
707
|
+
}
|
708
|
+
|
709
|
+
}
|
710
|
+
|
711
|
+
}
|
712
|
+
|
713
|
+
};
|
714
|
+
|
715
|
+
/* --- ivalidateViewArea END ----------------------------------------------------------------------------------- */
|
716
|
+
|
717
|
+
self.addEvent = function (target, eventType, func) {
|
718
|
+
self.events.push(new AppEvent(target, eventType, func));
|
719
|
+
return self;
|
720
|
+
};
|
721
|
+
|
722
|
+
self.removeAllEvents = function () {
|
723
|
+
utils.foreach(self.events, function (x) {
|
724
|
+
x.remove();
|
725
|
+
});
|
726
|
+
self.events.length = 0;
|
727
|
+
self.edit_type = null;
|
728
|
+
return this;
|
729
|
+
};
|
730
|
+
|
731
|
+
self.addNodeToSvg = function (node, is_overlay) {
|
732
|
+
if (is_overlay) {
|
733
|
+
self.svg_overlay[0].appendChild(node);
|
734
|
+
} else {
|
735
|
+
self.svg[0].appendChild(node);
|
736
|
+
}
|
737
|
+
return self;
|
738
|
+
};
|
739
|
+
|
740
|
+
self.removeNodeFromSvg = function(node, is_overlay) {
|
741
|
+
if (is_overlay) {
|
742
|
+
self.svg_overlay[0].removeChild(node);
|
743
|
+
} else {
|
744
|
+
self.svg[0].removeChild(node);
|
745
|
+
}
|
746
|
+
return this;
|
747
|
+
};
|
748
|
+
|
749
|
+
self.svgRemoveAllNodes = function () {
|
750
|
+
self.svg.empty();
|
751
|
+
self.svg_overlay.empty();
|
752
|
+
};
|
753
|
+
|
754
|
+
/** Нарисовать на карте объекты из массива childs.
|
755
|
+
*
|
756
|
+
* Массив childs содержит наборы однотипных объектов.
|
757
|
+
* Т.е. объекты только одного типа приходят в фукнцию.
|
758
|
+
* Типы могут быть: C80MapFloors::MapBuilding,C80MapFloors::Area
|
759
|
+
*
|
760
|
+
* Если мы рисуем набор Площадей C80MapFloors::Area, то:
|
761
|
+
* - это означает, что мы вошли в Здание C80MapFloors::Building.
|
762
|
+
* - parent_hash - это as_json объекта класса C80Rent:Building,
|
763
|
+
* который привязан к родителю отрисовываемого C80MapFloors::Area,
|
764
|
+
* (т.е. родитель - это C80MapFloors::Building).
|
765
|
+
* - И подаётся он для того, чтобы в окне с информацией о C80Rent:Area
|
766
|
+
* можно было отобразить характеристики Здания родителя C80Rent:Building.
|
767
|
+
*/
|
768
|
+
self.draw_childs = function (childs, parent_hash) {
|
769
|
+
//clog("<Map.draw_childs>");
|
770
|
+
|
771
|
+
//var ip;
|
772
|
+
var iobj;
|
773
|
+
var ib, id, ia;
|
774
|
+
for (var i = 0; i < childs.length; i++) {
|
775
|
+
iobj = childs[i];
|
776
|
+
|
777
|
+
switch (iobj["class_name"]) { /* NOTE:: сопоставление Ruby класса и JS класса */
|
778
|
+
case 'C80MapFloors::MapBuilding':
|
779
|
+
ib = new Building();
|
780
|
+
ib.init(iobj,self);
|
781
|
+
break;
|
782
|
+
case 'dot':
|
783
|
+
id = new Dot();
|
784
|
+
id.init(iobj,self);
|
785
|
+
break;
|
786
|
+
case 'C80MapFloors::Area':
|
787
|
+
ia = new Area();
|
788
|
+
ia.init(iobj, parent_hash, self);
|
789
|
+
break;
|
790
|
+
case 'C80MapFloors::Floor':
|
791
|
+
ia = new Floor();
|
792
|
+
ia.init(iobj, parent_hash, self);
|
793
|
+
break;
|
794
|
+
}
|
795
|
+
//ip = Polygon.createFromSaved(iobj);
|
796
|
+
//utils.id('svg').appendChild(ip.g);
|
797
|
+
}
|
798
|
+
};
|
799
|
+
|
800
|
+
/**
|
801
|
+
* создаёт DOM элемент:
|
802
|
+
* <div class='mlayer #{obj_type}'>
|
803
|
+
* <img src='#{img_src}' class='mmap-image' />
|
804
|
+
* </div>
|
805
|
+
* и помещает его либо в map_overlay_layers, либо в map_layers (~ от параметра is_overlay)
|
806
|
+
*/
|
807
|
+
self.draw_child_bg_image = function (img_src, obj_type, is_overlay) {
|
808
|
+
var t;
|
809
|
+
if (is_overlay == true) {
|
810
|
+
t = self.map_overlay_layers;
|
811
|
+
} else {
|
812
|
+
t = self.map_layers;
|
813
|
+
}
|
814
|
+
// Create new map layer
|
815
|
+
var layer = $('<div></div>').addClass('mlayer').addClass(obj_type).appendTo(t); // .hide()
|
816
|
+
$('<img>').attr('src', img_src).addClass('mmap-image').appendTo(layer);
|
817
|
+
|
818
|
+
return layer;
|
819
|
+
};
|
820
|
+
|
821
|
+
/**
|
822
|
+
* создаёт DOM элемент:
|
823
|
+
* <div class='map_object_image_bg'> // style='background-image:url(#{img_src});'
|
824
|
+
* <img src=#{img_src} />
|
825
|
+
* </div>
|
826
|
+
* и помещает его map_layers
|
827
|
+
*
|
828
|
+
* left и top - координаты bound box верхнего левого угла здания
|
829
|
+
*
|
830
|
+
*/
|
831
|
+
self.draw_map_object_image_bg = function (img_src, params) {
|
832
|
+
console.log('<draw_map_object_image_bg>');
|
833
|
+
|
834
|
+
// породим DOM
|
835
|
+
var $div_map_object_image_bg = $('<div></div>')
|
836
|
+
.addClass('mlayer')
|
837
|
+
//.attr('style','background-image:url("'+img_src+'")')
|
838
|
+
.appendTo(self.map_layers); // .hide()
|
839
|
+
|
840
|
+
// сохраним начальные параметры в data
|
841
|
+
var left = params["x"];
|
842
|
+
var top = params["y"];
|
843
|
+
var width = params["width"];
|
844
|
+
var height = params["height"];
|
845
|
+
|
846
|
+
var $img = $('<img>')
|
847
|
+
.data('top', top)
|
848
|
+
.data('left', left)
|
849
|
+
.data('width', width)
|
850
|
+
.data('height', height)
|
851
|
+
.attr('src', img_src)
|
852
|
+
.addClass('map_object_image_bg') /* этот класс используем при [zoomove]*/
|
853
|
+
.appendTo($div_map_object_image_bg);
|
854
|
+
|
855
|
+
// рассчитаем позиционирующий стиль и применим его к созданной оверлейной картинке
|
856
|
+
self.__compose_css_style_for_map_object_image($img);
|
857
|
+
|
858
|
+
return $div_map_object_image_bg;
|
859
|
+
|
860
|
+
};
|
861
|
+
|
862
|
+
/**
|
863
|
+
* Задача этой служебной функции:
|
864
|
+
* - рассчёт актуальных (для данного масштаба) размеров и координат местонах указанного объекта (вместо объекта подаётся хэш описывающий его, с x,y,width,height)
|
865
|
+
* - составление css стиля для картинки с css-классом map_object_image_bg
|
866
|
+
* - присвоении этого стиля картинке
|
867
|
+
*
|
868
|
+
* Вызывается каждый шаг анимации и при входе в здание на первый этаж.
|
869
|
+
*
|
870
|
+
* Пользуется map.scale_during_animation при рассчётах
|
871
|
+
*
|
872
|
+
* @private
|
873
|
+
*/
|
874
|
+
self.__compose_css_style_for_map_object_image = function ($img_with_class_map_object_image_bg) {
|
875
|
+
|
876
|
+
var $i = $img_with_class_map_object_image_bg;
|
877
|
+
|
878
|
+
// проведём калькуляцию [zoomove-calc]
|
879
|
+
var left = $i.data("left")*self.scale_during_animation;
|
880
|
+
var top = $i.data("top")*self.scale_during_animation;
|
881
|
+
var width = $i.data("width")*self.scale_during_animation;
|
882
|
+
var height = $i.data("height")*self.scale_during_animation;
|
883
|
+
|
884
|
+
// впишем в DOM стили
|
885
|
+
var style = 'top:';
|
886
|
+
style += top + 'px;';
|
887
|
+
style += "left:";
|
888
|
+
style += left + 'px;';
|
889
|
+
style += "width:";
|
890
|
+
style += width + 'px;';
|
891
|
+
style += "height:";
|
892
|
+
style += height + 'px;';
|
893
|
+
|
894
|
+
console.log("> scale: " + self.scale + "; style: " + style);
|
895
|
+
$i.attr('style',style);
|
896
|
+
|
897
|
+
};
|
898
|
+
|
899
|
+
self.onEdit = function (e) {
|
900
|
+
|
901
|
+
//clog("<Polygon.prototype.onEdit> _s_f = " + _s_f);
|
902
|
+
//clog("<Polygon.prototype.onEdit> e = ");
|
903
|
+
//clog(_s_f);
|
904
|
+
//clog(e.pageX);
|
905
|
+
|
906
|
+
var selected_area = self.selected_area;
|
907
|
+
var edit_type = self.edit_type;
|
908
|
+
//clog("<Polygon.prototype.onEdit> edit_type = " + edit_type);
|
909
|
+
|
910
|
+
selected_area.dynamicEdit(selected_area[edit_type](e.pageX - selected_area.delta.x, e.pageY - selected_area.delta.y));
|
911
|
+
selected_area.delta.x = e.pageX;
|
912
|
+
selected_area.delta.y = e.pageY;
|
913
|
+
};
|
914
|
+
|
915
|
+
self.onDrawStop = function (e) {
|
916
|
+
clog("<Map.onDrawStop>");
|
917
|
+
|
918
|
+
if (e != undefined) {
|
919
|
+
if (e.type == 'keydown' && e.keyCode == 13) {
|
920
|
+
// its ok, continue execution..
|
921
|
+
} else {
|
922
|
+
return
|
923
|
+
}
|
924
|
+
}
|
925
|
+
|
926
|
+
var _n_f = self.drawing_poligon;
|
927
|
+
if (_n_f.params.length >= 6) { //>= 3 points for polygon
|
928
|
+
_n_f.polyline = _n_f.polygon;
|
929
|
+
_n_f.polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
|
930
|
+
_n_f.g.replaceChild(_n_f.polygon, _n_f.polyline);
|
931
|
+
_n_f.setCoords(_n_f.params).deselect();
|
932
|
+
delete(_n_f.polyline);
|
933
|
+
|
934
|
+
// в зависимости от предыдущего состояния, создадим либо Здание, либо Площадь
|
935
|
+
if (self.prev_mode == "edit_building") {
|
936
|
+
var bo = self.current_building.options;
|
937
|
+
var a = new Area();
|
938
|
+
a.init({ coords:_n_f.params }, bo, self);
|
939
|
+
//a.is_new = true;
|
940
|
+
_n_f.remove(); // удаляем нарисованный полигон, т.к. его уже заменили полигоном Area
|
941
|
+
self.registerJustDrownArea(a);
|
942
|
+
}
|
943
|
+
else if (self.prev_mode == 'editing') {
|
944
|
+
var b = new Building();
|
945
|
+
b.init({ coords:_n_f.params }, self);
|
946
|
+
//b.is_new = true;
|
947
|
+
_n_f.remove(); // удаляем нарисованный полигон, т.к. его уже заменили полигоном Building
|
948
|
+
self.registerJustDrownBuilding(b);
|
949
|
+
}
|
950
|
+
|
951
|
+
self.removeAllEvents();
|
952
|
+
self.drawing_poligon = null;
|
953
|
+
self.is_draw = false;
|
954
|
+
}
|
955
|
+
|
956
|
+
self.setMode('editing');
|
957
|
+
};
|
958
|
+
|
959
|
+
self.onEditStop = function (e) {
|
960
|
+
//clog("<Polygon.prototype.onEditStop>");
|
961
|
+
var _s_f = self.selected_area,
|
962
|
+
edit_type = self.edit_type;
|
963
|
+
|
964
|
+
_s_f.setParams(_s_f.dynamicEdit(_s_f[edit_type](e.pageX - _s_f.delta.x, e.pageY - _s_f.delta.y)));
|
965
|
+
|
966
|
+
self.removeAllEvents();
|
967
|
+
};
|
968
|
+
|
969
|
+
self.registerJustDrownArea = function (area) {
|
970
|
+
self.drawn_areas.push(area);
|
971
|
+
};
|
972
|
+
|
973
|
+
self.registerJustDrownBuilding = function (building) {
|
974
|
+
self.drawn_buildings.push(building);
|
975
|
+
};
|
976
|
+
|
977
|
+
/**
|
978
|
+
* Зная ширину контейнера и контента,
|
979
|
+
* используя указанные параметры,
|
980
|
+
* рассчитать нормальный X
|
981
|
+
* @param x
|
982
|
+
* @param scale
|
983
|
+
* @returns {*}
|
984
|
+
*/
|
985
|
+
self.normalizeX = function (params) {
|
986
|
+
|
987
|
+
var x = params['x'];
|
988
|
+
var scale = params['scale'];
|
989
|
+
|
990
|
+
var minX = self.container.width() - self.contentWidth * scale;
|
991
|
+
|
992
|
+
if (minX < 0) {
|
993
|
+
if (x > 0) x = 0;
|
994
|
+
else if (x < minX) x = minX;
|
995
|
+
}
|
996
|
+
else x = minX / 2;
|
997
|
+
|
998
|
+
return x;
|
999
|
+
};
|
1000
|
+
|
1001
|
+
/**
|
1002
|
+
* Зная высоту контейнера и контента,
|
1003
|
+
* используя указанные параметры,
|
1004
|
+
* рассчитать нормальный Y
|
1005
|
+
* @param y
|
1006
|
+
* @param scale
|
1007
|
+
* @returns {*}
|
1008
|
+
*/
|
1009
|
+
self.normalizeY = function (params) {
|
1010
|
+
|
1011
|
+
var y = params['y'];
|
1012
|
+
var scale = params['scale'];
|
1013
|
+
|
1014
|
+
var minY = self.container.height() - self.contentHeight * scale;
|
1015
|
+
|
1016
|
+
if (minY < 0) {
|
1017
|
+
if (y >= 0) y = 0;
|
1018
|
+
else if (y < minY) y = minY;
|
1019
|
+
}
|
1020
|
+
else y = minY / 2;
|
1021
|
+
|
1022
|
+
return y;
|
1023
|
+
};
|
1024
|
+
|
1025
|
+
/**
|
1026
|
+
* Используя ограничения по масштабу нормализовать scale
|
1027
|
+
* @param scale
|
1028
|
+
* @returns {*}
|
1029
|
+
*/
|
1030
|
+
self.normalizeScale = function (scale) {
|
1031
|
+
clog('<self.normalizeScale>' + self.o.fitscale);
|
1032
|
+
if (scale < self.o.fitscale) scale = self.o.fitscale;
|
1033
|
+
else if (scale > self.o.maxscale) scale = self.o.maxscale;
|
1034
|
+
|
1035
|
+
if (self.zoombuttons) self.zoombuttons.update(scale);
|
1036
|
+
|
1037
|
+
return scale;
|
1038
|
+
};
|
1039
|
+
|
1040
|
+
/*self.zoomTo = function (x, y, s, duration, easing, ry) {
|
1041
|
+
duration = typeof duration !== 'undefined' ? duration : 400;
|
1042
|
+
ry = typeof ry !== 'undefined' ? ry : 0.5;
|
1043
|
+
|
1044
|
+
// это значение нужно присвоить только после анимации
|
1045
|
+
self.scale = self.normalizeScale(self.o.fitscale * s);
|
1046
|
+
|
1047
|
+
self.x = self.normalizeX(self.container.width() * 0.5 - self.scale * self.contentWidth * x);
|
1048
|
+
self.y = self.normalizeY(self.container.height() * ry - self.scale * self.contentHeight * y);
|
1049
|
+
|
1050
|
+
clog("<Map.zoomTo> Call moveTo.");
|
1051
|
+
self.moveTo(self.x, self.y, self.scale, duration, easing);
|
1052
|
+
};*/
|
1053
|
+
|
1054
|
+
/**
|
1055
|
+
* задачи этой функции:
|
1056
|
+
* - быть контейнером кода
|
1057
|
+
* - считывать css атрибут self.map
|
1058
|
+
* - по регулярке извлекать left и top
|
1059
|
+
* - трансформировать эти значения
|
1060
|
+
* - изменить атрибут viewBox обоих svg слоёв
|
1061
|
+
*
|
1062
|
+
* Изначально была задумка каждый шаг анимации вызывать эту функцию.
|
1063
|
+
* Но затем во время оптимизации слои с svg стали видны только тогда,
|
1064
|
+
* когда анимация не проходит. По-этому этот код был поставлен на setTimeout
|
1065
|
+
*
|
1066
|
+
* Отличие этого кода от [qq1] лишь в механике вычисления (извлечения) нужных значений.
|
1067
|
+
* Скорее всего, это код-дубликат, который появился во время rush разработки.
|
1068
|
+
* Т.е. желателен рефакторинг и упрощение логики, но не сейчас.
|
1069
|
+
* */
|
1070
|
+
var __afterMovingCorrectSvgLayersPositions = function () {
|
1071
|
+
//clog(self.map.attr('style'));
|
1072
|
+
// left: -69.9985px; top: -299.999px;
|
1073
|
+
// left: [-]{0,1}(\d+\.\d+px);
|
1074
|
+
|
1075
|
+
var str = self.map.attr('style');
|
1076
|
+
var rx_left = /left: [-]{0,1}(\d+\.\d+)px;/;
|
1077
|
+
var rx_top = /top: ([-]{0,1}\d+\.\d+)px;/;
|
1078
|
+
var match_left = str.match(rx_left);
|
1079
|
+
var match_right = str.match(rx_top);
|
1080
|
+
|
1081
|
+
if (match_left != null && match_right != null) {
|
1082
|
+
var x = -1 * Number(match_left[1]); // ["left: -69.9985px;", "69.9985"]
|
1083
|
+
var y = -1 * Number(match_right[1]); // ["left: -69.9985px;", "69.9985"]
|
1084
|
+
var att = x + " " + y + " " + self.contentWidth + " " + self.contentHeight;
|
1085
|
+
//clog(x + "; y = " + y);
|
1086
|
+
self.svg.attr('viewBox', att);
|
1087
|
+
self.svg_overlay.attr('viewBox', att);
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
};
|
1091
|
+
|
1092
|
+
/**
|
1093
|
+
* Вызывается после анимации moveTo
|
1094
|
+
* Задачей этого метода является :
|
1095
|
+
* - сохранение x,y,scale в данных карты,
|
1096
|
+
* - корректировка местонах и размера оверлейного слоя после анимации
|
1097
|
+
*
|
1098
|
+
* @param y // эти параметры есть конечная точка анимации moveTo,
|
1099
|
+
* @param x // т.е. к этим параметрам позиции стремится картинка карты и это анимируется
|
1100
|
+
* @param scale // как только картинка карты дойдёт до цели - их надо сохранить в map
|
1101
|
+
*
|
1102
|
+
* @private
|
1103
|
+
*/
|
1104
|
+
var __moveToComplete = function (x,y,scale) {
|
1105
|
+
console.log("<__moveToComplete> x = " + x + "; y = " + y + "; scale = " + scale);
|
1106
|
+
|
1107
|
+
/* NOTE:: CORE */
|
1108
|
+
|
1109
|
+
if (scale !== undefined) self.scale = scale;
|
1110
|
+
self.x = x;
|
1111
|
+
self.y = y;
|
1112
|
+
|
1113
|
+
if (self.tooltip) self.tooltip.position();
|
1114
|
+
|
1115
|
+
__afterMovingCorrectSvgLayersPositions();
|
1116
|
+
|
1117
|
+
};
|
1118
|
+
|
1119
|
+
var __moveToTimeout = function () {
|
1120
|
+
if (self.mode === 'edit_area'|| self.mode === 'view_area') {
|
1121
|
+
$("#masked").removeClass('hiddn');
|
1122
|
+
}
|
1123
|
+
};
|
1124
|
+
/*var __moveToAnimate = function () {
|
1125
|
+
|
1126
|
+
};*/
|
1127
|
+
|
1128
|
+
/**
|
1129
|
+
* Рассчитывает scale_during_animation и корректирует местонах. оверлейных картинок.
|
1130
|
+
* Вызывается каждый шаг анимации moveto.
|
1131
|
+
* @private
|
1132
|
+
*/
|
1133
|
+
var __moveToStep = function () {
|
1134
|
+
|
1135
|
+
//var x = self.map.css('left').split('px').join('');
|
1136
|
+
//var y = self.map.css('top').split('px').join('');
|
1137
|
+
var w = self.map.css('width').split('px').join('');
|
1138
|
+
//var h = self.map.css('height').split('px').join('');
|
1139
|
+
|
1140
|
+
//var image_width = MAP_WIDTH * scale;
|
1141
|
+
|
1142
|
+
// рассчитаем мгновенное значение scale
|
1143
|
+
self.scale_during_animation = w / MAP_WIDTH;
|
1144
|
+
|
1145
|
+
// [zoomove] пробежимся по всем оверлейным картинкам и позиционируем их
|
1146
|
+
$('.map_object_image_bg').each(function () {
|
1147
|
+
// рассчитаем и применим стиль
|
1148
|
+
self.__compose_css_style_for_map_object_image($( this ));
|
1149
|
+
});
|
1150
|
+
|
1151
|
+
//console.log("<__moveToStep> x = " + x + "; y = " + y + "; w = " + w + "; h = " + h + "; scale = " + scale_during_animation);
|
1152
|
+
};
|
1153
|
+
|
1154
|
+
// x,y - экранные координаты
|
1155
|
+
// сюда подаётся scale, который нужно присвоить map после анимации
|
1156
|
+
self.moveTo = function (x, y, scale, d, easing) {
|
1157
|
+
clog("<self.moveTo> x = " + x + "; y = " + y + "; scale = " + scale + "; delay = " + d);
|
1158
|
+
//clog('<self.moveTo>');
|
1159
|
+
|
1160
|
+
// если подан аргумент scale(масштаб)
|
1161
|
+
// перемещаемся анимированно
|
1162
|
+
if (scale !== undefined) {
|
1163
|
+
|
1164
|
+
// на время движения скрываем слой с полосатой анимацией
|
1165
|
+
if (self.current_area != null) {
|
1166
|
+
$("#masked").addClass('hiddn');
|
1167
|
+
setTimeout(__moveToTimeout, d);
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
//setTimeout(__afterMovingCorrectSvgLayersPositions, d);
|
1171
|
+
|
1172
|
+
self.map.stop().animate(
|
1173
|
+
{
|
1174
|
+
'left': x,
|
1175
|
+
'top': y,
|
1176
|
+
'width': self.contentWidth * scale,
|
1177
|
+
'height': self.contentHeight * scale
|
1178
|
+
},
|
1179
|
+
{
|
1180
|
+
'step': __moveToStep,
|
1181
|
+
'complete': function () {
|
1182
|
+
__moveToComplete(x,y,scale);
|
1183
|
+
}
|
1184
|
+
},
|
1185
|
+
d,
|
1186
|
+
easing //,
|
1187
|
+
//__moveToAnimate
|
1188
|
+
);
|
1189
|
+
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
// если не подан аргумент scale(масштаб)
|
1193
|
+
// перемещаемся без анимации
|
1194
|
+
else {
|
1195
|
+
|
1196
|
+
self.map.css({
|
1197
|
+
'left': x,
|
1198
|
+
'top': y
|
1199
|
+
});
|
1200
|
+
|
1201
|
+
__moveToComplete(x,y);
|
1202
|
+
|
1203
|
+
// отличие этого кода [qq1] от кода в [__afterMovingCorrectSvgLayersPositions] лишь в том,
|
1204
|
+
// что строка для атрибута viewbox формируется иным образом
|
1205
|
+
// Скорее всего, это код-дубликат, который появился во время rush разработки.
|
1206
|
+
//var t = (-x) + " " + (-y) + " " + self.contentWidth * self.scale + " " + self.contentHeight * self.scale;
|
1207
|
+
//self.svg.attr('viewBox',t);
|
1208
|
+
//self.svg_overlay.attr('viewBox', t);
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
if (self.current_area != null) {
|
1212
|
+
self.current_area.invalidateAnimationMask();
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
//if (self.tooltip) self.tooltip.position();
|
1216
|
+
//if (self.minimap) self.minimap.update(x, y);
|
1217
|
+
};
|
1218
|
+
|
1219
|
+
// показать инфо о здании
|
1220
|
+
self.showBuildingInfo = function (rent_building_hash) {
|
1221
|
+
console.log("<main.showBuildingInfo> Показать информацию о Rent-здании с id = " + rent_building_hash.id);
|
1222
|
+
|
1223
|
+
//"rent_building_hash": {
|
1224
|
+
// "id": 2,
|
1225
|
+
// "title": "Здание 2",
|
1226
|
+
// "props": {
|
1227
|
+
// "square": "1234 кв.м.",
|
1228
|
+
// "square_free": "124 кв. м",
|
1229
|
+
// "floor_height": "124 кв. м",
|
1230
|
+
// "column_step": "2 м",
|
1231
|
+
// "gate_type": "распашные",
|
1232
|
+
// "communications": "Интернет, электричество, водоснабжение",
|
1233
|
+
// "price": "от 155 руб/кв.м в месяц"
|
1234
|
+
// }
|
1235
|
+
|
1236
|
+
if (rent_building_hash.id == undefined) {
|
1237
|
+
$building_info.css('display','none');
|
1238
|
+
} else {
|
1239
|
+
$building_info.css('display','block');
|
1240
|
+
$building_info.find("h2").text(rent_building_hash["title"]);
|
1241
|
+
|
1242
|
+
var v, $ili, p;
|
1243
|
+
for (p in rent_building_hash["props"]) {
|
1244
|
+
|
1245
|
+
v = rent_building_hash["props"][p];
|
1246
|
+
$ili = $building_info.find("#" + p);
|
1247
|
+
$ili.find('span').text(v);
|
1248
|
+
//console.log("."+v+".");
|
1249
|
+
|
1250
|
+
// Не показывать пользователю карты незаполненные поля
|
1251
|
+
var li_css_display = 'block';
|
1252
|
+
if (v == '' || v == '-1' || v === 'null' || v == null) {
|
1253
|
+
li_css_display = 'none';
|
1254
|
+
}
|
1255
|
+
$ili.css('display',li_css_display);
|
1256
|
+
|
1257
|
+
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
$building_info.find("#square_free").css('height', 'auto');
|
1261
|
+
}
|
1262
|
+
};
|
1263
|
+
|
1264
|
+
// показать инфо о просматриваемой площади
|
1265
|
+
self.showAreaInfo = function (area_hash, parent_building_hash) {
|
1266
|
+
//clog(area_hash);
|
1267
|
+
|
1268
|
+
//"area_hash": {
|
1269
|
+
// "id": 2,
|
1270
|
+
// "title": "Площадь 2.12",
|
1271
|
+
// "is_free": false,
|
1272
|
+
// "props": {
|
1273
|
+
// "square": "100 кв.м.",
|
1274
|
+
// "floor_height": "6 кв. м",
|
1275
|
+
// "column_step": "2 м",
|
1276
|
+
// "gate_type": "распашные",
|
1277
|
+
// "communications": "Интернет, электричество, водоснабжение",
|
1278
|
+
// "price": "от 155 руб/кв.м в месяц"
|
1279
|
+
// }
|
1280
|
+
|
1281
|
+
//"rent_building_hash": {
|
1282
|
+
// "id": 2,
|
1283
|
+
// "title": "Здание 2",
|
1284
|
+
// "props": {
|
1285
|
+
// "square": "1234 кв.м.",
|
1286
|
+
// "square_free": "124 кв. м",
|
1287
|
+
// "floor_height": "6 кв. м",
|
1288
|
+
// "column_step": "2 м",
|
1289
|
+
// "gate_type": "распашные",
|
1290
|
+
// "communications": "Интернет, электричество, водоснабжение",
|
1291
|
+
// "price": "от 155 руб/кв.м в месяц"
|
1292
|
+
// }
|
1293
|
+
|
1294
|
+
$building_info.find("h2").html("</span>" + area_hash["title"] + "<span style='color:#D0B2B2;'> / " + parent_building_hash["title"]);
|
1295
|
+
|
1296
|
+
var v;
|
1297
|
+
for (var p in area_hash["props"]) {
|
1298
|
+
v = area_hash["props"][p];
|
1299
|
+
$building_info.find("#" + p).find('span').text(v);
|
1300
|
+
}
|
1301
|
+
|
1302
|
+
$building_info.find("#square_free").css('height', '0');
|
1303
|
+
|
1304
|
+
// заполняем данными ссылку 'Оставить заявку'
|
1305
|
+
var $a_make_order = $building_info.find('.c80_order_invoking_btn');
|
1306
|
+
$a_make_order.data('comment-text', 'Здравствуйте, оставляю заявку на площадь: ' + area_hash["title"]);
|
1307
|
+
$a_make_order.data('subj-id', area_hash["id"]);
|
1308
|
+
|
1309
|
+
};
|
1310
|
+
|
1311
|
+
// перевод экранных координат в логические
|
1312
|
+
self.rightX = function(x) {
|
1313
|
+
return (x - self.x - self.container.offset().left) / self.scale;
|
1314
|
+
};
|
1315
|
+
|
1316
|
+
self.rightY = function(y) {
|
1317
|
+
return (y - self.y - self.container.offset().top) / self.scale
|
1318
|
+
};
|
1319
|
+
|
1320
|
+
// взять C80MapFloors::current_area и назначить ей Rent::area.id,
|
1321
|
+
// выбранный в окне _modal_window.html.erb
|
1322
|
+
self.link_area = function () {
|
1323
|
+
|
1324
|
+
// фиксируем компоненты модального окна
|
1325
|
+
var $m = $('#modal_window');
|
1326
|
+
var $b = $m.find('.modal-footer').find('.btn');
|
1327
|
+
var $s = $m.find('select');
|
1328
|
+
|
1329
|
+
// извлекаем значения
|
1330
|
+
var rent_area_id = $s.val();
|
1331
|
+
var map_area_id = self.current_area.id;
|
1332
|
+
console.log("<Map.link_area> rent_area_id = " + rent_area_id + "; map_area_id = " + map_area_id);
|
1333
|
+
|
1334
|
+
// нажимаем кнопку "закрыть"
|
1335
|
+
$b.click();
|
1336
|
+
|
1337
|
+
// показываем прелоадер
|
1338
|
+
self.save_preloader_klass.show();
|
1339
|
+
|
1340
|
+
// отправляем запрос на сервер
|
1341
|
+
// TODO_MY:: реализовать обработчик ошибок
|
1342
|
+
$.ajax({
|
1343
|
+
url:'/ajax/link_area',
|
1344
|
+
type:'POST',
|
1345
|
+
data: {
|
1346
|
+
rent_area_id: rent_area_id,
|
1347
|
+
map_area_id: map_area_id
|
1348
|
+
},
|
1349
|
+
dataType:"json"
|
1350
|
+
}).done(function (data, result) {
|
1351
|
+
self.save_preloader_klass.hide();
|
1352
|
+
self.data = data["updated_locations_json"];
|
1353
|
+
});
|
1354
|
+
|
1355
|
+
};
|
1356
|
+
|
1357
|
+
// взять C80MapFloors::current_building и назначить ему Rent::building.id,
|
1358
|
+
// выбранный в окне _modal_window.html.erb
|
1359
|
+
self.link_building = function () {
|
1360
|
+
console.log('<Map.link_building> ');
|
1361
|
+
|
1362
|
+
// фиксируем компоненты модального окна
|
1363
|
+
var $m = $('#modal_window');
|
1364
|
+
var $b = $m.find('.modal-footer').find('.btn');
|
1365
|
+
var $s = $m.find('select');
|
1366
|
+
|
1367
|
+
// извлекаем значения
|
1368
|
+
var rent_building_id = $s.val();
|
1369
|
+
var map_building_id = self.current_building.id;
|
1370
|
+
console.log("<Map.link_area> rent_building_id = " + rent_building_id + "; map_building_id = " + map_building_id);
|
1371
|
+
|
1372
|
+
// нажимаем кнопку "закрыть"
|
1373
|
+
$b.click();
|
1374
|
+
|
1375
|
+
// показываем прелоадер
|
1376
|
+
self.save_preloader_klass.show();
|
1377
|
+
|
1378
|
+
// отправляем запрос на сервер
|
1379
|
+
// TODO_MY:: реализовать обработчик ошибок
|
1380
|
+
$.ajax({
|
1381
|
+
url:'/ajax/link_building',
|
1382
|
+
type:'POST',
|
1383
|
+
data: {
|
1384
|
+
rent_building_id: rent_building_id,
|
1385
|
+
map_building_id: map_building_id
|
1386
|
+
},
|
1387
|
+
dataType:"json"
|
1388
|
+
}).done(function (data, result) {
|
1389
|
+
self.save_preloader_klass.hide();
|
1390
|
+
self.data = data["updated_locations_json"];
|
1391
|
+
});
|
1392
|
+
|
1393
|
+
};
|
1394
|
+
|
1395
|
+
self.show_free_areas_hint = function () {
|
1396
|
+
// рисуем в слое #svg_overlay,
|
1397
|
+
// а т.к. находимся в режиме просмотра карты,
|
1398
|
+
// этот слой пуст, можно им пока воспользоваться
|
1399
|
+
|
1400
|
+
|
1401
|
+
|
1402
|
+
};
|
1403
|
+
self.hide_free_areas_hint = function () {
|
1404
|
+
|
1405
|
+
};
|
1406
|
+
|
1407
|
+
};
|
1408
|
+
|
1409
|
+
// Create a jQuery plugin
|
1410
|
+
$.fn.beMap = function (params) {
|
1411
|
+
var len = this.length;
|
1412
|
+
|
1413
|
+
return this.each(function (index) {
|
1414
|
+
var me = $(this),
|
1415
|
+
key = 'beMap' + (len > 1 ? '-' + ++index : ''),
|
1416
|
+
instance = (new Map).init(me, params);
|
1417
|
+
});
|
1418
|
+
};
|
1419
|
+
|
1420
|
+
})
|
1421
|
+
(jQuery);
|