workarea-super_hero 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +15 -0
- data/.eslintrc +26 -0
- data/.gitignore +11 -0
- data/.jshintrc +37 -0
- data/.rails-rubocop.yml +119 -0
- data/.rubocop.yml +12 -0
- data/.scss-lint.yml +188 -0
- data/CHANGELOG.md +334 -0
- data/Gemfile +5 -0
- data/README.md +120 -0
- data/Rakefile +60 -0
- data/app/assets/images/workarea/admin/content_block_types/super_hero.svg +1 -0
- data/app/assets/images/workarea/svg/position_grid.svg +38 -0
- data/app/assets/javascripts/workarea/admin/super_hero/modules/media_modes.js +54 -0
- data/app/assets/javascripts/workarea/admin/super_hero/modules/position_input.js +59 -0
- data/app/assets/javascripts/workarea/storefront/super_hero/modules/vimeo_api.js +85 -0
- data/app/assets/javascripts/workarea/storefront/super_hero/modules/youtube_api.js +122 -0
- data/app/assets/stylesheets/workarea/admin/super_hero/components/_position_grid.scss +27 -0
- data/app/assets/stylesheets/workarea/storefront/super_hero/components/_content_position.scss +46 -0
- data/app/assets/stylesheets/workarea/storefront/super_hero/components/_super_hero_content_block.scss +69 -0
- data/app/models/workarea/content/fields/media_mode.rb +8 -0
- data/app/models/workarea/content/fields/video_advanced.rb +8 -0
- data/app/services/workarea/storefront/color_tools.rb +24 -0
- data/app/services/workarea/storefront/video_embedder/vimeo.rb +50 -0
- data/app/services/workarea/storefront/video_embedder/youtube.rb +56 -0
- data/app/services/workarea/storefront/video_embedder.rb +59 -0
- data/app/view_models/workarea/storefront/content_blocks/super_hero_view_model.rb +79 -0
- data/app/views/workarea/admin/content_blocks/_media_mode.html.haml +3 -0
- data/app/views/workarea/admin/content_blocks/_video_advanced.html.haml +12 -0
- data/app/views/workarea/admin/content_blocks/types/_super_hero.html.haml +106 -0
- data/app/views/workarea/storefront/content_blocks/_super_hero.html.haml +27 -0
- data/bin/rails +18 -0
- data/config/initializers/appends.rb +42 -0
- data/config/initializers/content_block_types.rb +49 -0
- data/config/locales/en.yml +23 -0
- data/config/routes.rb +2 -0
- data/lib/workarea/super_hero/engine.rb +8 -0
- data/lib/workarea/super_hero/version.rb +5 -0
- data/lib/workarea/super_hero.rb +11 -0
- data/script/admin_ci +9 -0
- data/script/ci +11 -0
- data/script/core_ci +9 -0
- data/script/plugins_ci +9 -0
- data/script/storefront_ci +9 -0
- data/super_hero_logo.svg +15 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +54 -0
- data/test/dummy/config/environments/production.rb +86 -0
- data/test/dummy/config/environments/test.rb +43 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +18 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/services/workarea/storefront/color_tools_test.rb +32 -0
- data/test/services/workarea/storefront/video_embedder_test.rb +52 -0
- data/test/test_helper.rb +10 -0
- data/test/view_models/workarea/storefront/super_hero_view_model_test.rb +38 -0
- data/workarea-super_hero.gemspec +18 -0
- metadata +158 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
/**
|
2
|
+
* @namespace WORKAREA.vimeoApi
|
3
|
+
*/
|
4
|
+
WORKAREA.registerModule('vimeoApi', (function () {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
var getIframe = function(player_id) {
|
8
|
+
return $('#'+player_id);
|
9
|
+
},
|
10
|
+
|
11
|
+
getLabel = function(iframe) {
|
12
|
+
var iframeSrc = iframe.attr('src').split('?')[0],
|
13
|
+
label = iframeSrc;
|
14
|
+
|
15
|
+
if (iframe.data('title')) {
|
16
|
+
label += ' (' + iframe.data('title') + ')';
|
17
|
+
} else if (iframe.attr('title')) {
|
18
|
+
label += ' (' + iframe.attr('title') + ')';
|
19
|
+
}
|
20
|
+
|
21
|
+
return label;
|
22
|
+
},
|
23
|
+
|
24
|
+
sendEvent = function (id, action) {
|
25
|
+
var iframe = getIframe(id),
|
26
|
+
label = getLabel(iframe);
|
27
|
+
|
28
|
+
WORKAREA.analytics.fireCallback(
|
29
|
+
'vimeo',
|
30
|
+
{
|
31
|
+
'eventCategory': 'Vimeo',
|
32
|
+
'eventAction': action,
|
33
|
+
'eventLabel': label,
|
34
|
+
'eventValue': undefined
|
35
|
+
}
|
36
|
+
);
|
37
|
+
},
|
38
|
+
|
39
|
+
muteVideo = function (player) {
|
40
|
+
player.setVolume(0);
|
41
|
+
},
|
42
|
+
|
43
|
+
onPlay = function (playerData) {
|
44
|
+
sendEvent(playerData.player_id, 'Play Video');
|
45
|
+
},
|
46
|
+
|
47
|
+
onPause = function (playerData) {
|
48
|
+
sendEvent(playerData.player_id, 'Paused video');
|
49
|
+
},
|
50
|
+
|
51
|
+
onFinish = function (playerData) {
|
52
|
+
sendEvent(playerData.player_id, 'Completed video');
|
53
|
+
},
|
54
|
+
|
55
|
+
parseOptions = function (index, iframe) {
|
56
|
+
var player = new Vimeo.Player(iframe),
|
57
|
+
playerData = $(iframe).data('vimeoApi');
|
58
|
+
|
59
|
+
if (playerData.mute === 'true') {
|
60
|
+
muteVideo(player);
|
61
|
+
}
|
62
|
+
|
63
|
+
player.on('play', _.partial(onPlay, playerData));
|
64
|
+
player.on('pause', _.partial(onPause, playerData));
|
65
|
+
player.on('finish', _.partial(onFinish, playerData));
|
66
|
+
},
|
67
|
+
|
68
|
+
injectSDK = function($vimeoIframes) {
|
69
|
+
$.getScript('https://player.vimeo.com/api/player.js', function() {
|
70
|
+
$vimeoIframes.each(parseOptions);
|
71
|
+
});
|
72
|
+
},
|
73
|
+
|
74
|
+
init = function ($scope) {
|
75
|
+
var $vimeoIframes = $('[data-vimeo-api]', $scope);
|
76
|
+
|
77
|
+
if (_.isEmpty($vimeoIframes)) { return; }
|
78
|
+
|
79
|
+
injectSDK($vimeoIframes);
|
80
|
+
};
|
81
|
+
|
82
|
+
return {
|
83
|
+
init: init
|
84
|
+
};
|
85
|
+
}()));
|
@@ -0,0 +1,122 @@
|
|
1
|
+
/**
|
2
|
+
* @namespace WORKAREA.youtubeApi
|
3
|
+
*/
|
4
|
+
WORKAREA.registerModule('youtubeApi', (function () {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
var getIframe = function(player_id) {
|
8
|
+
return $('#'+player_id);
|
9
|
+
},
|
10
|
+
|
11
|
+
getLabel = function(iframe) {
|
12
|
+
var iframeSrc = iframe.attr('src').split('?')[0],
|
13
|
+
label = iframeSrc;
|
14
|
+
|
15
|
+
if (iframe.data('title')) {
|
16
|
+
label += ' (' + iframe.data('title') + ')';
|
17
|
+
} else if (iframe.attr('title')) {
|
18
|
+
label += ' (' + iframe.attr('title') + ')';
|
19
|
+
}
|
20
|
+
|
21
|
+
return label;
|
22
|
+
},
|
23
|
+
|
24
|
+
sendEvent = function (id, action) {
|
25
|
+
var iframe = getIframe(id),
|
26
|
+
label = getLabel(iframe);
|
27
|
+
|
28
|
+
WORKAREA.analytics.fireCallback(
|
29
|
+
'youtube',
|
30
|
+
{
|
31
|
+
'eventCategory': 'Youtube',
|
32
|
+
'eventAction': action,
|
33
|
+
'eventLabel': label,
|
34
|
+
'eventValue': undefined
|
35
|
+
}
|
36
|
+
);
|
37
|
+
},
|
38
|
+
|
39
|
+
onPlay = function (playerId) {
|
40
|
+
sendEvent(playerId, 'Play Video');
|
41
|
+
},
|
42
|
+
|
43
|
+
onPause = function (playerId) {
|
44
|
+
sendEvent(playerId, 'Paused video');
|
45
|
+
},
|
46
|
+
|
47
|
+
onFinish = function (playerId) {
|
48
|
+
sendEvent(playerId, 'Completed video');
|
49
|
+
},
|
50
|
+
|
51
|
+
handlePlayerState = function(playerId, state) {
|
52
|
+
var stateMap = {
|
53
|
+
'-1': 'unstarted',
|
54
|
+
'0': 'ended',
|
55
|
+
'1': 'playing',
|
56
|
+
'2': 'paused',
|
57
|
+
'3': 'buffering',
|
58
|
+
'5': 'queued'
|
59
|
+
},
|
60
|
+
currentState = stateMap[state.data];
|
61
|
+
|
62
|
+
if (currentState === 'playing') {
|
63
|
+
onPlay(playerId);
|
64
|
+
} else if (currentState === 'paused') {
|
65
|
+
onPause(playerId);
|
66
|
+
} else if (currentState === 'ended') {
|
67
|
+
onFinish(playerId);
|
68
|
+
}
|
69
|
+
},
|
70
|
+
|
71
|
+
onPlayerReady = function (playerData, event) {
|
72
|
+
var player = event.target;
|
73
|
+
|
74
|
+
if (playerData.mute === 'true') {
|
75
|
+
player.mute();
|
76
|
+
}
|
77
|
+
},
|
78
|
+
|
79
|
+
setupPlayer = function (index, iframe) {
|
80
|
+
var playerData = $(iframe).data('youtubeApi'),
|
81
|
+
playerId = $(iframe).attr('id'),
|
82
|
+
player = new YT.Player(playerId, {
|
83
|
+
events: {
|
84
|
+
'onReady': _.partial(onPlayerReady, playerData),
|
85
|
+
'onStateChange': _.partial(handlePlayerState, playerId)
|
86
|
+
}
|
87
|
+
});
|
88
|
+
return player;
|
89
|
+
},
|
90
|
+
|
91
|
+
scriptLoaded = function ($scope) {
|
92
|
+
var $youtubeIframes = $('[data-youtube-api]', $scope);
|
93
|
+
|
94
|
+
$youtubeIframes.each(setupPlayer);
|
95
|
+
},
|
96
|
+
|
97
|
+
injectSDK = function () {
|
98
|
+
$.getScript('https://www.youtube.com/player_api');
|
99
|
+
},
|
100
|
+
|
101
|
+
init = function ($scope) {
|
102
|
+
var $youtubeIframes = $('[data-youtube-api]', $scope);
|
103
|
+
|
104
|
+
if (_.isEmpty($youtubeIframes)) { return; }
|
105
|
+
|
106
|
+
injectSDK();
|
107
|
+
};
|
108
|
+
|
109
|
+
return {
|
110
|
+
init: init,
|
111
|
+
scriptLoaded: scriptLoaded
|
112
|
+
};
|
113
|
+
}()));
|
114
|
+
|
115
|
+
/**
|
116
|
+
* onYouTubeIframeAPIReady is called by YouTube API
|
117
|
+
* This is executed when the API is ready to go.
|
118
|
+
*/
|
119
|
+
/*eslint no-unused-vars: 0 */
|
120
|
+
function onYouTubeIframeAPIReady() {
|
121
|
+
WORKAREA.youtubeApi.scriptLoaded($(document));
|
122
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
/*------------------------------------*\
|
2
|
+
#POSITION-GRID
|
3
|
+
\*------------------------------------*/
|
4
|
+
|
5
|
+
$position-grid-cell-fill-color: $white;
|
6
|
+
$position-grid-cell-fill-color-hover: $light-gray;
|
7
|
+
$position-grid-cell-path-color: $gray;
|
8
|
+
|
9
|
+
.position-grid {
|
10
|
+
height: 150px;
|
11
|
+
}
|
12
|
+
|
13
|
+
.position-grid--input {
|
14
|
+
display: none;
|
15
|
+
}
|
16
|
+
|
17
|
+
.position-grid__cell {
|
18
|
+
fill: $position-grid-cell-fill-color;
|
19
|
+
|
20
|
+
&:hover {
|
21
|
+
fill: $position-grid-cell-fill-color-hover;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
.position-grid__cell-path {
|
26
|
+
fill: $position-grid-cell-path-color;
|
27
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/*------------------------------------*\
|
2
|
+
#CONTENT-POSITION
|
3
|
+
\*------------------------------------*/
|
4
|
+
|
5
|
+
$positioning-offset: 5% !default;
|
6
|
+
|
7
|
+
|
8
|
+
.content-position {}
|
9
|
+
|
10
|
+
.content-position--top {
|
11
|
+
top: $positioning-offset;
|
12
|
+
}
|
13
|
+
|
14
|
+
.content-position--middle {
|
15
|
+
top: 50%;
|
16
|
+
transform: translateY(-50%);
|
17
|
+
}
|
18
|
+
|
19
|
+
.content-position--bottom {
|
20
|
+
bottom: $positioning-offset;
|
21
|
+
}
|
22
|
+
|
23
|
+
.content-position--left {
|
24
|
+
@include respond-to($medium-breakpoint) {
|
25
|
+
left: $positioning-offset;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
.content-position--center {
|
30
|
+
@include respond-to($medium-breakpoint) {
|
31
|
+
left: 50%;
|
32
|
+
transform: translateX(-50%);
|
33
|
+
}
|
34
|
+
|
35
|
+
&.content-position--middle {
|
36
|
+
@include respond-to($medium-breakpoint) {
|
37
|
+
transform: translate(-50%, -50%);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
.content-position--right {
|
43
|
+
@include respond-to($medium-breakpoint) {
|
44
|
+
right: $positioning-offset;
|
45
|
+
}
|
46
|
+
}
|
data/app/assets/stylesheets/workarea/storefront/super_hero/components/_super_hero_content_block.scss
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
/*------------------------------------*\
|
2
|
+
#SUPER-HERO-CONTENT-BLOCK
|
3
|
+
\*------------------------------------*/
|
4
|
+
|
5
|
+
$super-hero-content-block-content-max-width: 50% !default;
|
6
|
+
|
7
|
+
|
8
|
+
.super-hero-content-block {
|
9
|
+
position: relative;
|
10
|
+
overflow: hidden;
|
11
|
+
}
|
12
|
+
|
13
|
+
.super-hero-content-block--hide-mobile {
|
14
|
+
display: none;
|
15
|
+
|
16
|
+
@include respond-to($medium-breakpoint) {
|
17
|
+
display: block;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* 1. Above .super-hero-content-block__media-container
|
23
|
+
*/
|
24
|
+
|
25
|
+
.super-hero-content-block__content {
|
26
|
+
position: absolute;
|
27
|
+
z-index: 10; /* [1] */
|
28
|
+
padding: $spacing-unit * 2;
|
29
|
+
max-width: $super-hero-content-block-content-max-width;
|
30
|
+
}
|
31
|
+
|
32
|
+
.super-hero-content-block__media-container {}
|
33
|
+
|
34
|
+
.super-hero-content-block__media-container--maintain-aspect-ratio {
|
35
|
+
width: 100%;
|
36
|
+
height: 0;
|
37
|
+
|
38
|
+
.super-hero-content-block__media {
|
39
|
+
position: absolute;
|
40
|
+
width: 100%;
|
41
|
+
height: 100%;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
.super-hero-content-block__media {}
|
46
|
+
|
47
|
+
.super-hero-content-block__media--resize {
|
48
|
+
background-size: contain;
|
49
|
+
background-repeat: no-repeat;
|
50
|
+
}
|
51
|
+
|
52
|
+
.super-hero-content-block__media--crop {
|
53
|
+
position: absolute;
|
54
|
+
background-size: cover;
|
55
|
+
}
|
56
|
+
|
57
|
+
.super-hero-content-block__media--crop-center {
|
58
|
+
background-position: 50% 50%;
|
59
|
+
}
|
60
|
+
|
61
|
+
.super-hero-content-block__media--crop-right {
|
62
|
+
background-position: 100% 0%;
|
63
|
+
}
|
64
|
+
|
65
|
+
.super-hero-content-block__media--crop-left {
|
66
|
+
background-position: 0% 100%;
|
67
|
+
}
|
68
|
+
|
69
|
+
.super-hero-content-block__media--switch {}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class ColorTools
|
4
|
+
def initialize(color)
|
5
|
+
@color = color
|
6
|
+
end
|
7
|
+
|
8
|
+
def rgba
|
9
|
+
if @color[:hex] =~ /#(..)(..)(..)/
|
10
|
+
"#{hex_to_rgb}, #{alpha}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def alpha
|
15
|
+
@color[:alpha].to_f / 100.0
|
16
|
+
end
|
17
|
+
|
18
|
+
def hex_to_rgb
|
19
|
+
r, g, b = @color[:hex].match(/#(..)(..)(..)/).captures
|
20
|
+
"#{r.hex}, #{g.hex}, #{b.hex}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class VideoEmbedder
|
4
|
+
class Vimeo
|
5
|
+
def initialize(embed_code, options = {})
|
6
|
+
@embed_code = embed_code
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def attrs
|
11
|
+
{
|
12
|
+
id: vimeo_id,
|
13
|
+
src: "#{url}?#{url_params}",
|
14
|
+
webkitallowfullscreen: '',
|
15
|
+
mozallowfullscreen: '',
|
16
|
+
data: {
|
17
|
+
vimeo_api: {
|
18
|
+
player_id: vimeo_id,
|
19
|
+
mute: @options[:mute]
|
20
|
+
}.to_json
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def url_params
|
26
|
+
parsed_query = Rack::Utils.parse_query(uri.query)
|
27
|
+
parsed_query['api'] = 1
|
28
|
+
parsed_query['autoplay'] = @options[:autoplay]
|
29
|
+
parsed_query['loop'] = @options[:loop_playback]
|
30
|
+
parsed_query['player_id'] = vimeo_id
|
31
|
+
uri.query = URI.encode_www_form(parsed_query)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def vimeo_id
|
37
|
+
uri.path.split('/').last
|
38
|
+
end
|
39
|
+
|
40
|
+
def url
|
41
|
+
@url ||= @embed_code.attribute('src').value
|
42
|
+
end
|
43
|
+
|
44
|
+
def uri
|
45
|
+
URI.parse(url)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class VideoEmbedder
|
4
|
+
class Youtube
|
5
|
+
def initialize(embed_code, options = {})
|
6
|
+
@embed_code = embed_code
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def attrs
|
11
|
+
{
|
12
|
+
id: "youtube-#{youtube_id}",
|
13
|
+
src: "#{url}?#{url_params}",
|
14
|
+
data: {
|
15
|
+
youtube_api: {
|
16
|
+
mute: @options[:mute]
|
17
|
+
}.to_json
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def url_params
|
23
|
+
parsed_query = Rack::Utils.parse_query(uri.query)
|
24
|
+
parsed_query['enablejsapi'] = 1
|
25
|
+
parsed_query['autoplay'] = autoplay
|
26
|
+
parsed_query['loop'] = loop_playback
|
27
|
+
parsed_query['videoId'] = youtube_id
|
28
|
+
|
29
|
+
URI.encode_www_form(parsed_query)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def youtube_id
|
35
|
+
uri.path.split('/').last
|
36
|
+
end
|
37
|
+
|
38
|
+
def autoplay
|
39
|
+
@options[:autoplay] ? 1 : 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def loop_playback
|
43
|
+
@options[:loop_playback] ? 1 : 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def url
|
47
|
+
@url ||= @embed_code.attribute('src').value
|
48
|
+
end
|
49
|
+
|
50
|
+
def uri
|
51
|
+
URI.parse(url)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
class VideoEmbedder
|
4
|
+
def initialize(embed_code, options = {})
|
5
|
+
@embed_code = Nokogiri::HTML.fragment(embed_code).children.first
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def iframe_attrs
|
10
|
+
attrs = {
|
11
|
+
frameborder: '0',
|
12
|
+
allowfullscreen: '',
|
13
|
+
container_style: "padding-bottom: #{aspect_ratio}%"
|
14
|
+
}
|
15
|
+
|
16
|
+
service_embed_code = if vimeo?
|
17
|
+
Vimeo.new(@embed_code, @options)
|
18
|
+
elsif youtube?
|
19
|
+
Youtube.new(@embed_code, @options)
|
20
|
+
end
|
21
|
+
|
22
|
+
attrs.merge(service_embed_code.attrs)
|
23
|
+
end
|
24
|
+
|
25
|
+
def vimeo?
|
26
|
+
host =~ /vimeo/ ? true : false
|
27
|
+
end
|
28
|
+
|
29
|
+
def youtube?
|
30
|
+
host =~ /youtube/ ? true : false
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def url
|
36
|
+
@url ||= @embed_code.attribute('src').value
|
37
|
+
end
|
38
|
+
|
39
|
+
def uri
|
40
|
+
URI.parse(url)
|
41
|
+
end
|
42
|
+
|
43
|
+
def host
|
44
|
+
uri.host
|
45
|
+
end
|
46
|
+
|
47
|
+
def aspect_ratio
|
48
|
+
height = @embed_code.attribute('height').value
|
49
|
+
width = @embed_code.attribute('width').value
|
50
|
+
ratio = height.to_f / width.to_f
|
51
|
+
ratio * 100
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_vimeo_id
|
55
|
+
@embed_code.attribute('id').value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Storefront
|
3
|
+
module ContentBlocks
|
4
|
+
class SuperHeroViewModel < ContentBlockViewModel
|
5
|
+
def image_medium_url
|
6
|
+
if data[:asset_medium].present?
|
7
|
+
find_asset(data[:asset_medium]).url
|
8
|
+
else
|
9
|
+
image.url
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def image_small_url
|
14
|
+
if data[:asset_small].present?
|
15
|
+
find_asset(data[:asset_small]).url
|
16
|
+
else
|
17
|
+
image.url
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def breakpoints
|
22
|
+
Workarea.config.storefront_break_points
|
23
|
+
end
|
24
|
+
|
25
|
+
def image
|
26
|
+
@image ||= find_asset(data[:asset])
|
27
|
+
end
|
28
|
+
|
29
|
+
def alt_text
|
30
|
+
model.data[:alt_text].presence
|
31
|
+
end
|
32
|
+
|
33
|
+
def media_class
|
34
|
+
if model.data[:media_mode] == 'crop'
|
35
|
+
"crop super-hero-content-block__media--crop-#{model.data[:crop_side]}"
|
36
|
+
else
|
37
|
+
model.data[:media_mode]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def media_styles
|
42
|
+
if model.data[:media_mode] == 'resize'
|
43
|
+
"padding-bottom: #{image.file_inverse_aspect_ratio * 100}%"
|
44
|
+
elsif model.data[:media_mode] == 'crop'
|
45
|
+
"padding-bottom: #{image.height}px"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def video_iframe_attrs
|
50
|
+
return unless model.data[:video].present?
|
51
|
+
embed_code = VideoEmbedder.new(
|
52
|
+
model.data[:video],
|
53
|
+
autoplay: model.data[:autoplay],
|
54
|
+
loop_playback: model.data[:loop],
|
55
|
+
mute: model.data[:mute]
|
56
|
+
)
|
57
|
+
embed_code.iframe_attrs
|
58
|
+
end
|
59
|
+
|
60
|
+
def content_class
|
61
|
+
content_class = 'content-position '
|
62
|
+
model.data[:content_position].split(',').each do |pos|
|
63
|
+
content_class << "content-position--#{pos.optionize} "
|
64
|
+
end
|
65
|
+
return content_class
|
66
|
+
end
|
67
|
+
|
68
|
+
def content_styles
|
69
|
+
background_color = ColorTools.new(
|
70
|
+
hex: model.data[:background_color],
|
71
|
+
alpha: model.data[:background_alpha]
|
72
|
+
)
|
73
|
+
|
74
|
+
"color: #{model.data[:text_color]}; background-color: rgba(#{background_color.rgba});"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,3 @@
|
|
1
|
+
.property
|
2
|
+
= label_tag dom_id(block, field.slug), field.name, class: 'property__name'
|
3
|
+
= select_tag "block[data][#{field.slug}]", options_for_select([['Resize', 'resize'],['Crop', 'crop'], ['Switch', 'switch'], ['Video', 'video']], block.data["#{field.slug}"]), id: dom_id(block, field.slug), data: { media_mode: 'control' }
|
@@ -0,0 +1,12 @@
|
|
1
|
+
.property{ class: ('property--required' if field.required?), data: field.options[:html_data_attributes] }
|
2
|
+
= label_tag dom_id(block, field.slug), field.name, class: 'property__name'
|
3
|
+
= text_area_tag "block[data][#{field.slug}]", block.data[field.slug], id: dom_id(block, field.slug), class: 'text-box text-box--multi-line text-box--i18n'
|
4
|
+
|
5
|
+
.property{ data: field.options[:html_data_attributes] }
|
6
|
+
%p.property__name
|
7
|
+
%span.property__text= t("workarea.admin.content_blocks.video_advanced.video_options")
|
8
|
+
.value
|
9
|
+
- %w(autoplay loop mute).each do |option|
|
10
|
+
.property.property--stacked.property--inline-with-label
|
11
|
+
= label_tag dom_id(block, :"#{option}_for"), option.capitalize, class: 'property__name'
|
12
|
+
= select_tag "block[data][#{option}]", options_for_select([['No', 'false'], ['Yes', 'true']], block.data["#{option}"]), id: dom_id(block, "#{option}_for")
|