pageflow 12.2.0 → 12.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pageflow might be problematic. Click here for more details.

Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -92
  3. data/admins/pageflow/accounts.rb +1 -0
  4. data/app/assets/audios/pageflow/unmute.mp3 +0 -0
  5. data/app/assets/javascripts/pageflow/asset_urls.js.erb +1 -1
  6. data/app/assets/javascripts/pageflow/audio/multi_player.js +4 -0
  7. data/app/assets/javascripts/pageflow/audio_player.js +1 -1
  8. data/app/assets/javascripts/pageflow/background_media.js +22 -0
  9. data/app/assets/javascripts/pageflow/base.js +2 -0
  10. data/app/assets/javascripts/pageflow/browser/agent.js +92 -78
  11. data/app/assets/javascripts/pageflow/browser/autoplay_support.js +2 -2
  12. data/app/assets/javascripts/pageflow/cookie_notice.js +7 -0
  13. data/app/assets/javascripts/pageflow/dist/react.js +1312 -329
  14. data/app/assets/javascripts/pageflow/editor/models/configuration.js +5 -5
  15. data/app/assets/javascripts/pageflow/editor/templates/background_positioning_sliders.jst.ejs +8 -0
  16. data/app/assets/javascripts/pageflow/editor/views/background_positioning_sliders_view.js +37 -23
  17. data/app/assets/javascripts/pageflow/editor/views/background_positioning_view.js +2 -2
  18. data/app/assets/javascripts/pageflow/editor/views/configuration_editors/video.js +1 -1
  19. data/app/assets/javascripts/pageflow/editor/views/edit_widget_view.js +9 -0
  20. data/app/assets/javascripts/pageflow/editor/views/info_box_view.js +8 -0
  21. data/app/assets/javascripts/pageflow/editor/views/widget_types/cookie_notice_bar.js +15 -0
  22. data/app/assets/javascripts/pageflow/media_player.js +7 -3
  23. data/app/assets/javascripts/pageflow/media_player/handle_failed_play.js +34 -0
  24. data/app/assets/javascripts/pageflow/media_player/volume_fading/web_audio.js +29 -3
  25. data/app/assets/javascripts/pageflow/seed_entry_data.js +3 -3
  26. data/app/assets/javascripts/pageflow/slideshow.js +17 -9
  27. data/app/assets/javascripts/pageflow/slideshow/adjacent_pages.js +7 -2
  28. data/app/assets/javascripts/pageflow/slideshow/adjacent_preloader.js +26 -0
  29. data/app/assets/javascripts/pageflow/slideshow/atmo.js +23 -12
  30. data/app/assets/javascripts/pageflow/slideshow/lazy_page_widget.js +2 -2
  31. data/app/assets/javascripts/pageflow/slideshow/{adjacent_preparer.js → successor_preparer.js} +14 -11
  32. data/app/assets/javascripts/pageflow/ui/views/configuration_editor_view.js +2 -2
  33. data/app/assets/javascripts/pageflow/video_player/lazy.js +1 -1
  34. data/app/assets/javascripts/pageflow/visited.js +2 -0
  35. data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +34 -10
  36. data/app/assets/stylesheets/pageflow/page_types/video.scss +1 -4
  37. data/app/assets/stylesheets/pageflow/page_types/video/mobile_poster.scss +15 -0
  38. data/app/assets/stylesheets/pageflow/themes/default/background_media_unmute_button.scss +68 -0
  39. data/app/assets/stylesheets/pageflow/themes/default/base.scss +2 -0
  40. data/app/assets/stylesheets/pageflow/themes/default/cookie_notice_bar.scss +57 -0
  41. data/app/assets/stylesheets/pageflow/themes/default/page.scss +1 -0
  42. data/app/assets/stylesheets/pageflow/themes/default/page/hyphenate.scss +24 -0
  43. data/app/assets/stylesheets/pageflow/themes/default/slideshow.scss +1 -0
  44. data/app/controllers/pageflow/admin/initial_passwords_controller.rb +8 -0
  45. data/app/helpers/pageflow/common_entry_seed_helper.rb +1 -0
  46. data/app/helpers/pageflow/entries_helper.rb +20 -2
  47. data/app/helpers/pageflow/entry_json_seed_helper.rb +1 -1
  48. data/app/helpers/pageflow/public_i18n_helper.rb +6 -1
  49. data/app/views/admin/accounts/_form.html.erb +1 -0
  50. data/app/views/pageflow/admin/initial_passwords/edit.html.erb +16 -0
  51. data/app/views/pageflow/entry_json_seed/_entry.json.jbuilder +1 -1
  52. data/app/views/pageflow/user_mailer/invitation.html.erb +2 -2
  53. data/app/views/pageflow/user_mailer/invitation.text.erb +1 -1
  54. data/config/locales/de.yml +14 -6
  55. data/config/locales/en.yml +16 -8
  56. data/config/routes.rb +6 -0
  57. data/db/migrate/20180528144334_add_privacy_link_url_to_themings.rb +5 -0
  58. data/lib/pageflow/built_in_widget_type.rb +8 -0
  59. data/lib/pageflow/built_in_widget_types_plugin.rb +2 -0
  60. data/lib/pageflow/version.rb +1 -1
  61. data/vendor/assets/javascripts/audio5.min.js +280 -129
  62. metadata +19 -7
  63. data/app/assets/javascripts/pageflow/media_player/catch_play_promise.js +0 -23
  64. data/app/assets/javascripts/pageflow/slideshow/progressive_preload.js +0 -42
@@ -40,25 +40,25 @@ pageflow.Configuration = Backbone.Model.extend({
40
40
  },
41
41
 
42
42
  getFilePosition: function(attribute, coord) {
43
- var propertyName = this._filePositionProperty(attribute, coord);
43
+ var propertyName = this.filePositionProperty(attribute, coord);
44
44
  return this.has(propertyName) ? this.get(propertyName) : 50;
45
45
  },
46
46
 
47
47
  setFilePosition: function(attribute, coord, value) {
48
- var propertyName = this._filePositionProperty(attribute, coord);
48
+ var propertyName = this.filePositionProperty(attribute, coord);
49
49
  this.set(propertyName, value);
50
50
  },
51
51
 
52
52
  setFilePositions: function(attribute, x, y) {
53
53
  var attributes = {};
54
54
 
55
- attributes[this._filePositionProperty(attribute, 'x')] = x;
56
- attributes[this._filePositionProperty(attribute, 'y')] = y;
55
+ attributes[this.filePositionProperty(attribute, 'x')] = x;
56
+ attributes[this.filePositionProperty(attribute, 'y')] = y;
57
57
 
58
58
  this.set(attributes);
59
59
  },
60
60
 
61
- _filePositionProperty: function(attribute, coord) {
61
+ filePositionProperty: function(attribute, coord) {
62
62
  return attribute.replace(/_id$/, '_' + coord);
63
63
  },
64
64
 
@@ -3,4 +3,12 @@
3
3
  </div>
4
4
  <div class="slider vertical">
5
5
  </div>
6
+ <div class="percent horizontal">
7
+ <input type="number" min="0" max="100">
8
+ %
9
+ </div>
10
+ <div class="percent vertical">
11
+ <input type="number" min="0" max="100">
12
+ %
13
+ </div>
6
14
  </div>
@@ -6,7 +6,10 @@ pageflow.BackgroundPositioningSlidersView = Backbone.Marionette.ItemView.extend(
6
6
  container: '.container',
7
7
 
8
8
  sliderHorizontal: '.horizontal.slider',
9
- sliderVertical: '.vertical.slider'
9
+ sliderVertical: '.vertical.slider',
10
+
11
+ inputHorizontal: '.percent.horizontal input',
12
+ inputVertical: '.percent.vertical input'
10
13
  },
11
14
 
12
15
  events: {
@@ -34,6 +37,10 @@ pageflow.BackgroundPositioningSlidersView = Backbone.Marionette.ItemView.extend(
34
37
  }
35
38
  },
36
39
 
40
+ modelEvents: {
41
+ change: 'update'
42
+ },
43
+
37
44
  onRender: function() {
38
45
  var view = this;
39
46
  var file = this.model.getReference(this.options.propertyName, this.options.filesCollection),
@@ -43,52 +50,59 @@ pageflow.BackgroundPositioningSlidersView = Backbone.Marionette.ItemView.extend(
43
50
 
44
51
  this.ui.sliderVertical.slider({
45
52
  orientation: 'vertical',
46
- step: 0.01,
47
- value: 100 - this.model.getFilePosition(this.options.propertyName, 'y'),
48
53
 
49
- change: function() {
50
- view.save();
54
+ change: function(event, ui) {
55
+ view.save('y', 100 - ui.value);
51
56
  },
52
57
 
53
58
  slide: function(event, ui) {
54
- view.save({y: ui.value});
59
+ view.save('y', 100 - ui.value);
55
60
  }
56
61
  });
57
62
 
58
63
  this.ui.sliderHorizontal.slider({
59
64
  orientation: 'horizontal',
60
- step: 0.01,
61
- value: this.model.getFilePosition(this.options.propertyName, 'x'),
62
65
 
63
- change: function() {
64
- view.save();
66
+ change: function(event, ui) {
67
+ view.save('x', ui.value);
65
68
  },
66
69
 
67
70
  slide: function(event, ui) {
68
- view.save({y: ui.value});
71
+ view.save('x', ui.value);
69
72
  }
70
73
  });
74
+
75
+ this.ui.inputVertical.on('change', function() {
76
+ view.save('y', $(this).val());
77
+ });
78
+
79
+ this.ui.inputHorizontal.on('change', function() {
80
+ view.save('x', $(this).val());
81
+ });
82
+
83
+ this.update();
71
84
  },
72
85
 
73
- onShow: function() {
86
+ update: function() {
87
+ var x = this.model.getFilePosition(this.options.propertyName, 'x');
88
+ var y = this.model.getFilePosition(this.options.propertyName, 'y');
89
+
90
+ this.ui.sliderVertical.slider('value', 100 - y);
91
+ this.ui.sliderHorizontal.slider('value', x);
92
+
93
+ this.ui.inputVertical.val(y);
94
+ this.ui.inputHorizontal.val(x);
74
95
  },
75
96
 
76
97
  saveFromEvent: function(event) {
77
98
  var x = event.pageX - this.ui.container.offset().left;
78
99
  var y = event.pageY - this.ui.container.offset().top;
79
100
 
80
- this.ui.sliderHorizontal.slider('value', x / this.ui.container.width() * 100);
81
- this.ui.sliderVertical.slider('value', (1 - y / this.ui.container.height()) * 100);
82
- this.save();
101
+ this.save('x', Math.round(x / this.ui.container.width() * 100));
102
+ this.save('y', Math.round(y / this.ui.container.width() * 100));
83
103
  },
84
104
 
85
- save: function(options) {
86
- options = options || {};
87
-
88
- var x = x in options ? options.x : this.ui.sliderHorizontal.slider('value');
89
- var y = y in options ? options.y : 100 - this.ui.sliderVertical.slider('value');
90
-
91
- this.model.setFilePosition(this.options.propertyName, 'x', x);
92
- this.model.setFilePosition(this.options.propertyName, 'y', y);
105
+ save: function(coord, value) {
106
+ this.model.setFilePosition(this.options.propertyName, coord, Math.min(100, Math.max(0, value)));
93
107
  }
94
108
  });
@@ -63,5 +63,5 @@ pageflow.BackgroundPositioningView = Backbone.Marionette.ItemView.extend({
63
63
  });
64
64
 
65
65
  pageflow.BackgroundPositioningView.open = function(options) {
66
- pageflow.app.dialogRegion.show(new pageflow.BackgroundPositioningView(options).render());
67
- };
66
+ pageflow.app.dialogRegion.show(new pageflow.BackgroundPositioningView(options));
67
+ };
@@ -19,7 +19,7 @@ pageflow.ConfigurationEditorView.register('video', {
19
19
  });
20
20
  this.input('mobile_poster_image_id', pageflow.FileInputView, {
21
21
  collection: pageflow.imageFiles,
22
- positioning: false
22
+ positioning: true
23
23
  });
24
24
  this.input('thumbnail_image_id', pageflow.FileInputView, {
25
25
  collection: pageflow.imageFiles,
@@ -8,6 +8,15 @@ pageflow.EditWidgetView = Backbone.Marionette.ItemView.extend({
8
8
  }
9
9
  },
10
10
 
11
+ initialize: function() {
12
+ this.model.set('editing', true);
13
+ },
14
+
15
+ onClose: function() {
16
+ Backbone.Marionette.ItemView.prototype.onClose.call(this);
17
+ this.model.set('editing', false);
18
+ },
19
+
11
20
  onRender: function() {
12
21
  var configurationEditor = this.model.widgetType().createConfigurationEditorView({
13
22
  model: this.model.configuration,
@@ -0,0 +1,8 @@
1
+ pageflow.InfoBoxView = Backbone.Marionette.View.extend({
2
+ className: 'info_box',
3
+
4
+ render: function() {
5
+ this.$el.text(this.options.text);
6
+ return this;
7
+ }
8
+ });
@@ -0,0 +1,15 @@
1
+ pageflow.editor.widgetTypes.registerRole('cookie_notice', {
2
+ isOptional: true
3
+ });
4
+
5
+ pageflow.editor.widgetTypes.register('cookie_notice_bar', {
6
+ configurationEditorView: pageflow.ConfigurationEditorView.extend({
7
+ configure: function() {
8
+ this.tab('cookie_notice_bar', function() {
9
+ this.view(pageflow.InfoBoxView, {
10
+ text: I18n.t('pageflow.editor.cookie_notice_bar.widget_type_info_box_text')
11
+ });
12
+ });
13
+ }
14
+ })
15
+ });
@@ -1,5 +1,6 @@
1
1
  //= require_self
2
- //= require ./media_player/catch_play_promise
2
+
3
+ //= require ./media_player/handle_failed_play
3
4
  //= require ./media_player/volume_fading
4
5
  //= require ./media_player/volume_binding
5
6
  //= require ./media_player/load_waiting
@@ -8,7 +9,10 @@
8
9
 
9
10
  pageflow.mediaPlayer = {
10
11
  enhance: function(player, options) {
11
- pageflow.mediaPlayer.catchPlayerPromise(player);
12
+ pageflow.mediaPlayer.handleFailedPlay(player, _.extend({
13
+ hasAutoplaySupport: pageflow.browser.has('autoplay support')
14
+ }, options));
15
+
12
16
  pageflow.mediaPlayer.asyncPlay(player);
13
17
 
14
18
  if (options.hooks) {
@@ -24,4 +28,4 @@ pageflow.mediaPlayer = {
24
28
  pageflow.mediaPlayer.loadWaiting(player);
25
29
  }
26
30
  }
27
- };
31
+ };
@@ -0,0 +1,34 @@
1
+ pageflow.mediaPlayer.handleFailedPlay = function(player, options) {
2
+ var originalPlay = player.play;
3
+
4
+ player.play = function(/* arguments */) {
5
+ var result = originalPlay.apply(player, arguments);
6
+
7
+ if (result && typeof result.catch !== 'undefined') {
8
+ return result.catch(function(e) {
9
+ if (e.name === 'NotAllowedError' && options.hasAutoplaySupport) {
10
+ if (options.fallbackToMutedAutoplay) {
11
+ player.muted(true);
12
+
13
+ return originalPlay.apply(player, arguments).then(
14
+ function() {
15
+ player.trigger('playmuted');
16
+ },
17
+ function() {
18
+ player.trigger('playfailed');
19
+ }
20
+ );
21
+ }
22
+ else {
23
+ player.trigger('playfailed');
24
+ }
25
+ }
26
+ else {
27
+ pageflow.log('Caught play exception for video.');
28
+ }
29
+ });
30
+ }
31
+
32
+ return result;
33
+ };
34
+ };
@@ -12,10 +12,31 @@ pageflow.mediaPlayer.volumeFading.webAudio = function(player, audioContext) {
12
12
 
13
13
  var allowedMinValue = 0.000001;
14
14
 
15
- player.volume = function(value) {
16
- ensureGainNode();
15
+ var originalPlay = player.play;
16
+
17
+ if (audioContext.state === 'suspended') {
18
+ pageflow.events.on('background_media:unmute', function() {
19
+ audioContext.resume();
20
+ });
21
+
22
+ audioContext.addEventListener('statechange', function() {
23
+ player.volume(currentValue);
24
+ });
25
+ }
26
+
27
+ player.play = function(/* arguments */) {
28
+ return originalPlay.apply(player, arguments);
29
+ };
17
30
 
31
+ player.volume = function(value) {
18
32
  if (typeof value !== 'undefined') {
33
+ if (audioContext.state === 'suspended') {
34
+ currentValue = ensureInAllowedRange(value);
35
+ return;
36
+ }
37
+
38
+ ensureGainNode();
39
+
19
40
  cancel();
20
41
  currentValue = ensureInAllowedRange(value);
21
42
 
@@ -27,6 +48,11 @@ pageflow.mediaPlayer.volumeFading.webAudio = function(player, audioContext) {
27
48
  };
28
49
 
29
50
  player.fadeVolume = function(value, duration) {
51
+ if (audioContext.state === 'suspended') {
52
+ currentValue = ensureInAllowedRange(value);
53
+ return new $.Deferred().resolve().promise();
54
+ }
55
+
30
56
  ensureGainNode();
31
57
 
32
58
  cancel();
@@ -106,4 +132,4 @@ pageflow.mediaPlayer.volumeFading.webAudio = function(player, audioContext) {
106
132
  function ensureInAllowedRange(value) {
107
133
  return value < allowedMinValue ? allowedMinValue : value;
108
134
  }
109
- };
135
+ };
@@ -1,6 +1,6 @@
1
1
  pageflow.SeedEntryData = pageflow.EntryData.extend({
2
2
  initialize: function(options) {
3
- this.theming = options.theming;
3
+ this.theme = options.theme;
4
4
 
5
5
  this.storylineConfigurations = _(options.storylines).reduce(function(memo, storyline) {
6
6
  memo[storyline.id] = storyline.configuration;
@@ -40,7 +40,7 @@ pageflow.SeedEntryData = pageflow.EntryData.extend({
40
40
  },
41
41
 
42
42
  getThemingOption: function(name) {
43
- return this.theming[name];
43
+ return this.theme[name];
44
44
  },
45
45
 
46
46
  getChapterConfiguration: function(id) {
@@ -70,4 +70,4 @@ pageflow.SeedEntryData = pageflow.EntryData.extend({
70
70
  getStorylineIdByChapterId: function(id) {
71
71
  return this.storylineIdsByChapterIds[id];
72
72
  }
73
- });
73
+ });
@@ -6,8 +6,8 @@
6
6
  //=require ./slideshow/scroll_indicator
7
7
  //=require ./slideshow/scroll_indicator_widget
8
8
  //=require ./slideshow/hidden_text_indicator_widget
9
- //=require ./slideshow/progressive_preload
10
- //=require ./slideshow/adjacent_preparer
9
+ //=require ./slideshow/adjacent_preloader
10
+ //=require ./slideshow/successor_preparer
11
11
  //=require ./slideshow/swipe_gesture
12
12
  //=require ./slideshow/hide_text
13
13
  //=require ./slideshow/hide_text_on_swipe
@@ -15,7 +15,6 @@
15
15
 
16
16
  pageflow.Slideshow = function($el, configurations) {
17
17
  var transitioning = false,
18
- preload = new pageflow.ProgressivePreload(),
19
18
  currentPage = $(),
20
19
  pages = $(),
21
20
  that = this,
@@ -116,7 +115,7 @@ pageflow.Slideshow = function($el, configurations) {
116
115
  transition: transition
117
116
  });
118
117
 
119
- preload.start(currentPage);
118
+ currentPage.page('preload');
120
119
  $el.trigger('slideshowchangepage', [options]);
121
120
 
122
121
  return Math.max(outDuration, inDuration);
@@ -161,16 +160,17 @@ pageflow.Slideshow = function($el, configurations) {
161
160
  currentPageIndex = currentPage.index();
162
161
 
163
162
  currentPage.page('activateAsLandingPage');
164
- preload.start(currentPage);
163
+ currentPage.page('preload');
165
164
  }
166
165
  }
167
166
 
168
167
  function findNewCurrentPage(options) {
169
168
  if (!currentPage.length) {
170
169
  var permaId = options && options.landingPagePermaId;
170
+ var landingPage = permaId ? getPageByPermaId(permaId) : $();
171
171
 
172
- return permaId ?
173
- getPageByPermaId(permaId) :
172
+ return landingPage.length ?
173
+ landingPage :
174
174
  that.scrollNavigator.getLandingPage(pages);
175
175
  }
176
176
  else if (!currentPage.parent().length) {
@@ -217,7 +217,14 @@ pageflow.Slideshow = function($el, configurations) {
217
217
  $el.find('.scroll_indicator').scrollIndicator({parent: this});
218
218
 
219
219
  this.scrollNavigator = new pageflow.DomOrderScrollNavigator(this, pageflow.entryData);
220
- this.preparer = pageflow.AdjacentPreparer.create(function() { return pages; }, this.scrollNavigator).attach(pageflow.events);
220
+
221
+ pageflow.AdjacentPreloader
222
+ .create(function() { return pages; }, this.scrollNavigator)
223
+ .attach(pageflow.events);
224
+
225
+ pageflow.SuccessorPreparer
226
+ .create(function() { return pages; }, this.scrollNavigator)
227
+ .attach(pageflow.events);
221
228
  };
222
229
 
223
230
  pageflow.Slideshow.setup = function(options) {
@@ -238,7 +245,8 @@ pageflow.Slideshow.setup = function(options) {
238
245
  pageflow.atmo = pageflow.Atmo.create(
239
246
  pageflow.slides,
240
247
  pageflow.events,
241
- pageflow.audio
248
+ pageflow.audio,
249
+ pageflow.backgroundMedia
242
250
  );
243
251
 
244
252
  pageflow.history = pageflow.History.create(
@@ -7,7 +7,7 @@ pageflow.AdjacentPages = pageflow.Object.extend({
7
7
  of: function(page) {
8
8
  var result = [];
9
9
  var pages = this.pages();
10
- var nextPage = this.scrollNavigator.getNextPage(page.element, pages);
10
+ var nextPage = this.nextPage(page);
11
11
 
12
12
  if (nextPage.length) {
13
13
  result.push(nextPage.page('instance'));
@@ -22,5 +22,10 @@ pageflow.AdjacentPages = pageflow.Object.extend({
22
22
  }, this);
23
23
 
24
24
  return result;
25
+ },
26
+
27
+ nextPage: function(page) {
28
+ var nextPage = this.scrollNavigator.getNextPage(page.element, this.pages());
29
+ return nextPage.length && nextPage.page('instance');
25
30
  }
26
- });
31
+ });
@@ -0,0 +1,26 @@
1
+ //= require ./adjacent_pages
2
+
3
+ pageflow.AdjacentPreloader = pageflow.Object.extend({
4
+ initialize: function(adjacentPages) {
5
+ this.adjacentPages = adjacentPages;
6
+ },
7
+
8
+ attach: function(events) {
9
+ this.listenTo(events, 'page:change', this.preloadAdjacent);
10
+ },
11
+
12
+ preloadAdjacent: function(page) {
13
+ _(this.adjacentPages.of(page)).each(function(page) {
14
+ page.preload();
15
+ });
16
+ }
17
+ });
18
+
19
+ pageflow.AdjacentPreloader.create = function(pages, scrollNavigator) {
20
+ return new pageflow.AdjacentPreloader(
21
+ new pageflow.AdjacentPages(
22
+ pages,
23
+ scrollNavigator
24
+ )
25
+ );
26
+ };