pageflow 12.2.0 → 12.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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
+ };