pageflow-linkmap-page 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -26
- data/Gemfile +2 -7
- data/app/assets/javascript/pageflow/linkmap_page/editor/models/page_configuration_mixin.js +3 -0
- data/app/assets/javascript/pageflow/linkmap_page/editor/models/stored_mask_sprite.js +21 -9
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap.js +1 -13
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/area_redraw.js +6 -1
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/color_map.js +47 -7
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/image_data.js +17 -1
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap/remote_image.js +46 -30
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_panorama.js +49 -9
- data/app/assets/javascript/pageflow/linkmap_page/widgets/linkmap_panorama/get_panorama_size.js +1 -1
- data/app/assets/stylesheets/pageflow/linkmap_page.scss +27 -25
- data/app/assets/stylesheets/pageflow/linkmap_page/themes/default.scss +59 -31
- data/app/helpers/pageflow/linkmap_page/areas_helper.rb +1 -1
- data/app/views/pageflow/linkmap_page/page.html.erb +6 -0
- data/config/locales/de.yml +6 -4
- data/config/locales/en.yml +6 -4
- data/lib/pageflow/linkmap_page/version.rb +1 -1
- data/pageflow-linkmap-page.gemspec +1 -0
- data/spec/controllers/pageflow/linkmap_page/mask_sprites_controller_spec.rb +4 -4
- data/spec/helpers/pageflow/linkmap_page/areas_helper_spec.rb +10 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b73e3d49c82b5876fce90056bcb4fe58771fc34
|
4
|
+
data.tar.gz: 6d38604747a162226fc45fd9b2b6c1d56c596ea8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a18d92640f24a2539bd1d4f4c9742d7549cdc5c86e56cb7087be871816787f28568e6fb291fdcdee800ff4e0e4cfea87e415127540e8e83ffb9609d9caee176
|
7
|
+
data.tar.gz: 84e8646c2e3ca811472f92adc70b6f2df67a3146e71775003aab7b298ce1e38dd95368f0fa9f1239baf41efe244dfc0959825f9561899874802f4e0c5a018be7
|
data/CHANGELOG.md
CHANGED
@@ -1,34 +1,20 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
### Version 1.
|
3
|
+
### Version 1.1.0
|
4
4
|
|
5
|
-
2017-
|
5
|
+
2017-10-09
|
6
6
|
|
7
|
-
[Compare changes](https://github.com/codevise/pageflow-linkmap-page/compare/0-
|
7
|
+
[Compare changes](https://github.com/codevise/pageflow-linkmap-page/compare/1-0-stable...v1.1.0)
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
$ rake pageflow_linkmap_page:install:migrations
|
19
|
-
$ rake db:migrate
|
20
|
-
|
21
|
-
##### Features
|
22
|
-
|
23
|
-
- Support mask image for non rectangular areas
|
24
|
-
([#22](https://github.com/codevise/pageflow-linkmap-page/pull/22))
|
25
|
-
- Add support for pageflow-external-links 1.x
|
26
|
-
([#26](https://github.com/codevise/pageflow-linkmap-page/pull/26))
|
27
|
-
- Rename the last `css.scss` files
|
28
|
-
([#25](https://github.com/codevise/pageflow-linkmap-page/pull/25))
|
29
|
-
- Require pageflow 12
|
30
|
-
([#24](https://github.com/codevise/pageflow-linkmap-page/pull/24))
|
9
|
+
- Fix hover video variant in published entry
|
10
|
+
([#29](https://github.com/codevise/pageflow-linkmap-page/pull/29))
|
11
|
+
- Make mask image url template generation more robust
|
12
|
+
([#30](https://github.com/codevise/pageflow-linkmap-page/pull/30))
|
13
|
+
- Improve mask features of hotspot page
|
14
|
+
([#28](https://github.com/codevise/pageflow-linkmap-page/pull/28))
|
15
|
+
- Ensure pageflow 12 is used in tests
|
16
|
+
([#27](https://github.com/codevise/pageflow-linkmap-page/pull/27))
|
31
17
|
|
32
18
|
See
|
33
|
-
[0-
|
19
|
+
[1-0-stable branch](https://github.com/codevise/pageflow-linkmap-page/blob/1-0-stable/CHANGELOG.md)
|
34
20
|
for previous changes.
|
data/Gemfile
CHANGED
@@ -5,10 +5,5 @@ gemspec
|
|
5
5
|
|
6
6
|
gem 'state_machine', git: 'https://github.com/codevise/state_machine.git'
|
7
7
|
|
8
|
-
gem '
|
9
|
-
gem '
|
10
|
-
|
11
|
-
gem 'teaspoon', git: 'https://github.com/modeset/teaspoon'
|
12
|
-
|
13
|
-
gem "spring-commands-rspec", group: :development
|
14
|
-
gem "spring-commands-teaspoon", group: :development
|
8
|
+
gem 'spring-commands-rspec', group: :development
|
9
|
+
gem 'spring-commands-teaspoon', group: :development
|
@@ -63,8 +63,10 @@
|
|
63
63
|
}
|
64
64
|
|
65
65
|
function generateMaskSprite(configuration, imageFile) {
|
66
|
+
// panorama_mask_url is available in Pageflow >= 12.1
|
66
67
|
pageflow.linkmapPage.StoredMaskSprite
|
67
68
|
.findOrCreateForImageFileId(imageFile.id,
|
69
|
+
imageFile.get('panorama_mask_url') ||
|
68
70
|
imageFile.get('panorama_url'))
|
69
71
|
.then(
|
70
72
|
function(masks) {
|
@@ -78,6 +80,7 @@
|
|
78
80
|
alert(I18n.t(error.i18nKey));
|
79
81
|
}
|
80
82
|
else {
|
83
|
+
alert(I18n.t('pageflow.linkmap_page.errors.mask_image_failed'));
|
81
84
|
throw(error);
|
82
85
|
}
|
83
86
|
}
|
@@ -10,16 +10,28 @@ pageflow.linkmapPage.StoredMaskSprite = Backbone.Model.extend({
|
|
10
10
|
pageflow.linkmapPage.StoredMaskSprite.findOrCreateForImageFileId = function(imageFileId, imageFileUrl) {
|
11
11
|
return new $.Deferred(function(deferred) {
|
12
12
|
pageflow.linkmapPage.Masks.loadColorMapImage(imageFileUrl).then(function(masks) {
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
try {
|
14
|
+
var storedMaskSprite = new pageflow.linkmapPage.StoredMaskSprite({
|
15
|
+
image_file_id: imageFileId,
|
16
|
+
attachment: masks.getSpriteDataUrl()
|
17
|
+
});
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
storedMaskSprite.save(null, {
|
20
|
+
success: function() {
|
21
|
+
deferred.resolve(masks.serialize(storedMaskSprite.id));
|
22
|
+
},
|
23
|
+
|
24
|
+
error: function() {
|
25
|
+
deferred.reject({
|
26
|
+
message: 'Error saving mask sprite to the server.',
|
27
|
+
i18nKey: 'pageflow.linkmap_page.errors.saving_mask_image_failed'
|
28
|
+
});
|
29
|
+
}
|
30
|
+
});
|
31
|
+
}
|
32
|
+
catch (e) {
|
33
|
+
deferred.reject(e);
|
34
|
+
}
|
23
35
|
}, deferred.reject);
|
24
36
|
}).promise();
|
25
37
|
};
|
@@ -36,7 +36,7 @@
|
|
36
36
|
var area = widget.areaAt(widget.positionFromEvent(event));
|
37
37
|
|
38
38
|
if (area.length) {
|
39
|
-
area.first().trigger('linkmapareaclick');
|
39
|
+
area.first().trigger($.Event('linkmapareaclick', {originalEvent: event}));
|
40
40
|
}
|
41
41
|
else {
|
42
42
|
widget._trigger('backgroundclick');
|
@@ -45,18 +45,6 @@
|
|
45
45
|
return false;
|
46
46
|
});
|
47
47
|
|
48
|
-
this.element.on('touchstart', function(event) {
|
49
|
-
var area = widget.areaAt(widget.positionFromEvent(event.originalEvent.touches[0]));
|
50
|
-
|
51
|
-
var areaEvent = jQuery.Event('linkmapareatouchstart');
|
52
|
-
|
53
|
-
area.first().trigger(areaEvent);
|
54
|
-
|
55
|
-
if (areaEvent.isDefaultPrevented()) {
|
56
|
-
event.preventDefault();
|
57
|
-
}
|
58
|
-
});
|
59
|
-
|
60
48
|
this.element.on('mousemove mouseleave', function(event) {
|
61
49
|
widget.updateHoverStates(event);
|
62
50
|
});
|
@@ -6,7 +6,12 @@ $.fn.linkmapAreaRedraw = function(options) {
|
|
6
6
|
var mask = options.masks && options.masks.findByPermaId(area.attr('data-mask-id'));
|
7
7
|
area.data('mask', mask || null);
|
8
8
|
|
9
|
-
var canvas = area.find(options.target)[0];
|
9
|
+
var canvas = area.find('canvas').filter(options.target)[0];
|
10
|
+
|
11
|
+
if (!canvas) {
|
12
|
+
return;
|
13
|
+
}
|
14
|
+
|
10
15
|
var context = canvas.getContext('2d');
|
11
16
|
|
12
17
|
if (options.image) {
|
@@ -63,21 +63,35 @@ pageflow.linkmapPage.ColorMap = (function() {
|
|
63
63
|
var componentsByKey = {};
|
64
64
|
var components = [];
|
65
65
|
|
66
|
+
var currentStreakKey, currentStreakLength;
|
67
|
+
|
66
68
|
for (var y = 0; y < height; y++) {
|
69
|
+
currentStreakKey = null;
|
70
|
+
currentStreakLength = 0;
|
71
|
+
|
67
72
|
for (var x = 0; x < width; x++) {
|
68
73
|
i = (y * width + x) * 4;
|
69
74
|
|
70
|
-
if (data
|
75
|
+
if (!blackOrTransparent(data, i)) {
|
71
76
|
key = [data[i], data[i + 1], data[i + 2]].join('-');
|
72
77
|
component = componentsByKey[key];
|
73
78
|
|
79
|
+
if (currentStreakKey === key && sameColorAboveAndBelow(data, i, width)) {
|
80
|
+
currentStreakLength += 1;
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
currentStreakKey = key;
|
84
|
+
currentStreakLength = 1;
|
85
|
+
}
|
86
|
+
|
74
87
|
if (!component) {
|
75
88
|
component = componentsByKey[key] = {
|
76
89
|
color: [data[i], data[i + 1], data[i + 2]],
|
77
90
|
left: x,
|
78
91
|
top: y,
|
79
92
|
right: x + 1,
|
80
|
-
bottom: y + 1
|
93
|
+
bottom: y + 1,
|
94
|
+
longestStreak: currentStreakLength
|
81
95
|
};
|
82
96
|
|
83
97
|
components.push(component);
|
@@ -87,13 +101,18 @@ pageflow.linkmapPage.ColorMap = (function() {
|
|
87
101
|
component.top = Math.min(component.top, y);
|
88
102
|
component.right = Math.max(component.right, x + 1);
|
89
103
|
component.bottom = Math.max(component.bottom, y + 1);
|
104
|
+
component.longestStreak = Math.max(component.longestStreak, currentStreakLength);
|
90
105
|
}
|
91
106
|
}
|
92
107
|
}
|
93
108
|
}
|
94
109
|
|
95
|
-
|
96
|
-
|
110
|
+
components = _(components).select(function(component) {
|
111
|
+
return component.longestStreak > 7;
|
112
|
+
});
|
113
|
+
|
114
|
+
if (components.length === 0) {
|
115
|
+
throw noComponentsError();
|
97
116
|
}
|
98
117
|
|
99
118
|
return new ColorMap(width, height, _(components).map(function(component) {
|
@@ -111,9 +130,30 @@ pageflow.linkmapPage.ColorMap = (function() {
|
|
111
130
|
}));
|
112
131
|
};
|
113
132
|
|
114
|
-
function
|
115
|
-
|
116
|
-
|
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);
|
145
|
+
}
|
146
|
+
|
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
|
+
}
|
153
|
+
|
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';
|
117
157
|
|
118
158
|
return error;
|
119
159
|
}
|
@@ -27,6 +27,9 @@ pageflow.linkmapPage.ImageData = (function() {
|
|
27
27
|
|
28
28
|
data[i + 3] = 0;
|
29
29
|
}
|
30
|
+
else {
|
31
|
+
data[i + 3] = 255;
|
32
|
+
}
|
30
33
|
}
|
31
34
|
|
32
35
|
destinationContext.putImageData(imageData, destinationX, destinationY);
|
@@ -42,10 +45,23 @@ pageflow.linkmapPage.ImageData = (function() {
|
|
42
45
|
};
|
43
46
|
|
44
47
|
this.toDataURL = function() {
|
45
|
-
|
48
|
+
var result = canvas.toDataURL();
|
49
|
+
|
50
|
+
if (!result.match(/^data:image/)) {
|
51
|
+
throw new invalidImageDataUrl();
|
52
|
+
}
|
53
|
+
|
54
|
+
return result;
|
46
55
|
};
|
47
56
|
}
|
48
57
|
|
58
|
+
function invalidImageDataUrl() {
|
59
|
+
var error = new Error('Invalid data url from canvas.');
|
60
|
+
error.i18nKey = 'pageflow.linkmap_page.errors.invalid_image_data';
|
61
|
+
|
62
|
+
return error;
|
63
|
+
}
|
64
|
+
|
49
65
|
ImageData.load = function(url) {
|
50
66
|
return pageflow.linkmapPage.RemoteImage.load(url).then(function(image) {
|
51
67
|
var imageData = new ImageData(image.width(), image.height());
|
@@ -1,38 +1,54 @@
|
|
1
|
-
pageflow.linkmapPage.RemoteImage = function(
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
pageflow.linkmapPage.RemoteImage = (function() {
|
2
|
+
function RemoteImage(url, image) {
|
3
|
+
this.width = function() {
|
4
|
+
return image.width;
|
5
|
+
};
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
this.height = function() {
|
8
|
+
return image.height;
|
9
|
+
};
|
10
|
+
|
11
|
+
this.draw = function(canvas, options) {
|
12
|
+
options = options || {};
|
13
|
+
var context = canvas.getContext('2d');
|
14
|
+
|
15
|
+
if (options.disableImageSmoothing) {
|
16
|
+
context.imageSmoothingEnabled = false;
|
17
|
+
}
|
18
|
+
|
19
|
+
context.drawImage(image,
|
20
|
+
0,
|
21
|
+
0,
|
22
|
+
canvas.width,
|
23
|
+
canvas.height);
|
24
|
+
};
|
25
|
+
}
|
26
|
+
|
27
|
+
RemoteImage.load = function(url) {
|
28
|
+
return new $.Deferred(function(deferred) {
|
29
|
+
var image = new Image();
|
9
30
|
|
10
|
-
|
11
|
-
|
12
|
-
|
31
|
+
image.onload = onLoad;
|
32
|
+
image.onerror = onError;
|
33
|
+
image.crossOrigin = 'Anonymous';
|
34
|
+
image.src = url;
|
13
35
|
|
14
|
-
|
15
|
-
|
16
|
-
|
36
|
+
function onLoad() {
|
37
|
+
deferred.resolve(new pageflow.linkmapPage.RemoteImage(url, image));
|
38
|
+
}
|
17
39
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
canvas.height);
|
40
|
+
function onError() {
|
41
|
+
deferred.reject(loadError(url));
|
42
|
+
}
|
43
|
+
}).promise();
|
23
44
|
};
|
24
|
-
};
|
25
45
|
|
26
|
-
|
27
|
-
return new $.Deferred(function(deferred) {
|
28
|
-
var image = new Image();
|
46
|
+
return RemoteImage;
|
29
47
|
|
30
|
-
|
31
|
-
|
32
|
-
|
48
|
+
function loadError(url) {
|
49
|
+
var error = new Error('Error while loading ' + url + '.');
|
50
|
+
error.i18nKey = 'pageflow.linkmap_page.errors.loading_remote_image_failed';
|
33
51
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
}).promise();
|
38
|
-
};
|
52
|
+
return error;
|
53
|
+
}
|
54
|
+
}());
|
@@ -22,6 +22,10 @@
|
|
22
22
|
this.overlayTitle = pageElement.find('.description_overlay .link_title');
|
23
23
|
this.overlayDescription = pageElement.find('.description_overlay .link_description');
|
24
24
|
|
25
|
+
this.touchIndicator = pageElement.find('.touch_indicator');
|
26
|
+
this.externalLinkLoadingIndicator = pageElement.find('.external_link_loading_indicator');
|
27
|
+
this.globalIndicators = this.touchIndicator.add(this.externalLinkLoadingIndicator);
|
28
|
+
|
25
29
|
this.startScrollPosition = _.clone(this.options.startScrollPosition);
|
26
30
|
|
27
31
|
this.currentScrollPosition = null;
|
@@ -48,6 +52,7 @@
|
|
48
52
|
pageElement.on('click linkmapbackgroundclick', function() {
|
49
53
|
that.overlayBox.removeClass('active');
|
50
54
|
that.activeAreas.removeClass('hover hover_mobile');
|
55
|
+
that.globalIndicators.hide();
|
51
56
|
});
|
52
57
|
|
53
58
|
$('body').on('linkmaparealeave', '.hover_area', function() {
|
@@ -61,8 +66,8 @@
|
|
61
66
|
that.activeAreas.each(function() {
|
62
67
|
var area = $(this);
|
63
68
|
|
64
|
-
|
65
|
-
|
69
|
+
area.on('linkmapareaclick', function(event) {
|
70
|
+
if (pageflow.browser.has('mobile platform')) {
|
66
71
|
if (area.hasClass('hover_mobile')) {
|
67
72
|
that.activeAreas.removeClass('active');
|
68
73
|
area.addClass('active');
|
@@ -72,16 +77,23 @@
|
|
72
77
|
area.addClass('hover hover_mobile');
|
73
78
|
|
74
79
|
positionOverlay($(this));
|
80
|
+
|
81
|
+
if (!area.hasClass('dynamic_marker')) {
|
82
|
+
displayTouchIndicator(event.originalEvent);
|
83
|
+
}
|
84
|
+
|
75
85
|
return false;
|
76
86
|
}
|
77
|
-
}
|
78
|
-
|
79
|
-
else {
|
80
|
-
area.on('linkmapareaclick', function(e) {
|
87
|
+
}
|
88
|
+
else {
|
81
89
|
that.activeAreas.removeClass('active');
|
82
90
|
area.addClass('active');
|
83
|
-
}
|
84
|
-
|
91
|
+
}
|
92
|
+
|
93
|
+
if (!area.hasClass('dynamic_marker') && area.hasClass('external_site_area')) {
|
94
|
+
displayExternalLinkLoadingIndicator(event.originalEvent);
|
95
|
+
}
|
96
|
+
});
|
85
97
|
});
|
86
98
|
|
87
99
|
var positionOverlay = function(area) {
|
@@ -154,7 +166,35 @@
|
|
154
166
|
that.overlayInnerBox.css('top', '0px');
|
155
167
|
}
|
156
168
|
}
|
157
|
-
}
|
169
|
+
};
|
170
|
+
|
171
|
+
var displayExternalLinkLoadingIndicator = function(event) {
|
172
|
+
positionGlobalIndicator(that.externalLinkLoadingIndicator, event);
|
173
|
+
that.externalLinkLoadingIndicator.show();
|
174
|
+
};
|
175
|
+
|
176
|
+
var displayTouchIndicator = function(event) {
|
177
|
+
positionGlobalIndicator(that.touchIndicator, event);
|
178
|
+
animateTouchIndicator();
|
179
|
+
};
|
180
|
+
|
181
|
+
var animateTouchIndicator = function() {
|
182
|
+
that.touchIndicator.hide();
|
183
|
+
|
184
|
+
setTimeout(function() {
|
185
|
+
that.touchIndicator.show();
|
186
|
+
}, 500);
|
187
|
+
};
|
188
|
+
|
189
|
+
var positionGlobalIndicator = function(indicator, event) {
|
190
|
+
var parentClientRect = that.panoramaWrapper[0].getBoundingClientRect();
|
191
|
+
var touch = event.touches ? event.touches[0] : event;
|
192
|
+
|
193
|
+
indicator.css({
|
194
|
+
left: touch.clientX - parentClientRect.left,
|
195
|
+
top: touch.clientY - parentClientRect.top
|
196
|
+
});
|
197
|
+
};
|
158
198
|
|
159
199
|
this.refresh();
|
160
200
|
},
|
@@ -220,44 +220,46 @@
|
|
220
220
|
}
|
221
221
|
}
|
222
222
|
|
223
|
-
.
|
223
|
+
.external_link_loading_indicator,
|
224
|
+
.external_site_area .inline_loading_spinner {
|
225
|
+
position: absolute;
|
226
|
+
height: 100%;
|
227
|
+
width: 50%;
|
228
|
+
top: 0;
|
229
|
+
left: 0;
|
230
|
+
overflow: hidden;
|
224
231
|
|
225
|
-
.
|
232
|
+
.circle_inner {
|
226
233
|
position: absolute;
|
227
234
|
height: 100%;
|
228
|
-
width:
|
235
|
+
width: 100%;
|
229
236
|
top: 0;
|
230
237
|
left: 0;
|
231
238
|
overflow: hidden;
|
239
|
+
@include transform(rotate(0));
|
232
240
|
|
233
|
-
.
|
241
|
+
.circle_innerst {
|
234
242
|
position: absolute;
|
235
243
|
height: 100%;
|
236
|
-
width:
|
244
|
+
width: 200%;
|
237
245
|
top: 0;
|
238
246
|
left: 0;
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
.circle_innerst {
|
243
|
-
position: absolute;
|
244
|
-
height: 100%;
|
245
|
-
width: 200%;
|
246
|
-
top: 0;
|
247
|
-
left: 0;
|
248
|
-
border: 3px solid green;
|
249
|
-
box-sizing: border-box;
|
250
|
-
border-radius: 50%;
|
251
|
-
}
|
247
|
+
box-sizing: border-box;
|
248
|
+
border-radius: 50%;
|
252
249
|
}
|
253
|
-
|
254
|
-
@include inline-loading-spinner;
|
255
250
|
}
|
256
251
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
252
|
+
@include inline-loading-spinner;
|
253
|
+
}
|
254
|
+
|
255
|
+
.external_site_area.active.target_self.dynamic_marker .inline_loading_spinner {
|
256
|
+
display: block;
|
257
|
+
}
|
258
|
+
|
259
|
+
.external_link_loading_indicator {
|
260
|
+
height: 150px;
|
261
|
+
width: 75px;
|
262
|
+
margin-top: -75px;
|
263
|
+
z-index: 2;
|
262
264
|
}
|
263
265
|
}
|
@@ -1,5 +1,25 @@
|
|
1
1
|
@include pageflow-page-type-pictograms("linkmap_page");
|
2
2
|
|
3
|
+
@include keyframes(linkmap_touch_indicator_animation) {
|
4
|
+
0% {
|
5
|
+
@include transform(translate(-50%, -50%) scale(1));
|
6
|
+
opacity: 1;
|
7
|
+
}
|
8
|
+
|
9
|
+
25% {
|
10
|
+
@include transform(translate(-50%, -50%) scale(1.3));
|
11
|
+
}
|
12
|
+
|
13
|
+
50% {
|
14
|
+
@include transform(translate(-50%, -50%) scale(1));
|
15
|
+
opacity: 1;
|
16
|
+
}
|
17
|
+
|
18
|
+
100% {
|
19
|
+
opacity: 0;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
3
23
|
.linkmap_page {
|
4
24
|
$linkmap-icon-font: "FontAwesome" !default;
|
5
25
|
$linkmap-icon-line-height: 1.1em !default;
|
@@ -19,38 +39,46 @@
|
|
19
39
|
$linkmap-audio-progress-color: $linkmap-main-color !default;
|
20
40
|
$linkmap-audio-current-time-color: $linkmap-overlay-text-color !default;
|
21
41
|
|
22
|
-
.hover_area.page_area
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
42
|
+
.hover_area.page_area .linkmap_marker:before,
|
43
|
+
.hover_area.external_site_area .linkmap_marker:before,
|
44
|
+
.touch_indicator:before {
|
45
|
+
content: $linkmap-marker-icon;
|
46
|
+
font-family: $linkmap-icon-font;
|
47
|
+
color: white;
|
48
|
+
font-size: 30px;
|
49
|
+
background-color: rgba(255, 255, 255, 0.3);
|
50
|
+
padding: 10px;
|
51
|
+
border-radius: 50%;
|
52
|
+
width: 35px;
|
53
|
+
height: 35px;
|
54
|
+
@include transform(translate(-50%,-50%));
|
55
|
+
left: 50%;
|
56
|
+
top: 50%;
|
57
|
+
position: absolute;
|
58
|
+
text-align: center;
|
59
|
+
opacity: 0;
|
60
|
+
line-height: $linkmap-icon-line-height;
|
61
|
+
@include transition(0.5s);
|
62
|
+
}
|
44
63
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
64
|
+
.hover_area.page_area.hover_mobile.dynamic_marker .linkmap_marker:before,
|
65
|
+
.hover_area.external_site_area.hover_mobile.dynamic_marker .linkmap_marker:before,
|
66
|
+
.touch_indicator:before {
|
67
|
+
opacity: 1;
|
68
|
+
background-color: rgba(0,0,0,0.7);
|
69
|
+
color: $linkmap-icon-color;
|
70
|
+
}
|
71
|
+
|
72
|
+
.touch_indicator {
|
73
|
+
display: none;
|
74
|
+
position: absolute;
|
75
|
+
z-index: 2;
|
76
|
+
opacity: 0;
|
77
|
+
@include animation(linkmap_touch_indicator_animation 1s);
|
78
|
+
}
|
79
|
+
|
80
|
+
.external_link_loading_indicator .circle_innerst {
|
81
|
+
border: 4px solid $linkmap-audio-progress-color;
|
54
82
|
}
|
55
83
|
|
56
84
|
.linkmap_audio_player_controls {
|
@@ -8,7 +8,7 @@ module Pageflow
|
|
8
8
|
visited_image_file = Pageflow::ImageFile.find_by_id(configuration['visited_image_id'])
|
9
9
|
|
10
10
|
mask_sprite_url_template = MaskSprite.new(id: 1, attachment_file_name: 'data').attachment.url
|
11
|
-
.gsub(%r'(\d{3}/)+', '
|
11
|
+
.gsub(%r'/(\d{3}/)+', '/:id_partition/')
|
12
12
|
|
13
13
|
render('pageflow/linkmap_page/areas/div',
|
14
14
|
entry: entry,
|
@@ -37,6 +37,12 @@
|
|
37
37
|
<div class="link_description"></div>
|
38
38
|
</div>
|
39
39
|
</div>
|
40
|
+
<div class="touch_indicator"></div>
|
41
|
+
<div class="external_link_loading_indicator">
|
42
|
+
<div class="circle_inner">
|
43
|
+
<div class="circle_innerst"></div>
|
44
|
+
</div>
|
45
|
+
</div>
|
40
46
|
</div>
|
41
47
|
</div>
|
42
48
|
</div>
|
data/config/locales/de.yml
CHANGED
@@ -23,8 +23,6 @@ de:
|
|
23
23
|
text_only: Nur Text
|
24
24
|
pageflow:
|
25
25
|
linkmap_page:
|
26
|
-
color_map:
|
27
|
-
too_many_components: Das ausgewählte Bild enthält zu viele verschiedene Farbtöne. Es können maximal 20 Bereiche durch das Maskenbild bestimmt werden. Stellen Sie sicher, dass bei der Erstellung des Maskenbildes keine Kantenglättung verwendet wurde, da dies die Zahl der im Bild auftretenden Farbtöne stark erhöhen kann.
|
28
26
|
default_page_transition: "(Standard)"
|
29
27
|
editor:
|
30
28
|
area_types:
|
@@ -38,11 +36,9 @@ de:
|
|
38
36
|
destroy: Löschen
|
39
37
|
embedded:
|
40
38
|
area_item:
|
41
|
-
edit: DELETE
|
42
39
|
hide_marker: Linkmarkierung deaktivieren
|
43
40
|
set_mask: Maske auswählen
|
44
41
|
show_marker: Linkmarkierung aktivieren
|
45
|
-
toggle_marker: DELETE
|
46
42
|
unset_mask: Frei positionierbar machen
|
47
43
|
file_area_item:
|
48
44
|
edit: Bearbeiten
|
@@ -74,6 +70,12 @@ de:
|
|
74
70
|
drag_hint: Wähle einen Bereich für den Hotspot durch Klicken und Ziehen mit der Maus.
|
75
71
|
select_mask_hint: Klicke auf einen der farbigen Bereiche des Masken-Bildes, um einen Bereich für den Hotspot auszuwählen.
|
76
72
|
select_mask_or_drag_hint: Klicke auf einen der farbigen Bereiche des Masken-Bildes oder wähle einen frei positionierten Bereich durch Klicken und Ziehen mit der Maus.
|
73
|
+
errors:
|
74
|
+
invalid_image_data: Bei der Erkennung der Farbbereiche im Maskenbild ist ein Fehler aufgetreten. Stellen Sie sicher, dass die farbigen Bereiche im Maskenbild begrenzt und alle anderen Teile des Bildes transparent sind.
|
75
|
+
loading_remote_image_failed: Beim Laden des Bildes ist ein Fehler aufgetreten.
|
76
|
+
mask_image_failed: Beim Verarbeiten des Maskenbildes ist ein Fehler aufgetreten.
|
77
|
+
no_big_enough_color_map_components: Es konnten keine Farb-Bereiche erkannt werden. Stellen Sie sicher, dass die Bereiche midestens 7x7 Pixel groß sind.
|
78
|
+
saving_mask_image_failed: Beim Speichern des Maskenbildes ist ein Fehler aufgetreten.
|
77
79
|
help_entries:
|
78
80
|
page_type:
|
79
81
|
menu_item: Hotspots
|
data/config/locales/en.yml
CHANGED
@@ -23,8 +23,6 @@ en:
|
|
23
23
|
text_only: Text only
|
24
24
|
pageflow:
|
25
25
|
linkmap_page:
|
26
|
-
color_map:
|
27
|
-
too_many_components: The selected image contains too many different color values. There is a maximal number of 20 areas that can be determined via the mask image. Make sure that anti aliasing was turned off while creating the mask image. Anti aliasing leads to color gradients inside the image which prevent usage as mask image.
|
28
26
|
default_page_transition: "(Default)"
|
29
27
|
editor:
|
30
28
|
area_types:
|
@@ -38,11 +36,9 @@ en:
|
|
38
36
|
destroy: Delete
|
39
37
|
embedded:
|
40
38
|
area_item:
|
41
|
-
edit: DELETE
|
42
39
|
hide_marker: Hide marker
|
43
40
|
set_mask: Select mask
|
44
41
|
show_marker: Show marker
|
45
|
-
toggle_marker: DELETE
|
46
42
|
unset_mask: Detach from mask
|
47
43
|
file_area_item:
|
48
44
|
edit: Edit
|
@@ -74,6 +70,12 @@ en:
|
|
74
70
|
drag_hint: Select the hotspot's dimension by clicking and dragging somewhere inside the panorama.
|
75
71
|
select_mask_hint: Click on one of the colored areas of the mask image to determine the hotspots shape and position.
|
76
72
|
select_mask_or_drag_hint: Click on one of the colored areas of the mask image or select the hotspot's dimensions by clicking and dragging somewhere inside the panorama.
|
73
|
+
errors:
|
74
|
+
invalid_image_data: There has been an error while identifying color components. Ensure color areas are bounded inside the image and all other parts of the image are transparent.
|
75
|
+
loading_remote_image_failed: Error while loading the image.
|
76
|
+
mask_image_failed: There was an error while processing the mask image.
|
77
|
+
no_big_enough_color_map_components: No color components identified. Ensure each component is at least 7x7 pixels big.
|
78
|
+
saving_mask_image_failed: There has been an error while saving the mask image.
|
77
79
|
help_entries:
|
78
80
|
page_type:
|
79
81
|
menu_item: Hotspots
|
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_runtime_dependency 'pageflow', ['>= 0.10', '< 13']
|
22
22
|
spec.add_runtime_dependency 'pageflow-external-links', ['>= 0.3', '< 2']
|
23
23
|
|
24
|
+
spec.add_development_dependency 'pageflow-support', '~> 12.0'
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.0'
|
25
26
|
spec.add_development_dependency 'rake', '~> 12.0'
|
26
27
|
spec.add_development_dependency 'rspec-rails', '~> 3.0'
|
@@ -15,7 +15,7 @@ module Pageflow
|
|
15
15
|
|
16
16
|
it 'responds with success for member' do
|
17
17
|
user = create(:user)
|
18
|
-
entry = create(:entry,
|
18
|
+
entry = create(:entry, with_editor: user)
|
19
19
|
image_file = create(:image_file, used_in: entry.draft)
|
20
20
|
|
21
21
|
sign_in(user)
|
@@ -29,7 +29,7 @@ module Pageflow
|
|
29
29
|
|
30
30
|
it 'includes id of created mask sprite in response' do
|
31
31
|
user = create(:user)
|
32
|
-
entry = create(:entry,
|
32
|
+
entry = create(:entry, with_editor: user)
|
33
33
|
image_file = create(:image_file, used_in: entry.draft)
|
34
34
|
|
35
35
|
sign_in(user)
|
@@ -45,7 +45,7 @@ module Pageflow
|
|
45
45
|
|
46
46
|
it 'creates mask sprite for image' do
|
47
47
|
user = create(:user)
|
48
|
-
entry = create(:entry,
|
48
|
+
entry = create(:entry, with_editor: user)
|
49
49
|
image_file = create(:image_file, used_in: entry.draft)
|
50
50
|
|
51
51
|
sign_in(user)
|
@@ -61,7 +61,7 @@ module Pageflow
|
|
61
61
|
|
62
62
|
it 'does not recreate mask sprite if it already exists' do
|
63
63
|
user = create(:user)
|
64
|
-
entry = create(:entry,
|
64
|
+
entry = create(:entry, with_editor: user)
|
65
65
|
image_file = create(:image_file, used_in: entry.draft)
|
66
66
|
|
67
67
|
sign_in(user)
|
@@ -51,6 +51,16 @@ module Pageflow
|
|
51
51
|
|
52
52
|
expect(html).not_to have_selector('a[data-mask-id]')
|
53
53
|
end
|
54
|
+
|
55
|
+
it 'renders attribute with url template for mask sprite' do
|
56
|
+
entry = create(:entry)
|
57
|
+
configuration = {}
|
58
|
+
|
59
|
+
html = helper.linkmap_areas_div(entry, configuration)
|
60
|
+
|
61
|
+
url_matcher = 'attachments/:id_partition/original'
|
62
|
+
expect(html).to have_selector("div[data-mask-sprite-url-template*='#{url_matcher}']")
|
63
|
+
end
|
54
64
|
end
|
55
65
|
|
56
66
|
describe '#linkmap_area' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pageflow-linkmap-page
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Codevise Solutions Ltd.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pageflow
|
@@ -50,6 +50,20 @@ dependencies:
|
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '2'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: pageflow-support
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '12.0'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '12.0'
|
53
67
|
- !ruby/object:Gem::Dependency
|
54
68
|
name: bundler
|
55
69
|
requirement: !ruby/object:Gem::Requirement
|