pageflow-linkmap-page 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -6
  3. data/Gemfile +0 -7
  4. data/README.md +0 -5
  5. data/app/assets/javascript/pageflow/linkmap_page/editor/collections/areas_collection.js +8 -1
  6. data/app/assets/javascript/pageflow/linkmap_page/editor/config.js +23 -1
  7. data/app/assets/javascript/pageflow/linkmap_page/editor/controllers/side_bar_controller.js +24 -5
  8. data/app/assets/javascript/pageflow/linkmap_page/editor/models/area.js +4 -1
  9. data/app/assets/javascript/pageflow/linkmap_page/editor/models/color_map_delegator.js +16 -0
  10. data/app/assets/javascript/pageflow/linkmap_page/editor/models/color_map_file.js +6 -0
  11. data/app/assets/javascript/pageflow/linkmap_page/editor/models/masked_image_file.js +7 -0
  12. data/app/assets/javascript/pageflow/linkmap_page/editor/models/page_configuration_mixin.js +49 -55
  13. data/app/assets/javascript/pageflow/linkmap_page/editor/models/processed_file.js +12 -0
  14. data/app/assets/javascript/pageflow/linkmap_page/editor/patterns/area_pattern.js +42 -0
  15. data/app/assets/javascript/pageflow/linkmap_page/editor/routers/side_bar_router.js +3 -1
  16. data/app/assets/javascript/pageflow/linkmap_page/editor/templates/embedded/area_item.jst.ejs +2 -2
  17. data/app/assets/javascript/pageflow/linkmap_page/editor/templates/embedded/area_masks_preview.jst.ejs +4 -2
  18. data/app/assets/javascript/pageflow/linkmap_page/editor/templates/embedded/area_outlines.jst.ejs +3 -2
  19. data/app/assets/javascript/pageflow/linkmap_page/editor/templates/embedded/mobile_info_box_page_item.jst.ejs +2 -0
  20. data/app/assets/javascript/pageflow/linkmap_page/editor/views/areas_list_view.js +1 -0
  21. data/app/assets/javascript/pageflow/linkmap_page/editor/views/configuration_editor_view.js +46 -0
  22. data/app/assets/javascript/pageflow/linkmap_page/editor/views/edit_area_view.js +3 -6
  23. data/app/assets/javascript/pageflow/linkmap_page/editor/views/embedded/area_item_embedded_view.js +75 -10
  24. data/app/assets/javascript/pageflow/linkmap_page/editor/views/embedded/area_masks_preview_embedded_view.js +71 -77
  25. data/app/assets/javascript/pageflow/linkmap_page/editor/views/embedded/area_outlines_embedded_view.js +44 -82
  26. data/app/assets/javascript/pageflow/linkmap_page/editor/views/embedded/areas_embedded_view.js +12 -13
  27. data/app/assets/javascript/pageflow/linkmap_page/editor/views/embedded/mobile_info_box_embedded_view.js +61 -0
  28. data/app/assets/javascript/pageflow/linkmap_page/editor/views/embedded/mobile_info_box_page_item_embedded_view.js +28 -0
  29. data/app/assets/javascript/pageflow/linkmap_page/editor.js +10 -2
  30. data/app/assets/javascript/pageflow/linkmap_page/page_type.js +155 -20
  31. data/app/assets/javascript/pageflow/linkmap_page/widgets/hover_video.js +4 -1
  32. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/area_contains.js +7 -6
  33. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/area_set_mask.js +16 -0
  34. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/color_map.js +83 -142
  35. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/image_data.js +17 -47
  36. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/mask.js +3 -34
  37. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/remote_image.js +3 -6
  38. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap.js +78 -92
  39. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_area_indicators.js +75 -0
  40. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_paginator.js +292 -0
  41. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_pan_zoom.js +241 -0
  42. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_panorama.js +81 -59
  43. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_scroll_indicators.js +14 -0
  44. data/app/assets/stylesheets/pageflow/linkmap_page/editor/area_outlines.scss +6 -0
  45. data/app/assets/stylesheets/pageflow/linkmap_page/editor/masks_preview.scss +10 -0
  46. data/app/assets/stylesheets/pageflow/linkmap_page/themes/default/mobile_info_box.scss +31 -0
  47. data/app/assets/stylesheets/pageflow/linkmap_page/themes/default/paginator.scss +53 -0
  48. data/app/assets/stylesheets/pageflow/linkmap_page/themes/default/scroll_indicators.scss +5 -1
  49. data/app/assets/stylesheets/pageflow/linkmap_page/themes/default.scss +3 -0
  50. data/app/assets/stylesheets/pageflow/linkmap_page.scss +29 -3
  51. data/app/helpers/pageflow/linkmap_page/areas_helper.rb +37 -11
  52. data/app/jobs/pageflow/linkmap_page/process_source_image_file_job.rb +4 -4
  53. data/app/views/pageflow/linkmap_page/areas/_div.html.erb +13 -7
  54. data/app/views/pageflow/linkmap_page/color_map_files/_color_map_file.json.jbuilder +18 -0
  55. data/app/views/pageflow/linkmap_page/editor/color_map_files/_color_map_file.json.jbuilder +1 -0
  56. data/app/views/pageflow/linkmap_page/editor/masked_image_files/_masked_image_file.json.jbuilder +1 -0
  57. data/app/views/pageflow/linkmap_page/page.html.erb +76 -39
  58. data/config/locales/de.yml +47 -4
  59. data/config/locales/en.yml +43 -4
  60. data/db/migrate/20170330201200_create_mask_sprites.rb +1 -1
  61. data/db/migrate/20171106151700_create_masked_image_files.rb +1 -1
  62. data/db/migrate/20180111145100_create_color_map_files.rb +1 -1
  63. data/db/migrate/20180214201200_drop_mask_sprites.rb +7 -0
  64. data/lib/pageflow/linkmap_page/engine.rb +4 -0
  65. data/lib/pageflow/linkmap_page/page_type.rb +26 -0
  66. data/lib/pageflow/linkmap_page/paperclip_processors/color_mask.rb +1 -1
  67. data/lib/pageflow/linkmap_page/paperclip_processors/colors.rb +1 -1
  68. data/lib/pageflow/linkmap_page/version.rb +1 -1
  69. data/lib/tasks/pageflow_linkmap_page_tasks.rake +8 -7
  70. data/pageflow-linkmap-page.gemspec +11 -5
  71. data/spec/factories/color_map_file.rb +16 -0
  72. data/spec/factories/image_file.rb +25 -0
  73. data/spec/factories/masked_image_file.rb +10 -0
  74. data/spec/helpers/pageflow/linkmap_page/areas_helper_spec.rb +76 -13
  75. data/spec/integration/masked_image_file_type_spec.rb +15 -0
  76. data/spec/models/pageflow/linkmap_page/color_map_file_spec.rb +113 -0
  77. data/spec/models/pageflow/linkmap_page/masked_image_file_spec.rb +87 -0
  78. data/spec/pageflow/linkmap_page/paperclip_processors/colors_spec.rb +46 -0
  79. data/spec/pageflow/linkmap_page/progress_spec.rb +91 -0
  80. data/spec/spec_helper.rb +5 -1
  81. data/spec/support/config/devise.rb +1 -8
  82. data/spec/support/config/{factory_girl.rb → factory_bot.rb} +5 -3
  83. data/spec/support/config/resque.rb +9 -0
  84. data/spec/support/fixtures/black_dots.png +0 -0
  85. data/spec/support/fixtures/color_map.png +0 -0
  86. data/spec/support/fixtures/dots_and_lines.png +0 -0
  87. data/spec/support/fixtures/green_and_black.png +0 -0
  88. data/spec/support/fixtures/red.png +0 -0
  89. data/spec/support/fixtures/transparent.png +0 -0
  90. data/spec/support/matchers/have_color.rb +34 -0
  91. metadata +98 -41
  92. data/app/assets/javascript/pageflow/linkmap_page/editor/models/masks_delegator.js +0 -16
  93. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/area_redraw.js +0 -34
  94. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/mask_sprite.js +0 -68
  95. data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/masks.js +0 -99
  96. data/app/controllers/pageflow/linkmap_page/mask_sprites_controller.rb +0 -26
  97. data/app/models/pageflow/linkmap_page/mask_sprite.rb +0 -15
  98. data/config/routes.rb +0 -5
  99. data/spec/controllers/pageflow/linkmap_page/mask_sprites_controller_spec.rb +0 -108
@@ -0,0 +1,28 @@
1
+ pageflow.linkmapPage.MobileInfoBoxPageItemEmbeddedView = Backbone.Marionette.ItemView.extend({
2
+ template: 'pageflow/linkmap_page/editor/templates/embedded/mobile_info_box_page_item',
3
+
4
+ className: 'linkmap-paginator-page',
5
+
6
+ ui: {
7
+ title: 'h3',
8
+ description: 'p'
9
+ },
10
+
11
+ modelEvents: {
12
+ 'change:link_title change:link_description': 'update'
13
+ },
14
+
15
+ onRender: function() {
16
+ this.update();
17
+ },
18
+
19
+ update: function() {
20
+ this.ui.title.text(this.model.get('link_title'));
21
+ this.ui.description.html(this.model.get('link_description'));
22
+
23
+ this.ui.title.toggle(!!this.model.get('link_title'));
24
+ this.ui.description.toggle(!!this.model.get('link_description'));
25
+
26
+ this.options.paginator.linkmapPaginator('updateHeight');
27
+ }
28
+ });
@@ -1,11 +1,13 @@
1
1
  //= require_self
2
2
 
3
+ //= require ./editor/models/processed_file
3
4
  //= require_tree ./editor/models
4
5
  //= require_tree ./editor/collections
5
6
  //= require_tree ./editor/routers
6
7
  //= require_tree ./editor/controllers
7
8
  //= require_tree ./editor/templates
8
9
  //= require_tree ./editor/views
10
+ //= require_tree ./editor/patterns
9
11
 
10
12
  //= require ./editor/config
11
13
 
@@ -25,12 +27,18 @@ pageflow.linkmapPage.areaTypesFor = function(pageConfiguration) {
25
27
  };
26
28
 
27
29
  pageflow.linkmapPage.selectArea = function(page, options) {
30
+ options = options || {};
31
+
32
+ pageflow.entry.unset('emulation_mode');
33
+
28
34
  return $.Deferred(function(deferred) {
29
- pageflow.linkmapPage.currentAreaSelection = _.extend(options || {}, {
35
+ pageflow.linkmapPage.currentAreaSelection = _.extend(options, {
30
36
  deferred: deferred
31
37
  });
32
38
 
33
- var path = 'linkmap_pages/' + page.id + '/select_area_position';
39
+ var path = 'linkmap_pages/' + page.id + '/select_area_position' +
40
+ (options.areaIndex !== undefined ? '?area=' + options.areaIndex : '');
41
+
34
42
  pageflow.editor.navigate(path, {trigger: true});
35
43
  }).promise();
36
44
  };
@@ -8,33 +8,61 @@ pageflow.pageType.register('linkmap_page', _.extend({
8
8
  noHideTextOnSwipe: true,
9
9
 
10
10
  enhance: function(pageElement, configuration) {
11
+ var that = this;
12
+
11
13
  this.setupPanoramaBackground(pageElement, configuration);
12
14
  this.setupHoverImages(pageElement, configuration);
13
15
  this.setupVideoPlayer(pageElement);
14
16
 
17
+ this.contentAndBackground = pageElement.find('.linkmap_page');
15
18
  this.content = pageElement.find('.scroller');
16
19
  this.panorama = pageElement.find('.panorama');
17
20
 
21
+ this.contentAndBackground.linkmapAreaIndicators({
22
+ pageElement: pageElement
23
+ });
24
+
18
25
  this.content.linkmapPanorama({
26
+ disabled: this.isPanZoomEnabled(configuration),
27
+
19
28
  page: pageElement,
20
29
  panorama: function() {
21
30
  return pageElement.find('.panorama.active');
22
31
  },
23
32
  scroller: this.scroller,
33
+ areaIndicators: this.contentAndBackground.linkmapAreaIndicators('instance'),
24
34
  activeAreasSelector: '.linkmap_areas > .hover_area',
25
35
  limitScrolling: configuration.limit_scrolling,
26
36
  minScaling: pageflow.browser.has('mobile platform'),
27
37
  addEnvironment: configuration.add_environment,
28
- marginScrollingDisabled: configuration.margin_scrolling_disabled,
29
38
  startScrollPosition: this.getPanoramaStartScrollPosition(configuration)
30
39
  });
31
40
 
41
+ this.content.linkmapPanZoom({
42
+ disabled: !this.isPanZoomEnabled(configuration),
43
+
44
+ page: pageElement,
45
+ safeAreaWrapper: pageElement.find('.pan_zoom_safe_area_wrapper'),
46
+ panoramaWrapper: pageElement.find('.panorama_wrapper'),
47
+ panorama: function() {
48
+ return pageElement.find('.panorama.active');
49
+ },
50
+ areas: function() {
51
+ return pageElement.find('.hover_area');
52
+ },
53
+ scroller: this.scroller,
54
+ innerScrollerElement: pageElement.find('.linkmap'),
55
+ areaIndicators: this.contentAndBackground.linkmapAreaIndicators('instance'),
56
+ initialPosition: this.getPanoramaStartScrollPosition(configuration)
57
+ });
58
+
32
59
  this.content.linkmapLookaround({
33
60
  scroller: this.scroller,
34
- marginScrollingDisabled: configuration.margin_scrolling_disabled
61
+ marginScrollingDisabled: this.getMarginScrollingDisabled(configuration),
35
62
  });
36
63
 
37
- pageElement.find('.linkmap_page').linkmapScrollIndicators({
64
+ this.contentAndBackground.linkmapScrollIndicators({
65
+ disabled: this.isPanZoomEnabled(configuration),
38
66
  scroller: this.scroller
39
67
  });
40
68
 
@@ -44,19 +72,70 @@ pageflow.pageType.register('linkmap_page', _.extend({
44
72
 
45
73
  this.linkmapAreas = pageElement.find('.linkmap_areas');
46
74
  this.linkmapAreas.linkmap({
47
- hoverImageUrl: this.linkmapAreas.data('hoverImageUrl'),
48
- visitedImageUrl: this.linkmapAreas.data('visitedImageUrl'),
49
- maskSpriteUrlTemplate: this.linkmapAreas.data('maskSpriteUrlTemplate'),
50
- masksData: configuration.linkmap_masks,
75
+ disabled: this.isPanZoomEnabled(configuration),
76
+ colorMapFileId: configuration.linkmap_color_map_file_id,
51
77
 
52
78
  baseImage: function() {
53
79
  return pageElement.find('.panorama.active');
54
80
  },
55
81
 
82
+ parentScale: function() {
83
+ return that.content.linkmapPanZoom('getCurrentScale');
84
+ },
85
+
56
86
  hoverVideo: pageElement.find('.hover_video').linkmapHoverVideo('instance'),
57
87
  hoverVideoEnabled: configuration.background_type === 'hover_video'
58
88
  });
59
89
 
90
+ var carousel = !pageflow.navigationDirection || !pageflow.navigationDirection.isHorizontal();
91
+
92
+ this.mobileInfoBox = pageElement.find('.linkmap-paginator');
93
+ this.mobileInfoBox.linkmapPaginator({
94
+ disabled: !this.isPanZoomEnabled(configuration),
95
+ carousel: carousel,
96
+
97
+ scrollerEventListenerTarget: this.content,
98
+
99
+ change: function(currentPageIndex, pageCount) {
100
+ that.content.linkmapPanZoom('setBottomMarginFor', {
101
+ areaIndex: currentPageIndex - 1,
102
+ hiddenHeight: that.mobileInfoBox.linkmapPaginator('getCurrentHeight')
103
+ });
104
+
105
+ that.content.linkmapPanZoom('goToAreaByIndex', currentPageIndex - 1);
106
+
107
+ if (that.phoneEmulation() ||
108
+ !pageflow.slides.nextPageExists() ||
109
+ (carousel && currentPageIndex > 0) ||
110
+ (!carousel && currentPageIndex < pageCount - 1)) {
111
+ that.scrollIndicator.disable();
112
+ that.mobileInfoBox.linkmapPaginator('showDots');
113
+ }
114
+ else {
115
+ that.scrollIndicator.enable();
116
+ that.mobileInfoBox.linkmapPaginator('hideDots');
117
+ }
118
+
119
+ that.multiPlayer.fadeOutAndPause();
120
+ },
121
+
122
+ changing: function(options) {
123
+ that.content.linkmapPanZoom('transitionBottomMargin', {
124
+ from: {
125
+ areaIndex: options.currentPageIndex - 1,
126
+ hiddenHeight: options.currentHeight
127
+ },
128
+ to: {
129
+ areaIndex: options.destinationPageIndex - 1,
130
+ hiddenHeight: options.destinationHeight
131
+ },
132
+ progress: options.progress
133
+ });
134
+ }
135
+ });
136
+
137
+ pageElement.data('invertIndicator', false);
138
+
60
139
  this.setupPageLinkAreas(pageElement);
61
140
  this.setupExternalLinkAreas(pageElement);
62
141
  this.setupAudioFileAreas(pageElement, configuration);
@@ -175,7 +254,12 @@ pageflow.pageType.register('linkmap_page', _.extend({
175
254
 
176
255
  resize: function(pageElement, configuration) {
177
256
  this.content.linkmapPanorama('refresh');
257
+ this.content.linkmapPanZoom('refresh');
178
258
  this.linkmapAreas.linkmap('refresh');
259
+ this.mobileInfoBox.linkmapPaginator('refresh');
260
+
261
+ this.updateNavigationMode(configuration);
262
+ this.content.linkmapLookaround('update', this.getMarginScrollingDisabled(configuration));
179
263
  },
180
264
 
181
265
  prepare: function(pageElement, configuration) {
@@ -200,6 +284,18 @@ pageflow.pageType.register('linkmap_page', _.extend({
200
284
  });
201
285
  },
202
286
 
287
+ isPageChangeAllowed: function(pageElement, configuration, options) {
288
+ if (this.isPanZoomEnabled(configuration) &&
289
+ pageflow.navigationDirection && pageflow.navigationDirection.isHorizontal() &&
290
+ ((options.type == 'bumpnext' && !this.mobileInfoBox.linkmapPaginator('isOnLastPage')) ||
291
+ (options.type == 'bumpback' && !this.mobileInfoBox.linkmapPaginator('isOnFirstPage')))) {
292
+ return false;
293
+ }
294
+ else {
295
+ return true;
296
+ }
297
+ },
298
+
203
299
  preload: function(pageElement, configuration) {
204
300
  return pageflow.preload.backgroundImage(pageElement.find('.background_image'));
205
301
  },
@@ -210,15 +306,22 @@ pageflow.pageType.register('linkmap_page', _.extend({
210
306
  }
211
307
 
212
308
  this.content.linkmapPanorama('refresh');
309
+ this.content.linkmapPanZoom('refresh');
213
310
  this.linkmapAreas.linkmap('refresh');
311
+ this.mobileInfoBox.linkmapPaginator('refresh');
214
312
 
215
313
  this.content.linkmapLookaround('activate');
216
314
  this.content.linkmapPanorama('resetScrollPosition');
315
+ this.mobileInfoBox.linkmapPaginator('initScrollPosition');
217
316
 
218
317
  this.content.linkmapPanorama('resetAreaHighlighting');
219
318
  },
220
319
 
221
320
  activated: function(pageElement, configuration) {
321
+ if (this.isPanZoomEnabled(configuration)) {
322
+ this.scrollIndicator.disable();
323
+ }
324
+
222
325
  this.content.linkmapPanorama('highlightAreas');
223
326
  },
224
327
 
@@ -229,12 +332,18 @@ pageflow.pageType.register('linkmap_page', _.extend({
229
332
  },
230
333
 
231
334
  deactivated: function(pageElement, configuration) {
335
+ this.mobileInfoBox.linkmapPaginator('showDots');
336
+
232
337
  if (this.isVideoEnabled(configuration)) {
233
338
  this.pauseVideo(configuration);
234
339
  }
235
340
  },
236
341
 
237
342
  update: function(pageElement, configuration) {
343
+ pageElement.find('.linkmap_page').toggleClass('hide_overlay_boxes',
344
+ configuration.get('mobile_panorama_navigation') === 'pan_zoom' &&
345
+ !!configuration.get('hide_linkmap_overlay_boxes'));
346
+
238
347
  this.setupPanoramaBackground(pageElement, configuration.attributes);
239
348
  this.updateCommonPageCssClasses(pageElement, configuration);
240
349
 
@@ -244,18 +353,10 @@ pageflow.pageType.register('linkmap_page', _.extend({
244
353
  var minScaling = false;
245
354
 
246
355
  this.linkmapAreas.linkmap('option',
247
- 'hoverImageUrl',
248
- configuration.getImageFileUrl('hover_image_id', {
249
- styleGroup: 'panorama'
250
- }));
251
- this.linkmapAreas.linkmap('option',
252
- 'visitedImageUrl',
253
- configuration.getImageFileUrl('visited_image_id', {
254
- styleGroup: 'panorama'
255
- }));
256
- this.linkmapAreas.linkmap('option',
257
- 'masksData',
258
- configuration.get('linkmap_masks'));
356
+ 'colorMapFileId',
357
+ configuration.linkmapReadyColorMapFileId());
358
+
359
+ this.updateNavigationMode(configuration.attributes);
259
360
 
260
361
  this.content.linkmapPanorama('update',
261
362
  configuration.get('add_environment'),
@@ -263,11 +364,15 @@ pageflow.pageType.register('linkmap_page', _.extend({
263
364
  this.getPanoramaStartScrollPosition(configuration.attributes),
264
365
  minScaling);
265
366
 
367
+ this.content.linkmapPanZoom('update', {
368
+ initialPosition: this.getPanoramaStartScrollPosition(configuration.attributes)
369
+ });
370
+
266
371
  this.updateScaledOnPhoneFlags(configuration.page,
267
372
  this.content.linkmapPanorama('instance'));
268
373
 
269
374
  this.content.linkmapLookaround('update',
270
- configuration.get('margin_scrolling_disabled'));
375
+ this.getMarginScrollingDisabled(configuration.attributes));
271
376
  this.setupHoverImages(pageElement, configuration.attributes);
272
377
  this.updateVideoPlayState(configuration);
273
378
 
@@ -322,6 +427,36 @@ pageflow.pageType.register('linkmap_page', _.extend({
322
427
  configuration.background_type === 'hover_video';
323
428
  },
324
429
 
430
+ updateNavigationMode: function(configuration) {
431
+ if (this.isPanZoomEnabled(configuration)) {
432
+ this.linkmapAreas.linkmap('disable');
433
+ this.content.linkmapPanorama('disable');
434
+ this.contentAndBackground.linkmapScrollIndicators('disable');
435
+ this.content.linkmapPanZoom('enable');
436
+ this.mobileInfoBox.linkmapPaginator('enable');
437
+ }
438
+ else {
439
+ this.content.linkmapPanZoom('disable');
440
+ this.mobileInfoBox.linkmapPaginator('disable');
441
+ this.contentAndBackground.linkmapScrollIndicators('enable');
442
+ this.content.linkmapPanorama('enable');
443
+ this.linkmapAreas.linkmap('enable');
444
+ }
445
+ },
446
+
447
+ isPanZoomEnabled: function(configuration) {
448
+ return (pageflow.browser.has('phone platform') || this.phoneEmulation()) &&
449
+ configuration.mobile_panorama_navigation === 'pan_zoom';
450
+ },
451
+
452
+ getMarginScrollingDisabled: function(configuration) {
453
+ return configuration.margin_scrolling_disabled || this.phoneEmulation();
454
+ },
455
+
456
+ phoneEmulation: function() {
457
+ return !!$('#entry_preview > .emulation_mode_phone').length;
458
+ },
459
+
325
460
  playVideo: function(configuration) {
326
461
  var that = this;
327
462
 
@@ -38,7 +38,10 @@
38
38
 
39
39
  play: function(options) {
40
40
  var video = this.options.video;
41
- var position = options.area.position();
41
+ var position = {
42
+ left: options.area.prop('offsetLeft'),
43
+ top: options.area.prop('offsetTop')
44
+ };
42
45
 
43
46
  video
44
47
  .width(options.baseImage.width())
@@ -3,16 +3,17 @@ $.fn.linkmapAreaContains = function(position) {
3
3
  var mask = area.data('mask');
4
4
 
5
5
  if (mask) {
6
- return mask.contains(position.leftInPercent / 100, position.topInPercent / 100);
6
+ return mask.contains(position.leftInPercent, position.topInPercent);
7
7
  }
8
8
  else {
9
- var areaPosition = area.position();
9
+ var areaLeft = parseFloat(area.css('left'));
10
+ var areaTop = parseFloat(area.css('top'));
10
11
  var areaWidth = area.width();
11
12
  var areaHeight = area.height();
12
13
 
13
- return position.leftInPixel >= areaPosition.left &&
14
- position.leftInPixel < areaPosition.left + areaWidth &&
15
- position.topInPixel >= areaPosition.top &&
16
- position.topInPixel < areaPosition.top + areaHeight;
14
+ return position.leftInPixel >= areaLeft &&
15
+ position.leftInPixel < areaLeft + areaWidth &&
16
+ position.topInPixel >= areaTop &&
17
+ position.topInPixel < areaTop + areaHeight;
17
18
  }
18
19
  };
@@ -0,0 +1,16 @@
1
+ $.fn.linkmapAreaSetMask = function(options) {
2
+ this.each(function() {
3
+ var area = $(this);
4
+ var colorMapComponent = options.colorMap.componentByPermaId(area.attr('data-mask-perma-id'));
5
+
6
+ if (colorMapComponent) {
7
+ area.data('mask', new pageflow.linkmapPage.Mask({
8
+ colorMapComponentPermaId: colorMapComponent.permaId,
9
+ colorMap: options.colorMap
10
+ }));
11
+ }
12
+ else {
13
+ area.data('mask', null);
14
+ }
15
+ });
16
+ };
@@ -1,162 +1,103 @@
1
1
  pageflow.linkmapPage.ColorMap = (function() {
2
- function ColorMap(width, height, components) {
3
- this.width = width;
4
- this.height = height;
5
- this.components = components;
6
-
7
- this.sumOfComponentWidths = function() {
8
- return _(components).reduce(function(result, component) {
9
- return result + component.boundingBox.width;
10
- }, 0);
2
+ function ColorMapComponent(attributes, options) {
3
+ var colorMapWidth = options.colorMapWidth;
4
+ var colorMapHeight = options.colorMapHeight;
5
+ var colorMapSprite = options.colorMapSprite;
6
+
7
+ this.color = attributes.color;
8
+ this.permaId = options.colorMapId + ':' + attributes.color;
9
+
10
+ this.draw = function(context, width) {
11
+ var scale = width / attributes.width;
12
+
13
+ colorMapSprite.draw(context,
14
+ attributes.sprite_offset,
15
+ 0,
16
+ attributes.width,
17
+ attributes.height,
18
+ 0,
19
+ 0,
20
+ attributes.width * scale,
21
+ attributes.height * scale);
11
22
  };
12
23
 
13
- this.maxComponentHeight = function() {
14
- return _(components).reduce(function(result, rect) {
15
- return Math.max(result, rect.boundingBox.height);
16
- }, 0);
17
- };
18
-
19
- this.serialize = function() {
24
+ this.areaAttributes = function() {
20
25
  return {
21
- w: this.width,
22
- h: this.height,
23
- c: _(components).map(function(component) {
24
- return {
25
- c: component.color,
26
- l: component.boundingBox.left,
27
- t: component.boundingBox.top,
28
- w: component.boundingBox.width,
29
- h: component.boundingBox.height
30
- };
31
- })
26
+ mask_perma_id: this.permaId,
27
+ top: attributes.top / colorMapHeight * 100.0,
28
+ left: attributes.left / colorMapWidth * 100.0,
29
+ height: attributes.height / colorMapHeight * 100.0,
30
+ width: attributes.width / colorMapWidth * 100.0
32
31
  };
33
32
  };
34
- }
35
33
 
36
- ColorMap.deserialize = function(data) {
37
- return new ColorMap(
38
- data.w,
39
- data.h,
40
- _(data.c).map(function(item) {
41
- return {
42
- color: item.c,
43
- boundingBox: {
44
- left: item.l,
45
- top: item.t,
46
- width: item.w,
47
- height: item.h,
48
- right: item.l + item.w,
49
- bottom: item.t + item.h
50
- }
51
- };
52
- })
53
- );
54
- };
34
+ this.contains = function(xInPercent, yInPercent) {
35
+ var x = xInPercent * colorMapWidth / 100;
36
+ var y = yInPercent * colorMapHeight / 100;
37
+
38
+ return inBoundingBox(x, y) &&
39
+ colorMapSprite.nonTransparentAt(
40
+ x - attributes.left + attributes.sprite_offset,
41
+ y - attributes.top
42
+ );
43
+ };
55
44
 
56
- ColorMap.fromImageData = function(imageData) {
57
- var width = imageData.width;
58
- var height = imageData.height;
59
-
60
- var data = imageData.get(0, 0, width, height).data;
61
- var i, key, component;
62
-
63
- var componentsByKey = {};
64
- var components = [];
65
-
66
- var currentStreakKey, currentStreakLength;
67
-
68
- for (var y = 0; y < height; y++) {
69
- currentStreakKey = null;
70
- currentStreakLength = 0;
71
-
72
- for (var x = 0; x < width; x++) {
73
- i = (y * width + x) * 4;
74
-
75
- if (!blackOrTransparent(data, i)) {
76
- key = [data[i], data[i + 1], data[i + 2]].join('-');
77
- component = componentsByKey[key];
78
-
79
- if (currentStreakKey === key && sameColorAboveAndBelow(data, i, width)) {
80
- currentStreakLength += 1;
81
- }
82
- else {
83
- currentStreakKey = key;
84
- currentStreakLength = 1;
85
- }
86
-
87
- if (!component) {
88
- component = componentsByKey[key] = {
89
- color: [data[i], data[i + 1], data[i + 2]],
90
- left: x,
91
- top: y,
92
- right: x + 1,
93
- bottom: y + 1,
94
- longestStreak: currentStreakLength
95
- };
96
-
97
- components.push(component);
98
- }
99
- else {
100
- component.left = Math.min(component.left, x);
101
- component.top = Math.min(component.top, y);
102
- component.right = Math.max(component.right, x + 1);
103
- component.bottom = Math.max(component.bottom, y + 1);
104
- component.longestStreak = Math.max(component.longestStreak, currentStreakLength);
105
- }
106
- }
107
- }
45
+ function inBoundingBox(x, y) {
46
+ return x > attributes.left &&
47
+ x < attributes.left + attributes.width &&
48
+ y >= attributes.top &&
49
+ y < attributes.top + attributes.height;
108
50
  }
51
+ }
109
52
 
110
- components = _(components).select(function(component) {
111
- return component.longestStreak > 7;
112
- });
53
+ function ColorMap(attributes, sprite) {
54
+ var components = _(attributes.components).map(function(componentAttributes) {
55
+ return new ColorMapComponent(componentAttributes, {
56
+ colorMapId: attributes.id,
57
+ colorMapWidth: attributes.width,
58
+ colorMapHeight: attributes.height,
59
+ colorMapSprite: sprite
60
+ });
61
+ }, this);
62
+
63
+ this.components = function() {
64
+ return components;
65
+ };
113
66
 
114
- if (components.length === 0) {
115
- throw noComponentsError();
116
- }
67
+ this.componentFromPoint = function(xInPercent, yInPercent) {
68
+ return _(components).find(function(component) {
69
+ return component.contains(xInPercent, yInPercent);
70
+ });
71
+ };
117
72
 
118
- return new ColorMap(width, height, _(components).map(function(component) {
119
- return {
120
- color: component.color,
121
- boundingBox: {
122
- left: component.left,
123
- top: component.top,
124
- right: component.right,
125
- bottom: component.bottom,
126
- width: component.right - component.left,
127
- height: component.bottom - component.top
128
- }
129
- };
130
- }));
131
- };
73
+ this.componentByPermaId = function(permaId) {
74
+ return _(components).find(function(component) {
75
+ return component.permaId == permaId;
76
+ });
77
+ };
132
78
 
133
- function blackOrTransparent(data, i) {
134
- return (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0) ||
135
- data[i + 3] === 0;
136
- }
137
- function sameColorAboveAndBelow(data, i, width) {
138
- var above = i - width * 4;
139
- var below = i + width * 4;
140
-
141
- return above >= 0 &&
142
- below < data.length &&
143
- sameColor(data, i, above) &&
144
- sameColor(data, i, below);
79
+ this.previewUrl = function() {
80
+ return attributes.url;
81
+ };
145
82
  }
146
83
 
147
- function sameColor(data, i, j) {
148
- return data[i] === data[j] &&
149
- data[i + 1] === data[j + 1] &&
150
- data[i + 2] === data[j + 2] &&
151
- data[i + 3] === data[j + 3];
152
- }
84
+ ColorMap.empty = new ColorMap({
85
+ components: [],
86
+ width: 0,
87
+ height: 0
88
+ });
153
89
 
154
- function noComponentsError() {
155
- var error = new Error('No big enough components detected.');
156
- error.i18nKey = 'pageflow.linkmap_page.errors.no_big_enough_color_map_components';
90
+ ColorMap.load = function(id) {
91
+ var colorMapFile = pageflow.entryData.getFile('pageflow_linkmap_page_color_map_files', id);
157
92
 
158
- return error;
159
- }
93
+ if (!colorMapFile) {
94
+ return $.when(ColorMap.empty);
95
+ }
96
+
97
+ return pageflow.linkmapPage.ImageData.load(colorMapFile.sprite_url).then(function(sprite) {
98
+ return new ColorMap(colorMapFile, sprite);
99
+ });
100
+ };
160
101
 
161
102
  return ColorMap;
162
103
  }());