pageflow-outline-navigation-bar 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.jshintrc +13 -0
  4. data/.rubocop.yml +24 -0
  5. data/.rubocop_hound.yml +1065 -0
  6. data/.scss-lint.yml +145 -0
  7. data/CHANGELOG.md +7 -0
  8. data/Gemfile +4 -0
  9. data/README.md +42 -0
  10. data/Rakefile +10 -0
  11. data/app/assets/images/pageflow/outline_navigation_bar/indicator.png +0 -0
  12. data/app/assets/images/pageflow/outline_navigation_bar/volume_control_sprite.png +0 -0
  13. data/app/assets/javascript/pageflow/outline_navigation_bar.js +26 -0
  14. data/app/assets/javascript/pageflow/outline_navigation_bar/events.js +30 -0
  15. data/app/assets/javascript/pageflow/outline_navigation_bar/expander.js +34 -0
  16. data/app/assets/javascript/pageflow/outline_navigation_bar/fullscreen_button.js +24 -0
  17. data/app/assets/javascript/pageflow/outline_navigation_bar/hide_text_button.js +17 -0
  18. data/app/assets/javascript/pageflow/outline_navigation_bar/menu_item.js +41 -0
  19. data/app/assets/javascript/pageflow/outline_navigation_bar/navigator.js +35 -0
  20. data/app/assets/javascript/pageflow/outline_navigation_bar/panels.js +54 -0
  21. data/app/assets/javascript/pageflow/outline_navigation_bar/resizer.js +32 -0
  22. data/app/assets/javascript/pageflow/outline_navigation_bar/scroller.js +144 -0
  23. data/app/assets/javascript/pageflow/outline_navigation_bar/widget.js +227 -0
  24. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default.scss +87 -0
  25. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/credits_box.scss +28 -0
  26. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/cross_dependant_styles.css.scss +6 -0
  27. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/icons/icon_font.scss +177 -0
  28. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/icons/sprite.scss +140 -0
  29. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/menu_item.scss +107 -0
  30. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/menu_items.scss +33 -0
  31. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/mixins.scss +5 -0
  32. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/mobile_images.scss +54 -0
  33. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/mobile_panel.scss +61 -0
  34. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/mobile_sharing.scss +57 -0
  35. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/panel.scss +19 -0
  36. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/parent_page_button.scss +46 -0
  37. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/prevent_focus_rect_on_pointer_down.scss +4 -0
  38. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/scroller.scss +93 -0
  39. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/share_box.scss +20 -0
  40. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/toggle.scss +73 -0
  41. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/volume_box.scss +48 -0
  42. data/app/assets/stylesheets/pageflow/outline_navigation_bar/themes/default/widget_margin.scss +27 -0
  43. data/app/views/pageflow/outline_navigation_bar/_widget.html.erb +12 -0
  44. data/app/views/pageflow/outline_navigation_bar/widget/_buttons.html.erb +71 -0
  45. data/app/views/pageflow/outline_navigation_bar/widget/_chapter.html.erb +5 -0
  46. data/app/views/pageflow/outline_navigation_bar/widget/_home_button.html.erb +8 -0
  47. data/app/views/pageflow/outline_navigation_bar/widget/_link.html.erb +3 -0
  48. data/app/views/pageflow/outline_navigation_bar/widget/_mobile_panels.html.erb +28 -0
  49. data/app/views/pageflow/outline_navigation_bar/widget/_overview_button.html.erb +8 -0
  50. data/app/views/pageflow/outline_navigation_bar/widget/_scroller.html.erb +13 -0
  51. data/app/views/pageflow/outline_navigation_bar/widget/_toggles.html.erb +32 -0
  52. data/config/locales/de.yml +8 -0
  53. data/config/locales/en.yml +8 -0
  54. data/lib/pageflow-outline-navigation-bar.rb +17 -0
  55. data/lib/pageflow/outline_navigation_bar/engine.rb +9 -0
  56. data/lib/pageflow/outline_navigation_bar/expandable_widget_type.rb +17 -0
  57. data/lib/pageflow/outline_navigation_bar/fixed_widget_type.rb +17 -0
  58. data/lib/pageflow/outline_navigation_bar/plugin.rb +12 -0
  59. data/lib/pageflow/outline_navigation_bar/version.rb +5 -0
  60. data/lib/pageflow/outline_navigation_bar/widget_type.rb +14 -0
  61. data/pageflow-outline-navigation-bar.gemspec +26 -0
  62. metadata +160 -0
@@ -0,0 +1,32 @@
1
+ (function($) {
2
+ var BAR_MIN_WIDTH = 65;
3
+
4
+ pageflow.outlineNavigationBar.Resizer = pageflow.Object.extend({
5
+ initialize: function(element, options) {
6
+ this.element = element;
7
+ this.options = options;
8
+
9
+ this.list = this.element.find('.chapters_panel ul');
10
+
11
+ this._setupWidth();
12
+ },
13
+
14
+ _setupWidth: function() {
15
+ this.expandedWidth = Math.max(BAR_MIN_WIDTH, this.list.width()) + 'px';
16
+
17
+ if (this.options.isFixed) {
18
+ this.element.css('width', this.expandedWidth);
19
+ }
20
+ },
21
+
22
+ expand: function() {
23
+ this.element.addClass('expanded');
24
+ this.element.css('width', this.expandedWidth);
25
+ },
26
+
27
+ collapse: function() {
28
+ this.element.removeClass('expanded');
29
+ this.element.css('width', '');
30
+ },
31
+ });
32
+ }(jQuery));
@@ -0,0 +1,144 @@
1
+ /*global IScroll*/
2
+
3
+ (function($) {
4
+ var MIN_LINK_HEIGHT = 0;
5
+ var MAX_LINK_HEIGHT = 35;
6
+ var EXPANDED_OUTER_LINK_HEIGHT = 42;
7
+ var LINK_MARGIN = 2;
8
+
9
+ $.widget('pageflow.outlineNavigationBarScroller', {
10
+ _create: function() {
11
+ this.list = this.element.find('ul');
12
+ this.pageLinks = this.element.find('li a');
13
+
14
+ this.setupScroller();
15
+ this.setupResizing();
16
+ },
17
+
18
+ _destroy: function() {
19
+ this.teardownResizing();
20
+ },
21
+
22
+ on: function(event, handler) {
23
+ this.iscroll.on(event, handler);
24
+ },
25
+
26
+ setupScroller: function() {
27
+ var scrollerOptions = {
28
+ mouseWheel: true,
29
+ bounce: false,
30
+ probeType: 2
31
+ };
32
+
33
+ if (window.navigator.msPointerEnabled) {
34
+ scrollerOptions.preventDefault = false;
35
+ }
36
+
37
+ this.iscroll = new IScroll(this.element[0], scrollerOptions);
38
+
39
+ if (!this.options.isFixed) {
40
+ this.iscroll.disable();
41
+ }
42
+
43
+ this.list.pageNavigationList({
44
+ scroller: this.iscroll,
45
+ scrollToActive: this.options.isFixed,
46
+ highlightedPage: {
47
+ customNavigationBarMode: function(storylineId, entryData) {
48
+ if (!entryData.getStorylineConfiguration(storylineId).main) {
49
+ return 'inherit_from_parent';
50
+ }
51
+ }
52
+ }
53
+ });
54
+ },
55
+
56
+ setupResizing: function() {
57
+ this.resizeHandler = this.resizeHandler || _.bind(function() {
58
+ setTimeout(_.bind(this.refresh, this), 200);
59
+ }, this);
60
+
61
+ $(window).on('resize', this.resizeHandler);
62
+ this.refresh();
63
+ },
64
+
65
+ teardownResizing: function() {
66
+ $(window).off('resize', this.resizeHandler);
67
+ },
68
+
69
+ refresh: function() {
70
+ var height = this.element.parent().height() - 5;
71
+ var linkCount = this.pageLinks.length;
72
+ var linkHeight = (height / linkCount) - 2;
73
+
74
+ linkHeight = Math.min(Math.max(linkHeight, MIN_LINK_HEIGHT), MAX_LINK_HEIGHT);
75
+ this.collapsedOuterLinkHeight = linkHeight + LINK_MARGIN;
76
+
77
+ var collapsedListHeight = this.collapsedOuterLinkHeight * linkCount;
78
+ var expandedListHeight = EXPANDED_OUTER_LINK_HEIGHT * linkCount;
79
+
80
+ this.isOverflowing = (height < expandedListHeight);
81
+ this.collapsedTop = (height - collapsedListHeight) / 2;
82
+ this.expandedTop = (height - expandedListHeight) / 2;
83
+ this.maxTop = height - linkCount * EXPANDED_OUTER_LINK_HEIGHT;
84
+
85
+ this.setTop(this.collapsedTop);
86
+ this.pageLinks.css('height', linkHeight + 'px');
87
+ },
88
+
89
+ expand: function() {
90
+ var activeItemIndex = this.pageLinks.filter('.in_active_chapter').parent().index();
91
+ var top;
92
+
93
+ if (this.isOverflowing) {
94
+ if (activeItemIndex < this.pageLinks.length - 1) {
95
+ top = activeItemIndex * (this.collapsedOuterLinkHeight - EXPANDED_OUTER_LINK_HEIGHT);
96
+ }
97
+ else {
98
+ top = this.maxTop;
99
+ }
100
+
101
+ this.animateTop(top);
102
+
103
+ this.scrollTimeout = setTimeout(_.bind(function() {
104
+ this.setTop(0);
105
+
106
+ this.iscroll.refresh();
107
+ this.iscroll.scrollTo(0, Math.max(Math.min(0, top), this.iscroll.maxScrollY));
108
+ this.iscroll.enable();
109
+ }, this), 500);
110
+ }
111
+ else {
112
+ this.animateTop(this.expandedTop);
113
+ }
114
+ },
115
+
116
+ collapse: function() {
117
+ clearTimeout(this.scrollTimeout);
118
+
119
+ if (this.isOverflowing && this.iscroll.enabled) {
120
+ this.setTop(this.iscroll.y);
121
+ this.triggerRepaint();
122
+ }
123
+
124
+ this.iscroll.disable();
125
+ this.iscroll.scrollTo(0, 0, 0);
126
+
127
+ this.animateTop(this.collapsedTop);
128
+ },
129
+
130
+ animateTop: function(top) {
131
+ this.element.addClass('animated');
132
+ this.element.css('top', top);
133
+ },
134
+
135
+ setTop: function(top) {
136
+ this.element.removeClass('animated');
137
+ this.element.css('top', top);
138
+ },
139
+
140
+ triggerRepaint: function() {
141
+ this.element[0].offsetWidth
142
+ }
143
+ });
144
+ }(jQuery));
@@ -0,0 +1,227 @@
1
+ /*global IScroll*/
2
+
3
+ (function($) {
4
+ var o = pageflow.outlineNavigationBar;
5
+ var events = o.events;
6
+
7
+ $.widget('pageflow.outlineNavigationBar', {
8
+ _create: function() {
9
+ this.element.toggleClass('expandable', !this._isFixed());
10
+
11
+ this.expander = this._setupExpander();
12
+ this.panels = this._setupPanels();
13
+ this.scroller = this._setupChaptersPanel();
14
+ this.resizer = this._setupResizer();
15
+
16
+ this._setupPointerDownCollapsing();
17
+ this._setupPageChangeCollapsing();
18
+ this._setupMouseExpanding();
19
+ this._setupFocusExpanding();
20
+ this._setupGlobalSkipLinks();
21
+ this._setupButtonsPanel();
22
+ this._setupMobilePanels();
23
+ },
24
+
25
+ _destroy: function() {
26
+ this._teardownPageChangeCollapsing();
27
+ },
28
+
29
+ _setupExpander: function() {
30
+ var widget = this;
31
+
32
+ return new o.Expander({
33
+ enabled: function() {
34
+ return !widget._isFixed();
35
+ },
36
+
37
+ expand: function(options) {
38
+ widget.resizer.expand();
39
+ widget.scroller.expand();
40
+
41
+ if (mobileLayout()) {
42
+ hidePageContent();
43
+ }
44
+ },
45
+
46
+ collapse: function(options) {
47
+ if (!widget.element.hasClass('buttons_active')) {
48
+ widget.panels.reset();
49
+ }
50
+
51
+ widget.resizer.collapse();
52
+ widget.scroller.collapse();
53
+
54
+ showPageContent();
55
+ }
56
+ });
57
+ },
58
+
59
+ _setupPanels: function() {
60
+ var element = this.element;
61
+
62
+ return element
63
+ .outlineNavigationBarPanels({
64
+ expander: this.expander,
65
+ panels: element.find('.panel'),
66
+ toggles: element.find('.toggle'),
67
+ })
68
+ .outlineNavigationBarPanels('instance');
69
+ },
70
+
71
+ _setupChaptersPanel: function() {
72
+ var element = this.element;
73
+ var scroller = element.find('.scroller')
74
+ .outlineNavigationBarScroller({isFixed: this._isFixed()})
75
+ .outlineNavigationBarScroller('instance');
76
+
77
+ element.find('.scroller').outlineNavigationBarNavigator({
78
+ scroller: scroller
79
+ });
80
+
81
+ return scroller;
82
+ },
83
+
84
+ _setupResizer: function() {
85
+ return new o.Resizer(this.element, {
86
+ isFixed: this._isFixed()
87
+ });
88
+ },
89
+
90
+ _setupPointerDownCollapsing: function() {
91
+ var expander = this.expander;
92
+ var element = this.element;
93
+
94
+ $('body').on(events.pointerDown, function(event) {
95
+ if (!$(event.target).parents().andSelf().filter(element).length) {
96
+ expander.collapse();
97
+ }
98
+ });
99
+ },
100
+
101
+ _setupPageChangeCollapsing: function() {
102
+ var expander = this.expander;
103
+
104
+ pageflow.events.on('page:change', function() {
105
+ expander.collapse();
106
+ }, this);
107
+ },
108
+
109
+ _teardownPageChangeCollapsing: function() {
110
+ pageflow.events.off('page:change', null, this);
111
+ },
112
+
113
+ _setupMouseExpanding: function() {
114
+ var expander = this.expander;
115
+
116
+ if (!pageflow.browser.has('mobile platform')) {
117
+ this.element.on({
118
+ mouseenter: function() {
119
+ if (!mobileLayout()) {
120
+ expander.expand({by: 'mouse'});
121
+ }
122
+ },
123
+
124
+ mouseleave: function() {
125
+ if (!mobileLayout()) {
126
+ expander.collapse({by: 'mouse'});
127
+ }
128
+ }
129
+ });
130
+ }
131
+ },
132
+
133
+ _setupFocusExpanding: function() {
134
+ var expander = this.expander;
135
+
136
+ this.element.find('a, *[tabindex]').on({
137
+ focus: function() {
138
+ expander.expand({by: 'focus'});
139
+ },
140
+
141
+ blur: function() {
142
+ expander.scheduleCollapse({by: 'focus'});
143
+ }
144
+ });
145
+ },
146
+
147
+ _setupButtonsPanel: function() {
148
+ var element = this.element;
149
+
150
+ element.find('.toggle.buttons a').on('click', function() {
151
+ $('.header').toggleClass('active');
152
+ element.toggleClass('buttons_active');
153
+ });
154
+
155
+ element.find('.menu_item').outlineNavigationBarMenuItem();
156
+ element.find('.top a').topButton();
157
+ element.find('.fullscreen a').fullscreenButton();
158
+ element.find('.hide_text a').outlineNavigationBarHideTextButton();
159
+ element.find('.navigation_volume_box').volumeSlider({
160
+ orientation: 'v'
161
+ });
162
+
163
+ var shareBox = $('.share_box', this.element),
164
+ shareLinks = $('a', shareBox);
165
+
166
+ shareBox.shareMenu({
167
+ insertAfter: shareLinks.parent().last(),
168
+ closeOnMouseLeaving: shareBox
169
+ });
170
+ },
171
+
172
+ _setupMobilePanels: function() {
173
+ var element = this.element;
174
+
175
+ element.find('.parent_page').parentPageButton({
176
+ visibleClass: 'is_visible'
177
+ });
178
+
179
+ element.find('.mobile_panel').each(function() {
180
+ var sharingBox = $(this).filter('.mobile_sharing');
181
+ var scroller = new IScroll($(this).find('.wrapper')[0], {
182
+ mouseWheel: true,
183
+ bounce: false,
184
+ probeType: 3
185
+ });
186
+
187
+ element.on(events.pointerDown, '.toggle.mobile_only a', function() {
188
+ scroller.refresh();
189
+ });
190
+
191
+ sharingBox.shareMenu({
192
+ scroller: scroller
193
+ });
194
+ });
195
+
196
+ $('.mobile_panel a', element).on('click touchstart', function(event) {
197
+ event.stopPropagation();
198
+ });
199
+ },
200
+
201
+ _setupGlobalSkipLinks: function() {
202
+ $('a[href="#header"], a[href="#search"]', '#skipLinks').click(function() {
203
+ $('.header').addClass('active');
204
+ $(this.getAttribute('href')).select();
205
+ });
206
+ },
207
+
208
+ _isFixed: function() {
209
+ return (this.element.data('widget') === 'outline_navigation_bar_fixed' &&
210
+ !mobileLayout());
211
+ }
212
+ });
213
+
214
+ function mobileLayout() {
215
+ return ($('body').width() <= 900);
216
+ }
217
+
218
+ function hidePageContent() {
219
+ $('section.page').addClass('hidden_by_overlay');
220
+ $('.scroll_indicator').addClass('hidden');
221
+ }
222
+
223
+ function showPageContent() {
224
+ $('section.page').removeClass('hidden_by_overlay');
225
+ $('.scroll_indicator').removeClass('hidden');
226
+ }
227
+ }(jQuery));
@@ -0,0 +1,87 @@
1
+ @import "./default/cross_dependant_styles";
2
+ @import "./default/widget_margin";
3
+
4
+ /// Type of icons to use:
5
+ ///
6
+ /// - `"icon-font"`: Circular buttons with font awesome icons.
7
+ ///
8
+ /// - `"sprite"`: Custom icons from `icon_sprite.png` in theme
9
+ /// directory.
10
+ $outline-navigation-bar-icons: $widget-icons !default;
11
+
12
+ /// @see $default-widget-icon-font-options
13
+ $outline-navigation-bar-icon-font-options: (
14
+ share-icon-color: #fff,
15
+ active-share-icon-color: $main-color
16
+ ) !default;
17
+
18
+ .outline_navigation_bar {
19
+ @import "./default/mixins";
20
+
21
+ @import "./default/icons/icon_font";
22
+ @import "./default/icons/sprite";
23
+
24
+ $basic-text-color: #fff !default;
25
+
26
+ $outline-navigation-bar-basic-background-color: $basic-background-color-transparent !default;
27
+ $outline-navigation-bar-active-chapter-color: $main-color !default;
28
+
29
+ $outline-navigation-bar-menu-box-background-color: $widget-background-color !default;
30
+ $outline-navigation-bar-menu-box-color: $widget-text-color !default;
31
+
32
+ @if $outline-navigation-bar-icons == "sprite" {
33
+ @include outline-navigation-bar-icons-sprite;
34
+ } @else {
35
+ @include outline-navigation-bar-icons-icon-font(
36
+ widget-icon-font-options($outline-navigation-bar-icon-font-options)...
37
+ );
38
+ }
39
+
40
+ position: absolute;
41
+ right: 0;
42
+ top: 0;
43
+ z-index: 3;
44
+ height: 100%;
45
+
46
+ font-family: $standard-font;
47
+ background-color: $outline-navigation-bar-basic-background-color;
48
+ @include transition(min-width 0.2s ease, width 0.2s ease);
49
+ @include user-select(none);
50
+
51
+ &.fixed {
52
+ min-width: 65px;
53
+ }
54
+
55
+ &.expandable {
56
+ width: 18px;
57
+ }
58
+
59
+ &.buttons_active {
60
+ width: 65px !important;
61
+ }
62
+
63
+ @include mobile {
64
+ &.expanded {
65
+ width: 200px !important;
66
+ }
67
+ }
68
+
69
+ .has_mobile_platform &.expanded {
70
+ width: 200px !important;
71
+ }
72
+
73
+ @import "./default/prevent_focus_rect_on_pointer_down";
74
+
75
+ @import "./default/panel";
76
+ @import "./default/parent_page_button";
77
+ @import "./default/mobile_panel";
78
+ @import "./default/mobile_images";
79
+ @import "./default/menu_item";
80
+ @import "./default/menu_items";
81
+ @import "./default/toggle";
82
+ @import "./default/volume_box";
83
+ @import "./default/share_box";
84
+ @import "./default/credits_box";
85
+ @import "./default/mobile_sharing";
86
+ @import "./default/scroller";
87
+ }