c80_map_floors 0.1.0.1
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.
- 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);
|